devflare 1.0.0-next.21 → 1.0.0-next.23

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 (133) hide show
  1. package/LLM.md +144 -5
  2. package/dist/account-j8nfggg4.js +475 -0
  3. package/dist/account-qhe8vtds.js +475 -0
  4. package/dist/bridge/gateway-runtime.d.ts +1 -1
  5. package/dist/bridge/gateway-runtime.d.ts.map +1 -1
  6. package/dist/bridge/miniflare.d.ts +1 -1
  7. package/dist/bridge/miniflare.d.ts.map +1 -1
  8. package/dist/bridge/proxy.d.ts +2 -0
  9. package/dist/bridge/proxy.d.ts.map +1 -1
  10. package/dist/bridge/server.d.ts.map +1 -1
  11. package/dist/browser.d.ts +13 -13
  12. package/dist/browser.d.ts.map +1 -1
  13. package/dist/browser.js +5 -3
  14. package/dist/build-qsgnme4z.js +54 -0
  15. package/dist/build-vy95gy3f.js +54 -0
  16. package/dist/build-yzx0gsaj.js +54 -0
  17. package/dist/cli/commands/build-artifacts.d.ts.map +1 -1
  18. package/dist/cli/commands/config.d.ts.map +1 -1
  19. package/dist/cli/commands/type-generation/generator.d.ts +4 -2
  20. package/dist/cli/commands/type-generation/generator.d.ts.map +1 -1
  21. package/dist/cli/commands/types.d.ts.map +1 -1
  22. package/dist/cli/index.js +1 -1
  23. package/dist/config/compiler/types.d.ts +1 -1
  24. package/dist/config/compiler/types.d.ts.map +1 -1
  25. package/dist/config/define.d.ts +7 -4
  26. package/dist/config/define.d.ts.map +1 -1
  27. package/dist/config/env-vars.d.ts +309 -0
  28. package/dist/config/env-vars.d.ts.map +1 -0
  29. package/dist/config/index.d.ts +2 -1
  30. package/dist/config/index.d.ts.map +1 -1
  31. package/dist/config/loader.d.ts.map +1 -1
  32. package/dist/config/local-dev-vars.d.ts +2 -2
  33. package/dist/config/local-dev-vars.d.ts.map +1 -1
  34. package/dist/config/schema-env.d.ts +6 -6
  35. package/dist/config/schema-types-bindings-platform.d.ts +378 -0
  36. package/dist/config/schema-types-bindings-platform.d.ts.map +1 -0
  37. package/dist/config/schema-types-bindings-resources.d.ts +551 -0
  38. package/dist/config/schema-types-bindings-resources.d.ts.map +1 -0
  39. package/dist/config/schema-types-bindings.d.ts +254 -0
  40. package/dist/config/schema-types-bindings.d.ts.map +1 -0
  41. package/dist/config/schema-types-build.d.ts +86 -0
  42. package/dist/config/schema-types-build.d.ts.map +1 -0
  43. package/dist/config/schema-types-runtime.d.ts +882 -0
  44. package/dist/config/schema-types-runtime.d.ts.map +1 -0
  45. package/dist/config/schema-types.d.ts +377 -0
  46. package/dist/config/schema-types.d.ts.map +1 -0
  47. package/dist/config/schema.d.ts +14 -15
  48. package/dist/config/schema.d.ts.map +1 -1
  49. package/dist/config-entry.d.ts +2 -0
  50. package/dist/config-entry.d.ts.map +1 -1
  51. package/dist/config-entry.js +3 -1
  52. package/dist/config-gq5jh4cx.js +105 -0
  53. package/dist/config-vec13050.js +105 -0
  54. package/dist/deploy-01j0ep5n.js +1055 -0
  55. package/dist/deploy-nh5tbv45.js +1055 -0
  56. package/dist/deploy-tjypkhg7.js +1055 -0
  57. package/dist/dev-bh581ew3.js +2597 -0
  58. package/dist/dev-cme5de75.js +2551 -0
  59. package/dist/dev-gn5y93z9.js +2597 -0
  60. package/dist/dev-server/server.d.ts.map +1 -1
  61. package/dist/doctor-h5q28qt1.js +259 -0
  62. package/dist/doctor-khk550tw.js +259 -0
  63. package/dist/env.d.ts +10 -0
  64. package/dist/env.d.ts.map +1 -1
  65. package/dist/index-0bv2qjs1.js +1555 -0
  66. package/dist/index-35bmgpfw.js +573 -0
  67. package/dist/index-3tkzn06q.js +413 -0
  68. package/dist/index-4se6krdj.js +574 -0
  69. package/dist/index-8fyz6gcm.js +699 -0
  70. package/dist/index-97z629zr.js +109 -0
  71. package/dist/index-b28c4yr4.js +1205 -0
  72. package/dist/index-c1cj9085.js +2250 -0
  73. package/dist/index-c8p4njqy.js +479 -0
  74. package/dist/index-cr06zrgw.js +1033 -0
  75. package/dist/index-cwjjdtgn.js +74 -0
  76. package/dist/index-dref9ecb.js +476 -0
  77. package/dist/index-e151t4ge.js +895 -0
  78. package/dist/index-e7kakw0j.js +1033 -0
  79. package/dist/index-f1g5jdm8.js +1426 -0
  80. package/dist/index-f46984zs.js +1554 -0
  81. package/dist/index-grk8pzhr.js +185 -0
  82. package/dist/index-hbxkmb1q.js +1426 -0
  83. package/dist/index-hzmpecq9.js +52 -0
  84. package/dist/index-j1csb7gb.js +581 -0
  85. package/dist/index-j7x7f72h.js +185 -0
  86. package/dist/index-jkqbjwt2.js +476 -0
  87. package/dist/index-jwd3fanx.js +412 -0
  88. package/dist/index-mh5renra.js +895 -0
  89. package/dist/index-p9xq83p7.js +147 -0
  90. package/dist/index-q15nj71j.js +52 -0
  91. package/dist/index-qqp65pyv.js +699 -0
  92. package/dist/index-s0fmwxbk.js +74 -0
  93. package/dist/index-s9q605sq.js +1033 -0
  94. package/dist/index-stzx8nc4.js +111 -0
  95. package/dist/index-th4vrnbk.js +1205 -0
  96. package/dist/index-vtcmsgaf.js +581 -0
  97. package/dist/index-w36q6819.js +895 -0
  98. package/dist/index-x2k3awjs.js +147 -0
  99. package/dist/index-x8x547tz.js +1426 -0
  100. package/dist/index-xp0qkkxf.js +68 -0
  101. package/dist/index-xxxd0mvw.js +109 -0
  102. package/dist/index-zawn5tte.js +109 -0
  103. package/dist/index-zpy9caxn.js +1193 -0
  104. package/dist/index.d.ts +1 -1
  105. package/dist/index.d.ts.map +1 -1
  106. package/dist/index.js +9 -7
  107. package/dist/login-280p2cm9.js +77 -0
  108. package/dist/login-4n266whq.js +77 -0
  109. package/dist/previews-3m3ffpaw.js +1337 -0
  110. package/dist/previews-tr8sm03d.js +1337 -0
  111. package/dist/productions-62y489ff.js +505 -0
  112. package/dist/productions-cgn3fz7d.js +505 -0
  113. package/dist/runtime/exports.d.ts +23 -0
  114. package/dist/runtime/exports.d.ts.map +1 -1
  115. package/dist/runtime/index.d.ts +1 -1
  116. package/dist/runtime/index.d.ts.map +1 -1
  117. package/dist/runtime/index.js +6 -4
  118. package/dist/secrets-4050kqf5.js +91 -0
  119. package/dist/secrets-p112cajt.js +91 -0
  120. package/dist/sveltekit/index.js +8 -7
  121. package/dist/sveltekit/local-bindings.d.ts.map +1 -1
  122. package/dist/test/index.js +24 -12
  123. package/dist/test/resolve-service-bindings.d.ts +1 -1
  124. package/dist/test/resolve-service-bindings.d.ts.map +1 -1
  125. package/dist/test/simple-context-lifecycle.d.ts.map +1 -1
  126. package/dist/types-apmt10yj.js +705 -0
  127. package/dist/types-ttrrgdfj.js +705 -0
  128. package/dist/vite/index.js +5 -5
  129. package/dist/vite/plugin-context.d.ts.map +1 -1
  130. package/dist/vite/plugin-programmatic.d.ts.map +1 -1
  131. package/dist/worker-2k1jyr6p.js +513 -0
  132. package/dist/worker-jqgn6jyj.js +513 -0
  133. package/package.json +1 -1
@@ -0,0 +1,475 @@
1
+ import {
2
+ getConfiguredAccountId
3
+ } from "./index-cwjjdtgn.js";
4
+ import {
5
+ account
6
+ } from "./index-0m6e4mxz.js";
7
+ import"./index-k7m5f1dg.js";
8
+ import"./index-3jme4hgw.js";
9
+ import {
10
+ bold,
11
+ createCliTheme,
12
+ dim,
13
+ formatCommand,
14
+ formatLabelValue,
15
+ green,
16
+ logLine,
17
+ logTable,
18
+ whiteDim,
19
+ yellow
20
+ } from "./index-stgn34cr.js";
21
+ import {
22
+ CYAN,
23
+ CYAN_BOLD,
24
+ DIM,
25
+ RESET
26
+ } from "./index-3t6rypgc.js";
27
+ import"./index-15fpa5tx.js";
28
+ import"./index-f46984zs.js";
29
+ import {
30
+ getGlobalDefaultAccountId,
31
+ getWorkspaceAccountId,
32
+ setGlobalDefaultAccountId,
33
+ setWorkspaceAccountId
34
+ } from "./index-1d4jg11n.js";
35
+ import {
36
+ AuthenticationError,
37
+ CloudflareAPIError
38
+ } from "./index-mg8vwqxf.js";
39
+ import"./index-c8p4njqy.js";
40
+ import"./index-37x76zdn.js";
41
+
42
+ // src/cli/commands/account.ts
43
+ var ACCOUNT_SUBCOMMANDS = [
44
+ "info",
45
+ "workers",
46
+ "kv",
47
+ "d1",
48
+ "r2",
49
+ "vectorize",
50
+ "limits",
51
+ "usage",
52
+ "global",
53
+ "workspace"
54
+ ];
55
+ function isAccountSubcommand(value) {
56
+ return ACCOUNT_SUBCOMMANDS.includes(value);
57
+ }
58
+ var CLI_API_OPTIONS = { timeout: 1e4 };
59
+ function formatDate(date) {
60
+ if (!date)
61
+ return "N/A";
62
+ return date.toLocaleDateString("en-US", {
63
+ year: "numeric",
64
+ month: "short",
65
+ day: "numeric"
66
+ });
67
+ }
68
+ function formatPercent(value) {
69
+ if (value === undefined)
70
+ return "N/A";
71
+ return `${value.toFixed(1)}%`;
72
+ }
73
+ function logSection(logger, title, theme, count, accent = "cyan") {
74
+ logLine(logger);
75
+ const heading = accent === "yellow" ? yellow(title, theme) : accent === "green" ? green(title, theme) : bold(title, theme);
76
+ logLine(logger, `${heading}${count === undefined ? "" : ` ${dim(`(${count})`, theme)}`}`);
77
+ }
78
+ function logEmptyState(logger, message, theme) {
79
+ logLine(logger);
80
+ logLine(logger, dim(message, theme));
81
+ logLine(logger);
82
+ return { exitCode: 0 };
83
+ }
84
+ async function runAccountCommand(parsed, logger, options) {
85
+ const theme = createCliTheme(parsed.options);
86
+ const isAuth = await account.isAuthenticated();
87
+ if (!isAuth) {
88
+ logger.error("Not authenticated with Cloudflare");
89
+ logLine(logger, dim("Run: devflare login", theme));
90
+ return { exitCode: 1 };
91
+ }
92
+ const subcommand = parsed.args[0];
93
+ const rawSubcommand = parsed.args[0];
94
+ if (rawSubcommand && !isAccountSubcommand(rawSubcommand)) {
95
+ logger.error(`Unknown account subcommand: ${rawSubcommand}`);
96
+ logLine(logger, dim(`Available account subcommands: ${ACCOUNT_SUBCOMMANDS.join(", ")}`, theme));
97
+ return { exitCode: 1 };
98
+ }
99
+ if (subcommand === "global") {
100
+ return await selectGlobalAccount(logger, theme);
101
+ }
102
+ if (subcommand === "workspace") {
103
+ return await selectWorkspaceAccount(logger, theme);
104
+ }
105
+ try {
106
+ let accountId = parsed.options.account;
107
+ if (!accountId) {
108
+ accountId = await getConfiguredAccountId(options.cwd ?? process.cwd());
109
+ }
110
+ if (!accountId) {
111
+ const primary = await account.getPrimaryAccount();
112
+ if (!primary) {
113
+ logger.error("No Cloudflare accounts found");
114
+ return { exitCode: 1 };
115
+ }
116
+ accountId = primary.id;
117
+ }
118
+ switch (subcommand) {
119
+ case "workers":
120
+ return await showWorkers(accountId, logger, theme);
121
+ case "kv":
122
+ return await showKV(accountId, logger, theme);
123
+ case "d1":
124
+ return await showD1(accountId, logger, theme);
125
+ case "r2":
126
+ return await showR2(accountId, logger, theme);
127
+ case "vectorize":
128
+ return await showVectorize(accountId, logger, theme);
129
+ case "limits":
130
+ return await handleLimits(accountId, parsed, logger, theme);
131
+ case "usage":
132
+ return await showUsage(accountId, logger, theme);
133
+ case "info":
134
+ default:
135
+ return await showAccountOverview(accountId, logger, theme);
136
+ }
137
+ } catch (error) {
138
+ if (error instanceof AuthenticationError) {
139
+ logger.error(error.message);
140
+ return { exitCode: 1 };
141
+ }
142
+ if (error instanceof CloudflareAPIError) {
143
+ logger.error(`API Error: ${error.message}`);
144
+ return { exitCode: 1 };
145
+ }
146
+ if (error instanceof Error) {
147
+ if (error.name === "AbortError" || error.message.includes("timed out")) {
148
+ logger.error("Request timed out. The Cloudflare API is slow or unavailable.");
149
+ return { exitCode: 1 };
150
+ }
151
+ logger.error(`Error: ${error.message}`);
152
+ return { exitCode: 1 };
153
+ }
154
+ throw error;
155
+ }
156
+ }
157
+ async function showAccountOverview(accountId, logger, theme) {
158
+ logSection(logger, "Accounts", theme);
159
+ let accounts = [];
160
+ let limitedAccountView = false;
161
+ try {
162
+ accounts = await account.getAccounts();
163
+ } catch {
164
+ const fallbackAccount = await account.getAccountById(accountId);
165
+ if (!fallbackAccount) {
166
+ logger.error("Could not inspect Cloudflare accounts with the current credentials");
167
+ return { exitCode: 1 };
168
+ }
169
+ accounts = [fallbackAccount];
170
+ limitedAccountView = true;
171
+ }
172
+ if (accounts.length === 0) {
173
+ logger.error("No Cloudflare accounts found");
174
+ return { exitCode: 1 };
175
+ }
176
+ const workspaceId = getWorkspaceAccountId();
177
+ const globalId = await getGlobalDefaultAccountId(accountId);
178
+ if (limitedAccountView) {
179
+ logLine(logger, dim("Using the configured account directly because the current credentials cannot enumerate all Cloudflare accounts.", theme));
180
+ }
181
+ for (let i = 0;i < accounts.length; i++) {
182
+ const acc = accounts[i];
183
+ const isWorkspace = acc.id === workspaceId;
184
+ const isGlobal = acc.id === globalId;
185
+ let badge = "";
186
+ if (isWorkspace) {
187
+ badge = ` ${CYAN_BOLD}(workspace)${RESET}`;
188
+ } else if (isGlobal) {
189
+ badge = workspaceId ? ` ${DIM}(global)${RESET}` : ` ${CYAN}(global)${RESET}`;
190
+ }
191
+ if (i > 0) {
192
+ logLine(logger);
193
+ }
194
+ logLine(logger, `${dim("account", theme)} ${green(acc.name, theme)}${badge}`);
195
+ logLine(logger, formatLabelValue("id", whiteDim(acc.id, theme), theme, 10));
196
+ logLine(logger, formatLabelValue("type", acc.type, theme, 10));
197
+ }
198
+ logSection(logger, "Commands", theme);
199
+ logLine(logger, formatCommand("devflare account global", "Set global default account", theme));
200
+ logLine(logger, formatCommand("devflare account workspace", "Set workspace account", theme));
201
+ logLine(logger, formatCommand("devflare account workers", "List Workers", theme));
202
+ logLine(logger, formatCommand("devflare account kv", "List KV namespaces", theme));
203
+ logLine(logger, formatCommand("devflare account d1", "List D1 databases", theme));
204
+ logLine(logger, formatCommand("devflare account r2", "List R2 buckets", theme));
205
+ logLine(logger, formatCommand("devflare account vectorize", "List Vectorize indexes", theme));
206
+ logLine(logger, formatCommand("devflare account limits", "View or set usage limits", theme));
207
+ logLine(logger, formatCommand("devflare account usage", "View detailed usage", theme));
208
+ logLine(logger, formatCommand("devflare ai", "View AI models and pricing", theme));
209
+ logLine(logger);
210
+ return { exitCode: 0 };
211
+ }
212
+ async function selectGlobalAccount(logger, theme) {
213
+ const accounts = await account.getAccounts();
214
+ if (accounts.length === 0) {
215
+ logger.error("No Cloudflare accounts found");
216
+ return { exitCode: 1 };
217
+ }
218
+ if (accounts.length === 1) {
219
+ await setGlobalDefaultAccountId(accounts[0].id);
220
+ logger.success(`Global default set to: ${accounts[0].name}`);
221
+ return { exitCode: 0 };
222
+ }
223
+ const currentGlobal = await getGlobalDefaultAccountId(accounts[0].id);
224
+ const options = accounts.map((acc) => {
225
+ const isCurrent = acc.id === currentGlobal;
226
+ return {
227
+ label: isCurrent ? `${acc.name} ${CYAN}(default)${RESET}` : acc.name,
228
+ value: acc.id,
229
+ hint: acc.id.substring(0, 8) + "..."
230
+ };
231
+ });
232
+ const selected = await logger.prompt("Select global default account:", {
233
+ type: "select",
234
+ options,
235
+ initial: currentGlobal ?? accounts[0].id
236
+ });
237
+ if (!selected || typeof selected === "symbol") {
238
+ logLine(logger, dim("Cancelled", theme));
239
+ return { exitCode: 0 };
240
+ }
241
+ await setGlobalDefaultAccountId(selected, accounts[0].id);
242
+ const selectedAccount = accounts.find((a) => a.id === selected);
243
+ logger.success(`Global default set to: ${selectedAccount?.name}`);
244
+ logLine(logger, `${dim("saved to", theme)} ~/.devflare/preferences.json + cloud KV`);
245
+ return { exitCode: 0 };
246
+ }
247
+ async function selectWorkspaceAccount(logger, theme) {
248
+ const accounts = await account.getAccounts();
249
+ if (accounts.length === 0) {
250
+ logger.error("No Cloudflare accounts found");
251
+ return { exitCode: 1 };
252
+ }
253
+ if (accounts.length === 1) {
254
+ const pkgPath2 = setWorkspaceAccountId(accounts[0].id);
255
+ logger.success(`Workspace account set to: ${accounts[0].name}`);
256
+ logLine(logger, `${dim("saved to", theme)} ${pkgPath2}`);
257
+ return { exitCode: 0 };
258
+ }
259
+ const currentWorkspace = getWorkspaceAccountId();
260
+ const options = accounts.map((acc) => {
261
+ const isCurrent = acc.id === currentWorkspace;
262
+ return {
263
+ label: isCurrent ? `${acc.name} ${CYAN}(workspace)${RESET}` : acc.name,
264
+ value: acc.id,
265
+ hint: acc.id.substring(0, 8) + "..."
266
+ };
267
+ });
268
+ const selected = await logger.prompt("Select workspace account:", {
269
+ type: "select",
270
+ options,
271
+ initial: currentWorkspace ?? accounts[0].id
272
+ });
273
+ if (!selected || typeof selected === "symbol") {
274
+ logLine(logger, dim("Cancelled", theme));
275
+ return { exitCode: 0 };
276
+ }
277
+ const pkgPath = setWorkspaceAccountId(selected);
278
+ const selectedAccount = accounts.find((a) => a.id === selected);
279
+ logger.success(`Workspace account set to: ${selectedAccount?.name}`);
280
+ logLine(logger, `${dim("saved to", theme)} ${pkgPath}`);
281
+ return { exitCode: 0 };
282
+ }
283
+ async function showWorkers(accountId, logger, theme) {
284
+ const workers = await account.workers(accountId, CLI_API_OPTIONS);
285
+ if (workers.length === 0) {
286
+ return logEmptyState(logger, "No Workers found", theme);
287
+ }
288
+ logSection(logger, "Workers", theme, workers.length, "green");
289
+ logTable(logger, {
290
+ title: "Worker list",
291
+ rows: workers,
292
+ columns: [
293
+ { label: "Name", width: 30, value: (worker) => worker.name },
294
+ { label: "Modified", width: 20, value: (worker) => whiteDim(formatDate(worker.modifiedOn), theme) }
295
+ ],
296
+ theme,
297
+ titleAccent: "green"
298
+ });
299
+ logLine(logger);
300
+ return { exitCode: 0 };
301
+ }
302
+ async function showKV(accountId, logger, theme) {
303
+ const namespaces = await account.kv(accountId, CLI_API_OPTIONS);
304
+ if (namespaces.length === 0) {
305
+ return logEmptyState(logger, "No KV namespaces found", theme);
306
+ }
307
+ logSection(logger, "KV namespaces", theme, namespaces.length);
308
+ logTable(logger, {
309
+ title: "Namespace list",
310
+ rows: namespaces,
311
+ columns: [
312
+ { label: "Name", width: 35, value: (ns) => ns.name },
313
+ { label: "ID", width: 35, value: (ns) => whiteDim(ns.id, theme) }
314
+ ],
315
+ theme,
316
+ titleAccent: "cyan"
317
+ });
318
+ logLine(logger);
319
+ return { exitCode: 0 };
320
+ }
321
+ async function showD1(accountId, logger, theme) {
322
+ const databases = await account.d1(accountId, CLI_API_OPTIONS);
323
+ if (databases.length === 0) {
324
+ return logEmptyState(logger, "No D1 databases found", theme);
325
+ }
326
+ logSection(logger, "D1 databases", theme, databases.length, "yellow");
327
+ logTable(logger, {
328
+ title: "Database list",
329
+ rows: databases,
330
+ columns: [
331
+ { label: "Name", width: 25, value: (db) => db.name },
332
+ { label: "ID", width: 40, value: (db) => whiteDim(db.id, theme) },
333
+ { label: "Tables", width: 8, value: (db) => String(db.tableCount ?? "N/A") }
334
+ ],
335
+ theme,
336
+ titleAccent: "yellow"
337
+ });
338
+ logLine(logger);
339
+ return { exitCode: 0 };
340
+ }
341
+ async function showR2(accountId, logger, theme) {
342
+ const buckets = await account.r2(accountId, CLI_API_OPTIONS);
343
+ if (buckets.length === 0) {
344
+ return logEmptyState(logger, "No R2 buckets found", theme);
345
+ }
346
+ logSection(logger, "R2 buckets", theme, buckets.length, "green");
347
+ logTable(logger, {
348
+ title: "Bucket list",
349
+ rows: buckets,
350
+ columns: [
351
+ { label: "Name", width: 30, value: (bucket) => bucket.name },
352
+ { label: "Created", width: 20, value: (bucket) => whiteDim(formatDate(bucket.createdOn), theme) },
353
+ { label: "Location", width: 10, value: (bucket) => bucket.location ?? "auto" }
354
+ ],
355
+ theme,
356
+ titleAccent: "green"
357
+ });
358
+ logLine(logger);
359
+ return { exitCode: 0 };
360
+ }
361
+ async function showVectorize(accountId, logger, theme) {
362
+ const indexes = await account.vectorize(accountId, CLI_API_OPTIONS);
363
+ if (indexes.length === 0) {
364
+ return logEmptyState(logger, "No Vectorize indexes found", theme);
365
+ }
366
+ logSection(logger, "Vectorize indexes", theme, indexes.length, "yellow");
367
+ logTable(logger, {
368
+ title: "Index list",
369
+ rows: indexes,
370
+ columns: [
371
+ { label: "Name", width: 25, value: (idx) => idx.name },
372
+ { label: "Dimensions", width: 12, value: (idx) => String(idx.dimensions) },
373
+ { label: "Metric", width: 15, value: (idx) => idx.metric }
374
+ ],
375
+ theme,
376
+ titleAccent: "yellow"
377
+ });
378
+ logLine(logger);
379
+ return { exitCode: 0 };
380
+ }
381
+ async function showUsage(accountId, logger, theme) {
382
+ const usages = await account.getAllUsageSummaries(accountId);
383
+ const limits = await account.getLimits(accountId);
384
+ logSection(logger, "Usage", theme, undefined, "yellow");
385
+ logLine(logger, formatLabelValue("limits", limits.enabled ? green("enabled", theme) : dim("disabled", theme), theme, 12));
386
+ if (usages.length === 0) {
387
+ return logEmptyState(logger, "No usage tracked yet", theme);
388
+ }
389
+ logTable(logger, {
390
+ title: "Usage by service",
391
+ rows: usages,
392
+ columns: [
393
+ { label: "Service", width: 15, value: (usage) => usage.service },
394
+ { label: "Today", width: 10, value: (usage) => String(usage.today) },
395
+ { label: "Limit", width: 10, value: (usage) => usage.limit?.toString() ?? "∞" },
396
+ { label: "%", width: 10, value: (usage) => formatPercent(usage.percentUsed) },
397
+ { label: "Status", width: 10, value: (usage) => usage.withinLimit ? green("ok", theme) : yellow("limit", theme) }
398
+ ],
399
+ theme,
400
+ titleAccent: "yellow"
401
+ });
402
+ logLine(logger);
403
+ return { exitCode: 0 };
404
+ }
405
+ async function handleLimits(accountId, parsed, logger, theme) {
406
+ const action = parsed.args[1];
407
+ switch (action) {
408
+ case "set":
409
+ return await setLimit(accountId, parsed, logger, theme);
410
+ case "enable":
411
+ await account.setLimitsEnabled(accountId, true);
412
+ logger.success("Usage limits enabled");
413
+ return { exitCode: 0 };
414
+ case "disable":
415
+ await account.setLimitsEnabled(accountId, false);
416
+ logger.success("Usage limits disabled");
417
+ return { exitCode: 0 };
418
+ default:
419
+ return await showLimits(accountId, logger, theme);
420
+ }
421
+ }
422
+ async function showLimits(accountId, logger, theme) {
423
+ const limits = await account.getLimits(accountId);
424
+ logSection(logger, "Usage limits", theme, undefined, "yellow");
425
+ logLine(logger, formatLabelValue("status", limits.enabled ? green("enabled", theme) : dim("disabled", theme), theme, 16));
426
+ logLine(logger);
427
+ logLine(logger, dim("current limits", theme));
428
+ logLine(logger, formatLabelValue("AI Requests/Day", String(limits.aiRequestsPerDay ?? "Unlimited"), theme, 18));
429
+ logLine(logger, formatLabelValue("AI Tokens/Day", String(limits.aiTokensPerDay ?? "Unlimited"), theme, 18));
430
+ logLine(logger, formatLabelValue("Vectorize Ops/Day", String(limits.vectorizeOpsPerDay ?? "Unlimited"), theme, 18));
431
+ logSection(logger, "Commands", theme);
432
+ logLine(logger, formatCommand("devflare account limits set ai-requests 50", "Set the AI request daily limit", theme));
433
+ logLine(logger, formatCommand("devflare account limits set ai-tokens 5000", "Set the AI token daily limit", theme));
434
+ logLine(logger, formatCommand("devflare account limits set vectorize-ops 500", "Set the Vectorize daily limit", theme));
435
+ logLine(logger, formatCommand("devflare account limits enable", "Enable usage limits", theme));
436
+ logLine(logger, formatCommand("devflare account limits disable", "Disable usage limits", theme));
437
+ logLine(logger);
438
+ return { exitCode: 0 };
439
+ }
440
+ async function setLimit(accountId, parsed, logger, theme) {
441
+ const limitName = parsed.args[2];
442
+ const limitValue = parsed.args[3];
443
+ if (!limitName || !limitValue) {
444
+ logger.error("Usage: devflare account limits set <limit-name> <value>");
445
+ logLine(logger, dim("Limit names: ai-requests, ai-tokens, vectorize-ops", theme));
446
+ return { exitCode: 1 };
447
+ }
448
+ const value = parseInt(limitValue, 10);
449
+ if (isNaN(value) || value < 0) {
450
+ logger.error("Limit value must be a positive number");
451
+ return { exitCode: 1 };
452
+ }
453
+ switch (limitName) {
454
+ case "ai-requests":
455
+ await account.setLimits(accountId, { aiRequestsPerDay: value });
456
+ logger.success(`AI requests limit set to ${value}/day`);
457
+ break;
458
+ case "ai-tokens":
459
+ await account.setLimits(accountId, { aiTokensPerDay: value });
460
+ logger.success(`AI tokens limit set to ${value}/day`);
461
+ break;
462
+ case "vectorize-ops":
463
+ await account.setLimits(accountId, { vectorizeOpsPerDay: value });
464
+ logger.success(`Vectorize ops limit set to ${value}/day`);
465
+ break;
466
+ default:
467
+ logger.error(`Unknown limit: ${limitName}`);
468
+ logLine(logger, dim("Valid limits: ai-requests, ai-tokens, vectorize-ops", theme));
469
+ return { exitCode: 1 };
470
+ }
471
+ return { exitCode: 0 };
472
+ }
473
+ export {
474
+ runAccountCommand
475
+ };
@@ -4,5 +4,5 @@
4
4
  * module. All symbols are declared with `function`/`const` so they are
5
5
  * hoisted in both embedding sites.
6
6
  */
7
- export declare const GATEWAY_RUNTIME_JS = "\nconst RAW_EMAIL = 'EmailMessage::raw'\n\nfunction arrayBufferToBase64(buffer) {\n\tconst bytes = new Uint8Array(buffer)\n\tlet binary = ''\n\tfor (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i])\n\treturn btoa(binary)\n}\n\nfunction base64ToArrayBuffer(base64) {\n\tconst binary = atob(base64)\n\tconst bytes = new Uint8Array(binary.length)\n\tfor (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i)\n\treturn bytes.buffer\n}\n\nfunction serializeR2Object(obj) {\n\tif (!obj) return null\n\treturn {\n\t\t__type: 'R2Object',\n\t\tkey: obj.key,\n\t\tversion: obj.version,\n\t\tsize: obj.size,\n\t\tetag: obj.etag,\n\t\thttpEtag: obj.httpEtag,\n\t\tchecksums: obj.checksums,\n\t\tuploaded: obj.uploaded?.toISOString(),\n\t\thttpMetadata: obj.httpMetadata,\n\t\tcustomMetadata: obj.customMetadata,\n\t\trange: obj.range,\n\t\tstorageClass: obj.storageClass\n\t}\n}\n\nfunction serializeR2ObjectBody(obj, bodyData) {\n\tif (!obj) return null\n\treturn {\n\t\t__type: 'R2ObjectBody',\n\t\tkey: obj.key,\n\t\tversion: obj.version,\n\t\tsize: obj.size,\n\t\tetag: obj.etag,\n\t\thttpEtag: obj.httpEtag,\n\t\tchecksums: obj.checksums,\n\t\tuploaded: obj.uploaded?.toISOString(),\n\t\thttpMetadata: obj.httpMetadata,\n\t\tcustomMetadata: obj.customMetadata,\n\t\trange: obj.range,\n\t\tstorageClass: obj.storageClass,\n\t\tbodyData\n\t}\n}\n\nfunction serializeR2Objects(result) {\n\tif (!result) return null\n\treturn {\n\t\tobjects: result.objects.map(serializeR2Object),\n\t\ttruncated: result.truncated,\n\t\tcursor: result.cursor,\n\t\tdelimitedPrefixes: result.delimitedPrefixes\n\t}\n}\n\nasync function serializeResponse(response) {\n\tlet body = null\n\tif (response.body) {\n\t\tconst bytes = await response.arrayBuffer()\n\t\tif (bytes.byteLength > 0) {\n\t\t\tbody = { type: 'bytes', data: arrayBufferToBase64(bytes) }\n\t\t}\n\t}\n\treturn {\n\t\tstatus: response.status,\n\t\tstatusText: response.statusText,\n\t\theaders: [...response.headers.entries()],\n\t\tbody\n\t}\n}\n\nfunction createEmailMessageRaw(raw) {\n\tif (typeof raw === 'string' || raw instanceof ReadableStream) {\n\t\treturn raw\n\t}\n\tif (raw instanceof ArrayBuffer || raw instanceof Uint8Array) {\n\t\treturn new Response(raw).body\n\t}\n\tthrow new Error('Unsupported EmailMessage raw payload')\n}\n\nfunction isDurableObjectNamespace(binding) {\n\treturn !!binding\n\t\t&& typeof binding.idFromName === 'function'\n\t\t&& typeof binding.idFromString === 'function'\n\t\t&& typeof binding.newUniqueId === 'function'\n}\n\n/**\n * Execute an RPC method against the gateway's bindings.\n *\n * Method format: \"binding.operation\". Operations must be namespaced by\n * binding kind (e.g. \"kv.get\", \"r2.head\", \"d1.stmt.first\", \"do.fetch\",\n * \"queue.send\", \"email.send\", \"ai.run\"). Bare verbs and the legacy\n * \"stmt.*\" / \"stub.*\" sub-prefixes were removed in B3-final and now throw.\n * Method vocabulary must stay in sync with the canonical server in\n * src/bridge/server.ts.\n */\nasync function executeRpcMethod(method, params, env, _ctx) {\n\tconst parts = method.split('.')\n\tif (parts.length < 2) throw new Error('Invalid method format: ' + method)\n\n\tconst bindingName = parts[0]\n\tconst operation = parts.slice(1).join('.')\n\tconst binding = env[bindingName]\n\n\tif (!binding) throw new Error('Binding not found: ' + bindingName)\n\n\tconst isNamespaced =\n\t\toperation.indexOf('kv.') === 0 ||\n\t\toperation.indexOf('r2.') === 0 ||\n\t\toperation.indexOf('d1.') === 0 ||\n\t\toperation.indexOf('do.') === 0 ||\n\t\toperation.indexOf('queue.') === 0 ||\n\t\toperation.indexOf('email.') === 0 ||\n\t\toperation.indexOf('ai.') === 0 ||\n\t\toperation.indexOf('workflow.') === 0 ||\n\t\toperation.indexOf('var.') === 0\n\tif (!isNamespaced) {\n\t\tthrow new Error(\n\t\t\t\"[devflare][bridge] Unsupported bridge operation '\" + operation + \"' for binding '\" + bindingName + \"'. \"\n\t\t\t+ \"Bare verbs and the legacy stmt.*/stub.* sub-prefixes were removed in B3-final; \"\n\t\t\t+ \"use the namespaced form (e.g. kv.get, r2.put, d1.stmt.first, do.fetch).\"\n\t\t)\n\t}\n\n\t// KV\n\tif (operation === 'kv.get') return binding.get(params[0], params[1])\n\tif (operation === 'kv.put') return binding.put(params[0], params[1], params[2])\n\tif (operation === 'kv.delete') return binding.delete(params[0])\n\tif (operation === 'kv.list') return binding.list(params[0])\n\tif (operation === 'kv.getWithMetadata') return binding.getWithMetadata(params[0], params[1])\n\n\t// DO get (returns DOStub reference)\n\tif (operation === 'do.get') {\n\t\treturn { __type: 'DOStub', binding: bindingName, id: params[0] }\n\t}\n\n\t// R2\n\tif (operation === 'r2.head') return serializeR2Object(await binding.head(params[0]))\n\tif (operation === 'r2.get') {\n\t\tconst obj = await binding.get(params[0], params[1])\n\t\tif (!obj) return null\n\t\tconst body = await obj.arrayBuffer()\n\t\treturn serializeR2ObjectBody(obj, arrayBufferToBase64(body))\n\t}\n\tif (operation === 'r2.put') {\n\t\tlet value = params[1]\n\t\tif (value && typeof value === 'object') {\n\t\t\tif (value.__type === 'ArrayBuffer' || value.__type === 'Uint8Array') {\n\t\t\t\tvalue = base64ToArrayBuffer(value.data)\n\t\t\t}\n\t\t}\n\t\treturn serializeR2Object(await binding.put(params[0], value, params[2]))\n\t}\n\tif (operation === 'r2.delete') return binding.delete(params[0])\n\tif (operation === 'r2.list') return serializeR2Objects(await binding.list(params[0]))\n\n\t// D1\n\tif (operation === 'd1.exec') return binding.exec(params[0])\n\tif (operation === 'd1.batch') {\n\t\tconst statements = params[0].map((s) => binding.prepare(s.sql).bind(...(s.bindings || [])))\n\t\treturn binding.batch(statements)\n\t}\n\tif (operation.indexOf('d1.stmt.') === 0) {\n\t\tconst mode = operation.split('.')[2]\n\t\tconst [sql, ...rest] = params\n\t\tlet bindings = rest\n\t\tlet extraParam\n\t\tif (mode === 'first' || mode === 'raw') {\n\t\t\textraParam = rest[rest.length - 1]\n\t\t\tbindings = rest.slice(0, -1)\n\t\t}\n\t\tlet stmt = binding.prepare(sql)\n\t\tif (bindings.length > 0) stmt = stmt.bind(...bindings)\n\t\tif (mode === 'first') {\n\t\t\tif (typeof extraParam === 'string' && extraParam.length > 0) return stmt.first(extraParam)\n\t\t\treturn stmt.first()\n\t\t}\n\t\tif (mode === 'all') return stmt.all()\n\t\tif (mode === 'run') return stmt.run()\n\t\tif (mode === 'raw') return stmt.raw(extraParam)\n\t\tthrow new Error('Unknown stmt mode: ' + mode)\n\t}\n\n\t// Durable Objects\n\tif (operation === 'do.idFromName') {\n\t\tconst id = binding.idFromName(params[0])\n\t\treturn { __type: 'DOId', hex: id.toString() }\n\t}\n\tif (operation === 'do.idFromString') {\n\t\tconst id = binding.idFromString(params[0])\n\t\treturn { __type: 'DOId', hex: id.toString() }\n\t}\n\tif (operation === 'do.newUniqueId') {\n\t\tconst id = binding.newUniqueId(params[0])\n\t\treturn { __type: 'DOId', hex: id.toString() }\n\t}\n\tif (operation === 'do.fetch') {\n\t\tconst [, serializedId, serializedReq] = params\n\t\tconst id = binding.idFromString(serializedId.hex)\n\t\tconst stub = binding.get(id)\n\t\tconst response = await stub.fetch(new Request(serializedReq.url, {\n\t\t\tmethod: serializedReq.method,\n\t\t\theaders: serializedReq.headers,\n\t\t\tbody: serializedReq.body?.type === 'bytes'\n\t\t\t\t? base64ToArrayBuffer(serializedReq.body.data)\n\t\t\t\t: undefined\n\t\t}))\n\t\treturn serializeResponse(response)\n\t}\n\tif (operation === 'do.rpc') {\n\t\tconst [, serializedId, methodName, args] = params\n\t\tconst id = binding.idFromString(serializedId.hex)\n\t\tconst stub = binding.get(id)\n\t\tconst response = await stub.fetch(new Request('http://do/_rpc', {\n\t\t\tmethod: 'POST',\n\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\tbody: JSON.stringify({ method: methodName, params: args })\n\t\t}))\n\t\tconst result = await response.json()\n\t\tif (!result.ok) throw new Error(result.error?.message || 'RPC failed')\n\t\treturn result.result\n\t}\n\n\t// Queues\n\tif (operation === 'queue.send') return binding.send(params[0], params[1])\n\tif (operation === 'queue.sendBatch') return binding.sendBatch(params[0], params[1])\n\n\t// Send Email\n\tif (operation === 'email.send') {\n\t\tif (binding && typeof binding.send === 'function') {\n\t\t\tconst message = params[0]\n\t\t\tif (message && typeof message === 'object' && 'from' in message && 'to' in message && 'raw' in message) {\n\t\t\t\treturn binding.send({\n\t\t\t\t\tfrom: message.from,\n\t\t\t\t\tto: message.to,\n\t\t\t\t\t[RAW_EMAIL]: createEmailMessageRaw(message.raw)\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn binding.send(message)\n\t\t}\n\t\treturn { ok: true, simulated: true }\n\t}\n\n\t// Workflows\n\tif (operation === 'workflow.create') {\n\t\treturn serializeWorkflowInstance(await binding.create(params[0]))\n\t}\n\tif (operation === 'workflow.get') {\n\t\treturn serializeWorkflowInstance(await binding.get(params[0]))\n\t}\n\tif (operation === 'workflow.status') {\n\t\treturn (await binding.get(params[0])).status()\n\t}\n\tif (operation === 'workflow.pause') {\n\t\treturn (await binding.get(params[0])).pause()\n\t}\n\tif (operation === 'workflow.resume') {\n\t\treturn (await binding.get(params[0])).resume()\n\t}\n\tif (operation === 'workflow.terminate') {\n\t\treturn (await binding.get(params[0])).terminate()\n\t}\n\tif (operation === 'workflow.restart') {\n\t\treturn (await binding.get(params[0])).restart()\n\t}\n\tif (operation === 'workflow.sendEvent') {\n\t\treturn (await binding.get(params[0])).sendEvent(params[1])\n\t}\n\n\t// AI / generic run()\n\tif (operation === 'ai.run') {\n\t\tif (typeof binding.run !== 'function') {\n\t\t\tthrow new Error('Binding ' + bindingName + ' does not support run(): ' + method)\n\t\t}\n\t\treturn binding.run(params[0], params[1])\n\t}\n\n\tthrow new Error('Unknown operation: ' + method)\n}\n\nfunction serializeWorkflowInstance(instance) {\n\treturn {\n\t\t__type: 'WorkflowInstance',\n\t\tid: instance.id\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// WebSocket bridge (shared with src/bridge/server.ts in shape)\n// ---------------------------------------------------------------------------\n// NOTE: wsProxies is intentionally created per handleBridgeWebSocket call so\n// state never leaks across connections or across gateway-script regenerations.\n\nasync function handleBridgeRpcCall(msg, ws, env, ctx) {\n\ttry {\n\t\tconst result = await executeRpcMethod(msg.method, msg.params, env, ctx)\n\t\tws.send(JSON.stringify({ t: 'rpc.ok', id: msg.id, result }))\n\t} catch (error) {\n\t\tws.send(JSON.stringify({\n\t\t\tt: 'rpc.err',\n\t\t\tid: msg.id,\n\t\t\terror: {\n\t\t\t\tcode: error?.code || 'INTERNAL_ERROR',\n\t\t\t\tmessage: error?.message || String(error)\n\t\t\t}\n\t\t}))\n\t}\n}\n\nasync function handleBridgeWsOpen(msg, ws, env, wsProxies) {\n\ttry {\n\t\tconst binding = env[msg.target.binding]\n\t\tconst id = binding.idFromString(msg.target.id)\n\t\tconst stub = binding.get(id)\n\n\t\tconst headers = new Headers(msg.target.headers || [])\n\t\theaders.set('Upgrade', 'websocket')\n\n\t\tconst response = await stub.fetch(new Request(msg.target.url, { method: 'GET', headers }))\n\t\tconst doWs = response.webSocket\n\n\t\tif (!doWs) {\n\t\t\tws.send(JSON.stringify({\n\t\t\t\tt: 'rpc.err',\n\t\t\t\tid: 'ws_' + msg.wid,\n\t\t\t\terror: { code: 'WS_FAILED', message: 'No WebSocket returned' }\n\t\t\t}))\n\t\t\treturn\n\t\t}\n\n\t\tdoWs.accept()\n\t\twsProxies.set(msg.wid, { doWs })\n\n\t\tdoWs.addEventListener('message', (event) => {\n\t\t\tconst isText = typeof event.data === 'string'\n\t\t\tconst data = isText ? event.data : arrayBufferToBase64(event.data)\n\t\t\tws.send(JSON.stringify({ t: 'ws.data', wid: msg.wid, data, isText }))\n\t\t})\n\n\t\tdoWs.addEventListener('close', (event) => {\n\t\t\tws.send(JSON.stringify({ t: 'ws.close', wid: msg.wid, code: event.code, reason: event.reason }))\n\t\t\twsProxies.delete(msg.wid)\n\t\t})\n\n\t\tws.send(JSON.stringify({ t: 'ws.opened', wid: msg.wid }))\n\t} catch (error) {\n\t\tws.send(JSON.stringify({\n\t\t\tt: 'rpc.err',\n\t\t\tid: 'ws_' + msg.wid,\n\t\t\terror: { code: 'WS_FAILED', message: error.message }\n\t\t}))\n\t}\n}\n\nfunction handleBridgeWsClose(msg, wsProxies) {\n\tconst proxy = wsProxies.get(msg.wid)\n\tif (proxy) {\n\t\tproxy.doWs.close(msg.code, msg.reason)\n\t\twsProxies.delete(msg.wid)\n\t}\n}\n\nasync function handleBridgeJsonMessage(data, ws, env, ctx, wsProxies) {\n\tconst msg = JSON.parse(data)\n\tswitch (msg.t) {\n\t\tcase 'hello':\n\t\t\t// v2 handshake \u2014 acknowledge with welcome echoing the negotiated\n\t\t\t// capability intersection. Capabilities advertised by the gateway\n\t\t\t// are kept in sync with src/bridge/client.ts (BRIDGE_CLIENT_CAPABILITIES).\n\t\t\tws.send(JSON.stringify({\n\t\t\t\tt: 'welcome',\n\t\t\t\tprotocolVersion: 2,\n\t\t\t\tcapabilities: ['streams', 'ws-relay', 'http-transfer']\n\t\t\t\t\t.filter((c) => Array.isArray(msg.capabilities) && msg.capabilities.includes(c))\n\t\t\t\t\t.sort()\n\t\t\t}))\n\t\t\tbreak\n\t\tcase 'rpc.call':\n\t\t\tawait handleBridgeRpcCall(msg, ws, env, ctx)\n\t\t\tbreak\n\t\tcase 'ws.open':\n\t\t\tawait handleBridgeWsOpen(msg, ws, env, wsProxies)\n\t\t\tbreak\n\t\tcase 'ws.close':\n\t\t\thandleBridgeWsClose(msg, wsProxies)\n\t\t\tbreak\n\t}\n}\n\nfunction handleBridgeWebSocket(request, env, ctx) {\n\tconst { 0: client, 1: server } = new WebSocketPair()\n\tserver.accept()\n\n\t// Per-connection state: recreated for every bridge client so reloads and\n\t// concurrent clients never share WS proxy entries.\n\tconst wsProxies = new Map()\n\n\tserver.addEventListener('message', async (event) => {\n\t\ttry {\n\t\t\tif (typeof event.data === 'string') {\n\t\t\t\tawait handleBridgeJsonMessage(event.data, server, env, ctx, wsProxies)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('[Gateway] Error:', error)\n\t\t}\n\t})\n\n\tserver.addEventListener('close', () => {\n\t\tfor (const proxy of wsProxies.values()) {\n\t\t\t// Best-effort cleanup: the DO-side WS may already be closed or in an\n\t\t\t// invalid state; any throw here would abort sibling closes. Surface\n\t\t\t// the swallowed error when DEVFLARE_DEBUG_BRIDGE is enabled.\n\t\t\ttry { proxy.doWs.close() } catch (error) {\n\t\t\t\tif (globalThis.DEVFLARE_DEBUG_BRIDGE) {\n\t\t\t\t\tconsole.warn('[devflare:bridge] proxy.doWs.close() failed', error)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\twsProxies.clear()\n\t})\n\n\treturn new Response(null, { status: 101, webSocket: client })\n}\n\n// ---------------------------------------------------------------------------\n// HTTP transfer for R2 bodies (shared with src/bridge/server.ts in shape)\n// ---------------------------------------------------------------------------\n\nasync function handleHttpTransfer(request, env, url) {\n\tconst transferIdEncoded = url.pathname.split('/').pop()\n\tconst transferId = decodeURIComponent(transferIdEncoded || '')\n\tconst [binding, ...keyParts] = transferId.split(':')\n\tconst key = keyParts.join(':')\n\tconst bucket = env[binding]\n\n\tif (!bucket) return new Response('Bucket not found: ' + binding, { status: 404 })\n\n\tif (request.method === 'PUT' || request.method === 'POST') {\n\t\tconst result = await bucket.put(key, request.body)\n\t\treturn new Response(JSON.stringify(serializeR2Object(result)), {\n\t\t\theaders: { 'Content-Type': 'application/json' }\n\t\t})\n\t}\n\n\tif (request.method === 'GET') {\n\t\tconst object = await bucket.get(key)\n\t\tif (!object) return new Response('Not found', { status: 404 })\n\t\treturn new Response(object.body, {\n\t\t\theaders: {\n\t\t\t\t'Content-Type': object.httpMetadata?.contentType || 'application/octet-stream',\n\t\t\t\t'Content-Length': String(object.size)\n\t\t\t}\n\t\t})\n\t}\n\n\treturn new Response('Method not allowed', { status: 405 })\n}\n";
7
+ export declare const GATEWAY_RUNTIME_JS = "\nconst RAW_EMAIL = 'EmailMessage::raw'\n\nfunction arrayBufferToBase64(buffer) {\n\tconst bytes = new Uint8Array(buffer)\n\tlet binary = ''\n\tfor (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i])\n\treturn btoa(binary)\n}\n\nfunction base64ToArrayBuffer(base64) {\n\tconst binary = atob(base64)\n\tconst bytes = new Uint8Array(binary.length)\n\tfor (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i)\n\treturn bytes.buffer\n}\n\nfunction serializeR2Object(obj) {\n\tif (!obj) return null\n\treturn {\n\t\t__type: 'R2Object',\n\t\tkey: obj.key,\n\t\tversion: obj.version,\n\t\tsize: obj.size,\n\t\tetag: obj.etag,\n\t\thttpEtag: obj.httpEtag,\n\t\tchecksums: obj.checksums,\n\t\tuploaded: obj.uploaded?.toISOString(),\n\t\thttpMetadata: obj.httpMetadata,\n\t\tcustomMetadata: obj.customMetadata,\n\t\trange: obj.range,\n\t\tstorageClass: obj.storageClass\n\t}\n}\n\nfunction serializeR2ObjectBody(obj, bodyData) {\n\tif (!obj) return null\n\treturn {\n\t\t__type: 'R2ObjectBody',\n\t\tkey: obj.key,\n\t\tversion: obj.version,\n\t\tsize: obj.size,\n\t\tetag: obj.etag,\n\t\thttpEtag: obj.httpEtag,\n\t\tchecksums: obj.checksums,\n\t\tuploaded: obj.uploaded?.toISOString(),\n\t\thttpMetadata: obj.httpMetadata,\n\t\tcustomMetadata: obj.customMetadata,\n\t\trange: obj.range,\n\t\tstorageClass: obj.storageClass,\n\t\tbodyData\n\t}\n}\n\nfunction serializeR2Objects(result) {\n\tif (!result) return null\n\treturn {\n\t\tobjects: result.objects.map(serializeR2Object),\n\t\ttruncated: result.truncated,\n\t\tcursor: result.cursor,\n\t\tdelimitedPrefixes: result.delimitedPrefixes\n\t}\n}\n\nasync function serializeResponse(response) {\n\tlet body = null\n\tif (response.body) {\n\t\tconst bytes = await response.arrayBuffer()\n\t\tif (bytes.byteLength > 0) {\n\t\t\tbody = { type: 'bytes', data: arrayBufferToBase64(bytes) }\n\t\t}\n\t}\n\treturn {\n\t\tstatus: response.status,\n\t\tstatusText: response.statusText,\n\t\theaders: [...response.headers.entries()],\n\t\tbody\n\t}\n}\n\nfunction deserializeRequest(serializedReq) {\n\treturn new Request(serializedReq.url, {\n\t\tmethod: serializedReq.method,\n\t\theaders: serializedReq.headers,\n\t\tbody: serializedReq.body?.type === 'bytes'\n\t\t\t? base64ToArrayBuffer(serializedReq.body.data)\n\t\t\t: undefined,\n\t\tredirect: serializedReq.redirect\n\t})\n}\n\nfunction createEmailMessageRaw(raw) {\n\tif (typeof raw === 'string' || raw instanceof ReadableStream) {\n\t\treturn raw\n\t}\n\tif (raw instanceof ArrayBuffer || raw instanceof Uint8Array) {\n\t\treturn new Response(raw).body\n\t}\n\tthrow new Error('Unsupported EmailMessage raw payload')\n}\n\nfunction isDurableObjectNamespace(binding) {\n\treturn !!binding\n\t\t&& typeof binding.idFromName === 'function'\n\t\t&& typeof binding.idFromString === 'function'\n\t\t&& typeof binding.newUniqueId === 'function'\n}\n\n/**\n * Execute an RPC method against the gateway's bindings.\n *\n * Method format: \"binding.operation\". Operations must be namespaced by\n * binding kind (e.g. \"kv.get\", \"r2.head\", \"d1.stmt.first\", \"do.fetch\",\n * \"service.fetch\", \"queue.send\", \"email.send\", \"ai.run\"). Bare verbs and the legacy\n * \"stmt.*\" / \"stub.*\" sub-prefixes were removed in B3-final and now throw.\n * Method vocabulary must stay in sync with the canonical server in\n * src/bridge/server.ts.\n */\nasync function executeRpcMethod(method, params, env, _ctx) {\n\tconst parts = method.split('.')\n\tif (parts.length < 2) throw new Error('Invalid method format: ' + method)\n\n\tconst bindingName = parts[0]\n\tconst operation = parts.slice(1).join('.')\n\tconst binding = env[bindingName]\n\n\tif (!binding) throw new Error('Binding not found: ' + bindingName)\n\n\tconst isNamespaced =\n\t\toperation.indexOf('kv.') === 0 ||\n\t\toperation.indexOf('r2.') === 0 ||\n\t\toperation.indexOf('d1.') === 0 ||\n\t\toperation.indexOf('do.') === 0 ||\n\t\toperation.indexOf('service.') === 0 ||\n\t\toperation.indexOf('queue.') === 0 ||\n\t\toperation.indexOf('email.') === 0 ||\n\t\toperation.indexOf('ai.') === 0 ||\n\t\toperation.indexOf('workflow.') === 0 ||\n\t\toperation.indexOf('var.') === 0\n\tif (!isNamespaced) {\n\t\tthrow new Error(createUnsupportedBridgeOperationErrorMessage(bindingName, operation))\n\t}\n\n\t// KV\n\tif (operation === 'kv.get') return binding.get(params[0], params[1])\n\tif (operation === 'kv.put') return binding.put(params[0], params[1], params[2])\n\tif (operation === 'kv.delete') return binding.delete(params[0])\n\tif (operation === 'kv.list') return binding.list(params[0])\n\tif (operation === 'kv.getWithMetadata') return binding.getWithMetadata(params[0], params[1])\n\n\t// DO get (returns DOStub reference)\n\tif (operation === 'do.get') {\n\t\treturn { __type: 'DOStub', binding: bindingName, id: params[0] }\n\t}\n\n\t// R2\n\tif (operation === 'r2.head') return serializeR2Object(await binding.head(params[0]))\n\tif (operation === 'r2.get') {\n\t\tconst obj = await binding.get(params[0], params[1])\n\t\tif (!obj) return null\n\t\tconst body = await obj.arrayBuffer()\n\t\treturn serializeR2ObjectBody(obj, arrayBufferToBase64(body))\n\t}\n\tif (operation === 'r2.put') {\n\t\tlet value = params[1]\n\t\tif (value && typeof value === 'object') {\n\t\t\tif (value.__type === 'ArrayBuffer' || value.__type === 'Uint8Array') {\n\t\t\t\tvalue = base64ToArrayBuffer(value.data)\n\t\t\t}\n\t\t}\n\t\treturn serializeR2Object(await binding.put(params[0], value, params[2]))\n\t}\n\tif (operation === 'r2.delete') return binding.delete(params[0])\n\tif (operation === 'r2.list') return serializeR2Objects(await binding.list(params[0]))\n\n\t// D1\n\tif (operation === 'd1.exec') return binding.exec(params[0])\n\tif (operation === 'd1.batch') {\n\t\tconst statements = params[0].map((s) => binding.prepare(s.sql).bind(...(s.bindings || [])))\n\t\treturn binding.batch(statements)\n\t}\n\tif (operation.indexOf('d1.stmt.') === 0) {\n\t\tconst mode = operation.split('.')[2]\n\t\tconst [sql, ...rest] = params\n\t\tlet bindings = rest\n\t\tlet extraParam\n\t\tif (mode === 'first' || mode === 'raw') {\n\t\t\textraParam = rest[rest.length - 1]\n\t\t\tbindings = rest.slice(0, -1)\n\t\t}\n\t\tlet stmt = binding.prepare(sql)\n\t\tif (bindings.length > 0) stmt = stmt.bind(...bindings)\n\t\tif (mode === 'first') {\n\t\t\tif (typeof extraParam === 'string' && extraParam.length > 0) return stmt.first(extraParam)\n\t\t\treturn stmt.first()\n\t\t}\n\t\tif (mode === 'all') return stmt.all()\n\t\tif (mode === 'run') return stmt.run()\n\t\tif (mode === 'raw') return stmt.raw(extraParam)\n\t\tthrow new Error('Unknown stmt mode: ' + mode)\n\t}\n\n\t// Durable Objects\n\tif (operation === 'do.idFromName') {\n\t\tconst id = binding.idFromName(params[0])\n\t\treturn { __type: 'DOId', hex: id.toString() }\n\t}\n\tif (operation === 'do.idFromString') {\n\t\tconst id = binding.idFromString(params[0])\n\t\treturn { __type: 'DOId', hex: id.toString() }\n\t}\n\tif (operation === 'do.newUniqueId') {\n\t\tconst id = binding.newUniqueId(params[0])\n\t\treturn { __type: 'DOId', hex: id.toString() }\n\t}\n\tif (operation === 'do.fetch') {\n\t\tconst [, serializedId, serializedReq] = params\n\t\tconst id = binding.idFromString(serializedId.hex)\n\t\tconst stub = binding.get(id)\n\t\tconst response = await stub.fetch(new Request(serializedReq.url, {\n\t\t\tmethod: serializedReq.method,\n\t\t\theaders: serializedReq.headers,\n\t\t\tbody: serializedReq.body?.type === 'bytes'\n\t\t\t\t? base64ToArrayBuffer(serializedReq.body.data)\n\t\t\t\t: undefined\n\t\t}))\n\t\treturn serializeResponse(response)\n\t}\n\tif (operation === 'do.rpc') {\n\t\tconst [, serializedId, methodName, args] = params\n\t\tconst id = binding.idFromString(serializedId.hex)\n\t\tconst stub = binding.get(id)\n\t\tconst response = await stub.fetch(new Request('http://do/_rpc', {\n\t\t\tmethod: 'POST',\n\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\tbody: JSON.stringify({ method: methodName, params: args })\n\t\t}))\n\t\tconst result = await response.json()\n\t\tif (!result.ok) throw new Error(result.error?.message || 'RPC failed')\n\t\treturn result.result\n\t}\n\n\t// Service Bindings\n\tif (operation === 'service.fetch') {\n\t\tif (!binding || typeof binding.fetch !== 'function') {\n\t\t\tthrow new Error('Service binding ' + bindingName + ' does not support fetch()')\n\t\t}\n\t\tconst response = await binding.fetch(deserializeRequest(params[0]))\n\t\treturn serializeResponse(response)\n\t}\n\tif (operation === 'service.rpc') {\n\t\tconst methodName = params[0]\n\t\tif (typeof methodName !== 'string') {\n\t\t\tthrow new Error('Service binding ' + bindingName + ' RPC method name must be a string')\n\t\t}\n\t\tconst args = Array.isArray(params[1]) ? params[1] : []\n\t\tconst method = binding && binding[methodName]\n\t\tif (typeof method !== 'function') {\n\t\t\tthrow new Error('Service binding ' + bindingName + ' does not support ' + methodName + '()')\n\t\t}\n\t\treturn method.apply(binding, args)\n\t}\n\n\t// Queues\n\tif (operation === 'queue.send') return binding.send(params[0], params[1])\n\tif (operation === 'queue.sendBatch') return binding.sendBatch(params[0], params[1])\n\n\t// Send Email\n\tif (operation === 'email.send') {\n\t\tif (binding && typeof binding.send === 'function') {\n\t\t\tconst message = params[0]\n\t\t\tif (message && typeof message === 'object' && 'from' in message && 'to' in message && 'raw' in message) {\n\t\t\t\treturn binding.send({\n\t\t\t\t\tfrom: message.from,\n\t\t\t\t\tto: message.to,\n\t\t\t\t\t[RAW_EMAIL]: createEmailMessageRaw(message.raw)\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn binding.send(message)\n\t\t}\n\t\treturn { ok: true, simulated: true }\n\t}\n\n\t// Workflows\n\tif (operation === 'workflow.create') {\n\t\treturn serializeWorkflowInstance(await binding.create(params[0]))\n\t}\n\tif (operation === 'workflow.get') {\n\t\treturn serializeWorkflowInstance(await binding.get(params[0]))\n\t}\n\tif (operation === 'workflow.status') {\n\t\treturn (await binding.get(params[0])).status()\n\t}\n\tif (operation === 'workflow.pause') {\n\t\treturn (await binding.get(params[0])).pause()\n\t}\n\tif (operation === 'workflow.resume') {\n\t\treturn (await binding.get(params[0])).resume()\n\t}\n\tif (operation === 'workflow.terminate') {\n\t\treturn (await binding.get(params[0])).terminate()\n\t}\n\tif (operation === 'workflow.restart') {\n\t\treturn (await binding.get(params[0])).restart()\n\t}\n\tif (operation === 'workflow.sendEvent') {\n\t\treturn (await binding.get(params[0])).sendEvent(params[1])\n\t}\n\n\t// AI / generic run()\n\tif (operation === 'ai.run') {\n\t\tif (typeof binding.run !== 'function') {\n\t\t\tthrow new Error('Binding ' + bindingName + ' does not support run(): ' + method)\n\t\t}\n\t\treturn binding.run(params[0], params[1])\n\t}\n\n\tthrow new Error('Unknown operation: ' + method)\n}\n\nfunction createUnsupportedBridgeOperationErrorMessage(bindingName, operation) {\n\tconst base = \"[devflare][bridge] Unsupported bridge operation '\" + operation + \"' for binding '\" + bindingName + \"'.\"\n\tif (operation === 'fetch') {\n\t\treturn base + ' Devflare could not dispatch fetch() for this binding through the local bridge. '\n\t\t\t+ 'Expected Cloudflare API: env.' + bindingName + '.fetch(request). '\n\t\t\t+ 'If this came from SvelteKit platform.env, make sure the binding is declared as a service binding; '\n\t\t\t+ 'this is a Devflare local bridge issue when service bindings fall back to a bare fetch operation.'\n\t}\n\tif (operation === 'toString') {\n\t\treturn base + ' A platform.env value was coerced to a string through the bridge. '\n\t\t\t+ 'For SvelteKit local dev, declared vars should be plain string values and missing env names should read as undefined.'\n\t}\n\treturn base + ' Bare verbs and the legacy stmt.*/stub.* sub-prefixes are not supported; '\n\t\t+ 'use the namespaced form (e.g. kv.get, r2.put, d1.stmt.first, do.fetch, service.fetch).'\n}\n\nfunction serializeWorkflowInstance(instance) {\n\treturn {\n\t\t__type: 'WorkflowInstance',\n\t\tid: instance.id\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// WebSocket bridge (shared with src/bridge/server.ts in shape)\n// ---------------------------------------------------------------------------\n// NOTE: wsProxies is intentionally created per handleBridgeWebSocket call so\n// state never leaks across connections or across gateway-script regenerations.\n\nasync function handleBridgeRpcCall(msg, ws, env, ctx) {\n\ttry {\n\t\tconst result = await executeRpcMethod(msg.method, msg.params, env, ctx)\n\t\tws.send(JSON.stringify({ t: 'rpc.ok', id: msg.id, result }))\n\t} catch (error) {\n\t\tws.send(JSON.stringify({\n\t\t\tt: 'rpc.err',\n\t\t\tid: msg.id,\n\t\t\terror: {\n\t\t\t\tcode: error?.code || 'INTERNAL_ERROR',\n\t\t\t\tmessage: error?.message || String(error)\n\t\t\t}\n\t\t}))\n\t}\n}\n\nasync function handleBridgeWsOpen(msg, ws, env, wsProxies) {\n\ttry {\n\t\tconst binding = env[msg.target.binding]\n\t\tconst id = binding.idFromString(msg.target.id)\n\t\tconst stub = binding.get(id)\n\n\t\tconst headers = new Headers(msg.target.headers || [])\n\t\theaders.set('Upgrade', 'websocket')\n\n\t\tconst response = await stub.fetch(new Request(msg.target.url, { method: 'GET', headers }))\n\t\tconst doWs = response.webSocket\n\n\t\tif (!doWs) {\n\t\t\tws.send(JSON.stringify({\n\t\t\t\tt: 'rpc.err',\n\t\t\t\tid: 'ws_' + msg.wid,\n\t\t\t\terror: { code: 'WS_FAILED', message: 'No WebSocket returned' }\n\t\t\t}))\n\t\t\treturn\n\t\t}\n\n\t\tdoWs.accept()\n\t\twsProxies.set(msg.wid, { doWs })\n\n\t\tdoWs.addEventListener('message', (event) => {\n\t\t\tconst isText = typeof event.data === 'string'\n\t\t\tconst data = isText ? event.data : arrayBufferToBase64(event.data)\n\t\t\tws.send(JSON.stringify({ t: 'ws.data', wid: msg.wid, data, isText }))\n\t\t})\n\n\t\tdoWs.addEventListener('close', (event) => {\n\t\t\tws.send(JSON.stringify({ t: 'ws.close', wid: msg.wid, code: event.code, reason: event.reason }))\n\t\t\twsProxies.delete(msg.wid)\n\t\t})\n\n\t\tws.send(JSON.stringify({ t: 'ws.opened', wid: msg.wid }))\n\t} catch (error) {\n\t\tws.send(JSON.stringify({\n\t\t\tt: 'rpc.err',\n\t\t\tid: 'ws_' + msg.wid,\n\t\t\terror: { code: 'WS_FAILED', message: error.message }\n\t\t}))\n\t}\n}\n\nfunction handleBridgeWsClose(msg, wsProxies) {\n\tconst proxy = wsProxies.get(msg.wid)\n\tif (proxy) {\n\t\tproxy.doWs.close(msg.code, msg.reason)\n\t\twsProxies.delete(msg.wid)\n\t}\n}\n\nasync function handleBridgeJsonMessage(data, ws, env, ctx, wsProxies) {\n\tconst msg = JSON.parse(data)\n\tswitch (msg.t) {\n\t\tcase 'hello':\n\t\t\t// v2 handshake \u2014 acknowledge with welcome echoing the negotiated\n\t\t\t// capability intersection. Capabilities advertised by the gateway\n\t\t\t// are kept in sync with src/bridge/client.ts (BRIDGE_CLIENT_CAPABILITIES).\n\t\t\tws.send(JSON.stringify({\n\t\t\t\tt: 'welcome',\n\t\t\t\tprotocolVersion: 2,\n\t\t\t\tcapabilities: ['streams', 'ws-relay', 'http-transfer']\n\t\t\t\t\t.filter((c) => Array.isArray(msg.capabilities) && msg.capabilities.includes(c))\n\t\t\t\t\t.sort()\n\t\t\t}))\n\t\t\tbreak\n\t\tcase 'rpc.call':\n\t\t\tawait handleBridgeRpcCall(msg, ws, env, ctx)\n\t\t\tbreak\n\t\tcase 'ws.open':\n\t\t\tawait handleBridgeWsOpen(msg, ws, env, wsProxies)\n\t\t\tbreak\n\t\tcase 'ws.close':\n\t\t\thandleBridgeWsClose(msg, wsProxies)\n\t\t\tbreak\n\t}\n}\n\nfunction handleBridgeWebSocket(request, env, ctx) {\n\tconst { 0: client, 1: server } = new WebSocketPair()\n\tserver.accept()\n\n\t// Per-connection state: recreated for every bridge client so reloads and\n\t// concurrent clients never share WS proxy entries.\n\tconst wsProxies = new Map()\n\n\tserver.addEventListener('message', async (event) => {\n\t\ttry {\n\t\t\tif (typeof event.data === 'string') {\n\t\t\t\tawait handleBridgeJsonMessage(event.data, server, env, ctx, wsProxies)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('[Gateway] Error:', error)\n\t\t}\n\t})\n\n\tserver.addEventListener('close', () => {\n\t\tfor (const proxy of wsProxies.values()) {\n\t\t\t// Best-effort cleanup: the DO-side WS may already be closed or in an\n\t\t\t// invalid state; any throw here would abort sibling closes. Surface\n\t\t\t// the swallowed error when DEVFLARE_DEBUG_BRIDGE is enabled.\n\t\t\ttry { proxy.doWs.close() } catch (error) {\n\t\t\t\tif (globalThis.DEVFLARE_DEBUG_BRIDGE) {\n\t\t\t\t\tconsole.warn('[devflare:bridge] proxy.doWs.close() failed', error)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\twsProxies.clear()\n\t})\n\n\treturn new Response(null, { status: 101, webSocket: client })\n}\n\n// ---------------------------------------------------------------------------\n// HTTP transfer for R2 bodies (shared with src/bridge/server.ts in shape)\n// ---------------------------------------------------------------------------\n\nasync function handleHttpTransfer(request, env, url) {\n\tconst transferIdEncoded = url.pathname.split('/').pop()\n\tconst transferId = decodeURIComponent(transferIdEncoded || '')\n\tconst [binding, ...keyParts] = transferId.split(':')\n\tconst key = keyParts.join(':')\n\tconst bucket = env[binding]\n\n\tif (!bucket) return new Response('Bucket not found: ' + binding, { status: 404 })\n\n\tif (request.method === 'PUT' || request.method === 'POST') {\n\t\tconst result = await bucket.put(key, request.body)\n\t\treturn new Response(JSON.stringify(serializeR2Object(result)), {\n\t\t\theaders: { 'Content-Type': 'application/json' }\n\t\t})\n\t}\n\n\tif (request.method === 'GET') {\n\t\tconst object = await bucket.get(key)\n\t\tif (!object) return new Response('Not found', { status: 404 })\n\t\treturn new Response(object.body, {\n\t\t\theaders: {\n\t\t\t\t'Content-Type': object.httpMetadata?.contentType || 'application/octet-stream',\n\t\t\t\t'Content-Length': String(object.size)\n\t\t\t}\n\t\t})\n\t}\n\n\treturn new Response('Method not allowed', { status: 405 })\n}\n";
8
8
  //# sourceMappingURL=gateway-runtime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"gateway-runtime.d.ts","sourceRoot":"","sources":["../../src/bridge/gateway-runtime.ts"],"names":[],"mappings":"AAcA;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,wgfAod9B,CAAA"}
1
+ {"version":3,"file":"gateway-runtime.d.ts","sourceRoot":"","sources":["../../src/bridge/gateway-runtime.ts"],"names":[],"mappings":"AAcA;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,skjBAigB9B,CAAA"}
@@ -100,7 +100,7 @@ export interface MiniflareOptions {
100
100
  allowedSenderAddresses?: string[];
101
101
  }>;
102
102
  /** Environment variables */
103
- bindings?: Record<string, string>;
103
+ bindings?: Record<string, unknown>;
104
104
  /** Service bindings */
105
105
  serviceBindings?: Record<string, {
106
106
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"miniflare.d.ts","sourceRoot":"","sources":["../../src/bridge/miniflare.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"miniflare.d.ts","sourceRoot":"","sources":["../../src/bridge/miniflare.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,8 @@ export interface EnvProxyOptions {
4
4
  client?: BridgeClient;
5
5
  /** Lazily connect on first access */
6
6
  lazy?: boolean;
7
+ /** Return undefined for names that are not present in binding hints */
8
+ strict?: boolean;
7
9
  /** Transform results before returning (e.g., for transport decoding) */
8
10
  transformResult?: (result: unknown) => unknown;
9
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/bridge/proxy.ts"],"names":[],"mappings":"AAMA,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,UAAU,CAAA;AAavD,MAAM,WAAW,eAAe;IAC/B,0DAA0D;IAC1D,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB,qCAAqC;IACrC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,wEAAwE;IACxE,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAA;CAC9C;AAmhBD,mDAAmD;AACnD,MAAM,MAAM,WAAW,GACpB,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,OAAO,GACP,IAAI,GACJ,SAAS,GACT,WAAW,GACX,UAAU,GACV,QAAQ,GACR,KAAK,CAAA;AAER,MAAM,WAAW,YAAY;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAA;CAC1B;AAKD;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,eAAe,GAAG;IAAE,KAAK,CAAC,EAAE,YAAY,CAAA;CAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA4EhH;AAoFD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAO5C,CAAA;AAEF;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,GAAE,eAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAG9E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAIzD"}
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/bridge/proxy.ts"],"names":[],"mappings":"AAMA,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,UAAU,CAAA;AAavD,MAAM,WAAW,eAAe;IAC/B,0DAA0D;IAC1D,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB,qCAAqC;IACrC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,wEAAwE;IACxE,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAA;CAC9C;AAilBD,mDAAmD;AACnD,MAAM,MAAM,WAAW,GACpB,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,OAAO,GACP,IAAI,GACJ,SAAS,GACT,WAAW,GACX,UAAU,GACV,QAAQ,GACR,KAAK,CAAA;AAER,MAAM,WAAW,YAAY;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAA;CAC1B;AAKD;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,eAAe,GAAG;IAAE,KAAK,CAAC,EAAE,YAAY,CAAA;CAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoFhH;AAoFD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAO5C,CAAA;AAEF;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,GAAE,eAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAG9E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAIzD"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/bridge/server.ts"],"names":[],"mappings":"AAqCA,MAAM,WAAW,UAAU;IAE1B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACtB;;IAiBM,KAAK,UAAU,OAAO,OAAO,UAAU,OAAO,gBAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;;;AA8KzF,wBAAsB,gBAAgB,CACrC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,EAAE,EACjB,GAAG,EAAE,UAAU,EACf,GAAG,EAAE,gBAAgB,GACnB,OAAO,CAAC,OAAO,CAAC,CAwJlB"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/bridge/server.ts"],"names":[],"mappings":"AAuCA,MAAM,WAAW,UAAU;IAE1B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACtB;;IAiBM,KAAK,UAAU,OAAO,OAAO,UAAU,OAAO,gBAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;;;AA8KzF,wBAAsB,gBAAgB,CACrC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,EAAE,EACjB,GAAG,EAAE,UAAU,EACf,GAAG,EAAE,gBAAgB,GACnB,OAAO,CAAC,OAAO,CAAC,CA2JlB"}