@socketsecurity/lib 5.21.0 → 5.24.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 CHANGED
@@ -5,6 +5,38 @@ 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
+ ## [5.24.0](https://github.com/SocketDev/socket-lib/releases/tag/v5.24.0) - 2026-04-22
9
+
10
+ ### Removed
11
+
12
+ - `@socketsecurity/lib/env/socket-cli-shadow` — deleted. Unused after Socket CLI's shadow infrastructure was removed
13
+
14
+ ### Fixed
15
+
16
+ - `packPackage()` / `extractPackage()` now work for non-registry specs (local dir/tarball, remote tarball URL, git). The bundled pacote fetchers (`dir.js`, `file.js`, `remote.js`, `git.js`) were over-stubbed and broke every non-registry path
17
+ - `EditablePackageJson.prepare()` no longer throws `git.find is not a function`. `@npmcli/git` is reached from `normalize.gitHead`, not just `arb.audit()`, so it can't be stubbed
18
+ - `packPackage(<dir>)` now runs `prepack` / `postpack` scripts instead of throwing `runScript is not a function`. `@npmcli/run-script` is reachable whenever `ignoreScripts` isn't set
19
+
20
+ ## [5.23.0](https://github.com/SocketDev/socket-lib/releases/tag/v5.23.0) - 2026-04-22
21
+
22
+ ### Added
23
+
24
+ - `@socketsecurity/lib/errors` `isError(value)` — spec-compliant ES2025 [`Error.isError`](https://tc39.es/ecma262/#sec-error.iserror) with an `@@toStringTag`-based shim for older engines. Recognizes cross-realm Errors (worker threads, vm contexts, iframes) that same-realm `instanceof Error` misses
25
+ - `@socketsecurity/lib/errors` `errorMessage(value)` — extracts a readable message from any caught value (Error with cause chain via `messageWithCauses`, primitive, plain object, or nullish) with the shared `UNKNOWN_ERROR` (`'Unknown error'`) fallback. Replaces the `e instanceof Error ? e.message : String(e)` pattern
26
+ - `@socketsecurity/lib/errors` `errorStack(value)` — companion helper returning the cause-aware stack for Error instances (via `stackWithCauses`) and `undefined` otherwise
27
+ - `@socketsecurity/lib/errors` `isErrnoException(value)` — narrows to `NodeJS.ErrnoException` (an Error with a non-empty uppercase-prefixed `.code`, matching the libuv `UV_E*` / Node `ERR_*` conventions), cross-realm safe
28
+ - `@socketsecurity/lib/errors` re-exports `UNKNOWN_ERROR` from `constants/core` so callers don't need a separate import
29
+
30
+ ### Changed
31
+
32
+ - `@socketsecurity/lib/errors` pony-cause `messageWithCauses` / `stackWithCauses` / `findCauseByReference` / `getErrorCause` — patched to use `isError` internally so cross-realm Errors are recognized (previously returned `''` for any Error thrown in a different realm)
33
+
34
+ ## [5.22.0](https://github.com/SocketDev/socket-lib/releases/tag/v5.22.0) - 2026-04-21
35
+
36
+ ### Changed
37
+
38
+ - `@socketsecurity/lib/releases/socket-btm` `getPlatformArch()` / `getBinaryAssetName()` — aligned with pnpm pack-app's `<os>-<arch>[-<libc>]` target format. The Windows OS segment is now `win32` (was `win`); `getPlatformArch('win32', 'x64')` returns `'win32-x64'` and `getBinaryAssetName('node', 'win32', 'x64')` returns `'node-win32-x64.exe'`. Callers that string-match on the output need updates
39
+
8
40
  ## [5.21.0](https://github.com/SocketDev/socket-lib/releases/tag/v5.21.0) - 2026-04-20
9
41
 
10
42
  ### Added
package/README.md CHANGED
@@ -7,219 +7,62 @@
7
7
  [![Follow @SocketSecurity](https://img.shields.io/twitter/follow/SocketSecurity?style=social)](https://twitter.com/SocketSecurity)
8
8
  [![Follow @socket.dev on Bluesky](https://img.shields.io/badge/Follow-@socket.dev-1DA1F2?style=social&logo=bluesky)](https://bsky.app/profile/socket.dev)
9
9
 
10
- Core infrastructure library for [Socket.dev](https://socket.dev/) security tools. Provides utilities for file system operations, process spawning, HTTP requests, environment detection, logging, spinners, and more.
11
-
12
- ## Prerequisites
13
-
14
- **Node.js 22 or higher** is required.
10
+ Core utilities for [Socket.dev](https://socket.dev/) tools: file system, processes, HTTP, env detection, logging, spinners, and more. Tree-shakeable, TypeScript-first, cross-platform.
15
11
 
16
12
  ## Install
17
13
 
18
14
  ```bash
19
- # Using pnpm (recommended)
20
15
  pnpm add @socketsecurity/lib
21
-
22
- # Using npm
23
- npm install @socketsecurity/lib
24
-
25
- # Using yarn
26
- yarn add @socketsecurity/lib
27
16
  ```
28
17
 
29
18
  ## Quick Start
30
19
 
31
20
  ```typescript
32
21
  import { Spinner } from '@socketsecurity/lib/spinner'
33
- import { getDefaultLogger } from '@socketsecurity/lib/logger'
34
22
  import { readJson } from '@socketsecurity/lib/fs'
35
23
 
36
- const logger = getDefaultLogger()
37
- const spinner = Spinner({ text: 'Loading package.json...' })
38
-
24
+ const spinner = Spinner({ text: 'Loading…' })
39
25
  spinner.start()
40
26
  const pkg = await readJson('./package.json')
41
- spinner.successAndStop('Loaded successfully')
42
-
43
- logger.success(`Package: ${pkg.name}@${pkg.version}`)
27
+ spinner.successAndStop(`Loaded ${pkg.name}@${pkg.version}`)
44
28
  ```
45
29
 
46
- ## Documentation
47
-
48
- - [API Index](./docs/api-index.md) - Every subpath export with a one-line description (start here)
49
- - [Getting Started](./docs/getting-started.md) - Prerequisites, installation, and first examples
50
- - [Visual Effects](./docs/visual-effects.md) - Spinners, loggers, themes, and progress indicators
51
- - [File System](./docs/file-system.md) - File operations, globs, paths, and safe deletion
52
- - [HTTP Utilities](./docs/http-utilities.md) - Making requests, downloading files, and retry logic
53
- - [Process Utilities](./docs/process-utilities.md) - Spawning processes, IPC, and locks
54
- - [Package Management](./docs/package-management.md) - npm/pnpm/yarn detection and operations
55
- - [Environment](./docs/environment.md) - CI detection, env getters, and platform checks
56
- - [Constants](./docs/constants.md) - Node versions, npm URLs, and platform values
57
- - [Examples](./docs/examples.md) - Real-world usage patterns
58
- - [Troubleshooting](./docs/troubleshooting.md) - Common issues and solutions
59
-
60
- ## What's Inside
61
-
62
- ### Visual Effects
63
-
64
- Spinners, colored loggers, themes, progress bars, and terminal output formatting.
65
-
66
- - `Spinner` - Animated CLI spinners with progress tracking
67
- - `getDefaultLogger()` - Colored console logger with symbols
68
- - `LOG_SYMBOLS` - Colored terminal symbols (✓, ✗, ⚠, ℹ, →)
69
- - `setTheme()` - Customize colors across the library
70
-
71
- ### File System
72
-
73
- Cross-platform file operations with safe deletion and convenient wrappers.
74
-
75
- - `readFileUtf8()`, `readFileBinary()` - Read files as text or binary
76
- - `readJson()`, `writeJson()` - Parse and format JSON files
77
- - `safeDelete()` - Protected deletion with safety checks
78
- - `findUp()`, `findUpSync()` - Traverse up to find files
79
- - `safeMkdir()` - Create directories without EEXIST errors
80
- - `validateFiles()` - Check file readability (useful for Yarn PnP, pnpm)
81
-
82
- ### HTTP Utilities
83
-
84
- Native Node.js HTTP/HTTPS requests with retry logic and redirects.
85
-
86
- - `httpJson()` - Fetch and parse JSON from APIs
87
- - `httpText()` - Fetch text/HTML content
88
- - `httpDownload()` - Download files with progress callbacks
89
- - `httpRequest()` - Full control over requests and responses
90
- - Automatic redirects, exponential backoff retries, timeout support
91
-
92
- ### Process Management
93
-
94
- Spawn child processes safely with cross-platform support.
95
-
96
- - `spawn()` - Promise-based process spawning with output capture
97
- - `spawnSync()` - Synchronous version for blocking operations
98
- - Array-based arguments prevent command injection
99
- - Automatic Windows `.cmd`/`.bat` handling
100
- - `processLock.withLock()` / `processLock.acquire()` / `processLock.release()` - Ensure only one instance runs at a time
101
- - `writeIpcStub()` / `getIpcStubPath()` - Filesystem-based inter-process data handoff
102
-
103
- ### Environment Detection
104
-
105
- Type-safe environment variable access and platform detection.
106
-
107
- - `getCI()` - Detect CI environment
108
- - `getNodeEnv()` - Get NODE_ENV value
109
- - `isTest()` - Check if running tests
110
- - `getHome()` - Home directory (cross-platform, with Windows `USERPROFILE` fallback)
111
- - Test rewiring with `setEnv()`, `resetEnv()`
112
-
113
- ### Package Management
114
-
115
- Detect and work with npm, pnpm, and yarn.
116
-
117
- - `detectPackageManager()` - Identify running package manager from `npm_config_user_agent` / binary path
118
- - Package manifest operations
119
- - Lock file management
120
-
121
- ### Constants
122
-
123
- Pre-defined values for Node.js, npm, and platform detection.
124
-
125
- - `getNodeMajorVersion()` - Get current Node.js major version
126
- - `WIN32`, `DARWIN` - Platform booleans (use `!WIN32 && !DARWIN` for Linux)
127
- - `getAbortSignal()` - Global abort signal
128
-
129
- ### Utilities
130
-
131
- Helpers for arrays, objects, strings, promises, sorting, and more.
132
-
133
- - Arrays, objects, strings manipulation
134
- - Promise utilities and queues
135
- - Natural sorting
136
- - Version comparison
137
- - Error handling with causes
138
-
139
- ## Features
140
-
141
- - **Tree-shakeable exports** - Import only what you need
142
- - **Cross-platform** - Works on Windows, macOS, and Linux
143
- - **TypeScript-first** - Full type safety with .d.ts files
144
- - **Zero dependencies** (for core HTTP - uses Node.js native modules)
145
- - **Well-tested** - 6000+ tests across 139+ test files
146
- - **Security-focused** - Safe defaults, command injection protection
147
- - **CommonJS output** - Compatible with Node.js tooling
148
-
149
- ## Common Use Cases
150
-
151
- ### Running Shell Commands
30
+ Every export lives under a subpath — pick what you need:
152
31
 
153
32
  ```typescript
154
33
  import { spawn } from '@socketsecurity/lib/spawn'
155
-
156
- const result = await spawn('git', ['status'])
157
- console.log(result.stdout)
158
- ```
159
-
160
- ### Making API Requests
161
-
162
- ```typescript
163
34
  import { httpJson } from '@socketsecurity/lib/http-request'
164
-
165
- const data = await httpJson('https://api.example.com/data')
166
- ```
167
-
168
- ### Visual Feedback
169
-
170
- ```typescript
171
- import { Spinner } from '@socketsecurity/lib/spinner'
172
-
173
- const spinner = Spinner({ text: 'Processing...' })
174
- spinner.start()
175
- // ... do work ...
176
- spinner.successAndStop('Complete!')
177
- ```
178
-
179
- ### Safe File Deletion
180
-
181
- ```typescript
182
35
  import { safeDelete } from '@socketsecurity/lib/fs'
183
-
184
- // Protected against deleting parent directories
185
- await safeDelete('./build')
186
- ```
187
-
188
- ## Troubleshooting
189
-
190
- **Module not found**: Verify you're importing from the correct path:
191
-
192
- ```typescript
193
- // Correct
194
- import { Spinner } from '@socketsecurity/lib/spinner'
195
-
196
- // Wrong
197
- import { Spinner } from '@socketsecurity/lib'
198
36
  ```
199
37
 
200
- **Node version error**: This library requires Node.js 22+. Check your version:
38
+ ## Documentation
201
39
 
202
- ```bash
203
- node --version
204
- ```
40
+ Start with the [API Index](./docs/api-index.md) — every subpath export with a one-line description.
205
41
 
206
- For more issues, see the [Troubleshooting Guide](./docs/troubleshooting.md).
42
+ - [Getting Started](./docs/getting-started.md) – install + first examples
43
+ - [Visual Effects](./docs/visual-effects.md) – spinners, loggers, themes
44
+ - [File System](./docs/file-system.md) – files, globs, paths, safe deletion
45
+ - [HTTP Utilities](./docs/http-utilities.md) – requests, downloads, retries
46
+ - [Process Utilities](./docs/process-utilities.md) – spawn, IPC, locks
47
+ - [Package Management](./docs/package-management.md) – npm/pnpm/yarn detection
48
+ - [Environment](./docs/environment.md) – CI/platform detection, env getters
49
+ - [Constants](./docs/constants.md) – Node versions, npm URLs, platform values
50
+ - [Examples](./docs/examples.md) – real-world patterns
51
+ - [Troubleshooting](./docs/troubleshooting.md) – common issues
207
52
 
208
53
  ## Development
209
54
 
210
55
  ```bash
211
- pnpm install # Install dependencies
212
- pnpm build # Build the library
213
- pnpm test # Run tests
214
- pnpm run cover # Run tests with coverage
215
- pnpm dev # Watch mode
216
- pnpm run lint # Check code style
217
- pnpm run fix # Fix formatting issues
56
+ pnpm install # install
57
+ pnpm build # build
58
+ pnpm test # run tests
59
+ pnpm run cover # tests with coverage
60
+ pnpm dev # watch mode
61
+ pnpm run lint # check style
62
+ pnpm run fix # auto-fix formatting
218
63
  ```
219
64
 
220
- ## Contributing
221
-
222
- Contributions are welcome! Please read the [CLAUDE.md](./CLAUDE.md) file for development guidelines and coding standards.
65
+ See [CLAUDE.md](./CLAUDE.md) for contributor guidelines.
223
66
 
224
67
  ## License
225
68
 
@@ -77,7 +77,7 @@ const SOCKET_FIREWALL_APP_NAME = "sfw";
77
77
  const SOCKET_REGISTRY_APP_NAME = "registry";
78
78
  const SOCKET_APP_PREFIX = "_";
79
79
  const SOCKET_LIB_NAME = "@socketsecurity/lib";
80
- const SOCKET_LIB_VERSION = "5.21.0";
80
+ const SOCKET_LIB_VERSION = "5.24.0";
81
81
  const SOCKET_LIB_URL = "https://github.com/SocketDev/socket-lib";
82
82
  const SOCKET_LIB_USER_AGENT = `socketsecurity-lib/${SOCKET_LIB_VERSION} (${SOCKET_LIB_URL})`;
83
83
  const SOCKET_IPC_HANDSHAKE = "SOCKET_IPC_HANDSHAKE";
@@ -26,6 +26,7 @@ __export(manifest_exports, {
26
26
  isPackageEntry: () => isPackageEntry
27
27
  });
28
28
  module.exports = __toCommonJS(manifest_exports);
29
+ var import_errors = require("../errors");
29
30
  var import_fs = require("../fs");
30
31
  var import_logger = require("../logger");
31
32
  var import_socket = require("../paths/socket");
@@ -79,9 +80,7 @@ class DlxManifest {
79
80
  }
80
81
  return JSON.parse(content);
81
82
  } catch (error) {
82
- logger.warn(
83
- `Failed to read manifest: ${error instanceof Error ? error.message : String(error)}`
84
- );
83
+ logger.warn(`Failed to read manifest: ${(0, import_errors.errorMessage)(error)}`);
85
84
  return { __proto__: null };
86
85
  }
87
86
  }
@@ -94,9 +93,7 @@ class DlxManifest {
94
93
  try {
95
94
  (0, import_fs.safeMkdirSync)(manifestDir, { recursive: true });
96
95
  } catch (error) {
97
- logger.warn(
98
- `Failed to create manifest directory: ${error instanceof Error ? error.message : String(error)}`
99
- );
96
+ logger.warn(`Failed to create manifest directory: ${(0, import_errors.errorMessage)(error)}`);
100
97
  }
101
98
  const content = JSON.stringify(data, null, 2);
102
99
  const tempPath = `${this.manifestPath}.tmp`;
@@ -130,9 +127,7 @@ class DlxManifest {
130
127
  delete data[name];
131
128
  await this.writeManifest(data);
132
129
  } catch (error) {
133
- logger.warn(
134
- `Failed to clear cache for ${name}: ${error instanceof Error ? error.message : String(error)}`
135
- );
130
+ logger.warn(`Failed to clear cache for ${name}: ${(0, import_errors.errorMessage)(error)}`);
136
131
  }
137
132
  });
138
133
  }
@@ -146,9 +141,7 @@ class DlxManifest {
146
141
  fs.unlinkSync(this.manifestPath);
147
142
  }
148
143
  } catch (error) {
149
- logger.warn(
150
- `Failed to clear all cache: ${error instanceof Error ? error.message : String(error)}`
151
- );
144
+ logger.warn(`Failed to clear all cache: ${(0, import_errors.errorMessage)(error)}`);
152
145
  }
153
146
  });
154
147
  }
@@ -180,9 +173,7 @@ class DlxManifest {
180
173
  const data = JSON.parse(content);
181
174
  return Object.keys(data);
182
175
  } catch (error) {
183
- logger.warn(
184
- `Failed to get package list: ${error instanceof Error ? error.message : String(error)}`
185
- );
176
+ logger.warn(`Failed to get package list: ${(0, import_errors.errorMessage)(error)}`);
186
177
  return [];
187
178
  }
188
179
  }
@@ -224,9 +215,7 @@ class DlxManifest {
224
215
  }
225
216
  }
226
217
  } catch (error) {
227
- logger.warn(
228
- `Failed to read existing manifest: ${error instanceof Error ? error.message : String(error)}`
229
- );
218
+ logger.warn(`Failed to read existing manifest: ${(0, import_errors.errorMessage)(error)}`);
230
219
  }
231
220
  data[name] = record;
232
221
  const manifestDir = path.dirname(this.manifestPath);
@@ -234,7 +223,7 @@ class DlxManifest {
234
223
  (0, import_fs.safeMkdirSync)(manifestDir, { recursive: true });
235
224
  } catch (error) {
236
225
  logger.warn(
237
- `Failed to create manifest directory: ${error instanceof Error ? error.message : String(error)}`
226
+ `Failed to create manifest directory: ${(0, import_errors.errorMessage)(error)}`
238
227
  );
239
228
  }
240
229
  const content = JSON.stringify(data, null, 2);
@@ -43,6 +43,7 @@ __export(package_exports, {
43
43
  module.exports = __toCommonJS(package_exports);
44
44
  var import_platform = require("../constants/platform");
45
45
  var import_socket = require("../constants/socket");
46
+ var import_errors = require("../errors");
46
47
  var import_arborist = __toESM(require("../external/@npmcli/arborist"));
47
48
  var import_libnpmexec = __toESM(require("../external/libnpmexec"));
48
49
  var import_npm_package_arg = __toESM(require("../external/npm-package-arg"));
@@ -276,7 +277,7 @@ Ensure the filesystem is writable or set SOCKET_DLX_DIR to a writable location.`
276
277
  await checkFirewallPurls(arb, packageName);
277
278
  await arb.reify({ save: true });
278
279
  } catch (e) {
279
- if (e instanceof Error && e.message.startsWith("Socket Firewall blocked")) {
280
+ if ((0, import_errors.isError)(e) && e.message.startsWith("Socket Firewall blocked")) {
280
281
  throw e;
281
282
  }
282
283
  const code = e?.code;
@@ -63,9 +63,10 @@ export declare function getSocketCliApiProxy(): string | undefined;
63
63
  */
64
64
  export declare function getSocketCliApiTimeout(): number;
65
65
  /**
66
- * Socket CLI API authentication token (alternative name).
67
- * Checks SOCKET_CLI_API_TOKEN, SOCKET_CLI_API_KEY, SOCKET_SECURITY_API_TOKEN, SOCKET_SECURITY_API_KEY.
68
- * Maintains full v1.x backward compatibility.
66
+ * Socket CLI API authentication token.
67
+ * Checks SOCKET_API_TOKEN (canonical), then the legacy names
68
+ * SOCKET_CLI_API_TOKEN, SOCKET_CLI_API_KEY, SOCKET_SECURITY_API_TOKEN,
69
+ * SOCKET_SECURITY_API_KEY. Maintains full v1.x backward compatibility.
69
70
  *
70
71
  * @returns API token or undefined
71
72
  *
@@ -56,7 +56,7 @@ function getSocketCliApiTimeout() {
56
56
  }
57
57
  // @__NO_SIDE_EFFECTS__
58
58
  function getSocketCliApiToken() {
59
- return (0, import_rewire.getEnvValue)("SOCKET_CLI_API_TOKEN") || (0, import_rewire.getEnvValue)("SOCKET_CLI_API_KEY") || (0, import_rewire.getEnvValue)("SOCKET_SECURITY_API_TOKEN") || (0, import_rewire.getEnvValue)("SOCKET_SECURITY_API_KEY");
59
+ return (0, import_rewire.getEnvValue)("SOCKET_API_TOKEN") || (0, import_rewire.getEnvValue)("SOCKET_CLI_API_TOKEN") || (0, import_rewire.getEnvValue)("SOCKET_CLI_API_KEY") || (0, import_rewire.getEnvValue)("SOCKET_SECURITY_API_TOKEN") || (0, import_rewire.getEnvValue)("SOCKET_SECURITY_API_KEY");
60
60
  }
61
61
  // @__NO_SIDE_EFFECTS__
62
62
  function getSocketCliBootstrapCacheDir() {
package/dist/errors.d.ts CHANGED
@@ -1,6 +1,100 @@
1
1
  /**
2
2
  * @fileoverview Error utilities with cause chain support.
3
- * Provides helpers for working with error causes and stack traces.
3
+ *
4
+ * Provides:
5
+ * - `isError(value)` — cross-realm-safe Error check (ES2025 `Error.isError`
6
+ * when available, `@@toStringTag` fallback otherwise).
7
+ * - `errorMessage(value)` — read the message (with cause chain) from any
8
+ * caught value, falling back to the shared `UNKNOWN_ERROR` sentinel.
9
+ * - `errorStack(value)` — read the stack (with cause chain) from any
10
+ * caught value, or `undefined` for non-Errors.
11
+ *
12
+ * `messageWithCauses` / `stackWithCauses` are re-exported from pony-cause;
13
+ * a patched copy recognizes cross-realm Errors via `isError`.
4
14
  */
15
+ import { UNKNOWN_ERROR } from './constants/core';
5
16
  import { messageWithCauses, stackWithCauses } from './external/pony-cause';
6
- export { messageWithCauses, stackWithCauses };
17
+ export { UNKNOWN_ERROR, messageWithCauses, stackWithCauses };
18
+ /**
19
+ * Spec-compliant [`Error.isError`](https://tc39.es/ecma262/#sec-error.iserror)
20
+ * with a fallback shim for engines that don't ship it yet.
21
+ *
22
+ * Returns `true` for Errors from any realm (worker threads, vm contexts,
23
+ * iframes) — things same-realm `instanceof Error` misses. Plain objects
24
+ * with `name` + `message` properties are **not** recognized.
25
+ *
26
+ * @example
27
+ * try {
28
+ * await doWork()
29
+ * } catch (e) {
30
+ * if (isError(e)) {
31
+ * logger.error(e.message)
32
+ * } else {
33
+ * logger.error(String(e))
34
+ * }
35
+ * }
36
+ */
37
+ /**
38
+ * `Error.isError` fallback shim — the in-language approximation used
39
+ * when the native ES2025 method isn't available.
40
+ *
41
+ * Exported separately so test suites on engines that ship the native
42
+ * method can still exercise the shim branch directly. Consumers should
43
+ * prefer {@link isError}, which picks the native method when present.
44
+ */
45
+ export declare function isErrorShim(value: unknown): value is Error;
46
+ /**
47
+ * Reference to the native ES2025 `Error.isError` when the running
48
+ * engine ships it, otherwise `undefined`. Exposed separately so tests
49
+ * and callers can detect the fast-path without re-probing.
50
+ */
51
+ export declare const isErrorBuiltin: ((value: unknown) => value is Error) | undefined;
52
+ /**
53
+ * Prefer the native ES2025 `Error.isError` when available (exact
54
+ * `[[ErrorData]]` slot check, cross-realm-safe); fall back to
55
+ * {@link isErrorShim} otherwise.
56
+ */
57
+ export declare const isError: (value: unknown) => value is Error;
58
+ /**
59
+ * Narrow a caught value to a Node.js `ErrnoException` — an Error with a
60
+ * `.code` string set by libuv/syscall failures (e.g. `'ENOENT'`,
61
+ * `'EACCES'`, `'EBUSY'`, `'EPERM'`). Cross-realm safe (builds on
62
+ * {@link isError}), and checks that `code` is a string so a merely
63
+ * branded Error without a real errno code returns `false`.
64
+ *
65
+ * @example
66
+ * try {
67
+ * await fsPromises.readFile(path)
68
+ * } catch (e) {
69
+ * if (isErrnoException(e) && e.code === 'ENOENT') {
70
+ * // … retry, or return default …
71
+ * } else {
72
+ * throw e
73
+ * }
74
+ * }
75
+ */
76
+ export declare function isErrnoException(value: unknown): value is NodeJS.ErrnoException;
77
+ /**
78
+ * Extract a human-readable message from any caught value.
79
+ *
80
+ * Walks the `cause` chain for Errors (via {@link messageWithCauses});
81
+ * coerces primitives and objects to string; returns
82
+ * {@link UNKNOWN_ERROR} for `null`, `undefined`, empty strings,
83
+ * `[object Object]`, or Errors with no message.
84
+ *
85
+ * @example
86
+ * try {
87
+ * await readConfig(path)
88
+ * } catch (e) {
89
+ * throw new Error(`Failed to read ${path}: ${errorMessage(e)}`, { cause: e })
90
+ * }
91
+ */
92
+ export declare function errorMessage(value: unknown): string;
93
+ /**
94
+ * Extract a stack trace (with causes) from any caught value.
95
+ *
96
+ * Returns the cause-aware stack via {@link stackWithCauses} for Errors;
97
+ * returns `undefined` for non-Error values, so callers can
98
+ * `logger.error(msg, { stack: errorStack(e) })` safely.
99
+ */
100
+ export declare function errorStack(value: unknown): string | undefined;
package/dist/errors.js CHANGED
@@ -20,13 +20,68 @@ var __copyProps = (to, from, except, desc) => {
20
20
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
21
  var errors_exports = {};
22
22
  __export(errors_exports, {
23
+ UNKNOWN_ERROR: () => import_core.UNKNOWN_ERROR,
24
+ errorMessage: () => errorMessage,
25
+ errorStack: () => errorStack,
26
+ isErrnoException: () => isErrnoException,
27
+ isError: () => isError,
28
+ isErrorBuiltin: () => isErrorBuiltin,
29
+ isErrorShim: () => isErrorShim,
23
30
  messageWithCauses: () => import_pony_cause.messageWithCauses,
24
31
  stackWithCauses: () => import_pony_cause.stackWithCauses
25
32
  });
26
33
  module.exports = __toCommonJS(errors_exports);
34
+ var import_core = require("./constants/core");
27
35
  var import_pony_cause = require("./external/pony-cause");
36
+ const ObjectPrototypeToString = Object.prototype.toString;
37
+ const ReflectApply = Reflect.apply;
38
+ function isErrorShim(value) {
39
+ if (value === null || typeof value !== "object") {
40
+ return false;
41
+ }
42
+ return ReflectApply(ObjectPrototypeToString, value, []) === "[object Error]";
43
+ }
44
+ const isErrorBuiltin = Error.isError;
45
+ const isError = isErrorBuiltin ?? isErrorShim;
46
+ function isErrnoException(value) {
47
+ if (!isError(value)) {
48
+ return false;
49
+ }
50
+ const code = value.code;
51
+ if (typeof code !== "string" || code.length === 0) {
52
+ return false;
53
+ }
54
+ const first = code.charCodeAt(0);
55
+ return first >= 65 && first <= 90;
56
+ }
57
+ function errorMessage(value) {
58
+ if (isError(value)) {
59
+ return (0, import_pony_cause.messageWithCauses)(value) || import_core.UNKNOWN_ERROR;
60
+ }
61
+ if (value === null || value === void 0) {
62
+ return import_core.UNKNOWN_ERROR;
63
+ }
64
+ const s = String(value);
65
+ if (s === "" || s === "[object Object]") {
66
+ return import_core.UNKNOWN_ERROR;
67
+ }
68
+ return s;
69
+ }
70
+ function errorStack(value) {
71
+ if (isError(value)) {
72
+ return (0, import_pony_cause.stackWithCauses)(value);
73
+ }
74
+ return void 0;
75
+ }
28
76
  // Annotate the CommonJS export names for ESM import in node:
29
77
  0 && (module.exports = {
78
+ UNKNOWN_ERROR,
79
+ errorMessage,
80
+ errorStack,
81
+ isErrnoException,
82
+ isError,
83
+ isErrorBuiltin,
84
+ isErrorShim,
30
85
  messageWithCauses,
31
86
  stackWithCauses
32
87
  });