@b9g/platform 0.1.12 → 0.1.14-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +25 -17
- package/src/config.d.ts +24 -0
- package/src/config.js +29 -0
- package/src/globals.d.ts +119 -0
- package/src/index.d.ts +167 -114
- package/src/index.js +176 -291
- package/src/runtime.d.ts +372 -72
- package/src/runtime.js +469 -181
- package/chunk-P57PW2II.js +0 -11
- package/src/worker.d.ts +0 -39
- package/src/worker.js +0 -285
package/package.json
CHANGED
|
@@ -1,28 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@b9g/platform",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.14-beta.0",
|
|
4
|
+
"description": "The portable meta-framework built on web standards.",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"
|
|
6
|
+
"service-worker",
|
|
7
7
|
"universal",
|
|
8
8
|
"deployment",
|
|
9
9
|
"platform",
|
|
10
|
-
"registry",
|
|
11
10
|
"node",
|
|
12
11
|
"bun",
|
|
13
12
|
"cloudflare",
|
|
14
13
|
"workers",
|
|
14
|
+
"cache",
|
|
15
|
+
"framework",
|
|
16
|
+
"meta-framework",
|
|
17
|
+
"esbuild",
|
|
15
18
|
"shovel"
|
|
16
19
|
],
|
|
17
20
|
"dependencies": {
|
|
18
|
-
"@b9g/async-context": "^0.
|
|
19
|
-
"@b9g/cache": "^0.
|
|
20
|
-
"@b9g/filesystem": "^0.1.
|
|
21
|
+
"@b9g/async-context": "^0.2.0-beta.0",
|
|
22
|
+
"@b9g/cache": "^0.2.0-beta.0",
|
|
23
|
+
"@b9g/filesystem": "^0.1.8",
|
|
24
|
+
"@b9g/zen": "^0.1.6",
|
|
21
25
|
"@logtape/logtape": "^1.2.0"
|
|
22
26
|
},
|
|
23
27
|
"devDependencies": {
|
|
24
|
-
"@b9g/libuild": "^0.1.
|
|
25
|
-
"
|
|
28
|
+
"@b9g/libuild": "^0.1.20",
|
|
29
|
+
"@b9g/node-webworker": "^0.2.0-beta.1",
|
|
30
|
+
"@b9g/platform-bun": "^0.1.12-beta.0",
|
|
31
|
+
"@b9g/platform-node": "^0.1.14-beta.0"
|
|
26
32
|
},
|
|
27
33
|
"peerDependencies": {
|
|
28
34
|
"@logtape/file": "^1.0.0",
|
|
@@ -65,14 +71,6 @@
|
|
|
65
71
|
"types": "./src/runtime.d.ts",
|
|
66
72
|
"import": "./src/runtime.js"
|
|
67
73
|
},
|
|
68
|
-
"./worker": {
|
|
69
|
-
"types": "./src/worker.d.ts",
|
|
70
|
-
"import": "./src/worker.js"
|
|
71
|
-
},
|
|
72
|
-
"./worker.js": {
|
|
73
|
-
"types": "./src/worker.d.ts",
|
|
74
|
-
"import": "./src/worker.js"
|
|
75
|
-
},
|
|
76
74
|
"./index": {
|
|
77
75
|
"types": "./src/index.d.ts",
|
|
78
76
|
"import": "./src/index.js"
|
|
@@ -80,6 +78,16 @@
|
|
|
80
78
|
"./index.js": {
|
|
81
79
|
"types": "./src/index.d.ts",
|
|
82
80
|
"import": "./src/index.js"
|
|
81
|
+
},
|
|
82
|
+
"./globals.d.ts": "./src/globals.d.ts",
|
|
83
|
+
"./shovel-config.d.ts": "./src/shovel-config.d.ts",
|
|
84
|
+
"./config": {
|
|
85
|
+
"types": "./src/config.d.ts",
|
|
86
|
+
"import": "./src/config.js"
|
|
87
|
+
},
|
|
88
|
+
"./config.js": {
|
|
89
|
+
"types": "./src/config.d.ts",
|
|
90
|
+
"import": "./src/config.js"
|
|
83
91
|
}
|
|
84
92
|
}
|
|
85
93
|
}
|
package/src/config.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/// <reference path="./globals.d.ts" />
|
|
2
|
+
/// <reference path="./shovel-config.d.ts" />
|
|
3
|
+
/**
|
|
4
|
+
* Config Validation Utilities
|
|
5
|
+
*
|
|
6
|
+
* Helpers for validating config objects at runtime.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Error thrown when config validation fails
|
|
10
|
+
*/
|
|
11
|
+
export declare class ConfigValidationError extends Error {
|
|
12
|
+
readonly path: string;
|
|
13
|
+
readonly issue: "undefined" | "NaN";
|
|
14
|
+
constructor(path: string, issue: "undefined" | "NaN");
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Validate that a config object has no undefined or NaN values.
|
|
18
|
+
* Call this at runtime to fail fast on missing env vars.
|
|
19
|
+
*
|
|
20
|
+
* @param config - The config object to validate
|
|
21
|
+
* @param path - Current path for error messages (used in recursion)
|
|
22
|
+
* @throws ConfigValidationError if any value is undefined or NaN
|
|
23
|
+
*/
|
|
24
|
+
export declare function validateConfig(config: Record<string, unknown>, path?: string): void;
|
package/src/config.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/// <reference types="./config.d.ts" />
|
|
2
|
+
// src/config.ts
|
|
3
|
+
var ConfigValidationError = class extends Error {
|
|
4
|
+
constructor(path, issue) {
|
|
5
|
+
const message = issue === "undefined" ? `Config "${path}" is undefined. Ensure required environment variables are set.` : `Config "${path}" is NaN. Ensure the environment variable contains a valid number.`;
|
|
6
|
+
super(message);
|
|
7
|
+
this.path = path;
|
|
8
|
+
this.issue = issue;
|
|
9
|
+
this.name = "ConfigValidationError";
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
function validateConfig(config, path = "") {
|
|
13
|
+
for (const [key, value] of Object.entries(config)) {
|
|
14
|
+
const fullPath = path ? `${path}.${key}` : key;
|
|
15
|
+
if (value === void 0) {
|
|
16
|
+
throw new ConfigValidationError(fullPath, "undefined");
|
|
17
|
+
}
|
|
18
|
+
if (typeof value === "number" && Number.isNaN(value)) {
|
|
19
|
+
throw new ConfigValidationError(fullPath, "NaN");
|
|
20
|
+
}
|
|
21
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
22
|
+
validateConfig(value, fullPath);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
ConfigValidationError,
|
|
28
|
+
validateConfig
|
|
29
|
+
};
|
package/src/globals.d.ts
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/// <reference lib="webworker" />
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Global type declarations for Shovel ServiceWorker environment.
|
|
5
|
+
*
|
|
6
|
+
* These types augment the global scope with Shovel-specific APIs
|
|
7
|
+
* that are installed by ServiceWorkerGlobals.
|
|
8
|
+
*
|
|
9
|
+
* Usage: Include this file in your tsconfig.json "include" array
|
|
10
|
+
* or reference it with /// <reference types="@b9g/platform/globals" />
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type {Logger} from "@logtape/logtape";
|
|
14
|
+
import type {DirectoryStorage} from "@b9g/filesystem";
|
|
15
|
+
|
|
16
|
+
declare global {
|
|
17
|
+
/**
|
|
18
|
+
* Logger storage API for accessing named loggers.
|
|
19
|
+
* @example const logger = self.loggers.get(["app"]);
|
|
20
|
+
* @example const dbLogger = self.loggers.get(["app", "db"]);
|
|
21
|
+
*/
|
|
22
|
+
interface LoggerStorage {
|
|
23
|
+
get(categories: string[]): Logger;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Upgrade event passed to onUpgrade callback during database.open().
|
|
28
|
+
*/
|
|
29
|
+
interface DatabaseUpgradeEvent {
|
|
30
|
+
/** The database being upgraded */
|
|
31
|
+
db: unknown;
|
|
32
|
+
/** Previous database version (0 if new) */
|
|
33
|
+
oldVersion: number;
|
|
34
|
+
/** Target version being opened */
|
|
35
|
+
newVersion: number;
|
|
36
|
+
/** Register a promise that must complete before open() resolves */
|
|
37
|
+
waitUntil(promise: Promise<unknown>): void;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Database storage API for accessing named database instances.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* // In activate - open with migrations
|
|
45
|
+
* await self.databases.open("main", 2, (e) => {
|
|
46
|
+
* e.waitUntil(runMigrations(e));
|
|
47
|
+
* });
|
|
48
|
+
*
|
|
49
|
+
* // In fetch - get opened database (sync)
|
|
50
|
+
* const db = self.databases.get("main");
|
|
51
|
+
*/
|
|
52
|
+
interface DatabaseStorage {
|
|
53
|
+
/** Open a database at a specific version, running migrations if needed */
|
|
54
|
+
open(
|
|
55
|
+
name: string,
|
|
56
|
+
version: number,
|
|
57
|
+
onUpgrade?: (event: DatabaseUpgradeEvent) => void,
|
|
58
|
+
): Promise<unknown>;
|
|
59
|
+
/** Get an already-opened database (throws if not opened) */
|
|
60
|
+
get(name: string): unknown;
|
|
61
|
+
/** Close a specific database */
|
|
62
|
+
close(name: string): Promise<void>;
|
|
63
|
+
/** Close all databases */
|
|
64
|
+
closeAll(): Promise<void>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Directory storage API for accessing named directories.
|
|
69
|
+
* @example const uploads = await directories.open("uploads");
|
|
70
|
+
*/
|
|
71
|
+
var directories: DirectoryStorage;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Logger storage API for accessing named loggers.
|
|
75
|
+
* @example const logger = self.loggers.get(["app"]);
|
|
76
|
+
* @example const dbLogger = self.loggers.get(["app", "db"]);
|
|
77
|
+
*/
|
|
78
|
+
var loggers: LoggerStorage;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Database storage API for accessing named database instances.
|
|
82
|
+
* @example const db = self.databases.get("main");
|
|
83
|
+
*/
|
|
84
|
+
var databases: DatabaseStorage;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Environment variables available via import.meta.env
|
|
88
|
+
* Works across all platforms (Node/Bun via esbuild shim, Cloudflare natively)
|
|
89
|
+
*/
|
|
90
|
+
interface ImportMetaEnv {
|
|
91
|
+
readonly [key: string]: string | undefined;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
interface ImportMeta {
|
|
95
|
+
readonly env: ImportMetaEnv;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Augment WorkerGlobalScopeEventMap with ServiceWorker events.
|
|
100
|
+
*
|
|
101
|
+
* TypeScript's lib.webworker.d.ts declares `self` as `WorkerGlobalScope`, not
|
|
102
|
+
* `ServiceWorkerGlobalScope`. This means `self.addEventListener("fetch", ...)`
|
|
103
|
+
* doesn't know about FetchEvent. See: https://github.com/microsoft/TypeScript/issues/14877
|
|
104
|
+
*
|
|
105
|
+
* Rather than trying to redeclare `self` (which causes conflicts), we augment
|
|
106
|
+
* the base WorkerGlobalScopeEventMap to include ServiceWorker-specific events.
|
|
107
|
+
* This allows `self.addEventListener("fetch", (event) => ...)` to correctly
|
|
108
|
+
* infer `event` as `FetchEvent`.
|
|
109
|
+
*/
|
|
110
|
+
interface WorkerGlobalScopeEventMap {
|
|
111
|
+
fetch: FetchEvent;
|
|
112
|
+
install: ExtendableEvent;
|
|
113
|
+
activate: ExtendableEvent;
|
|
114
|
+
message: ExtendableMessageEvent;
|
|
115
|
+
messageerror: MessageEvent;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export {};
|
package/src/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/// <reference path="./globals.d.ts" />
|
|
2
|
+
/// <reference path="./shovel-config.d.ts" />
|
|
1
3
|
/**
|
|
2
4
|
* @b9g/platform - Platform interface for ServiceWorker entrypoint loading
|
|
3
5
|
*
|
|
@@ -6,11 +8,11 @@
|
|
|
6
8
|
*
|
|
7
9
|
* This module contains:
|
|
8
10
|
* - Platform interface and base classes
|
|
9
|
-
* - SingleThreadedRuntime for main-thread execution
|
|
10
11
|
* - ServiceWorkerPool for multi-worker execution
|
|
11
12
|
*/
|
|
12
13
|
import type { DirectoryStorage } from "@b9g/filesystem";
|
|
13
14
|
import { CustomLoggerStorage, type LoggerStorage } from "./runtime.js";
|
|
15
|
+
export { validateConfig, ConfigValidationError } from "./config.js";
|
|
14
16
|
/**
|
|
15
17
|
* Platform configuration
|
|
16
18
|
* Extended by platform-specific implementations (NodePlatformOptions, etc.)
|
|
@@ -25,13 +27,8 @@ export interface ServerOptions {
|
|
|
25
27
|
port?: number;
|
|
26
28
|
/** Host to bind to */
|
|
27
29
|
host?: string;
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
/** Source maps support */
|
|
31
|
-
sourceMaps?: boolean;
|
|
32
|
-
/** Verbose logging */
|
|
33
|
-
verbose?: boolean;
|
|
34
|
-
};
|
|
30
|
+
/** Enable SO_REUSEPORT for multi-worker deployments (Bun only) */
|
|
31
|
+
reusePort?: boolean;
|
|
35
32
|
}
|
|
36
33
|
/**
|
|
37
34
|
* Request handler function (Web Fetch API compatible)
|
|
@@ -84,15 +81,18 @@ export interface ServiceWorkerInstance {
|
|
|
84
81
|
dispose(): Promise<void>;
|
|
85
82
|
}
|
|
86
83
|
/**
|
|
87
|
-
*
|
|
88
|
-
*
|
|
84
|
+
* Production entry points returned by getProductionEntryPoints().
|
|
85
|
+
* Each key is the output filename (without .js), value is the code.
|
|
86
|
+
*
|
|
87
|
+
* Examples:
|
|
88
|
+
* - Cloudflare: { "worker": "<code>" } - single worker file
|
|
89
|
+
* - Node/Bun: { "index": "<supervisor>", "worker": "<worker>" } - two files
|
|
89
90
|
*/
|
|
90
|
-
export
|
|
91
|
-
}
|
|
91
|
+
export type ProductionEntryPoints = Record<string, string>;
|
|
92
92
|
/**
|
|
93
|
-
*
|
|
93
|
+
* ESBuild configuration subset that platforms can customize
|
|
94
94
|
*/
|
|
95
|
-
export interface
|
|
95
|
+
export interface PlatformESBuildConfig {
|
|
96
96
|
/** Target platform: "node" or "browser" */
|
|
97
97
|
platform?: "node" | "browser" | "neutral";
|
|
98
98
|
/** Export conditions for package.json resolution */
|
|
@@ -101,16 +101,42 @@ export interface PlatformEsbuildConfig {
|
|
|
101
101
|
external?: string[];
|
|
102
102
|
/** Compile-time defines */
|
|
103
103
|
define?: Record<string, string>;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Default resource configuration for a named resource (cache, directory, etc.)
|
|
107
|
+
* Used by platforms to define built-in defaults that get merged with user config.
|
|
108
|
+
*/
|
|
109
|
+
export interface ResourceDefault {
|
|
110
|
+
/** Module path to import (e.g., "@b9g/cache/memory") */
|
|
111
|
+
module: string;
|
|
112
|
+
/** Named export to use (defaults to "default") */
|
|
113
|
+
export?: string;
|
|
114
|
+
/** Additional options (e.g., path for directories) */
|
|
115
|
+
[key: string]: unknown;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Platform-specific defaults for config generation.
|
|
119
|
+
* These are merged with user config at build time to provide
|
|
120
|
+
* sensible defaults for each platform.
|
|
121
|
+
*/
|
|
122
|
+
export interface PlatformDefaults {
|
|
123
|
+
/** Default directory configurations (server, public, tmp, etc.) */
|
|
124
|
+
directories?: Record<string, ResourceDefault>;
|
|
125
|
+
/** Default cache configuration (e.g., memory cache) */
|
|
126
|
+
caches?: Record<string, ResourceDefault>;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Extended ServiceWorkerContainer with internal methods for hot reload
|
|
130
|
+
*/
|
|
131
|
+
export interface ShovelServiceWorkerContainer extends ServiceWorkerContainer {
|
|
132
|
+
/** Internal: Get the worker pool for request handling */
|
|
133
|
+
readonly pool?: {
|
|
134
|
+
handleRequest(request: Request): Promise<Response>;
|
|
135
|
+
};
|
|
136
|
+
/** Internal: Terminate all workers */
|
|
137
|
+
terminate(): Promise<void>;
|
|
138
|
+
/** Internal: Reload workers (for hot reload) */
|
|
139
|
+
reloadWorkers(entrypoint: string): Promise<void>;
|
|
114
140
|
}
|
|
115
141
|
/**
|
|
116
142
|
* Platform interface - ServiceWorker entrypoint loader for JavaScript runtimes
|
|
@@ -123,41 +149,77 @@ export interface Platform {
|
|
|
123
149
|
*/
|
|
124
150
|
readonly name: string;
|
|
125
151
|
/**
|
|
126
|
-
*
|
|
127
|
-
*
|
|
152
|
+
* ServiceWorkerContainer for managing registrations (Node/Bun only)
|
|
153
|
+
* Similar to navigator.serviceWorker in browsers
|
|
128
154
|
*/
|
|
129
|
-
|
|
155
|
+
readonly serviceWorker: ShovelServiceWorkerContainer;
|
|
130
156
|
/**
|
|
131
|
-
*
|
|
132
|
-
*
|
|
157
|
+
* Start HTTP server and route requests to ServiceWorker (Node/Bun only)
|
|
158
|
+
* Must call serviceWorker.register() first
|
|
133
159
|
*/
|
|
134
|
-
|
|
160
|
+
listen(): Promise<Server>;
|
|
161
|
+
/**
|
|
162
|
+
* Close server and terminate workers (Node/Bun only)
|
|
163
|
+
*/
|
|
164
|
+
close(): Promise<void>;
|
|
135
165
|
/**
|
|
136
166
|
* SUPPORTING UTILITY - Create server instance for this platform
|
|
137
167
|
*/
|
|
138
168
|
createServer(handler: Handler, options?: ServerOptions): Server;
|
|
139
169
|
/**
|
|
140
|
-
* BUILD SUPPORT - Get
|
|
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.
|
|
141
174
|
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
* 3. Exports any required handlers (e.g., ES module export for Cloudflare)
|
|
175
|
+
* Platform determines the structure:
|
|
176
|
+
* - Cloudflare: { "worker": "<code>" } - single worker file
|
|
177
|
+
* - Node/Bun: { "index": "<supervisor>", "worker": "<runtime + user code>" }
|
|
146
178
|
*
|
|
147
|
-
* The
|
|
148
|
-
* Every platform must provide a wrapper - there is no "raw user code" mode.
|
|
179
|
+
* The user's entrypoint code is statically imported into the appropriate file.
|
|
149
180
|
*
|
|
150
|
-
* @param
|
|
151
|
-
* @param options - Additional options
|
|
181
|
+
* @param userEntryPath - Path to user's entrypoint (will be imported)
|
|
152
182
|
*/
|
|
153
|
-
|
|
183
|
+
getProductionEntryPoints(userEntryPath: string): ProductionEntryPoints;
|
|
154
184
|
/**
|
|
155
185
|
* BUILD SUPPORT - Get platform-specific esbuild configuration
|
|
156
186
|
*
|
|
157
187
|
* Returns partial esbuild config that the CLI merges with common settings.
|
|
158
188
|
* Includes platform target, conditions, externals, and defines.
|
|
159
189
|
*/
|
|
160
|
-
|
|
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>;
|
|
161
223
|
}
|
|
162
224
|
/**
|
|
163
225
|
* Platform registry - internal implementation
|
|
@@ -206,7 +268,7 @@ export declare function resolvePlatform(options: {
|
|
|
206
268
|
/**
|
|
207
269
|
* Create platform instance based on name
|
|
208
270
|
*/
|
|
209
|
-
export declare function createPlatform(platformName: string, options?: any): Promise<
|
|
271
|
+
export declare function createPlatform(platformName: string, options?: any): Promise<Platform>;
|
|
210
272
|
/**
|
|
211
273
|
* Base platform class with shared adapter loading logic
|
|
212
274
|
* Platform implementations extend this and provide platform-specific methods
|
|
@@ -215,24 +277,57 @@ export declare abstract class BasePlatform implements Platform {
|
|
|
215
277
|
config: PlatformConfig;
|
|
216
278
|
constructor(config?: PlatformConfig);
|
|
217
279
|
abstract readonly name: string;
|
|
218
|
-
abstract
|
|
280
|
+
abstract readonly serviceWorker: ShovelServiceWorkerContainer;
|
|
281
|
+
abstract listen(): Promise<Server>;
|
|
282
|
+
abstract close(): Promise<void>;
|
|
219
283
|
abstract createServer(handler: any, options?: any): any;
|
|
220
284
|
/**
|
|
221
|
-
*
|
|
222
|
-
*
|
|
285
|
+
* Get production entry points for bundling
|
|
286
|
+
* Subclasses must override to provide platform-specific entry points
|
|
223
287
|
*/
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Get virtual entry wrapper template for user code
|
|
227
|
-
* Subclasses must override to provide platform-specific wrappers
|
|
228
|
-
*/
|
|
229
|
-
abstract getEntryWrapper(entryPath: string, options?: EntryWrapperOptions): string;
|
|
288
|
+
abstract getProductionEntryPoints(userEntryPath: string): ProductionEntryPoints;
|
|
230
289
|
/**
|
|
231
290
|
* Get platform-specific esbuild configuration
|
|
232
291
|
* Subclasses should override to provide platform-specific config
|
|
233
292
|
*/
|
|
234
|
-
abstract
|
|
293
|
+
abstract getESBuildConfig(): PlatformESBuildConfig;
|
|
294
|
+
/**
|
|
295
|
+
* Get platform-specific defaults for config generation
|
|
296
|
+
* Subclasses should override to provide platform-specific defaults
|
|
297
|
+
*/
|
|
298
|
+
abstract getDefaults(): PlatformDefaults;
|
|
299
|
+
/**
|
|
300
|
+
* Create cache storage for this platform
|
|
301
|
+
* Subclasses must override to provide platform-specific implementation
|
|
302
|
+
*/
|
|
303
|
+
abstract createCaches(): Promise<CacheStorage>;
|
|
304
|
+
/**
|
|
305
|
+
* Create directory storage for this platform
|
|
306
|
+
* Subclasses must override to provide platform-specific implementation
|
|
307
|
+
*/
|
|
308
|
+
abstract createDirectories(): Promise<DirectoryStorage>;
|
|
309
|
+
/**
|
|
310
|
+
* Create logger storage for this platform
|
|
311
|
+
* Subclasses must override to provide platform-specific implementation
|
|
312
|
+
*/
|
|
313
|
+
abstract createLoggers(): Promise<LoggerStorage>;
|
|
314
|
+
/**
|
|
315
|
+
* Dispose of platform resources
|
|
316
|
+
* Subclasses should override to clean up worker pools, connections, etc.
|
|
317
|
+
*/
|
|
318
|
+
dispose(): Promise<void>;
|
|
235
319
|
}
|
|
320
|
+
/**
|
|
321
|
+
* Merge platform defaults with user config
|
|
322
|
+
*
|
|
323
|
+
* Deep merges each entry so user can override specific options without
|
|
324
|
+
* losing the platform's default implementation class.
|
|
325
|
+
*
|
|
326
|
+
* @param defaults - Platform's runtime defaults (with actual class refs)
|
|
327
|
+
* @param userConfig - User's config from shovel.json (may be partial)
|
|
328
|
+
* @returns Merged config with all entries
|
|
329
|
+
*/
|
|
330
|
+
export declare function mergeConfigWithDefaults(defaults: Record<string, Record<string, unknown>>, userConfig: Record<string, Record<string, unknown>> | undefined): Record<string, Record<string, unknown>>;
|
|
236
331
|
/**
|
|
237
332
|
* Global platform registry
|
|
238
333
|
*/
|
|
@@ -266,50 +361,6 @@ export interface ServiceWorkerRuntime {
|
|
|
266
361
|
readonly workerCount: number;
|
|
267
362
|
readonly ready: boolean;
|
|
268
363
|
}
|
|
269
|
-
export interface SingleThreadedRuntimeOptions {
|
|
270
|
-
/** Cache storage for the runtime */
|
|
271
|
-
caches: CacheStorage;
|
|
272
|
-
/** Directory storage for the runtime */
|
|
273
|
-
directories: DirectoryStorage;
|
|
274
|
-
/** Logger storage for the runtime */
|
|
275
|
-
loggers: LoggerStorage;
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* Single-threaded ServiceWorker runtime
|
|
279
|
-
*
|
|
280
|
-
* Runs ServiceWorker code directly in the main thread.
|
|
281
|
-
* Implements ServiceWorkerRuntime interface for interchangeability with ServiceWorkerPool.
|
|
282
|
-
*/
|
|
283
|
-
export declare class SingleThreadedRuntime implements ServiceWorkerRuntime {
|
|
284
|
-
#private;
|
|
285
|
-
constructor(options: SingleThreadedRuntimeOptions);
|
|
286
|
-
/**
|
|
287
|
-
* Initialize the runtime (install ServiceWorker globals)
|
|
288
|
-
*/
|
|
289
|
-
init(): Promise<void>;
|
|
290
|
-
/**
|
|
291
|
-
* Load (or reload) a ServiceWorker entrypoint
|
|
292
|
-
* @param entrypoint - Path to the entrypoint file (content-hashed filename)
|
|
293
|
-
*/
|
|
294
|
-
load(entrypoint: string): Promise<void>;
|
|
295
|
-
/**
|
|
296
|
-
* Handle an HTTP request
|
|
297
|
-
* This is the key method - direct call, no postMessage!
|
|
298
|
-
*/
|
|
299
|
-
handleRequest(request: Request): Promise<Response>;
|
|
300
|
-
/**
|
|
301
|
-
* Graceful shutdown
|
|
302
|
-
*/
|
|
303
|
-
terminate(): Promise<void>;
|
|
304
|
-
/**
|
|
305
|
-
* Get the number of workers (always 1 for single-threaded)
|
|
306
|
-
*/
|
|
307
|
-
get workerCount(): number;
|
|
308
|
-
/**
|
|
309
|
-
* Check if ready to handle requests
|
|
310
|
-
*/
|
|
311
|
-
get ready(): boolean;
|
|
312
|
-
}
|
|
313
364
|
/**
|
|
314
365
|
* Worker pool options
|
|
315
366
|
*/
|
|
@@ -320,6 +371,8 @@ export interface WorkerPoolOptions {
|
|
|
320
371
|
requestTimeout?: number;
|
|
321
372
|
/** Working directory for file resolution */
|
|
322
373
|
cwd?: string;
|
|
374
|
+
/** Custom worker factory (if not provided, uses createWebWorker) */
|
|
375
|
+
createWorker?: (entrypoint: string) => Worker | Promise<Worker>;
|
|
323
376
|
}
|
|
324
377
|
export interface WorkerMessage {
|
|
325
378
|
type: string;
|
|
@@ -345,13 +398,8 @@ export interface WorkerResponse extends WorkerMessage {
|
|
|
345
398
|
};
|
|
346
399
|
requestID: number;
|
|
347
400
|
}
|
|
348
|
-
export interface WorkerLoadMessage extends WorkerMessage {
|
|
349
|
-
type: "load";
|
|
350
|
-
entrypoint: string;
|
|
351
|
-
}
|
|
352
401
|
export interface WorkerReadyMessage extends WorkerMessage {
|
|
353
|
-
type: "ready"
|
|
354
|
-
entrypoint?: string;
|
|
402
|
+
type: "ready";
|
|
355
403
|
}
|
|
356
404
|
export interface WorkerErrorMessage extends WorkerMessage {
|
|
357
405
|
type: "error";
|
|
@@ -359,21 +407,21 @@ export interface WorkerErrorMessage extends WorkerMessage {
|
|
|
359
407
|
stack?: string;
|
|
360
408
|
requestID?: number;
|
|
361
409
|
}
|
|
362
|
-
export interface WorkerInitMessage extends WorkerMessage {
|
|
363
|
-
type: "init";
|
|
364
|
-
config: any;
|
|
365
|
-
baseDir: string;
|
|
366
|
-
}
|
|
367
|
-
export interface WorkerInitializedMessage extends WorkerMessage {
|
|
368
|
-
type: "initialized";
|
|
369
|
-
}
|
|
370
410
|
/**
|
|
371
411
|
* ServiceWorkerPool - manages a pool of ServiceWorker instances
|
|
372
|
-
*
|
|
412
|
+
*
|
|
413
|
+
* With the unified build model, workers are self-contained bundles that:
|
|
414
|
+
* 1. Initialize their own runtime (via initWorkerRuntime)
|
|
415
|
+
* 2. Import user code
|
|
416
|
+
* 3. Run lifecycle events
|
|
417
|
+
* 4. Start message loop (via startWorkerMessageLoop)
|
|
418
|
+
*
|
|
419
|
+
* Hot reload is achieved by terminating old workers and creating new ones
|
|
420
|
+
* with the new bundle path.
|
|
373
421
|
*/
|
|
374
422
|
export declare class ServiceWorkerPool {
|
|
375
423
|
#private;
|
|
376
|
-
constructor(options
|
|
424
|
+
constructor(options: WorkerPoolOptions, appEntrypoint: string, cacheStorage?: CacheStorage);
|
|
377
425
|
/**
|
|
378
426
|
* Initialize workers (must be called after construction)
|
|
379
427
|
*/
|
|
@@ -383,8 +431,12 @@ export declare class ServiceWorkerPool {
|
|
|
383
431
|
*/
|
|
384
432
|
handleRequest(request: Request): Promise<Response>;
|
|
385
433
|
/**
|
|
386
|
-
* Reload
|
|
387
|
-
*
|
|
434
|
+
* Reload workers with new entrypoint (hot reload)
|
|
435
|
+
*
|
|
436
|
+
* With unified builds, hot reload means:
|
|
437
|
+
* 1. Gracefully shutdown existing workers (close databases, etc.)
|
|
438
|
+
* 2. Terminate workers after resources are closed
|
|
439
|
+
* 3. Create new workers with the new bundle
|
|
388
440
|
*/
|
|
389
441
|
reloadWorkers(entrypoint: string): Promise<void>;
|
|
390
442
|
/**
|
|
@@ -402,3 +454,4 @@ export declare class ServiceWorkerPool {
|
|
|
402
454
|
}
|
|
403
455
|
export { CustomLoggerStorage, type LoggerStorage };
|
|
404
456
|
export type { LoggerFactory } from "./runtime.js";
|
|
457
|
+
export { CustomDatabaseStorage, createDatabaseFactory, type DatabaseStorage, type DatabaseConfig, type DatabaseFactory, type DatabaseUpgradeEvent, } from "./runtime.js";
|