@b9g/platform 0.1.12 → 0.1.13
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 +24 -16
- 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 +105 -41
- package/src/index.js +174 -219
- package/src/runtime.d.ts +315 -62
- package/src/runtime.js +424 -129
- package/chunk-P57PW2II.js +0 -11
- package/src/worker.d.ts +0 -39
- package/src/worker.js +0 -285
package/chunk-P57PW2II.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
-
}) : x)(function(x) {
|
|
4
|
-
if (typeof require !== "undefined")
|
|
5
|
-
return require.apply(this, arguments);
|
|
6
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
export {
|
|
10
|
-
__require
|
|
11
|
-
};
|
package/src/worker.d.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Worker Entry Point for MultiThreadedRuntime
|
|
3
|
-
*
|
|
4
|
-
* This is the explicit entry point for worker threads spawned by MultiThreadedRuntime.
|
|
5
|
-
* It sets up message handling and initializes the ServiceWorker runtime.
|
|
6
|
-
*
|
|
7
|
-
* This file is loaded directly as a Worker script - no detection needed.
|
|
8
|
-
*
|
|
9
|
-
* BOOTSTRAP ORDER:
|
|
10
|
-
* 1. Create placeholder caches/directories with deferred factories
|
|
11
|
-
* 2. Create and install ServiceWorkerGlobals (provides `self`, `addEventListener`, etc.)
|
|
12
|
-
* 3. Set up message handlers using `self.addEventListener`
|
|
13
|
-
* 4. Wait for "init" message to configure factories with real config
|
|
14
|
-
* 5. Wait for "load" message to load and activate ServiceWorker
|
|
15
|
-
*/
|
|
16
|
-
import { Cache } from "@b9g/cache";
|
|
17
|
-
import { type ShovelConfig } from "./runtime.js";
|
|
18
|
-
export interface DirectoryFactoryOptions {
|
|
19
|
-
/** Base directory for path resolution (entrypoint directory) - REQUIRED */
|
|
20
|
-
baseDir: string;
|
|
21
|
-
/** Shovel configuration for overrides */
|
|
22
|
-
config?: ShovelConfig;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Creates a directory factory function for CustomDirectoryStorage.
|
|
26
|
-
*/
|
|
27
|
-
export declare function createDirectoryFactory(options: DirectoryFactoryOptions): (name: string) => Promise<FileSystemDirectoryHandle>;
|
|
28
|
-
export interface CacheFactoryOptions {
|
|
29
|
-
/** Shovel configuration for cache settings */
|
|
30
|
-
config?: ShovelConfig;
|
|
31
|
-
/** Default provider when not specified in config. Defaults to "memory". */
|
|
32
|
-
defaultProvider?: string;
|
|
33
|
-
/** If true, use PostMessageCache for memory caches (for workers) */
|
|
34
|
-
usePostMessage?: boolean;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Creates a cache factory function for CustomCacheStorage.
|
|
38
|
-
*/
|
|
39
|
-
export declare function createCacheFactory(options?: CacheFactoryOptions): (name: string) => Promise<Cache>;
|
package/src/worker.js
DELETED
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
/// <reference types="./worker.d.ts" />
|
|
2
|
-
import "../chunk-P57PW2II.js";
|
|
3
|
-
|
|
4
|
-
// src/worker.ts
|
|
5
|
-
import { resolve } from "path";
|
|
6
|
-
import { getLogger } from "@logtape/logtape";
|
|
7
|
-
import { CustomDirectoryStorage } from "@b9g/filesystem";
|
|
8
|
-
import { CustomCacheStorage } from "@b9g/cache";
|
|
9
|
-
import { handleCacheResponse, PostMessageCache } from "@b9g/cache/postmessage";
|
|
10
|
-
import {
|
|
11
|
-
ServiceWorkerGlobals,
|
|
12
|
-
ShovelServiceWorkerRegistration,
|
|
13
|
-
CustomLoggerStorage,
|
|
14
|
-
configureLogging
|
|
15
|
-
} from "./runtime.js";
|
|
16
|
-
function matchPattern(name, patterns) {
|
|
17
|
-
if (!patterns)
|
|
18
|
-
return void 0;
|
|
19
|
-
if (patterns[name])
|
|
20
|
-
return patterns[name];
|
|
21
|
-
for (const [pattern, value] of Object.entries(patterns)) {
|
|
22
|
-
if (pattern.includes("*")) {
|
|
23
|
-
const regex = new RegExp("^" + pattern.replace(/\*/g, ".*") + "$");
|
|
24
|
-
if (regex.test(name))
|
|
25
|
-
return value;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return void 0;
|
|
29
|
-
}
|
|
30
|
-
function getCacheConfig(config, name) {
|
|
31
|
-
return matchPattern(name, config.caches) || {};
|
|
32
|
-
}
|
|
33
|
-
function getDirectoryConfig(config, name) {
|
|
34
|
-
return matchPattern(name, config.directories) || {};
|
|
35
|
-
}
|
|
36
|
-
var WELL_KNOWN_DIRECTORY_PATHS = {
|
|
37
|
-
static: (baseDir) => resolve(baseDir, "../static"),
|
|
38
|
-
server: (baseDir) => baseDir
|
|
39
|
-
};
|
|
40
|
-
var BUILTIN_DIRECTORY_PROVIDERS = {
|
|
41
|
-
node: "@b9g/filesystem/node.js",
|
|
42
|
-
memory: "@b9g/filesystem/memory.js",
|
|
43
|
-
s3: "@b9g/filesystem-s3"
|
|
44
|
-
};
|
|
45
|
-
function createDirectoryFactory(options) {
|
|
46
|
-
const { baseDir, config } = options;
|
|
47
|
-
return async (name) => {
|
|
48
|
-
const dirConfig = config ? getDirectoryConfig(config, name) : {};
|
|
49
|
-
let dirPath;
|
|
50
|
-
if (dirConfig.path) {
|
|
51
|
-
dirPath = String(dirConfig.path);
|
|
52
|
-
} else if (WELL_KNOWN_DIRECTORY_PATHS[name]) {
|
|
53
|
-
dirPath = WELL_KNOWN_DIRECTORY_PATHS[name](baseDir);
|
|
54
|
-
} else {
|
|
55
|
-
dirPath = resolve(baseDir, `../${name}`);
|
|
56
|
-
}
|
|
57
|
-
const provider = String(dirConfig.provider || "node");
|
|
58
|
-
const modulePath = BUILTIN_DIRECTORY_PROVIDERS[provider] || provider;
|
|
59
|
-
if (modulePath === "@b9g/filesystem/node.js") {
|
|
60
|
-
const { NodeDirectory } = await import("@b9g/filesystem/node.js");
|
|
61
|
-
return new NodeDirectory(dirPath);
|
|
62
|
-
}
|
|
63
|
-
if (modulePath === "@b9g/filesystem/memory.js") {
|
|
64
|
-
const { MemoryDirectory } = await import("@b9g/filesystem/memory.js");
|
|
65
|
-
return new MemoryDirectory(name);
|
|
66
|
-
}
|
|
67
|
-
const module = await import(modulePath);
|
|
68
|
-
const DirectoryClass = module.default || module.S3Directory || module.Directory || Object.values(module).find(
|
|
69
|
-
(v) => typeof v === "function" && v.name?.includes("Directory")
|
|
70
|
-
);
|
|
71
|
-
if (!DirectoryClass) {
|
|
72
|
-
throw new Error(
|
|
73
|
-
`Directory module "${modulePath}" does not export a valid directory class.`
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
const { provider: _, path: __, ...dirOptions } = dirConfig;
|
|
77
|
-
return new DirectoryClass(name, { path: dirPath, ...dirOptions });
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
var BUILTIN_CACHE_PROVIDERS = {
|
|
81
|
-
memory: "@b9g/cache/memory.js",
|
|
82
|
-
redis: "@b9g/cache-redis"
|
|
83
|
-
};
|
|
84
|
-
function createCacheFactory(options = {}) {
|
|
85
|
-
const { config, defaultProvider = "memory", usePostMessage = false } = options;
|
|
86
|
-
return async (name) => {
|
|
87
|
-
const cacheConfig = config ? getCacheConfig(config, name) : {};
|
|
88
|
-
const provider = String(cacheConfig.provider || defaultProvider);
|
|
89
|
-
if (provider === "cloudflare") {
|
|
90
|
-
const nativeCaches = globalThis.__cloudflareCaches ?? globalThis.caches;
|
|
91
|
-
if (!nativeCaches) {
|
|
92
|
-
throw new Error(
|
|
93
|
-
"Cloudflare cache provider requires native caches API."
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
return nativeCaches.open(name);
|
|
97
|
-
}
|
|
98
|
-
if (provider === "memory" && usePostMessage) {
|
|
99
|
-
return new PostMessageCache(name);
|
|
100
|
-
}
|
|
101
|
-
const { provider: _, ...cacheOptions } = cacheConfig;
|
|
102
|
-
const modulePath = BUILTIN_CACHE_PROVIDERS[provider] || provider;
|
|
103
|
-
const module = await import(modulePath);
|
|
104
|
-
const CacheClass = module.default || module.RedisCache || module.MemoryCache || module.Cache || Object.values(module).find(
|
|
105
|
-
(v) => typeof v === "function" && v.name?.includes("Cache")
|
|
106
|
-
);
|
|
107
|
-
if (!CacheClass) {
|
|
108
|
-
throw new Error(
|
|
109
|
-
`Cache module "${modulePath}" does not export a valid cache class.`
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
return new CacheClass(name, cacheOptions);
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
var workerId = Math.random().toString(36).substring(2, 8);
|
|
116
|
-
var resolveCacheFactory;
|
|
117
|
-
var resolveDirectoryFactory;
|
|
118
|
-
var cacheFactoryPromise = new Promise((resolve2) => {
|
|
119
|
-
resolveCacheFactory = resolve2;
|
|
120
|
-
});
|
|
121
|
-
var directoryFactoryPromise = new Promise((resolve2) => {
|
|
122
|
-
resolveDirectoryFactory = resolve2;
|
|
123
|
-
});
|
|
124
|
-
var caches = new CustomCacheStorage(async (name) => {
|
|
125
|
-
const factory = await cacheFactoryPromise;
|
|
126
|
-
return factory(name);
|
|
127
|
-
});
|
|
128
|
-
var directories = new CustomDirectoryStorage(async (name) => {
|
|
129
|
-
const factory = await directoryFactoryPromise;
|
|
130
|
-
return factory(name);
|
|
131
|
-
});
|
|
132
|
-
var loggers = new CustomLoggerStorage(
|
|
133
|
-
(...categories) => getLogger(categories)
|
|
134
|
-
);
|
|
135
|
-
var registration = new ShovelServiceWorkerRegistration();
|
|
136
|
-
var scope = new ServiceWorkerGlobals({
|
|
137
|
-
registration,
|
|
138
|
-
caches,
|
|
139
|
-
directories,
|
|
140
|
-
loggers
|
|
141
|
-
});
|
|
142
|
-
scope.install();
|
|
143
|
-
var logger = getLogger(["platform"]);
|
|
144
|
-
var sendMessage;
|
|
145
|
-
var serviceWorkerReady = false;
|
|
146
|
-
var loadedEntrypoint = null;
|
|
147
|
-
async function handleFetchEvent(request) {
|
|
148
|
-
if (!serviceWorkerReady) {
|
|
149
|
-
throw new Error("ServiceWorker not ready");
|
|
150
|
-
}
|
|
151
|
-
try {
|
|
152
|
-
return await registration.handleRequest(request);
|
|
153
|
-
} catch (error) {
|
|
154
|
-
logger.error("[Worker] ServiceWorker request failed: {error}", { error });
|
|
155
|
-
console.error("[Worker] ServiceWorker request failed:", error);
|
|
156
|
-
return new Response("ServiceWorker request failed", { status: 500 });
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
async function loadServiceWorker(entrypoint) {
|
|
160
|
-
try {
|
|
161
|
-
logger.debug("loadServiceWorker called", { entrypoint, loadedEntrypoint });
|
|
162
|
-
logger.info("[Worker] Loading from", { entrypoint });
|
|
163
|
-
if (loadedEntrypoint !== null && loadedEntrypoint !== entrypoint) {
|
|
164
|
-
logger.info(
|
|
165
|
-
`[Worker] Hot reload detected: ${loadedEntrypoint} -> ${entrypoint}`
|
|
166
|
-
);
|
|
167
|
-
logger.info("[Worker] Creating completely fresh ServiceWorker context");
|
|
168
|
-
registration = new ShovelServiceWorkerRegistration();
|
|
169
|
-
scope = new ServiceWorkerGlobals({
|
|
170
|
-
registration,
|
|
171
|
-
caches,
|
|
172
|
-
directories,
|
|
173
|
-
loggers
|
|
174
|
-
});
|
|
175
|
-
scope.install();
|
|
176
|
-
}
|
|
177
|
-
loadedEntrypoint = entrypoint;
|
|
178
|
-
const app = await import(entrypoint);
|
|
179
|
-
logger.debug("[Worker] ServiceWorker module loaded", {
|
|
180
|
-
exports: Object.keys(app)
|
|
181
|
-
});
|
|
182
|
-
logger.info("[Worker] Running install event");
|
|
183
|
-
await registration.install();
|
|
184
|
-
logger.info("[Worker] Running activate event");
|
|
185
|
-
await registration.activate();
|
|
186
|
-
serviceWorkerReady = true;
|
|
187
|
-
logger.info("[Worker] ServiceWorker ready", { entrypoint });
|
|
188
|
-
} catch (error) {
|
|
189
|
-
logger.error("[Worker] Failed to load ServiceWorker: {error}", {
|
|
190
|
-
error,
|
|
191
|
-
entrypoint
|
|
192
|
-
});
|
|
193
|
-
serviceWorkerReady = false;
|
|
194
|
-
throw error;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
async function initializeRuntime(config, baseDir) {
|
|
198
|
-
try {
|
|
199
|
-
if (config?.logging) {
|
|
200
|
-
await configureLogging(config.logging, { reset: true });
|
|
201
|
-
}
|
|
202
|
-
logger.info(`[Worker-${workerId}] Initializing runtime`, { config, baseDir });
|
|
203
|
-
logger.info(`[Worker-${workerId}] Configuring cache factory`);
|
|
204
|
-
resolveCacheFactory(createCacheFactory({ config, usePostMessage: true }));
|
|
205
|
-
logger.info(`[Worker-${workerId}] Configuring directory factory`);
|
|
206
|
-
resolveDirectoryFactory(createDirectoryFactory({ baseDir, config }));
|
|
207
|
-
logger.info(`[Worker-${workerId}] Runtime initialized successfully`);
|
|
208
|
-
} catch (error) {
|
|
209
|
-
logger.error(`[Worker-${workerId}] Failed to initialize runtime: {error}`, {
|
|
210
|
-
error
|
|
211
|
-
});
|
|
212
|
-
throw error;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
async function handleMessage(message) {
|
|
216
|
-
try {
|
|
217
|
-
logger.info(`[Worker-${workerId}] Received message`, { type: message.type });
|
|
218
|
-
if (message.type === "init") {
|
|
219
|
-
const initMsg = message;
|
|
220
|
-
await initializeRuntime(initMsg.config, initMsg.baseDir);
|
|
221
|
-
logger.info(`[Worker-${workerId}] Sending initialized message`);
|
|
222
|
-
sendMessage({ type: "initialized" });
|
|
223
|
-
} else if (message.type === "load") {
|
|
224
|
-
const loadMsg = message;
|
|
225
|
-
await loadServiceWorker(loadMsg.entrypoint);
|
|
226
|
-
sendMessage({ type: "ready", entrypoint: loadMsg.entrypoint });
|
|
227
|
-
} else if (message.type === "request") {
|
|
228
|
-
const reqMsg = message;
|
|
229
|
-
const request = new Request(reqMsg.request.url, {
|
|
230
|
-
method: reqMsg.request.method,
|
|
231
|
-
headers: reqMsg.request.headers,
|
|
232
|
-
body: reqMsg.request.body
|
|
233
|
-
});
|
|
234
|
-
const response = await handleFetchEvent(request);
|
|
235
|
-
const body = await response.arrayBuffer();
|
|
236
|
-
const headers = Object.fromEntries(response.headers.entries());
|
|
237
|
-
if (!headers["Content-Type"] && !headers["content-type"]) {
|
|
238
|
-
headers["Content-Type"] = "text/plain; charset=utf-8";
|
|
239
|
-
}
|
|
240
|
-
const responseMsg = {
|
|
241
|
-
type: "response",
|
|
242
|
-
response: {
|
|
243
|
-
status: response.status,
|
|
244
|
-
statusText: response.statusText,
|
|
245
|
-
headers,
|
|
246
|
-
body
|
|
247
|
-
},
|
|
248
|
-
requestID: reqMsg.requestID
|
|
249
|
-
};
|
|
250
|
-
sendMessage(responseMsg, [body]);
|
|
251
|
-
}
|
|
252
|
-
} catch (error) {
|
|
253
|
-
const errorMsg = {
|
|
254
|
-
type: "error",
|
|
255
|
-
error: error instanceof Error ? error.message : String(error),
|
|
256
|
-
stack: error instanceof Error ? error.stack : void 0,
|
|
257
|
-
requestID: message.requestID
|
|
258
|
-
};
|
|
259
|
-
sendMessage(errorMsg);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
self.addEventListener("message", (event) => {
|
|
263
|
-
const msg = event.data;
|
|
264
|
-
if (msg?.type === "cache:response" || msg?.type === "cache:error") {
|
|
265
|
-
logger.debug(`[Worker-${workerId}] Forwarding cache message`, {
|
|
266
|
-
type: msg.type,
|
|
267
|
-
requestID: msg.requestID
|
|
268
|
-
});
|
|
269
|
-
handleCacheResponse(msg);
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
void handleMessage(event.data);
|
|
273
|
-
});
|
|
274
|
-
sendMessage = (message, transfer) => {
|
|
275
|
-
if (transfer && transfer.length > 0) {
|
|
276
|
-
postMessage(message, transfer);
|
|
277
|
-
} else {
|
|
278
|
-
postMessage(message);
|
|
279
|
-
}
|
|
280
|
-
};
|
|
281
|
-
sendMessage({ type: "worker-ready" });
|
|
282
|
-
export {
|
|
283
|
-
createCacheFactory,
|
|
284
|
-
createDirectoryFactory
|
|
285
|
-
};
|