@moku-labs/worker 0.5.1 → 0.6.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/dist/index.mjs CHANGED
@@ -1,5 +1,36 @@
1
- import { a as defineDurableObject, c as coreConfig, d as stagePlugin, i as durableObjectsPlugin, l as createCore, n as queuesPlugin, o as d1Plugin, r as kvPlugin, s as bindingsPlugin, t as storagePlugin, u as createPlugin$1 } from "./storage-COo-F38H.mjs";
1
+ import { a as kvPlugin, c as d1Plugin, d as createCore, f as createPlugin$1, i as queuesPlugin, l as bindingsPlugin, n as deployPlugin, o as durableObjectsPlugin, p as stagePlugin, r as storagePlugin, s as defineDurableObject, t as cliPlugin, u as coreConfig } from "./cli-DgZv5A0G.mjs";
2
2
  import { envPlugin, logPlugin } from "@moku-labs/common";
3
+ //#region src/env-provider.ts
4
+ /**
5
+ * Build the default env provider: a shallow copy of `process.env` when a `process` global exists,
6
+ * else an empty record. Safe to evaluate at Worker cold start — it never throws on a missing
7
+ * `process` (typeof of an undeclared identifier is the string "undefined", not a ReferenceError).
8
+ *
9
+ * @returns An {@link EnvProvider} named `worker-process-env`.
10
+ * @example
11
+ * ```ts
12
+ * // wired by createApp so `ctx.env.get("CLOUDFLARE_API_TOKEN")` resolves under Bun/Node
13
+ * const provider = workerSafeProcessEnv();
14
+ * provider.load().CLOUDFLARE_API_TOKEN;
15
+ * ```
16
+ */
17
+ const workerSafeProcessEnv = () => ({
18
+ name: "worker-process-env",
19
+ /**
20
+ * Read a shallow copy of `process.env`, or `{}` when there is no `process` global (workerd
21
+ * without nodejs_compat). Never throws at cold start.
22
+ *
23
+ * @returns The current environment as a flat record (empty when `process` is absent).
24
+ * @example
25
+ * ```ts
26
+ * workerSafeProcessEnv().load();
27
+ * ```
28
+ */
29
+ load() {
30
+ return typeof process === "undefined" ? {} : { ...process.env };
31
+ }
32
+ });
33
+ //#endregion
3
34
  //#region src/plugins/server/api.ts
4
35
  /**
5
36
  * Builds the `app.server.*` surface the consumer's Worker default export reads.
@@ -483,50 +514,6 @@ const serverPlugin = createPlugin$1("server", {
483
514
  });
484
515
  //#endregion
485
516
  //#region src/index.ts
486
- /**
487
- * @file `@moku-labs/worker` — server-side Cloudflare Workers app + deploy framework on `@moku-labs/core`.
488
- *
489
- * The package root exports the bound {@link createApp} factory (the Layer-3 entry
490
- * point), {@link createPlugin} for consumer plugins, every runtime plugin instance,
491
- * the `server`/`durable-objects` helpers, and the framework types. Node-only tooling
492
- * (`deploy`, `cli`) ships from the separate `@moku-labs/worker/cli` entry, never here.
493
- *
494
- * `createApp(options?)` boots a fully-typed, synchronous, per-isolate app. The
495
- * framework defaults `[logPlugin, envPlugin, stagePlugin, bindingsPlugin, serverPlugin]`
496
- * are applied first, then the `options` below are shallow-merged on top:
497
- *
498
- * - `config` — `Partial<WorkerConfig>`; defaults `{ stage: "production", name: "moku-worker", compatibilityDate: "" }`.
499
- * `config.stage` is the single stage source: the framework mirrors it into the `stage` core
500
- * plugin so `ctx.stage.*` / `app.stage.*` stay in lockstep with `ctx.global.stage` (see {@link createApp}).
501
- * - `pluginConfigs` — per-plugin config overrides keyed by plugin name (e.g. `server.endpoints`, `bindings.required`); default `{}`.
502
- * - `plugins` — extra `PluginInstance[]` appended to the defaults; default `[]`. Do NOT re-list a default plugin.
503
- * - `onReady` — optional `(app) => void`, runs after every plugin's `onInit`.
504
- * - `onError` — optional `(error) => void` boot/lifecycle error handler.
505
- * - `onStart` / `onStop` — optional `() => void | Promise<void>` runtime lifecycle hooks (`app.start()` / `app.stop()`).
506
- *
507
- * Re-listing a default plugin name in `plugins` throws
508
- * `TypeError: [moku-worker] Duplicate plugin name: "<name>"` — `bindings` and `server`
509
- * are already wired, so consumers list only the resource plugins they add (`kv`, `d1`, …).
510
- *
511
- * Minimal HTTP Worker (shape taken from the server integration test):
512
- *
513
- * ```typescript
514
- * import { createApp, endpoint } from "@moku-labs/worker";
515
- *
516
- * export const app = createApp({
517
- * config: { name: "my-worker", compatibilityDate: "2024-09-23" },
518
- * pluginConfigs: {
519
- * server: { endpoints: [endpoint("/health").get(() => new Response("ok"))] }
520
- * }
521
- * });
522
- *
523
- * // worker.ts — the default export is hand-assembled; no plugin produces it.
524
- * export default {
525
- * fetch: (request: Request, env: Record<string, unknown>, ctx: ExecutionContext) =>
526
- * app.server.handle(request, env, ctx)
527
- * } satisfies ExportedHandler;
528
- * ```
529
- */
530
517
  const framework = createCore(coreConfig, { plugins: [bindingsPlugin, serverPlugin] });
531
518
  const { createPlugin } = framework;
532
519
  /** The core-bound app factory; wrapped by {@link createApp} to bridge `config.stage`. */
@@ -543,8 +530,11 @@ const boundCreateApp = framework.createApp;
543
530
  * that sees the consumer's chosen stage, so it mirrors `config.stage` into the stage
544
531
  * plugin's level-4 `pluginConfigs` override (`WorkerConfig.stage → pluginConfigs.stage.stage`).
545
532
  * When `config.stage` is omitted, the global config and the stage plugin both fall back
546
- * to their identical `"production"` default. See the module JSDoc above for the full
547
- * options/defaults table.
533
+ * to their identical `"production"` default. It ALSO wires a default workerd-safe
534
+ * {@link workerSafeProcessEnv} provider into the `env` core plugin (same bridge mechanism) so
535
+ * deploy/auth can read `CLOUDFLARE_API_TOKEN` and friends via `ctx.env` — without it the env plugin
536
+ * has zero providers and every `ctx.env` read is undefined. See the module JSDoc above for the
537
+ * full options/defaults table.
548
538
  *
549
539
  * @param options - The createApp options (`config`, `pluginConfigs`, `plugins`, and lifecycle callbacks).
550
540
  * @returns The initialized app — every plugin's `onInit` has already run.
@@ -552,18 +542,24 @@ const boundCreateApp = framework.createApp;
552
542
  * ```typescript
553
543
  * const app = createApp({ config: { stage: "development", name: "my-worker" } });
554
544
  * app.stage.isDev(); // true — bridged from config.stage
545
+ * app.env.get("CLOUDFLARE_API_TOKEN"); // read from process.env via the default env provider
555
546
  * ```
556
547
  */
557
548
  const createApp = (options) => {
558
549
  const explicitStage = options?.config?.stage;
559
- if (explicitStage === void 0) return boundCreateApp(options);
550
+ const provided = options?.pluginConfigs;
551
+ const pluginConfigs = {
552
+ ...options?.pluginConfigs,
553
+ env: {
554
+ ...provided?.env,
555
+ providers: provided?.env?.providers ?? [workerSafeProcessEnv()]
556
+ }
557
+ };
558
+ if (explicitStage !== void 0) pluginConfigs.stage = { stage: explicitStage };
560
559
  return boundCreateApp({
561
560
  ...options,
562
- pluginConfigs: {
563
- ...options?.pluginConfigs,
564
- stage: { stage: explicitStage }
565
- }
561
+ pluginConfigs
566
562
  });
567
563
  };
568
564
  //#endregion
569
- export { bindingsPlugin, createApp, createPlugin, d1Plugin, defineDurableObject, durableObjectsPlugin, endpoint, envPlugin, kvPlugin, logPlugin, queuesPlugin, serverPlugin, stagePlugin, storagePlugin };
565
+ export { bindingsPlugin, cliPlugin, createApp, createPlugin, d1Plugin, defineDurableObject, deployPlugin, durableObjectsPlugin, endpoint, envPlugin, kvPlugin, logPlugin, queuesPlugin, serverPlugin, stagePlugin, storagePlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moku-labs/worker",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "description": "Cloudflare Worker framework for Moku — Durable Objects, Queues, R2, D1, and KV plugins that compose with Moku Web.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,88 +0,0 @@
1
- import { PluginCtx } from "@moku-labs/core";
2
-
3
- //#region src/config.d.ts
4
- /** Per-request Cloudflare bindings object (env). Framework-level shared type. */
5
- type WorkerEnv = Record<string, unknown>;
6
- /** Global framework config — flat, with complete defaults. */
7
- type WorkerConfig = {
8
- stage: "production" | "development" | "test";
9
- name: string;
10
- compatibilityDate: string;
11
- };
12
- /** Global framework events — declared once, visible to every plugin. */
13
- type WorkerEvents = {
14
- "request:start": {
15
- method: string;
16
- path: string;
17
- requestId: string;
18
- };
19
- "request:end": {
20
- method: string;
21
- path: string;
22
- status: number;
23
- ms: number;
24
- };
25
- "deploy:phase": {
26
- phase: string;
27
- detail?: string;
28
- };
29
- "deploy:complete": {
30
- url: string;
31
- };
32
- "provision:resource": {
33
- kind: "kv" | "r2" | "d1" | "queue" | "do";
34
- name: string;
35
- };
36
- "provision:plan": {
37
- exists: number;
38
- missing: number;
39
- account: string;
40
- };
41
- "provision:skip": {
42
- kind: "kv" | "r2" | "d1" | "queue" | "do";
43
- name: string;
44
- };
45
- "auth:verified": {
46
- account: string;
47
- accountId: string;
48
- scopes: string[];
49
- };
50
- "dev:phase": {
51
- phase: string;
52
- detail?: string;
53
- };
54
- "dev:rebuilt": {
55
- files: number;
56
- ms: number;
57
- };
58
- "dev:error": {
59
- message: string;
60
- };
61
- };
62
- /**
63
- * Worker-bound plugin context for Layer-3 consumer plugins. Aliases the core
64
- * {@link PluginCtx} with the global {@link WorkerEvents} pre-merged into the event
65
- * map, so a consumer plugin types its own `config`/`state`/`emit` by passing only
66
- * its OWN event map — never hand-merging `WorkerEvents`, and never importing from
67
- * `@moku-labs/core` (a Layer-1 boundary the spec validator flags for consumers).
68
- *
69
- * A plugin that resolves sibling plugins also needs a `require` field; intersect the
70
- * public `Server.RequireFn` for it, exactly as this framework's own plugins do. When
71
- * you need the unaliased shape (e.g. a different global event map), use the raw
72
- * re-exported {@link PluginCtx} instead.
73
- *
74
- * @template Config - This plugin's own flat configuration object.
75
- * @template State - This plugin's mutable state (use `Record<string, never>` when stateless).
76
- * @template Events - This plugin's own event map, merged on top of {@link WorkerEvents}; defaults to none.
77
- * @example
78
- * ```typescript
79
- * import type { Server, WorkerPluginCtx } from "@moku-labs/worker";
80
- * type MyEvents = { "my:done": { id: string } };
81
- * export type MyCtx = WorkerPluginCtx<MyConfig, Record<string, never>, MyEvents> & {
82
- * require: Server.RequireFn;
83
- * };
84
- * ```
85
- */
86
- type WorkerPluginCtx<Config, State, Events extends Record<string, unknown> = Record<never, never>> = PluginCtx<Config, State, WorkerEvents & Events>;
87
- //#endregion
88
- export { WorkerPluginCtx as i, WorkerEnv as n, WorkerEvents as r, WorkerConfig as t };
@@ -1,88 +0,0 @@
1
- import { PluginCtx } from "@moku-labs/core";
2
-
3
- //#region src/config.d.ts
4
- /** Per-request Cloudflare bindings object (env). Framework-level shared type. */
5
- type WorkerEnv = Record<string, unknown>;
6
- /** Global framework config — flat, with complete defaults. */
7
- type WorkerConfig = {
8
- stage: "production" | "development" | "test";
9
- name: string;
10
- compatibilityDate: string;
11
- };
12
- /** Global framework events — declared once, visible to every plugin. */
13
- type WorkerEvents = {
14
- "request:start": {
15
- method: string;
16
- path: string;
17
- requestId: string;
18
- };
19
- "request:end": {
20
- method: string;
21
- path: string;
22
- status: number;
23
- ms: number;
24
- };
25
- "deploy:phase": {
26
- phase: string;
27
- detail?: string;
28
- };
29
- "deploy:complete": {
30
- url: string;
31
- };
32
- "provision:resource": {
33
- kind: "kv" | "r2" | "d1" | "queue" | "do";
34
- name: string;
35
- };
36
- "provision:plan": {
37
- exists: number;
38
- missing: number;
39
- account: string;
40
- };
41
- "provision:skip": {
42
- kind: "kv" | "r2" | "d1" | "queue" | "do";
43
- name: string;
44
- };
45
- "auth:verified": {
46
- account: string;
47
- accountId: string;
48
- scopes: string[];
49
- };
50
- "dev:phase": {
51
- phase: string;
52
- detail?: string;
53
- };
54
- "dev:rebuilt": {
55
- files: number;
56
- ms: number;
57
- };
58
- "dev:error": {
59
- message: string;
60
- };
61
- };
62
- /**
63
- * Worker-bound plugin context for Layer-3 consumer plugins. Aliases the core
64
- * {@link PluginCtx} with the global {@link WorkerEvents} pre-merged into the event
65
- * map, so a consumer plugin types its own `config`/`state`/`emit` by passing only
66
- * its OWN event map — never hand-merging `WorkerEvents`, and never importing from
67
- * `@moku-labs/core` (a Layer-1 boundary the spec validator flags for consumers).
68
- *
69
- * A plugin that resolves sibling plugins also needs a `require` field; intersect the
70
- * public `Server.RequireFn` for it, exactly as this framework's own plugins do. When
71
- * you need the unaliased shape (e.g. a different global event map), use the raw
72
- * re-exported {@link PluginCtx} instead.
73
- *
74
- * @template Config - This plugin's own flat configuration object.
75
- * @template State - This plugin's mutable state (use `Record<string, never>` when stateless).
76
- * @template Events - This plugin's own event map, merged on top of {@link WorkerEvents}; defaults to none.
77
- * @example
78
- * ```typescript
79
- * import type { Server, WorkerPluginCtx } from "@moku-labs/worker";
80
- * type MyEvents = { "my:done": { id: string } };
81
- * export type MyCtx = WorkerPluginCtx<MyConfig, Record<string, never>, MyEvents> & {
82
- * require: Server.RequireFn;
83
- * };
84
- * ```
85
- */
86
- type WorkerPluginCtx<Config, State, Events extends Record<string, unknown> = Record<never, never>> = PluginCtx<Config, State, WorkerEvents & Events>;
87
- //#endregion
88
- export { WorkerPluginCtx as i, WorkerEnv as n, WorkerEvents as r, WorkerConfig as t };