@verdaccio/config 8.1.2 → 8.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/_virtual/_rolldown/runtime.js +23 -0
- package/build/address.js +80 -102
- package/build/address.js.map +1 -1
- package/build/address.mjs +86 -0
- package/build/address.mjs.map +1 -0
- package/build/agent.js +11 -16
- package/build/agent.js.map +1 -1
- package/build/agent.mjs +12 -0
- package/build/agent.mjs.map +1 -0
- package/build/builder.js +128 -131
- package/build/builder.js.map +1 -1
- package/build/builder.mjs +129 -0
- package/build/builder.mjs.map +1 -0
- package/build/conf/index.js +10 -11
- package/build/conf/index.js.map +1 -1
- package/build/conf/index.mjs +12 -0
- package/build/conf/index.mjs.map +1 -0
- package/build/config-path.js +154 -163
- package/build/config-path.js.map +1 -1
- package/build/config-path.mjs +171 -0
- package/build/config-path.mjs.map +1 -0
- package/build/config-utils.js +37 -41
- package/build/config-utils.js.map +1 -1
- package/build/config-utils.mjs +40 -0
- package/build/config-utils.mjs.map +1 -0
- package/build/config.js +154 -203
- package/build/config.js.map +1 -1
- package/build/config.mjs +153 -0
- package/build/config.mjs.map +1 -0
- package/build/index.js +52 -167
- package/build/index.mjs +14 -0
- package/build/package-access.js +52 -68
- package/build/package-access.js.map +1 -1
- package/build/package-access.mjs +52 -0
- package/build/package-access.mjs.map +1 -0
- package/build/parse.js +83 -100
- package/build/parse.js.map +1 -1
- package/build/parse.mjs +85 -0
- package/build/parse.mjs.map +1 -0
- package/build/security.js +15 -22
- package/build/security.js.map +1 -1
- package/build/security.mjs +16 -0
- package/build/security.mjs.map +1 -0
- package/build/serverSettings.js +10 -15
- package/build/serverSettings.js.map +1 -1
- package/build/serverSettings.mjs +12 -0
- package/build/serverSettings.mjs.map +1 -0
- package/build/token.js +10 -13
- package/build/token.js.map +1 -1
- package/build/token.mjs +13 -0
- package/build/token.mjs.map +1 -0
- package/build/uplinks.js +47 -55
- package/build/uplinks.js.map +1 -1
- package/build/uplinks.mjs +50 -0
- package/build/uplinks.mjs.map +1 -0
- package/build/user.js +42 -37
- package/build/user.js.map +1 -1
- package/build/user.mjs +48 -0
- package/build/user.mjs.map +1 -0
- package/package.json +43 -30
- package/build/index.js.map +0 -1
package/build/config-path.js
CHANGED
|
@@ -1,187 +1,178 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
};
|
|
20
|
-
const debug = (0, _debug.default)('verdaccio:config:config-path');
|
|
21
|
-
|
|
1
|
+
const require_runtime = require("./_virtual/_rolldown/runtime.js");
|
|
2
|
+
const require_config_utils = require("./config-utils.js");
|
|
3
|
+
let debug = require("debug");
|
|
4
|
+
debug = require_runtime.__toESM(debug);
|
|
5
|
+
let lodash = require("lodash");
|
|
6
|
+
lodash = require_runtime.__toESM(lodash);
|
|
7
|
+
let node_fs = require("node:fs");
|
|
8
|
+
node_fs = require_runtime.__toESM(node_fs);
|
|
9
|
+
let node_os = require("node:os");
|
|
10
|
+
node_os = require_runtime.__toESM(node_os);
|
|
11
|
+
let node_path = require("node:path");
|
|
12
|
+
node_path = require_runtime.__toESM(node_path);
|
|
13
|
+
let node_url = require("node:url");
|
|
14
|
+
//#region src/config-path.ts
|
|
15
|
+
var CONFIG_FILE = "config.yaml";
|
|
16
|
+
var XDG = "xdg";
|
|
17
|
+
var pkgJSON = { name: "verdaccio" };
|
|
18
|
+
var debug$1 = (0, debug.default)("verdaccio:config:config-path");
|
|
22
19
|
/**
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
* Find and get the first config file that match.
|
|
21
|
+
* @return {String} the config file path
|
|
22
|
+
*/
|
|
26
23
|
function findConfigFile(configPath) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
debug('no previous location found, creating a new one');
|
|
48
|
-
debug('generating the first match path location %s', configPaths[0].path);
|
|
49
|
-
return createConfigFile(configPaths[0]).path;
|
|
24
|
+
debug$1("searching for config file %o", configPath);
|
|
25
|
+
if (typeof configPath !== "undefined") {
|
|
26
|
+
const configLocation = node_path.default.resolve(configPath);
|
|
27
|
+
debug$1("custom location %s", configLocation);
|
|
28
|
+
return configLocation;
|
|
29
|
+
}
|
|
30
|
+
const configPaths = getConfigPaths();
|
|
31
|
+
debug$1("%o posible locations found", configPaths.length);
|
|
32
|
+
if (configPaths.length === 0) {
|
|
33
|
+
debug$1("no configuration files can be processed");
|
|
34
|
+
throw new Error("no configuration files can be processed");
|
|
35
|
+
}
|
|
36
|
+
const primaryConf = lodash.default.find(configPaths, (configLocation) => require_config_utils.fileExists(configLocation.path));
|
|
37
|
+
if (typeof primaryConf !== "undefined") {
|
|
38
|
+
debug$1("at least one primary location detected at %s", primaryConf?.path);
|
|
39
|
+
return primaryConf.path;
|
|
40
|
+
}
|
|
41
|
+
debug$1("no previous location found, creating a new one");
|
|
42
|
+
debug$1("generating the first match path location %s", configPaths[0].path);
|
|
43
|
+
return createConfigFile(configPaths[0]).path;
|
|
50
44
|
}
|
|
51
45
|
function createConfigFile(configLocation) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
46
|
+
createConfigFolder(configLocation);
|
|
47
|
+
const defaultConfig = updateStorageLinks(configLocation, readDefaultConfig());
|
|
48
|
+
node_fs.default.writeFileSync(configLocation.path, defaultConfig);
|
|
49
|
+
return configLocation;
|
|
56
50
|
}
|
|
57
51
|
function readDefaultConfig() {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
52
|
+
const currentDir = {}.url ? node_path.default.dirname((0, node_url.fileURLToPath)({}.url)) : __dirname;
|
|
53
|
+
const pathDefaultConf = node_path.default.resolve(currentDir, "conf/default.yaml");
|
|
54
|
+
try {
|
|
55
|
+
debug$1("the path of default config used from %s", pathDefaultConf);
|
|
56
|
+
node_fs.default.accessSync(pathDefaultConf, node_fs.default.constants.R_OK);
|
|
57
|
+
debug$1("configuration file has enough permissions for reading");
|
|
58
|
+
} catch {
|
|
59
|
+
debug$1("configuration file does not have enough permissions for reading");
|
|
60
|
+
throw new TypeError("configuration file does not have enough permissions for reading");
|
|
61
|
+
}
|
|
62
|
+
return node_fs.default.readFileSync(pathDefaultConf, "utf8");
|
|
68
63
|
}
|
|
69
64
|
function createConfigFolder(configLocation) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
});
|
|
75
|
-
debug(`folder %o created`, folder);
|
|
65
|
+
const folder = node_path.default.dirname(configLocation.path);
|
|
66
|
+
debug$1(`creating default config file folder at %o`, folder);
|
|
67
|
+
node_fs.default.mkdirSync(folder, { recursive: true });
|
|
68
|
+
debug$1(`folder %o created`, folder);
|
|
76
69
|
}
|
|
77
|
-
|
|
78
70
|
/**
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
71
|
+
* Update the storage links to the new location if it is necessary.
|
|
72
|
+
* @param configLocation
|
|
73
|
+
* @param defaultConfig
|
|
74
|
+
* @returns
|
|
75
|
+
*/
|
|
84
76
|
function updateStorageLinks(configLocation, defaultConfig) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
return defaultConfig.replace(/^storage: .\/storage$/m, `storage: ${dataDir}`);
|
|
100
|
-
}
|
|
101
|
-
debug(`could not find a previous storage location, skip override`);
|
|
102
|
-
return defaultConfig;
|
|
77
|
+
debug$1("checking storage links for %s and type %s", configLocation.path, configLocation.type);
|
|
78
|
+
if (configLocation.type !== XDG) {
|
|
79
|
+
debug$1(`skip storage override for %s`, configLocation.type);
|
|
80
|
+
return defaultConfig;
|
|
81
|
+
}
|
|
82
|
+
let dataDir = process.env.XDG_DATA_HOME || node_path.default.join(process.env.HOME, ".local", "share");
|
|
83
|
+
if (require_config_utils.folderExists(dataDir)) {
|
|
84
|
+
debug$1(`previous storage located`);
|
|
85
|
+
debug$1(`update storage links to %s`, dataDir);
|
|
86
|
+
dataDir = node_path.default.resolve(node_path.default.join(dataDir, pkgJSON.name, "storage"));
|
|
87
|
+
return defaultConfig.replace(/^storage: .\/storage$/m, `storage: ${dataDir}`);
|
|
88
|
+
}
|
|
89
|
+
debug$1(`could not find a previous storage location, skip override`);
|
|
90
|
+
return defaultConfig;
|
|
103
91
|
}
|
|
104
|
-
|
|
105
92
|
/**
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
93
|
+
* Return a list of configuration locations by platform.
|
|
94
|
+
* @returns
|
|
95
|
+
*/
|
|
109
96
|
function getConfigPaths() {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
97
|
+
return [
|
|
98
|
+
getXDGDirectory(),
|
|
99
|
+
getWindowsDirectory(),
|
|
100
|
+
getRelativeDefaultDirectory(),
|
|
101
|
+
getOldDirectory()
|
|
102
|
+
].reduce(function(acc, currentValue) {
|
|
103
|
+
if (typeof currentValue !== "undefined") {
|
|
104
|
+
debug$1("posible directory path generated %s for type %s", currentValue?.path, currentValue.type);
|
|
105
|
+
acc.push(currentValue);
|
|
106
|
+
}
|
|
107
|
+
return acc;
|
|
108
|
+
}, []);
|
|
118
109
|
}
|
|
119
|
-
|
|
120
110
|
/**
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
111
|
+
* Get XDG_CONFIG_HOME or HOME location (usually unix)
|
|
112
|
+
*
|
|
113
|
+
* The XDG_CONFIG_HOME environment variable is also part of the XDG Base Directory Specification,
|
|
114
|
+
* which aims to standardize the locations where applications store configuration files and other
|
|
115
|
+
* user-specific data on Unix-like operating systems.
|
|
116
|
+
*
|
|
117
|
+
*
|
|
118
|
+
*
|
|
119
|
+
* https://specifications.freedesktop.org/basedir-spec/latest/
|
|
120
|
+
*
|
|
121
|
+
*
|
|
122
|
+
* @returns
|
|
123
|
+
*/
|
|
124
|
+
var getXDGDirectory = () => {
|
|
125
|
+
const xDGConfigPath = process.env.XDG_CONFIG_HOME || process.env.HOME && node_path.default.join(process.env.HOME, ".config");
|
|
126
|
+
debug$1("XDGConfig folder path %s", xDGConfigPath);
|
|
127
|
+
if (xDGConfigPath && require_config_utils.folderExists(xDGConfigPath)) {
|
|
128
|
+
debug$1("XDGConfig folder path %s", xDGConfigPath);
|
|
129
|
+
return {
|
|
130
|
+
path: node_path.default.join(xDGConfigPath, pkgJSON.name, CONFIG_FILE),
|
|
131
|
+
type: XDG
|
|
132
|
+
};
|
|
133
|
+
}
|
|
144
134
|
};
|
|
145
|
-
|
|
146
135
|
/**
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
136
|
+
* Detect windows location, APPDATA
|
|
137
|
+
* usually something like C:\User\<Build User>\AppData\Local
|
|
138
|
+
* @returns
|
|
139
|
+
*/
|
|
140
|
+
var getWindowsDirectory = () => {
|
|
141
|
+
if (node_os.default.platform() === "win32" && process.env.APPDATA && require_config_utils.folderExists(process.env.APPDATA)) {
|
|
142
|
+
debug$1("windows appdata folder path %s", process.env.APPDATA);
|
|
143
|
+
return {
|
|
144
|
+
path: node_path.default.resolve(node_path.default.join(process.env.APPDATA, pkgJSON.name, CONFIG_FILE)),
|
|
145
|
+
type: "win"
|
|
146
|
+
};
|
|
147
|
+
}
|
|
159
148
|
};
|
|
160
|
-
|
|
161
149
|
/**
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
150
|
+
* Return relative directory, this is the default.
|
|
151
|
+
* It will cretate config in your {currentLocation/verdaccio/config.yaml}
|
|
152
|
+
* @returns
|
|
153
|
+
*/
|
|
154
|
+
var getRelativeDefaultDirectory = () => {
|
|
155
|
+
const relativePath = node_path.default.resolve(node_path.default.join(".", pkgJSON.name, CONFIG_FILE));
|
|
156
|
+
debug$1("relative folder path %s", relativePath);
|
|
157
|
+
return {
|
|
158
|
+
path: relativePath,
|
|
159
|
+
type: "def"
|
|
160
|
+
};
|
|
173
161
|
};
|
|
174
|
-
|
|
175
162
|
/**
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
163
|
+
* This should never happens, consider it DEPRECATED
|
|
164
|
+
* @returns
|
|
165
|
+
*/
|
|
166
|
+
var getOldDirectory = () => {
|
|
167
|
+
const oldPath = node_path.default.resolve(node_path.default.join(".", CONFIG_FILE));
|
|
168
|
+
debug$1("old folder path %s", oldPath);
|
|
169
|
+
return {
|
|
170
|
+
path: oldPath,
|
|
171
|
+
type: "old"
|
|
172
|
+
};
|
|
186
173
|
};
|
|
174
|
+
//#endregion
|
|
175
|
+
exports.findConfigFile = findConfigFile;
|
|
176
|
+
exports.readDefaultConfig = readDefaultConfig;
|
|
177
|
+
|
|
187
178
|
//# sourceMappingURL=config-path.js.map
|
package/build/config-path.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-path.js","names":["_debug","_interopRequireDefault","require","_lodash","_nodeFs","_nodeOs","_nodePath","_configUtils","e","__esModule","default","CONFIG_FILE","XDG","pkgJSON","name","debug","buildDebug","findConfigFile","configPath","configLocation","path","resolve","configPaths","getConfigPaths","length","Error","primaryConf","_","find","fileExists","createConfigFile","createConfigFolder","defaultConfig","updateStorageLinks","readDefaultConfig","fs","writeFileSync","pathDefaultConf","__dirname","accessSync","constants","R_OK","TypeError","readFileSync","folder","dirname","mkdirSync","recursive","type","dataDir","process","env","XDG_DATA_HOME","join","HOME","folderExists","replace","listPaths","getXDGDirectory","getWindowsDirectory","getRelativeDefaultDirectory","getOldDirectory","reduce","acc","currentValue","push","xDGConfigPath","XDG_CONFIG_HOME","os","platform","APPDATA","relativePath","oldPath"],"sources":["../src/config-path.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport _ from 'lodash';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { fileExists, folderExists } from './config-utils';\n\nconst CONFIG_FILE = 'config.yaml';\nconst XDG = 'xdg';\n\nconst pkgJSON = {\n name: 'verdaccio',\n};\n\nexport type SetupDirectory = {\n path: string;\n type: 'xdg' | 'win' | 'win32' | 'def' | 'old';\n};\n\nconst debug = buildDebug('verdaccio:config:config-path');\n\n/**\n * Find and get the first config file that match.\n * @return {String} the config file path\n */\nfunction findConfigFile(configPath?: string): string {\n debug('searching for config file %o', configPath);\n if (typeof configPath !== 'undefined') {\n const configLocation = path.resolve(configPath);\n debug('custom location %s', configLocation);\n return configLocation;\n }\n\n const configPaths: SetupDirectory[] = getConfigPaths();\n debug('%o posible locations found', configPaths.length);\n if (configPaths.length === 0) {\n debug('no configuration files can be processed');\n // this should never happens\n throw new Error('no configuration files can be processed');\n }\n\n // find the first location that already exist\n const primaryConf: SetupDirectory | void = _.find(configPaths, (configLocation: SetupDirectory) =>\n fileExists(configLocation.path)\n );\n\n if (typeof primaryConf !== 'undefined') {\n debug('at least one primary location detected at %s', primaryConf?.path);\n return primaryConf.path;\n }\n debug('no previous location found, creating a new one');\n debug('generating the first match path location %s', configPaths[0].path);\n return createConfigFile(configPaths[0]).path;\n}\n\nfunction createConfigFile(configLocation: SetupDirectory): SetupDirectory {\n createConfigFolder(configLocation);\n\n const defaultConfig = updateStorageLinks(configLocation, readDefaultConfig());\n\n fs.writeFileSync(configLocation.path, defaultConfig);\n\n return configLocation;\n}\n\nexport function readDefaultConfig(): string {\n const pathDefaultConf: string = path.resolve(__dirname, 'conf/default.yaml');\n try {\n debug('the path of default config used from %s', pathDefaultConf);\n fs.accessSync(pathDefaultConf, fs.constants.R_OK);\n debug('configuration file has enough permissions for reading');\n } catch {\n debug('configuration file does not have enough permissions for reading');\n throw new TypeError('configuration file does not have enough permissions for reading');\n }\n\n return fs.readFileSync(pathDefaultConf, 'utf8');\n}\n\nfunction createConfigFolder(configLocation: SetupDirectory): void {\n const folder = path.dirname(configLocation.path);\n debug(`creating default config file folder at %o`, folder);\n fs.mkdirSync(folder, { recursive: true });\n debug(`folder %o created`, folder);\n}\n\n/**\n * Update the storage links to the new location if it is necessary.\n * @param configLocation\n * @param defaultConfig\n * @returns\n */\nfunction updateStorageLinks(configLocation: SetupDirectory, defaultConfig: string): string {\n debug('checking storage links for %s and type %s', configLocation.path, configLocation.type);\n if (configLocation.type !== XDG) {\n debug(`skip storage override for %s`, configLocation.type);\n return defaultConfig;\n }\n\n // $XDG_DATA_HOME defines the base directory relative to which user specific data\n // files should be stored, If $XDG_DATA_HOME is either not set or empty, a default\n // equal to $HOME/.local/share should be used.\n let dataDir =\n process.env.XDG_DATA_HOME || path.join(process.env.HOME as string, '.local', 'share');\n if (folderExists(dataDir)) {\n debug(`previous storage located`);\n debug(`update storage links to %s`, dataDir);\n dataDir = path.resolve(path.join(dataDir, pkgJSON.name, 'storage'));\n return defaultConfig.replace(/^storage: .\\/storage$/m, `storage: ${dataDir}`);\n }\n debug(`could not find a previous storage location, skip override`);\n return defaultConfig;\n}\n\n/**\n * Return a list of configuration locations by platform.\n * @returns\n */\nfunction getConfigPaths(): SetupDirectory[] {\n const listPaths: (SetupDirectory | void)[] = [\n getXDGDirectory(),\n getWindowsDirectory(),\n getRelativeDefaultDirectory(),\n getOldDirectory(),\n ];\n\n return listPaths.reduce(function (acc, currentValue: SetupDirectory | void): SetupDirectory[] {\n if (typeof currentValue !== 'undefined') {\n debug(\n 'posible directory path generated %s for type %s',\n currentValue?.path,\n currentValue.type\n );\n acc.push(currentValue);\n }\n return acc;\n }, [] as SetupDirectory[]);\n}\n\n/**\n * Get XDG_CONFIG_HOME or HOME location (usually unix)\n *\n * The XDG_CONFIG_HOME environment variable is also part of the XDG Base Directory Specification,\n * which aims to standardize the locations where applications store configuration files and other\n * user-specific data on Unix-like operating systems.\n *\n *\n *\n * https://specifications.freedesktop.org/basedir-spec/latest/\n *\n *\n * @returns\n */\nconst getXDGDirectory = (): SetupDirectory | void => {\n const xDGConfigPath =\n process.env.XDG_CONFIG_HOME || (process.env.HOME && path.join(process.env.HOME, '.config'));\n debug('XDGConfig folder path %s', xDGConfigPath);\n if (xDGConfigPath && folderExists(xDGConfigPath)) {\n debug('XDGConfig folder path %s', xDGConfigPath);\n return {\n path: path.join(xDGConfigPath, pkgJSON.name, CONFIG_FILE),\n type: XDG,\n };\n }\n};\n\n/**\n * Detect windows location, APPDATA\n * usually something like C:\\User\\<Build User>\\AppData\\Local\n * @returns\n */\nconst getWindowsDirectory = (): SetupDirectory | void => {\n if (os.platform() === 'win32' && process.env.APPDATA && folderExists(process.env.APPDATA)) {\n debug('windows appdata folder path %s', process.env.APPDATA);\n return {\n path: path.resolve(path.join(process.env.APPDATA, pkgJSON.name, CONFIG_FILE)),\n type: 'win',\n };\n }\n};\n\n/**\n * Return relative directory, this is the default.\n * It will cretate config in your {currentLocation/verdaccio/config.yaml}\n * @returns\n */\nconst getRelativeDefaultDirectory = (): SetupDirectory => {\n const relativePath = path.resolve(path.join('.', pkgJSON.name, CONFIG_FILE));\n debug('relative folder path %s', relativePath);\n return {\n path: relativePath,\n type: 'def',\n };\n};\n\n/**\n * This should never happens, consider it DEPRECATED\n * @returns\n */\nconst getOldDirectory = (): SetupDirectory => {\n const oldPath = path.resolve(path.join('.', CONFIG_FILE));\n debug('old folder path %s', oldPath);\n return {\n path: oldPath,\n type: 'old',\n };\n};\n\nexport { findConfigFile };\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"config-path.js","names":[],"sources":["../src/config-path.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport _ from 'lodash';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { fileExists, folderExists } from './config-utils';\n\nconst CONFIG_FILE = 'config.yaml';\nconst XDG = 'xdg';\n\nconst pkgJSON = {\n name: 'verdaccio',\n};\n\nexport type SetupDirectory = {\n path: string;\n type: 'xdg' | 'win' | 'win32' | 'def' | 'old';\n};\n\nconst debug = buildDebug('verdaccio:config:config-path');\n\n/**\n * Find and get the first config file that match.\n * @return {String} the config file path\n */\nfunction findConfigFile(configPath?: string): string {\n debug('searching for config file %o', configPath);\n if (typeof configPath !== 'undefined') {\n const configLocation = path.resolve(configPath);\n debug('custom location %s', configLocation);\n return configLocation;\n }\n\n const configPaths: SetupDirectory[] = getConfigPaths();\n debug('%o posible locations found', configPaths.length);\n if (configPaths.length === 0) {\n debug('no configuration files can be processed');\n // this should never happens\n throw new Error('no configuration files can be processed');\n }\n\n // find the first location that already exist\n const primaryConf: SetupDirectory | void = _.find(configPaths, (configLocation: SetupDirectory) =>\n fileExists(configLocation.path)\n );\n\n if (typeof primaryConf !== 'undefined') {\n debug('at least one primary location detected at %s', primaryConf?.path);\n return primaryConf.path;\n }\n debug('no previous location found, creating a new one');\n debug('generating the first match path location %s', configPaths[0].path);\n return createConfigFile(configPaths[0]).path;\n}\n\nfunction createConfigFile(configLocation: SetupDirectory): SetupDirectory {\n createConfigFolder(configLocation);\n\n const defaultConfig = updateStorageLinks(configLocation, readDefaultConfig());\n\n fs.writeFileSync(configLocation.path, defaultConfig);\n\n return configLocation;\n}\n\nexport function readDefaultConfig(): string {\n // import.meta.url is only defined in the ESM build; the CJS build falls back to __dirname\n const currentDir = import.meta.url ? path.dirname(fileURLToPath(import.meta.url)) : __dirname;\n const pathDefaultConf: string = path.resolve(currentDir, 'conf/default.yaml');\n try {\n debug('the path of default config used from %s', pathDefaultConf);\n fs.accessSync(pathDefaultConf, fs.constants.R_OK);\n debug('configuration file has enough permissions for reading');\n } catch {\n debug('configuration file does not have enough permissions for reading');\n throw new TypeError('configuration file does not have enough permissions for reading');\n }\n\n return fs.readFileSync(pathDefaultConf, 'utf8');\n}\n\nfunction createConfigFolder(configLocation: SetupDirectory): void {\n const folder = path.dirname(configLocation.path);\n debug(`creating default config file folder at %o`, folder);\n fs.mkdirSync(folder, { recursive: true });\n debug(`folder %o created`, folder);\n}\n\n/**\n * Update the storage links to the new location if it is necessary.\n * @param configLocation\n * @param defaultConfig\n * @returns\n */\nfunction updateStorageLinks(configLocation: SetupDirectory, defaultConfig: string): string {\n debug('checking storage links for %s and type %s', configLocation.path, configLocation.type);\n if (configLocation.type !== XDG) {\n debug(`skip storage override for %s`, configLocation.type);\n return defaultConfig;\n }\n\n // $XDG_DATA_HOME defines the base directory relative to which user specific data\n // files should be stored, If $XDG_DATA_HOME is either not set or empty, a default\n // equal to $HOME/.local/share should be used.\n let dataDir =\n process.env.XDG_DATA_HOME || path.join(process.env.HOME as string, '.local', 'share');\n if (folderExists(dataDir)) {\n debug(`previous storage located`);\n debug(`update storage links to %s`, dataDir);\n dataDir = path.resolve(path.join(dataDir, pkgJSON.name, 'storage'));\n return defaultConfig.replace(/^storage: .\\/storage$/m, `storage: ${dataDir}`);\n }\n debug(`could not find a previous storage location, skip override`);\n return defaultConfig;\n}\n\n/**\n * Return a list of configuration locations by platform.\n * @returns\n */\nfunction getConfigPaths(): SetupDirectory[] {\n const listPaths: (SetupDirectory | void)[] = [\n getXDGDirectory(),\n getWindowsDirectory(),\n getRelativeDefaultDirectory(),\n getOldDirectory(),\n ];\n\n return listPaths.reduce(function (acc, currentValue: SetupDirectory | void): SetupDirectory[] {\n if (typeof currentValue !== 'undefined') {\n debug(\n 'posible directory path generated %s for type %s',\n currentValue?.path,\n currentValue.type\n );\n acc.push(currentValue);\n }\n return acc;\n }, [] as SetupDirectory[]);\n}\n\n/**\n * Get XDG_CONFIG_HOME or HOME location (usually unix)\n *\n * The XDG_CONFIG_HOME environment variable is also part of the XDG Base Directory Specification,\n * which aims to standardize the locations where applications store configuration files and other\n * user-specific data on Unix-like operating systems.\n *\n *\n *\n * https://specifications.freedesktop.org/basedir-spec/latest/\n *\n *\n * @returns\n */\nconst getXDGDirectory = (): SetupDirectory | void => {\n const xDGConfigPath =\n process.env.XDG_CONFIG_HOME || (process.env.HOME && path.join(process.env.HOME, '.config'));\n debug('XDGConfig folder path %s', xDGConfigPath);\n if (xDGConfigPath && folderExists(xDGConfigPath)) {\n debug('XDGConfig folder path %s', xDGConfigPath);\n return {\n path: path.join(xDGConfigPath, pkgJSON.name, CONFIG_FILE),\n type: XDG,\n };\n }\n};\n\n/**\n * Detect windows location, APPDATA\n * usually something like C:\\User\\<Build User>\\AppData\\Local\n * @returns\n */\nconst getWindowsDirectory = (): SetupDirectory | void => {\n if (os.platform() === 'win32' && process.env.APPDATA && folderExists(process.env.APPDATA)) {\n debug('windows appdata folder path %s', process.env.APPDATA);\n return {\n path: path.resolve(path.join(process.env.APPDATA, pkgJSON.name, CONFIG_FILE)),\n type: 'win',\n };\n }\n};\n\n/**\n * Return relative directory, this is the default.\n * It will cretate config in your {currentLocation/verdaccio/config.yaml}\n * @returns\n */\nconst getRelativeDefaultDirectory = (): SetupDirectory => {\n const relativePath = path.resolve(path.join('.', pkgJSON.name, CONFIG_FILE));\n debug('relative folder path %s', relativePath);\n return {\n path: relativePath,\n type: 'def',\n };\n};\n\n/**\n * This should never happens, consider it DEPRECATED\n * @returns\n */\nconst getOldDirectory = (): SetupDirectory => {\n const oldPath = path.resolve(path.join('.', CONFIG_FILE));\n debug('old folder path %s', oldPath);\n return {\n path: oldPath,\n type: 'old',\n };\n};\n\nexport { findConfigFile };\n"],"mappings":"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"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { fileExists, folderExists } from "./config-utils.mjs";
|
|
2
|
+
import buildDebug from "debug";
|
|
3
|
+
import _ from "lodash";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
//#region src/config-path.ts
|
|
9
|
+
var CONFIG_FILE = "config.yaml";
|
|
10
|
+
var XDG = "xdg";
|
|
11
|
+
var pkgJSON = { name: "verdaccio" };
|
|
12
|
+
var debug = buildDebug("verdaccio:config:config-path");
|
|
13
|
+
/**
|
|
14
|
+
* Find and get the first config file that match.
|
|
15
|
+
* @return {String} the config file path
|
|
16
|
+
*/
|
|
17
|
+
function findConfigFile(configPath) {
|
|
18
|
+
debug("searching for config file %o", configPath);
|
|
19
|
+
if (typeof configPath !== "undefined") {
|
|
20
|
+
const configLocation = path.resolve(configPath);
|
|
21
|
+
debug("custom location %s", configLocation);
|
|
22
|
+
return configLocation;
|
|
23
|
+
}
|
|
24
|
+
const configPaths = getConfigPaths();
|
|
25
|
+
debug("%o posible locations found", configPaths.length);
|
|
26
|
+
if (configPaths.length === 0) {
|
|
27
|
+
debug("no configuration files can be processed");
|
|
28
|
+
throw new Error("no configuration files can be processed");
|
|
29
|
+
}
|
|
30
|
+
const primaryConf = _.find(configPaths, (configLocation) => fileExists(configLocation.path));
|
|
31
|
+
if (typeof primaryConf !== "undefined") {
|
|
32
|
+
debug("at least one primary location detected at %s", primaryConf?.path);
|
|
33
|
+
return primaryConf.path;
|
|
34
|
+
}
|
|
35
|
+
debug("no previous location found, creating a new one");
|
|
36
|
+
debug("generating the first match path location %s", configPaths[0].path);
|
|
37
|
+
return createConfigFile(configPaths[0]).path;
|
|
38
|
+
}
|
|
39
|
+
function createConfigFile(configLocation) {
|
|
40
|
+
createConfigFolder(configLocation);
|
|
41
|
+
const defaultConfig = updateStorageLinks(configLocation, readDefaultConfig());
|
|
42
|
+
fs.writeFileSync(configLocation.path, defaultConfig);
|
|
43
|
+
return configLocation;
|
|
44
|
+
}
|
|
45
|
+
function readDefaultConfig() {
|
|
46
|
+
const currentDir = import.meta.url ? path.dirname(fileURLToPath(import.meta.url)) : __dirname;
|
|
47
|
+
const pathDefaultConf = path.resolve(currentDir, "conf/default.yaml");
|
|
48
|
+
try {
|
|
49
|
+
debug("the path of default config used from %s", pathDefaultConf);
|
|
50
|
+
fs.accessSync(pathDefaultConf, fs.constants.R_OK);
|
|
51
|
+
debug("configuration file has enough permissions for reading");
|
|
52
|
+
} catch {
|
|
53
|
+
debug("configuration file does not have enough permissions for reading");
|
|
54
|
+
throw new TypeError("configuration file does not have enough permissions for reading");
|
|
55
|
+
}
|
|
56
|
+
return fs.readFileSync(pathDefaultConf, "utf8");
|
|
57
|
+
}
|
|
58
|
+
function createConfigFolder(configLocation) {
|
|
59
|
+
const folder = path.dirname(configLocation.path);
|
|
60
|
+
debug(`creating default config file folder at %o`, folder);
|
|
61
|
+
fs.mkdirSync(folder, { recursive: true });
|
|
62
|
+
debug(`folder %o created`, folder);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Update the storage links to the new location if it is necessary.
|
|
66
|
+
* @param configLocation
|
|
67
|
+
* @param defaultConfig
|
|
68
|
+
* @returns
|
|
69
|
+
*/
|
|
70
|
+
function updateStorageLinks(configLocation, defaultConfig) {
|
|
71
|
+
debug("checking storage links for %s and type %s", configLocation.path, configLocation.type);
|
|
72
|
+
if (configLocation.type !== XDG) {
|
|
73
|
+
debug(`skip storage override for %s`, configLocation.type);
|
|
74
|
+
return defaultConfig;
|
|
75
|
+
}
|
|
76
|
+
let dataDir = process.env.XDG_DATA_HOME || path.join(process.env.HOME, ".local", "share");
|
|
77
|
+
if (folderExists(dataDir)) {
|
|
78
|
+
debug(`previous storage located`);
|
|
79
|
+
debug(`update storage links to %s`, dataDir);
|
|
80
|
+
dataDir = path.resolve(path.join(dataDir, pkgJSON.name, "storage"));
|
|
81
|
+
return defaultConfig.replace(/^storage: .\/storage$/m, `storage: ${dataDir}`);
|
|
82
|
+
}
|
|
83
|
+
debug(`could not find a previous storage location, skip override`);
|
|
84
|
+
return defaultConfig;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Return a list of configuration locations by platform.
|
|
88
|
+
* @returns
|
|
89
|
+
*/
|
|
90
|
+
function getConfigPaths() {
|
|
91
|
+
return [
|
|
92
|
+
getXDGDirectory(),
|
|
93
|
+
getWindowsDirectory(),
|
|
94
|
+
getRelativeDefaultDirectory(),
|
|
95
|
+
getOldDirectory()
|
|
96
|
+
].reduce(function(acc, currentValue) {
|
|
97
|
+
if (typeof currentValue !== "undefined") {
|
|
98
|
+
debug("posible directory path generated %s for type %s", currentValue?.path, currentValue.type);
|
|
99
|
+
acc.push(currentValue);
|
|
100
|
+
}
|
|
101
|
+
return acc;
|
|
102
|
+
}, []);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get XDG_CONFIG_HOME or HOME location (usually unix)
|
|
106
|
+
*
|
|
107
|
+
* The XDG_CONFIG_HOME environment variable is also part of the XDG Base Directory Specification,
|
|
108
|
+
* which aims to standardize the locations where applications store configuration files and other
|
|
109
|
+
* user-specific data on Unix-like operating systems.
|
|
110
|
+
*
|
|
111
|
+
*
|
|
112
|
+
*
|
|
113
|
+
* https://specifications.freedesktop.org/basedir-spec/latest/
|
|
114
|
+
*
|
|
115
|
+
*
|
|
116
|
+
* @returns
|
|
117
|
+
*/
|
|
118
|
+
var getXDGDirectory = () => {
|
|
119
|
+
const xDGConfigPath = process.env.XDG_CONFIG_HOME || process.env.HOME && path.join(process.env.HOME, ".config");
|
|
120
|
+
debug("XDGConfig folder path %s", xDGConfigPath);
|
|
121
|
+
if (xDGConfigPath && folderExists(xDGConfigPath)) {
|
|
122
|
+
debug("XDGConfig folder path %s", xDGConfigPath);
|
|
123
|
+
return {
|
|
124
|
+
path: path.join(xDGConfigPath, pkgJSON.name, CONFIG_FILE),
|
|
125
|
+
type: XDG
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Detect windows location, APPDATA
|
|
131
|
+
* usually something like C:\User\<Build User>\AppData\Local
|
|
132
|
+
* @returns
|
|
133
|
+
*/
|
|
134
|
+
var getWindowsDirectory = () => {
|
|
135
|
+
if (os.platform() === "win32" && process.env.APPDATA && folderExists(process.env.APPDATA)) {
|
|
136
|
+
debug("windows appdata folder path %s", process.env.APPDATA);
|
|
137
|
+
return {
|
|
138
|
+
path: path.resolve(path.join(process.env.APPDATA, pkgJSON.name, CONFIG_FILE)),
|
|
139
|
+
type: "win"
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Return relative directory, this is the default.
|
|
145
|
+
* It will cretate config in your {currentLocation/verdaccio/config.yaml}
|
|
146
|
+
* @returns
|
|
147
|
+
*/
|
|
148
|
+
var getRelativeDefaultDirectory = () => {
|
|
149
|
+
const relativePath = path.resolve(path.join(".", pkgJSON.name, CONFIG_FILE));
|
|
150
|
+
debug("relative folder path %s", relativePath);
|
|
151
|
+
return {
|
|
152
|
+
path: relativePath,
|
|
153
|
+
type: "def"
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* This should never happens, consider it DEPRECATED
|
|
158
|
+
* @returns
|
|
159
|
+
*/
|
|
160
|
+
var getOldDirectory = () => {
|
|
161
|
+
const oldPath = path.resolve(path.join(".", CONFIG_FILE));
|
|
162
|
+
debug("old folder path %s", oldPath);
|
|
163
|
+
return {
|
|
164
|
+
path: oldPath,
|
|
165
|
+
type: "old"
|
|
166
|
+
};
|
|
167
|
+
};
|
|
168
|
+
//#endregion
|
|
169
|
+
export { findConfigFile, readDefaultConfig };
|
|
170
|
+
|
|
171
|
+
//# sourceMappingURL=config-path.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-path.mjs","names":[],"sources":["../src/config-path.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport _ from 'lodash';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { fileExists, folderExists } from './config-utils';\n\nconst CONFIG_FILE = 'config.yaml';\nconst XDG = 'xdg';\n\nconst pkgJSON = {\n name: 'verdaccio',\n};\n\nexport type SetupDirectory = {\n path: string;\n type: 'xdg' | 'win' | 'win32' | 'def' | 'old';\n};\n\nconst debug = buildDebug('verdaccio:config:config-path');\n\n/**\n * Find and get the first config file that match.\n * @return {String} the config file path\n */\nfunction findConfigFile(configPath?: string): string {\n debug('searching for config file %o', configPath);\n if (typeof configPath !== 'undefined') {\n const configLocation = path.resolve(configPath);\n debug('custom location %s', configLocation);\n return configLocation;\n }\n\n const configPaths: SetupDirectory[] = getConfigPaths();\n debug('%o posible locations found', configPaths.length);\n if (configPaths.length === 0) {\n debug('no configuration files can be processed');\n // this should never happens\n throw new Error('no configuration files can be processed');\n }\n\n // find the first location that already exist\n const primaryConf: SetupDirectory | void = _.find(configPaths, (configLocation: SetupDirectory) =>\n fileExists(configLocation.path)\n );\n\n if (typeof primaryConf !== 'undefined') {\n debug('at least one primary location detected at %s', primaryConf?.path);\n return primaryConf.path;\n }\n debug('no previous location found, creating a new one');\n debug('generating the first match path location %s', configPaths[0].path);\n return createConfigFile(configPaths[0]).path;\n}\n\nfunction createConfigFile(configLocation: SetupDirectory): SetupDirectory {\n createConfigFolder(configLocation);\n\n const defaultConfig = updateStorageLinks(configLocation, readDefaultConfig());\n\n fs.writeFileSync(configLocation.path, defaultConfig);\n\n return configLocation;\n}\n\nexport function readDefaultConfig(): string {\n // import.meta.url is only defined in the ESM build; the CJS build falls back to __dirname\n const currentDir = import.meta.url ? path.dirname(fileURLToPath(import.meta.url)) : __dirname;\n const pathDefaultConf: string = path.resolve(currentDir, 'conf/default.yaml');\n try {\n debug('the path of default config used from %s', pathDefaultConf);\n fs.accessSync(pathDefaultConf, fs.constants.R_OK);\n debug('configuration file has enough permissions for reading');\n } catch {\n debug('configuration file does not have enough permissions for reading');\n throw new TypeError('configuration file does not have enough permissions for reading');\n }\n\n return fs.readFileSync(pathDefaultConf, 'utf8');\n}\n\nfunction createConfigFolder(configLocation: SetupDirectory): void {\n const folder = path.dirname(configLocation.path);\n debug(`creating default config file folder at %o`, folder);\n fs.mkdirSync(folder, { recursive: true });\n debug(`folder %o created`, folder);\n}\n\n/**\n * Update the storage links to the new location if it is necessary.\n * @param configLocation\n * @param defaultConfig\n * @returns\n */\nfunction updateStorageLinks(configLocation: SetupDirectory, defaultConfig: string): string {\n debug('checking storage links for %s and type %s', configLocation.path, configLocation.type);\n if (configLocation.type !== XDG) {\n debug(`skip storage override for %s`, configLocation.type);\n return defaultConfig;\n }\n\n // $XDG_DATA_HOME defines the base directory relative to which user specific data\n // files should be stored, If $XDG_DATA_HOME is either not set or empty, a default\n // equal to $HOME/.local/share should be used.\n let dataDir =\n process.env.XDG_DATA_HOME || path.join(process.env.HOME as string, '.local', 'share');\n if (folderExists(dataDir)) {\n debug(`previous storage located`);\n debug(`update storage links to %s`, dataDir);\n dataDir = path.resolve(path.join(dataDir, pkgJSON.name, 'storage'));\n return defaultConfig.replace(/^storage: .\\/storage$/m, `storage: ${dataDir}`);\n }\n debug(`could not find a previous storage location, skip override`);\n return defaultConfig;\n}\n\n/**\n * Return a list of configuration locations by platform.\n * @returns\n */\nfunction getConfigPaths(): SetupDirectory[] {\n const listPaths: (SetupDirectory | void)[] = [\n getXDGDirectory(),\n getWindowsDirectory(),\n getRelativeDefaultDirectory(),\n getOldDirectory(),\n ];\n\n return listPaths.reduce(function (acc, currentValue: SetupDirectory | void): SetupDirectory[] {\n if (typeof currentValue !== 'undefined') {\n debug(\n 'posible directory path generated %s for type %s',\n currentValue?.path,\n currentValue.type\n );\n acc.push(currentValue);\n }\n return acc;\n }, [] as SetupDirectory[]);\n}\n\n/**\n * Get XDG_CONFIG_HOME or HOME location (usually unix)\n *\n * The XDG_CONFIG_HOME environment variable is also part of the XDG Base Directory Specification,\n * which aims to standardize the locations where applications store configuration files and other\n * user-specific data on Unix-like operating systems.\n *\n *\n *\n * https://specifications.freedesktop.org/basedir-spec/latest/\n *\n *\n * @returns\n */\nconst getXDGDirectory = (): SetupDirectory | void => {\n const xDGConfigPath =\n process.env.XDG_CONFIG_HOME || (process.env.HOME && path.join(process.env.HOME, '.config'));\n debug('XDGConfig folder path %s', xDGConfigPath);\n if (xDGConfigPath && folderExists(xDGConfigPath)) {\n debug('XDGConfig folder path %s', xDGConfigPath);\n return {\n path: path.join(xDGConfigPath, pkgJSON.name, CONFIG_FILE),\n type: XDG,\n };\n }\n};\n\n/**\n * Detect windows location, APPDATA\n * usually something like C:\\User\\<Build User>\\AppData\\Local\n * @returns\n */\nconst getWindowsDirectory = (): SetupDirectory | void => {\n if (os.platform() === 'win32' && process.env.APPDATA && folderExists(process.env.APPDATA)) {\n debug('windows appdata folder path %s', process.env.APPDATA);\n return {\n path: path.resolve(path.join(process.env.APPDATA, pkgJSON.name, CONFIG_FILE)),\n type: 'win',\n };\n }\n};\n\n/**\n * Return relative directory, this is the default.\n * It will cretate config in your {currentLocation/verdaccio/config.yaml}\n * @returns\n */\nconst getRelativeDefaultDirectory = (): SetupDirectory => {\n const relativePath = path.resolve(path.join('.', pkgJSON.name, CONFIG_FILE));\n debug('relative folder path %s', relativePath);\n return {\n path: relativePath,\n type: 'def',\n };\n};\n\n/**\n * This should never happens, consider it DEPRECATED\n * @returns\n */\nconst getOldDirectory = (): SetupDirectory => {\n const oldPath = path.resolve(path.join('.', CONFIG_FILE));\n debug('old folder path %s', oldPath);\n return {\n path: oldPath,\n type: 'old',\n };\n};\n\nexport { findConfigFile };\n"],"mappings":"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"}
|