package-management 0.0.15 → 0.1.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/LICENSE +21 -0
- package/README.md +1 -0
- package/dist/index.cjs +382 -357
- package/dist/index.d.cts +149 -75
- package/dist/index.d.mts +149 -75
- package/dist/index.d.ts +149 -75
- package/dist/index.mjs +378 -357
- package/package.json +10 -13
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const ErrorStackParser = require('error-stack-parser');
|
|
4
3
|
const path = require('pathe');
|
|
5
|
-
const
|
|
6
|
-
const path$1 = require('node:path');
|
|
4
|
+
const util = require('node:util');
|
|
7
5
|
const node_url = require('node:url');
|
|
8
6
|
const node_fs = require('node:fs');
|
|
9
7
|
const asyncCacheFn = require('async-cache-fn');
|
|
@@ -11,17 +9,19 @@ const execa = require('execa');
|
|
|
11
9
|
const findUp = require('find-up');
|
|
12
10
|
const promises = require('node:fs/promises');
|
|
13
11
|
const mlly = require('mlly');
|
|
12
|
+
const WST = require('workspace-tools');
|
|
13
|
+
const process = require('node:process');
|
|
14
|
+
const path$1 = require('node:path');
|
|
14
15
|
const globby = require('globby');
|
|
15
16
|
const gitignoreParser = require('parse-gitignore');
|
|
16
|
-
const WST = require('workspace-tools');
|
|
17
17
|
const utils = require('pathe/utils');
|
|
18
18
|
const os = require('node:os');
|
|
19
19
|
const jsoncParser = require('jsonc-parser');
|
|
20
|
-
const util = require('@arktype/util');
|
|
21
20
|
const unstorage = require('unstorage');
|
|
22
21
|
const defineMemoryDriver = require('unstorage/drivers/memory');
|
|
23
22
|
const defineFsLiteDriver = require('unstorage/drivers/fs-lite');
|
|
24
23
|
|
|
24
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
25
25
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
26
26
|
|
|
27
27
|
function _interopNamespaceCompat(e) {
|
|
@@ -36,16 +36,80 @@ function _interopNamespaceCompat(e) {
|
|
|
36
36
|
return n;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
const
|
|
40
|
-
const
|
|
39
|
+
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
40
|
+
const util__default = /*#__PURE__*/_interopDefaultCompat(util);
|
|
41
|
+
const WST__namespace = /*#__PURE__*/_interopNamespaceCompat(WST);
|
|
41
42
|
const process__default = /*#__PURE__*/_interopDefaultCompat(process);
|
|
42
|
-
const path__default = /*#__PURE__*/_interopDefaultCompat(path$1);
|
|
43
|
+
const path__default$1 = /*#__PURE__*/_interopDefaultCompat(path$1);
|
|
43
44
|
const gitignoreParser__default = /*#__PURE__*/_interopDefaultCompat(gitignoreParser);
|
|
44
|
-
const WST__namespace = /*#__PURE__*/_interopNamespaceCompat(WST);
|
|
45
45
|
const os__default = /*#__PURE__*/_interopDefaultCompat(os);
|
|
46
46
|
const defineMemoryDriver__default = /*#__PURE__*/_interopDefaultCompat(defineMemoryDriver);
|
|
47
47
|
const defineFsLiteDriver__default = /*#__PURE__*/_interopDefaultCompat(defineFsLiteDriver);
|
|
48
48
|
|
|
49
|
+
const getCallSites = "getCallSites" in util__default ? util__default.getCallSites : void 0;
|
|
50
|
+
const MAX_FRAMES = 200;
|
|
51
|
+
function resolveCallerFile(options) {
|
|
52
|
+
const { from, boundaryFunctionName, internalScripts = [] } = options ?? {};
|
|
53
|
+
if (from) return toCallerPath(String(from));
|
|
54
|
+
if (getCallSites === void 0) return void 0;
|
|
55
|
+
const sites = getCallSites(MAX_FRAMES, { sourceMap: true });
|
|
56
|
+
const scriptName = boundaryFunctionName && frameAfterFunction(sites, boundaryFunctionName) || firstForeignFrame(sites, [OWN_SCRIPT, ...internalScripts]);
|
|
57
|
+
return scriptName ? toFilePath(scriptName) : void 0;
|
|
58
|
+
}
|
|
59
|
+
const OWN_SCRIPT = (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href));
|
|
60
|
+
function frameAfterFunction(sites, functionName) {
|
|
61
|
+
const boundary = sites.findIndex((site) => site.functionName === functionName);
|
|
62
|
+
return boundary === -1 ? void 0 : sites[boundary + 1]?.scriptName;
|
|
63
|
+
}
|
|
64
|
+
function firstForeignFrame(sites, internalScripts) {
|
|
65
|
+
const internal = new Set(internalScripts.map(toFilePath));
|
|
66
|
+
return sites.find(
|
|
67
|
+
(site) => (
|
|
68
|
+
// Frames from `node:` internals and evaluated code name no file, so they
|
|
69
|
+
// are never the caller's location however far out they appear.
|
|
70
|
+
isFileScript(site.scriptName) && !internal.has(toFilePath(site.scriptName))
|
|
71
|
+
)
|
|
72
|
+
)?.scriptName;
|
|
73
|
+
}
|
|
74
|
+
const isFileScript = (script) => Boolean(script) && (script.startsWith("file:") || path.isAbsolute(script));
|
|
75
|
+
const toFilePath = (script) => script.startsWith("file:") ? node_url.fileURLToPath(script) : script;
|
|
76
|
+
function toCallerPath(from) {
|
|
77
|
+
if (from.startsWith("file:")) return node_url.fileURLToPath(from);
|
|
78
|
+
if (path.isAbsolute(from)) return from;
|
|
79
|
+
throw new Error(
|
|
80
|
+
`\`from\` must be a file: URL or an absolute path, received ${JSON.stringify(from)}. Pass \`import.meta.url\`.`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const _filename = (options) => resolveCallerFile(withOwnScript(options));
|
|
85
|
+
const _dirname = (options) => {
|
|
86
|
+
const filePath = resolveCallerFile(withOwnScript(options));
|
|
87
|
+
return filePath === void 0 ? void 0 : path.dirname(filePath);
|
|
88
|
+
};
|
|
89
|
+
const withOwnScript = (options) => ({
|
|
90
|
+
...options,
|
|
91
|
+
internalScripts: [...options?.internalScripts ?? [], (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))]
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
function createFile(filePath, data, options) {
|
|
95
|
+
const { encoding = "utf-8", ...rest } = typeof options === "string" ? { encoding: options } : options ?? {};
|
|
96
|
+
const dir = path__default.dirname(filePath);
|
|
97
|
+
const writeFileOptions = { encoding, ...rest };
|
|
98
|
+
if (!node_fs.existsSync(dir)) {
|
|
99
|
+
node_fs.mkdirSync(dir, { recursive: true });
|
|
100
|
+
}
|
|
101
|
+
node_fs.writeFileSync(filePath, data, writeFileOptions);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function isWritable(filename) {
|
|
105
|
+
try {
|
|
106
|
+
node_fs.accessSync(filename, node_fs.constants.W_OK);
|
|
107
|
+
return true;
|
|
108
|
+
} catch (e) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
49
113
|
const toArray = (data) => Array.isArray(data) ? data : [data];
|
|
50
114
|
const entriesOf = (o) => Object.entries(o);
|
|
51
115
|
const fromEntries = (entries) => Object.fromEntries(entries);
|
|
@@ -59,7 +123,7 @@ const select = (obj, selection, mode) => {
|
|
|
59
123
|
};
|
|
60
124
|
function normalizePath(path$1, option) {
|
|
61
125
|
if (typeof option === "function") {
|
|
62
|
-
return
|
|
126
|
+
return option(path$1);
|
|
63
127
|
}
|
|
64
128
|
if (option === false) {
|
|
65
129
|
return path$1;
|
|
@@ -71,14 +135,6 @@ const invariant = (predicate, message) => {
|
|
|
71
135
|
throw new Error(message);
|
|
72
136
|
}
|
|
73
137
|
};
|
|
74
|
-
function getArrayItemAtOffset(arr, index, offset = 0) {
|
|
75
|
-
if (arr === void 0 || index === void 0) return void 0;
|
|
76
|
-
return arr[index + offset];
|
|
77
|
-
}
|
|
78
|
-
function isMatching(a, b) {
|
|
79
|
-
if (!a || !b) return false;
|
|
80
|
-
return a === b;
|
|
81
|
-
}
|
|
82
138
|
function checkResult(cb, options) {
|
|
83
139
|
try {
|
|
84
140
|
return buildSingleProp({
|
|
@@ -103,123 +159,16 @@ function buildSingleProp(entry) {
|
|
|
103
159
|
return { [key]: value };
|
|
104
160
|
}
|
|
105
161
|
|
|
106
|
-
function findCallerStackFrame(options) {
|
|
107
|
-
return findErrorStackFrame(options, (frame) => frame.isParentOfRootFunction);
|
|
108
|
-
}
|
|
109
|
-
function findErrorStackFrame(options, find) {
|
|
110
|
-
return getErrorStackFrames(options, find)[0];
|
|
111
|
-
}
|
|
112
|
-
function getErrorStackFrames(options, filter) {
|
|
113
|
-
const { error, rootFunctionName, startFrom = "top" } = options;
|
|
114
|
-
const frames = startFrom === "bottom" ? ErrorStackParser__default.parse(error).reverse() : ErrorStackParser__default.parse(error);
|
|
115
|
-
const { parsedFrames } = frames.reduce(
|
|
116
|
-
(acc, frame, index) => {
|
|
117
|
-
const parsed = parseFrame({
|
|
118
|
-
frame,
|
|
119
|
-
index,
|
|
120
|
-
rootFunctionName,
|
|
121
|
-
frames
|
|
122
|
-
});
|
|
123
|
-
const isValid = filter ? filter(parsed) : true;
|
|
124
|
-
if (isValid) {
|
|
125
|
-
acc.parsedFrames.push(parsed);
|
|
126
|
-
}
|
|
127
|
-
return acc;
|
|
128
|
-
},
|
|
129
|
-
{ parsedFrames: [] }
|
|
130
|
-
);
|
|
131
|
-
return parsedFrames ?? [];
|
|
132
|
-
}
|
|
133
|
-
function parseFrame(options) {
|
|
134
|
-
const { frame, frames, index, rootFunctionName, cwd, debug } = options ?? {};
|
|
135
|
-
const functionName = parseFunctionName(frame.functionName);
|
|
136
|
-
const isRootFunction = isMatching(functionName, rootFunctionName);
|
|
137
|
-
const beforeFrameFunctionName = parseFunctionName(
|
|
138
|
-
getArrayItemAtOffset(frames, index, -1)?.functionName
|
|
139
|
-
);
|
|
140
|
-
const isParentOfRootFunction = isMatching(
|
|
141
|
-
beforeFrameFunctionName,
|
|
142
|
-
rootFunctionName
|
|
143
|
-
);
|
|
144
|
-
const fileData = frame.fileName ? getFilePathData({ filepath: frame.fileName, cwd }) : void 0;
|
|
145
|
-
const { isFileInCwd: isFrameInScope, ...restFileData } = fileData ?? {};
|
|
146
|
-
const data = {
|
|
147
|
-
...restFileData,
|
|
148
|
-
functionName,
|
|
149
|
-
source: frame.source,
|
|
150
|
-
sourceFunctionName: frame.functionName,
|
|
151
|
-
isFrameInScope,
|
|
152
|
-
place: placeFormatter(index, frames?.length),
|
|
153
|
-
isRootFunction,
|
|
154
|
-
isParentOfRootFunction,
|
|
155
|
-
rootFunctionName
|
|
156
|
-
};
|
|
157
|
-
debug && console.log(data);
|
|
158
|
-
return data;
|
|
159
|
-
}
|
|
160
|
-
function getFilePathData({
|
|
161
|
-
filepath,
|
|
162
|
-
cwd
|
|
163
|
-
}) {
|
|
164
|
-
const workingDir = cwd ?? process__default.cwd();
|
|
165
|
-
const filePath = path.normalize(toFilePath(filepath));
|
|
166
|
-
const fileBasename = path.basename(filePath);
|
|
167
|
-
const dirPath = path.dirname(filePath);
|
|
168
|
-
const dirBasename = path.basename(dirPath);
|
|
169
|
-
const relativeFilePath = path.relative(workingDir, filePath);
|
|
170
|
-
const relativeDirPath = path.dirname(relativeFilePath);
|
|
171
|
-
const isFileInCwd = filePath.startsWith(workingDir);
|
|
172
|
-
return {
|
|
173
|
-
filePath,
|
|
174
|
-
dirPath,
|
|
175
|
-
relativeFilePath,
|
|
176
|
-
relativeDirPath,
|
|
177
|
-
fileBasename,
|
|
178
|
-
dirBasename,
|
|
179
|
-
isFileInCwd
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
function toFilePath(fileName) {
|
|
183
|
-
return fileName.startsWith("file:") ? node_url.fileURLToPath(fileName) : fileName;
|
|
184
|
-
}
|
|
185
|
-
function parseFunctionName(functionName) {
|
|
186
|
-
if (!functionName) return void 0;
|
|
187
|
-
return removeStart(functionName, "Module.");
|
|
188
|
-
}
|
|
189
|
-
function removeStart(input, value) {
|
|
190
|
-
return input.startsWith(value) ? input.slice(value.length) : input;
|
|
191
|
-
}
|
|
192
|
-
function placeFormatter(index, total) {
|
|
193
|
-
if (index === void 0 || !total) return void 0;
|
|
194
|
-
return [index, total].join("/");
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const _filename = (options) => {
|
|
198
|
-
const { filePath } = findCallerStackFrame({ error: new Error(), ...options }) ?? {};
|
|
199
|
-
return filePath;
|
|
200
|
-
};
|
|
201
|
-
const _dirname = (options) => {
|
|
202
|
-
const { dirPath } = findCallerStackFrame({ error: new Error(), ...options }) ?? {};
|
|
203
|
-
return dirPath;
|
|
204
|
-
};
|
|
205
|
-
|
|
206
162
|
async function resolveModule(module) {
|
|
207
163
|
const resolved = await module;
|
|
208
|
-
|
|
164
|
+
const hasDefault = resolved !== null && typeof resolved === "object" && "default" in resolved;
|
|
165
|
+
return hasDefault ? resolved.default : resolved;
|
|
209
166
|
}
|
|
210
167
|
function isPackageModuleFound(name, options) {
|
|
211
168
|
return Boolean(resolvePackageModulePath(name, options));
|
|
212
169
|
}
|
|
213
170
|
function resolvePackageModulePath(name, options) {
|
|
214
|
-
|
|
215
|
-
[`${name}/package.json`, name],
|
|
216
|
-
options
|
|
217
|
-
);
|
|
218
|
-
if (resolvedPath === void 0) {
|
|
219
|
-
console.error(`Could not resolve package ${name}`);
|
|
220
|
-
return void 0;
|
|
221
|
-
}
|
|
222
|
-
return resolvedPath;
|
|
171
|
+
return findResolvedModulePath([`${name}/package.json`, name], options);
|
|
223
172
|
}
|
|
224
173
|
function findResolvedModulePath(paths, options) {
|
|
225
174
|
for (const path of paths) {
|
|
@@ -241,28 +190,68 @@ function resolveModulePath(modulePath, options) {
|
|
|
241
190
|
}
|
|
242
191
|
}
|
|
243
192
|
|
|
193
|
+
function getPackageFolder(options) {
|
|
194
|
+
return WST__namespace.findPackageRoot(options?.cwd ?? process__default.cwd());
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function getPackageInfo(options) {
|
|
198
|
+
const packageDir = getPackageFolder(options);
|
|
199
|
+
if (!packageDir) {
|
|
200
|
+
throw new Error(
|
|
201
|
+
`No package.json found searching up from "${options?.cwd ?? process__default.cwd()}"`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
return readPackageInfo({ packageDir });
|
|
205
|
+
}
|
|
206
|
+
function readPackageInfo({
|
|
207
|
+
packageDir
|
|
208
|
+
}) {
|
|
209
|
+
const packageJsonPath = path__default$1.join(packageDir, "package.json");
|
|
210
|
+
const packageJson = readPackageJson(packageJsonPath);
|
|
211
|
+
return {
|
|
212
|
+
name: packageJson.name,
|
|
213
|
+
path: packageJsonPath,
|
|
214
|
+
dirpath: packageDir,
|
|
215
|
+
packageJson
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
const packageJsonCache = /* @__PURE__ */ new Map();
|
|
219
|
+
function readPackageJson(packageJsonPath) {
|
|
220
|
+
const { mtimeMs } = node_fs.statSync(packageJsonPath);
|
|
221
|
+
const cached = packageJsonCache.get(packageJsonPath);
|
|
222
|
+
if (cached?.mtimeMs === mtimeMs) return cached.packageJson;
|
|
223
|
+
const packageJson = JSON.parse(
|
|
224
|
+
node_fs.readFileSync(packageJsonPath, "utf-8")
|
|
225
|
+
);
|
|
226
|
+
packageJsonCache.set(packageJsonPath, { mtimeMs, packageJson });
|
|
227
|
+
return packageJson;
|
|
228
|
+
}
|
|
229
|
+
|
|
244
230
|
const tsconfig = (tsconfigDir) => ({
|
|
245
231
|
get paths() {
|
|
232
|
+
if (!tsconfigDir) return [];
|
|
246
233
|
return globby.globbySync(["tsconfig.json", "tsconfig.*.json"], {
|
|
247
|
-
cwd: tsconfigDir
|
|
248
|
-
|
|
234
|
+
cwd: tsconfigDir,
|
|
235
|
+
absolute: true
|
|
236
|
+
});
|
|
249
237
|
}
|
|
250
238
|
});
|
|
251
239
|
|
|
252
|
-
function
|
|
253
|
-
return gitignoreParser__default(
|
|
240
|
+
function parseGitignoreContent(gitignoreContent, options) {
|
|
241
|
+
return gitignoreParser__default(gitignoreContent, options);
|
|
254
242
|
}
|
|
255
|
-
function getGitignoreData(gitignorePath) {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
243
|
+
function getGitignoreData(gitignorePath, options) {
|
|
244
|
+
if (!gitignorePath || !node_fs.existsSync(gitignorePath)) {
|
|
245
|
+
return parseGitignoreContent("", options);
|
|
246
|
+
}
|
|
247
|
+
return parseGitignoreContent(node_fs.readFileSync(gitignorePath, "utf-8"), options);
|
|
259
248
|
}
|
|
260
|
-
const gitignore = (gitignorePath) => ({
|
|
249
|
+
const gitignore = (gitignorePath, options) => ({
|
|
261
250
|
get data() {
|
|
262
|
-
return getGitignoreData(gitignorePath);
|
|
251
|
+
return getGitignoreData(gitignorePath, options);
|
|
263
252
|
},
|
|
264
253
|
get patterns() {
|
|
265
|
-
return getGitignoreData(gitignorePath).patterns;
|
|
254
|
+
return getGitignoreData(gitignorePath, options).patterns;
|
|
266
255
|
}
|
|
267
256
|
});
|
|
268
257
|
|
|
@@ -325,36 +314,13 @@ function getWorkspaceFolder(options) {
|
|
|
325
314
|
throwIfNotFound = true
|
|
326
315
|
} = options ?? {};
|
|
327
316
|
const getFolder = fallbackToGitRoot ? WST__namespace.findProjectRoot : WST__namespace.getWorkspaceManagerRoot;
|
|
328
|
-
const folder = getFolder(cwd);
|
|
317
|
+
const folder = checkResult(() => getFolder(cwd)).data;
|
|
329
318
|
if (folder === void 0 && throwIfNotFound) {
|
|
330
319
|
throw new Error(`Could not find workspace folder`);
|
|
331
320
|
}
|
|
332
321
|
return folder;
|
|
333
322
|
}
|
|
334
323
|
|
|
335
|
-
function getPackageFolder(options) {
|
|
336
|
-
return WST__namespace.findPackageRoot(options?.cwd ?? process__default.cwd());
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
function getPackageInfo(options) {
|
|
340
|
-
const packageDir = getPackageFolder(options);
|
|
341
|
-
return readPackageInfo({ packageDir });
|
|
342
|
-
}
|
|
343
|
-
function readPackageInfo({
|
|
344
|
-
packageDir
|
|
345
|
-
}) {
|
|
346
|
-
const packageJsonPath = path__default.join(packageDir, "package.json");
|
|
347
|
-
const packageJson = JSON.parse(
|
|
348
|
-
node_fs.readFileSync(packageJsonPath, "utf-8")
|
|
349
|
-
);
|
|
350
|
-
return {
|
|
351
|
-
name: packageJson.name,
|
|
352
|
-
path: packageJsonPath,
|
|
353
|
-
dirpath: packageDir,
|
|
354
|
-
packageJson
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
|
|
358
324
|
function getWorkspaceProjectInfo(options) {
|
|
359
325
|
try {
|
|
360
326
|
const workspaceDir = getWorkspaceFolder(options);
|
|
@@ -370,13 +336,21 @@ function getWorkspacePackageInfoList(options) {
|
|
|
370
336
|
const wstList = WST__namespace.getWorkspaceInfos(workspaceDir);
|
|
371
337
|
return resolveWstList(wstList);
|
|
372
338
|
}
|
|
339
|
+
function toPackageInfo(info) {
|
|
340
|
+
return {
|
|
341
|
+
name: info.name,
|
|
342
|
+
dirpath: info.path,
|
|
343
|
+
path: path.join(info.path, "package.json"),
|
|
344
|
+
packageJson: info.packageJson
|
|
345
|
+
};
|
|
346
|
+
}
|
|
373
347
|
function common(options) {
|
|
374
348
|
const { cwd, includeRoot: includeWorkspace } = options ?? {};
|
|
375
349
|
const workspaceDir = getWorkspaceFolder({ cwd });
|
|
376
350
|
function resolveWstList(list) {
|
|
377
351
|
if (!workspaceDir || !list) return [];
|
|
378
|
-
|
|
379
|
-
return
|
|
352
|
+
const packages = list.map(toPackageInfo);
|
|
353
|
+
return includeWorkspace ? [getWorkspaceProjectInfo({ cwd }), ...packages] : packages;
|
|
380
354
|
}
|
|
381
355
|
return {
|
|
382
356
|
workspaceDir,
|
|
@@ -393,7 +367,7 @@ function getWorkspacePackageInfoMap(options) {
|
|
|
393
367
|
|
|
394
368
|
function getProjectInfoByName(name, options) {
|
|
395
369
|
const { cwd } = options ?? {};
|
|
396
|
-
return getWorkspacePackageInfoMap({ cwd })[name];
|
|
370
|
+
return getWorkspacePackageInfoMap({ cwd, includeRoot: true })[name];
|
|
397
371
|
}
|
|
398
372
|
|
|
399
373
|
function getGitRootFolder(options) {
|
|
@@ -408,7 +382,7 @@ function getGitRootFolder(options) {
|
|
|
408
382
|
}
|
|
409
383
|
return void 0;
|
|
410
384
|
}
|
|
411
|
-
return path__default
|
|
385
|
+
return path__default.normalize(stdout);
|
|
412
386
|
}
|
|
413
387
|
|
|
414
388
|
function getProjectInfo(folder, options) {
|
|
@@ -439,9 +413,14 @@ function parseWorkspaceFolderTypeOptions(option, defaultOptions) {
|
|
|
439
413
|
|
|
440
414
|
const project = (...args) => {
|
|
441
415
|
const [source, projectOptions] = args;
|
|
442
|
-
const { packageJson, packageJsonPath, packageName, projectDir } = info();
|
|
443
416
|
const {
|
|
444
|
-
|
|
417
|
+
packageJson,
|
|
418
|
+
name: packageName,
|
|
419
|
+
dirpath: projectDir,
|
|
420
|
+
path: packageJsonPath
|
|
421
|
+
} = getProjectInfo(source, projectOptions) ?? {};
|
|
422
|
+
const {
|
|
423
|
+
findPackageManager,
|
|
445
424
|
detectPackageManagers,
|
|
446
425
|
detectLockfilePackageManagers,
|
|
447
426
|
detectGlobalPackageManagers,
|
|
@@ -449,41 +428,29 @@ const project = (...args) => {
|
|
|
449
428
|
filterPackageManagers,
|
|
450
429
|
mapPackageManagers
|
|
451
430
|
} = definePackageManagerClient({ cwd: projectDir });
|
|
431
|
+
const getPackageJson = () => projectDir ? readPackageInfo({ packageDir: projectDir }).packageJson : packageJson;
|
|
452
432
|
return {
|
|
453
433
|
packageJson,
|
|
454
434
|
packageJsonPath,
|
|
455
435
|
packageName,
|
|
456
436
|
projectDir,
|
|
457
|
-
findPackageManager
|
|
437
|
+
findPackageManager,
|
|
458
438
|
detectPackageManagers,
|
|
459
439
|
detectGlobalPackageManagers,
|
|
460
440
|
detectLockfilePackageManagers,
|
|
461
441
|
globalVersions,
|
|
462
442
|
mapPackageManagers,
|
|
463
|
-
|
|
464
|
-
|
|
443
|
+
// Passed through as-is: substituting "" for an unresolved project made
|
|
444
|
+
// both of these read from the calling process's directory instead.
|
|
445
|
+
tsconfig: tsconfig(projectDir),
|
|
446
|
+
gitignore: gitignore(
|
|
447
|
+
projectDir ? path__default.join(projectDir, ".gitignore") : void 0
|
|
448
|
+
),
|
|
465
449
|
filterPackageManagers,
|
|
466
|
-
getPackageJson
|
|
467
|
-
findDependencyInPackageJson: (options) => findDependencyInPackageJson(options,
|
|
468
|
-
isDependencyInPackageJson: (options) => isDependencyInPackageJson(options,
|
|
450
|
+
getPackageJson,
|
|
451
|
+
findDependencyInPackageJson: (options) => findDependencyInPackageJson(options, getPackageJson()),
|
|
452
|
+
isDependencyInPackageJson: (options) => isDependencyInPackageJson(options, getPackageJson())
|
|
469
453
|
};
|
|
470
|
-
function info() {
|
|
471
|
-
const {
|
|
472
|
-
packageJson: packageJson2,
|
|
473
|
-
name: packageName2,
|
|
474
|
-
dirpath: projectDir2,
|
|
475
|
-
path: packageJsonPath2
|
|
476
|
-
} = getProjectInfo(source, projectOptions) ?? {};
|
|
477
|
-
return {
|
|
478
|
-
packageJson: packageJson2,
|
|
479
|
-
packageJsonPath: packageJsonPath2,
|
|
480
|
-
packageName: packageName2,
|
|
481
|
-
projectDir: projectDir2
|
|
482
|
-
};
|
|
483
|
-
}
|
|
484
|
-
function get(key) {
|
|
485
|
-
return info()[key];
|
|
486
|
-
}
|
|
487
454
|
};
|
|
488
455
|
|
|
489
456
|
function getWorkspacePackageNames(options) {
|
|
@@ -498,18 +465,24 @@ const workspace = {
|
|
|
498
465
|
getProject: project
|
|
499
466
|
};
|
|
500
467
|
|
|
501
|
-
function importer(imports, options) {
|
|
468
|
+
async function importer(imports, options) {
|
|
502
469
|
const { install: defaultInstall = true, installer } = options ?? {};
|
|
470
|
+
const resolved = imports.map((option) => resolveImportOption(option));
|
|
471
|
+
const missing = resolved.filter(
|
|
472
|
+
(option) => Boolean(option.name) && (option.install ?? defaultInstall) && !((option.checkExists ?? true) && isSatisfied(option.name))
|
|
473
|
+
);
|
|
474
|
+
await installMissing(
|
|
475
|
+
missing.filter(({ dev }) => !dev).map(({ name }) => name),
|
|
476
|
+
{ dev: false },
|
|
477
|
+
installer
|
|
478
|
+
);
|
|
479
|
+
await installMissing(
|
|
480
|
+
missing.filter(({ dev }) => dev).map(({ name }) => name),
|
|
481
|
+
{ dev: true },
|
|
482
|
+
installer
|
|
483
|
+
);
|
|
503
484
|
return Promise.all(
|
|
504
|
-
|
|
505
|
-
const importOpt = resolveImportOption(e);
|
|
506
|
-
const shouldInstall = importOpt.install ?? defaultInstall;
|
|
507
|
-
if (shouldInstall && importOpt.name) {
|
|
508
|
-
await installImport(importOpt.name, importOpt, installer);
|
|
509
|
-
}
|
|
510
|
-
const m = await importOpt.import();
|
|
511
|
-
return resolveModule(m);
|
|
512
|
-
})
|
|
485
|
+
resolved.map(async (option) => resolveModule(await option.import()))
|
|
513
486
|
);
|
|
514
487
|
}
|
|
515
488
|
const definePackage = (option) => {
|
|
@@ -533,12 +506,11 @@ function resolveImportOption(option) {
|
|
|
533
506
|
}
|
|
534
507
|
return option;
|
|
535
508
|
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
if (checkExists && isPackageDependency(packageName)) return;
|
|
509
|
+
const isSatisfied = (packageName) => isPackageDependency(packageName) && isPackageModuleFound(packageName);
|
|
510
|
+
async function installMissing(packageNames, options, installer) {
|
|
511
|
+
if (packageNames.length === 0) return;
|
|
540
512
|
const installerFn = installer ?? (await workspace.getProject("<package_folder>").findPackageManager()).installPackage;
|
|
541
|
-
await installerFn(
|
|
513
|
+
await installerFn(packageNames, options);
|
|
542
514
|
}
|
|
543
515
|
|
|
544
516
|
const importMap = async (importMap2, options) => {
|
|
@@ -560,20 +532,36 @@ function definePackageManager(config, options) {
|
|
|
560
532
|
const lockfiles = toArray(config.meta.lockfile);
|
|
561
533
|
return await findUp.findUp(lockfiles, { cwd });
|
|
562
534
|
});
|
|
535
|
+
const globalVersion = asyncCacheFn.asyncCacheFn(
|
|
536
|
+
async (options2) => {
|
|
537
|
+
try {
|
|
538
|
+
const { stdout } = await $$({
|
|
539
|
+
command,
|
|
540
|
+
args: [agentOptions.version],
|
|
541
|
+
cwd: defaultCwd,
|
|
542
|
+
...options2
|
|
543
|
+
});
|
|
544
|
+
return `${stdout}`.trim();
|
|
545
|
+
} catch {
|
|
546
|
+
return void 0;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
);
|
|
563
550
|
const installPackage = async (packageName, options2) => {
|
|
564
551
|
const install = agentArgs.install;
|
|
565
|
-
const { dev, preferOffline } =
|
|
566
|
-
|
|
567
|
-
{
|
|
568
|
-
preferOffline: true,
|
|
569
|
-
cwd: defaultCwd,
|
|
570
|
-
...options2
|
|
571
|
-
});
|
|
552
|
+
const { dev = false, preferOffline = true } = options2 ?? {};
|
|
553
|
+
const flags = select(install.options, { dev, preferOffline });
|
|
572
554
|
const packageNames = toArray(packageName);
|
|
555
|
+
assertInstallableNames(packageNames);
|
|
573
556
|
try {
|
|
574
557
|
await $$({
|
|
575
558
|
command,
|
|
576
|
-
args: [
|
|
559
|
+
args: [
|
|
560
|
+
install.command,
|
|
561
|
+
flags.dev,
|
|
562
|
+
flags.preferOffline,
|
|
563
|
+
...packageNames
|
|
564
|
+
],
|
|
577
565
|
cwd: defaultCwd,
|
|
578
566
|
...options2
|
|
579
567
|
});
|
|
@@ -617,19 +605,12 @@ function definePackageManager(config, options) {
|
|
|
617
605
|
if (!lockfilePath) return void 0;
|
|
618
606
|
return promises.readFile(lockfilePath, "utf8");
|
|
619
607
|
}),
|
|
620
|
-
globalVersion
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
cwd: defaultCwd,
|
|
627
|
-
...options2
|
|
628
|
-
});
|
|
629
|
-
return `${stdout}`;
|
|
630
|
-
} catch (e) {
|
|
631
|
-
return void 0;
|
|
632
|
-
}
|
|
608
|
+
globalVersion,
|
|
609
|
+
matchesVersion: asyncCacheFn.asyncCacheFn(async (...args) => {
|
|
610
|
+
const { matchesVersion } = config.meta;
|
|
611
|
+
if (!matchesVersion) return true;
|
|
612
|
+
const version = await globalVersion.noCache(...args);
|
|
613
|
+
return version ? matchesVersion(version) : false;
|
|
633
614
|
}),
|
|
634
615
|
definePackage,
|
|
635
616
|
installPackage,
|
|
@@ -643,6 +624,16 @@ function definePackageManager(config, options) {
|
|
|
643
624
|
}
|
|
644
625
|
};
|
|
645
626
|
}
|
|
627
|
+
function assertInstallableNames(packageNames) {
|
|
628
|
+
const rejected = packageNames.filter(
|
|
629
|
+
(name) => name.length === 0 || name.startsWith("-")
|
|
630
|
+
);
|
|
631
|
+
if (rejected.length > 0) {
|
|
632
|
+
throw new Error(
|
|
633
|
+
`Not a package name: ${rejected.map((name) => JSON.stringify(name)).join(", ")}. A package name cannot be empty or begin with "-".`
|
|
634
|
+
);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
646
637
|
async function $$(options) {
|
|
647
638
|
const { command, args = [], silent = true, cwd, shellOptions } = options;
|
|
648
639
|
return execa.execa(command, args.filter(notFalsy), {
|
|
@@ -665,7 +656,9 @@ const bun = definePackageManagerConfig({
|
|
|
665
656
|
command: "bun",
|
|
666
657
|
runner: "bunx",
|
|
667
658
|
meta: {
|
|
668
|
-
lockfile
|
|
659
|
+
// Bun wrote a binary lockfile originally and a text one from 1.2 onwards,
|
|
660
|
+
// so a project using either must still be detected.
|
|
661
|
+
lockfile: ["bun.lock", "bun.lockb"]
|
|
669
662
|
},
|
|
670
663
|
args: {
|
|
671
664
|
install: {
|
|
@@ -676,7 +669,7 @@ const bun = definePackageManagerConfig({
|
|
|
676
669
|
}
|
|
677
670
|
},
|
|
678
671
|
uninstall: {
|
|
679
|
-
command: "
|
|
672
|
+
command: "remove"
|
|
680
673
|
}
|
|
681
674
|
},
|
|
682
675
|
options: {
|
|
@@ -740,7 +733,9 @@ const yarn = definePackageManagerConfig({
|
|
|
740
733
|
command: "yarn",
|
|
741
734
|
runner: "yarn dlx",
|
|
742
735
|
meta: {
|
|
743
|
-
lockfile: "yarn.lock"
|
|
736
|
+
lockfile: "yarn.lock",
|
|
737
|
+
// Berry shares this command and lockfile, so the version decides.
|
|
738
|
+
matchesVersion: (version) => version.startsWith("1.")
|
|
744
739
|
},
|
|
745
740
|
args: {
|
|
746
741
|
install: {
|
|
@@ -759,6 +754,33 @@ const yarn = definePackageManagerConfig({
|
|
|
759
754
|
}
|
|
760
755
|
});
|
|
761
756
|
|
|
757
|
+
const yarnBerry = definePackageManagerConfig({
|
|
758
|
+
id: "yarn-berry",
|
|
759
|
+
name: "Yarn Berry",
|
|
760
|
+
command: "yarn",
|
|
761
|
+
runner: "yarn dlx",
|
|
762
|
+
meta: {
|
|
763
|
+
lockfile: "yarn.lock",
|
|
764
|
+
// Classic shares this command and lockfile; everything past 1.x is Berry.
|
|
765
|
+
matchesVersion: (version) => !version.startsWith("1.")
|
|
766
|
+
},
|
|
767
|
+
args: {
|
|
768
|
+
install: {
|
|
769
|
+
command: "add",
|
|
770
|
+
options: {
|
|
771
|
+
dev: "-D",
|
|
772
|
+
preferOffline: "--cached"
|
|
773
|
+
}
|
|
774
|
+
},
|
|
775
|
+
uninstall: {
|
|
776
|
+
command: "remove"
|
|
777
|
+
}
|
|
778
|
+
},
|
|
779
|
+
options: {
|
|
780
|
+
version: "--version"
|
|
781
|
+
}
|
|
782
|
+
});
|
|
783
|
+
|
|
762
784
|
async function findPackageManager(packageManagers, options) {
|
|
763
785
|
const packageManager = await findPackageManagerSafely(
|
|
764
786
|
packageManagers,
|
|
@@ -788,7 +810,9 @@ async function detectPackageManagers(packageManagers, options) {
|
|
|
788
810
|
async function detectLockfilePackageManagers(packageManagers, options) {
|
|
789
811
|
return filterPackageManagers(
|
|
790
812
|
packageManagers,
|
|
791
|
-
|
|
813
|
+
// Yarn Classic and Berry share a lockfile name, so a lockfile match alone
|
|
814
|
+
// would report both. The version check settles which one it is.
|
|
815
|
+
async (packageManager) => await packageManager.hasLockfile(options) && await packageManager.matchesVersion(options),
|
|
792
816
|
options
|
|
793
817
|
);
|
|
794
818
|
}
|
|
@@ -798,7 +822,7 @@ async function detectGlobalPackageManagers(packageManagers, options) {
|
|
|
798
822
|
// Without the `await`, `Boolean` receives a pending promise and is always
|
|
799
823
|
// `true`, so every package manager passes the filter regardless of whether
|
|
800
824
|
// it is actually installed.
|
|
801
|
-
async (packageManager) => Boolean(await packageManager.globalVersion(options)),
|
|
825
|
+
async (packageManager) => Boolean(await packageManager.globalVersion(options)) && await packageManager.matchesVersion(options),
|
|
802
826
|
options
|
|
803
827
|
);
|
|
804
828
|
}
|
|
@@ -831,7 +855,7 @@ function selectAllowedPackageManagers(packageManagers, options) {
|
|
|
831
855
|
);
|
|
832
856
|
}
|
|
833
857
|
|
|
834
|
-
const packageManagerConfigs = [pnpm, yarn, bun, npm];
|
|
858
|
+
const packageManagerConfigs = [pnpm, yarn, yarnBerry, bun, npm];
|
|
835
859
|
function definePackageManagerClient(options) {
|
|
836
860
|
const configs = packageManagerConfigs.map(
|
|
837
861
|
(config) => definePackageManager(config, options)
|
|
@@ -861,8 +885,11 @@ function definePackageManagerClient(options) {
|
|
|
861
885
|
};
|
|
862
886
|
}
|
|
863
887
|
|
|
864
|
-
function isPackageDependency(packageName) {
|
|
865
|
-
|
|
888
|
+
function isPackageDependency(packageName, options) {
|
|
889
|
+
const { packageJson } = getPackageInfo(options);
|
|
890
|
+
return toArray(packageName).every(
|
|
891
|
+
(name) => isDependencyInPackageJson(name, packageJson)
|
|
892
|
+
);
|
|
866
893
|
}
|
|
867
894
|
|
|
868
895
|
function definePathAliases(aliasDefinitions) {
|
|
@@ -880,42 +907,49 @@ function definePathAliases(aliasDefinitions) {
|
|
|
880
907
|
};
|
|
881
908
|
}
|
|
882
909
|
function getAliasedFilePath(aliasMap, options) {
|
|
883
|
-
const { to, startingFrom, cwd, checkExistence, glob } = typeof options === "string" || Array.isArray(options) ? { to: options } : options;
|
|
884
|
-
const resolveOptions = { cwd, checkExistence, glob, aliasMap };
|
|
910
|
+
const { to, startingFrom, cwd, from, checkExistence, glob } = typeof options === "string" || Array.isArray(options) ? { to: options } : options;
|
|
911
|
+
const resolveOptions = { cwd, from, checkExistence, glob, aliasMap };
|
|
885
912
|
try {
|
|
886
913
|
return startingFrom ? resolveRelativePathTo(to, startingFrom, resolveOptions) : resolvePathTo(to, resolveOptions);
|
|
887
914
|
} catch (error) {
|
|
888
|
-
if (
|
|
915
|
+
if (error instanceof PathNotFoundError) return void 0;
|
|
889
916
|
throw error;
|
|
890
917
|
}
|
|
891
918
|
}
|
|
919
|
+
class PathNotFoundError extends Error {
|
|
920
|
+
}
|
|
892
921
|
function resolveRelativePathTo(to, from, options) {
|
|
893
922
|
const pathFrom = resolvePathTo(from, options);
|
|
894
923
|
const pathTo = resolvePathTo(to, options);
|
|
895
|
-
return path__default
|
|
924
|
+
return path__default.relative(pathFrom, pathTo);
|
|
896
925
|
}
|
|
897
|
-
function resolvePathTo(pathTo, { cwd, checkExistence, glob, aliasMap }) {
|
|
898
|
-
const normalized = normalizePathTo(pathTo, { cwd, aliasMap });
|
|
926
|
+
function resolvePathTo(pathTo, { cwd, from, checkExistence, glob, aliasMap }) {
|
|
927
|
+
const normalized = normalizePathTo(pathTo, { cwd, from, aliasMap });
|
|
899
928
|
if (glob) {
|
|
900
929
|
const globPaths = globby.globbySync(normalized, { cwd });
|
|
901
930
|
if (!globPaths[0])
|
|
902
|
-
throw new
|
|
931
|
+
throw new PathNotFoundError(`No paths found for glob: ${normalized}`);
|
|
903
932
|
return globPaths[0];
|
|
904
933
|
}
|
|
905
934
|
if (!glob && checkExistence && !node_fs.existsSync(normalized))
|
|
906
|
-
throw new
|
|
935
|
+
throw new PathNotFoundError(`Path does not exist: ${normalized}`);
|
|
907
936
|
return normalized;
|
|
908
937
|
}
|
|
909
938
|
function normalizePathTo(pathTo, options) {
|
|
910
|
-
const { cwd, aliasMap } = options ?? {};
|
|
911
|
-
const
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
939
|
+
const { cwd, from, aliasMap } = options ?? {};
|
|
940
|
+
const baseDir = Array.isArray(pathTo) ? pathTo[0] : findAliasToken(pathTo, aliasMap);
|
|
941
|
+
if (baseDir === void 0) return pathTo;
|
|
942
|
+
const baseDirPath = assertResolved(
|
|
943
|
+
baseDir,
|
|
944
|
+
executeMapFn(aliasMap, baseDir, [{ cwd, from }])
|
|
945
|
+
);
|
|
946
|
+
return Array.isArray(pathTo) ? path__default.join(baseDirPath, ...pathTo.slice(1).filter(isNotNull)) : utils.resolveAlias(pathTo, { [baseDir]: baseDirPath });
|
|
947
|
+
}
|
|
948
|
+
function assertResolved(alias, resolved) {
|
|
949
|
+
if (typeof resolved !== "string" || resolved.length === 0) {
|
|
950
|
+
throw new Error(`Path alias resolved to no location: ${alias}`);
|
|
917
951
|
}
|
|
918
|
-
return
|
|
952
|
+
return resolved;
|
|
919
953
|
}
|
|
920
954
|
function findAliasToken(pathTo, aliasMap) {
|
|
921
955
|
return Object.keys(aliasMap ?? {}).filter((alias) => pathTo === alias || pathTo.startsWith(`${alias}/`)).sort((a, b) => b.length - a.length)[0];
|
|
@@ -933,10 +967,17 @@ function getAliasMap(aliasDefs) {
|
|
|
933
967
|
return [
|
|
934
968
|
[alias, resolve],
|
|
935
969
|
...subpaths.map(({ to }) => {
|
|
936
|
-
const subpathAlias = path__default
|
|
970
|
+
const subpathAlias = path__default.join(alias, to);
|
|
937
971
|
return [
|
|
938
972
|
subpathAlias,
|
|
939
|
-
(opts) =>
|
|
973
|
+
(opts) => (
|
|
974
|
+
// The same assertion the bare alias gets. Without it an
|
|
975
|
+
// unresolvable parent produced `join(undefined, "/node_modules")`
|
|
976
|
+
// — a path at the filesystem root — instead of failing.
|
|
977
|
+
utils.resolveAlias(subpathAlias, {
|
|
978
|
+
[alias]: assertResolved(alias, resolve(opts))
|
|
979
|
+
})
|
|
980
|
+
)
|
|
940
981
|
];
|
|
941
982
|
})
|
|
942
983
|
];
|
|
@@ -1011,13 +1052,13 @@ const predefinedPathAliases = {
|
|
|
1011
1052
|
subpaths: []
|
|
1012
1053
|
},
|
|
1013
1054
|
"<current_file>": {
|
|
1014
|
-
//
|
|
1015
|
-
|
|
1055
|
+
// `from` is the caller naming itself, which is exact. Without it the stack
|
|
1056
|
+
// is read, which is a best effort and Node-only.
|
|
1057
|
+
resolve: (opts) => _filename({ from: opts?.from, boundaryFunctionName: "getFilePath" }),
|
|
1016
1058
|
subpaths: []
|
|
1017
1059
|
},
|
|
1018
1060
|
"<current_folder>": {
|
|
1019
|
-
|
|
1020
|
-
resolve: () => _dirname({ rootFunctionName: "getFilePath" }) ?? "",
|
|
1061
|
+
resolve: (opts) => _dirname({ from: opts?.from, boundaryFunctionName: "getFilePath" }),
|
|
1021
1062
|
subpaths: []
|
|
1022
1063
|
}
|
|
1023
1064
|
};
|
|
@@ -1040,59 +1081,65 @@ const jsonSourceResolvers = {
|
|
|
1040
1081
|
text: (text) => {
|
|
1041
1082
|
return {
|
|
1042
1083
|
text: () => text,
|
|
1043
|
-
|
|
1084
|
+
// `jsonc-parser`'s parse, not `JSON.parse`: the whole point of this
|
|
1085
|
+
// module is editing files like tsconfig.json, which carry comments.
|
|
1086
|
+
data: () => jsoncParser.parse(text)
|
|
1044
1087
|
};
|
|
1045
1088
|
},
|
|
1046
1089
|
filepath: (filepath) => {
|
|
1047
1090
|
const text = node_fs.readFileSync(filepath, "utf-8");
|
|
1048
1091
|
return {
|
|
1049
1092
|
text: () => text,
|
|
1050
|
-
|
|
1093
|
+
// `jsonc-parser`'s parse, not `JSON.parse`: the whole point of this
|
|
1094
|
+
// module is editing files like tsconfig.json, which carry comments.
|
|
1095
|
+
data: () => jsoncParser.parse(text)
|
|
1051
1096
|
};
|
|
1052
1097
|
}
|
|
1053
1098
|
};
|
|
1054
1099
|
function resolveJsonSource(source, as) {
|
|
1055
1100
|
const [sourceType, sourceData] = Object.entries(source).find(([_, selected]) => selected !== void 0) ?? [];
|
|
1056
|
-
if (!sourceType || !(sourceType in jsonSourceResolvers) ||
|
|
1101
|
+
if (!sourceType || !(sourceType in jsonSourceResolvers) || sourceData === void 0) {
|
|
1057
1102
|
throw new Error("Invalid source data");
|
|
1058
1103
|
}
|
|
1059
1104
|
const sourceTypeResolvers = jsonSourceResolvers[sourceType](
|
|
1060
1105
|
sourceData
|
|
1061
1106
|
);
|
|
1062
|
-
const resolved =
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1107
|
+
const resolved = fromEntries(
|
|
1108
|
+
entriesOf(sourceTypeResolvers).flatMap(([key, v]) => {
|
|
1109
|
+
if (as && key !== as) return [];
|
|
1110
|
+
try {
|
|
1111
|
+
return [[key, v()]];
|
|
1112
|
+
} catch (error) {
|
|
1113
|
+
throw new Error(`Failed to resolve ${key} from ${sourceType}`, {
|
|
1114
|
+
cause: error
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
})
|
|
1118
|
+
);
|
|
1070
1119
|
if (as) {
|
|
1071
1120
|
return resolved[as];
|
|
1072
1121
|
}
|
|
1073
1122
|
return resolved;
|
|
1074
1123
|
}
|
|
1075
1124
|
|
|
1125
|
+
const toPathSegment = (segment) => /^\d+$/.test(segment) ? Number(segment) : segment;
|
|
1076
1126
|
function resolveEditPath(path, options) {
|
|
1077
|
-
const { pathSeparator = "." } = {};
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
return pathSeparator === false ? path2 : path2.split(pathSeparator);
|
|
1082
|
-
}
|
|
1083
|
-
return path2;
|
|
1084
|
-
}).flat();
|
|
1127
|
+
const { pathSeparator = "." } = options || {};
|
|
1128
|
+
if (Array.isArray(path)) return path;
|
|
1129
|
+
if (typeof path === "number" || pathSeparator === false) return [path];
|
|
1130
|
+
return path.split(pathSeparator).map(toPathSegment);
|
|
1085
1131
|
}
|
|
1086
|
-
function parseJSONCEdits(edits) {
|
|
1132
|
+
function parseJSONCEdits(edits, defaultEditOptions) {
|
|
1133
|
+
const resolve = (path, options) => resolveEditPath(path, { ...defaultEditOptions, ...options });
|
|
1087
1134
|
if (Array.isArray(edits)) {
|
|
1088
1135
|
return edits.map(({ path, ...edit }) => ({
|
|
1089
|
-
path:
|
|
1136
|
+
path: resolve(path, edit.options),
|
|
1090
1137
|
...edit
|
|
1091
1138
|
}));
|
|
1092
1139
|
}
|
|
1093
1140
|
return Object.entries(edits).map(
|
|
1094
1141
|
([path, value]) => ({
|
|
1095
|
-
path:
|
|
1142
|
+
path: resolve(path, value.options),
|
|
1096
1143
|
...value
|
|
1097
1144
|
})
|
|
1098
1145
|
);
|
|
@@ -1104,14 +1151,17 @@ function modifyJSON({
|
|
|
1104
1151
|
}) {
|
|
1105
1152
|
return checkResult(() => {
|
|
1106
1153
|
const text = resolveJsonSource(json, "text");
|
|
1107
|
-
const jsoncEdits = parseJSONCEdits(edits);
|
|
1108
|
-
const
|
|
1109
|
-
(edit) => jsoncParser.
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1154
|
+
const jsoncEdits = parseJSONCEdits(edits, defaultEditOptions);
|
|
1155
|
+
const updated = jsoncEdits.reduce(
|
|
1156
|
+
(current, edit) => jsoncParser.applyEdits(
|
|
1157
|
+
current,
|
|
1158
|
+
jsoncParser.modify(current, edit.path, edit.value, {
|
|
1159
|
+
...defaultEditOptions,
|
|
1160
|
+
...edit.options
|
|
1161
|
+
})
|
|
1162
|
+
),
|
|
1163
|
+
text
|
|
1113
1164
|
);
|
|
1114
|
-
const updated = jsoncParser.applyEdits(text, editResult);
|
|
1115
1165
|
return resolveJsonSource({ text: updated });
|
|
1116
1166
|
});
|
|
1117
1167
|
}
|
|
@@ -1146,117 +1196,91 @@ const storage = unstorage.createStorage({ driver: defineMemoryDriver__default()
|
|
|
1146
1196
|
const tempFileSystem = defineFileSystemStorage({
|
|
1147
1197
|
base: path.join(os__default.tmpdir(), ".package-manager")
|
|
1148
1198
|
});
|
|
1199
|
+
const encodeEntry = (value) => typeof value === "string" ? value : JSON.stringify(value);
|
|
1149
1200
|
function defineFileSystemEntries(definition) {
|
|
1150
|
-
const fileSystemEntries = Object.entries(definition).map(([
|
|
1151
|
-
if (
|
|
1152
|
-
const {
|
|
1153
|
-
|
|
1154
|
-
options,
|
|
1155
|
-
serialize = (input) => JSON.stringify(input),
|
|
1156
|
-
deserialize = (input) => {
|
|
1157
|
-
try {
|
|
1158
|
-
return JSON.parse(input);
|
|
1159
|
-
} catch {
|
|
1160
|
-
return input;
|
|
1161
|
-
}
|
|
1162
|
-
}
|
|
1163
|
-
} = v();
|
|
1164
|
-
return {
|
|
1165
|
-
key: k,
|
|
1166
|
-
value: serialize(file),
|
|
1167
|
-
options,
|
|
1168
|
-
serialize,
|
|
1169
|
-
deserialize
|
|
1170
|
-
};
|
|
1201
|
+
const fileSystemEntries = Object.entries(definition).map(([key, value]) => {
|
|
1202
|
+
if (typeof value === "function") {
|
|
1203
|
+
const { file, options } = value();
|
|
1204
|
+
return { key, value: encodeEntry(file), options };
|
|
1171
1205
|
}
|
|
1172
|
-
if (isStorageValue(
|
|
1173
|
-
|
|
1174
|
-
key:
|
|
1175
|
-
|
|
1176
|
-
};
|
|
1206
|
+
if (!isStorageValue(value)) {
|
|
1207
|
+
throw new Error(
|
|
1208
|
+
`Cannot store a ${typeof value} at "${key}": file system entries must be a storage value or a function returning one.`
|
|
1209
|
+
);
|
|
1177
1210
|
}
|
|
1178
|
-
return
|
|
1179
|
-
})
|
|
1211
|
+
return { key, value: encodeEntry(value) };
|
|
1212
|
+
});
|
|
1180
1213
|
const resolved = {
|
|
1181
1214
|
definition,
|
|
1182
1215
|
fileSystemEntries
|
|
1183
1216
|
};
|
|
1184
1217
|
return resolved;
|
|
1185
1218
|
}
|
|
1219
|
+
const keyToFilePath = (root, key) => path.join(root, ...key.split(/[:/\\]+/).filter(Boolean));
|
|
1186
1220
|
function defineFileSystemStorage(options) {
|
|
1187
1221
|
const { base: root, initial, ...storageOptions } = options;
|
|
1188
|
-
let
|
|
1222
|
+
let entriesData = defineFileSystemEntries(initial ?? {});
|
|
1189
1223
|
const storage2 = unstorage.createStorage({
|
|
1190
1224
|
driver: defineFsLiteDriver__default({ base: root, ...storageOptions })
|
|
1191
1225
|
});
|
|
1226
|
+
const getFilePath = (key) => keyToFilePath(root, key);
|
|
1227
|
+
const getFile = async (key) => ({
|
|
1228
|
+
key,
|
|
1229
|
+
filepath: getFilePath(key),
|
|
1230
|
+
data: await storage2.getItem(key),
|
|
1231
|
+
// `getItemRaw` resolves to null for a missing file rather than throwing.
|
|
1232
|
+
read: async () => (await storage2.getItemRaw(key))?.toString()
|
|
1233
|
+
});
|
|
1234
|
+
const removeAllFiles = async () => storage2.clear();
|
|
1192
1235
|
const fileStorage = {
|
|
1193
1236
|
createFile: async (key, data) => {
|
|
1194
1237
|
await storage2.setItem(key, data);
|
|
1195
1238
|
return {
|
|
1196
1239
|
key,
|
|
1197
|
-
filepath:
|
|
1240
|
+
filepath: getFilePath(key),
|
|
1198
1241
|
get: async () => storage2.getItem(key),
|
|
1199
1242
|
update: async (data2) => storage2.setItem(key, data2)
|
|
1200
1243
|
};
|
|
1201
1244
|
},
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
filepath: path.join(root, key),
|
|
1210
|
-
data: storageData,
|
|
1211
|
-
read: async () => (await storage2.getItemRaw(key))?.toString()
|
|
1212
|
-
};
|
|
1213
|
-
},
|
|
1214
|
-
async readFile(key) {
|
|
1215
|
-
const { read } = await this.getFile(key);
|
|
1216
|
-
const content = await read();
|
|
1217
|
-
return content;
|
|
1218
|
-
},
|
|
1219
|
-
snapshotFs: async (base = root) => {
|
|
1220
|
-
return unstorage.snapshot(storage2, base);
|
|
1221
|
-
},
|
|
1222
|
-
restoreFs: async (snapshot2) => {
|
|
1223
|
-
return unstorage.restoreSnapshot(storage2, snapshot2);
|
|
1224
|
-
},
|
|
1245
|
+
getFilePath,
|
|
1246
|
+
getFile,
|
|
1247
|
+
readFile: async (key) => (await getFile(key)).read(),
|
|
1248
|
+
// `base` is a key prefix. Defaulting it to the filesystem root would match
|
|
1249
|
+
// no key at all and silently report an empty filesystem.
|
|
1250
|
+
snapshotFs: async (base = "") => unstorage.snapshot(storage2, base),
|
|
1251
|
+
restoreFs: async (snapshot2, base) => unstorage.restoreSnapshot(storage2, snapshot2, base),
|
|
1225
1252
|
initializeFs: async (override) => {
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
await storage2.
|
|
1230
|
-
return storage2.setItems(initialFileEntriesData.fileSystemEntries);
|
|
1253
|
+
const previousKeys = entriesData.fileSystemEntries.map(({ key }) => key);
|
|
1254
|
+
if (override) entriesData = defineFileSystemEntries(override);
|
|
1255
|
+
await Promise.all(previousKeys.map((key) => storage2.removeItem(key)));
|
|
1256
|
+
await storage2.setItems(entriesData.fileSystemEntries);
|
|
1231
1257
|
},
|
|
1232
1258
|
defineFileSystemEntries,
|
|
1233
|
-
removeAllFiles
|
|
1259
|
+
removeAllFiles,
|
|
1234
1260
|
async deleteFileSystem() {
|
|
1235
|
-
await
|
|
1236
|
-
await storage2.
|
|
1261
|
+
await removeAllFiles();
|
|
1262
|
+
await storage2.dispose();
|
|
1237
1263
|
await promises.rm(root, { recursive: true, force: true });
|
|
1238
1264
|
},
|
|
1239
1265
|
storage: storage2,
|
|
1240
1266
|
meta: {
|
|
1241
|
-
|
|
1267
|
+
// A getter, so that `initializeFs(override)` is reflected here rather
|
|
1268
|
+
// than this reporting whatever the definition was at construction.
|
|
1269
|
+
get fileEntriesData() {
|
|
1270
|
+
return entriesData;
|
|
1271
|
+
}
|
|
1242
1272
|
}
|
|
1243
1273
|
};
|
|
1244
|
-
if (initial) {
|
|
1245
|
-
return {
|
|
1246
|
-
initialize: async () => {
|
|
1247
|
-
await fileStorage.initializeFs(initial);
|
|
1248
|
-
return fileStorage;
|
|
1249
|
-
}
|
|
1250
|
-
};
|
|
1251
|
-
}
|
|
1252
1274
|
return fileStorage;
|
|
1253
1275
|
}
|
|
1254
1276
|
|
|
1255
1277
|
exports._dirname = _dirname;
|
|
1256
1278
|
exports._filename = _filename;
|
|
1279
|
+
exports.createFile = createFile;
|
|
1257
1280
|
exports.defineFileSystemEntries = defineFileSystemEntries;
|
|
1258
1281
|
exports.defineFileSystemStorage = defineFileSystemStorage;
|
|
1259
1282
|
exports.definePackage = definePackage;
|
|
1283
|
+
exports.definePackageManager = definePackageManager;
|
|
1260
1284
|
exports.definePackageManagerClient = definePackageManagerClient;
|
|
1261
1285
|
exports.definePathAliases = definePathAliases;
|
|
1262
1286
|
exports.detectGlobalPackageManagers = detectGlobalPackageManagers;
|
|
@@ -1279,6 +1303,7 @@ exports.importer = importer;
|
|
|
1279
1303
|
exports.isDependencyInPackageJson = isDependencyInPackageJson;
|
|
1280
1304
|
exports.isPackageDependency = isPackageDependency;
|
|
1281
1305
|
exports.isPackageModuleFound = isPackageModuleFound;
|
|
1306
|
+
exports.isWritable = isWritable;
|
|
1282
1307
|
exports.mapPackageManagers = mapPackageManagers;
|
|
1283
1308
|
exports.modifyJSON = modifyJSON;
|
|
1284
1309
|
exports.modifyJSONFile = modifyJSONFile;
|