blob: b2a8f0a8c333811abf65ee585fa16a655687bf32 [file] [log] [blame]
Leo Repp58b9f112021-11-22 11:57:47 +01001'use strict';
2const fs = require('fs');
3const path = require('path');
4const ConfigChain = require('config-chain').ConfigChain;
5const util = require('./util');
6
7class Conf extends ConfigChain {
8 // https://github.com/npm/npm/blob/latest/lib/config/core.js#L208-L222
9 constructor(base) {
10 super(base);
11 this.root = base;
12 }
13
14 // https://github.com/npm/npm/blob/latest/lib/config/core.js#L332-L342
15 add(data, marker) {
16 try {
17 for (const x of Object.keys(data)) {
18 data[x] = util.parseField(data[x], x);
19 }
20 } catch (err) {
21 throw err;
22 }
23
24 return super.add(data, marker);
25 }
26
27 // https://github.com/npm/npm/blob/latest/lib/config/core.js#L312-L325
28 addFile(file, name) {
29 name = name || file;
30
31 const marker = {__source__: name};
32
33 this.sources[name] = {path: file, type: 'ini'};
34 this.push(marker);
35 this._await();
36
37 try {
38 const contents = fs.readFileSync(file, 'utf8');
39 this.addString(contents, file, 'ini', marker);
40 } catch (err) {
41 this.add({}, marker);
42 }
43
44 return this;
45 }
46
47 // https://github.com/npm/npm/blob/latest/lib/config/core.js#L344-L360
48 addEnv(env) {
49 env = env || process.env;
50
51 const conf = {};
52
53 Object.keys(env)
54 .filter(x => /^npm_config_/i.test(x))
55 .forEach(x => {
56 if (!env[x]) {
57 return;
58 }
59
60 const p = x.toLowerCase()
61 .replace(/^npm_config_/, '')
62 .replace(/(?!^)_/g, '-');
63
64 conf[p] = env[x];
65 });
66
67 return super.addEnv('', conf, 'env');
68 }
69
70 // https://github.com/npm/npm/blob/latest/lib/config/load-prefix.js
71 loadPrefix() {
72 const cli = this.list[0];
73
74 Object.defineProperty(this, 'prefix', {
75 enumerable: true,
76 set: prefix => {
77 const g = this.get('global');
78 this[g ? 'globalPrefix' : 'localPrefix'] = prefix;
79 },
80 get: () => {
81 const g = this.get('global');
82 return g ? this.globalPrefix : this.localPrefix;
83 }
84 });
85
86 Object.defineProperty(this, 'globalPrefix', {
87 enumerable: true,
88 set: prefix => {
89 this.set('prefix', prefix);
90 },
91 get: () => {
92 return path.resolve(this.get('prefix'));
93 }
94 });
95
96 let p;
97
98 Object.defineProperty(this, 'localPrefix', {
99 enumerable: true,
100 set: prefix => {
101 p = prefix;
102 },
103 get: () => {
104 return p;
105 }
106 });
107
108 if (Object.prototype.hasOwnProperty.call(cli, 'prefix')) {
109 p = path.resolve(cli.prefix);
110 } else {
111 try {
112 const prefix = util.findPrefix(process.cwd());
113 p = prefix;
114 } catch (err) {
115 throw err;
116 }
117 }
118
119 return p;
120 }
121
122 // https://github.com/npm/npm/blob/latest/lib/config/load-cafile.js
123 loadCAFile(file) {
124 if (!file) {
125 return;
126 }
127
128 try {
129 const contents = fs.readFileSync(file, 'utf8');
130 const delim = '-----END CERTIFICATE-----';
131 const output = contents
132 .split(delim)
133 .filter(x => Boolean(x.trim()))
134 .map(x => x.trimLeft() + delim);
135
136 this.set('ca', output);
137 } catch (err) {
138 if (err.code === 'ENOENT') {
139 return;
140 }
141
142 throw err;
143 }
144 }
145
146 // https://github.com/npm/npm/blob/latest/lib/config/set-user.js
147 loadUser() {
148 const defConf = this.root;
149
150 if (this.get('global')) {
151 return;
152 }
153
154 if (process.env.SUDO_UID) {
155 defConf.user = Number(process.env.SUDO_UID);
156 return;
157 }
158
159 const prefix = path.resolve(this.get('prefix'));
160
161 try {
162 const stats = fs.statSync(prefix);
163 defConf.user = stats.uid;
164 } catch (err) {
165 if (err.code === 'ENOENT') {
166 return;
167 }
168
169 throw err;
170 }
171 }
172}
173
174module.exports = Conf;