devflare 1.0.0-next.59 → 1.0.0-next.60

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 (45) hide show
  1. package/dist/_chunks/{build-IR-IaQN1.js → build-Dp8k2SWa.js} +1 -1
  2. package/dist/_chunks/{build-artifacts-C7JfIRnw.js → build-artifacts-DLEYfdVL.js} +2 -2
  3. package/dist/_chunks/{cli-yOO5yCaf.js → cli-BlVetiEh.js} +5 -5
  4. package/dist/_chunks/{compiler-okj8qvCh.js → compiler-CgIFPfRA.js} +23 -1
  5. package/dist/_chunks/{config-C8Qux0NR.js → config-BwRb2_vD.js} +1 -1
  6. package/dist/_chunks/{deploy-BG2PHaWu.js → deploy-Blrdr3Gv.js} +2 -2
  7. package/dist/_chunks/{dev-BgQl56Bd.js → dev-DRP6LR2H.js} +42 -7
  8. package/dist/_chunks/{previews-fTFp1WkQ.js → previews-D-GPVCeq.js} +1 -1
  9. package/dist/_chunks/r2-presign-runtime-zTOLS0Ea.js +291 -0
  10. package/dist/_chunks/{runtime-DL-Nz3k8.js → runtime-RekfD_2X.js} +325 -1
  11. package/dist/_chunks/{vite-De7bGxC6.js → vite-CtvgOi1c.js} +2 -2
  12. package/dist/bridge/miniflare-gateway.d.ts +45 -0
  13. package/dist/bridge/miniflare-gateway.d.ts.map +1 -0
  14. package/dist/bridge/miniflare.d.ts +8 -1
  15. package/dist/bridge/miniflare.d.ts.map +1 -1
  16. package/dist/bridge/r2-presign-runtime.d.ts +9 -0
  17. package/dist/bridge/r2-presign-runtime.d.ts.map +1 -0
  18. package/dist/cli/index.js +1 -1
  19. package/dist/config/compiler.d.ts.map +1 -1
  20. package/dist/dev-server/gateway-script.d.ts +2 -1
  21. package/dist/dev-server/gateway-script.d.ts.map +1 -1
  22. package/dist/dev-server/miniflare-dev-config.d.ts +13 -0
  23. package/dist/dev-server/miniflare-dev-config.d.ts.map +1 -1
  24. package/dist/dev-server/miniflare-worker-config.d.ts +7 -0
  25. package/dist/dev-server/miniflare-worker-config.d.ts.map +1 -1
  26. package/dist/dev-server/server.d.ts.map +1 -1
  27. package/dist/dev-server/vite-process.d.ts +9 -0
  28. package/dist/dev-server/vite-process.d.ts.map +1 -1
  29. package/dist/index.js +2 -2
  30. package/dist/runtime/index.d.ts +1 -0
  31. package/dist/runtime/index.d.ts.map +1 -1
  32. package/dist/runtime/index.js +2 -2
  33. package/dist/runtime/r2-presign.d.ts +164 -0
  34. package/dist/runtime/r2-presign.d.ts.map +1 -0
  35. package/dist/test/index.js +41 -4
  36. package/dist/test/simple-context-gateway-script.d.ts.map +1 -1
  37. package/dist/test/simple-context-mfconfig.d.ts +8 -0
  38. package/dist/test/simple-context-mfconfig.d.ts.map +1 -1
  39. package/dist/test/simple-context-multi-worker.d.ts.map +1 -1
  40. package/dist/test/simple-context-runtime.d.ts.map +1 -1
  41. package/dist/test/simple-context-startup.d.ts.map +1 -1
  42. package/dist/test/simple-context.d.ts.map +1 -1
  43. package/dist/vite/index.js +1 -1
  44. package/package.json +3 -2
  45. package/dist/_chunks/local-workflow-entrypoints-ZIL7apIa.js +0 -90
@@ -1,5 +1,5 @@
1
1
  import { n as getDurableObjectOptions, t as durableObject } from "../_chunks/decorators-QmV57ixr.js";
2
2
  import { A as createTailEvent, C as createDurableObjectWebSocketCloseEvent, D as createFetchEvent, E as createEmailEvent, O as createQueueEvent, S as createDurableObjectFetchEvent, T as createDurableObjectWebSocketMessageEvent, _ as runWithContext, a as getDurableObjectFetchEvent, b as createContextProxy, c as getDurableObjectWebSocketMessageEvent, d as getEventContextOrNull, f as getFetchEvent, g as hasContext, h as getTailEvent, i as getDurableObjectEvent, k as createScheduledEvent, l as getEmailEvent, m as getScheduledEvent, n as getContextOrNull, o as getDurableObjectWebSocketCloseEvent, p as getQueueEvent, r as getDurableObjectAlarmEvent, s as getDurableObjectWebSocketErrorEvent, t as getContext, u as getEventContext, v as runWithEventContext, w as createDurableObjectWebSocketErrorEvent, x as createDurableObjectAlarmEvent, y as ContextAccessError } from "../_chunks/context-CX50Y2Kb.js";
3
3
  import { clearLocalSendEmailBindings, setLocalSendEmailBindings } from "../utils/send-email.js";
4
- import { _ as ctx, a as assertExplicitQueueHandlerStyle, b as locals, c as defineFetchHandler, d as invokeFetchHandler, f as invokeFetchModule, g as sequence, h as resolveFetchHandler, i as assertExplicit2ArgStyle, l as defineQueueHandler, m as markWorkerStyle, n as invokeRouteModules, o as assertExplicitScheduledHandlerStyle, p as markResolveStyle, r as matchFetchRoute, s as createResolveFetch, t as createRouteResolve, u as defineScheduledHandler, v as env, x as vars, y as event } from "../_chunks/runtime-DL-Nz3k8.js";
5
- export { ContextAccessError, assertExplicit2ArgStyle, assertExplicitQueueHandlerStyle, assertExplicitScheduledHandlerStyle, clearLocalSendEmailBindings, createContextProxy, createDurableObjectAlarmEvent, createDurableObjectFetchEvent, createDurableObjectWebSocketCloseEvent, createDurableObjectWebSocketErrorEvent, createDurableObjectWebSocketMessageEvent, createEmailEvent, createFetchEvent, createQueueEvent, createResolveFetch, createRouteResolve, createScheduledEvent, createTailEvent, ctx, defineFetchHandler, defineQueueHandler, defineScheduledHandler, durableObject, env, event, getContext, getContextOrNull, getDurableObjectAlarmEvent, getDurableObjectEvent, getDurableObjectFetchEvent, getDurableObjectOptions, getDurableObjectWebSocketCloseEvent, getDurableObjectWebSocketErrorEvent, getDurableObjectWebSocketMessageEvent, getEmailEvent, getEventContext, getEventContextOrNull, getFetchEvent, getQueueEvent, getScheduledEvent, getTailEvent, hasContext, invokeFetchHandler, invokeFetchModule, invokeRouteModules, locals, markResolveStyle, markWorkerStyle, matchFetchRoute, resolveFetchHandler, runWithContext, runWithEventContext, sequence, setLocalSendEmailBindings, vars };
4
+ import { C as vars, S as locals, _ as resolveFetchHandler, a as matchFetchRoute, b as env, c as assertExplicitScheduledHandlerStyle, d as defineQueueHandler, f as defineScheduledHandler, g as markWorkerStyle, h as markResolveStyle, i as invokeRouteModules, l as createResolveFetch, m as invokeFetchModule, n as presignR2Put, o as assertExplicit2ArgStyle, p as invokeFetchHandler, r as createRouteResolve, s as assertExplicitQueueHandlerStyle, t as presignR2Get, u as defineFetchHandler, v as sequence, x as event, y as ctx } from "../_chunks/runtime-RekfD_2X.js";
5
+ export { ContextAccessError, assertExplicit2ArgStyle, assertExplicitQueueHandlerStyle, assertExplicitScheduledHandlerStyle, clearLocalSendEmailBindings, createContextProxy, createDurableObjectAlarmEvent, createDurableObjectFetchEvent, createDurableObjectWebSocketCloseEvent, createDurableObjectWebSocketErrorEvent, createDurableObjectWebSocketMessageEvent, createEmailEvent, createFetchEvent, createQueueEvent, createResolveFetch, createRouteResolve, createScheduledEvent, createTailEvent, ctx, defineFetchHandler, defineQueueHandler, defineScheduledHandler, durableObject, env, event, getContext, getContextOrNull, getDurableObjectAlarmEvent, getDurableObjectEvent, getDurableObjectFetchEvent, getDurableObjectOptions, getDurableObjectWebSocketCloseEvent, getDurableObjectWebSocketErrorEvent, getDurableObjectWebSocketMessageEvent, getEmailEvent, getEventContext, getEventContextOrNull, getFetchEvent, getQueueEvent, getScheduledEvent, getTailEvent, hasContext, invokeFetchHandler, invokeFetchModule, invokeRouteModules, locals, markResolveStyle, markWorkerStyle, matchFetchRoute, presignR2Get, presignR2Put, resolveFetchHandler, runWithContext, runWithEventContext, sequence, setLocalSendEmailBindings, vars };
@@ -0,0 +1,164 @@
1
+ /** URL path prefix of the local presign endpoint served by devflare gateways. */
2
+ export declare const R2_PRESIGN_LOCAL_PATH_PREFIX = "/_devflare/r2/presigned/";
3
+ /** Env/var names devflare injects in local dev + tests to enable local presigning. */
4
+ export declare const R2_PRESIGN_SECRET_VAR = "DEVFLARE_R2_PRESIGN_SECRET";
5
+ export declare const R2_PRESIGN_ORIGIN_VAR = "DEVFLARE_R2_PRESIGN_ORIGIN";
6
+ /** Var (injected at deploy compile time) mapping R2 binding names to bucket metadata. */
7
+ export declare const R2_BUCKETS_VAR = "DEVFLARE_R2_BUCKETS";
8
+ /** Default env/secret names for R2 S3 API credentials in production. */
9
+ export declare const R2_ACCOUNT_ID_VAR = "R2_ACCOUNT_ID";
10
+ export declare const R2_ACCESS_KEY_ID_VAR = "R2_ACCESS_KEY_ID";
11
+ export declare const R2_SECRET_ACCESS_KEY_VAR = "R2_SECRET_ACCESS_KEY";
12
+ /**
13
+ * R2 S3 API credentials used for production presigning.
14
+ * Create them under Cloudflare Dashboard → R2 → Manage R2 API Tokens.
15
+ */
16
+ export interface R2PresignCredentials {
17
+ /** Cloudflare account id that owns the bucket (not secret). */
18
+ accountId: string;
19
+ /** R2 S3 API access key id. */
20
+ accessKeyId: string;
21
+ /** R2 S3 API secret access key. Store as a Worker secret, never in config. */
22
+ secretAccessKey: string;
23
+ }
24
+ /**
25
+ * Options shared by `presignR2Put` and `presignR2Get`.
26
+ */
27
+ export interface R2PresignBaseOptions {
28
+ /**
29
+ * URL lifetime in seconds. Enforced by R2 in production and by the
30
+ * devflare gateway locally.
31
+ *
32
+ * @default 900 (15 minutes). Maximum 604800 (7 days).
33
+ */
34
+ expiresIn?: number;
35
+ /**
36
+ * Production credentials override. When omitted they are read from `env`
37
+ * under `R2_ACCOUNT_ID`, `R2_ACCESS_KEY_ID` and `R2_SECRET_ACCESS_KEY`.
38
+ * Ignored in local dev (the gateway signs with its own per-boot secret).
39
+ */
40
+ credentials?: R2PresignCredentials;
41
+ /**
42
+ * Production bucket name override. When omitted it is resolved from the
43
+ * `DEVFLARE_R2_BUCKETS` var that `devflare` injects at deploy compile
44
+ * time from `bindings.r2`. Ignored in local dev (the binding name routes
45
+ * directly to the local bucket).
46
+ */
47
+ bucketName?: string;
48
+ /**
49
+ * Jurisdiction of the production bucket (e.g. `'eu'`), which changes the
50
+ * S3 endpoint host. When omitted it is resolved from `DEVFLARE_R2_BUCKETS`
51
+ * (i.e. from the `jurisdiction` field on the R2 binding config).
52
+ */
53
+ jurisdiction?: string;
54
+ }
55
+ /**
56
+ * Options for `presignR2Put`.
57
+ */
58
+ export interface R2PresignPutOptions extends R2PresignBaseOptions {
59
+ /**
60
+ * Content type the uploader must send. Enforced cryptographically in both
61
+ * environments: it is a signed header in production and part of the
62
+ * signed canonical string locally, so a mismatching `Content-Type` on the
63
+ * actual PUT is rejected.
64
+ */
65
+ contentType?: string;
66
+ /**
67
+ * Exact body size in bytes the uploader must send. Enforced in both
68
+ * environments (signed `Content-Length` header in production; header +
69
+ * actual byte count locally). Prefer this over `maxSizeBytes` when the
70
+ * file size is known up front — it is the only size guarantee real R2
71
+ * presigned PUTs can enforce. GOTCHA: the client must then send a
72
+ * fixed-size body (`File`/`Blob`/`ArrayBuffer`); a streamed body carries
73
+ * no `Content-Length` header and fails the signed-header check.
74
+ */
75
+ contentLength?: number;
76
+ /**
77
+ * Upper size bound in bytes. Enforced by the devflare gateway locally.
78
+ * GOTCHA: real R2 presigned PUT URLs CANNOT enforce an upper bound —
79
+ * only an exact signed `Content-Length` — so in production this value is
80
+ * advisory. Always confirm the object with a server-side `head()` before
81
+ * committing quota.
82
+ */
83
+ maxSizeBytes?: number;
84
+ }
85
+ /**
86
+ * Options for `presignR2Get`.
87
+ */
88
+ export type R2PresignGetOptions = R2PresignBaseOptions;
89
+ /**
90
+ * A presigned request the browser can execute directly against storage.
91
+ */
92
+ export interface PresignedR2Request {
93
+ /** Fully-signed URL to fetch. Treat as opaque; it embeds the signature. */
94
+ url: string;
95
+ /** HTTP method the URL was signed for (`HEAD` is also accepted for `GET` URLs). */
96
+ method: 'PUT' | 'GET';
97
+ /**
98
+ * Headers the client MUST send for the signature to validate (e.g. the
99
+ * pinned `content-type`). `content-length` is intentionally omitted —
100
+ * browsers set it automatically from the request body and reject manual
101
+ * assignment.
102
+ */
103
+ headers: Record<string, string>;
104
+ /** Moment the URL stops being accepted. */
105
+ expiresAt: Date;
106
+ /** Object key the URL operates on. */
107
+ key: string;
108
+ /** `'local'` when served by the devflare gateway, `'remote'` for real R2. */
109
+ mode: 'local' | 'remote';
110
+ }
111
+ /**
112
+ * Presign a direct-to-R2 `PUT` URL for a browser (or any HTTP client) upload.
113
+ *
114
+ * Resolves to a real R2 S3 presigned URL in production and to a signed
115
+ * devflare-gateway URL in local dev and the test harness — same call, same
116
+ * guarantees (signature, expiry, method, content type, size), so upload and
117
+ * quota logic can be exercised identically in every environment.
118
+ *
119
+ * @param env - The platform env (`platform.env` in SvelteKit, `env` in a
120
+ * Worker handler). Used to detect the local dev context and to read
121
+ * production credentials/bucket mapping.
122
+ * @param binding - The R2 binding name from `bindings.r2` (e.g. `'BUCKET'`).
123
+ * @param key - Object key to upload to. Percent-encoding is handled internally.
124
+ * @param options - Expiry, enforcement (content type / length / max size) and
125
+ * production credential overrides.
126
+ * @returns The presigned request: `url` to PUT to, `headers` the client must
127
+ * send, and `expiresAt`.
128
+ * @throws {Error} in production when credentials or the bucket mapping are missing.
129
+ * @throws {TypeError | RangeError} on invalid inputs.
130
+ *
131
+ * @example
132
+ * ```ts
133
+ * // Server (SvelteKit endpoint) — reserve quota first, then presign:
134
+ * const { url, headers } = await presignR2Put(platform.env, 'BUCKET', `media/${id}.png`, {
135
+ * expiresIn: 600,
136
+ * contentType: file.type,
137
+ * contentLength: file.size
138
+ * })
139
+ *
140
+ * // Browser — upload directly to storage:
141
+ * await fetch(url, { method: 'PUT', body: file, headers })
142
+ *
143
+ * // Server — finalize: confirm the object before committing quota:
144
+ * const head = await platform.env.BUCKET.head(`media/${id}.png`)
145
+ * ```
146
+ */
147
+ export declare function presignR2Put(env: Record<string, unknown>, binding: string, key: string, options?: R2PresignPutOptions): Promise<PresignedR2Request>;
148
+ /**
149
+ * Presign a direct-from-R2 `GET` URL (also valid for `HEAD`) so a browser can
150
+ * download an object without routing the bytes through the Worker.
151
+ *
152
+ * Same dev/prod symmetry as {@link presignR2Put}. Note that browser reads
153
+ * from real R2 additionally require CORS rules on the bucket itself.
154
+ *
155
+ * @param env - The platform env (see {@link presignR2Put}).
156
+ * @param binding - The R2 binding name from `bindings.r2`.
157
+ * @param key - Object key to read.
158
+ * @param options - Expiry and production credential overrides.
159
+ * @returns The presigned request; `headers` is always empty for GET.
160
+ * @throws {Error} in production when credentials or the bucket mapping are missing.
161
+ * @throws {TypeError | RangeError} on invalid inputs.
162
+ */
163
+ export declare function presignR2Get(env: Record<string, unknown>, binding: string, key: string, options?: R2PresignGetOptions): Promise<PresignedR2Request>;
164
+ //# sourceMappingURL=r2-presign.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"r2-presign.d.ts","sourceRoot":"","sources":["../../src/runtime/r2-presign.ts"],"names":[],"mappings":"AAuBA,iFAAiF;AACjF,eAAO,MAAM,4BAA4B,6BAA6B,CAAA;AAKtE,sFAAsF;AACtF,eAAO,MAAM,qBAAqB,+BAA+B,CAAA;AACjE,eAAO,MAAM,qBAAqB,+BAA+B,CAAA;AAEjE,yFAAyF;AACzF,eAAO,MAAM,cAAc,wBAAwB,CAAA;AAEnD,wEAAwE;AACxE,eAAO,MAAM,iBAAiB,kBAAkB,CAAA;AAChD,eAAO,MAAM,oBAAoB,qBAAqB,CAAA;AACtD,eAAO,MAAM,wBAAwB,yBAAyB,CAAA;AAY9D;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACpC,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAA;IACjB,+BAA+B;IAC/B,WAAW,EAAE,MAAM,CAAA;IACnB,8EAA8E;IAC9E,eAAe,EAAE,MAAM,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;;;OAIG;IACH,WAAW,CAAC,EAAE,oBAAoB,CAAA;IAElC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,oBAAoB;IAChE;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACrB;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,oBAAoB,CAAA;AAEtD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,2EAA2E;IAC3E,GAAG,EAAE,MAAM,CAAA;IACX,mFAAmF;IACnF,MAAM,EAAE,KAAK,GAAG,KAAK,CAAA;IACrB;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,2CAA2C;IAC3C,SAAS,EAAE,IAAI,CAAA;IACf,sCAAsC;IACtC,GAAG,EAAE,MAAM,CAAA;IACX,6EAA6E;IAC7E,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAA;CACxB;AAqYD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAsB,YAAY,CACjC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,mBAAwB,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CA0B7B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,YAAY,CACjC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,mBAAwB,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CAe7B"}
@@ -7,12 +7,12 @@ import { d as getPrimaryAccount, n as getEffectiveAccountId } from "../_chunks/p
7
7
  import { A as createTailEvent, D as createFetchEvent, E as createEmailEvent, F as BridgeClient, M as createEnvProxy, O as createQueueEvent, P as setBindingHints, _ as runWithContext, k as createScheduledEvent, v as runWithEventContext, x as createDurableObjectAlarmEvent } from "../_chunks/context-CX50Y2Kb.js";
8
8
  import { createLocalSendEmailBinding, wrapEnvSendEmailBindings } from "../utils/send-email.js";
9
9
  import { n as __setTestContext, r as env, t as __clearTestContext } from "../_chunks/env-S0_nMVz1.js";
10
- import { f as invokeFetchModule, h as resolveFetchHandler, r as matchFetchRoute, t as createRouteResolve } from "../_chunks/runtime-DL-Nz3k8.js";
10
+ import { _ as resolveFetchHandler, a as matchFetchRoute, m as invokeFetchModule, r as createRouteResolve } from "../_chunks/runtime-RekfD_2X.js";
11
11
  import { i as extractBindingHints, n as createLocalWorkerLoaderBinding, r as disposeLocalWorkerLoaderBindings, t as createLocalHyperdrive } from "../_chunks/local-hyperdrive-CJ90j46O.js";
12
12
  import { E as buildTailConsumersConfig, T as buildStreamingTailConsumersConfig, a as hasServiceBindings, i as hasCrossWorkerDOs, m as buildHyperdrivesConfig, o as resolveDOBindings, r as clearBundleCache, s as resolveServiceBindings, t as discoverRoutes, u as buildAnalyticsEngineConfig } from "../_chunks/routes-BMU7ga_l.js";
13
13
  import { i as findFiles, t as DEFAULT_DO_PATTERN } from "../_chunks/glob-CmQOvunB.js";
14
14
  import { a as isRemoteModeActive, i as getRemoteModeStatus } from "../_chunks/remote-config-D39BY9ji.js";
15
- import { t as bundleWorkflowEntrypointScript } from "../_chunks/local-workflow-entrypoints-ZIL7apIa.js";
15
+ import { n as bundleWorkflowEntrypointScript, t as R2_PRESIGN_RUNTIME_JS } from "../_chunks/r2-presign-runtime-zTOLS0Ea.js";
16
16
  import { a as resolveLocalSecretValuesForBindings, n as buildLocalSecretWrappedBindingConfig } from "../_chunks/local-secrets-6sMstHXw.js";
17
17
  import { t as buildLocalBindingShimServiceConfig } from "../_chunks/local-media-bindings-DsAW4AMF.js";
18
18
  import { t as canProceedWithTest } from "../_chunks/usage-BBTGzjon.js";
@@ -1574,6 +1574,8 @@ function buildRemoteAndStaticBindings(config) {
1574
1574
  //#region src/test/simple-context-gateway-script.ts
1575
1575
  function buildGatewayScript(bundledCode, wrappers, nativeRpcBindingNames = []) {
1576
1576
  return `
1577
+ ${R2_PRESIGN_RUNTIME_JS}
1578
+
1577
1579
  // Bundled transport + DO classes
1578
1580
  ${bundledCode}
1579
1581
 
@@ -1630,6 +1632,10 @@ export default {
1630
1632
  })
1631
1633
  return new Response(null, { status: 101, webSocket: client })
1632
1634
  }
1635
+ const presignResponse = await __devflareR2PresignHandle(request, env, new URL(request.url))
1636
+ if (presignResponse) {
1637
+ return presignResponse
1638
+ }
1633
1639
  return new Response('Gateway')
1634
1640
  }
1635
1641
  }
@@ -3332,6 +3338,20 @@ function createDisposeContext(state) {
3332
3338
  //#endregion
3333
3339
  //#region src/test/simple-context-mfconfig.ts
3334
3340
  /**
3341
+ * Return `bindings` with the local R2 presign gateway origin added, when (and
3342
+ * only when) the presign secret was wired in. The origin can only be built at
3343
+ * boot time — the test context picks a fresh port per startup attempt — so
3344
+ * this runs next to each `new Miniflare(...)` call rather than in the config
3345
+ * builder.
3346
+ */
3347
+ function addR2PresignOriginVar(bindings, port) {
3348
+ if (!bindings || typeof bindings.DEVFLARE_R2_PRESIGN_SECRET !== "string") return bindings;
3349
+ return {
3350
+ ...bindings,
3351
+ DEVFLARE_R2_PRESIGN_ORIGIN: `http://127.0.0.1:${port}`
3352
+ };
3353
+ }
3354
+ /**
3335
3355
  * Build the seed Miniflare config for an inline (single-worker) bridge.
3336
3356
  * Pure: no I/O, no closures.
3337
3357
  */
@@ -3484,6 +3504,7 @@ function applyMultiWorkerConfig(mfConfig, config, serviceBindingResolution, doBi
3484
3504
  ...mfConfig.artifacts && { artifacts: mfConfig.artifacts },
3485
3505
  ...mfConfig.secretsStoreSecrets && { secretsStoreSecrets: mfConfig.secretsStoreSecrets },
3486
3506
  ...mfConfig.wrappedBindings && { wrappedBindings: mfConfig.wrappedBindings },
3507
+ ...mfConfig.bindings && { bindings: mfConfig.bindings },
3487
3508
  ...mfConfig.email && { email: mfConfig.email },
3488
3509
  ...Object.keys(primaryDurableObjects).length > 0 && { durableObjects: primaryDurableObjects },
3489
3510
  ...mfConfig.serviceBindings || serviceBindingResolution?.primaryServiceBindings ? { serviceBindings: {
@@ -3529,6 +3550,7 @@ function applyMultiWorkerConfig(mfConfig, config, serviceBindingResolution, doBi
3529
3550
  delete mfConfig.artifacts;
3530
3551
  delete mfConfig.secretsStoreSecrets;
3531
3552
  delete mfConfig.wrappedBindings;
3553
+ delete mfConfig.bindings;
3532
3554
  delete mfConfig.serviceBindings;
3533
3555
  delete mfConfig.__devflareLocalSecretWorkers;
3534
3556
  delete mfConfig.__devflareLocalBindingWorkers;
@@ -3597,10 +3619,13 @@ async function startBridgeBackedTestContext(mfConfig) {
3597
3619
  let miniflare = null;
3598
3620
  let client = null;
3599
3621
  try {
3600
- miniflare = new Miniflare(expandLocalBindingWorkers({
3622
+ const attemptConfig = {
3601
3623
  ...mfConfig,
3602
3624
  port
3603
- }));
3625
+ };
3626
+ const bindingsWithOrigin = addR2PresignOriginVar(attemptConfig.bindings, port);
3627
+ if (bindingsWithOrigin) attemptConfig.bindings = bindingsWithOrigin;
3628
+ miniflare = new Miniflare(expandLocalBindingWorkers(attemptConfig));
3604
3629
  await miniflare.ready;
3605
3630
  const miniflareBindings = wrapEnvSendEmailBindings(await miniflare.getBindings());
3606
3631
  client = await connectBridgeClientWithRetry(`ws://localhost:${port}`);
@@ -3636,6 +3661,9 @@ async function bootTestRuntime(mfConfig, usesMultiWorker) {
3636
3661
  if (usesMultiWorker) {
3637
3662
  const { Miniflare } = await import("miniflare");
3638
3663
  const activePort = await getAvailablePort();
3664
+ const primaryWorker = Array.isArray(mfConfig.workers) ? mfConfig.workers[0] : void 0;
3665
+ const primaryBindings = addR2PresignOriginVar(primaryWorker?.bindings, activePort);
3666
+ if (primaryWorker && primaryBindings) primaryWorker.bindings = primaryBindings;
3639
3667
  const miniflare = new Miniflare({
3640
3668
  ...mfConfig,
3641
3669
  port: activePort
@@ -3728,6 +3756,11 @@ async function createTestContext(configPath) {
3728
3756
  if (needsMultiWorkerForServices) serviceBindingResolution = await resolveServiceBindings(config, configDir);
3729
3757
  if (needsMultiWorkerForDOs) doBindingResolution = await resolveDOBindings(config, configDir);
3730
3758
  const mfConfig = buildInlineBridgeMfConfig(config, { cwd: configDir });
3759
+ const r2PresignSecret = config.bindings?.r2 ? `${crypto.randomUUID()}${crypto.randomUUID()}` : null;
3760
+ if (r2PresignSecret) mfConfig.bindings = {
3761
+ ...mfConfig.bindings,
3762
+ DEVFLARE_R2_PRESIGN_SECRET: r2PresignSecret
3763
+ };
3731
3764
  const transportFile = resolveTransportFile(configDir, config.files?.transport);
3732
3765
  if (transportFile) state.transportDecode = await loadTransportDecoders(configDir, transportFile);
3733
3766
  const gateway = await buildDurableObjectGateway(config, configDir, transportFile);
@@ -3742,6 +3775,10 @@ async function createTestContext(configPath) {
3742
3775
  state.miniflare = runtime.miniflare;
3743
3776
  state.miniflareBindings = runtime.miniflareBindings;
3744
3777
  state.client = runtime.client;
3778
+ if (r2PresignSecret && state.miniflareBindings) {
3779
+ state.miniflareBindings.DEVFLARE_R2_PRESIGN_SECRET = r2PresignSecret;
3780
+ state.miniflareBindings.DEVFLARE_R2_PRESIGN_ORIGIN = `http://127.0.0.1:${activePort}`;
3781
+ }
3745
3782
  const disposeContext = createDisposeContext(state);
3746
3783
  const getTestEnv = () => {
3747
3784
  return new Proxy({}, {
@@ -1 +1 @@
1
- {"version":3,"file":"simple-context-gateway-script.d.ts","sourceRoot":"","sources":["../../src/test/simple-context-gateway-script.ts"],"names":[],"mappings":"AAAA,wBAAgB,kBAAkB,CACjC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,qBAAqB,GAAE,MAAM,EAAO,GAClC,MAAM,CAoNR"}
1
+ {"version":3,"file":"simple-context-gateway-script.d.ts","sourceRoot":"","sources":["../../src/test/simple-context-gateway-script.ts"],"names":[],"mappings":"AAEA,wBAAgB,kBAAkB,CACjC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,qBAAqB,GAAE,MAAM,EAAO,GAClC,MAAM,CA0NR"}
@@ -2,6 +2,14 @@ import type { DevflareConfig } from '../config/index.js';
2
2
  export interface BuildInlineBridgeMfConfigOptions {
3
3
  cwd?: string;
4
4
  }
5
+ /**
6
+ * Return `bindings` with the local R2 presign gateway origin added, when (and
7
+ * only when) the presign secret was wired in. The origin can only be built at
8
+ * boot time — the test context picks a fresh port per startup attempt — so
9
+ * this runs next to each `new Miniflare(...)` call rather than in the config
10
+ * builder.
11
+ */
12
+ export declare function addR2PresignOriginVar(bindings: Record<string, unknown> | undefined, port: number): Record<string, unknown> | undefined;
5
13
  /**
6
14
  * Build the seed Miniflare config for an inline (single-worker) bridge.
7
15
  * Pure: no I/O, no closures.
@@ -1 +1 @@
1
- {"version":3,"file":"simple-context-mfconfig.d.ts","sourceRoot":"","sources":["../../src/test/simple-context-mfconfig.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAU/C,MAAM,WAAW,gCAAgC;IAChD,GAAG,CAAC,EAAE,MAAM,CAAA;CACZ;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACxC,MAAM,EAAE,cAAc,EACtB,OAAO,GAAE,gCAAqC,GAC5C,GAAG,CA6QL"}
1
+ {"version":3,"file":"simple-context-mfconfig.d.ts","sourceRoot":"","sources":["../../src/test/simple-context-mfconfig.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAU/C,MAAM,WAAW,gCAAgC;IAChD,GAAG,CAAC,EAAE,MAAM,CAAA;CACZ;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACpC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC7C,IAAI,EAAE,MAAM,GACV,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAKrC;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACxC,MAAM,EAAE,cAAc,EACtB,OAAO,GAAE,gCAAqC,GAC5C,GAAG,CA6QL"}
@@ -1 +1 @@
1
- {"version":3,"file":"simple-context-multi-worker.d.ts","sourceRoot":"","sources":["../../src/test/simple-context-multi-worker.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AAE3F,KAAK,wBAAwB,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAA;AAClF,KAAK,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAA;AAExE;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACrC,QAAQ,EAAE,GAAG,EACb,MAAM,EAAE,cAAc,EACtB,wBAAwB,EAAE,wBAAwB,GAAG,IAAI,EACzD,mBAAmB,EAAE,mBAAmB,GAAG,IAAI,GAC7C,IAAI,CA0FN"}
1
+ {"version":3,"file":"simple-context-multi-worker.d.ts","sourceRoot":"","sources":["../../src/test/simple-context-multi-worker.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AAE3F,KAAK,wBAAwB,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAA;AAClF,KAAK,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAA;AAExE;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACrC,QAAQ,EAAE,GAAG,EACb,MAAM,EAAE,cAAc,EACtB,wBAAwB,EAAE,wBAAwB,GAAG,IAAI,EACzD,mBAAmB,EAAE,mBAAmB,GAAG,IAAI,GAC7C,IAAI,CA+FN"}
@@ -1 +1 @@
1
- {"version":3,"file":"simple-context-runtime.d.ts","sourceRoot":"","sources":["../../src/test/simple-context-runtime.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAKpD,MAAM,WAAW,iBAAiB;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,GAAG,CAAA;IACd,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC1C,8CAA8C;IAC9C,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;CAC3B;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACpC,QAAQ,EAAE,GAAG,EACb,eAAe,EAAE,OAAO,GACtB,OAAO,CAAC,iBAAiB,CAAC,CAoB5B"}
1
+ {"version":3,"file":"simple-context-runtime.d.ts","sourceRoot":"","sources":["../../src/test/simple-context-runtime.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAMpD,MAAM,WAAW,iBAAiB;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,GAAG,CAAA;IACd,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC1C,8CAA8C;IAC9C,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;CAC3B;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACpC,QAAQ,EAAE,GAAG,EACb,eAAe,EAAE,OAAO,GACtB,OAAO,CAAC,iBAAiB,CAAC,CA6B5B"}
@@ -1 +1 @@
1
- {"version":3,"file":"simple-context-startup.d.ts","sourceRoot":"","sources":["../../src/test/simple-context-startup.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAS/C,MAAM,WAAW,8BAA8B;IAC9C,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,YAAY,CAAA;IACpB,SAAS,EAAE,GAAG,CAAA;IACd,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC1C;AAED,wBAAgB,kCAAkC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAa1E;AAUD,wBAAsB,4BAA4B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA2BrF;AAiDD,wBAAsB,4BAA4B,CACjD,QAAQ,EAAE,GAAG,GACX,OAAO,CAAC,8BAA8B,CAAC,CAiDzC"}
1
+ {"version":3,"file":"simple-context-startup.d.ts","sourceRoot":"","sources":["../../src/test/simple-context-startup.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAU/C,MAAM,WAAW,8BAA8B;IAC9C,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,YAAY,CAAA;IACpB,SAAS,EAAE,GAAG,CAAA;IACd,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC1C;AAED,wBAAgB,kCAAkC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAa1E;AAUD,wBAAsB,4BAA4B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA2BrF;AAiDD,wBAAsB,4BAA4B,CACjD,QAAQ,EAAE,GAAG,GACX,OAAO,CAAC,8BAA8B,CAAC,CAkDzC"}
@@ -1 +1 @@
1
- {"version":3,"file":"simple-context.d.ts","sourceRoot":"","sources":["../../src/test/simple-context.ts"],"names":[],"mappings":"AA2EA;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiH1E;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACvB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACxB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,CAAA;AAEhD,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAA"}
1
+ {"version":3,"file":"simple-context.d.ts","sourceRoot":"","sources":["../../src/test/simple-context.ts"],"names":[],"mappings":"AA2EA;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmI1E;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACvB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACxB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,CAAA;AAEhD,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAA"}
@@ -1,2 +1,2 @@
1
- import { a as devflarePlugin, c as getDevflareConfigs, i as writeGeneratedViteConfig, n as resolveEffectiveViteProject, o as getPluginContext, r as resolveViteUserConfig, s as getCloudflareConfig, t as hasInlineViteConfig } from "../_chunks/vite-De7bGxC6.js";
1
+ import { a as devflarePlugin, c as getDevflareConfigs, i as writeGeneratedViteConfig, n as resolveEffectiveViteProject, o as getPluginContext, r as resolveViteUserConfig, s as getCloudflareConfig, t as hasInlineViteConfig } from "../_chunks/vite-CtvgOi1c.js";
2
2
  export { devflarePlugin as default, devflarePlugin, getCloudflareConfig, getDevflareConfigs, getPluginContext, hasInlineViteConfig, resolveEffectiveViteProject, resolveViteUserConfig, writeGeneratedViteConfig };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devflare",
3
- "version": "1.0.0-next.59",
3
+ "version": "1.0.0-next.60",
4
4
  "description": "Devflare is a developer-first toolkit for Cloudflare Workers that sits on top of Miniflare and Wrangler-compatible config",
5
5
  "repository": {
6
6
  "type": "git",
@@ -84,7 +84,7 @@
84
84
  "test:unit": "bun test tests/unit",
85
85
  "test:coverage": "bun test tests/unit --coverage",
86
86
  "test:integration:control": "bun test tests/integration/cli tests/integration/examples tests/integration/package-entry tests/integration/vite",
87
- "test:integration:bridge": "bun test tests/integration/bridge/bridge-proxy.test.ts --parallel=1 --max-concurrency=1 && bun test tests/integration/bridge/case18-do.test.ts --parallel=1 --max-concurrency=1 && bun test tests/integration/bridge/durable-object.test.ts --parallel=1 --max-concurrency=1 && bun test tests/integration/bridge/do-websocket.test.ts --parallel=1 --max-concurrency=1 && bun test tests/integration/bridge/miniflare.test.ts --parallel=1 --max-concurrency=1 && bun test tests/integration/bridge/r2-transfer.test.ts --parallel=1 --max-concurrency=1",
87
+ "test:integration:bridge": "bun test tests/integration/bridge/bridge-proxy.test.ts --parallel=1 --max-concurrency=1 && bun test tests/integration/bridge/case18-do.test.ts --parallel=1 --max-concurrency=1 && bun test tests/integration/bridge/durable-object.test.ts --parallel=1 --max-concurrency=1 && bun test tests/integration/bridge/do-websocket.test.ts --parallel=1 --max-concurrency=1 && bun test tests/integration/bridge/miniflare.test.ts --parallel=1 --max-concurrency=1 && bun test tests/integration/bridge/r2-transfer.test.ts --parallel=1 --max-concurrency=1 && bun test tests/integration/bridge/r2-presign.test.ts --parallel=1 --max-concurrency=1",
88
88
  "test:integration:test-context": "bun test tests/integration/test-context --parallel=1 --max-concurrency=1",
89
89
  "test:integration:dev-server": "bun test tests/integration/dev-server --parallel=1 --max-concurrency=1",
90
90
  "test:integration:shims": "bun test tests/integration/shims --parallel=1 --max-concurrency=1",
@@ -95,6 +95,7 @@
95
95
  },
96
96
  "dependencies": {
97
97
  "@puppeteer/browsers": "^2.10.3",
98
+ "aws4fetch": "^1.0.20",
98
99
  "c12": "^2.0.1",
99
100
  "chokidar": "^4.0.3",
100
101
  "citty": "^0.1.6",
@@ -1,90 +0,0 @@
1
- import { x as normalizeWorkflowBinding } from "./schema-normalization-Zgm4W6O6.js";
2
- import { i as findFiles, r as DEFAULT_WORKFLOW_PATTERN } from "./glob-CmQOvunB.js";
3
- import { t as bundleWorkerEntry } from "./worker-bundler-dTTnYU3n.js";
4
- import { mkdir, readFile, writeFile } from "node:fs/promises";
5
- import { join, relative, resolve } from "pathe";
6
- //#region src/workflows/local-workflow-entrypoints.ts
7
- function findExportedClasses(code) {
8
- const classes = [];
9
- const classPattern = /export\s+class\s+(\w+)/g;
10
- let match = classPattern.exec(code);
11
- while (match !== null) {
12
- classes.push(match[1]);
13
- match = classPattern.exec(code);
14
- }
15
- return classes;
16
- }
17
- function toImportSpecifier(fromDir, filePath) {
18
- const relativePath = relative(fromDir, filePath).replace(/\\/g, "/");
19
- return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
20
- }
21
- async function discoverWorkflowClasses(config, configDir) {
22
- const classToFilePath = /* @__PURE__ */ new Map();
23
- const workflowPatternConfig = config.files?.workflows;
24
- const workflowPattern = typeof workflowPatternConfig === "string" ? workflowPatternConfig : DEFAULT_WORKFLOW_PATTERN;
25
- if (workflowPatternConfig === false) return classToFilePath;
26
- const files = await findFiles(workflowPattern, { cwd: configDir });
27
- for (const filePath of files) try {
28
- const code = await readFile(filePath, "utf-8");
29
- for (const className of findExportedClasses(code)) classToFilePath.set(className, filePath);
30
- } catch {}
31
- return classToFilePath;
32
- }
33
- async function resolveLocalWorkflowEntrypoints(config, configDir) {
34
- const workflows = config.bindings?.workflows;
35
- if (!workflows || Object.keys(workflows).length === 0) return [];
36
- const classToFilePath = await discoverWorkflowClasses(config, configDir);
37
- const entrypoints = [];
38
- for (const [bindingName, binding] of Object.entries(workflows)) {
39
- const normalized = normalizeWorkflowBinding(binding);
40
- if (normalized.scriptName) continue;
41
- const scriptPath = classToFilePath.get(normalized.className);
42
- if (!scriptPath) throw new Error(`Workflow binding ${bindingName} (className: '${normalized.className}') not found.\nEither set files.workflows to match the workflow source file, or set scriptName when the workflow lives in another worker.`);
43
- entrypoints.push({
44
- bindingName,
45
- className: normalized.className,
46
- scriptPath
47
- });
48
- }
49
- return entrypoints;
50
- }
51
- function buildWorkflowVirtualEntry(entrypoints, entryDir) {
52
- const imports = entrypoints.map((entrypoint, index) => {
53
- const importName = `__DevflareWorkflow${index}`;
54
- const importPath = toImportSpecifier(entryDir, entrypoint.scriptPath);
55
- return {
56
- importName,
57
- className: entrypoint.className,
58
- line: `import { ${entrypoint.className} as ${importName} } from '${importPath}'`
59
- };
60
- });
61
- const exports = imports.map((entrypoint) => {
62
- return `export { ${entrypoint.importName} as ${entrypoint.className} }`;
63
- });
64
- return [
65
- ...imports.map((entrypoint) => entrypoint.line),
66
- "",
67
- ...exports
68
- ].join("\n");
69
- }
70
- async function bundleWorkflowEntrypointScript(config, configDir, options = {}) {
71
- const entrypoints = await resolveLocalWorkflowEntrypoints(config, configDir);
72
- if (entrypoints.length === 0) return "";
73
- const entryDir = resolve(configDir, ".devflare", "workflow-entrypoints");
74
- const entryPath = join(entryDir, "__entry.ts");
75
- const outFile = join(entryDir, "index.js");
76
- await mkdir(entryDir, { recursive: true });
77
- await writeFile(entryPath, buildWorkflowVirtualEntry(entrypoints, entryDir));
78
- await bundleWorkerEntry({
79
- cwd: configDir,
80
- inputFile: entryPath,
81
- outFile,
82
- rolldownOptions: config.rolldown?.options,
83
- sourcemap: config.rolldown?.sourcemap,
84
- minify: config.rolldown?.minify,
85
- logger: options.logger
86
- });
87
- return await readFile(outFile, "utf-8");
88
- }
89
- //#endregion
90
- export { bundleWorkflowEntrypointScript as t };