@oh-my-pi/pi-natives 10.0.0 → 10.2.1
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/native/pi_natives.darwin-arm64.node +0 -0
- package/native/pi_natives.darwin-x64.node +0 -0
- package/native/pi_natives.linux-arm64.node +0 -0
- package/native/pi_natives.linux-x64.node +0 -0
- package/native/pi_natives.win32-x64.node +0 -0
- package/package.json +2 -2
- package/src/bindings.ts +11 -1
- package/src/{find → glob}/index.ts +6 -5
- package/src/{find → glob}/types.ts +17 -8
- package/src/grep/index.ts +2 -3
- package/src/grep/types.ts +3 -4
- package/src/html/index.ts +2 -7
- package/src/index.ts +8 -5
- package/src/native.ts +4 -3
- package/src/shell/index.ts +3 -20
- package/src/shell/types.ts +10 -21
- package/src/work/index.ts +11 -0
- package/src/work/types.ts +31 -0
- package/src/request-options.ts +0 -94
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-my-pi/pi-natives",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.2.1",
|
|
4
4
|
"description": "Native Rust functionality via N-API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"directory": "packages/natives"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@oh-my-pi/pi-utils": "10.
|
|
35
|
+
"@oh-my-pi/pi-utils": "10.2.1"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/node": "^25.0.10"
|
package/src/bindings.ts
CHANGED
|
@@ -6,8 +6,18 @@
|
|
|
6
6
|
/** Callback type for threadsafe functions from N-API. */
|
|
7
7
|
export type TsFunc<T> = (error: Error | null, value: T) => void;
|
|
8
8
|
|
|
9
|
+
/** Options for cancellable operations. */
|
|
10
|
+
export interface Cancellable {
|
|
11
|
+
/** Timeout in milliseconds for the operation. */
|
|
12
|
+
timeoutMs?: number;
|
|
13
|
+
/** Abort signal for cancelling the operation. */
|
|
14
|
+
signal?: AbortSignal;
|
|
15
|
+
}
|
|
16
|
+
|
|
9
17
|
/**
|
|
10
18
|
* Native bindings interface.
|
|
11
19
|
* Extended by each module via declaration merging.
|
|
12
20
|
*/
|
|
13
|
-
export interface NativeBindings {
|
|
21
|
+
export interface NativeBindings {
|
|
22
|
+
cancelWork(id: number): void;
|
|
23
|
+
}
|
|
@@ -4,15 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
import * as path from "node:path";
|
|
6
6
|
import { native } from "../native";
|
|
7
|
-
import type {
|
|
7
|
+
import type { GlobMatch, GlobOptions, GlobResult } from "./types";
|
|
8
8
|
|
|
9
|
-
export type {
|
|
9
|
+
export type { GlobMatch, GlobOptions, GlobResult } from "./types";
|
|
10
|
+
export { FileType } from "./types";
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Find files matching a glob pattern.
|
|
13
14
|
* Respects .gitignore by default.
|
|
14
15
|
*/
|
|
15
|
-
export async function
|
|
16
|
+
export async function glob(options: GlobOptions, onMatch?: (match: GlobMatch) => void): Promise<GlobResult> {
|
|
16
17
|
const searchPath = path.resolve(options.path);
|
|
17
18
|
const pattern = options.pattern || "*";
|
|
18
19
|
|
|
@@ -20,9 +21,9 @@ export async function find(options: FindOptions, onMatch?: (match: FindMatch) =>
|
|
|
20
21
|
const globPattern = pattern.includes("/") || pattern.startsWith("**") ? pattern : `**/${pattern}`;
|
|
21
22
|
|
|
22
23
|
// napi-rs ThreadsafeFunction passes (error, value) - skip callback on error
|
|
23
|
-
const cb = onMatch ? (err: Error | null, m:
|
|
24
|
+
const cb = onMatch ? (err: Error | null, m: GlobMatch) => !err && onMatch(m) : undefined;
|
|
24
25
|
|
|
25
|
-
return native.
|
|
26
|
+
return native.glob(
|
|
26
27
|
{
|
|
27
28
|
...options,
|
|
28
29
|
path: searchPath,
|
|
@@ -2,16 +2,25 @@
|
|
|
2
2
|
* Types for native find API.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { TsFunc } from "../bindings";
|
|
5
|
+
import type { Cancellable, TsFunc } from "../bindings";
|
|
6
|
+
|
|
7
|
+
export const enum FileType {
|
|
8
|
+
/** A regular file. */
|
|
9
|
+
File = 1,
|
|
10
|
+
/** A directory. */
|
|
11
|
+
Dir = 2,
|
|
12
|
+
/** A symlink. */
|
|
13
|
+
Symlink = 3,
|
|
14
|
+
}
|
|
6
15
|
|
|
7
16
|
/** Options for discovering files and directories. */
|
|
8
|
-
export interface
|
|
17
|
+
export interface GlobOptions extends Cancellable {
|
|
9
18
|
/** Glob pattern to match (e.g., `*.ts`). */
|
|
10
19
|
pattern: string;
|
|
11
20
|
/** Directory to search. */
|
|
12
21
|
path: string;
|
|
13
22
|
/** Filter by file type: "file", "dir", or "symlink". */
|
|
14
|
-
fileType?:
|
|
23
|
+
fileType?: FileType;
|
|
15
24
|
/** Include hidden files (default: false). */
|
|
16
25
|
hidden?: boolean;
|
|
17
26
|
/** Maximum number of results to return. */
|
|
@@ -23,19 +32,19 @@ export interface FindOptions {
|
|
|
23
32
|
}
|
|
24
33
|
|
|
25
34
|
/** A single filesystem match. */
|
|
26
|
-
export interface
|
|
35
|
+
export interface GlobMatch {
|
|
27
36
|
/** Relative path from the search root. */
|
|
28
37
|
path: string;
|
|
29
38
|
/** Resolved filesystem type for the match. */
|
|
30
|
-
fileType:
|
|
39
|
+
fileType: FileType;
|
|
31
40
|
/** Modification time in milliseconds since epoch, if available. */
|
|
32
41
|
mtime?: number;
|
|
33
42
|
}
|
|
34
43
|
|
|
35
44
|
/** Result of a find operation. */
|
|
36
|
-
export interface
|
|
45
|
+
export interface GlobResult {
|
|
37
46
|
/** Matched filesystem entries. */
|
|
38
|
-
matches:
|
|
47
|
+
matches: GlobMatch[];
|
|
39
48
|
/** Number of matches returned after limits are applied. */
|
|
40
49
|
totalMatches: number;
|
|
41
50
|
}
|
|
@@ -47,6 +56,6 @@ declare module "../bindings" {
|
|
|
47
56
|
* @param options Search options that control globbing and filters.
|
|
48
57
|
* @param onMatch Optional callback for streaming matches as they are found.
|
|
49
58
|
*/
|
|
50
|
-
|
|
59
|
+
glob(options: GlobOptions, onMatch?: TsFunc<GlobMatch>): Promise<GlobResult>;
|
|
51
60
|
}
|
|
52
61
|
}
|
package/src/grep/index.ts
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { native } from "../native";
|
|
6
|
-
import { wrapRequestOptions } from "../request-options";
|
|
7
6
|
import type {
|
|
8
7
|
ContextLine,
|
|
9
8
|
FuzzyFindMatch,
|
|
@@ -36,7 +35,7 @@ export type {
|
|
|
36
35
|
export async function grep(options: GrepOptions, onMatch?: (match: GrepMatch) => void): Promise<GrepResult> {
|
|
37
36
|
// napi-rs ThreadsafeFunction passes (error, value) - skip callback on error
|
|
38
37
|
const cb = onMatch ? (err: Error | null, m: GrepMatch) => !err && onMatch(m) : undefined;
|
|
39
|
-
return
|
|
38
|
+
return native.grep(options, cb);
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
/**
|
|
@@ -69,5 +68,5 @@ export function hasMatch(
|
|
|
69
68
|
* (case-insensitive). Respects .gitignore by default.
|
|
70
69
|
*/
|
|
71
70
|
export async function fuzzyFind(options: FuzzyFindOptions): Promise<FuzzyFindResult> {
|
|
72
|
-
return
|
|
71
|
+
return native.fuzzyFind(options);
|
|
73
72
|
}
|
package/src/grep/types.ts
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
* Types for grep/search operations.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { TsFunc } from "../bindings";
|
|
6
|
-
import type { RequestOptions } from "../request-options";
|
|
5
|
+
import type { Cancellable, TsFunc } from "../bindings";
|
|
7
6
|
|
|
8
7
|
/** Options for searching files. */
|
|
9
|
-
export interface GrepOptions extends
|
|
8
|
+
export interface GrepOptions extends Cancellable {
|
|
10
9
|
/** Regex pattern to search for */
|
|
11
10
|
pattern: string;
|
|
12
11
|
/** Directory or file to search */
|
|
@@ -129,7 +128,7 @@ export type WasmMatch = SearchMatch;
|
|
|
129
128
|
export type WasmSearchResult = SearchResult;
|
|
130
129
|
|
|
131
130
|
/** Options for fuzzy file path search. */
|
|
132
|
-
export interface FuzzyFindOptions extends
|
|
131
|
+
export interface FuzzyFindOptions extends Cancellable {
|
|
133
132
|
/** Substring query to match against file paths (case-insensitive). */
|
|
134
133
|
query: string;
|
|
135
134
|
/** Directory to search. */
|
package/src/html/index.ts
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { native } from "../native";
|
|
6
|
-
import { type RequestOptions, wrapRequestOptions } from "../request-options";
|
|
7
6
|
import type { HtmlToMarkdownOptions } from "./types";
|
|
8
7
|
|
|
9
8
|
export type { HtmlToMarkdownOptions } from "./types";
|
|
@@ -15,10 +14,6 @@ export type { HtmlToMarkdownOptions } from "./types";
|
|
|
15
14
|
* @param options - Conversion options
|
|
16
15
|
* @returns Markdown text
|
|
17
16
|
*/
|
|
18
|
-
export async function htmlToMarkdown(
|
|
19
|
-
html
|
|
20
|
-
options?: HtmlToMarkdownOptions,
|
|
21
|
-
req?: RequestOptions,
|
|
22
|
-
): Promise<string> {
|
|
23
|
-
return wrapRequestOptions(() => native.htmlToMarkdown(html, options), req);
|
|
17
|
+
export async function htmlToMarkdown(html: string, options?: HtmlToMarkdownOptions): Promise<string> {
|
|
18
|
+
return native.htmlToMarkdown(html, options);
|
|
24
19
|
}
|
package/src/index.ts
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
* Native utilities powered by N-API.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export type { RequestOptions } from "./request-options";
|
|
6
|
-
|
|
7
5
|
// =============================================================================
|
|
8
6
|
// Clipboard
|
|
9
7
|
// =============================================================================
|
|
@@ -30,10 +28,16 @@ export {
|
|
|
30
28
|
} from "./grep";
|
|
31
29
|
|
|
32
30
|
// =============================================================================
|
|
33
|
-
//
|
|
31
|
+
// Glob (file discovery)
|
|
34
32
|
// =============================================================================
|
|
35
33
|
|
|
36
|
-
export {
|
|
34
|
+
export {
|
|
35
|
+
FileType,
|
|
36
|
+
type GlobMatch,
|
|
37
|
+
type GlobOptions,
|
|
38
|
+
type GlobResult,
|
|
39
|
+
glob,
|
|
40
|
+
} from "./glob";
|
|
37
41
|
|
|
38
42
|
// =============================================================================
|
|
39
43
|
// Image processing (photon-compatible API)
|
|
@@ -98,7 +102,6 @@ export { getSystemInfo, type SystemInfo } from "./system-info";
|
|
|
98
102
|
// =============================================================================
|
|
99
103
|
|
|
100
104
|
export {
|
|
101
|
-
abortShellExecution,
|
|
102
105
|
executeShell,
|
|
103
106
|
Shell,
|
|
104
107
|
type ShellExecuteOptions,
|
package/src/native.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { embeddedAddon } from "./embedded-addon";
|
|
|
14
14
|
|
|
15
15
|
// Import types to trigger declaration merging
|
|
16
16
|
import "./clipboard/types";
|
|
17
|
-
import "./
|
|
17
|
+
import "./glob/types";
|
|
18
18
|
import "./grep/types";
|
|
19
19
|
import "./highlight/types";
|
|
20
20
|
import "./html/types";
|
|
@@ -24,6 +24,7 @@ import "./ps/types";
|
|
|
24
24
|
import "./shell/types";
|
|
25
25
|
import "./system-info/types";
|
|
26
26
|
import "./text/types";
|
|
27
|
+
import "./work/types";
|
|
27
28
|
|
|
28
29
|
export type { NativeBindings, TsFunc } from "./bindings";
|
|
29
30
|
|
|
@@ -159,7 +160,7 @@ function validateNative(bindings: NativeBindings, source: string): void {
|
|
|
159
160
|
|
|
160
161
|
checkFn("copyToClipboard");
|
|
161
162
|
checkFn("readImageFromClipboard");
|
|
162
|
-
checkFn("
|
|
163
|
+
checkFn("glob");
|
|
163
164
|
checkFn("fuzzyFind");
|
|
164
165
|
checkFn("grep");
|
|
165
166
|
checkFn("search");
|
|
@@ -174,7 +175,6 @@ function validateNative(bindings: NativeBindings, source: string): void {
|
|
|
174
175
|
checkFn("extractSegments");
|
|
175
176
|
checkFn("matchesKittySequence");
|
|
176
177
|
checkFn("executeShell");
|
|
177
|
-
checkFn("abortShellExecution");
|
|
178
178
|
checkFn("Shell");
|
|
179
179
|
checkFn("parseKey");
|
|
180
180
|
checkFn("matchesLegacySequence");
|
|
@@ -184,6 +184,7 @@ function validateNative(bindings: NativeBindings, source: string): void {
|
|
|
184
184
|
checkFn("killTree");
|
|
185
185
|
checkFn("listDescendants");
|
|
186
186
|
checkFn("getSystemInfo");
|
|
187
|
+
checkFn("getWorkProfile");
|
|
187
188
|
|
|
188
189
|
if (missing.length) {
|
|
189
190
|
throw new Error(
|
package/src/shell/index.ts
CHANGED
|
@@ -3,20 +3,12 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { native } from "../native";
|
|
6
|
-
import type { ShellExecuteOptions, ShellExecuteResult
|
|
6
|
+
import type { ShellExecuteOptions, ShellExecuteResult } from "./types";
|
|
7
7
|
|
|
8
8
|
export type { ShellExecuteOptions, ShellExecuteResult, ShellOptions, ShellRunOptions, ShellRunResult } from "./types";
|
|
9
9
|
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
abort(): void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface ShellConstructor {
|
|
16
|
-
new (options?: ShellOptions): Shell;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export const Shell = native.Shell as ShellConstructor;
|
|
10
|
+
export const { Shell } = native;
|
|
11
|
+
export type Shell = import("./types").Shell;
|
|
20
12
|
|
|
21
13
|
/**
|
|
22
14
|
* Execute a shell command using brush-core.
|
|
@@ -32,12 +24,3 @@ export async function executeShell(
|
|
|
32
24
|
const wrappedCallback = onChunk ? (err: Error | null, chunk: string) => !err && onChunk(chunk) : undefined;
|
|
33
25
|
return native.executeShell(options, wrappedCallback);
|
|
34
26
|
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Abort a running shell execution.
|
|
38
|
-
*
|
|
39
|
-
* @param executionId - The execution ID to abort
|
|
40
|
-
*/
|
|
41
|
-
export function abortShellExecution(executionId: string): void {
|
|
42
|
-
native.abortShellExecution(executionId);
|
|
43
|
-
}
|
package/src/shell/types.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Types for shell execution via brush-core.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { TsFunc } from "../bindings";
|
|
5
|
+
import type { Cancellable, TsFunc } from "../bindings";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Configuration for a persistent brush-core shell session.
|
|
@@ -17,15 +17,13 @@ export interface ShellOptions {
|
|
|
17
17
|
/**
|
|
18
18
|
* Options for running a single shell command.
|
|
19
19
|
*/
|
|
20
|
-
export interface ShellRunOptions {
|
|
20
|
+
export interface ShellRunOptions extends Cancellable {
|
|
21
21
|
/** The command to execute. */
|
|
22
22
|
command: string;
|
|
23
23
|
/** Working directory for command execution. */
|
|
24
24
|
cwd?: string;
|
|
25
25
|
/** Environment variables to apply for this command. */
|
|
26
26
|
env?: Record<string, string>;
|
|
27
|
-
/** Timeout in milliseconds. */
|
|
28
|
-
timeoutMs?: number;
|
|
29
27
|
}
|
|
30
28
|
|
|
31
29
|
/**
|
|
@@ -43,7 +41,7 @@ export interface ShellRunResult {
|
|
|
43
41
|
/**
|
|
44
42
|
* Internal options for the native brush-core binding.
|
|
45
43
|
*/
|
|
46
|
-
export interface ShellExecuteOptions {
|
|
44
|
+
export interface ShellExecuteOptions extends Cancellable {
|
|
47
45
|
/** The command to execute. */
|
|
48
46
|
command: string;
|
|
49
47
|
/** Working directory for command execution. */
|
|
@@ -52,12 +50,6 @@ export interface ShellExecuteOptions {
|
|
|
52
50
|
env?: Record<string, string>;
|
|
53
51
|
/** Environment variables to set once per session. */
|
|
54
52
|
sessionEnv?: Record<string, string>;
|
|
55
|
-
/** Timeout in milliseconds. */
|
|
56
|
-
timeoutMs?: number;
|
|
57
|
-
/** Unique identifier for this execution (used for abort). */
|
|
58
|
-
executionId: string;
|
|
59
|
-
/** Session key for persistent brush shell instances. */
|
|
60
|
-
sessionKey: string;
|
|
61
53
|
/** Optional snapshot path to source for bash sessions. */
|
|
62
54
|
snapshotPath?: string;
|
|
63
55
|
}
|
|
@@ -67,7 +59,7 @@ export interface ShellExecuteOptions {
|
|
|
67
59
|
export interface ShellExecuteResult extends ShellRunResult {}
|
|
68
60
|
|
|
69
61
|
/** Native Shell class instance. */
|
|
70
|
-
export interface
|
|
62
|
+
export interface Shell {
|
|
71
63
|
/**
|
|
72
64
|
* Run a command in the shell.
|
|
73
65
|
* @param options Command execution options.
|
|
@@ -77,17 +69,18 @@ export interface NativeShell {
|
|
|
77
69
|
run(options: ShellRunOptions, onChunk?: TsFunc<string>): Promise<ShellRunResult>;
|
|
78
70
|
/**
|
|
79
71
|
* Abort all running commands in this session.
|
|
72
|
+
* @param reason Optional reason for the abort.
|
|
80
73
|
*/
|
|
81
|
-
abort(): void;
|
|
74
|
+
abort(reason?: string): void;
|
|
82
75
|
}
|
|
83
76
|
|
|
84
77
|
/** Native Shell class constructor. */
|
|
85
|
-
export interface
|
|
78
|
+
export interface ShellConstructor {
|
|
86
79
|
/**
|
|
87
80
|
* Create a new shell session.
|
|
88
81
|
* @param options Optional session configuration.
|
|
89
82
|
*/
|
|
90
|
-
new (options?: ShellOptions):
|
|
83
|
+
new (options?: ShellOptions): Shell;
|
|
91
84
|
}
|
|
92
85
|
|
|
93
86
|
declare module "../bindings" {
|
|
@@ -100,12 +93,8 @@ declare module "../bindings" {
|
|
|
100
93
|
* @returns Promise resolving to the command result.
|
|
101
94
|
*/
|
|
102
95
|
executeShell(options: ShellExecuteOptions, onChunk?: TsFunc<string>): Promise<ShellExecuteResult>;
|
|
103
|
-
|
|
104
|
-
* Abort a running shell execution by ID.
|
|
105
|
-
* @param executionId Execution identifier from ShellExecuteOptions.
|
|
106
|
-
*/
|
|
107
|
-
abortShellExecution(executionId: string): void;
|
|
96
|
+
|
|
108
97
|
/** Shell class constructor for creating sessions. */
|
|
109
|
-
Shell:
|
|
98
|
+
Shell: ShellConstructor;
|
|
110
99
|
}
|
|
111
100
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Work scheduling profiling via native instrumentation.
|
|
3
|
+
*
|
|
4
|
+
* Always-on profiling - samples are collected into a circular buffer.
|
|
5
|
+
* Call `getWorkProfile()` to retrieve recent activity.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { native } from "../native";
|
|
9
|
+
|
|
10
|
+
export type { WorkProfile } from "./types";
|
|
11
|
+
export const { getWorkProfile } = native;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for work scheduling profiling.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Profiling results from work scheduling instrumentation.
|
|
7
|
+
*/
|
|
8
|
+
export interface WorkProfile {
|
|
9
|
+
/** Folded stack format for flamegraph tools. */
|
|
10
|
+
folded: string;
|
|
11
|
+
/** Markdown summary of profiling results. */
|
|
12
|
+
summary: string;
|
|
13
|
+
/** SVG flamegraph (if generation succeeded). */
|
|
14
|
+
svg: string | null;
|
|
15
|
+
/** Total work time in milliseconds. */
|
|
16
|
+
totalMs: number;
|
|
17
|
+
/** Number of samples collected. */
|
|
18
|
+
sampleCount: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
declare module "../bindings" {
|
|
22
|
+
interface NativeBindings {
|
|
23
|
+
/**
|
|
24
|
+
* Get work profile data from the last N seconds.
|
|
25
|
+
*
|
|
26
|
+
* Always-on profiling - samples are collected into a circular buffer.
|
|
27
|
+
* Call this to retrieve recent activity.
|
|
28
|
+
*/
|
|
29
|
+
getWorkProfile(lastSeconds: number): WorkProfile;
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/request-options.ts
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
export interface RequestOptions {
|
|
2
|
-
timeoutMs?: number;
|
|
3
|
-
signal?: AbortSignal;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
function abortReason(signal?: AbortSignal): Error {
|
|
7
|
-
if (!signal || !signal.reason) return new Error("Request aborted");
|
|
8
|
-
if (signal.reason instanceof Error) return signal.reason;
|
|
9
|
-
return new Error("Request aborted", { cause: signal.reason });
|
|
10
|
-
}
|
|
11
|
-
export async function wrapRequestOptions<T>(fn: () => Promise<T>, options?: RequestOptions): Promise<T> {
|
|
12
|
-
const timeoutMs = options?.timeoutMs ?? 0;
|
|
13
|
-
const signal = options?.signal;
|
|
14
|
-
|
|
15
|
-
// Fast path: no timeout + no signal
|
|
16
|
-
if (!signal && timeoutMs <= 0) return fn();
|
|
17
|
-
|
|
18
|
-
// If already aborted, fail immediately
|
|
19
|
-
if (signal?.aborted) throw abortReason(signal);
|
|
20
|
-
|
|
21
|
-
// If we only have an abort signal and no timeout, keep it simple.
|
|
22
|
-
if (signal && timeoutMs <= 0) {
|
|
23
|
-
return withAbortSignal(fn, signal);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return withTimeoutAndOptionalAbort(fn, timeoutMs, signal);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function withAbortSignal<T>(fn: () => Promise<T>, signal: AbortSignal): Promise<T> {
|
|
30
|
-
return new Promise<T>((resolve, reject) => {
|
|
31
|
-
const onAbort = () => {
|
|
32
|
-
signal.removeEventListener("abort", onAbort);
|
|
33
|
-
reject(abortReason(signal));
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
37
|
-
|
|
38
|
-
// If it races and aborts right after addEventListener, `once` handles it,
|
|
39
|
-
// but we still want to short-circuit.
|
|
40
|
-
if (signal.aborted) return onAbort();
|
|
41
|
-
|
|
42
|
-
fn().then(
|
|
43
|
-
v => {
|
|
44
|
-
signal.removeEventListener("abort", onAbort);
|
|
45
|
-
resolve(v);
|
|
46
|
-
},
|
|
47
|
-
err => {
|
|
48
|
-
signal.removeEventListener("abort", onAbort);
|
|
49
|
-
reject(err);
|
|
50
|
-
},
|
|
51
|
-
);
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function withTimeoutAndOptionalAbort<T>(fn: () => Promise<T>, timeoutMs: number, signal?: AbortSignal): Promise<T> {
|
|
56
|
-
return new Promise<T>((resolve, reject) => {
|
|
57
|
-
let settled = false;
|
|
58
|
-
|
|
59
|
-
let timeoutId: ReturnType<typeof setTimeout> | undefined;
|
|
60
|
-
const cleanup = () => {
|
|
61
|
-
if (timeoutId) {
|
|
62
|
-
clearTimeout(timeoutId);
|
|
63
|
-
timeoutId = undefined;
|
|
64
|
-
}
|
|
65
|
-
if (signal) signal.removeEventListener("abort", onAbort);
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
const settle = (ok: boolean, value: any) => {
|
|
69
|
-
if (settled) return;
|
|
70
|
-
settled = true;
|
|
71
|
-
cleanup();
|
|
72
|
-
ok ? resolve(value as T) : reject(value);
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const onAbort = () => settle(false, abortReason(signal!));
|
|
76
|
-
|
|
77
|
-
// timeout
|
|
78
|
-
timeoutId = setTimeout(() => {
|
|
79
|
-
settle(false, new Error(`Request timed out after ${timeoutMs}ms`));
|
|
80
|
-
}, timeoutMs);
|
|
81
|
-
|
|
82
|
-
// abort (optional)
|
|
83
|
-
if (signal) {
|
|
84
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
85
|
-
if (signal.aborted) return onAbort();
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// run
|
|
89
|
-
fn().then(
|
|
90
|
-
v => settle(true, v),
|
|
91
|
-
err => settle(false, err),
|
|
92
|
-
);
|
|
93
|
-
});
|
|
94
|
-
}
|