@portel/photon 1.29.0 → 1.31.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.
Files changed (139) hide show
  1. package/README.md +41 -11
  2. package/dist/asset-resolver.d.ts +44 -0
  3. package/dist/asset-resolver.d.ts.map +1 -0
  4. package/dist/asset-resolver.js +105 -0
  5. package/dist/asset-resolver.js.map +1 -0
  6. package/dist/auto-ui/beam/external-mcp-manager.d.ts +73 -0
  7. package/dist/auto-ui/beam/external-mcp-manager.d.ts.map +1 -0
  8. package/dist/auto-ui/beam/external-mcp-manager.js +65 -0
  9. package/dist/auto-ui/beam/external-mcp-manager.js.map +1 -0
  10. package/dist/auto-ui/beam/external-mcp.d.ts.map +1 -1
  11. package/dist/auto-ui/beam/external-mcp.js +25 -1
  12. package/dist/auto-ui/beam/external-mcp.js.map +1 -1
  13. package/dist/auto-ui/beam/photon-management.d.ts.map +1 -1
  14. package/dist/auto-ui/beam/photon-management.js +11 -8
  15. package/dist/auto-ui/beam/photon-management.js.map +1 -1
  16. package/dist/auto-ui/beam/routes/api-browse.d.ts.map +1 -1
  17. package/dist/auto-ui/beam/routes/api-browse.js +7 -4
  18. package/dist/auto-ui/beam/routes/api-browse.js.map +1 -1
  19. package/dist/auto-ui/beam/routes/api-config.d.ts.map +1 -1
  20. package/dist/auto-ui/beam/routes/api-config.js +3 -2
  21. package/dist/auto-ui/beam/routes/api-config.js.map +1 -1
  22. package/dist/auto-ui/beam/routes/api-marketplace.d.ts.map +1 -1
  23. package/dist/auto-ui/beam/routes/api-marketplace.js +6 -2
  24. package/dist/auto-ui/beam/routes/api-marketplace.js.map +1 -1
  25. package/dist/auto-ui/beam/startup.js.map +1 -1
  26. package/dist/auto-ui/beam/types.d.ts +5 -2
  27. package/dist/auto-ui/beam/types.d.ts.map +1 -1
  28. package/dist/auto-ui/beam.d.ts.map +1 -1
  29. package/dist/auto-ui/beam.js +162 -45
  30. package/dist/auto-ui/beam.js.map +1 -1
  31. package/dist/auto-ui/bridge/index.d.ts.map +1 -1
  32. package/dist/auto-ui/bridge/index.js +11 -0
  33. package/dist/auto-ui/bridge/index.js.map +1 -1
  34. package/dist/auto-ui/bridge/types.d.ts +2 -0
  35. package/dist/auto-ui/bridge/types.d.ts.map +1 -1
  36. package/dist/auto-ui/openapi-generator.js +1 -4
  37. package/dist/auto-ui/openapi-generator.js.map +1 -1
  38. package/dist/auto-ui/photon-bridge.d.ts +4 -0
  39. package/dist/auto-ui/photon-bridge.d.ts.map +1 -1
  40. package/dist/auto-ui/photon-bridge.js.map +1 -1
  41. package/dist/auto-ui/photon-host.js.map +1 -1
  42. package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -1
  43. package/dist/auto-ui/streamable-http-transport.js +24 -14
  44. package/dist/auto-ui/streamable-http-transport.js.map +1 -1
  45. package/dist/auto-ui/types.d.ts +15 -1
  46. package/dist/auto-ui/types.d.ts.map +1 -1
  47. package/dist/auto-ui/types.js.map +1 -1
  48. package/dist/beam.bundle.js +170 -22
  49. package/dist/beam.bundle.js.map +3 -3
  50. package/dist/capability-negotiator.d.ts +39 -1
  51. package/dist/capability-negotiator.d.ts.map +1 -1
  52. package/dist/capability-negotiator.js +5 -0
  53. package/dist/capability-negotiator.js.map +1 -1
  54. package/dist/cf-bindings-parser.d.ts +15 -0
  55. package/dist/cf-bindings-parser.d.ts.map +1 -0
  56. package/dist/cf-bindings-parser.js +98 -0
  57. package/dist/cf-bindings-parser.js.map +1 -0
  58. package/dist/cf-usage-scanner.d.ts +76 -0
  59. package/dist/cf-usage-scanner.d.ts.map +1 -0
  60. package/dist/cf-usage-scanner.js +179 -0
  61. package/dist/cf-usage-scanner.js.map +1 -0
  62. package/dist/cli/commands/build.js +1 -1
  63. package/dist/cli/commands/cf.d.ts +18 -0
  64. package/dist/cli/commands/cf.d.ts.map +1 -0
  65. package/dist/cli/commands/cf.js +207 -0
  66. package/dist/cli/commands/cf.js.map +1 -0
  67. package/dist/cli/commands/info.js +1 -1
  68. package/dist/cli/commands/info.js.map +1 -1
  69. package/dist/cli/commands/init.d.ts.map +1 -1
  70. package/dist/cli/commands/init.js +59 -46
  71. package/dist/cli/commands/init.js.map +1 -1
  72. package/dist/cli/commands/run.d.ts.map +1 -1
  73. package/dist/cli/commands/run.js +3 -0
  74. package/dist/cli/commands/run.js.map +1 -1
  75. package/dist/cli/index.d.ts.map +1 -1
  76. package/dist/cli/index.js +43 -6
  77. package/dist/cli/index.js.map +1 -1
  78. package/dist/daemon/client.d.ts.map +1 -1
  79. package/dist/daemon/client.js +40 -33
  80. package/dist/daemon/client.js.map +1 -1
  81. package/dist/daemon/manager.d.ts +6 -2
  82. package/dist/daemon/manager.d.ts.map +1 -1
  83. package/dist/daemon/manager.js +30 -9
  84. package/dist/daemon/manager.js.map +1 -1
  85. package/dist/daemon/server.js +28 -11
  86. package/dist/daemon/server.js.map +1 -1
  87. package/dist/daemon/worker-host.js.map +1 -1
  88. package/dist/deploy/cloudflare.d.ts +27 -0
  89. package/dist/deploy/cloudflare.d.ts.map +1 -1
  90. package/dist/deploy/cloudflare.js +129 -2
  91. package/dist/deploy/cloudflare.js.map +1 -1
  92. package/dist/embedded-runtime.js.map +1 -1
  93. package/dist/loader.d.ts +43 -66
  94. package/dist/loader.d.ts.map +1 -1
  95. package/dist/loader.js +185 -305
  96. package/dist/loader.js.map +1 -1
  97. package/dist/photon-cli-runner.d.ts.map +1 -1
  98. package/dist/photon-cli-runner.js +20 -11
  99. package/dist/photon-cli-runner.js.map +1 -1
  100. package/dist/resource-server.d.ts +3 -3
  101. package/dist/resource-server.d.ts.map +1 -1
  102. package/dist/resource-server.js.map +1 -1
  103. package/dist/runtime/cf-local.d.ts +157 -0
  104. package/dist/runtime/cf-local.d.ts.map +1 -0
  105. package/dist/runtime/cf-local.js +406 -0
  106. package/dist/runtime/cf-local.js.map +1 -0
  107. package/dist/server.d.ts +42 -2
  108. package/dist/server.d.ts.map +1 -1
  109. package/dist/server.js +166 -14
  110. package/dist/server.js.map +1 -1
  111. package/dist/settings-persistence.d.ts +50 -0
  112. package/dist/settings-persistence.d.ts.map +1 -0
  113. package/dist/settings-persistence.js +188 -0
  114. package/dist/settings-persistence.js.map +1 -0
  115. package/dist/shared/audit-sqlite.d.ts.map +1 -1
  116. package/dist/shared/audit-sqlite.js +0 -1
  117. package/dist/shared/audit-sqlite.js.map +1 -1
  118. package/dist/shared/error-handler.d.ts.map +1 -1
  119. package/dist/shared/error-handler.js +3 -1
  120. package/dist/shared/error-handler.js.map +1 -1
  121. package/dist/shared/io.d.ts.map +1 -1
  122. package/dist/shared/io.js +5 -2
  123. package/dist/shared/io.js.map +1 -1
  124. package/dist/shared/logger.js.map +1 -1
  125. package/dist/shared/sqlite-runtime.d.ts.map +1 -1
  126. package/dist/shared/sqlite-runtime.js +0 -1
  127. package/dist/shared/sqlite-runtime.js.map +1 -1
  128. package/dist/task-executor.js.map +1 -1
  129. package/dist/telemetry/sdk.d.ts.map +1 -1
  130. package/dist/telemetry/sdk.js +0 -1
  131. package/dist/telemetry/sdk.js.map +1 -1
  132. package/dist/test-runner.d.ts.map +1 -1
  133. package/dist/test-runner.js.map +1 -1
  134. package/dist/types/server-types.d.ts +16 -8
  135. package/dist/types/server-types.d.ts.map +1 -1
  136. package/package.json +11 -4
  137. package/templates/cloudflare/worker.ts.template +338 -11
  138. package/templates/cloudflare/wrangler.toml.template +1 -6
  139. package/templates/photon.template.ts +13 -0
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Local Cloudflare runtime adapter for the new `Cloudflare` injection
3
+ * surface. Backs `private cf: Cloudflare` constructor params (and the
4
+ * forgiving auto-inject path for plain classes that reference
5
+ * `this.cf.*`) with a miniflare sandbox when a photon runs outside a
6
+ * deployed Worker.
7
+ *
8
+ * Auto-naming rule (single source of truth — `bindingNameFor`):
9
+ * cf.kv() → <photon>_kv
10
+ * cf.kv('x') → <photon>_x_kv
11
+ * cf.ai → AI (shared, single per Worker)
12
+ * cf.images → IMAGES (shared)
13
+ * cf.browser → BROWSER (shared)
14
+ *
15
+ * Photons no longer pick global binding names. The framework derives
16
+ * them from the photon name plus an optional qualifier so per-photon
17
+ * resources never collide.
18
+ *
19
+ * Boot is keyed off the `cf-usage-scanner` output: every literal
20
+ * qualifier the photon uses is configured in miniflare up front, so
21
+ * the first call to a binding doesn't pay a reconfigure cost. Dynamic
22
+ * qualifiers (`cf.kv(this.tenantId)`) only get the default binding
23
+ * unless the author lists overrides in `protected cfBindings`.
24
+ *
25
+ * Storage persists under `<baseDir>/.data/cf-sandbox/<photon>/` so
26
+ * state survives process restarts and matches the Phase A2 layout.
27
+ */
28
+ import { type Cloudflare, type ScopedBindingCategory, type R2BucketLike, type KVNamespaceLike, type D1DatabaseLike, type QueueLike, type VectorizeIndexLike, type AiLike, type ImagesBindingLike, type FetcherLike } from '@portel/photon-core';
29
+ import { type CfUsage } from '../cf-usage-scanner.js';
30
+ /**
31
+ * Optional override layer. Most photons leave this empty — the
32
+ * auto-naming convention covers the common case. Authors set it when
33
+ * they need a binding to point at a pre-existing CF resource owned
34
+ * outside the photon (typically only matters at deploy time, not for
35
+ * the local sandbox).
36
+ *
37
+ * Schema mirrors the deploy-side override JSON (~/.photon/state/...).
38
+ * For local boot, we accept the same shape so a single
39
+ * `protected cfBindings` block round-trips through both layers.
40
+ */
41
+ export interface CfOverrides {
42
+ /** Per-qualifier override of the resource name a binding points at. */
43
+ kv?: Record<string, string>;
44
+ r2?: Record<string, string>;
45
+ d1?: Record<string, string | {
46
+ name: string;
47
+ id: string;
48
+ }>;
49
+ queue?: Record<string, string>;
50
+ vectorize?: Record<string, string>;
51
+ }
52
+ export interface CFLocalRuntimeOptions {
53
+ photonName: string;
54
+ baseDir: string;
55
+ /**
56
+ * Static-analysis output from cf-usage-scanner. Determines which
57
+ * binding names miniflare boots with. When absent, only the
58
+ * default per-category binding is configured (callers that hit a
59
+ * qualified binding without source-scanning will get a clear miss
60
+ * error from miniflare).
61
+ */
62
+ usage?: CfUsage;
63
+ /** Optional `protected cfBindings` override layer, see CfOverrides. */
64
+ overrides?: CfOverrides;
65
+ }
66
+ /**
67
+ * Legacy override schema. The Phase A2 release shipped `cfBindings`
68
+ * as a `Record<bindingName, resourceId>` declaration that doubled as
69
+ * a binding declaration. Under the new auto-naming model
70
+ * (bindingNameFor) the same shape becomes a pure override layer —
71
+ * authors who want to repoint a default binding at a pre-existing
72
+ * resource still write the same JSON. Kept exported so deploy code
73
+ * and the photon-cf CLI keep building during the migration.
74
+ */
75
+ export type CfBindingsConfig = CfOverrides & {
76
+ ai?: boolean;
77
+ images?: boolean;
78
+ browser?: boolean;
79
+ };
80
+ /**
81
+ * Merge two CfBindingsConfig blobs. Used by the deploy pipeline to
82
+ * stack a per-photon override JSON on top of in-source declarations.
83
+ * Boolean shared flags are last-write-wins; per-binding records merge
84
+ * key-by-key.
85
+ */
86
+ export declare function mergeBindings(base: CfBindingsConfig | null | undefined, override: CfBindingsConfig | null | undefined): CfBindingsConfig;
87
+ export declare class CFLocalRuntime implements Cloudflare {
88
+ private mfPromise;
89
+ private readonly photonName;
90
+ private readonly baseDir;
91
+ private readonly usage;
92
+ private readonly overrides;
93
+ /**
94
+ * Legacy mode means the photon was constructed via the Phase-A2
95
+ * positional `(name, cfBindings, baseDir)` form. In that mode the
96
+ * `qualifier` arg passed to `cf.kv(...)` etc. is treated as a
97
+ * literal binding name (not run through `bindingNameFor`), and
98
+ * miniflare seeds the names declared in `overrides.<category>`.
99
+ * The new options-form constructor flips this to false and the
100
+ * auto-naming convention takes over.
101
+ */
102
+ private readonly legacyMode;
103
+ private readonly legacyBooleanFlags;
104
+ /**
105
+ * New options-object form (preferred). Hosts that source-scan the
106
+ * photon for `Cloudflare` usage pass the scanner output as `usage`
107
+ * so miniflare seeds every literal-qualified binding upfront.
108
+ */
109
+ constructor(opts: CFLocalRuntimeOptions);
110
+ /**
111
+ * Legacy positional form retained for the classic loader and
112
+ * existing CF-runtime tests. Translates the Phase-A2 `cfBindings`
113
+ * declaration to the new override schema; auto-naming is disabled
114
+ * (no usage scan) so explicit binding names take precedence over
115
+ * `<photon>_<category>` defaults. Callers should migrate to the
116
+ * options form when the demolition commit lands.
117
+ *
118
+ * @deprecated use the options-object constructor.
119
+ */
120
+ constructor(photonName: string, bindings: CfBindingsConfig, baseDir: string);
121
+ /** Legacy alias retained for callers that built against the Phase-A2 API. */
122
+ getBindings(): CfBindingsConfig;
123
+ /** Inspector for tools/CLI: lists every binding miniflare seeded. */
124
+ getSeededBindings(): Record<ScopedBindingCategory, string[]>;
125
+ /**
126
+ * Resolve the miniflare binding name for a `cf.<cat>(qualifier?)`
127
+ * call. In auto-naming mode runs through `bindingNameFor`; in
128
+ * legacy mode treats the arg as a literal binding name (matching
129
+ * the Phase-A2 `cf.kv(name)` semantics).
130
+ */
131
+ private resolveBindingName;
132
+ dispose(): Promise<void>;
133
+ kv(qualifier?: string): KVNamespaceLike;
134
+ r2(qualifier?: string): R2BucketLike;
135
+ d1(qualifier?: string): D1DatabaseLike;
136
+ queue<Body = unknown>(qualifier?: string): QueueLike<Body>;
137
+ vectorize(qualifier?: string): VectorizeIndexLike;
138
+ get ai(): AiLike;
139
+ get images(): ImagesBindingLike;
140
+ get browser(): FetcherLike;
141
+ fetch(_input: string, _init?: unknown): Promise<unknown>;
142
+ /** Lazily boot a Miniflare instance scoped to this photon. */
143
+ private getMiniflare;
144
+ /**
145
+ * Build a thin proxy whose methods defer to a binding fetched via
146
+ * `mf.getKVNamespace(name)` / `mf.getR2Bucket(name)` / etc on first
147
+ * invocation. Avoids paying the boot cost on cold paths.
148
+ */
149
+ private scopedBinding;
150
+ /**
151
+ * Pull a binding off the miniflare-built env (for AI, Vectorize,
152
+ * Images — categories that surface as env props rather than via a
153
+ * dedicated `mf.getXxx(name)` accessor).
154
+ */
155
+ private envBindingProxy;
156
+ }
157
+ //# sourceMappingURL=cf-local.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cf-local.d.ts","sourceRoot":"","sources":["../../src/runtime/cf-local.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,406 @@
1
+ /**
2
+ * Local Cloudflare runtime adapter for the new `Cloudflare` injection
3
+ * surface. Backs `private cf: Cloudflare` constructor params (and the
4
+ * forgiving auto-inject path for plain classes that reference
5
+ * `this.cf.*`) with a miniflare sandbox when a photon runs outside a
6
+ * deployed Worker.
7
+ *
8
+ * Auto-naming rule (single source of truth — `bindingNameFor`):
9
+ * cf.kv() → <photon>_kv
10
+ * cf.kv('x') → <photon>_x_kv
11
+ * cf.ai → AI (shared, single per Worker)
12
+ * cf.images → IMAGES (shared)
13
+ * cf.browser → BROWSER (shared)
14
+ *
15
+ * Photons no longer pick global binding names. The framework derives
16
+ * them from the photon name plus an optional qualifier so per-photon
17
+ * resources never collide.
18
+ *
19
+ * Boot is keyed off the `cf-usage-scanner` output: every literal
20
+ * qualifier the photon uses is configured in miniflare up front, so
21
+ * the first call to a binding doesn't pay a reconfigure cost. Dynamic
22
+ * qualifiers (`cf.kv(this.tenantId)`) only get the default binding
23
+ * unless the author lists overrides in `protected cfBindings`.
24
+ *
25
+ * Storage persists under `<baseDir>/.data/cf-sandbox/<photon>/` so
26
+ * state survives process restarts and matches the Phase A2 layout.
27
+ */
28
+ import * as path from 'path';
29
+ import { bindingNameFor, } from '@portel/photon-core';
30
+ import { expandScopedBindingNames } from '../cf-usage-scanner.js';
31
+ /**
32
+ * Merge two CfBindingsConfig blobs. Used by the deploy pipeline to
33
+ * stack a per-photon override JSON on top of in-source declarations.
34
+ * Boolean shared flags are last-write-wins; per-binding records merge
35
+ * key-by-key.
36
+ */
37
+ export function mergeBindings(base, override) {
38
+ const merged = { ...(base ?? {}) };
39
+ if (!override)
40
+ return merged;
41
+ for (const cat of ['kv', 'r2', 'queue', 'vectorize']) {
42
+ const ov = override[cat];
43
+ if (ov) {
44
+ merged[cat] = { ...(merged[cat] ?? {}), ...ov };
45
+ }
46
+ }
47
+ if (override.d1) {
48
+ merged.d1 = { ...(merged.d1 ?? {}), ...override.d1 };
49
+ }
50
+ for (const cat of ['ai', 'images', 'browser']) {
51
+ if (typeof override[cat] === 'boolean')
52
+ merged[cat] = override[cat];
53
+ }
54
+ return merged;
55
+ }
56
+ const SCOPED = ['kv', 'r2', 'd1', 'queue', 'vectorize'];
57
+ const SHARED_BINDING_NAMES = {
58
+ ai: 'AI',
59
+ images: 'IMAGES',
60
+ browser: 'BROWSER',
61
+ };
62
+ export class CFLocalRuntime {
63
+ mfPromise = null;
64
+ photonName;
65
+ baseDir;
66
+ usage;
67
+ overrides;
68
+ /**
69
+ * Legacy mode means the photon was constructed via the Phase-A2
70
+ * positional `(name, cfBindings, baseDir)` form. In that mode the
71
+ * `qualifier` arg passed to `cf.kv(...)` etc. is treated as a
72
+ * literal binding name (not run through `bindingNameFor`), and
73
+ * miniflare seeds the names declared in `overrides.<category>`.
74
+ * The new options-form constructor flips this to false and the
75
+ * auto-naming convention takes over.
76
+ */
77
+ legacyMode;
78
+ legacyBooleanFlags;
79
+ constructor(optsOrName, legacyBindings, legacyBaseDir) {
80
+ if (typeof optsOrName === 'string') {
81
+ this.photonName = optsOrName;
82
+ this.baseDir = legacyBaseDir ?? '';
83
+ this.usage = null;
84
+ this.overrides = legacyBindings ?? {};
85
+ this.legacyMode = true;
86
+ this.legacyBooleanFlags = {
87
+ ai: legacyBindings?.ai === true,
88
+ images: legacyBindings?.images === true,
89
+ browser: legacyBindings?.browser === true,
90
+ };
91
+ }
92
+ else {
93
+ this.photonName = optsOrName.photonName;
94
+ this.baseDir = optsOrName.baseDir;
95
+ this.usage = optsOrName.usage ?? null;
96
+ this.overrides = optsOrName.overrides ?? {};
97
+ this.legacyMode = false;
98
+ this.legacyBooleanFlags = { ai: false, images: false, browser: false };
99
+ }
100
+ }
101
+ /** Legacy alias retained for callers that built against the Phase-A2 API. */
102
+ getBindings() {
103
+ return this.overrides;
104
+ }
105
+ /** Inspector for tools/CLI: lists every binding miniflare seeded. */
106
+ getSeededBindings() {
107
+ const out = {};
108
+ if (this.legacyMode) {
109
+ // Legacy: seed exactly what `cfBindings` declared, no auto-naming.
110
+ for (const cat of SCOPED) {
111
+ const declared = this.overrides[cat];
112
+ if (!declared) {
113
+ out[cat] = [];
114
+ continue;
115
+ }
116
+ out[cat] = Object.keys(declared);
117
+ }
118
+ return out;
119
+ }
120
+ if (!this.usage) {
121
+ for (const cat of SCOPED)
122
+ out[cat] = [bindingNameFor(this.photonName, cat)];
123
+ return out;
124
+ }
125
+ return expandScopedBindingNames(this.photonName, this.usage);
126
+ }
127
+ /**
128
+ * Resolve the miniflare binding name for a `cf.<cat>(qualifier?)`
129
+ * call. In auto-naming mode runs through `bindingNameFor`; in
130
+ * legacy mode treats the arg as a literal binding name (matching
131
+ * the Phase-A2 `cf.kv(name)` semantics).
132
+ */
133
+ resolveBindingName(category, qualifier) {
134
+ if (this.legacyMode) {
135
+ // Legacy callers pass the binding name directly. Empty / missing
136
+ // is invalid in this mode (the old API required a name).
137
+ if (!qualifier) {
138
+ throw new Error(`cf.${category}() in legacy mode requires the binding name as an argument ` +
139
+ `(e.g. cf.${category}('cache')). Migrate to the new options-object ` +
140
+ `constructor to use auto-naming.`);
141
+ }
142
+ return qualifier;
143
+ }
144
+ return bindingNameFor(this.photonName, category, qualifier);
145
+ }
146
+ async dispose() {
147
+ if (this.mfPromise) {
148
+ const mf = await this.mfPromise;
149
+ await mf.dispose();
150
+ this.mfPromise = null;
151
+ }
152
+ }
153
+ // ────────────────────────────────────────────────────────────────
154
+ // Cloudflare interface — scoped categories with auto-naming
155
+ // ────────────────────────────────────────────────────────────────
156
+ kv(qualifier) {
157
+ return this.scopedBinding('kv', qualifier, ['get', 'put', 'delete', 'list']);
158
+ }
159
+ r2(qualifier) {
160
+ return this.scopedBinding('r2', qualifier, [
161
+ 'head',
162
+ 'get',
163
+ 'put',
164
+ 'delete',
165
+ 'list',
166
+ ]);
167
+ }
168
+ d1(qualifier) {
169
+ const name = this.resolveBindingName('d1', qualifier);
170
+ const get = this.getMiniflare.bind(this);
171
+ return {
172
+ prepare: (query) => makeD1PreparedStatement(get, name, query, []),
173
+ batch: async (statements) => {
174
+ const mf = await get();
175
+ const db = (await mf.getD1Database(name));
176
+ const real = await Promise.all(statements.map(async (s) => {
177
+ const candidate = s._materialize;
178
+ return candidate ? candidate() : s;
179
+ }));
180
+ return db.batch(real);
181
+ },
182
+ exec: async (query) => {
183
+ const mf = await get();
184
+ const db = (await mf.getD1Database(name));
185
+ return db.exec(query);
186
+ },
187
+ dump: async () => {
188
+ const mf = await get();
189
+ const db = (await mf.getD1Database(name));
190
+ return db.dump();
191
+ },
192
+ };
193
+ }
194
+ queue(qualifier) {
195
+ return this.scopedBinding('queue', qualifier, ['send', 'sendBatch']);
196
+ }
197
+ vectorize(qualifier) {
198
+ return this.envBindingProxy(this.resolveBindingName('vectorize', qualifier), [
199
+ 'insert',
200
+ 'upsert',
201
+ 'query',
202
+ 'getByIds',
203
+ 'deleteByIds',
204
+ ]);
205
+ }
206
+ // ────────────────────────────────────────────────────────────────
207
+ // Cloudflare interface — shared categories (single per Worker)
208
+ // ────────────────────────────────────────────────────────────────
209
+ get ai() {
210
+ const enabled = this.usage?.shared.ai === true || this.legacyBooleanFlags.ai;
211
+ if (!enabled) {
212
+ return throwingShared('ai', 'reference this.cf.ai (or cf.ai) somewhere in the photon to enable');
213
+ }
214
+ return this.envBindingProxy(SHARED_BINDING_NAMES.ai, ['run']);
215
+ }
216
+ get images() {
217
+ const enabled = this.usage?.shared.images === true || this.legacyBooleanFlags.images;
218
+ if (!enabled) {
219
+ return throwingShared('images', 'reference this.cf.images (or cf.images) somewhere in the photon to enable');
220
+ }
221
+ return this.envBindingProxy(SHARED_BINDING_NAMES.images, [
222
+ 'info',
223
+ 'input',
224
+ ]);
225
+ }
226
+ get browser() {
227
+ return throwingShared('browser', 'browser rendering requires a Chromium dep and is deferred until a photon dogfoods it');
228
+ }
229
+ fetch(_input, _init) {
230
+ return Promise.reject(new Error('cf.fetch() — not yet supported on the local sandbox. Service-binding ' +
231
+ 'fetch lands with the deploy adapter; until then, use plain `fetch()` ' +
232
+ 'or wire the photon up to a deployed Worker.'));
233
+ }
234
+ // ────────────────────────────────────────────────────────────────
235
+ // Internals
236
+ // ────────────────────────────────────────────────────────────────
237
+ /** Lazily boot a Miniflare instance scoped to this photon. */
238
+ getMiniflare() {
239
+ if (!this.mfPromise) {
240
+ this.mfPromise = (async () => {
241
+ const { Miniflare } = await import('miniflare');
242
+ const sandbox = path.join(this.baseDir, '.data', 'cf-sandbox', this.photonName);
243
+ const seeded = this.getSeededBindings();
244
+ const options = {
245
+ modules: true,
246
+ script: 'export default { async fetch() { return new Response("noop"); } };',
247
+ };
248
+ if (seeded.kv.length > 0) {
249
+ options.kvNamespaces = seeded.kv;
250
+ options.kvPersist = path.join(sandbox, 'kv');
251
+ }
252
+ if (seeded.r2.length > 0) {
253
+ options.r2Buckets = seeded.r2;
254
+ options.r2Persist = path.join(sandbox, 'r2');
255
+ }
256
+ if (seeded.d1.length > 0) {
257
+ options.d1Databases = seeded.d1;
258
+ options.d1Persist = path.join(sandbox, 'd1');
259
+ }
260
+ if (seeded.queue.length > 0) {
261
+ const producers = {};
262
+ for (const bindingName of seeded.queue) {
263
+ // Local sandbox: queue name == binding name. Overrides only
264
+ // come into play at deploy time.
265
+ producers[bindingName] = { queueName: bindingName };
266
+ }
267
+ options.queueProducers = producers;
268
+ }
269
+ if (seeded.vectorize.length > 0) {
270
+ const indices = {};
271
+ for (const bindingName of seeded.vectorize) {
272
+ indices[bindingName] = { indexName: bindingName };
273
+ }
274
+ options.vectorize = indices;
275
+ }
276
+ if (this.usage?.shared.ai) {
277
+ options.ai = { binding: SHARED_BINDING_NAMES.ai };
278
+ }
279
+ if (this.usage?.shared.images) {
280
+ options.images = { binding: SHARED_BINDING_NAMES.images };
281
+ }
282
+ // browser intentionally omitted — see `get browser` deferral.
283
+ return new Miniflare(options);
284
+ })();
285
+ }
286
+ return this.mfPromise;
287
+ }
288
+ /**
289
+ * Build a thin proxy whose methods defer to a binding fetched via
290
+ * `mf.getKVNamespace(name)` / `mf.getR2Bucket(name)` / etc on first
291
+ * invocation. Avoids paying the boot cost on cold paths.
292
+ */
293
+ scopedBinding(category, qualifier, methods) {
294
+ const name = this.resolveBindingName(category, qualifier);
295
+ const dynamicCategory = this.usage?.dynamicQualifiers.has(category);
296
+ const knownNames = new Set(this.getSeededBindings()[category]);
297
+ if (!knownNames.has(name) && !dynamicCategory) {
298
+ throw new Error(`cf.${category}(${qualifier ? JSON.stringify(qualifier) : ''}) on ` +
299
+ `${this.photonName} resolves to binding "${name}", which the runtime ` +
300
+ `did not seed. Either reference this binding with a literal qualifier ` +
301
+ `somewhere in your photon source (the boot scanner only sees literals), ` +
302
+ `or add a "${category}" override to \`protected cfBindings\`.`);
303
+ }
304
+ const get = this.getMiniflare.bind(this);
305
+ const out = {};
306
+ for (const method of methods) {
307
+ out[method] = async (...args) => {
308
+ const mf = await get();
309
+ const binding = await getMiniflareBinding(mf, category, name);
310
+ const fn = binding[method];
311
+ if (typeof fn !== 'function') {
312
+ throw new Error(`Miniflare binding "${name}" has no method "${method}" (category=${category}).`);
313
+ }
314
+ return fn.apply(binding, args);
315
+ };
316
+ }
317
+ return out;
318
+ }
319
+ /**
320
+ * Pull a binding off the miniflare-built env (for AI, Vectorize,
321
+ * Images — categories that surface as env props rather than via a
322
+ * dedicated `mf.getXxx(name)` accessor).
323
+ */
324
+ envBindingProxy(bindingName, methods) {
325
+ const get = this.getMiniflare.bind(this);
326
+ const out = {};
327
+ for (const method of methods) {
328
+ out[method] = async (...args) => {
329
+ const mf = await get();
330
+ const env = await mf.getBindings();
331
+ const binding = env[bindingName];
332
+ if (!binding) {
333
+ throw new Error(`Miniflare has no binding named '${bindingName}' (photon=${this.photonName}).`);
334
+ }
335
+ return binding[method].apply(binding, args);
336
+ };
337
+ }
338
+ return out;
339
+ }
340
+ }
341
+ async function getMiniflareBinding(mf, category, name) {
342
+ // Each miniflare accessor is typed for its specific binding; the
343
+ // `as never` cast keeps the dispatcher concise without giving up
344
+ // the runtime guarantee that `name` is one of the configured
345
+ // bindings (the dispatcher gate above ensures this).
346
+ switch (category) {
347
+ case 'kv':
348
+ return mf.getKVNamespace(name);
349
+ case 'r2':
350
+ return mf.getR2Bucket(name);
351
+ case 'd1':
352
+ return mf.getD1Database(name);
353
+ case 'queue':
354
+ return mf.getQueueProducer(name);
355
+ case 'vectorize': {
356
+ const env = await mf.getBindings();
357
+ return env[name];
358
+ }
359
+ }
360
+ }
361
+ function throwingShared(category, hint) {
362
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
363
+ return new Proxy(Object.create(null), {
364
+ get(_target, prop) {
365
+ throw new Error(`cf.${category}.${String(prop)} — ${hint}.`);
366
+ },
367
+ });
368
+ }
369
+ /**
370
+ * Build a chainable D1 prepared-statement proxy that mirrors
371
+ * `D1PreparedStatement.bind(...).first/all/run/raw()` semantics. We
372
+ * accumulate the bind list on the proxy and materialize the real
373
+ * statement only when a terminal method runs.
374
+ */
375
+ function makeD1PreparedStatement(get, dbName, query, bound) {
376
+ const materialize = async () => {
377
+ const mf = await get();
378
+ const db = (await mf.getD1Database(dbName));
379
+ const stmt = db.prepare(query);
380
+ if (bound.length > 0)
381
+ return stmt.bind(...bound);
382
+ return stmt;
383
+ };
384
+ const proxy = {
385
+ bind: (...values) => makeD1PreparedStatement(get, dbName, query, [...bound, ...values]),
386
+ first: async (colName) => {
387
+ const real = (await materialize());
388
+ return real.first(colName);
389
+ },
390
+ run: async () => {
391
+ const real = (await materialize());
392
+ return real.run();
393
+ },
394
+ all: async () => {
395
+ const real = (await materialize());
396
+ return real.all();
397
+ },
398
+ raw: async () => {
399
+ const real = (await materialize());
400
+ return real.raw();
401
+ },
402
+ _materialize: materialize,
403
+ };
404
+ return proxy;
405
+ }
406
+ //# sourceMappingURL=cf-local.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cf-local.js","sourceRoot":"","sources":["../../src/runtime/cf-local.ts"],"names":[],"mappings":"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"}
package/dist/server.d.ts CHANGED
@@ -126,7 +126,40 @@ export declare class PhotonServer {
126
126
  /** Write queue for serialized STDIO notifications (prevents interleaving from concurrent generators) */
127
127
  private _notifyQueue;
128
128
  /** Compatibility alias for tests that seed raw capabilities directly on PhotonServer */
129
- rawClientCapabilities: WeakMap<Server, Record<string, any>>;
129
+ rawClientCapabilities: WeakMap<Server<{
130
+ method: string;
131
+ params?: {
132
+ [x: string]: unknown;
133
+ _meta?: {
134
+ [x: string]: unknown;
135
+ progressToken?: string | number | undefined;
136
+ "io.modelcontextprotocol/related-task"?: {
137
+ taskId: string;
138
+ } | undefined;
139
+ } | undefined;
140
+ } | undefined;
141
+ }, {
142
+ method: string;
143
+ params?: {
144
+ [x: string]: unknown;
145
+ _meta?: {
146
+ [x: string]: unknown;
147
+ progressToken?: string | number | undefined;
148
+ "io.modelcontextprotocol/related-task"?: {
149
+ taskId: string;
150
+ } | undefined;
151
+ } | undefined;
152
+ } | undefined;
153
+ }, {
154
+ [x: string]: unknown;
155
+ _meta?: {
156
+ [x: string]: unknown;
157
+ progressToken?: string | number | undefined;
158
+ "io.modelcontextprotocol/related-task"?: {
159
+ taskId: string;
160
+ } | undefined;
161
+ } | undefined;
162
+ }>, Record<string, any>>;
130
163
  /** Resource listing, reading, and asset serving */
131
164
  private resourceServer;
132
165
  /**
@@ -292,9 +325,16 @@ export declare class PhotonServer {
292
325
  */
293
326
  start(): Promise<void>;
294
327
  /**
295
- * Start server with stdio transport
328
+ * Start server with stdio transport.
329
+ * @param webPort - when set, start a companion HTTP server on this port
330
+ * to serve @get/@post web routes for stateful photons.
296
331
  */
297
332
  private startStdio;
333
+ /**
334
+ * Dispatch an incoming HTTP request to the photon's @get/@post web routes.
335
+ * Used by the companion HTTP server that runs alongside STDIO stateful photons.
336
+ */
337
+ private handleWebRoute;
298
338
  /**
299
339
  * Start server with SSE transport (HTTP)
300
340
  */