lopata 0.0.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.
- package/README.md +15 -0
- package/package.json +51 -0
- package/runtime/bindings/ai.ts +132 -0
- package/runtime/bindings/analytics-engine.ts +96 -0
- package/runtime/bindings/browser.ts +64 -0
- package/runtime/bindings/cache.ts +179 -0
- package/runtime/bindings/cf-streams.ts +56 -0
- package/runtime/bindings/container-docker.ts +225 -0
- package/runtime/bindings/container.ts +662 -0
- package/runtime/bindings/crypto-extras.ts +89 -0
- package/runtime/bindings/d1.ts +315 -0
- package/runtime/bindings/do-executor-inprocess.ts +140 -0
- package/runtime/bindings/do-executor-worker.ts +368 -0
- package/runtime/bindings/do-executor.ts +45 -0
- package/runtime/bindings/do-websocket-bridge.ts +70 -0
- package/runtime/bindings/do-worker-entry.ts +220 -0
- package/runtime/bindings/do-worker-env.ts +74 -0
- package/runtime/bindings/durable-object.ts +992 -0
- package/runtime/bindings/email.ts +180 -0
- package/runtime/bindings/html-rewriter.ts +84 -0
- package/runtime/bindings/hyperdrive.ts +130 -0
- package/runtime/bindings/images.ts +381 -0
- package/runtime/bindings/kv.ts +359 -0
- package/runtime/bindings/queue.ts +507 -0
- package/runtime/bindings/r2.ts +759 -0
- package/runtime/bindings/rpc-stub.ts +267 -0
- package/runtime/bindings/scheduled.ts +172 -0
- package/runtime/bindings/service-binding.ts +217 -0
- package/runtime/bindings/static-assets.ts +481 -0
- package/runtime/bindings/websocket-pair.ts +182 -0
- package/runtime/bindings/workflow.ts +858 -0
- package/runtime/bunflare-config.ts +56 -0
- package/runtime/cli/cache.ts +39 -0
- package/runtime/cli/context.ts +105 -0
- package/runtime/cli/d1.ts +163 -0
- package/runtime/cli/dev.ts +392 -0
- package/runtime/cli/kv.ts +84 -0
- package/runtime/cli/queues.ts +109 -0
- package/runtime/cli/r2.ts +140 -0
- package/runtime/cli/traces.ts +251 -0
- package/runtime/cli.ts +102 -0
- package/runtime/config.ts +148 -0
- package/runtime/d1-migrate.ts +37 -0
- package/runtime/dashboard/api.ts +174 -0
- package/runtime/dashboard/app.tsx +220 -0
- package/runtime/dashboard/components/breadcrumb.tsx +16 -0
- package/runtime/dashboard/components/buttons.tsx +13 -0
- package/runtime/dashboard/components/code-block.tsx +5 -0
- package/runtime/dashboard/components/detail-field.tsx +8 -0
- package/runtime/dashboard/components/empty-state.tsx +8 -0
- package/runtime/dashboard/components/filter-input.tsx +11 -0
- package/runtime/dashboard/components/index.ts +16 -0
- package/runtime/dashboard/components/key-value-table.tsx +23 -0
- package/runtime/dashboard/components/modal.tsx +23 -0
- package/runtime/dashboard/components/page-header.tsx +11 -0
- package/runtime/dashboard/components/pill-button.tsx +14 -0
- package/runtime/dashboard/components/refresh-button.tsx +7 -0
- package/runtime/dashboard/components/service-info.tsx +45 -0
- package/runtime/dashboard/components/status-badge.tsx +7 -0
- package/runtime/dashboard/components/table-link.tsx +5 -0
- package/runtime/dashboard/components/table.tsx +26 -0
- package/runtime/dashboard/components.tsx +19 -0
- package/runtime/dashboard/index.html +23 -0
- package/runtime/dashboard/lib.ts +45 -0
- package/runtime/dashboard/rpc/client.ts +20 -0
- package/runtime/dashboard/rpc/handlers/ai.ts +71 -0
- package/runtime/dashboard/rpc/handlers/analytics-engine.ts +53 -0
- package/runtime/dashboard/rpc/handlers/cache.ts +24 -0
- package/runtime/dashboard/rpc/handlers/config.ts +137 -0
- package/runtime/dashboard/rpc/handlers/containers.ts +194 -0
- package/runtime/dashboard/rpc/handlers/d1.ts +84 -0
- package/runtime/dashboard/rpc/handlers/do.ts +117 -0
- package/runtime/dashboard/rpc/handlers/email.ts +82 -0
- package/runtime/dashboard/rpc/handlers/errors.ts +32 -0
- package/runtime/dashboard/rpc/handlers/generations.ts +60 -0
- package/runtime/dashboard/rpc/handlers/kv.ts +76 -0
- package/runtime/dashboard/rpc/handlers/overview.ts +94 -0
- package/runtime/dashboard/rpc/handlers/queue.ts +79 -0
- package/runtime/dashboard/rpc/handlers/r2.ts +72 -0
- package/runtime/dashboard/rpc/handlers/scheduled.ts +91 -0
- package/runtime/dashboard/rpc/handlers/traces.ts +64 -0
- package/runtime/dashboard/rpc/handlers/workers.ts +65 -0
- package/runtime/dashboard/rpc/handlers/workflows.ts +171 -0
- package/runtime/dashboard/rpc/hooks.ts +132 -0
- package/runtime/dashboard/rpc/server.ts +70 -0
- package/runtime/dashboard/rpc/types.ts +396 -0
- package/runtime/dashboard/sql-browser/data-browser-tab.tsx +122 -0
- package/runtime/dashboard/sql-browser/editable-cell.tsx +117 -0
- package/runtime/dashboard/sql-browser/filter-row.tsx +99 -0
- package/runtime/dashboard/sql-browser/history-panels.tsx +110 -0
- package/runtime/dashboard/sql-browser/hooks.ts +137 -0
- package/runtime/dashboard/sql-browser/index.ts +4 -0
- package/runtime/dashboard/sql-browser/insert-row-form.tsx +85 -0
- package/runtime/dashboard/sql-browser/modals.tsx +116 -0
- package/runtime/dashboard/sql-browser/schema-browser-tab.tsx +67 -0
- package/runtime/dashboard/sql-browser/sql-browser.tsx +52 -0
- package/runtime/dashboard/sql-browser/sql-console-tab.tsx +124 -0
- package/runtime/dashboard/sql-browser/table-data-view.tsx +566 -0
- package/runtime/dashboard/sql-browser/table-sidebar.tsx +38 -0
- package/runtime/dashboard/sql-browser/types.ts +61 -0
- package/runtime/dashboard/sql-browser/utils.ts +167 -0
- package/runtime/dashboard/style.css +177 -0
- package/runtime/dashboard/views/ai.tsx +152 -0
- package/runtime/dashboard/views/analytics-engine.tsx +169 -0
- package/runtime/dashboard/views/cache.tsx +93 -0
- package/runtime/dashboard/views/containers.tsx +197 -0
- package/runtime/dashboard/views/d1.tsx +81 -0
- package/runtime/dashboard/views/do.tsx +168 -0
- package/runtime/dashboard/views/email.tsx +235 -0
- package/runtime/dashboard/views/errors.tsx +558 -0
- package/runtime/dashboard/views/home.tsx +287 -0
- package/runtime/dashboard/views/kv.tsx +273 -0
- package/runtime/dashboard/views/queue.tsx +193 -0
- package/runtime/dashboard/views/r2.tsx +202 -0
- package/runtime/dashboard/views/scheduled.tsx +89 -0
- package/runtime/dashboard/views/trace-waterfall.tsx +410 -0
- package/runtime/dashboard/views/traces.tsx +768 -0
- package/runtime/dashboard/views/workers.tsx +55 -0
- package/runtime/dashboard/views/workflows.tsx +473 -0
- package/runtime/db.ts +258 -0
- package/runtime/env.ts +362 -0
- package/runtime/error-page/app.tsx +394 -0
- package/runtime/error-page/build.ts +269 -0
- package/runtime/error-page/index.html +16 -0
- package/runtime/error-page/style.css +31 -0
- package/runtime/execution-context.ts +18 -0
- package/runtime/file-watcher.ts +57 -0
- package/runtime/generation-manager.ts +230 -0
- package/runtime/generation.ts +411 -0
- package/runtime/plugin.ts +292 -0
- package/runtime/request-cf.ts +28 -0
- package/runtime/rpc-validate.ts +154 -0
- package/runtime/tracing/context.ts +40 -0
- package/runtime/tracing/db.ts +73 -0
- package/runtime/tracing/frames.ts +75 -0
- package/runtime/tracing/instrument.ts +186 -0
- package/runtime/tracing/span.ts +138 -0
- package/runtime/tracing/store.ts +499 -0
- package/runtime/tracing/types.ts +47 -0
- package/runtime/vite-plugin/config-plugin.ts +68 -0
- package/runtime/vite-plugin/dev-server-plugin.ts +493 -0
- package/runtime/vite-plugin/dist/index.mjs +52333 -0
- package/runtime/vite-plugin/globals-plugin.ts +94 -0
- package/runtime/vite-plugin/index.ts +43 -0
- package/runtime/vite-plugin/modules-plugin.ts +88 -0
- package/runtime/vite-plugin/react-router-plugin.ts +95 -0
- package/runtime/worker-registry.ts +52 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
|
|
3
|
+
let initialized = false;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Sets up global Cloudflare-compatible APIs in the Bun process:
|
|
7
|
+
* caches, HTMLRewriter, WebSocketPair, IdentityTransformStream, FixedLengthStream,
|
|
8
|
+
* navigator.userAgent, scheduler.wait(), crypto extensions.
|
|
9
|
+
*
|
|
10
|
+
* Runs once on configureServer (before middleware), idempotent.
|
|
11
|
+
* Imports are lazy because the plugin is externalized by Vite's config bundler —
|
|
12
|
+
* dynamic imports run at dev server startup time through Bun's native loader.
|
|
13
|
+
*/
|
|
14
|
+
export function globalsPlugin(): Plugin {
|
|
15
|
+
return {
|
|
16
|
+
name: "bunflare:globals",
|
|
17
|
+
|
|
18
|
+
async configureServer() {
|
|
19
|
+
if (initialized) return;
|
|
20
|
+
initialized = true;
|
|
21
|
+
|
|
22
|
+
const { SqliteCacheStorage } = await import("../bindings/cache.ts");
|
|
23
|
+
const { HTMLRewriter } = await import("../bindings/html-rewriter.ts");
|
|
24
|
+
const { WebSocketPair } = await import("../bindings/websocket-pair.ts");
|
|
25
|
+
const { IdentityTransformStream, FixedLengthStream } = await import("../bindings/cf-streams.ts");
|
|
26
|
+
const { patchGlobalCrypto } = await import("../bindings/crypto-extras.ts");
|
|
27
|
+
const { getDatabase } = await import("../db.ts");
|
|
28
|
+
const { instrumentBinding } = await import("../tracing/instrument.ts");
|
|
29
|
+
|
|
30
|
+
// Global caches (CacheStorage)
|
|
31
|
+
const cacheMethods = ["match", "put", "delete"];
|
|
32
|
+
const rawCacheStorage = new SqliteCacheStorage(getDatabase());
|
|
33
|
+
rawCacheStorage.default = instrumentBinding(rawCacheStorage.default, {
|
|
34
|
+
type: "cache", name: "default", methods: cacheMethods,
|
|
35
|
+
}) as typeof rawCacheStorage.default;
|
|
36
|
+
|
|
37
|
+
const originalOpen = rawCacheStorage.open.bind(rawCacheStorage);
|
|
38
|
+
rawCacheStorage.open = async (cacheName: string) => {
|
|
39
|
+
const cache = await originalOpen(cacheName);
|
|
40
|
+
return instrumentBinding(cache, {
|
|
41
|
+
type: "cache", name: cacheName, methods: cacheMethods,
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
Object.defineProperty(globalThis, "caches", {
|
|
46
|
+
value: rawCacheStorage,
|
|
47
|
+
writable: false,
|
|
48
|
+
configurable: true,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
Object.defineProperty(globalThis, "HTMLRewriter", {
|
|
52
|
+
value: HTMLRewriter,
|
|
53
|
+
writable: false,
|
|
54
|
+
configurable: true,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
Object.defineProperty(globalThis, "WebSocketPair", {
|
|
58
|
+
value: WebSocketPair,
|
|
59
|
+
writable: false,
|
|
60
|
+
configurable: true,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
Object.defineProperty(globalThis, "IdentityTransformStream", {
|
|
64
|
+
value: IdentityTransformStream,
|
|
65
|
+
writable: false,
|
|
66
|
+
configurable: true,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
Object.defineProperty(globalThis, "FixedLengthStream", {
|
|
70
|
+
value: FixedLengthStream,
|
|
71
|
+
writable: false,
|
|
72
|
+
configurable: true,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
patchGlobalCrypto();
|
|
76
|
+
|
|
77
|
+
Object.defineProperty(globalThis.navigator, "userAgent", {
|
|
78
|
+
value: "Cloudflare-Workers",
|
|
79
|
+
writable: false,
|
|
80
|
+
configurable: true,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
Object.defineProperty(globalThis, "scheduler", {
|
|
84
|
+
value: {
|
|
85
|
+
wait(ms: number): Promise<void> {
|
|
86
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
writable: false,
|
|
90
|
+
configurable: true,
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
import { configPlugin } from "./config-plugin.ts";
|
|
3
|
+
import { modulesPlugin } from "./modules-plugin.ts";
|
|
4
|
+
import { globalsPlugin } from "./globals-plugin.ts";
|
|
5
|
+
import { devServerPlugin } from "./dev-server-plugin.ts";
|
|
6
|
+
import { reactRouterPlugin } from "./react-router-plugin.ts";
|
|
7
|
+
|
|
8
|
+
export interface BunflarePluginConfig {
|
|
9
|
+
/** Path to wrangler.jsonc/.json/.toml config. Auto-detected if not specified. */
|
|
10
|
+
configPath?: string;
|
|
11
|
+
/** Vite environment name for SSR. Default: "ssr" */
|
|
12
|
+
viteEnvironment?: { name?: string };
|
|
13
|
+
/** Auxiliary workers loaded via native Bun import (not through Vite). */
|
|
14
|
+
auxiliaryWorkers?: { configPath: string }[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Bunflare Vite plugin — drop-in replacement for `@cloudflare/vite-plugin`.
|
|
19
|
+
*
|
|
20
|
+
* Provides Cloudflare Worker compatibility in Vite dev mode:
|
|
21
|
+
* - CF module resolution (cloudflare:workers, cloudflare:workflows, @cloudflare/containers)
|
|
22
|
+
* - Global CF APIs (caches, HTMLRewriter, WebSocketPair, etc.)
|
|
23
|
+
* - Bindings (KV, R2, D1, DO, Workflows, Queues, etc.) backed by SQLite/FS
|
|
24
|
+
* - SSR middleware that calls worker.fetch() with the built env
|
|
25
|
+
*
|
|
26
|
+
* Install as a dependency (or link:) so Vite externalizes it at config bundle time.
|
|
27
|
+
* Runtime imports then go through Bun's native module loader.
|
|
28
|
+
*/
|
|
29
|
+
export function bunflare(config?: BunflarePluginConfig): Plugin[] {
|
|
30
|
+
const envName = config?.viteEnvironment?.name ?? "ssr";
|
|
31
|
+
|
|
32
|
+
return [
|
|
33
|
+
configPlugin(envName),
|
|
34
|
+
modulesPlugin(envName),
|
|
35
|
+
globalsPlugin(),
|
|
36
|
+
devServerPlugin({
|
|
37
|
+
configPath: config?.configPath,
|
|
38
|
+
envName,
|
|
39
|
+
auxiliaryWorkers: config?.auxiliaryWorkers,
|
|
40
|
+
}),
|
|
41
|
+
reactRouterPlugin(),
|
|
42
|
+
];
|
|
43
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { resolve, dirname } from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import type { Plugin } from "vite";
|
|
4
|
+
|
|
5
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
|
|
7
|
+
const VIRTUAL_MODULES: Record<string, string> = {
|
|
8
|
+
"cloudflare:workers": "\0cloudflare:workers",
|
|
9
|
+
"cloudflare:workflows": "\0cloudflare:workflows",
|
|
10
|
+
"@cloudflare/containers": "\0@cloudflare/containers",
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
function resolvePath(relativePath: string): string {
|
|
14
|
+
return resolve(__dirname, "..", relativePath);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Resolves Cloudflare virtual modules (cloudflare:workers, cloudflare:workflows,
|
|
19
|
+
* @cloudflare/containers) to re-exports from Bunflare runtime binding implementations.
|
|
20
|
+
*
|
|
21
|
+
* Only active in the SSR environment.
|
|
22
|
+
*/
|
|
23
|
+
export function modulesPlugin(envName: string): Plugin {
|
|
24
|
+
return {
|
|
25
|
+
name: "bunflare:modules",
|
|
26
|
+
|
|
27
|
+
resolveId(id: string) {
|
|
28
|
+
if (this.environment?.name !== envName) return;
|
|
29
|
+
if (id in VIRTUAL_MODULES) {
|
|
30
|
+
return VIRTUAL_MODULES[id];
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
load(id: string) {
|
|
35
|
+
if (id === "\0cloudflare:workers") {
|
|
36
|
+
const durableObject = resolvePath("bindings/durable-object");
|
|
37
|
+
const workflow = resolvePath("bindings/workflow");
|
|
38
|
+
const websocketPair = resolvePath("bindings/websocket-pair");
|
|
39
|
+
|
|
40
|
+
// env is a proxy to globalThis.__bunflare_env so it works across
|
|
41
|
+
// Vite SSR runner and native Bun module graphs (which are separate
|
|
42
|
+
// module instances — a direct re-export of globalEnv would be empty
|
|
43
|
+
// in the SSR runner because setGlobalEnv() writes to the native instance).
|
|
44
|
+
return `
|
|
45
|
+
export { DurableObjectBase as DurableObject } from "${durableObject}";
|
|
46
|
+
export { WorkflowEntrypointBase as WorkflowEntrypoint } from "${workflow}";
|
|
47
|
+
export { WebSocketRequestResponsePair } from "${durableObject}";
|
|
48
|
+
export { WebSocketPair } from "${websocketPair}";
|
|
49
|
+
export const env = new Proxy({}, {
|
|
50
|
+
get(_, prop) { return globalThis.__bunflare_env?.[prop]; },
|
|
51
|
+
set(_, prop, value) { if (globalThis.__bunflare_env) globalThis.__bunflare_env[prop] = value; return true; },
|
|
52
|
+
has(_, prop) { return prop in (globalThis.__bunflare_env ?? {}); },
|
|
53
|
+
ownKeys() { return Object.keys(globalThis.__bunflare_env ?? {}); },
|
|
54
|
+
getOwnPropertyDescriptor(_, prop) {
|
|
55
|
+
const target = globalThis.__bunflare_env;
|
|
56
|
+
if (target && prop in target) return { configurable: true, enumerable: true, value: target[prop] };
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
export class WorkerEntrypoint {
|
|
60
|
+
constructor(ctx, env) {
|
|
61
|
+
this.ctx = ctx;
|
|
62
|
+
this.env = env;
|
|
63
|
+
this[Symbol.for("bunflare.RpcTarget")] = true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export class RpcTarget {
|
|
67
|
+
constructor() {
|
|
68
|
+
this[Symbol.for("bunflare.RpcTarget")] = true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (id === "\0cloudflare:workflows") {
|
|
75
|
+
const workflow = resolvePath("bindings/workflow");
|
|
76
|
+
return `export { NonRetryableError } from "${workflow}";`;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (id === "\0@cloudflare/containers") {
|
|
80
|
+
const container = resolvePath("bindings/container");
|
|
81
|
+
return `
|
|
82
|
+
export { ContainerBase as Container } from "${container}";
|
|
83
|
+
export { getContainer, getRandom } from "${container}";
|
|
84
|
+
`;
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
|
|
3
|
+
const SERVER_BUILD_ID = "\0virtual:react-router/server-build";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Instruments React Router loaders, actions, and SSR rendering with
|
|
7
|
+
* Bunflare tracing spans via the `unstable_instrumentations` API.
|
|
8
|
+
*
|
|
9
|
+
* Works by transforming React Router's `virtual:react-router/server-build`
|
|
10
|
+
* virtual module to inject an `unstable_ServerInstrumentation` and wrap
|
|
11
|
+
* the `handleRequest` (default export) with a render span.
|
|
12
|
+
*
|
|
13
|
+
* Uses the `globalThis.__bunflare_startSpan` bridge set up by
|
|
14
|
+
* `dev-server-plugin.ts` to call into the tracing runtime, which lives
|
|
15
|
+
* in Bun's native module graph (separate from Vite's SSR runner).
|
|
16
|
+
*
|
|
17
|
+
* If React Router is not used, this plugin is a no-op.
|
|
18
|
+
*/
|
|
19
|
+
export function reactRouterPlugin(): Plugin {
|
|
20
|
+
return {
|
|
21
|
+
name: "bunflare:react-router",
|
|
22
|
+
|
|
23
|
+
transform(code, id) {
|
|
24
|
+
if (id !== SERVER_BUILD_ID) return;
|
|
25
|
+
|
|
26
|
+
// Replace the `export const entry = { module: entryServer };` line
|
|
27
|
+
// with our instrumented version that adds tracing.
|
|
28
|
+
const entryPattern = /export const entry\s*=\s*\{\s*module:\s*entryServer\s*\};/;
|
|
29
|
+
|
|
30
|
+
if (!entryPattern.test(code)) return;
|
|
31
|
+
|
|
32
|
+
const injected = `
|
|
33
|
+
const __bf_instr = {
|
|
34
|
+
route({ id, path, instrument }) {
|
|
35
|
+
instrument({
|
|
36
|
+
loader: async (callHandler, info) => {
|
|
37
|
+
const startSpan = globalThis.__bunflare_startSpan;
|
|
38
|
+
if (!startSpan) { await callHandler(); return; }
|
|
39
|
+
await startSpan({
|
|
40
|
+
name: "loader " + id,
|
|
41
|
+
kind: "internal",
|
|
42
|
+
attributes: {
|
|
43
|
+
"rr.type": "loader",
|
|
44
|
+
"rr.route.id": id,
|
|
45
|
+
"rr.route.pattern": info?.unstable_pattern,
|
|
46
|
+
},
|
|
47
|
+
}, async () => {
|
|
48
|
+
const result = await callHandler();
|
|
49
|
+
if (result.status === "error") throw result.error;
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
action: async (callHandler, info) => {
|
|
53
|
+
const startSpan = globalThis.__bunflare_startSpan;
|
|
54
|
+
if (!startSpan) { await callHandler(); return; }
|
|
55
|
+
await startSpan({
|
|
56
|
+
name: "action " + id,
|
|
57
|
+
kind: "internal",
|
|
58
|
+
attributes: {
|
|
59
|
+
"rr.type": "action",
|
|
60
|
+
"rr.route.id": id,
|
|
61
|
+
"rr.route.pattern": info?.unstable_pattern,
|
|
62
|
+
},
|
|
63
|
+
}, async () => {
|
|
64
|
+
const result = await callHandler();
|
|
65
|
+
if (result.status === "error") throw result.error;
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const __bf_entry = {
|
|
73
|
+
...entryServer,
|
|
74
|
+
default: async function(...args) {
|
|
75
|
+
const startSpan = globalThis.__bunflare_startSpan;
|
|
76
|
+
if (!startSpan) return entryServer.default(...args);
|
|
77
|
+
return startSpan({
|
|
78
|
+
name: "react-router.render",
|
|
79
|
+
kind: "internal",
|
|
80
|
+
attributes: { "rr.type": "render" },
|
|
81
|
+
}, () => entryServer.default(...args));
|
|
82
|
+
},
|
|
83
|
+
unstable_instrumentations: [
|
|
84
|
+
...(entryServer.unstable_instrumentations || []),
|
|
85
|
+
__bf_instr,
|
|
86
|
+
],
|
|
87
|
+
};
|
|
88
|
+
export const entry = { module: __bf_entry };
|
|
89
|
+
`;
|
|
90
|
+
|
|
91
|
+
const transformed = code.replace(entryPattern, injected);
|
|
92
|
+
return { code: transformed, map: null };
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { GenerationManager } from "./generation-manager";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Central registry holding all worker GenerationManagers, keyed by worker name.
|
|
5
|
+
* Used to resolve cross-worker service bindings.
|
|
6
|
+
*/
|
|
7
|
+
export class WorkerRegistry {
|
|
8
|
+
private managers = new Map<string, GenerationManager>();
|
|
9
|
+
private mainName: string | null = null;
|
|
10
|
+
|
|
11
|
+
/** Register a worker's GenerationManager */
|
|
12
|
+
register(name: string, manager: GenerationManager, isMain = false): void {
|
|
13
|
+
this.managers.set(name, manager);
|
|
14
|
+
if (isMain) {
|
|
15
|
+
this.mainName = name;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Get manager by worker name */
|
|
20
|
+
getManager(name: string): GenerationManager | undefined {
|
|
21
|
+
return this.managers.get(name);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Get the main (HTTP entrypoint) worker's manager */
|
|
25
|
+
getMainManager(): GenerationManager {
|
|
26
|
+
if (!this.mainName) throw new Error("No main worker registered");
|
|
27
|
+
const manager = this.managers.get(this.mainName);
|
|
28
|
+
if (!manager) throw new Error("Main worker manager not found");
|
|
29
|
+
return manager;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Lazily resolve a target worker's module and env from its active generation.
|
|
34
|
+
* Called on each service binding invocation so hot-reloaded workers are picked up.
|
|
35
|
+
*/
|
|
36
|
+
resolveTarget(workerName: string): { workerModule: Record<string, unknown>; env: Record<string, unknown> } {
|
|
37
|
+
const manager = this.managers.get(workerName);
|
|
38
|
+
if (!manager) {
|
|
39
|
+
throw new Error(`Worker "${workerName}" is not registered in the worker registry`);
|
|
40
|
+
}
|
|
41
|
+
const gen = manager.active;
|
|
42
|
+
if (!gen) {
|
|
43
|
+
throw new Error(`Worker "${workerName}" has no active generation (failed to load?)`);
|
|
44
|
+
}
|
|
45
|
+
return { workerModule: gen.workerModule, env: gen.env };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** List all registered managers (for dashboard) */
|
|
49
|
+
listManagers(): Map<string, GenerationManager> {
|
|
50
|
+
return this.managers;
|
|
51
|
+
}
|
|
52
|
+
}
|