@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.
@@ -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
- * Check if cached data is fresh based on TTL.
160
+ * Get cached update information for a package (legacy format).
161
+ * @deprecated Use getManifestEntry() for new code.
262
162
  */
263
- isFresh(record, ttlMs) {
264
- if (!record) {
265
- return false;
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
- const age = Date.now() - record.timestampFetch;
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:
@@ -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;
@@ -31,7 +31,12 @@ var package_exports = {};
31
31
  __export(package_exports, {
32
32
  dlxPackage: () => dlxPackage,
33
33
  downloadPackage: () => downloadPackage,
34
- executePackage: () => executePackage
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 parsePackageSpec(spec) {
65
- try {
66
- const parsed = (0, import_npm_package_arg.default)(spec);
67
- const version = parsed.type === "tag" ? parsed.fetchSpec : parsed.type === "version" || parsed.type === "range" ? parsed.fetchSpec : void 0;
68
- return {
69
- name: parsed.name || spec,
70
- version
71
- };
72
- } catch {
73
- const atIndex = spec.lastIndexOf("@");
74
- if (atIndex === -1 || spec.startsWith("@")) {
75
- return { name: spec, version: void 0 };
76
- }
77
- return {
78
- name: spec.slice(0, atIndex),
79
- version: spec.slice(atIndex + 1)
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 resolveBinaryPath(basePath) {
176
- if (!import_platform.WIN32) {
177
- return basePath;
178
- }
179
- const fs = /* @__PURE__ */ getFs();
180
- const extensions = [".cmd", ".bat", ".ps1", ".exe", ""];
181
- for (const ext of extensions) {
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
- async function downloadPackage(options) {
292
- const {
293
- binaryName,
294
- force: userForce,
295
- package: packageSpec,
296
- yes
297
- } = {
298
- __proto__: null,
299
- ...options
300
- };
301
- const { name: packageName, version: packageVersion } = parsePackageSpec(packageSpec);
302
- const isVersionRange = packageVersion !== void 0 && rangeOperatorsRegExp.test(packageVersion);
303
- const force = userForce !== void 0 ? userForce : yes === true ? true : isVersionRange;
304
- const fullPackageSpec = packageVersion ? `${packageName}@${packageVersion}` : packageName;
305
- const { installed, packageDir } = await ensurePackageInstalled(
306
- packageName,
307
- fullPackageSpec,
308
- force
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 executePackage(binaryPath, args, spawnOptions, spawnExtra) {
319
- const needsShell = import_platform.WIN32 && /\.(?:bat|cmd|ps1)$/i.test(binaryPath);
320
- const finalOptions = needsShell ? {
321
- ...spawnOptions,
322
- shell: true
323
- } : spawnOptions;
324
- return (0, import_spawn.spawn)(binaryPath, args, finalOptions, spawnExtra);
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
- executePackage
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, import_helpers.envAsBoolean)((0, import_rewire.getEnvValue)("CI"));
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 = {
@@ -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.
@@ -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 setEnv(key, value) {
61
- sharedOverrides?.set(key, value);
65
+ function hasOverride(key) {
66
+ const isolatedOverrides = isolatedOverridesStorage.getStore();
67
+ return !!(isolatedOverrides?.has(key) || sharedOverrides?.has(key));
62
68
  }
63
- function clearEnv(key) {
64
- sharedOverrides?.delete(key);
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 hasOverride(key) {
70
- const isolatedOverrides = isolatedOverridesStorage.getStore();
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,