@ricsam/quickjs-fetch 0.0.1 → 0.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.
Files changed (59) hide show
  1. package/README.md +109 -43
  2. package/dist/cjs/abort-controller.cjs +212 -0
  3. package/dist/cjs/abort-controller.cjs.map +10 -0
  4. package/dist/cjs/fetch.cjs +199 -0
  5. package/dist/cjs/fetch.cjs.map +10 -0
  6. package/dist/cjs/form-data.cjs +289 -0
  7. package/dist/cjs/form-data.cjs.map +10 -0
  8. package/dist/cjs/handle.cjs +248 -0
  9. package/dist/cjs/handle.cjs.map +10 -0
  10. package/dist/cjs/headers.cjs +196 -0
  11. package/dist/cjs/headers.cjs.map +10 -0
  12. package/dist/cjs/index.cjs +47 -0
  13. package/dist/cjs/index.cjs.map +10 -0
  14. package/dist/cjs/package.json +5 -0
  15. package/dist/cjs/request.cjs +315 -0
  16. package/dist/cjs/request.cjs.map +10 -0
  17. package/dist/cjs/response.cjs +315 -0
  18. package/dist/cjs/response.cjs.map +10 -0
  19. package/dist/cjs/serve.cjs +182 -0
  20. package/dist/cjs/serve.cjs.map +10 -0
  21. package/dist/cjs/setup.cjs +119 -0
  22. package/dist/cjs/setup.cjs.map +10 -0
  23. package/dist/cjs/types.cjs +26 -0
  24. package/dist/cjs/types.cjs.map +9 -0
  25. package/dist/mjs/abort-controller.mjs +181 -0
  26. package/dist/mjs/abort-controller.mjs.map +10 -0
  27. package/dist/mjs/fetch.mjs +168 -0
  28. package/dist/mjs/fetch.mjs.map +10 -0
  29. package/dist/mjs/form-data.mjs +258 -0
  30. package/dist/mjs/form-data.mjs.map +10 -0
  31. package/dist/mjs/handle.mjs +217 -0
  32. package/dist/mjs/handle.mjs.map +10 -0
  33. package/dist/mjs/headers.mjs +165 -0
  34. package/dist/mjs/headers.mjs.map +10 -0
  35. package/dist/mjs/index.mjs +22 -0
  36. package/dist/mjs/index.mjs.map +10 -0
  37. package/dist/mjs/package.json +5 -0
  38. package/dist/mjs/request.mjs +284 -0
  39. package/dist/mjs/request.mjs.map +10 -0
  40. package/dist/mjs/response.mjs +284 -0
  41. package/dist/mjs/response.mjs.map +10 -0
  42. package/dist/mjs/serve.mjs +151 -0
  43. package/dist/mjs/serve.mjs.map +10 -0
  44. package/dist/mjs/setup.mjs +92 -0
  45. package/dist/mjs/setup.mjs.map +10 -0
  46. package/dist/mjs/types.mjs +3 -0
  47. package/dist/mjs/types.mjs.map +9 -0
  48. package/dist/types/globals/abort-controller.d.ts +9 -0
  49. package/dist/types/globals/fetch.d.ts +5 -0
  50. package/dist/types/globals/form-data.d.ts +37 -0
  51. package/dist/types/globals/headers.d.ts +36 -0
  52. package/dist/types/globals/request.d.ts +16 -0
  53. package/dist/types/globals/response.d.ts +25 -0
  54. package/dist/types/globals/serve.d.ts +16 -0
  55. package/dist/types/handle.d.ts +6 -0
  56. package/dist/types/index.d.ts +5 -0
  57. package/dist/types/setup.d.ts +48 -0
  58. package/dist/types/types.d.ts +175 -0
  59. package/package.json +51 -6
@@ -0,0 +1,37 @@
1
+ import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
2
+ import type { StateMap } from "@ricsam/quickjs-core";
3
+ /**
4
+ * Internal state for FormData entries
5
+ * Each entry can have multiple values (same key appended multiple times)
6
+ */
7
+ export interface FormDataEntry {
8
+ name: string;
9
+ value: string | FormDataFileValue;
10
+ }
11
+ export interface FormDataFileValue {
12
+ data: Uint8Array;
13
+ filename: string;
14
+ type: string;
15
+ }
16
+ export interface FormDataState {
17
+ entries: FormDataEntry[];
18
+ }
19
+ /**
20
+ * Create the FormData class for QuickJS
21
+ */
22
+ export declare function createFormDataClass(context: QuickJSContext, stateMap: StateMap): QuickJSHandle;
23
+ /**
24
+ * Parse multipart/form-data body
25
+ */
26
+ export declare function parseMultipartFormData(body: Uint8Array, contentType: string): FormDataState;
27
+ /**
28
+ * Parse URL-encoded form data
29
+ */
30
+ export declare function parseUrlEncodedFormData(body: Uint8Array): FormDataState;
31
+ /**
32
+ * Serialize FormData to multipart/form-data format
33
+ */
34
+ export declare function serializeFormData(state: FormDataState): {
35
+ body: Uint8Array;
36
+ contentType: string;
37
+ };
@@ -0,0 +1,36 @@
1
+ import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
2
+ import type { StateMap } from "@ricsam/quickjs-core";
3
+ import type { HeadersState } from "../types.ts";
4
+ /**
5
+ * Create the Headers class for QuickJS
6
+ */
7
+ export declare function createHeadersClass(context: QuickJSContext, stateMap: StateMap): QuickJSHandle;
8
+ /**
9
+ * Create a HeadersState from a native Headers object
10
+ */
11
+ export declare function createHeadersStateFromNative(headers: Headers): HeadersState;
12
+ /**
13
+ * Convert HeadersState to native Headers
14
+ */
15
+ export declare function headersStateToNative(state: HeadersState): Headers;
16
+ /**
17
+ * Interface for a Headers-like object that can be returned from getters
18
+ */
19
+ export interface HeadersLike {
20
+ headers: Map<string, string[]>;
21
+ append(name: string, value: string): void;
22
+ delete(name: string): void;
23
+ get(name: string): string | null;
24
+ has(name: string): boolean;
25
+ set(name: string, value: string): void;
26
+ entries(): Array<[string, string]>;
27
+ keys(): string[];
28
+ values(): string[];
29
+ forEach(callback: (value: string, key: string) => void): void;
30
+ getSetCookie(): string[];
31
+ }
32
+ /**
33
+ * Create a Headers-like object from HeadersState that has all the Headers methods
34
+ * This is used for getters that need to return an object with Headers API
35
+ */
36
+ export declare function createHeadersLike(state: HeadersState): HeadersLike;
@@ -0,0 +1,16 @@
1
+ import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
2
+ import type { StateMap } from "@ricsam/quickjs-core";
3
+ import type { RequestState } from "../types.ts";
4
+ /**
5
+ * Type for the stream factory function
6
+ */
7
+ type StreamFactory = (source: UnderlyingSource) => QuickJSHandle;
8
+ /**
9
+ * Create the Request class for QuickJS
10
+ */
11
+ export declare function createRequestClass(context: QuickJSContext, stateMap: StateMap, createStream?: StreamFactory): QuickJSHandle;
12
+ /**
13
+ * Create a RequestState from a native Request object
14
+ */
15
+ export declare function createRequestStateFromNative(request: Request): Promise<RequestState>;
16
+ export {};
@@ -0,0 +1,25 @@
1
+ import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
2
+ import type { StateMap } from "@ricsam/quickjs-core";
3
+ import type { ResponseState } from "../types.ts";
4
+ /**
5
+ * Type for the stream factory function
6
+ */
7
+ type StreamFactory = (source: UnderlyingSource) => QuickJSHandle;
8
+ /**
9
+ * Create the Response class for QuickJS
10
+ */
11
+ export declare function createResponseClass(context: QuickJSContext, stateMap: StateMap, createStream?: StreamFactory): QuickJSHandle;
12
+ /**
13
+ * Add static methods to Response class after it's been set on global
14
+ * This must be called after Response and Headers are available on global
15
+ */
16
+ export declare function addResponseStaticMethods(context: QuickJSContext): void;
17
+ /**
18
+ * Convert ResponseState (or unmarshalled Response object) to native Response
19
+ */
20
+ export declare function responseStateToNative(state: ResponseState | Record<string, unknown>): Response;
21
+ /**
22
+ * Create a ResponseState from a native Response
23
+ */
24
+ export declare function createResponseStateFromNative(response: Response): Promise<ResponseState>;
25
+ export {};
@@ -0,0 +1,16 @@
1
+ import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
2
+ import type { StateMap } from "@ricsam/quickjs-core";
3
+ import type { ServeState, WebSocketCommand } from "../types.ts";
4
+ /**
5
+ * Create the ServerWebSocket class for QuickJS
6
+ */
7
+ export declare function createServerWebSocketClass(context: QuickJSContext, stateMap: StateMap, onWebSocketCommand: (cmd: WebSocketCommand) => void): QuickJSHandle;
8
+ /**
9
+ * Create the Server class for QuickJS
10
+ */
11
+ export declare function createServerClass(context: QuickJSContext, stateMap: StateMap, serveState: ServeState): QuickJSHandle;
12
+ /**
13
+ * Create the serve function for QuickJS
14
+ * Uses context.newFunction instead of defineFunction to properly manage handle lifetimes
15
+ */
16
+ export declare function createServeFunction(context: QuickJSContext, stateMap: StateMap, serveState: ServeState): QuickJSHandle;
@@ -0,0 +1,6 @@
1
+ import type { QuickJSContext } from "quickjs-emscripten";
2
+ import type { StateMap, FetchHandle, ServeState } from "./types.ts";
3
+ /**
4
+ * Create the FetchHandle implementation
5
+ */
6
+ export declare function createFetchHandle(context: QuickJSContext, stateMap: StateMap, serveState: ServeState): FetchHandle;
@@ -0,0 +1,5 @@
1
+ export { setupFetch } from "./setup.ts";
2
+ export type { SetupFetchOptions, FetchHandle, WebSocketData, UpgradeRequest, WebSocketCommand, WebSocketOutgoingMessage, WebSocketClose, ServeState, ServerWebSocketState, } from "./types.ts";
3
+ export { createHeadersStateFromNative, headersStateToNative, } from "./globals/headers.ts";
4
+ export { responseStateToNative, createResponseStateFromNative, } from "./globals/response.ts";
5
+ export { createRequestStateFromNative } from "./globals/request.ts";
@@ -0,0 +1,48 @@
1
+ import type { QuickJSContext } from "quickjs-emscripten";
2
+ import type { SetupFetchOptions, FetchHandle } from "./types.ts";
3
+ /**
4
+ * Setup Fetch API in a QuickJS context
5
+ *
6
+ * Injects the following globals:
7
+ * - fetch
8
+ * - Request
9
+ * - Response
10
+ * - Headers
11
+ * - AbortController
12
+ * - AbortSignal
13
+ * - serve
14
+ * - FormData
15
+ *
16
+ * Also sets up Core APIs (Streams, Blob, File) if not already present.
17
+ *
18
+ * **Private globals (internal use):**
19
+ * - `__Server__` - Server class for serve() handler, instantiated via evalCode
20
+ * - `__ServerWebSocket__` - WebSocket class for connection handling
21
+ * - `__scheduleTimeout__` - Host function to schedule AbortSignal.timeout()
22
+ * - `__checkTimeout__` - Host function to check if timeout elapsed
23
+ *
24
+ * These private globals follow the `__Name__` convention and are required for
25
+ * JavaScript code in QuickJS to create class instances via evalCode.
26
+ * See PATTERNS.md section 5 for details.
27
+ *
28
+ * @example
29
+ * const handle = setupFetch(context, {
30
+ * onFetch: async (request) => {
31
+ * // Proxy to real fetch
32
+ * return fetch(request);
33
+ * }
34
+ * });
35
+ *
36
+ * context.evalCode(`
37
+ * serve({
38
+ * fetch(request, server) {
39
+ * return new Response("Hello!");
40
+ * }
41
+ * });
42
+ * `);
43
+ *
44
+ * const response = await handle.dispatchRequest(
45
+ * new Request("http://localhost/")
46
+ * );
47
+ */
48
+ export declare function setupFetch(context: QuickJSContext, options?: SetupFetchOptions): FetchHandle;
@@ -0,0 +1,175 @@
1
+ import type { QuickJSHandle } from "quickjs-emscripten";
2
+ import type { StateMap, CoreHandle } from "@ricsam/quickjs-core";
3
+ export type { StateMap, CoreHandle };
4
+ /**
5
+ * Options for setting up Fetch APIs
6
+ */
7
+ export interface SetupFetchOptions {
8
+ /**
9
+ * Handler for outbound fetch() calls from QuickJS
10
+ * If not provided, fetch() will throw an error
11
+ */
12
+ onFetch?: (request: Request) => Promise<Response>;
13
+ /** Existing state map (creates new one if not provided) */
14
+ stateMap?: StateMap;
15
+ /** Existing core handle (sets up core if not provided) */
16
+ coreHandle?: CoreHandle;
17
+ }
18
+ /**
19
+ * Data associated with a WebSocket connection
20
+ */
21
+ export interface WebSocketData {
22
+ /** User-provided data from server.upgrade() */
23
+ data: unknown;
24
+ /** Connection ID assigned by the host */
25
+ connectionId: string;
26
+ }
27
+ /**
28
+ * Pending upgrade request info
29
+ */
30
+ export interface UpgradeRequest {
31
+ /** Whether an upgrade was requested */
32
+ requested: true;
33
+ /** User data passed to server.upgrade() */
34
+ data: unknown;
35
+ }
36
+ /**
37
+ * Message to send to a WebSocket
38
+ */
39
+ export interface WebSocketOutgoingMessage {
40
+ type: "message";
41
+ connectionId: string;
42
+ data: string | ArrayBuffer;
43
+ }
44
+ /**
45
+ * Close command for a WebSocket
46
+ */
47
+ export interface WebSocketClose {
48
+ type: "close";
49
+ connectionId: string;
50
+ code?: number;
51
+ reason?: string;
52
+ }
53
+ export type WebSocketCommand = WebSocketOutgoingMessage | WebSocketClose;
54
+ /**
55
+ * Internal state for serve() handler
56
+ */
57
+ export interface ServeState {
58
+ fetchHandler: QuickJSHandle | null;
59
+ websocketHandlers: {
60
+ open?: QuickJSHandle;
61
+ message?: QuickJSHandle;
62
+ close?: QuickJSHandle;
63
+ error?: QuickJSHandle;
64
+ };
65
+ pendingUpgrade: UpgradeRequest | null;
66
+ activeConnections: Map<string, ServerWebSocketState>;
67
+ }
68
+ export interface ServerWebSocketState {
69
+ data: unknown;
70
+ readyState: number;
71
+ connectionId: string;
72
+ wsHandle: QuickJSHandle | null;
73
+ }
74
+ /**
75
+ * Handle returned from setupFetch
76
+ */
77
+ export interface FetchHandle {
78
+ /** State map containing all internal states */
79
+ readonly stateMap: StateMap;
80
+ /**
81
+ * Dispatch an HTTP request to the serve() handler
82
+ *
83
+ * @returns Response from the QuickJS handler
84
+ * @throws If no serve() handler is registered
85
+ */
86
+ dispatchRequest(request: Request): Promise<Response>;
87
+ /**
88
+ * Check if the last request resulted in an upgrade request
89
+ * Must be called immediately after dispatchRequest()
90
+ */
91
+ getUpgradeRequest(): UpgradeRequest | null;
92
+ /**
93
+ * Dispatch WebSocket open event
94
+ *
95
+ * @param connectionId Unique ID for this connection (host-assigned)
96
+ * @param data The data object from getUpgradeRequest()
97
+ */
98
+ dispatchWebSocketOpen(connectionId: string, data?: unknown): void;
99
+ /**
100
+ * Dispatch WebSocket message event
101
+ */
102
+ dispatchWebSocketMessage(connectionId: string, message: string | ArrayBuffer): void;
103
+ /**
104
+ * Dispatch WebSocket close event
105
+ */
106
+ dispatchWebSocketClose(connectionId: string, code: number, reason: string): void;
107
+ /**
108
+ * Dispatch WebSocket error event
109
+ */
110
+ dispatchWebSocketError(connectionId: string, error: Error): void;
111
+ /**
112
+ * Register a callback for outgoing WebSocket messages/commands
113
+ * Called when QuickJS code calls ws.send() or ws.close()
114
+ */
115
+ onWebSocketCommand(callback: (command: WebSocketCommand) => void): () => void;
116
+ /**
117
+ * Check if a serve() handler is registered
118
+ */
119
+ hasServeHandler(): boolean;
120
+ /**
121
+ * Dispose all handles and cleanup
122
+ */
123
+ dispose(): void;
124
+ }
125
+ export interface HeadersState {
126
+ headers: Map<string, string[]>;
127
+ }
128
+ export interface RequestState {
129
+ method: string;
130
+ url: string;
131
+ headersState: HeadersState;
132
+ body: Uint8Array | null;
133
+ bodyUsed: boolean;
134
+ cache: string;
135
+ credentials: string;
136
+ destination: string;
137
+ integrity: string;
138
+ keepalive: boolean;
139
+ mode: string;
140
+ redirect: string;
141
+ referrer: string;
142
+ referrerPolicy: string;
143
+ signal: AbortSignalState | null;
144
+ }
145
+ export interface ResponseState {
146
+ status: number;
147
+ statusText: string;
148
+ headersState: HeadersState;
149
+ body: Uint8Array | null;
150
+ bodyUsed: boolean;
151
+ url: string;
152
+ redirected: boolean;
153
+ type: string;
154
+ ok: boolean;
155
+ }
156
+ export interface AbortControllerState {
157
+ signalState: AbortSignalState;
158
+ }
159
+ export interface AbortSignalState {
160
+ aborted: boolean;
161
+ reason: unknown;
162
+ listeners: Set<() => void>;
163
+ }
164
+ export interface FormDataFileValue {
165
+ data: Uint8Array;
166
+ filename: string;
167
+ type: string;
168
+ }
169
+ export interface FormDataEntry {
170
+ name: string;
171
+ value: string | FormDataFileValue;
172
+ }
173
+ export interface FormDataState {
174
+ entries: FormDataEntry[];
175
+ }
package/package.json CHANGED
@@ -1,10 +1,55 @@
1
1
  {
2
2
  "name": "@ricsam/quickjs-fetch",
3
- "version": "0.0.1",
4
- "description": "OIDC trusted publishing setup package for @ricsam/quickjs-fetch",
3
+ "version": "0.2.1",
4
+ "main": "./dist/cjs/index.cjs",
5
+ "types": "./dist/types/index.d.ts",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/types/index.d.ts",
9
+ "require": "./dist/cjs/index.cjs",
10
+ "import": "./dist/mjs/index.mjs"
11
+ }
12
+ },
13
+ "scripts": {
14
+ "build": "bun build ./src/index.ts --outdir ./dist --target bun",
15
+ "test": "bun test",
16
+ "typecheck": "tsc --noEmit"
17
+ },
18
+ "dependencies": {
19
+ "@ricsam/quickjs-core": "^0.2.1",
20
+ "quickjs-emscripten": "^0.31.0"
21
+ },
22
+ "peerDependencies": {
23
+ "quickjs-emscripten": "^0.31.0"
24
+ },
25
+ "author": "Richard Samuelsson",
26
+ "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/ricsam/richie-qjs.git"
30
+ },
31
+ "bugs": {
32
+ "url": "https://github.com/ricsam/richie-qjs/issues"
33
+ },
34
+ "homepage": "https://github.com/ricsam/richie-qjs#readme",
5
35
  "keywords": [
6
- "oidc",
7
- "trusted-publishing",
8
- "setup"
36
+ "quickjs",
37
+ "sandbox",
38
+ "javascript",
39
+ "runtime",
40
+ "fetch",
41
+ "filesystem",
42
+ "streams",
43
+ "wasm",
44
+ "emscripten"
45
+ ],
46
+ "description": "Fetch API implementation for QuickJS runtime",
47
+ "module": "./dist/mjs/index.mjs",
48
+ "publishConfig": {
49
+ "access": "public"
50
+ },
51
+ "files": [
52
+ "dist",
53
+ "README.md"
9
54
  ]
10
- }
55
+ }