@ricsam/quickjs-core 0.2.12 → 0.2.14
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/dist/cjs/class-builder.cjs +24 -2
- package/dist/cjs/class-builder.cjs.map +3 -3
- package/dist/cjs/class-helpers.cjs +16 -2
- package/dist/cjs/class-helpers.cjs.map +3 -3
- package/dist/cjs/coerce.cjs +320 -0
- package/dist/cjs/coerce.cjs.map +10 -0
- package/dist/cjs/index.cjs +18 -2
- package/dist/cjs/index.cjs.map +3 -3
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/unmarshal.cjs +105 -6
- package/dist/cjs/unmarshal.cjs.map +3 -3
- package/dist/cjs/url.cjs +109 -16
- package/dist/cjs/url.cjs.map +3 -3
- package/dist/mjs/class-builder.mjs +24 -2
- package/dist/mjs/class-builder.mjs.map +3 -3
- package/dist/mjs/class-helpers.mjs +16 -2
- package/dist/mjs/class-helpers.mjs.map +3 -3
- package/dist/mjs/coerce.mjs +292 -0
- package/dist/mjs/coerce.mjs.map +10 -0
- package/dist/mjs/index.mjs +36 -5
- package/dist/mjs/index.mjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/unmarshal.mjs +105 -6
- package/dist/mjs/unmarshal.mjs.map +3 -3
- package/dist/mjs/url.mjs +109 -16
- package/dist/mjs/url.mjs.map +3 -3
- package/dist/types/class-helpers.d.ts +32 -0
- package/dist/types/coerce.d.ts +98 -0
- package/dist/types/index.d.ts +5 -3
- package/dist/types/url.d.ts +9 -1
- package/package.json +1 -1
package/dist/mjs/url.mjs
CHANGED
|
@@ -1,22 +1,31 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/core/src/url.ts
|
|
3
3
|
import { defineClass } from "./class-builder.mjs";
|
|
4
|
+
function rebuildURLHref(state) {
|
|
5
|
+
let userinfo = "";
|
|
6
|
+
if (state.username) {
|
|
7
|
+
userinfo = state.password ? `${state.username}:${state.password}@` : `${state.username}@`;
|
|
8
|
+
}
|
|
9
|
+
state.href = `${state.protocol}//${userinfo}${state.host}${state.pathname}${state.search}${state.hash}`;
|
|
10
|
+
state.origin = `${state.protocol}//${state.host}`;
|
|
11
|
+
}
|
|
4
12
|
function createURLClass(context, stateMap) {
|
|
5
13
|
return defineClass(context, stateMap, {
|
|
6
14
|
name: "URL",
|
|
7
15
|
construct: (args) => {
|
|
8
|
-
const
|
|
16
|
+
const urlInput = args[0];
|
|
9
17
|
const base = args[1];
|
|
10
|
-
if (
|
|
18
|
+
if (urlInput === undefined) {
|
|
11
19
|
throw new TypeError("Failed to construct 'URL': 1 argument required, but only 0 present.");
|
|
12
20
|
}
|
|
21
|
+
const urlString = typeof urlInput === "object" && urlInput !== null && "href" in urlInput ? urlInput.href : String(urlInput);
|
|
13
22
|
let parsed;
|
|
14
23
|
try {
|
|
15
24
|
if (base !== undefined) {
|
|
16
25
|
const baseStr = typeof base === "object" && base !== null && "href" in base ? base.href : String(base);
|
|
17
|
-
parsed = new globalThis.URL(
|
|
26
|
+
parsed = new globalThis.URL(urlString, baseStr);
|
|
18
27
|
} else {
|
|
19
|
-
parsed = new globalThis.URL(
|
|
28
|
+
parsed = new globalThis.URL(urlString);
|
|
20
29
|
}
|
|
21
30
|
} catch (e) {
|
|
22
31
|
throw new TypeError(`Failed to construct 'URL': Invalid URL`);
|
|
@@ -39,21 +48,56 @@ function createURLClass(context, stateMap) {
|
|
|
39
48
|
hash: {
|
|
40
49
|
get() {
|
|
41
50
|
return this.hash;
|
|
51
|
+
},
|
|
52
|
+
set(value) {
|
|
53
|
+
this.hash = value.startsWith("#") ? value : `#${value}`;
|
|
54
|
+
rebuildURLHref(this);
|
|
42
55
|
}
|
|
43
56
|
},
|
|
44
57
|
host: {
|
|
45
58
|
get() {
|
|
46
59
|
return this.host;
|
|
60
|
+
},
|
|
61
|
+
set(value) {
|
|
62
|
+
const colonIndex = value.lastIndexOf(":");
|
|
63
|
+
if (colonIndex > -1 && !value.includes("]", colonIndex)) {
|
|
64
|
+
this.hostname = value.slice(0, colonIndex);
|
|
65
|
+
this.port = value.slice(colonIndex + 1);
|
|
66
|
+
} else {
|
|
67
|
+
this.hostname = value;
|
|
68
|
+
this.port = "";
|
|
69
|
+
}
|
|
70
|
+
this.host = value;
|
|
71
|
+
rebuildURLHref(this);
|
|
47
72
|
}
|
|
48
73
|
},
|
|
49
74
|
hostname: {
|
|
50
75
|
get() {
|
|
51
76
|
return this.hostname;
|
|
77
|
+
},
|
|
78
|
+
set(value) {
|
|
79
|
+
this.hostname = value;
|
|
80
|
+
this.host = this.port ? `${value}:${this.port}` : value;
|
|
81
|
+
rebuildURLHref(this);
|
|
52
82
|
}
|
|
53
83
|
},
|
|
54
84
|
href: {
|
|
55
85
|
get() {
|
|
56
86
|
return this.href;
|
|
87
|
+
},
|
|
88
|
+
set(value) {
|
|
89
|
+
const parsed = new globalThis.URL(value);
|
|
90
|
+
this.hash = parsed.hash;
|
|
91
|
+
this.host = parsed.host;
|
|
92
|
+
this.hostname = parsed.hostname;
|
|
93
|
+
this.href = parsed.href;
|
|
94
|
+
this.origin = parsed.origin;
|
|
95
|
+
this.password = parsed.password;
|
|
96
|
+
this.pathname = parsed.pathname;
|
|
97
|
+
this.port = parsed.port;
|
|
98
|
+
this.protocol = parsed.protocol;
|
|
99
|
+
this.search = parsed.search;
|
|
100
|
+
this.username = parsed.username;
|
|
57
101
|
}
|
|
58
102
|
},
|
|
59
103
|
origin: {
|
|
@@ -64,31 +108,57 @@ function createURLClass(context, stateMap) {
|
|
|
64
108
|
password: {
|
|
65
109
|
get() {
|
|
66
110
|
return this.password;
|
|
111
|
+
},
|
|
112
|
+
set(value) {
|
|
113
|
+
this.password = value;
|
|
114
|
+
rebuildURLHref(this);
|
|
67
115
|
}
|
|
68
116
|
},
|
|
69
117
|
pathname: {
|
|
70
118
|
get() {
|
|
71
119
|
return this.pathname;
|
|
120
|
+
},
|
|
121
|
+
set(value) {
|
|
122
|
+
this.pathname = value.startsWith("/") ? value : `/${value}`;
|
|
123
|
+
rebuildURLHref(this);
|
|
72
124
|
}
|
|
73
125
|
},
|
|
74
126
|
port: {
|
|
75
127
|
get() {
|
|
76
128
|
return this.port;
|
|
129
|
+
},
|
|
130
|
+
set(value) {
|
|
131
|
+
this.port = value;
|
|
132
|
+
this.host = value ? `${this.hostname}:${value}` : this.hostname;
|
|
133
|
+
rebuildURLHref(this);
|
|
77
134
|
}
|
|
78
135
|
},
|
|
79
136
|
protocol: {
|
|
80
137
|
get() {
|
|
81
138
|
return this.protocol;
|
|
139
|
+
},
|
|
140
|
+
set(value) {
|
|
141
|
+
this.protocol = value.endsWith(":") ? value : `${value}:`;
|
|
142
|
+
this.origin = `${this.protocol}//${this.host}`;
|
|
143
|
+
rebuildURLHref(this);
|
|
82
144
|
}
|
|
83
145
|
},
|
|
84
146
|
search: {
|
|
85
147
|
get() {
|
|
86
148
|
return this.search;
|
|
149
|
+
},
|
|
150
|
+
set(value) {
|
|
151
|
+
this.search = value && !value.startsWith("?") ? `?${value}` : value;
|
|
152
|
+
rebuildURLHref(this);
|
|
87
153
|
}
|
|
88
154
|
},
|
|
89
155
|
username: {
|
|
90
156
|
get() {
|
|
91
157
|
return this.username;
|
|
158
|
+
},
|
|
159
|
+
set(value) {
|
|
160
|
+
this.username = value;
|
|
161
|
+
rebuildURLHref(this);
|
|
92
162
|
}
|
|
93
163
|
}
|
|
94
164
|
},
|
|
@@ -98,9 +168,6 @@ function createURLClass(context, stateMap) {
|
|
|
98
168
|
},
|
|
99
169
|
toJSON() {
|
|
100
170
|
return this.href;
|
|
101
|
-
},
|
|
102
|
-
__getSearch__() {
|
|
103
|
-
return this.search;
|
|
104
171
|
}
|
|
105
172
|
},
|
|
106
173
|
staticMethods: {
|
|
@@ -119,18 +186,42 @@ function createURLClass(context, stateMap) {
|
|
|
119
186
|
}
|
|
120
187
|
});
|
|
121
188
|
}
|
|
122
|
-
function
|
|
189
|
+
function addURLSearchParamsLinkage(context) {
|
|
123
190
|
const result = context.evalCode(`
|
|
124
191
|
(function() {
|
|
125
|
-
const searchParamsCache = new Map();
|
|
126
|
-
|
|
127
192
|
Object.defineProperty(URL.prototype, 'searchParams', {
|
|
128
193
|
get: function() {
|
|
129
|
-
|
|
130
|
-
if (!
|
|
131
|
-
|
|
194
|
+
// Cache the URLSearchParams instance on first access
|
|
195
|
+
if (!this._cachedSearchParams) {
|
|
196
|
+
const url = this;
|
|
197
|
+
const params = new URLSearchParams(this.search);
|
|
198
|
+
|
|
199
|
+
// Wrap mutating methods to sync back to URL
|
|
200
|
+
const originalSet = params.set.bind(params);
|
|
201
|
+
const originalAppend = params.append.bind(params);
|
|
202
|
+
const originalDelete = params.delete.bind(params);
|
|
203
|
+
const originalSort = params.sort.bind(params);
|
|
204
|
+
|
|
205
|
+
params.set = function(name, value) {
|
|
206
|
+
originalSet(name, value);
|
|
207
|
+
url.search = this.toString();
|
|
208
|
+
};
|
|
209
|
+
params.append = function(name, value) {
|
|
210
|
+
originalAppend(name, value);
|
|
211
|
+
url.search = this.toString();
|
|
212
|
+
};
|
|
213
|
+
params.delete = function(name, value) {
|
|
214
|
+
originalDelete(name, value);
|
|
215
|
+
url.search = this.toString();
|
|
216
|
+
};
|
|
217
|
+
params.sort = function() {
|
|
218
|
+
originalSort();
|
|
219
|
+
url.search = this.toString();
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
this._cachedSearchParams = params;
|
|
132
223
|
}
|
|
133
|
-
return
|
|
224
|
+
return this._cachedSearchParams;
|
|
134
225
|
},
|
|
135
226
|
enumerable: true,
|
|
136
227
|
configurable: true
|
|
@@ -140,13 +231,15 @@ function addURLSearchParamsGetter(context) {
|
|
|
140
231
|
if (result.error) {
|
|
141
232
|
const err = context.dump(result.error);
|
|
142
233
|
result.error.dispose();
|
|
143
|
-
throw new Error(`Failed to
|
|
234
|
+
throw new Error(`Failed to setup URL/URLSearchParams linkage: ${JSON.stringify(err)}`);
|
|
144
235
|
}
|
|
145
236
|
result.value.dispose();
|
|
146
237
|
}
|
|
238
|
+
var addURLSearchParamsGetter = addURLSearchParamsLinkage;
|
|
147
239
|
export {
|
|
148
240
|
createURLClass,
|
|
241
|
+
addURLSearchParamsLinkage,
|
|
149
242
|
addURLSearchParamsGetter
|
|
150
243
|
};
|
|
151
244
|
|
|
152
|
-
//# debugId=
|
|
245
|
+
//# debugId=3CB02D6BB183083C64756E2164756E21
|
package/dist/mjs/url.mjs.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/url.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport type { StateMap } from \"./types.mjs\";\nimport { defineClass } from \"./class-builder.mjs\";\n\n/**\n * Internal state for URL\n */\nexport interface URLState {\n hash: string;\n host: string;\n hostname: string;\n href: string;\n origin: string;\n password: string;\n pathname: string;\n port: string;\n protocol: string;\n search: string;\n username: string;\n}\n\n/**\n * Create the URL class for QuickJS\n *\n * Note: The searchParams property is added separately via evalCode\n * after this class is registered, as it needs to return a URLSearchParams instance.\n */\nexport function createURLClass(\n context: QuickJSContext,\n stateMap: StateMap\n): QuickJSHandle {\n return defineClass<URLState>(context, stateMap, {\n name: \"URL\",\n construct: (args) => {\n const
|
|
5
|
+
"import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport type { StateMap } from \"./types.mjs\";\nimport { defineClass } from \"./class-builder.mjs\";\n\n/**\n * Internal state for URL\n */\nexport interface URLState {\n hash: string;\n host: string;\n hostname: string;\n href: string;\n origin: string;\n password: string;\n pathname: string;\n port: string;\n protocol: string;\n search: string;\n username: string;\n}\n\n/**\n * Helper to rebuild the href from URL components\n */\nfunction rebuildURLHref(state: URLState): void {\n // Build userinfo part\n let userinfo = \"\";\n if (state.username) {\n userinfo = state.password\n ? `${state.username}:${state.password}@`\n : `${state.username}@`;\n }\n\n // Build the href\n state.href = `${state.protocol}//${userinfo}${state.host}${state.pathname}${state.search}${state.hash}`;\n\n // Update origin\n state.origin = `${state.protocol}//${state.host}`;\n}\n\n/**\n * Create the URL class for QuickJS\n *\n * Note: The searchParams property is added separately via evalCode\n * after this class is registered, as it needs to return a URLSearchParams instance.\n */\nexport function createURLClass(\n context: QuickJSContext,\n stateMap: StateMap\n): QuickJSHandle {\n return defineClass<URLState>(context, stateMap, {\n name: \"URL\",\n construct: (args) => {\n const urlInput = args[0];\n const base = args[1];\n\n if (urlInput === undefined) {\n throw new TypeError(\"Failed to construct 'URL': 1 argument required, but only 0 present.\");\n }\n\n // Handle URL object as first argument (extract href)\n const urlString = typeof urlInput === \"object\" && urlInput !== null && \"href\" in urlInput\n ? (urlInput as URLState).href\n : String(urlInput);\n\n let parsed: globalThis.URL;\n try {\n if (base !== undefined) {\n // Handle base URL\n const baseStr = typeof base === \"object\" && base !== null && \"href\" in base\n ? (base as URLState).href\n : String(base);\n parsed = new globalThis.URL(urlString, baseStr);\n } else {\n parsed = new globalThis.URL(urlString);\n }\n } catch (e) {\n throw new TypeError(`Failed to construct 'URL': Invalid URL`);\n }\n\n return {\n hash: parsed.hash,\n host: parsed.host,\n hostname: parsed.hostname,\n href: parsed.href,\n origin: parsed.origin,\n password: parsed.password,\n pathname: parsed.pathname,\n port: parsed.port,\n protocol: parsed.protocol,\n search: parsed.search,\n username: parsed.username,\n };\n },\n properties: {\n hash: {\n get(this: URLState) {\n return this.hash;\n },\n set(this: URLState, value: string) {\n this.hash = value.startsWith(\"#\") ? value : `#${value}`;\n rebuildURLHref(this);\n },\n },\n host: {\n get(this: URLState) {\n return this.host;\n },\n set(this: URLState, value: string) {\n // Parse host into hostname and port\n const colonIndex = value.lastIndexOf(\":\");\n if (colonIndex > -1 && !value.includes(\"]\", colonIndex)) {\n this.hostname = value.slice(0, colonIndex);\n this.port = value.slice(colonIndex + 1);\n } else {\n this.hostname = value;\n this.port = \"\";\n }\n this.host = value;\n rebuildURLHref(this);\n },\n },\n hostname: {\n get(this: URLState) {\n return this.hostname;\n },\n set(this: URLState, value: string) {\n this.hostname = value;\n this.host = this.port ? `${value}:${this.port}` : value;\n rebuildURLHref(this);\n },\n },\n href: {\n get(this: URLState) {\n return this.href;\n },\n set(this: URLState, value: string) {\n // Parse the new href and update all properties\n const parsed = new globalThis.URL(value);\n this.hash = parsed.hash;\n this.host = parsed.host;\n this.hostname = parsed.hostname;\n this.href = parsed.href;\n this.origin = parsed.origin;\n this.password = parsed.password;\n this.pathname = parsed.pathname;\n this.port = parsed.port;\n this.protocol = parsed.protocol;\n this.search = parsed.search;\n this.username = parsed.username;\n },\n },\n origin: {\n get(this: URLState) {\n return this.origin;\n },\n // origin is read-only per spec\n },\n password: {\n get(this: URLState) {\n return this.password;\n },\n set(this: URLState, value: string) {\n this.password = value;\n rebuildURLHref(this);\n },\n },\n pathname: {\n get(this: URLState) {\n return this.pathname;\n },\n set(this: URLState, value: string) {\n this.pathname = value.startsWith(\"/\") ? value : `/${value}`;\n rebuildURLHref(this);\n },\n },\n port: {\n get(this: URLState) {\n return this.port;\n },\n set(this: URLState, value: string) {\n this.port = value;\n this.host = value ? `${this.hostname}:${value}` : this.hostname;\n rebuildURLHref(this);\n },\n },\n protocol: {\n get(this: URLState) {\n return this.protocol;\n },\n set(this: URLState, value: string) {\n this.protocol = value.endsWith(\":\") ? value : `${value}:`;\n // Update origin\n this.origin = `${this.protocol}//${this.host}`;\n rebuildURLHref(this);\n },\n },\n search: {\n get(this: URLState) {\n return this.search;\n },\n set(this: URLState, value: string) {\n this.search = value && !value.startsWith(\"?\") ? `?${value}` : value;\n rebuildURLHref(this);\n },\n },\n username: {\n get(this: URLState) {\n return this.username;\n },\n set(this: URLState, value: string) {\n this.username = value;\n rebuildURLHref(this);\n },\n },\n },\n methods: {\n toString(this: URLState): string {\n return this.href;\n },\n toJSON(this: URLState): string {\n return this.href;\n },\n },\n staticMethods: {\n canParse(url: unknown, base?: unknown): boolean {\n try {\n if (base !== undefined) {\n new globalThis.URL(String(url), String(base));\n } else {\n new globalThis.URL(String(url));\n }\n return true;\n } catch {\n return false;\n }\n },\n },\n });\n}\n\n/**\n * Add searchParams getter to URL prototype using evalCode\n * This must be called after both URL and URLSearchParams are registered as globals\n *\n * The getter creates a URLSearchParams instance on first access and wraps its\n * mutating methods (set, append, delete, sort) to sync changes back to the URL.\n * This eliminates cross-module coupling by keeping all sync logic in JavaScript.\n */\nexport function addURLSearchParamsLinkage(context: QuickJSContext): void {\n const result = context.evalCode(`\n (function() {\n Object.defineProperty(URL.prototype, 'searchParams', {\n get: function() {\n // Cache the URLSearchParams instance on first access\n if (!this._cachedSearchParams) {\n const url = this;\n const params = new URLSearchParams(this.search);\n\n // Wrap mutating methods to sync back to URL\n const originalSet = params.set.bind(params);\n const originalAppend = params.append.bind(params);\n const originalDelete = params.delete.bind(params);\n const originalSort = params.sort.bind(params);\n\n params.set = function(name, value) {\n originalSet(name, value);\n url.search = this.toString();\n };\n params.append = function(name, value) {\n originalAppend(name, value);\n url.search = this.toString();\n };\n params.delete = function(name, value) {\n originalDelete(name, value);\n url.search = this.toString();\n };\n params.sort = function() {\n originalSort();\n url.search = this.toString();\n };\n\n this._cachedSearchParams = params;\n }\n return this._cachedSearchParams;\n },\n enumerable: true,\n configurable: true\n });\n })();\n `);\n\n if (result.error) {\n const err = context.dump(result.error);\n result.error.dispose();\n throw new Error(`Failed to setup URL/URLSearchParams linkage: ${JSON.stringify(err)}`);\n }\n result.value.dispose();\n}\n\n/**\n * @deprecated Use addURLSearchParamsLinkage instead\n */\nexport const addURLSearchParamsGetter = addURLSearchParamsLinkage;\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;AAEA;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "3CB02D6BB183083C64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -43,3 +43,35 @@ export declare function getInstanceId(value: unknown): number | undefined;
|
|
|
43
43
|
* Get the class name from an unmarshalled value if it's a defineClass instance
|
|
44
44
|
*/
|
|
45
45
|
export declare function getClassName(value: unknown): string | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Interface for typed class instance with specific class name
|
|
48
|
+
*/
|
|
49
|
+
export interface TypedClassInstance<T extends string> extends DefineClassInstance {
|
|
50
|
+
__className__: T;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Create a type guard for a specific class name
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* const isRequest = createClassTypeGuard<"Request">("Request");
|
|
57
|
+
* if (isRequest(value)) {
|
|
58
|
+
* // value is TypedClassInstance<"Request">
|
|
59
|
+
* }
|
|
60
|
+
*/
|
|
61
|
+
export declare function createClassTypeGuard<T extends string>(className: T): (value: unknown) => value is TypedClassInstance<T>;
|
|
62
|
+
/**
|
|
63
|
+
* Pre-built type guard for Request instances
|
|
64
|
+
*/
|
|
65
|
+
export declare const isUnmarshalledRequest: (value: unknown) => value is TypedClassInstance<"Request">;
|
|
66
|
+
/**
|
|
67
|
+
* Pre-built type guard for Response instances
|
|
68
|
+
*/
|
|
69
|
+
export declare const isUnmarshalledResponse: (value: unknown) => value is TypedClassInstance<"Response">;
|
|
70
|
+
/**
|
|
71
|
+
* Pre-built type guard for Headers instances
|
|
72
|
+
*/
|
|
73
|
+
export declare const isUnmarshalledHeaders: (value: unknown) => value is TypedClassInstance<"Headers">;
|
|
74
|
+
/**
|
|
75
|
+
* Pre-built type guard for FormData instances
|
|
76
|
+
*/
|
|
77
|
+
export declare const isUnmarshalledFormData: (value: unknown) => value is TypedClassInstance<"FormData">;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coercion system for QuickJS class instances
|
|
3
|
+
*
|
|
4
|
+
* Provides a Zod-like API for detecting and extracting values from
|
|
5
|
+
* class instances, plain objects, and primitive values.
|
|
6
|
+
*
|
|
7
|
+
* This enables consistent handling of class instances across the codebase,
|
|
8
|
+
* reducing duplication and ensuring reliable type detection.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Result of a coercion attempt
|
|
12
|
+
*/
|
|
13
|
+
export type CoercionResult<T> = {
|
|
14
|
+
success: true;
|
|
15
|
+
value: T;
|
|
16
|
+
} | {
|
|
17
|
+
success: false;
|
|
18
|
+
error: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* A coercer that can transform unknown values into a specific type
|
|
22
|
+
*/
|
|
23
|
+
export interface Coercer<T> {
|
|
24
|
+
/** The name of this coercer (for error messages) */
|
|
25
|
+
readonly name: string;
|
|
26
|
+
/** Attempt to coerce a value, returning a result object */
|
|
27
|
+
safeParse(value: unknown): CoercionResult<T>;
|
|
28
|
+
/** Coerce a value, throwing on failure */
|
|
29
|
+
parse(value: unknown): T;
|
|
30
|
+
/** Check if a value can be coerced without actually coercing */
|
|
31
|
+
is(value: unknown): boolean;
|
|
32
|
+
/** Create a new coercer with a fallback */
|
|
33
|
+
or<U>(other: Coercer<U>): Coercer<T | U>;
|
|
34
|
+
/** Transform the coerced value */
|
|
35
|
+
transform<U>(fn: (value: T) => U): Coercer<U>;
|
|
36
|
+
/** Make the coercer optional (allows undefined/null) */
|
|
37
|
+
optional(): Coercer<T | undefined>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Create a base coercer from detection and extraction functions
|
|
41
|
+
*/
|
|
42
|
+
export declare function createCoercer<T>(name: string, detect: (value: unknown) => boolean, extract: (value: unknown) => T): Coercer<T>;
|
|
43
|
+
/**
|
|
44
|
+
* Create a coercer for a QuickJS class instance
|
|
45
|
+
*/
|
|
46
|
+
export declare function classCoercer<TState>(className: string): Coercer<TState>;
|
|
47
|
+
/**
|
|
48
|
+
* Coerce a value that could be a class instance OR have a specific shape
|
|
49
|
+
*/
|
|
50
|
+
export declare function instanceOrShape<TState, TShape>(className: string, shapeCheck: (value: unknown) => value is TShape, shapeToState: (value: TShape) => TState): Coercer<TState>;
|
|
51
|
+
export interface URLCoerced {
|
|
52
|
+
href: string;
|
|
53
|
+
protocol: string;
|
|
54
|
+
host: string;
|
|
55
|
+
hostname: string;
|
|
56
|
+
port: string;
|
|
57
|
+
pathname: string;
|
|
58
|
+
search: string;
|
|
59
|
+
hash: string;
|
|
60
|
+
origin: string;
|
|
61
|
+
username: string;
|
|
62
|
+
password: string;
|
|
63
|
+
}
|
|
64
|
+
/** Coerce a value to URL data */
|
|
65
|
+
export declare const coerceURL: Coercer<URLCoerced>;
|
|
66
|
+
/** Get just the href string from a URL-like value */
|
|
67
|
+
export declare function coerceToURLString(value: unknown): string;
|
|
68
|
+
export interface HeadersCoerced {
|
|
69
|
+
headers: Map<string, string[]>;
|
|
70
|
+
}
|
|
71
|
+
/** Coerce a value to Headers data */
|
|
72
|
+
export declare const coerceHeaders: Coercer<HeadersCoerced>;
|
|
73
|
+
/** Coerce body to Uint8Array */
|
|
74
|
+
export declare function coerceBody(value: unknown): Uint8Array | null;
|
|
75
|
+
export interface RequestInitCoerced {
|
|
76
|
+
method?: string;
|
|
77
|
+
headersState?: HeadersCoerced;
|
|
78
|
+
body?: Uint8Array | null;
|
|
79
|
+
cache?: string;
|
|
80
|
+
credentials?: string;
|
|
81
|
+
destination?: string;
|
|
82
|
+
integrity?: string;
|
|
83
|
+
keepalive?: boolean;
|
|
84
|
+
mode?: string;
|
|
85
|
+
redirect?: string;
|
|
86
|
+
referrer?: string;
|
|
87
|
+
referrerPolicy?: string;
|
|
88
|
+
signal?: unknown;
|
|
89
|
+
}
|
|
90
|
+
/** Coerce a value to Request init data (for use as RequestInit second arg) */
|
|
91
|
+
export declare const coerceRequestInit: Coercer<RequestInitCoerced>;
|
|
92
|
+
export interface ResponseInitCoerced {
|
|
93
|
+
status?: number;
|
|
94
|
+
statusText?: string;
|
|
95
|
+
headersState?: HeadersCoerced;
|
|
96
|
+
}
|
|
97
|
+
/** Coerce a value to Response init data */
|
|
98
|
+
export declare const coerceResponseInit: Coercer<ResponseInitCoerced>;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -36,8 +36,8 @@ export { marshal, isHandle, getHandleType } from "./marshal.ts";
|
|
|
36
36
|
export { unmarshal, cleanupUnmarshaledHandles } from "./unmarshal.ts";
|
|
37
37
|
export { defineFunction, defineAsyncFunction } from "./function-builder.ts";
|
|
38
38
|
export { defineClass, createStateMap, getState, setState, getInstanceState, setInstanceState, getInstanceStateById, cleanupInstanceState, clearAllInstanceState, } from "./class-builder.ts";
|
|
39
|
-
export { isDefineClassInstance, isInstanceOf, getClassInstanceState, getInstanceId, getClassName, } from "./class-helpers.ts";
|
|
40
|
-
export type { DefineClassInstance } from "./class-helpers.ts";
|
|
39
|
+
export { isDefineClassInstance, isInstanceOf, getClassInstanceState, getInstanceId, getClassName, createClassTypeGuard, isUnmarshalledRequest, isUnmarshalledResponse, isUnmarshalledHeaders, isUnmarshalledFormData, } from "./class-helpers.ts";
|
|
40
|
+
export type { DefineClassInstance, TypedClassInstance } from "./class-helpers.ts";
|
|
41
41
|
export { nextInstanceId, registerInstance, getInstanceMetadata, getInstanceClassName, cleanupInstanceState as cleanupInstanceStateById, } from "./instance-state.ts";
|
|
42
42
|
export type { InstanceMetadata } from "./instance-state.ts";
|
|
43
43
|
export { createReadableStream, consumeReadableStream, } from "./streams/readable-stream.ts";
|
|
@@ -46,5 +46,7 @@ export { createBlob } from "./blob.ts";
|
|
|
46
46
|
export { createFile } from "./file.ts";
|
|
47
47
|
export { createURLSearchParamsClass } from "./url-search-params.ts";
|
|
48
48
|
export type { URLSearchParamsState } from "./url-search-params.ts";
|
|
49
|
-
export { createURLClass, addURLSearchParamsGetter } from "./url.ts";
|
|
49
|
+
export { createURLClass, addURLSearchParamsLinkage, addURLSearchParamsGetter } from "./url.ts";
|
|
50
50
|
export type { URLState } from "./url.ts";
|
|
51
|
+
export { createCoercer, classCoercer, instanceOrShape, coerceURL, coerceToURLString, coerceHeaders, coerceBody, coerceRequestInit, coerceResponseInit, } from "./coerce.ts";
|
|
52
|
+
export type { Coercer, CoercionResult, URLCoerced, HeadersCoerced, RequestInitCoerced, ResponseInitCoerced, } from "./coerce.ts";
|
package/dist/types/url.d.ts
CHANGED
|
@@ -26,5 +26,13 @@ export declare function createURLClass(context: QuickJSContext, stateMap: StateM
|
|
|
26
26
|
/**
|
|
27
27
|
* Add searchParams getter to URL prototype using evalCode
|
|
28
28
|
* This must be called after both URL and URLSearchParams are registered as globals
|
|
29
|
+
*
|
|
30
|
+
* The getter creates a URLSearchParams instance on first access and wraps its
|
|
31
|
+
* mutating methods (set, append, delete, sort) to sync changes back to the URL.
|
|
32
|
+
* This eliminates cross-module coupling by keeping all sync logic in JavaScript.
|
|
33
|
+
*/
|
|
34
|
+
export declare function addURLSearchParamsLinkage(context: QuickJSContext): void;
|
|
35
|
+
/**
|
|
36
|
+
* @deprecated Use addURLSearchParamsLinkage instead
|
|
29
37
|
*/
|
|
30
|
-
export declare
|
|
38
|
+
export declare const addURLSearchParamsGetter: typeof addURLSearchParamsLinkage;
|