@b9g/platform 0.1.14-beta.3 → 0.1.15
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/README.md +0 -2
- package/package.json +14 -6
- package/src/index.d.ts +4 -217
- package/src/index.js +3 -73
- package/src/module.d.ts +142 -0
- package/src/module.js +1 -0
- package/src/runtime.js +9 -8
package/README.md
CHANGED
|
@@ -203,8 +203,6 @@ const platform = new CloudflarePlatform({
|
|
|
203
203
|
|
|
204
204
|
### Types
|
|
205
205
|
|
|
206
|
-
- `Platform` - Platform interface
|
|
207
|
-
- `PlatformConfig` - Platform configuration options
|
|
208
206
|
- `ServerOptions` - Server configuration options
|
|
209
207
|
- `Handler` - Request handler function type
|
|
210
208
|
- `Server` - Server interface
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@b9g/platform",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"description": "The portable meta-framework built on web standards.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"service-worker",
|
|
@@ -18,16 +18,16 @@
|
|
|
18
18
|
"shovel"
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@b9g/async-context": "^0.2.0
|
|
22
|
-
"@b9g/cache": "^0.2.0
|
|
21
|
+
"@b9g/async-context": "^0.2.0",
|
|
22
|
+
"@b9g/cache": "^0.2.0",
|
|
23
23
|
"@b9g/filesystem": "^0.1.8",
|
|
24
24
|
"@logtape/logtape": "^1.2.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@b9g/libuild": "^0.1.20",
|
|
28
|
-
"@b9g/node-webworker": "^0.2.0
|
|
29
|
-
"@b9g/platform-bun": "^0.1.
|
|
30
|
-
"@b9g/platform-node": "^0.1.
|
|
28
|
+
"@b9g/node-webworker": "^0.2.0",
|
|
29
|
+
"@b9g/platform-bun": "^0.1.13",
|
|
30
|
+
"@b9g/platform-node": "^0.1.15"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@b9g/zen": "^0.1.6"
|
|
@@ -71,6 +71,14 @@
|
|
|
71
71
|
"./config.js": {
|
|
72
72
|
"types": "./src/config.d.ts",
|
|
73
73
|
"import": "./src/config.js"
|
|
74
|
+
},
|
|
75
|
+
"./module": {
|
|
76
|
+
"types": "./src/module.d.ts",
|
|
77
|
+
"import": "./src/module.js"
|
|
78
|
+
},
|
|
79
|
+
"./module.js": {
|
|
80
|
+
"types": "./src/module.d.ts",
|
|
81
|
+
"import": "./src/module.js"
|
|
74
82
|
}
|
|
75
83
|
}
|
|
76
84
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -10,15 +10,8 @@
|
|
|
10
10
|
* - Platform interface and base classes
|
|
11
11
|
* - ServiceWorkerPool for multi-worker execution
|
|
12
12
|
*/
|
|
13
|
-
import type { DirectoryStorage } from "@b9g/filesystem";
|
|
14
13
|
import { CustomLoggerStorage, type LoggerStorage } from "./runtime.js";
|
|
15
14
|
export { validateConfig, ConfigValidationError } from "./config.js";
|
|
16
|
-
/**
|
|
17
|
-
* Platform configuration
|
|
18
|
-
* Extended by platform-specific implementations (NodePlatformOptions, etc.)
|
|
19
|
-
*/
|
|
20
|
-
export interface PlatformConfig {
|
|
21
|
-
}
|
|
22
15
|
/**
|
|
23
16
|
* Server options for platform implementations
|
|
24
17
|
*/
|
|
@@ -81,14 +74,16 @@ export interface ServiceWorkerInstance {
|
|
|
81
74
|
dispose(): Promise<void>;
|
|
82
75
|
}
|
|
83
76
|
/**
|
|
84
|
-
*
|
|
77
|
+
* Entry points returned by getEntryPoints().
|
|
85
78
|
* Each key is the output filename (without .js), value is the code.
|
|
86
79
|
*
|
|
87
80
|
* Examples:
|
|
88
81
|
* - Cloudflare: { "worker": "<code>" } - single worker file
|
|
89
82
|
* - Node/Bun: { "index": "<supervisor>", "worker": "<worker>" } - two files
|
|
90
83
|
*/
|
|
91
|
-
export type
|
|
84
|
+
export type EntryPoints = Record<string, string>;
|
|
85
|
+
/** @deprecated Use EntryPoints instead */
|
|
86
|
+
export type ProductionEntryPoints = EntryPoints;
|
|
92
87
|
/**
|
|
93
88
|
* ESBuild configuration subset that platforms can customize
|
|
94
89
|
*/
|
|
@@ -138,100 +133,6 @@ export interface ShovelServiceWorkerContainer extends ServiceWorkerContainer {
|
|
|
138
133
|
/** Internal: Reload workers (for hot reload) */
|
|
139
134
|
reloadWorkers(entrypoint: string): Promise<void>;
|
|
140
135
|
}
|
|
141
|
-
/**
|
|
142
|
-
* Platform interface - ServiceWorker entrypoint loader for JavaScript runtimes
|
|
143
|
-
*
|
|
144
|
-
* The core responsibility: "Take a ServiceWorker-style app file and make it run in this environment"
|
|
145
|
-
*/
|
|
146
|
-
export interface Platform {
|
|
147
|
-
/**
|
|
148
|
-
* Platform name for identification
|
|
149
|
-
*/
|
|
150
|
-
readonly name: string;
|
|
151
|
-
/**
|
|
152
|
-
* ServiceWorkerContainer for managing registrations (Node/Bun only)
|
|
153
|
-
* Similar to navigator.serviceWorker in browsers
|
|
154
|
-
*/
|
|
155
|
-
readonly serviceWorker: ShovelServiceWorkerContainer;
|
|
156
|
-
/**
|
|
157
|
-
* Start HTTP server and route requests to ServiceWorker (Node/Bun only)
|
|
158
|
-
* Must call serviceWorker.register() first
|
|
159
|
-
*/
|
|
160
|
-
listen(): Promise<Server>;
|
|
161
|
-
/**
|
|
162
|
-
* Close server and terminate workers (Node/Bun only)
|
|
163
|
-
*/
|
|
164
|
-
close(): Promise<void>;
|
|
165
|
-
/**
|
|
166
|
-
* SUPPORTING UTILITY - Create server instance for this platform
|
|
167
|
-
*/
|
|
168
|
-
createServer(handler: Handler, options?: ServerOptions): Server;
|
|
169
|
-
/**
|
|
170
|
-
* BUILD SUPPORT - Get production entry points for bundling
|
|
171
|
-
*
|
|
172
|
-
* Returns a map of output filenames to their source code.
|
|
173
|
-
* The build system creates one output file per entry point.
|
|
174
|
-
*
|
|
175
|
-
* Platform determines the structure:
|
|
176
|
-
* - Cloudflare: { "worker": "<code>" } - single worker file
|
|
177
|
-
* - Node/Bun: { "index": "<supervisor>", "worker": "<runtime + user code>" }
|
|
178
|
-
*
|
|
179
|
-
* The user's entrypoint code is statically imported into the appropriate file.
|
|
180
|
-
*
|
|
181
|
-
* @param userEntryPath - Path to user's entrypoint (will be imported)
|
|
182
|
-
*/
|
|
183
|
-
getProductionEntryPoints(userEntryPath: string): ProductionEntryPoints;
|
|
184
|
-
/**
|
|
185
|
-
* BUILD SUPPORT - Get platform-specific esbuild configuration
|
|
186
|
-
*
|
|
187
|
-
* Returns partial esbuild config that the CLI merges with common settings.
|
|
188
|
-
* Includes platform target, conditions, externals, and defines.
|
|
189
|
-
*/
|
|
190
|
-
getESBuildConfig(): PlatformESBuildConfig;
|
|
191
|
-
/**
|
|
192
|
-
* BUILD SUPPORT - Get platform-specific defaults for config generation
|
|
193
|
-
*
|
|
194
|
-
* Returns defaults for directories, caches, etc. that get merged with
|
|
195
|
-
* user config at build time. These are used by generateConfigModule()
|
|
196
|
-
* to create static imports for the default implementations.
|
|
197
|
-
*/
|
|
198
|
-
getDefaults(): PlatformDefaults;
|
|
199
|
-
/**
|
|
200
|
-
* Create cache storage for this platform
|
|
201
|
-
* Uses platform-specific defaults, overridable via shovel.json config
|
|
202
|
-
*/
|
|
203
|
-
createCaches(): Promise<CacheStorage>;
|
|
204
|
-
/**
|
|
205
|
-
* Create directory storage for this platform
|
|
206
|
-
* Uses platform-specific defaults, overridable via shovel.json config
|
|
207
|
-
*/
|
|
208
|
-
createDirectories(): Promise<DirectoryStorage>;
|
|
209
|
-
/**
|
|
210
|
-
* Create logger storage for this platform
|
|
211
|
-
* Uses platform-specific defaults, overridable via shovel.json config
|
|
212
|
-
*/
|
|
213
|
-
createLoggers(): Promise<LoggerStorage>;
|
|
214
|
-
/**
|
|
215
|
-
* Dispose of platform resources (worker pools, connections, etc.)
|
|
216
|
-
*/
|
|
217
|
-
dispose(): Promise<void>;
|
|
218
|
-
/**
|
|
219
|
-
* HOT RELOAD - Reload workers with a new entrypoint (development only)
|
|
220
|
-
* Optional - only Node and Bun platforms implement this
|
|
221
|
-
*/
|
|
222
|
-
reloadWorkers?(entrypoint: string): Promise<void>;
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Platform registry - internal implementation
|
|
226
|
-
*/
|
|
227
|
-
interface PlatformRegistry {
|
|
228
|
-
/** Register a platform implementation */
|
|
229
|
-
register(name: string, platform: any): void;
|
|
230
|
-
/** Get platform by name */
|
|
231
|
-
get(name: string): any | undefined;
|
|
232
|
-
/** Get all registered platforms */
|
|
233
|
-
list(): string[];
|
|
234
|
-
}
|
|
235
136
|
/**
|
|
236
137
|
* Detect the current JavaScript runtime
|
|
237
138
|
*/
|
|
@@ -265,54 +166,6 @@ export declare function resolvePlatform(options: {
|
|
|
265
166
|
platform?: string;
|
|
266
167
|
};
|
|
267
168
|
}): string;
|
|
268
|
-
/**
|
|
269
|
-
* Base platform class with shared adapter loading logic
|
|
270
|
-
* Platform implementations extend this and provide platform-specific methods
|
|
271
|
-
*/
|
|
272
|
-
export declare abstract class BasePlatform implements Platform {
|
|
273
|
-
config: PlatformConfig;
|
|
274
|
-
constructor(config?: PlatformConfig);
|
|
275
|
-
abstract readonly name: string;
|
|
276
|
-
abstract readonly serviceWorker: ShovelServiceWorkerContainer;
|
|
277
|
-
abstract listen(): Promise<Server>;
|
|
278
|
-
abstract close(): Promise<void>;
|
|
279
|
-
abstract createServer(handler: any, options?: any): any;
|
|
280
|
-
/**
|
|
281
|
-
* Get production entry points for bundling
|
|
282
|
-
* Subclasses must override to provide platform-specific entry points
|
|
283
|
-
*/
|
|
284
|
-
abstract getProductionEntryPoints(userEntryPath: string): ProductionEntryPoints;
|
|
285
|
-
/**
|
|
286
|
-
* Get platform-specific esbuild configuration
|
|
287
|
-
* Subclasses should override to provide platform-specific config
|
|
288
|
-
*/
|
|
289
|
-
abstract getESBuildConfig(): PlatformESBuildConfig;
|
|
290
|
-
/**
|
|
291
|
-
* Get platform-specific defaults for config generation
|
|
292
|
-
* Subclasses should override to provide platform-specific defaults
|
|
293
|
-
*/
|
|
294
|
-
abstract getDefaults(): PlatformDefaults;
|
|
295
|
-
/**
|
|
296
|
-
* Create cache storage for this platform
|
|
297
|
-
* Subclasses must override to provide platform-specific implementation
|
|
298
|
-
*/
|
|
299
|
-
abstract createCaches(): Promise<CacheStorage>;
|
|
300
|
-
/**
|
|
301
|
-
* Create directory storage for this platform
|
|
302
|
-
* Subclasses must override to provide platform-specific implementation
|
|
303
|
-
*/
|
|
304
|
-
abstract createDirectories(): Promise<DirectoryStorage>;
|
|
305
|
-
/**
|
|
306
|
-
* Create logger storage for this platform
|
|
307
|
-
* Subclasses must override to provide platform-specific implementation
|
|
308
|
-
*/
|
|
309
|
-
abstract createLoggers(): Promise<LoggerStorage>;
|
|
310
|
-
/**
|
|
311
|
-
* Dispose of platform resources
|
|
312
|
-
* Subclasses should override to clean up worker pools, connections, etc.
|
|
313
|
-
*/
|
|
314
|
-
dispose(): Promise<void>;
|
|
315
|
-
}
|
|
316
169
|
/**
|
|
317
170
|
* Merge platform defaults with user config
|
|
318
171
|
*
|
|
@@ -324,39 +177,6 @@ export declare abstract class BasePlatform implements Platform {
|
|
|
324
177
|
* @returns Merged config with all entries
|
|
325
178
|
*/
|
|
326
179
|
export declare function mergeConfigWithDefaults(defaults: Record<string, Record<string, unknown>>, userConfig: Record<string, Record<string, unknown>> | undefined): Record<string, Record<string, unknown>>;
|
|
327
|
-
/**
|
|
328
|
-
* Global platform registry
|
|
329
|
-
*/
|
|
330
|
-
declare class DefaultPlatformRegistry implements PlatformRegistry {
|
|
331
|
-
#private;
|
|
332
|
-
constructor();
|
|
333
|
-
register(name: string, platform: Platform): void;
|
|
334
|
-
get(name: string): Platform | undefined;
|
|
335
|
-
list(): string[];
|
|
336
|
-
}
|
|
337
|
-
/**
|
|
338
|
-
* Global platform registry instance
|
|
339
|
-
*/
|
|
340
|
-
export declare const platformRegistry: DefaultPlatformRegistry;
|
|
341
|
-
/**
|
|
342
|
-
* Get platform by name with error handling
|
|
343
|
-
*/
|
|
344
|
-
export declare function getPlatform(name?: string): Platform;
|
|
345
|
-
/**
|
|
346
|
-
* Get platform with async auto-registration fallback
|
|
347
|
-
*/
|
|
348
|
-
export declare function getPlatformAsync(name?: string): Promise<Platform>;
|
|
349
|
-
/**
|
|
350
|
-
* Common interface for ServiceWorker runtimes
|
|
351
|
-
*/
|
|
352
|
-
export interface ServiceWorkerRuntime {
|
|
353
|
-
init(): Promise<void>;
|
|
354
|
-
load(entrypoint: string): Promise<void>;
|
|
355
|
-
handleRequest(request: Request): Promise<Response>;
|
|
356
|
-
terminate(): Promise<void>;
|
|
357
|
-
readonly workerCount: number;
|
|
358
|
-
readonly ready: boolean;
|
|
359
|
-
}
|
|
360
180
|
/**
|
|
361
181
|
* Worker pool options
|
|
362
182
|
*/
|
|
@@ -370,39 +190,6 @@ export interface WorkerPoolOptions {
|
|
|
370
190
|
/** Custom worker factory (if not provided, uses createWebWorker) */
|
|
371
191
|
createWorker?: (entrypoint: string) => Worker | Promise<Worker>;
|
|
372
192
|
}
|
|
373
|
-
export interface WorkerMessage {
|
|
374
|
-
type: string;
|
|
375
|
-
[key: string]: any;
|
|
376
|
-
}
|
|
377
|
-
export interface WorkerRequest extends WorkerMessage {
|
|
378
|
-
type: "request";
|
|
379
|
-
request: {
|
|
380
|
-
url: string;
|
|
381
|
-
method: string;
|
|
382
|
-
headers: Record<string, string>;
|
|
383
|
-
body?: ArrayBuffer | null;
|
|
384
|
-
};
|
|
385
|
-
requestID: number;
|
|
386
|
-
}
|
|
387
|
-
export interface WorkerResponse extends WorkerMessage {
|
|
388
|
-
type: "response";
|
|
389
|
-
response: {
|
|
390
|
-
status: number;
|
|
391
|
-
statusText: string;
|
|
392
|
-
headers: Record<string, string>;
|
|
393
|
-
body: ArrayBuffer;
|
|
394
|
-
};
|
|
395
|
-
requestID: number;
|
|
396
|
-
}
|
|
397
|
-
export interface WorkerReadyMessage extends WorkerMessage {
|
|
398
|
-
type: "ready";
|
|
399
|
-
}
|
|
400
|
-
export interface WorkerErrorMessage extends WorkerMessage {
|
|
401
|
-
type: "error";
|
|
402
|
-
error: string;
|
|
403
|
-
stack?: string;
|
|
404
|
-
requestID?: number;
|
|
405
|
-
}
|
|
406
193
|
/**
|
|
407
194
|
* ServiceWorkerPool - manages a pool of ServiceWorker instances
|
|
408
195
|
*
|
package/src/index.js
CHANGED
|
@@ -55,18 +55,6 @@ function resolvePlatform(options) {
|
|
|
55
55
|
}
|
|
56
56
|
return detectDevelopmentPlatform();
|
|
57
57
|
}
|
|
58
|
-
var BasePlatform = class {
|
|
59
|
-
config;
|
|
60
|
-
constructor(config = {}) {
|
|
61
|
-
this.config = config;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Dispose of platform resources
|
|
65
|
-
* Subclasses should override to clean up worker pools, connections, etc.
|
|
66
|
-
*/
|
|
67
|
-
async dispose() {
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
58
|
function mergeConfigWithDefaults(defaults, userConfig) {
|
|
71
59
|
const user = userConfig ?? {};
|
|
72
60
|
const allNames = /* @__PURE__ */ new Set([...Object.keys(defaults), ...Object.keys(user)]);
|
|
@@ -76,62 +64,6 @@ function mergeConfigWithDefaults(defaults, userConfig) {
|
|
|
76
64
|
}
|
|
77
65
|
return merged;
|
|
78
66
|
}
|
|
79
|
-
var DefaultPlatformRegistry = class {
|
|
80
|
-
#platforms;
|
|
81
|
-
constructor() {
|
|
82
|
-
this.#platforms = /* @__PURE__ */ new Map();
|
|
83
|
-
}
|
|
84
|
-
register(name, platform) {
|
|
85
|
-
this.#platforms.set(name, platform);
|
|
86
|
-
}
|
|
87
|
-
get(name) {
|
|
88
|
-
return this.#platforms.get(name);
|
|
89
|
-
}
|
|
90
|
-
list() {
|
|
91
|
-
return Array.from(this.#platforms.keys());
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
var platformRegistry = new DefaultPlatformRegistry();
|
|
95
|
-
function getPlatform(name) {
|
|
96
|
-
if (name) {
|
|
97
|
-
const platform2 = platformRegistry.get(name);
|
|
98
|
-
if (!platform2) {
|
|
99
|
-
const available = platformRegistry.list();
|
|
100
|
-
throw new Error(
|
|
101
|
-
`Platform '${name}' not found. Available platforms: ${available.join(", ")}`
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
return platform2;
|
|
105
|
-
}
|
|
106
|
-
const platformName = detectDeploymentPlatform() || detectDevelopmentPlatform();
|
|
107
|
-
const platform = platformRegistry.get(platformName);
|
|
108
|
-
if (!platform) {
|
|
109
|
-
throw new Error(
|
|
110
|
-
`Detected platform '${platformName}' not registered. Please register it manually or specify a platform name.`
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
return platform;
|
|
114
|
-
}
|
|
115
|
-
async function getPlatformAsync(name) {
|
|
116
|
-
if (name) {
|
|
117
|
-
const platform2 = platformRegistry.get(name);
|
|
118
|
-
if (!platform2) {
|
|
119
|
-
const available = platformRegistry.list();
|
|
120
|
-
throw new Error(
|
|
121
|
-
`Platform '${name}' not found. Available platforms: ${available.join(", ")}`
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
return platform2;
|
|
125
|
-
}
|
|
126
|
-
const platformName = detectDeploymentPlatform() || detectDevelopmentPlatform();
|
|
127
|
-
const platform = platformRegistry.get(platformName);
|
|
128
|
-
if (!platform) {
|
|
129
|
-
throw new Error(
|
|
130
|
-
`Detected platform '${platformName}' not registered. Please register it manually using platformRegistry.register().`
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
return platform;
|
|
134
|
-
}
|
|
135
67
|
async function createWebWorker(workerScript) {
|
|
136
68
|
if (typeof Worker !== "undefined") {
|
|
137
69
|
return new Worker(workerScript, { type: "module" });
|
|
@@ -454,7 +386,9 @@ var ServiceWorkerPool = class {
|
|
|
454
386
|
createPromises.push(this.#createWorker(entrypoint));
|
|
455
387
|
}
|
|
456
388
|
await Promise.all(createPromises);
|
|
457
|
-
logger.
|
|
389
|
+
logger.info("Reloaded {count} workers", {
|
|
390
|
+
count: this.#options.workerCount
|
|
391
|
+
});
|
|
458
392
|
} catch (error) {
|
|
459
393
|
const waiters = this.#workerAvailableWaiters;
|
|
460
394
|
this.#workerAvailableWaiters = [];
|
|
@@ -500,7 +434,6 @@ var ServiceWorkerPool = class {
|
|
|
500
434
|
}
|
|
501
435
|
};
|
|
502
436
|
export {
|
|
503
|
-
BasePlatform,
|
|
504
437
|
ConfigValidationError,
|
|
505
438
|
CustomDatabaseStorage,
|
|
506
439
|
CustomLoggerStorage,
|
|
@@ -509,10 +442,7 @@ export {
|
|
|
509
442
|
detectDeploymentPlatform,
|
|
510
443
|
detectDevelopmentPlatform,
|
|
511
444
|
detectRuntime,
|
|
512
|
-
getPlatform,
|
|
513
|
-
getPlatformAsync,
|
|
514
445
|
mergeConfigWithDefaults,
|
|
515
|
-
platformRegistry,
|
|
516
446
|
resolvePlatform,
|
|
517
447
|
validateConfig
|
|
518
448
|
};
|
package/src/module.d.ts
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/// <reference path="./globals.d.ts" />
|
|
2
|
+
/// <reference path="./shovel-config.d.ts" />
|
|
3
|
+
/**
|
|
4
|
+
* Platform Module Interface
|
|
5
|
+
*
|
|
6
|
+
* Platforms are modules, not classes. Each platform exports functions
|
|
7
|
+
* that the CLI and generated entry code use.
|
|
8
|
+
*
|
|
9
|
+
* Build-time functions: Used by CLI/bundler, never bundled into prod
|
|
10
|
+
* Runtime functions: Imported by generated entry code, bundled into prod
|
|
11
|
+
*
|
|
12
|
+
* This separation enables tree-shaking - dev dependencies like Miniflare
|
|
13
|
+
* never end up in production bundles.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Entry points returned by getEntryPoints().
|
|
17
|
+
* Maps output filename (without .js) to source code.
|
|
18
|
+
*/
|
|
19
|
+
export type EntryPoints = Record<string, string>;
|
|
20
|
+
/**
|
|
21
|
+
* ESBuild configuration that platforms can customize.
|
|
22
|
+
*/
|
|
23
|
+
export interface ESBuildConfig {
|
|
24
|
+
/** Target platform: "node" or "browser" */
|
|
25
|
+
platform?: "node" | "browser";
|
|
26
|
+
/** Export conditions for package.json resolution */
|
|
27
|
+
conditions?: string[];
|
|
28
|
+
/** Modules to exclude from bundling */
|
|
29
|
+
external?: string[];
|
|
30
|
+
/** Define replacements */
|
|
31
|
+
define?: Record<string, string>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Platform defaults for config generation.
|
|
35
|
+
* Module paths that get statically imported at build time.
|
|
36
|
+
*/
|
|
37
|
+
export interface PlatformDefaults {
|
|
38
|
+
caches?: Record<string, {
|
|
39
|
+
module: string;
|
|
40
|
+
export?: string;
|
|
41
|
+
[key: string]: unknown;
|
|
42
|
+
}>;
|
|
43
|
+
directories?: Record<string, {
|
|
44
|
+
module: string;
|
|
45
|
+
export?: string;
|
|
46
|
+
[key: string]: unknown;
|
|
47
|
+
}>;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Options for creating a dev server.
|
|
51
|
+
*/
|
|
52
|
+
export interface DevServerOptions {
|
|
53
|
+
/** Port to listen on */
|
|
54
|
+
port: number;
|
|
55
|
+
/** Host to bind to */
|
|
56
|
+
host: string;
|
|
57
|
+
/** Path to the built worker entry */
|
|
58
|
+
workerPath: string;
|
|
59
|
+
/** Number of workers (Node/Bun only) */
|
|
60
|
+
workers?: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Dev server instance returned by createDevServer().
|
|
64
|
+
* Abstracts over Miniflare, worker pools, etc.
|
|
65
|
+
*/
|
|
66
|
+
export interface DevServer {
|
|
67
|
+
/** Server URL */
|
|
68
|
+
readonly url: string;
|
|
69
|
+
/** Reload workers with new entry */
|
|
70
|
+
reload(workerPath: string): Promise<void>;
|
|
71
|
+
/** Shut down the server */
|
|
72
|
+
close(): Promise<void>;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Result from installGlobals().
|
|
76
|
+
*/
|
|
77
|
+
export interface RuntimeContext {
|
|
78
|
+
/** ServiceWorker registration for dispatching events */
|
|
79
|
+
registration: ServiceWorkerRegistration;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Server instance for Node/Bun.
|
|
83
|
+
*/
|
|
84
|
+
export interface Server {
|
|
85
|
+
/** Start listening */
|
|
86
|
+
listen(): Promise<void>;
|
|
87
|
+
/** Stop the server */
|
|
88
|
+
close(): Promise<void>;
|
|
89
|
+
/** Server address */
|
|
90
|
+
readonly url: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Handler function type for HTTP requests.
|
|
94
|
+
*/
|
|
95
|
+
export type RequestHandler = (request: Request) => Response | Promise<Response>;
|
|
96
|
+
/**
|
|
97
|
+
* Fetch handler for Cloudflare Workers.
|
|
98
|
+
* ExecutionContext is Cloudflare-specific, so we use a generic type here.
|
|
99
|
+
*/
|
|
100
|
+
export type FetchHandler = (request: Request, env: unknown, ctx: {
|
|
101
|
+
waitUntil(promise: Promise<unknown>): void;
|
|
102
|
+
passThroughOnException(): void;
|
|
103
|
+
}) => Response | Promise<Response>;
|
|
104
|
+
/**
|
|
105
|
+
* What a platform module exports.
|
|
106
|
+
*
|
|
107
|
+
* This is not enforced at runtime - it's documentation of the contract.
|
|
108
|
+
* Each platform module should export these functions.
|
|
109
|
+
*
|
|
110
|
+
* Build-time exports (from main module):
|
|
111
|
+
* - name: string
|
|
112
|
+
* - getEntryPoints(userPath, mode): EntryPoints
|
|
113
|
+
* - getESBuildConfig(): ESBuildConfig
|
|
114
|
+
* - getDefaults(): PlatformDefaults
|
|
115
|
+
* - createDevServer(options): Promise<DevServer>
|
|
116
|
+
*
|
|
117
|
+
* Runtime exports (from /runtime subpath):
|
|
118
|
+
* - installGlobals(config): Promise<RuntimeContext>
|
|
119
|
+
* - Platform-specific: createServer, createFetchHandler, etc.
|
|
120
|
+
*/
|
|
121
|
+
export interface PlatformModule {
|
|
122
|
+
/** Platform identifier */
|
|
123
|
+
readonly name: string;
|
|
124
|
+
/** Generate entry point code for bundling */
|
|
125
|
+
getEntryPoints(userEntryPath: string, mode: "development" | "production"): EntryPoints;
|
|
126
|
+
/** Get ESBuild configuration for this platform */
|
|
127
|
+
getESBuildConfig(): ESBuildConfig;
|
|
128
|
+
/** Get default configs for caches, directories, etc. */
|
|
129
|
+
getDefaults(): PlatformDefaults;
|
|
130
|
+
/** Create a dev server (imports heavy deps like Miniflare) */
|
|
131
|
+
createDevServer(options: DevServerOptions): Promise<DevServer>;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* What a platform runtime module exports.
|
|
135
|
+
*
|
|
136
|
+
* Each platform's /runtime subpath exports these.
|
|
137
|
+
* The specific functions vary by platform.
|
|
138
|
+
*/
|
|
139
|
+
export interface PlatformRuntimeModule {
|
|
140
|
+
/** Install ServiceWorker globals (caches, directories, loggers) */
|
|
141
|
+
installGlobals(config: unknown): Promise<RuntimeContext>;
|
|
142
|
+
}
|
package/src/module.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="./module.d.ts" />
|
package/src/runtime.js
CHANGED
|
@@ -324,9 +324,10 @@ function createDatabaseFactory(configs) {
|
|
|
324
324
|
let Database;
|
|
325
325
|
try {
|
|
326
326
|
({ Database } = await import("@b9g/zen"));
|
|
327
|
-
} catch {
|
|
327
|
+
} catch (e) {
|
|
328
328
|
throw new Error(
|
|
329
|
-
"@b9g/zen is required for database support. Install it with: npm install @b9g/zen"
|
|
329
|
+
"@b9g/zen is required for database support. Install it with: npm install @b9g/zen",
|
|
330
|
+
{ cause: e }
|
|
330
331
|
);
|
|
331
332
|
}
|
|
332
333
|
const driver = new impl(url, driverOptions);
|
|
@@ -634,11 +635,11 @@ var ShovelServiceWorkerRegistration = class extends EventTarget {
|
|
|
634
635
|
this[kServiceWorker]._setState("installing");
|
|
635
636
|
return new Promise((resolve, reject) => {
|
|
636
637
|
const event = new ShovelInstallEvent();
|
|
637
|
-
|
|
638
|
+
queueMicrotask(() => {
|
|
638
639
|
try {
|
|
639
640
|
this.dispatchEvent(event);
|
|
640
641
|
} catch (error) {
|
|
641
|
-
|
|
642
|
+
queueMicrotask(() => {
|
|
642
643
|
throw error;
|
|
643
644
|
});
|
|
644
645
|
}
|
|
@@ -670,11 +671,11 @@ var ShovelServiceWorkerRegistration = class extends EventTarget {
|
|
|
670
671
|
this[kServiceWorker]._setState("activating");
|
|
671
672
|
return new Promise((resolve, reject) => {
|
|
672
673
|
const event = new ShovelActivateEvent();
|
|
673
|
-
|
|
674
|
+
queueMicrotask(() => {
|
|
674
675
|
try {
|
|
675
676
|
this.dispatchEvent(event);
|
|
676
677
|
} catch (error) {
|
|
677
|
-
|
|
678
|
+
queueMicrotask(() => {
|
|
678
679
|
throw error;
|
|
679
680
|
});
|
|
680
681
|
}
|
|
@@ -705,8 +706,8 @@ var ShovelServiceWorkerRegistration = class extends EventTarget {
|
|
|
705
706
|
* @param event - The fetch event to handle (created by platform adapter)
|
|
706
707
|
*/
|
|
707
708
|
async [kHandleRequest](event) {
|
|
708
|
-
if (this[kServiceWorker].state
|
|
709
|
-
throw new Error("ServiceWorker not
|
|
709
|
+
if (this[kServiceWorker].state === "parsed") {
|
|
710
|
+
throw new Error("ServiceWorker not initialized");
|
|
710
711
|
}
|
|
711
712
|
return cookieStoreStorage.run(event.cookieStore, async () => {
|
|
712
713
|
this.dispatchEvent(event);
|