@socketsecurity/lib 6.0.1 → 6.0.3

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/ai/profiles.d.mts +48 -25
  3. package/dist/ai/profiles.js +40 -33
  4. package/dist/ai/spawn.d.mts +2 -2
  5. package/dist/ai/types.d.mts +3 -3
  6. package/dist/ai/worktree.d.mts +2 -2
  7. package/dist/constants/socket.js +1 -1
  8. package/dist/debug/_internal.d.ts +1 -1
  9. package/dist/dlx/detect.js +4 -12
  10. package/dist/dlx/firewall.js +2 -2
  11. package/dist/fs/access.d.ts +32 -0
  12. package/dist/fs/access.js +63 -0
  13. package/dist/fs/find-up.js +9 -31
  14. package/dist/fs/resolve-module.d.ts +57 -0
  15. package/dist/fs/resolve-module.js +63 -0
  16. package/dist/fs/validate.js +3 -6
  17. package/dist/http-request/download-types.d.ts +2 -2
  18. package/dist/http-request/http-request.d.ts +12 -0
  19. package/dist/http-request/http-request.js +36 -0
  20. package/dist/http-request/node.d.ts +29 -0
  21. package/dist/http-request/{convenience.js → node.js} +9 -3
  22. package/dist/logger/_internal.d.ts +1 -1
  23. package/dist/logger/browser.d.ts +14 -12
  24. package/dist/logger/browser.js +3 -10
  25. package/dist/logger/console.js +3 -3
  26. package/dist/logger/default.d.ts +8 -402
  27. package/dist/logger/default.js +5 -822
  28. package/dist/logger/logger.d.ts +10 -0
  29. package/dist/logger/logger.js +30 -0
  30. package/dist/logger/node.d.ts +400 -0
  31. package/dist/logger/node.js +856 -0
  32. package/dist/logger/symbols-builder.d.ts +1 -1
  33. package/dist/logger/types.d.ts +1 -1
  34. package/dist/packages/provenance.d.ts +42 -0
  35. package/dist/packages/provenance.js +71 -0
  36. package/dist/paths/walk.d.ts +40 -0
  37. package/dist/paths/walk.js +63 -0
  38. package/dist/primordials/map-set.d.ts +35 -0
  39. package/dist/primordials/map-set.js +43 -0
  40. package/dist/promises/_internal.d.ts +8 -2
  41. package/dist/promises/_internal.js +1 -5
  42. package/dist/releases/github-asset-url.js +2 -11
  43. package/dist/releases/github-listing.js +2 -11
  44. package/dist/releases/github-retry-config.d.ts +31 -0
  45. package/dist/releases/github-retry-config.js +52 -0
  46. package/dist/smol/path.d.ts +51 -0
  47. package/dist/smol/path.js +42 -0
  48. package/package.json +113 -40
  49. package/dist/http-request/convenience.d.ts +0 -104
package/CHANGELOG.md CHANGED
@@ -5,6 +5,44 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [6.0.3](https://github.com/SocketDev/socket-lib/releases/tag/v6.0.3) - 2026-05-26
9
+
10
+ ### Added
11
+
12
+ - **`paths/walk` — `walkUp(from, { cwd, stopAt })`.** Lazy generator yielding a path then each ancestor up to (and including) the filesystem root or a `stopAt` boundary. `fs/find-up` now builds on it.
13
+ - **`fs/access` — `canAccess` / `canRead` / `canWrite` / `canExecute`.** Sync boolean permission checks over `fs.accessSync` (F_OK / R_OK / W_OK / X_OK). For "I'm about to write" prefer attempting the write over a pre-check (TOCTOU); use these when the answer drives a branch.
14
+ - **`fs/resolve-module` — `requireResolveFrom(fromDir, specifier)` / `requireResolveFromCwd(specifier)`.** `require.resolve` anchored at an arbitrary directory (e.g. "the `typescript` THIS project would load"). `nothrow: true` returns `undefined` instead of throwing.
15
+ - **`releases/github-retry-config` — `GITHUB_RETRY_CONFIG`, `resolveBaseDelayMs()`, `DEFAULT_BASE_DELAY_MS`.** Shared backoff config for the GitHub release helpers. The base retry delay is overridable via the `SOCKET_GITHUB_RETRY_BASE_DELAY_MS` env var (default 5000ms; set `0` for near-instant retries) — useful in CI / tests to skip the exponential-backoff wait.
16
+ - **`smol/path` — `getSmolPath()`.** Lazy accessor for socket-btm's `node:smol-path` native binding; `undefined` on stock Node. `walkUp`, `canAccess`, and `findUp` now prefer the native fast path (`dirname` / `access` / batched find-up) when running on a smol binary and fall back to the JS implementation otherwise — transparent to callers.
17
+
18
+ ### Changed (breaking)
19
+
20
+ - **`ai/profiles` exports a single `AI_PROFILE` capability ladder** instead of the four standalone `*_PROFILE` constants. The tiers are `AI_PROFILE.read` ⊂ `.edit` ⊂ `.create` ⊂ `.full`, ordered least-to-most capable. Migration: `READ_ONLY_PROFILE` → `AI_PROFILE.read`; `EDIT_ONLY_PROFILE` → `AI_PROFILE.create` (the old `EDIT_ONLY` allowed `Write`/`MultiEdit`); `FULL_FIX_PROFILE` → `AI_PROFILE.full`. New `AI_PROFILE.edit` is the narrowest fix tier — `Edit` on existing files only, no `Write`/`MultiEdit` — for lint autofix and in-place codemods.
21
+
22
+ ### Changed
23
+
24
+ - **Every `AI_PROFILE` tier now denies `Agent`.** Sub-agent spawning is blocked across all profiles, since a sub-agent can escape the parent's tool restrictions.
25
+
26
+ ## [6.0.2](https://github.com/SocketDev/socket-lib/releases/tag/v6.0.2) - 2026-05-26
27
+
28
+ ### Added
29
+
30
+ - **`./logger/logger` and `./http-request/http-request`** as the canonical class / function-surface entries, paired with the existing `./logger/{node,browser}` and `./http-request/{node,browser}` implementations. Bundlers that honor the `'browser'` export condition pick the right impl automatically: `import { Logger } from '@socketsecurity/lib/logger/logger'` and `import { httpJson } from '@socketsecurity/lib/http-request/http-request'` work on both platforms.
31
+ - **`./logger/default`** holds the shared-singleton accessor: `getDefaultLogger()` returns one process-wide `Logger` instance (lazily constructed). Same on both platforms.
32
+ - **`./http-request` top-level export.** New canonical entry mirroring `./http-request/http-request`.
33
+ - **Package trust-status helpers in `./packages/provenance`.** `getTrustStatus(meta)` extracts `{ provenance, trustedPublisher, stagedPublish }` from an npm registry version document; `getTrustLevel(status)` maps to a 0..3 ladder and `getTrustLevelName(status)` to its name; `TRUST_LEVELS` is the single source-of-truth array (index = level); `compareTrust(a, b)` is an ascending-level comparator; `didTrustDecrease(prev, next)` flags a release that regressed its supply-chain posture.
34
+ - **`primordials/map-set` Stage 4 surface.** `getOrInsert` / `getOrInsertComputed` on `Map` / `WeakMap` plus the Set-composition methods (`union`, `intersection`, `difference`, `symmetricDifference`, `isSubsetOf`, `isSupersetOf`, `isDisjointFrom`) are ambient-declared, so consumers get types for methods Node 22+ ships but TypeScript's lib doesn't yet surface.
35
+
36
+ ### Changed (breaking)
37
+
38
+ - **`getDefaultLogger` moved from `./logger` to `./logger/default`.** The bare `./logger` entry now exposes the `Logger` class only (matching `./logger/logger`). Migration: `import { getDefaultLogger } from '@socketsecurity/lib/logger'` → `from '@socketsecurity/lib/logger/default'`.
39
+ - **`./logger/default` semantics shifted.** Previously `./logger/default` resolved to the Node logger source; that file is now `./logger/node`. The `./logger/default` path is the singleton accessor module.
40
+ - **`./http-request/convenience` removed.** `httpJson` and `httpText` live on `./http-request/node` and `./http-request/browser` alongside `httpRequest` and `HttpResponseError`. Most consumers should import from `./http-request` (auto-routing) rather than the explicit leaf.
41
+
42
+ ### Fixed
43
+
44
+ - **`./logger` auto-resolves to `./logger/browser` on browser platforms.** 6.0.1 announced this but shipped without the `'browser'` condition on the `./logger` entry, so bundlers fell through to the Node default and pulled in `node:*` builtins.
45
+
8
46
  ## [6.0.1](https://github.com/SocketDev/socket-lib/releases/tag/v6.0.1) - 2026-05-25
9
47
 
10
48
  Five additive features plus public-surface polish on top of 6.0.0. The path renames drop doubled-name leaves (`spawn/spawn`, `ttl-cache/cache`, `globs/glob`, `links/link`, `promise-queue/queue`) and regroup three top-level directories whose contents were the same concept (process events) under a new `events/` umbrella. Renames are path-only; no symbol renames or behavior changes.
@@ -2,38 +2,61 @@
2
2
  * @file Pre-built lockdown profiles for spawnAiAgent. Per CLAUDE.md
3
3
  * "Programmatic Claude calls" rule: every spawn must set tools / disallow /
4
4
  * permissionMode (and the helper always sets --no-session-persistence +
5
- * --add-dir cwd). These profiles are canonical safe defaults that callers
6
- * spread + override per call. Choose by capability:
5
+ * --add-dir cwd). `AI_PROFILE` is a capability ladder each tier permits
6
+ * everything the tier above it does, plus one more capability. Spread a tier
7
+ * and override per call (`tools`/`disallow` to tighten further, `model`,
8
+ * `addDirs`). Choose the LEAST-capable tier that gets the job done:
7
9
  *
8
- * - `READ_ONLY_PROFILE` — research / scanning. Read + Grep + Glob
9
- * - WebFetch + WebSearch. No Edit, no Write, no Bash. Use for static analysis
10
- * skills (scanning-quality, scanning-security).
11
- * - `EDIT_ONLY_PROFILE` — fix-mode. Read + Edit + Grep + Glob. Bash explicitly
12
- * denied. Use for skills that mutate source files but don't run arbitrary
13
- * shell (ai-lint-fix, refactor passes).
14
- * - `FULL_FIX_PROFILE` — fix-mode WITH Bash. Read + Edit + Write + Grep + Glob
15
- * - Bash (allowlisted to git/pnpm/node by default). Use for skills that need to
16
- * commit, run tests, install deps. No `WIDE_OPEN_PROFILE` exists by design
17
- * letting an agent run arbitrary tools is the lockdown rule's exact
18
- * failure mode.
10
+ * - `AI_PROFILE.read` — research / scanning. Read + Grep + Glob + WebFetch +
11
+ * WebSearch. No Edit, no Write, no Bash. Static-analysis skills
12
+ * (scanning-quality, scanning-security).
13
+ * - `AI_PROFILE.edit` — in-place edits only. Read + Edit + Grep + Glob. NO
14
+ * Write (can't create files), NO MultiEdit, NO Bash. Lint autofix /
15
+ * codemods constrained to existing files.
16
+ * - `AI_PROFILE.create` — edit AND create files. Adds MultiEdit + Write on top
17
+ * of `.edit`. Still no Bash. Codegen, adding a test, refactors that split
18
+ * modules.
19
+ * - `AI_PROFILE.full` `.create` plus Bash, allowlisted to git / pnpm / node.
20
+ * Skills that commit, run tests, install deps. No "wide open" tier exists
21
+ * by design — letting an agent run arbitrary tools is the lockdown rule's
22
+ * exact failure mode. The ladder is read ⊂ edit ⊂ create ⊂ full: each
23
+ * tier's tool set is a superset of the one above.
19
24
  */
20
25
  import type { PermissionMode } from './types.mts';
21
- interface Profile {
26
+ export interface AiProfile {
22
27
  readonly allow: readonly string[];
23
28
  readonly disallow: readonly string[];
24
29
  readonly permissionMode: PermissionMode;
25
30
  readonly tools: readonly string[];
26
31
  }
27
32
  /**
28
- * Read-only research / scanning. No mutation.
33
+ * Capability ladder of lockdown profiles, ordered least → most capable. Key
34
+ * order documents the ladder; each tier is a strict superset of the previous
35
+ * tier's tool surface.
29
36
  */
30
- export declare const READ_ONLY_PROFILE: Profile;
31
- /**
32
- * Edit-mode without Bash. Mutates source but can't run shell.
33
- */
34
- export declare const EDIT_ONLY_PROFILE: Profile;
35
- /**
36
- * Fix-mode with Bash, allowlisted to git / pnpm / node.
37
- */
38
- export declare const FULL_FIX_PROFILE: Profile;
39
- export {};
37
+ export declare const AI_PROFILE: {
38
+ readonly read: {
39
+ readonly allow: readonly [];
40
+ readonly disallow: readonly ["Agent", "Bash", "Edit", "MultiEdit", "Write"];
41
+ readonly permissionMode: 'dontAsk';
42
+ readonly tools: readonly ["Glob", "Grep", "Read", "WebFetch", "WebSearch"];
43
+ };
44
+ readonly edit: {
45
+ readonly allow: readonly [];
46
+ readonly disallow: readonly ["Agent", "Bash", "MultiEdit", "WebFetch", "WebSearch", "Write"];
47
+ readonly permissionMode: 'acceptEdits';
48
+ readonly tools: readonly ["Edit", "Glob", "Grep", "Read"];
49
+ };
50
+ readonly create: {
51
+ readonly allow: readonly [];
52
+ readonly disallow: readonly ["Agent", "Bash", "WebFetch", "WebSearch"];
53
+ readonly permissionMode: 'acceptEdits';
54
+ readonly tools: readonly ["Edit", "Glob", "Grep", "MultiEdit", "Read", "Write"];
55
+ };
56
+ readonly full: {
57
+ readonly allow: readonly ["Bash(git status:*)", "Bash(git diff:*)", "Bash(git log:*)", "Bash(git add:*)", "Bash(git commit:*)", "Bash(node:*)", "Bash(pnpm exec:*)", "Bash(pnpm run:*)", "Bash(pnpm test:*)"];
58
+ readonly disallow: readonly ["Agent", "WebFetch", "WebSearch"];
59
+ readonly permissionMode: 'acceptEdits';
60
+ readonly tools: readonly ["Bash", "Edit", "Glob", "Grep", "MultiEdit", "Read", "Write"];
61
+ };
62
+ };
@@ -20,42 +20,49 @@ var __copyProps = (to, from, except, desc) => {
20
20
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
21
  var profiles_exports = {};
22
22
  __export(profiles_exports, {
23
- EDIT_ONLY_PROFILE: () => EDIT_ONLY_PROFILE,
24
- FULL_FIX_PROFILE: () => FULL_FIX_PROFILE,
25
- READ_ONLY_PROFILE: () => READ_ONLY_PROFILE
23
+ AI_PROFILE: () => AI_PROFILE
26
24
  });
27
25
  module.exports = __toCommonJS(profiles_exports);
28
- const READ_ONLY_PROFILE = {
29
- allow: [],
30
- disallow: ["Bash", "Edit", "MultiEdit", "Write"],
31
- permissionMode: "dontAsk",
32
- tools: ["Glob", "Grep", "Read", "WebFetch", "WebSearch"]
33
- };
34
- const EDIT_ONLY_PROFILE = {
35
- allow: [],
36
- disallow: ["Bash", "WebFetch", "WebSearch"],
37
- permissionMode: "acceptEdits",
38
- tools: ["Edit", "Glob", "Grep", "MultiEdit", "Read", "Write"]
39
- };
40
- const FULL_FIX_PROFILE = {
41
- allow: [
42
- "Bash(git status:*)",
43
- "Bash(git diff:*)",
44
- "Bash(git log:*)",
45
- "Bash(git add:*)",
46
- "Bash(git commit:*)",
47
- "Bash(node:*)",
48
- "Bash(pnpm exec:*)",
49
- "Bash(pnpm run:*)",
50
- "Bash(pnpm test:*)"
51
- ],
52
- disallow: ["WebFetch", "WebSearch"],
53
- permissionMode: "acceptEdits",
54
- tools: ["Bash", "Edit", "Glob", "Grep", "MultiEdit", "Read", "Write"]
26
+ const AI_PROFILE = {
27
+ read: {
28
+ allow: [],
29
+ disallow: ["Agent", "Bash", "Edit", "MultiEdit", "Write"],
30
+ permissionMode: "dontAsk",
31
+ tools: ["Glob", "Grep", "Read", "WebFetch", "WebSearch"]
32
+ },
33
+ // No Write / MultiEdit: edits land in existing files, never create new ones.
34
+ edit: {
35
+ allow: [],
36
+ disallow: ["Agent", "Bash", "MultiEdit", "WebFetch", "WebSearch", "Write"],
37
+ permissionMode: "acceptEdits",
38
+ tools: ["Edit", "Glob", "Grep", "Read"]
39
+ },
40
+ // MultiEdit + Write added: may create files. Bash still denied.
41
+ create: {
42
+ allow: [],
43
+ disallow: ["Agent", "Bash", "WebFetch", "WebSearch"],
44
+ permissionMode: "acceptEdits",
45
+ tools: ["Edit", "Glob", "Grep", "MultiEdit", "Read", "Write"]
46
+ },
47
+ // Bash allowlisted to git / pnpm / node only; anything else is denied.
48
+ full: {
49
+ allow: [
50
+ "Bash(git status:*)",
51
+ "Bash(git diff:*)",
52
+ "Bash(git log:*)",
53
+ "Bash(git add:*)",
54
+ "Bash(git commit:*)",
55
+ "Bash(node:*)",
56
+ "Bash(pnpm exec:*)",
57
+ "Bash(pnpm run:*)",
58
+ "Bash(pnpm test:*)"
59
+ ],
60
+ disallow: ["Agent", "WebFetch", "WebSearch"],
61
+ permissionMode: "acceptEdits",
62
+ tools: ["Bash", "Edit", "Glob", "Grep", "MultiEdit", "Read", "Write"]
63
+ }
55
64
  };
56
65
  // Annotate the CommonJS export names for ESM import in node:
57
66
  0 && (module.exports = {
58
- EDIT_ONLY_PROFILE,
59
- FULL_FIX_PROFILE,
60
- READ_ONLY_PROFILE
67
+ AI_PROFILE
61
68
  });
@@ -30,11 +30,11 @@ export declare function pickAgent(requested: AiAgentName | undefined, cwd: strin
30
30
  *
31
31
  * @example
32
32
  * ```ts
33
- * import { EDIT_ONLY_PROFILE } from '@socketsecurity/lib/ai/profiles'
33
+ * import { AI_PROFILE } from '@socketsecurity/lib/ai/profiles'
34
34
  * import { spawnAiAgent } from '@socketsecurity/lib/ai/spawn'
35
35
  *
36
36
  * const result = await spawnAiAgent({
37
- * ...EDIT_ONLY_PROFILE,
37
+ * ...AI_PROFILE.edit,
38
38
  * prompt: 'Fix the lint findings in src/foo.ts',
39
39
  * cwd: process.cwd(),
40
40
  * model: 'claude-sonnet-4-6',
@@ -42,9 +42,9 @@ export interface AgentSpawnResult {
42
42
  *
43
43
  * Required: `prompt`, `cwd`, `tools`, `disallow`, `permissionMode`.
44
44
  *
45
- * Pre-built profiles in `profiles.ts` cover the common shapes
46
- * (READ_ONLY_PROFILE, EDIT_ONLY_PROFILE) — callers spread the profile and
47
- * override per-call (model, timeout, addDirs).
45
+ * Pre-built profiles in `profiles.ts` cover the common shapes (the `AI_PROFILE`
46
+ * capability ladder) — callers spread a tier and override per-call (model,
47
+ * timeout, addDirs).
48
48
  *
49
49
  * Why the lockdown fields are required (not defaulted to a permissive shape):
50
50
  * the CLAUDE.md rule says "all four lockdown flags MUST be set on every spawn."
@@ -77,14 +77,14 @@ export declare function runOne<I, T>(item: I, index: number, worktreeBranch: str
77
77
  * ;```ts
78
78
  * import { spawnAiAgentsInWorktrees } from '@socketsecurity/lib/ai/worktree'
79
79
  * import { spawnAiAgent } from '@socketsecurity/lib/ai/spawn'
80
- * import { EDIT_ONLY_PROFILE } from '@socketsecurity/lib/ai/profiles'
80
+ * import { AI_PROFILE } from '@socketsecurity/lib/ai/profiles'
81
81
  *
82
82
  * const repos = ['socket-addon', 'socket-btm', 'socket-lib']
83
83
  * const settled = await spawnAiAgentsInWorktrees(
84
84
  * repos,
85
85
  * async ({ cwd }) => {
86
86
  * return await spawnAiAgent({
87
- * ...EDIT_ONLY_PROFILE,
87
+ * ...AI_PROFILE.create,
88
88
  * prompt: 'Run the cleanup task',
89
89
  * cwd,
90
90
  * })
@@ -77,7 +77,7 @@ const SOCKET_REGISTRY_APP_NAME = "registry";
77
77
  const SOCKET_WHEELHOUSE_APP_NAME = "wheelhouse";
78
78
  const SOCKET_APP_PREFIX = "_";
79
79
  const SOCKET_LIB_NAME = "@socketsecurity/lib";
80
- const SOCKET_LIB_VERSION = "6.0.1";
80
+ const SOCKET_LIB_VERSION = "6.0.3";
81
81
  const SOCKET_IPC_HANDSHAKE = "SOCKET_IPC_HANDSHAKE";
82
82
  const CACHE_SOCKET_API_DIR = "socket-api";
83
83
  const REGISTRY = "registry";
@@ -6,7 +6,7 @@
6
6
  * override). Co-located so the namespace / output / caller-info leaves don't
7
7
  * fragment ownership of this shared module state.
8
8
  */
9
- export declare const logger: import("../logger/default").Logger;
9
+ export declare const logger: import("../logger/node").Logger;
10
10
  export declare const debugByNamespace: Map<any, any>;
11
11
  export { getNodeUtil as getUtil } from '../node/util';
12
12
  /**
@@ -32,6 +32,7 @@ __export(detect_exports, {
32
32
  });
33
33
  module.exports = __toCommonJS(detect_exports);
34
34
  var import_paths = require("./paths");
35
+ var import_find_up = require("../fs/find-up");
35
36
  var import_socket = require("../paths/socket");
36
37
  var import_date = require("../primordials/date");
37
38
  var import_json = require("../primordials/json");
@@ -72,18 +73,9 @@ function findPackageJson(filePath) {
72
73
  packageJsonPathCache.delete(startDir);
73
74
  }
74
75
  }
75
- let currentDir = startDir;
76
- const root = path.parse(currentDir).root;
77
- while (currentDir !== root) {
78
- const packageJsonPath = path.join(currentDir, "package.json");
79
- if (fs.existsSync(packageJsonPath)) {
80
- packageJsonPathCacheSet(startDir, packageJsonPath);
81
- return packageJsonPath;
82
- }
83
- currentDir = path.dirname(currentDir);
84
- }
85
- packageJsonPathCacheSet(startDir, void 0);
86
- return void 0;
76
+ const packageJsonPath = (0, import_find_up.findUpSync)("package.json", { cwd: startDir });
77
+ packageJsonPathCacheSet(startDir, packageJsonPath);
78
+ return packageJsonPath;
87
79
  }
88
80
  function readPackageJson(packageJsonPath) {
89
81
  const fs = (0, import_fs.getNodeFs)();
@@ -24,7 +24,7 @@ __export(firewall_exports, {
24
24
  npmPurl: () => npmPurl
25
25
  });
26
26
  module.exports = __toCommonJS(firewall_exports);
27
- var import_convenience = require("../http-request/convenience");
27
+ var import_node = require("../http-request/node");
28
28
  var import_user_agent = require("../http-request/user-agent");
29
29
  var import_error = require("../primordials/error");
30
30
  var import_map_set = require("../primordials/map-set");
@@ -59,7 +59,7 @@ async function checkFirewallPurls(arb, requestedPackage) {
59
59
  await (0, import_promise.PromiseAllSettled)(
60
60
  purls.map(async ({ name, purl, version }) => {
61
61
  try {
62
- const data = await (0, import_convenience.httpJson)(
62
+ const data = await (0, import_node.httpJson)(
63
63
  `${FIREWALL_API_URL}/${encodeURIComponent(purl)}`,
64
64
  {
65
65
  headers: { "User-Agent": (0, import_user_agent.getSocketCallerUserAgent)() },
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @file Synchronous file-access predicates — boolean "can this process do X to
3
+ * this path?" checks over `fs.accessSync`. Prefer these only where the answer
4
+ * drives a user-facing decision (e.g. "is the cache dir writable, so I can
5
+ * pick a fallback?"). For "I'm about to write, can I?" do NOT pre-check —
6
+ * just attempt the write and handle the error; a check-then-act gap is a
7
+ * TOCTOU race. `canAccess` (F_OK) overlaps `existsSync`; use `existsSync` for
8
+ * plain existence, these for permission bits.
9
+ */
10
+ import type { PathLike } from 'node:fs';
11
+ /**
12
+ * Does the process have `mode` access to `path`? Wraps `fs.accessSync`,
13
+ * returning a boolean instead of throwing. Default mode is `F_OK` (existence).
14
+ *
15
+ * @param path - Path to check.
16
+ * @param mode - `fs.constants` bit (`F_OK` / `R_OK` / `W_OK` / `X_OK`).
17
+ *
18
+ * @returns True if the access check succeeds.
19
+ */
20
+ export declare function canAccess(path: PathLike, mode?: number | undefined): boolean;
21
+ /**
22
+ * Can the process execute `path`? (`X_OK`)
23
+ */
24
+ export declare function canExecute(path: PathLike): boolean;
25
+ /**
26
+ * Can the process read `path`? (`R_OK`)
27
+ */
28
+ export declare function canRead(path: PathLike): boolean;
29
+ /**
30
+ * Can the process write `path`? (`W_OK`)
31
+ */
32
+ export declare function canWrite(path: PathLike): boolean;
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ /* Socket Lib - Built with esbuild */
3
+ "use strict";
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+ var access_exports = {};
22
+ __export(access_exports, {
23
+ canAccess: () => canAccess,
24
+ canExecute: () => canExecute,
25
+ canRead: () => canRead,
26
+ canWrite: () => canWrite
27
+ });
28
+ module.exports = __toCommonJS(access_exports);
29
+ var import_fs = require("../node/fs");
30
+ var import_path = require("../smol/path");
31
+ // @__NO_SIDE_EFFECTS__
32
+ function canAccess(path, mode) {
33
+ const smolAccess = (0, import_path.getSmolPath)()?.access;
34
+ if (smolAccess) {
35
+ return smolAccess(path, mode);
36
+ }
37
+ const fs = (0, import_fs.getNodeFs)();
38
+ try {
39
+ fs.accessSync(path, mode);
40
+ return true;
41
+ } catch {
42
+ return false;
43
+ }
44
+ }
45
+ // @__NO_SIDE_EFFECTS__
46
+ function canExecute(path) {
47
+ return /* @__PURE__ */ canAccess(path, (0, import_fs.getNodeFs)().constants.X_OK);
48
+ }
49
+ // @__NO_SIDE_EFFECTS__
50
+ function canRead(path) {
51
+ return /* @__PURE__ */ canAccess(path, (0, import_fs.getNodeFs)().constants.R_OK);
52
+ }
53
+ // @__NO_SIDE_EFFECTS__
54
+ function canWrite(path) {
55
+ return /* @__PURE__ */ canAccess(path, (0, import_fs.getNodeFs)().constants.W_OK);
56
+ }
57
+ // Annotate the CommonJS export names for ESM import in node:
58
+ 0 && (module.exports = {
59
+ canAccess,
60
+ canExecute,
61
+ canRead,
62
+ canWrite
63
+ });
@@ -40,6 +40,8 @@ var import_abort = require("../process/abort");
40
40
  var import_fs = require("../node/fs");
41
41
  var import_path = require("../node/path");
42
42
  var import_normalize = require("../paths/normalize");
43
+ var import_walk = require("../paths/walk");
44
+ var import_path2 = require("../smol/path");
43
45
  const abortSignal = (0, import_abort.getAbortSignal)();
44
46
  // @__NO_SIDE_EFFECTS__
45
47
  async function findUp(name, options) {
@@ -59,10 +61,8 @@ async function findUp(name, options) {
59
61
  }
60
62
  const fs = (0, import_fs.getNodeFs)();
61
63
  const path = (0, import_path.getNodePath)();
62
- let dir = path.resolve(cwd);
63
- const { root } = path.parse(dir);
64
64
  const names = (0, import_predicates.isArray)(name) ? name : [name];
65
- while (dir) {
65
+ for (const dir of (0, import_walk.walkUp)(cwd)) {
66
66
  for (const n of names) {
67
67
  if (signal?.aborted) {
68
68
  return void 0;
@@ -79,10 +79,6 @@ async function findUp(name, options) {
79
79
  } catch {
80
80
  }
81
81
  }
82
- if (dir === root) {
83
- break;
84
- }
85
- dir = path.dirname(dir);
86
82
  }
87
83
  return void 0;
88
84
  }
@@ -104,27 +100,13 @@ function findUpSync(name, options) {
104
100
  }
105
101
  const fs = (0, import_fs.getNodeFs)();
106
102
  const path = (0, import_path.getNodePath)();
107
- let dir = path.resolve(cwd);
108
- const { root } = path.parse(dir);
109
- const stopDir = stopAt ? path.resolve(stopAt) : void 0;
110
103
  const names = (0, import_predicates.isArray)(name) ? name : [name];
111
- while (dir) {
112
- if (stopDir && dir === stopDir) {
113
- for (const n of names) {
114
- const thePath = path.join(dir, n);
115
- try {
116
- const stats = fs.statSync(thePath);
117
- if (!onlyDirectories && stats.isFile()) {
118
- return (0, import_normalize.normalizePath)(thePath);
119
- }
120
- if (!onlyFiles && stats.isDirectory()) {
121
- return (0, import_normalize.normalizePath)(thePath);
122
- }
123
- } catch {
124
- }
125
- }
126
- return void 0;
127
- }
104
+ const smolFindUp = (0, import_path2.getSmolPath)()?.findUp;
105
+ if (smolFindUp && stopAt === void 0) {
106
+ const found = smolFindUp(path.resolve(cwd), names, { onlyDirectories });
107
+ return found === void 0 ? void 0 : (0, import_normalize.normalizePath)(found);
108
+ }
109
+ for (const dir of (0, import_walk.walkUp)(cwd, { stopAt })) {
128
110
  for (const n of names) {
129
111
  const thePath = path.join(dir, n);
130
112
  try {
@@ -138,10 +120,6 @@ function findUpSync(name, options) {
138
120
  } catch {
139
121
  }
140
122
  }
141
- if (dir === root) {
142
- break;
143
- }
144
- dir = path.dirname(dir);
145
123
  }
146
124
  return void 0;
147
125
  }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @file `require.resolve`-from-an-arbitrary-base. Node's bare
3
+ * `require.resolve(spec)` resolves relative to the calling module; these
4
+ * helpers resolve a specifier as if required from a DIFFERENT directory —
5
+ * useful for "find the copy of `typescript` that THIS project would load,"
6
+ * not the copy socket-lib itself loads. Returns the resolved absolute file
7
+ * path, or (in `nothrow` form) `undefined` when the specifier can't be
8
+ * resolved.
9
+ */
10
+ /**
11
+ * Resolve a module specifier as if `require`'d from `fromDir`.
12
+ *
13
+ * Equivalent to running `require.resolve(specifier)` inside a module located at
14
+ * `fromDir`. Accepts package specifiers (`'typescript'`, `'pkg/sub/path'`) and
15
+ * relative paths (`'./foo'`).
16
+ *
17
+ * @example
18
+ * ;```ts
19
+ * // The `typescript` the project at /repo would load:
20
+ * requireResolveFrom('/repo', 'typescript')
21
+ * //=> '/repo/node_modules/typescript/lib/typescript.js'
22
+ *
23
+ * requireResolveFrom('/repo', './missing', { nothrow: true })
24
+ * //=> undefined
25
+ * ```
26
+ *
27
+ * @param fromDir - Directory to resolve as if the require originated there.
28
+ * @param specifier - Module specifier or relative path to resolve.
29
+ * @param options - `nothrow: true` returns `undefined` instead of throwing.
30
+ *
31
+ * @returns Absolute resolved path (or `undefined` when `nothrow` and
32
+ * unresolved).
33
+ *
34
+ * @throws When the specifier can't be resolved and `nothrow` is not set.
35
+ */
36
+ export declare function requireResolveFrom(fromDir: string, specifier: string, options: {
37
+ nothrow: true;
38
+ }): string | undefined;
39
+ export declare function requireResolveFrom(fromDir: string, specifier: string, options?: {
40
+ nothrow?: false | undefined;
41
+ } | undefined): string;
42
+ /**
43
+ * Resolve a module specifier as if `require`'d from `process.cwd()`. Alias for
44
+ * {@link requireResolveFrom} anchored at the current directory.
45
+ *
46
+ * @param specifier - Module specifier or relative path to resolve.
47
+ * @param options - `nothrow: true` returns `undefined` instead of throwing.
48
+ *
49
+ * @returns Absolute resolved path (or `undefined` when `nothrow` and
50
+ * unresolved).
51
+ */
52
+ export declare function requireResolveFromCwd(specifier: string, options: {
53
+ nothrow: true;
54
+ }): string | undefined;
55
+ export declare function requireResolveFromCwd(specifier: string, options?: {
56
+ nothrow?: false | undefined;
57
+ } | undefined): string;
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ /* Socket Lib - Built with esbuild */
3
+ "use strict";
4
+ var __create = Object.create;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __export = (target, all) => {
11
+ for (var name in all)
12
+ __defProp(target, name, { get: all[name], enumerable: true });
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
23
+ // If the importer is in node compatibility mode or this is not an ESM
24
+ // file that has been converted to a CommonJS file using a Babel-
25
+ // compatible transform (i.e. "__esModule" has not been set), then set
26
+ // "default" to the CommonJS "module.exports" for node compatibility.
27
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
28
+ mod
29
+ ));
30
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
+ var resolve_module_exports = {};
32
+ __export(resolve_module_exports, {
33
+ requireResolveFrom: () => requireResolveFrom,
34
+ requireResolveFromCwd: () => requireResolveFromCwd
35
+ });
36
+ module.exports = __toCommonJS(resolve_module_exports);
37
+ var import_node_module = require("node:module");
38
+ var import_node_process = __toESM(require("node:process"));
39
+ var import_path = require("../node/path");
40
+ function requireResolveFrom(fromDir, specifier, options) {
41
+ const { nothrow = false } = {
42
+ __proto__: null,
43
+ ...options
44
+ };
45
+ const path = (0, import_path.getNodePath)();
46
+ const anchor = path.join(path.resolve(fromDir), "noop.js");
47
+ try {
48
+ return (0, import_node_module.createRequire)(anchor).resolve(specifier);
49
+ } catch (e) {
50
+ if (nothrow) {
51
+ return void 0;
52
+ }
53
+ throw e;
54
+ }
55
+ }
56
+ function requireResolveFromCwd(specifier, options) {
57
+ return options && options.nothrow ? requireResolveFrom(import_node_process.default.cwd(), specifier, { nothrow: true }) : requireResolveFrom(import_node_process.default.cwd(), specifier);
58
+ }
59
+ // Annotate the CommonJS export names for ESM import in node:
60
+ 0 && (module.exports = {
61
+ requireResolveFrom,
62
+ requireResolveFromCwd
63
+ });