@socketsecurity/lib 5.6.0 → 5.7.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/CHANGELOG.md +64 -1
- package/dist/cache-with-ttl.js +5 -1
- package/dist/dlx/binary.d.ts +20 -0
- package/dist/dlx/binary.js +115 -99
- package/dist/dlx/detect.d.ts +8 -8
- package/dist/dlx/detect.js +18 -18
- package/dist/dlx/manifest.d.ts +32 -31
- package/dist/dlx/manifest.js +114 -112
- package/dist/dlx/package.d.ts +55 -0
- package/dist/dlx/package.js +89 -79
- package/dist/env/ci.js +1 -2
- package/dist/env/rewire.d.ts +33 -22
- package/dist/env/rewire.js +20 -7
- package/dist/env/socket-cli.d.ts +24 -24
- package/dist/env/socket-cli.js +12 -12
- package/dist/env/temp-dir.d.ts +6 -6
- package/dist/env/temp-dir.js +4 -4
- package/dist/env/windows.d.ts +6 -6
- package/dist/env/windows.js +4 -4
- package/dist/github.js +10 -1
- package/dist/packages/specs.js +1 -1
- package/dist/releases/github.d.ts +18 -7
- package/dist/releases/github.js +94 -92
- package/package.json +1 -1
package/dist/dlx/manifest.js
CHANGED
|
@@ -47,12 +47,12 @@ function getPath() {
|
|
|
47
47
|
}
|
|
48
48
|
const logger = (0, import_logger.getDefaultLogger)();
|
|
49
49
|
const MANIFEST_FILE_NAME = ".dlx-manifest.json";
|
|
50
|
-
function isPackageEntry(entry) {
|
|
51
|
-
return entry.type === "package";
|
|
52
|
-
}
|
|
53
50
|
function isBinaryEntry(entry) {
|
|
54
51
|
return entry.type === "binary";
|
|
55
52
|
}
|
|
53
|
+
function isPackageEntry(entry) {
|
|
54
|
+
return entry.type === "package";
|
|
55
|
+
}
|
|
56
56
|
class DlxManifest {
|
|
57
57
|
manifestPath;
|
|
58
58
|
lockPath;
|
|
@@ -62,6 +62,7 @@ class DlxManifest {
|
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
64
64
|
* Read the entire manifest file.
|
|
65
|
+
* @private
|
|
65
66
|
*/
|
|
66
67
|
readManifest() {
|
|
67
68
|
try {
|
|
@@ -81,61 +82,9 @@ class DlxManifest {
|
|
|
81
82
|
return /* @__PURE__ */ Object.create(null);
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
|
-
/**
|
|
85
|
-
* Get a manifest entry by spec (e.g., "@socketsecurity/cli@^2.0.11").
|
|
86
|
-
*/
|
|
87
|
-
getManifestEntry(spec) {
|
|
88
|
-
const data = this.readManifest();
|
|
89
|
-
const entry = data[spec];
|
|
90
|
-
if (entry && "type" in entry) {
|
|
91
|
-
return entry;
|
|
92
|
-
}
|
|
93
|
-
return void 0;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Get cached update information for a package (legacy format).
|
|
97
|
-
* @deprecated Use getManifestEntry() for new code.
|
|
98
|
-
*/
|
|
99
|
-
get(name) {
|
|
100
|
-
const data = this.readManifest();
|
|
101
|
-
const entry = data[name];
|
|
102
|
-
if (entry && !("type" in entry)) {
|
|
103
|
-
return entry;
|
|
104
|
-
}
|
|
105
|
-
return void 0;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Set a package manifest entry.
|
|
109
|
-
*/
|
|
110
|
-
async setPackageEntry(spec, cacheKey, details) {
|
|
111
|
-
await import_process_lock.processLock.withLock(this.lockPath, async () => {
|
|
112
|
-
const data = this.readManifest();
|
|
113
|
-
data[spec] = {
|
|
114
|
-
type: "package",
|
|
115
|
-
cache_key: cacheKey,
|
|
116
|
-
timestamp: Date.now(),
|
|
117
|
-
details
|
|
118
|
-
};
|
|
119
|
-
await this.writeManifest(data);
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Set a binary manifest entry.
|
|
124
|
-
*/
|
|
125
|
-
async setBinaryEntry(spec, cacheKey, details) {
|
|
126
|
-
await import_process_lock.processLock.withLock(this.lockPath, async () => {
|
|
127
|
-
const data = this.readManifest();
|
|
128
|
-
data[spec] = {
|
|
129
|
-
type: "binary",
|
|
130
|
-
cache_key: cacheKey,
|
|
131
|
-
timestamp: Date.now(),
|
|
132
|
-
details
|
|
133
|
-
};
|
|
134
|
-
await this.writeManifest(data);
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
85
|
/**
|
|
138
86
|
* Write the manifest file atomically.
|
|
87
|
+
* @private
|
|
139
88
|
*/
|
|
140
89
|
async writeManifest(data) {
|
|
141
90
|
const manifestDir = (/* @__PURE__ */ getPath()).dirname(this.manifestPath);
|
|
@@ -167,56 +116,6 @@ class DlxManifest {
|
|
|
167
116
|
throw error;
|
|
168
117
|
}
|
|
169
118
|
}
|
|
170
|
-
/**
|
|
171
|
-
* Store update information for a package (legacy format).
|
|
172
|
-
* @deprecated Use setPackageEntry() for new code.
|
|
173
|
-
*/
|
|
174
|
-
async set(name, record) {
|
|
175
|
-
await import_process_lock.processLock.withLock(this.lockPath, async () => {
|
|
176
|
-
let data = /* @__PURE__ */ Object.create(null);
|
|
177
|
-
try {
|
|
178
|
-
if ((/* @__PURE__ */ getFs()).existsSync(this.manifestPath)) {
|
|
179
|
-
const content2 = (/* @__PURE__ */ getFs()).readFileSync(this.manifestPath, "utf8");
|
|
180
|
-
if (content2.trim()) {
|
|
181
|
-
data = JSON.parse(content2);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
} catch (error) {
|
|
185
|
-
logger.warn(
|
|
186
|
-
`Failed to read existing manifest: ${error instanceof Error ? error.message : String(error)}`
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
data[name] = record;
|
|
190
|
-
const manifestDir = (/* @__PURE__ */ getPath()).dirname(this.manifestPath);
|
|
191
|
-
try {
|
|
192
|
-
(0, import_fs.safeMkdirSync)(manifestDir, { recursive: true });
|
|
193
|
-
} catch (error) {
|
|
194
|
-
logger.warn(
|
|
195
|
-
`Failed to create manifest directory: ${error instanceof Error ? error.message : String(error)}`
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
const content = JSON.stringify(data, null, 2);
|
|
199
|
-
const tempPath = `${this.manifestPath}.tmp`;
|
|
200
|
-
try {
|
|
201
|
-
(/* @__PURE__ */ getFs()).writeFileSync(tempPath, content, "utf8");
|
|
202
|
-
(/* @__PURE__ */ getFs()).writeFileSync(this.manifestPath, content, "utf8");
|
|
203
|
-
try {
|
|
204
|
-
if ((/* @__PURE__ */ getFs()).existsSync(tempPath)) {
|
|
205
|
-
(/* @__PURE__ */ getFs()).unlinkSync(tempPath);
|
|
206
|
-
}
|
|
207
|
-
} catch {
|
|
208
|
-
}
|
|
209
|
-
} catch (error) {
|
|
210
|
-
try {
|
|
211
|
-
if ((/* @__PURE__ */ getFs()).existsSync(tempPath)) {
|
|
212
|
-
(/* @__PURE__ */ getFs()).unlinkSync(tempPath);
|
|
213
|
-
}
|
|
214
|
-
} catch {
|
|
215
|
-
}
|
|
216
|
-
throw error;
|
|
217
|
-
}
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
119
|
/**
|
|
221
120
|
* Clear cached data for a specific entry.
|
|
222
121
|
*/
|
|
@@ -258,14 +157,16 @@ class DlxManifest {
|
|
|
258
157
|
});
|
|
259
158
|
}
|
|
260
159
|
/**
|
|
261
|
-
*
|
|
160
|
+
* Get cached update information for a package (legacy format).
|
|
161
|
+
* @deprecated Use getManifestEntry() for new code.
|
|
262
162
|
*/
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
163
|
+
get(name) {
|
|
164
|
+
const data = this.readManifest();
|
|
165
|
+
const entry = data[name];
|
|
166
|
+
if (entry && !("type" in entry)) {
|
|
167
|
+
return entry;
|
|
266
168
|
}
|
|
267
|
-
|
|
268
|
-
return age < ttlMs;
|
|
169
|
+
return void 0;
|
|
269
170
|
}
|
|
270
171
|
/**
|
|
271
172
|
* Get all cached package names.
|
|
@@ -289,6 +190,107 @@ class DlxManifest {
|
|
|
289
190
|
return [];
|
|
290
191
|
}
|
|
291
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Get a manifest entry by spec (e.g., "@socketsecurity/cli@^2.0.11").
|
|
195
|
+
*/
|
|
196
|
+
getManifestEntry(spec) {
|
|
197
|
+
const data = this.readManifest();
|
|
198
|
+
const entry = data[spec];
|
|
199
|
+
if (entry && "type" in entry) {
|
|
200
|
+
return entry;
|
|
201
|
+
}
|
|
202
|
+
return void 0;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Check if cached data is fresh based on TTL.
|
|
206
|
+
*/
|
|
207
|
+
isFresh(record, ttlMs) {
|
|
208
|
+
if (!record) {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
const age = Date.now() - record.timestampFetch;
|
|
212
|
+
return age < ttlMs;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Store update information for a package (legacy format).
|
|
216
|
+
* @deprecated Use setPackageEntry() for new code.
|
|
217
|
+
*/
|
|
218
|
+
async set(name, record) {
|
|
219
|
+
await import_process_lock.processLock.withLock(this.lockPath, async () => {
|
|
220
|
+
let data = /* @__PURE__ */ Object.create(null);
|
|
221
|
+
try {
|
|
222
|
+
if ((/* @__PURE__ */ getFs()).existsSync(this.manifestPath)) {
|
|
223
|
+
const content2 = (/* @__PURE__ */ getFs()).readFileSync(this.manifestPath, "utf8");
|
|
224
|
+
if (content2.trim()) {
|
|
225
|
+
data = JSON.parse(content2);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
} catch (error) {
|
|
229
|
+
logger.warn(
|
|
230
|
+
`Failed to read existing manifest: ${error instanceof Error ? error.message : String(error)}`
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
data[name] = record;
|
|
234
|
+
const manifestDir = (/* @__PURE__ */ getPath()).dirname(this.manifestPath);
|
|
235
|
+
try {
|
|
236
|
+
(0, import_fs.safeMkdirSync)(manifestDir, { recursive: true });
|
|
237
|
+
} catch (error) {
|
|
238
|
+
logger.warn(
|
|
239
|
+
`Failed to create manifest directory: ${error instanceof Error ? error.message : String(error)}`
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
const content = JSON.stringify(data, null, 2);
|
|
243
|
+
const tempPath = `${this.manifestPath}.tmp`;
|
|
244
|
+
try {
|
|
245
|
+
(/* @__PURE__ */ getFs()).writeFileSync(tempPath, content, "utf8");
|
|
246
|
+
(/* @__PURE__ */ getFs()).writeFileSync(this.manifestPath, content, "utf8");
|
|
247
|
+
try {
|
|
248
|
+
if ((/* @__PURE__ */ getFs()).existsSync(tempPath)) {
|
|
249
|
+
(/* @__PURE__ */ getFs()).unlinkSync(tempPath);
|
|
250
|
+
}
|
|
251
|
+
} catch {
|
|
252
|
+
}
|
|
253
|
+
} catch (error) {
|
|
254
|
+
try {
|
|
255
|
+
if ((/* @__PURE__ */ getFs()).existsSync(tempPath)) {
|
|
256
|
+
(/* @__PURE__ */ getFs()).unlinkSync(tempPath);
|
|
257
|
+
}
|
|
258
|
+
} catch {
|
|
259
|
+
}
|
|
260
|
+
throw error;
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Set a binary manifest entry.
|
|
266
|
+
*/
|
|
267
|
+
async setBinaryEntry(spec, cacheKey, details) {
|
|
268
|
+
await import_process_lock.processLock.withLock(this.lockPath, async () => {
|
|
269
|
+
const data = this.readManifest();
|
|
270
|
+
data[spec] = {
|
|
271
|
+
type: "binary",
|
|
272
|
+
cache_key: cacheKey,
|
|
273
|
+
timestamp: Date.now(),
|
|
274
|
+
details
|
|
275
|
+
};
|
|
276
|
+
await this.writeManifest(data);
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Set a package manifest entry.
|
|
281
|
+
*/
|
|
282
|
+
async setPackageEntry(spec, cacheKey, details) {
|
|
283
|
+
await import_process_lock.processLock.withLock(this.lockPath, async () => {
|
|
284
|
+
const data = this.readManifest();
|
|
285
|
+
data[spec] = {
|
|
286
|
+
type: "package",
|
|
287
|
+
cache_key: cacheKey,
|
|
288
|
+
timestamp: Date.now(),
|
|
289
|
+
details
|
|
290
|
+
};
|
|
291
|
+
await this.writeManifest(data);
|
|
292
|
+
});
|
|
293
|
+
}
|
|
292
294
|
}
|
|
293
295
|
const dlxManifest = new DlxManifest();
|
|
294
296
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/dlx/package.d.ts
CHANGED
|
@@ -99,6 +99,15 @@ export declare function dlxPackage(args: readonly string[] | string[], options?:
|
|
|
99
99
|
* ```
|
|
100
100
|
*/
|
|
101
101
|
export declare function downloadPackage(options: DlxPackageOptions): Promise<DownloadPackageResult>;
|
|
102
|
+
/**
|
|
103
|
+
* Install package to ~/.socket/_dlx/<hash>/ if not already installed.
|
|
104
|
+
* Uses pacote for installation (no npm CLI required).
|
|
105
|
+
* Protected by process lock to prevent concurrent installation corruption.
|
|
106
|
+
*/
|
|
107
|
+
export declare function ensurePackageInstalled(packageName: string, packageSpec: string, force: boolean): Promise<{
|
|
108
|
+
installed: boolean;
|
|
109
|
+
packageDir: string;
|
|
110
|
+
}>;
|
|
102
111
|
/**
|
|
103
112
|
* Execute a package's binary with cross-platform shell handling.
|
|
104
113
|
* The package must already be installed (use downloadPackage first).
|
|
@@ -118,3 +127,49 @@ export declare function downloadPackage(options: DlxPackageOptions): Promise<Dow
|
|
|
118
127
|
* ```
|
|
119
128
|
*/
|
|
120
129
|
export declare function executePackage(binaryPath: string, args: readonly string[] | string[], spawnOptions?: SpawnOptions | undefined, spawnExtra?: SpawnExtra | undefined): ReturnType<typeof spawn>;
|
|
130
|
+
/**
|
|
131
|
+
* Find the binary path for an installed package.
|
|
132
|
+
* Uses npm's bin resolution strategy with user-friendly fallbacks.
|
|
133
|
+
* Resolves platform-specific wrappers (.cmd, .ps1, etc.) on Windows.
|
|
134
|
+
*
|
|
135
|
+
* Resolution strategy (cherry-picked from libnpmexec):
|
|
136
|
+
* 1. Use npm's getBinFromManifest (handles aliases and standard cases)
|
|
137
|
+
* 2. Fall back to user-provided binaryName if npm's strategy fails
|
|
138
|
+
* 3. Try last segment of package name as final fallback
|
|
139
|
+
* 4. Use first binary as last resort
|
|
140
|
+
*/
|
|
141
|
+
export declare function findBinaryPath(packageDir: string, packageName: string, binaryName?: string): string;
|
|
142
|
+
/**
|
|
143
|
+
* Make all binaries in an installed package executable.
|
|
144
|
+
* Reads the package.json bin field and makes all binaries executable (chmod 0o755).
|
|
145
|
+
* Handles both single binary (string) and multiple binaries (object) formats.
|
|
146
|
+
*
|
|
147
|
+
* Aligns with npm's approach:
|
|
148
|
+
* - Uses 0o755 permission (matches npm's cmd-shim)
|
|
149
|
+
* - Reads bin field from package.json (matches npm's bin-links and libnpmexec)
|
|
150
|
+
* - Handles both string and object bin formats
|
|
151
|
+
*
|
|
152
|
+
* References:
|
|
153
|
+
* - npm cmd-shim: https://github.com/npm/cmd-shim/blob/main/lib/index.js
|
|
154
|
+
* - npm getBinFromManifest: https://github.com/npm/libnpmexec/blob/main/lib/get-bin-from-manifest.js
|
|
155
|
+
*/
|
|
156
|
+
export declare function makePackageBinsExecutable(packageDir: string, packageName: string): void;
|
|
157
|
+
/**
|
|
158
|
+
* Parse package spec into name and version using npm-package-arg.
|
|
159
|
+
* Examples:
|
|
160
|
+
* - 'lodash@4.17.21' → { name: 'lodash', version: '4.17.21' }
|
|
161
|
+
* - '@scope/pkg@1.0.0' → { name: '@scope/pkg', version: '1.0.0' }
|
|
162
|
+
* - 'lodash' → { name: 'lodash', version: undefined }
|
|
163
|
+
*/
|
|
164
|
+
export declare function parsePackageSpec(spec: string): {
|
|
165
|
+
name: string;
|
|
166
|
+
version: string | undefined;
|
|
167
|
+
};
|
|
168
|
+
/**
|
|
169
|
+
* Resolve binary path with cross-platform wrapper support.
|
|
170
|
+
* On Windows, checks for .cmd, .bat, .ps1, .exe wrappers in order.
|
|
171
|
+
* On Unix, uses path directly.
|
|
172
|
+
*
|
|
173
|
+
* Aligns with npm/npx binary resolution strategy.
|
|
174
|
+
*/
|
|
175
|
+
export declare function resolveBinaryPath(basePath: string): string;
|
package/dist/dlx/package.js
CHANGED
|
@@ -31,7 +31,12 @@ var package_exports = {};
|
|
|
31
31
|
__export(package_exports, {
|
|
32
32
|
dlxPackage: () => dlxPackage,
|
|
33
33
|
downloadPackage: () => downloadPackage,
|
|
34
|
-
|
|
34
|
+
ensurePackageInstalled: () => ensurePackageInstalled,
|
|
35
|
+
executePackage: () => executePackage,
|
|
36
|
+
findBinaryPath: () => findBinaryPath,
|
|
37
|
+
makePackageBinsExecutable: () => makePackageBinsExecutable,
|
|
38
|
+
parsePackageSpec: () => parsePackageSpec,
|
|
39
|
+
resolveBinaryPath: () => resolveBinaryPath
|
|
35
40
|
});
|
|
36
41
|
module.exports = __toCommonJS(package_exports);
|
|
37
42
|
var import_platform = require("../constants/platform");
|
|
@@ -61,24 +66,45 @@ function getPath() {
|
|
|
61
66
|
return _path;
|
|
62
67
|
}
|
|
63
68
|
const rangeOperatorsRegExp = /[~^><=xX* ]|\|\|/;
|
|
64
|
-
function
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
69
|
+
async function dlxPackage(args, options, spawnExtra) {
|
|
70
|
+
const downloadResult = await downloadPackage(options);
|
|
71
|
+
const spawnPromise = executePackage(
|
|
72
|
+
downloadResult.binaryPath,
|
|
73
|
+
args,
|
|
74
|
+
options?.spawnOptions,
|
|
75
|
+
spawnExtra
|
|
76
|
+
);
|
|
77
|
+
return {
|
|
78
|
+
...downloadResult,
|
|
79
|
+
spawnPromise
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async function downloadPackage(options) {
|
|
83
|
+
const {
|
|
84
|
+
binaryName,
|
|
85
|
+
force: userForce,
|
|
86
|
+
package: packageSpec,
|
|
87
|
+
yes
|
|
88
|
+
} = {
|
|
89
|
+
__proto__: null,
|
|
90
|
+
...options
|
|
91
|
+
};
|
|
92
|
+
const { name: packageName, version: packageVersion } = parsePackageSpec(packageSpec);
|
|
93
|
+
const isVersionRange = packageVersion !== void 0 && rangeOperatorsRegExp.test(packageVersion);
|
|
94
|
+
const force = userForce !== void 0 ? userForce : yes === true ? true : isVersionRange;
|
|
95
|
+
const fullPackageSpec = packageVersion ? `${packageName}@${packageVersion}` : packageName;
|
|
96
|
+
const { installed, packageDir } = await ensurePackageInstalled(
|
|
97
|
+
packageName,
|
|
98
|
+
fullPackageSpec,
|
|
99
|
+
force
|
|
100
|
+
);
|
|
101
|
+
const binaryPath = findBinaryPath(packageDir, packageName, binaryName);
|
|
102
|
+
makePackageBinsExecutable(packageDir, packageName);
|
|
103
|
+
return {
|
|
104
|
+
binaryPath,
|
|
105
|
+
installed,
|
|
106
|
+
packageDir
|
|
107
|
+
};
|
|
82
108
|
}
|
|
83
109
|
async function ensurePackageInstalled(packageName, packageSpec, force) {
|
|
84
110
|
const fs = /* @__PURE__ */ getFs();
|
|
@@ -172,19 +198,13 @@ Check npm registry connectivity or package name.`,
|
|
|
172
198
|
}
|
|
173
199
|
);
|
|
174
200
|
}
|
|
175
|
-
function
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
const testPath = basePath + ext;
|
|
183
|
-
if (fs.existsSync(testPath)) {
|
|
184
|
-
return testPath;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
return basePath;
|
|
201
|
+
function executePackage(binaryPath, args, spawnOptions, spawnExtra) {
|
|
202
|
+
const needsShell = import_platform.WIN32 && /\.(?:bat|cmd|ps1)$/i.test(binaryPath);
|
|
203
|
+
const finalOptions = needsShell ? {
|
|
204
|
+
...spawnOptions,
|
|
205
|
+
shell: true
|
|
206
|
+
} : spawnOptions;
|
|
207
|
+
return (0, import_spawn.spawn)(binaryPath, args, finalOptions, spawnExtra);
|
|
188
208
|
}
|
|
189
209
|
function findBinaryPath(packageDir, packageName, binaryName) {
|
|
190
210
|
const path = /* @__PURE__ */ getPath();
|
|
@@ -240,19 +260,6 @@ function findBinaryPath(packageDir, packageName, binaryName) {
|
|
|
240
260
|
const rawPath = (0, import_normalize.normalizePath)(path.join(installedDir, binPath));
|
|
241
261
|
return resolveBinaryPath(rawPath);
|
|
242
262
|
}
|
|
243
|
-
async function dlxPackage(args, options, spawnExtra) {
|
|
244
|
-
const downloadResult = await downloadPackage(options);
|
|
245
|
-
const spawnPromise = executePackage(
|
|
246
|
-
downloadResult.binaryPath,
|
|
247
|
-
args,
|
|
248
|
-
options?.spawnOptions,
|
|
249
|
-
spawnExtra
|
|
250
|
-
);
|
|
251
|
-
return {
|
|
252
|
-
...downloadResult,
|
|
253
|
-
spawnPromise
|
|
254
|
-
};
|
|
255
|
-
}
|
|
256
263
|
function makePackageBinsExecutable(packageDir, packageName) {
|
|
257
264
|
if (import_platform.WIN32) {
|
|
258
265
|
return;
|
|
@@ -288,44 +295,47 @@ function makePackageBinsExecutable(packageDir, packageName) {
|
|
|
288
295
|
} catch {
|
|
289
296
|
}
|
|
290
297
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
);
|
|
310
|
-
const binaryPath = findBinaryPath(packageDir, packageName, binaryName);
|
|
311
|
-
makePackageBinsExecutable(packageDir, packageName);
|
|
312
|
-
return {
|
|
313
|
-
binaryPath,
|
|
314
|
-
installed,
|
|
315
|
-
packageDir
|
|
316
|
-
};
|
|
298
|
+
function parsePackageSpec(spec) {
|
|
299
|
+
try {
|
|
300
|
+
const parsed = (0, import_npm_package_arg.default)(spec);
|
|
301
|
+
const version = parsed.type === "tag" ? parsed.fetchSpec : parsed.type === "version" || parsed.type === "range" ? parsed.fetchSpec : void 0;
|
|
302
|
+
return {
|
|
303
|
+
name: parsed.name || spec,
|
|
304
|
+
version
|
|
305
|
+
};
|
|
306
|
+
} catch {
|
|
307
|
+
const atIndex = spec.lastIndexOf("@");
|
|
308
|
+
if (atIndex === -1 || atIndex === 0) {
|
|
309
|
+
return { name: spec, version: void 0 };
|
|
310
|
+
}
|
|
311
|
+
return {
|
|
312
|
+
name: spec.slice(0, atIndex),
|
|
313
|
+
version: spec.slice(atIndex + 1)
|
|
314
|
+
};
|
|
315
|
+
}
|
|
317
316
|
}
|
|
318
|
-
function
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
317
|
+
function resolveBinaryPath(basePath) {
|
|
318
|
+
if (!import_platform.WIN32) {
|
|
319
|
+
return basePath;
|
|
320
|
+
}
|
|
321
|
+
const fs = /* @__PURE__ */ getFs();
|
|
322
|
+
const extensions = [".cmd", ".bat", ".ps1", ".exe", ""];
|
|
323
|
+
for (const ext of extensions) {
|
|
324
|
+
const testPath = basePath + ext;
|
|
325
|
+
if (fs.existsSync(testPath)) {
|
|
326
|
+
return testPath;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return basePath;
|
|
325
330
|
}
|
|
326
331
|
// Annotate the CommonJS export names for ESM import in node:
|
|
327
332
|
0 && (module.exports = {
|
|
328
333
|
dlxPackage,
|
|
329
334
|
downloadPackage,
|
|
330
|
-
|
|
335
|
+
ensurePackageInstalled,
|
|
336
|
+
executePackage,
|
|
337
|
+
findBinaryPath,
|
|
338
|
+
makePackageBinsExecutable,
|
|
339
|
+
parsePackageSpec,
|
|
340
|
+
resolveBinaryPath
|
|
331
341
|
});
|
package/dist/env/ci.js
CHANGED
|
@@ -22,11 +22,10 @@ __export(ci_exports, {
|
|
|
22
22
|
getCI: () => getCI
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(ci_exports);
|
|
25
|
-
var import_helpers = require("./helpers");
|
|
26
25
|
var import_rewire = require("./rewire");
|
|
27
26
|
// @__NO_SIDE_EFFECTS__
|
|
28
27
|
function getCI() {
|
|
29
|
-
return (0,
|
|
28
|
+
return (0, import_rewire.isInEnv)("CI");
|
|
30
29
|
}
|
|
31
30
|
// Annotate the CommonJS export names for ESM import in node:
|
|
32
31
|
0 && (module.exports = {
|
package/dist/env/rewire.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clear a specific environment variable override.
|
|
3
|
+
*/
|
|
4
|
+
export declare function clearEnv(key: string): void;
|
|
1
5
|
/**
|
|
2
6
|
* Get an environment variable value, checking overrides first.
|
|
3
7
|
*
|
|
@@ -9,6 +13,35 @@
|
|
|
9
13
|
* @internal Used by env getters to support test rewiring
|
|
10
14
|
*/
|
|
11
15
|
export declare function getEnvValue(key: string): string | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Check if an environment variable has been overridden.
|
|
18
|
+
*/
|
|
19
|
+
export declare function hasOverride(key: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Check if an environment variable exists (has a key), checking overrides first.
|
|
22
|
+
*
|
|
23
|
+
* Resolution order:
|
|
24
|
+
* 1. Isolated overrides (temporary - set via withEnv/withEnvSync)
|
|
25
|
+
* 2. Shared overrides (persistent - set via setEnv in beforeEach)
|
|
26
|
+
* 3. process.env (including vi.stubEnv modifications)
|
|
27
|
+
*
|
|
28
|
+
* @internal Used by env getters to check for key presence (not value truthiness)
|
|
29
|
+
*/
|
|
30
|
+
export declare function isInEnv(key: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Clear all environment variable overrides.
|
|
33
|
+
* Useful in afterEach hooks to ensure clean test state.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* import { resetEnv } from './rewire'
|
|
38
|
+
*
|
|
39
|
+
* afterEach(() => {
|
|
40
|
+
* resetEnv()
|
|
41
|
+
* })
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare function resetEnv(): void;
|
|
12
45
|
/**
|
|
13
46
|
* Set an environment variable override for testing.
|
|
14
47
|
* This does not modify process.env, only affects env getters.
|
|
@@ -35,28 +68,6 @@ export declare function getEnvValue(key: string): string | undefined;
|
|
|
35
68
|
* ```
|
|
36
69
|
*/
|
|
37
70
|
export declare function setEnv(key: string, value: string | undefined): void;
|
|
38
|
-
/**
|
|
39
|
-
* Clear a specific environment variable override.
|
|
40
|
-
*/
|
|
41
|
-
export declare function clearEnv(key: string): void;
|
|
42
|
-
/**
|
|
43
|
-
* Clear all environment variable overrides.
|
|
44
|
-
* Useful in afterEach hooks to ensure clean test state.
|
|
45
|
-
*
|
|
46
|
-
* @example
|
|
47
|
-
* ```typescript
|
|
48
|
-
* import { resetEnv } from './rewire'
|
|
49
|
-
*
|
|
50
|
-
* afterEach(() => {
|
|
51
|
-
* resetEnv()
|
|
52
|
-
* })
|
|
53
|
-
* ```
|
|
54
|
-
*/
|
|
55
|
-
export declare function resetEnv(): void;
|
|
56
|
-
/**
|
|
57
|
-
* Check if an environment variable has been overridden.
|
|
58
|
-
*/
|
|
59
|
-
export declare function hasOverride(key: string): boolean;
|
|
60
71
|
/**
|
|
61
72
|
* Run code with environment overrides in an isolated AsyncLocalStorage context.
|
|
62
73
|
* Creates true context isolation - overrides don't leak to concurrent code.
|
package/dist/env/rewire.js
CHANGED
|
@@ -22,12 +22,14 @@ __export(rewire_exports, {
|
|
|
22
22
|
clearEnv: () => clearEnv,
|
|
23
23
|
getEnvValue: () => getEnvValue,
|
|
24
24
|
hasOverride: () => hasOverride,
|
|
25
|
+
isInEnv: () => isInEnv,
|
|
25
26
|
resetEnv: () => resetEnv,
|
|
26
27
|
setEnv: () => setEnv,
|
|
27
28
|
withEnv: () => withEnv,
|
|
28
29
|
withEnvSync: () => withEnvSync
|
|
29
30
|
});
|
|
30
31
|
module.exports = __toCommonJS(rewire_exports);
|
|
32
|
+
var import_objects = require("../objects");
|
|
31
33
|
var import_helpers = require("./helpers");
|
|
32
34
|
let _async_hooks;
|
|
33
35
|
// @__NO_SIDE_EFFECTS__
|
|
@@ -47,6 +49,9 @@ if (isVitestEnv && !globalThis[sharedOverridesSymbol]) {
|
|
|
47
49
|
globalThis[sharedOverridesSymbol] = /* @__PURE__ */ new Map();
|
|
48
50
|
}
|
|
49
51
|
const sharedOverrides = globalThis[sharedOverridesSymbol];
|
|
52
|
+
function clearEnv(key) {
|
|
53
|
+
sharedOverrides?.delete(key);
|
|
54
|
+
}
|
|
50
55
|
function getEnvValue(key) {
|
|
51
56
|
const isolatedOverrides = isolatedOverridesStorage.getStore();
|
|
52
57
|
if (isolatedOverrides?.has(key)) {
|
|
@@ -57,18 +62,25 @@ function getEnvValue(key) {
|
|
|
57
62
|
}
|
|
58
63
|
return process.env[key];
|
|
59
64
|
}
|
|
60
|
-
function
|
|
61
|
-
|
|
65
|
+
function hasOverride(key) {
|
|
66
|
+
const isolatedOverrides = isolatedOverridesStorage.getStore();
|
|
67
|
+
return !!(isolatedOverrides?.has(key) || sharedOverrides?.has(key));
|
|
62
68
|
}
|
|
63
|
-
function
|
|
64
|
-
|
|
69
|
+
function isInEnv(key) {
|
|
70
|
+
const isolatedOverrides = isolatedOverridesStorage.getStore();
|
|
71
|
+
if (isolatedOverrides?.has(key)) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
if (sharedOverrides?.has(key)) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
return (0, import_objects.hasOwn)(process.env, key);
|
|
65
78
|
}
|
|
66
79
|
function resetEnv() {
|
|
67
80
|
sharedOverrides?.clear();
|
|
68
81
|
}
|
|
69
|
-
function
|
|
70
|
-
|
|
71
|
-
return !!(isolatedOverrides?.has(key) || sharedOverrides?.has(key));
|
|
82
|
+
function setEnv(key, value) {
|
|
83
|
+
sharedOverrides?.set(key, value);
|
|
72
84
|
}
|
|
73
85
|
async function withEnv(overrides, fn) {
|
|
74
86
|
const map = new Map(Object.entries(overrides));
|
|
@@ -83,6 +95,7 @@ function withEnvSync(overrides, fn) {
|
|
|
83
95
|
clearEnv,
|
|
84
96
|
getEnvValue,
|
|
85
97
|
hasOverride,
|
|
98
|
+
isInEnv,
|
|
86
99
|
resetEnv,
|
|
87
100
|
setEnv,
|
|
88
101
|
withEnv,
|