devflare 1.0.0-next.10 → 1.0.0-next.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LLM.md +683 -7
- package/README.md +27 -1
- package/dist/{build-k36xrzvy.js → build-ezksv2dd.js} +2 -2
- package/dist/config/schema.d.ts +37 -31
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/{deploy-dbvfq8vq.js → deploy-jdpy21t6.js} +2 -2
- package/dist/{dev-rk8p6pse.js → dev-9mq7zhww.js} +9 -9
- package/dist/dev-server/server.d.ts.map +1 -1
- package/dist/{doctor-06y8nxd4.js → doctor-z4ffybce.js} +2 -2
- package/dist/{index-6v3wjg1r.js → index-51s1hkw4.js} +1 -1
- package/dist/{index-jht2j546.js → index-53xcakh8.js} +23 -3
- package/dist/{index-pwgyy2q9.js → index-dr6sbp8d.js} +1 -1
- package/dist/{index-1phx14av.js → index-wyf3s77s.js} +1 -1
- package/dist/{index-05fyzwne.js → index-xqfbd9fx.js} +5 -5
- package/dist/{index-vs49yxn4.js → index-xxwbb2nt.js} +1 -1
- package/dist/src/cli/index.js +1 -1
- package/dist/src/index.js +5 -5
- package/dist/src/sveltekit/index.js +3 -3
- package/dist/src/test/index.js +4 -4
- package/dist/src/vite/index.js +2 -2
- package/dist/test/simple-context.d.ts.map +1 -1
- package/dist/{types-x9q7t491.js → types-nq5acrwh.js} +3 -3
- package/package.json +1 -1
package/LLM.md
CHANGED
|
@@ -64,7 +64,8 @@ The classic mixups are:
|
|
|
64
64
|
|
|
65
65
|
- `files.routes` vs top-level `routes`
|
|
66
66
|
- `vars` vs `secrets`
|
|
67
|
-
- Bun `.env
|
|
67
|
+
- Bun or host `.env*` loading vs runtime secret loading
|
|
68
|
+
- config-time `.env*` files vs local runtime `.dev.vars*` files
|
|
68
69
|
- Devflare `config.env` overrides vs Wrangler environment blocks
|
|
69
70
|
- main-entry `env` vs runtime `env`
|
|
70
71
|
|
|
@@ -110,6 +111,11 @@ Core public capabilities today:
|
|
|
110
111
|
|
|
111
112
|
Devflare is not a replacement runtime. It is a higher-level developer system that sits on top of the Cloudflare ecosystem.
|
|
112
113
|
|
|
114
|
+
The shortest truthful mental model is:
|
|
115
|
+
|
|
116
|
+
- **Vite** is the optional outer app/framework host. Devflare plugs into it only when the current package has a local `vite.config.*`.
|
|
117
|
+
- **Rolldown** is the inner builder Devflare uses when Devflare itself needs to transform Worker source into runnable Worker modules. Today that shows up most clearly in the Durable Object bundler and its watch/rebuild loop.
|
|
118
|
+
|
|
113
119
|
### Authoring model
|
|
114
120
|
|
|
115
121
|
A **surface** is a distinct handler or entry file that Devflare treats as its own concern. The common surfaces are:
|
|
@@ -525,9 +531,234 @@ Secondary keys:
|
|
|
525
531
|
| `limits` | worker limits |
|
|
526
532
|
| `wsRoutes` | local WebSocket proxy rules for dev |
|
|
527
533
|
| `vite` | Devflare Vite metadata |
|
|
528
|
-
| `rolldown` |
|
|
534
|
+
| `rolldown` | Durable Object bundler options |
|
|
529
535
|
| `wrangler.passthrough` | raw Wrangler overrides after compile |
|
|
530
536
|
|
|
537
|
+
### Complete config property reference
|
|
538
|
+
|
|
539
|
+
Treat this as the exhaustive property checklist for `defineConfig({...})`. The later sections explain behavior in narrative form; this section answers “what keys exist right now, what shape do they accept, and what do they control?”
|
|
540
|
+
|
|
541
|
+
#### Root properties
|
|
542
|
+
|
|
543
|
+
| Property | Shape | Required | Current behavior |
|
|
544
|
+
|---|---|---|---|
|
|
545
|
+
| `name` | `string` | yes | Worker name compiled to Wrangler `name`. It is also the base name used for generated auxiliary DO workers (`${name}-do`) when Devflare creates one. |
|
|
546
|
+
| `accountId` | `string` | no | Compiled to Wrangler `account_id`. Most relevant for deploy flows and remote-oriented bindings such as AI and Vectorize. Not currently supported inside `config.env`. |
|
|
547
|
+
| `compatibilityDate` | `string` (`YYYY-MM-DD`) | no | Compiled to Wrangler `compatibility_date`. Defaults to the current date when omitted. |
|
|
548
|
+
| `compatibilityFlags` | `string[]` | no | Additional Workers compatibility flags. Devflare also forces `nodejs_compat` and `nodejs_als`. |
|
|
549
|
+
| `files` | object | no | Explicit surface file paths and discovery globs. Use this when a surface matters to generated output. |
|
|
550
|
+
| `bindings` | object | no | Cloudflare binding declarations. These compile to Wrangler binding sections and also drive generated typing. |
|
|
551
|
+
| `triggers` | object | no | Scheduled trigger configuration such as cron expressions. |
|
|
552
|
+
| `vars` | `Record<string, string>` | no | Non-secret runtime bindings compiled into Wrangler `vars`. |
|
|
553
|
+
| `secrets` | `Record<string, { required?: boolean }>` | no | Secret declarations only. Values do not live here. |
|
|
554
|
+
| `routes` | `Array<{ pattern; zone_name?; zone_id?; custom_domain? }>` | no | Cloudflare deployment routes. This is separate from the built-in file router. |
|
|
555
|
+
| `wsRoutes` | `Array<{ pattern; doNamespace; idParam?; forwardPath? }>` | no | Dev-only WebSocket proxy rules that forward matching upgrade requests to Durable Objects. Not compiled into Wrangler config. |
|
|
556
|
+
| `assets` | `{ directory: string; binding?: string }` | no | Static asset directory config compiled into Wrangler `assets`. |
|
|
557
|
+
| `limits` | `{ cpu_ms?: number }` | no | Worker execution limits compiled into Wrangler `limits`. |
|
|
558
|
+
| `observability` | `{ enabled?: boolean; head_sampling_rate?: number }` | no | Workers observability and sampling config compiled into Wrangler `observability`. |
|
|
559
|
+
| `migrations` | `Migration[]` | no | Durable Object migration history compiled into Wrangler `migrations`. |
|
|
560
|
+
| `rolldown` | object | no | Rolldown builder configuration for Devflare's own code-transformation path, currently focused on Durable Object workers. This is not a replacement for `vite.config.*`. |
|
|
561
|
+
| `vite` | object | no | Devflare-owned Vite metadata namespace. Raw Vite server/build/resolve config still belongs in local `vite.config.*`. |
|
|
562
|
+
| `env` | `Record<string, EnvOverride>` | no | Named environment overlays merged into the base config before compile/build/deploy. |
|
|
563
|
+
| `wrangler` | `{ passthrough?: Record<string, unknown> }` | no | Escape hatch for unsupported Wrangler keys, merged after native Devflare compile. |
|
|
564
|
+
| `build` | object | legacy | Deprecated alias normalized into `rolldown`. Keep accepting it for compatibility; teach `rolldown` in new docs. |
|
|
565
|
+
| `plugins` | `unknown[]` | legacy | Deprecated alias normalized into `vite.plugins`. Raw Vite plugin wiring still belongs in `vite.config.*`. |
|
|
566
|
+
|
|
567
|
+
#### `files`
|
|
568
|
+
|
|
569
|
+
`files` is where Devflare discovers or pins the files that make up your worker surfaces.
|
|
570
|
+
|
|
571
|
+
| Key | Shape | Default or convention | Meaning |
|
|
572
|
+
|---|---|---|---|
|
|
573
|
+
| `fetch` | `string \| false` | `src/fetch.ts` when present | Main HTTP entry. Keep this explicit when build or deploy output depends on it. |
|
|
574
|
+
| `queue` | `string \| false` | `src/queue.ts` when present | Queue consumer surface. |
|
|
575
|
+
| `scheduled` | `string \| false` | `src/scheduled.ts` when present | Scheduled/cron surface. |
|
|
576
|
+
| `email` | `string \| false` | `src/email.ts` when present | Inbound email surface. |
|
|
577
|
+
| `durableObjects` | `string \| false` | `**/do.*.{ts,js}` | Discovery glob for Durable Object classes. Respects `.gitignore`. |
|
|
578
|
+
| `entrypoints` | `string \| false` | `**/ep.*.{ts,js}` | Discovery glob for `WorkerEntrypoint` classes. Respects `.gitignore`. |
|
|
579
|
+
| `workflows` | `string \| false` | `**/wf.*.{ts,js}` | Discovery glob for workflow classes. Respects `.gitignore`. |
|
|
580
|
+
| `routes` | `{ dir: string; prefix?: string } \| false` | `src/routes` when that directory exists | Built-in route-tree config. `dir` changes the route root; `prefix` mounts it under a static pathname prefix such as `/api`; `false` disables route discovery. |
|
|
581
|
+
| `transport` | `string \| null` | `src/transport.{ts,js,mts,mjs}` when present | Custom serialization transport file. The file must export a named `transport` object. Set `null` to disable autodiscovery explicitly. |
|
|
582
|
+
|
|
583
|
+
Current `files` rules worth keeping explicit:
|
|
584
|
+
|
|
585
|
+
- `compileConfig()` only writes Wrangler `main` when `files.fetch` is explicit
|
|
586
|
+
- higher-level `build`, `deploy`, and `devflare/vite` flows may still generate a composed `.devflare/worker-entrypoints/main.ts` when multiple surfaces must be stitched together
|
|
587
|
+
- `wrangler.passthrough.main` opts out of that composed-entry generation path
|
|
588
|
+
- `createTestContext()` and local dev can still auto-discover conventional files even when you omit them from config
|
|
589
|
+
|
|
590
|
+
#### `bindings`
|
|
591
|
+
|
|
592
|
+
`bindings` groups Cloudflare service bindings by kind.
|
|
593
|
+
|
|
594
|
+
| Key | Shape | Meaning |
|
|
595
|
+
|---|---|---|
|
|
596
|
+
| `kv` | `Record<string, string>` | KV namespace binding name → namespace id |
|
|
597
|
+
| `d1` | `Record<string, string>` | D1 binding name → database id |
|
|
598
|
+
| `r2` | `Record<string, string>` | R2 binding name → bucket name |
|
|
599
|
+
| `durableObjects` | `Record<string, string \| { className: string; scriptName?: string }>` | Durable Object namespace binding. String form is shorthand for `{ className }`. Object form also covers cross-worker DOs and `ref()`-driven bindings. |
|
|
600
|
+
| `queues` | `{ producers?: Record<string, string>; consumers?: QueueConsumer[] }` | Queue producer bindings plus consumer settings |
|
|
601
|
+
| `services` | `Record<string, { service: string; environment?: string; entrypoint?: string }>` | Worker service bindings. `ref().worker` and `ref().worker('Entrypoint')` normalize here. |
|
|
602
|
+
| `ai` | `{ binding: string }` | Workers AI binding |
|
|
603
|
+
| `vectorize` | `Record<string, { indexName: string }>` | Vectorize index bindings |
|
|
604
|
+
| `hyperdrive` | `Record<string, { id: string }>` | Hyperdrive bindings |
|
|
605
|
+
| `browser` | `{ binding: string }` | Browser Rendering binding |
|
|
606
|
+
| `analyticsEngine` | `Record<string, { dataset: string }>` | Analytics Engine dataset bindings |
|
|
607
|
+
| `sendEmail` | `Record<string, { destinationAddress?: string; allowedDestinationAddresses?: string[]; allowedSenderAddresses?: string[] }>` | Outbound email bindings |
|
|
608
|
+
|
|
609
|
+
Queue consumer objects currently support:
|
|
610
|
+
|
|
611
|
+
| Field | Shape | Meaning |
|
|
612
|
+
|---|---|---|
|
|
613
|
+
| `queue` | `string` | Queue name to consume |
|
|
614
|
+
| `maxBatchSize` | `number` | Max messages per batch |
|
|
615
|
+
| `maxBatchTimeout` | `number` | Max seconds to wait for a batch |
|
|
616
|
+
| `maxRetries` | `number` | Max retry attempts |
|
|
617
|
+
| `deadLetterQueue` | `string` | Queue for permanently failed messages |
|
|
618
|
+
| `maxConcurrency` | `number` | Max concurrent batch invocations |
|
|
619
|
+
| `retryDelay` | `number` | Delay between retries in seconds |
|
|
620
|
+
|
|
621
|
+
Two `bindings` details that matter in practice:
|
|
622
|
+
|
|
623
|
+
- `bindings.sendEmail` must use either `destinationAddress` or `allowedDestinationAddresses`, not both
|
|
624
|
+
- `bindings.durableObjects.*.scriptName` is how you point a binding at another worker when the class does not live in the main worker bundle
|
|
625
|
+
|
|
626
|
+
#### `triggers`, `routes`, and `wsRoutes`
|
|
627
|
+
|
|
628
|
+
| Property | Shape | Current behavior |
|
|
629
|
+
|---|---|---|
|
|
630
|
+
| `triggers.crons` | `string[]` | Cloudflare cron expressions compiled into Wrangler `triggers.crons` |
|
|
631
|
+
| `routes[].pattern` | `string` | Deployment route pattern such as `example.com/*` |
|
|
632
|
+
| `routes[].zone_name` | `string` | Optional zone association |
|
|
633
|
+
| `routes[].zone_id` | `string` | Optional zone association alternative to `zone_name` |
|
|
634
|
+
| `routes[].custom_domain` | `boolean` | Mark route as a custom domain |
|
|
635
|
+
| `wsRoutes[].pattern` | `string` | Local URL pattern to intercept for WebSocket upgrades |
|
|
636
|
+
| `wsRoutes[].doNamespace` | `string` | Target Durable Object namespace binding name |
|
|
637
|
+
| `wsRoutes[].idParam` | `string` | Query parameter used to pick the DO instance. Defaults to `'id'`. |
|
|
638
|
+
| `wsRoutes[].forwardPath` | `string` | Path forwarded inside the DO. Defaults to `'/websocket'`. |
|
|
639
|
+
|
|
640
|
+
Remember the split:
|
|
641
|
+
|
|
642
|
+
- `files.routes` is app routing
|
|
643
|
+
- top-level `routes` is Cloudflare deployment routing
|
|
644
|
+
- `wsRoutes` is local dev-time WebSocket proxy routing for Durable Objects
|
|
645
|
+
|
|
646
|
+
#### `vars` and `secrets`
|
|
647
|
+
|
|
648
|
+
| Property | Shape | Current behavior |
|
|
649
|
+
|---|---|---|
|
|
650
|
+
| `vars` | `Record<string, string>` | Non-secret runtime bindings compiled into Wrangler `vars` |
|
|
651
|
+
| `secrets` | `Record<string, { required?: boolean }>` | Secret declarations only. `required` defaults to `true`. Values must come from Cloudflare secrets, tests, or upstream local tooling. |
|
|
652
|
+
|
|
653
|
+
#### `assets`, `limits`, and `observability`
|
|
654
|
+
|
|
655
|
+
| Property | Shape | Current behavior |
|
|
656
|
+
|---|---|---|
|
|
657
|
+
| `assets.directory` | `string` | Required asset directory path |
|
|
658
|
+
| `assets.binding` | `string` | Optional asset binding name for programmatic access |
|
|
659
|
+
| `limits.cpu_ms` | `number` | Optional CPU limit for unbound workers |
|
|
660
|
+
| `observability.enabled` | `boolean` | Enable Worker Logs |
|
|
661
|
+
| `observability.head_sampling_rate` | `number` | Log sampling rate from `0` to `1` |
|
|
662
|
+
|
|
663
|
+
#### `migrations`
|
|
664
|
+
|
|
665
|
+
Each migration object has this shape:
|
|
666
|
+
|
|
667
|
+
| Field | Shape | Meaning |
|
|
668
|
+
|---|---|---|
|
|
669
|
+
| `tag` | `string` | Required migration version label |
|
|
670
|
+
| `new_classes` | `string[]` | Newly introduced DO classes |
|
|
671
|
+
| `renamed_classes` | `Array<{ from: string; to: string }>` | DO class renames with state preservation |
|
|
672
|
+
| `deleted_classes` | `string[]` | Deleted DO classes |
|
|
673
|
+
| `new_sqlite_classes` | `string[]` | DO classes migrating to SQLite storage |
|
|
674
|
+
|
|
675
|
+
#### `rolldown`
|
|
676
|
+
|
|
677
|
+
`rolldown` config applies to Devflare's Durable Object bundler.
|
|
678
|
+
|
|
679
|
+
| Key | Shape | Current behavior |
|
|
680
|
+
|---|---|---|
|
|
681
|
+
| `target` | `string` | Bundle target for emitted DO bundles |
|
|
682
|
+
| `minify` | `boolean` | Minify DO bundles |
|
|
683
|
+
| `sourcemap` | `boolean` | Emit source maps for DO bundles |
|
|
684
|
+
| `options` | `DevflareRolldownOptions` | Additional Rolldown input/output options and plugins, minus Devflare-owned fields |
|
|
685
|
+
|
|
686
|
+
Current `rolldown.options` ownership rules:
|
|
687
|
+
|
|
688
|
+
- Devflare owns `cwd`, `input`, `platform`, and `watch`
|
|
689
|
+
- Devflare also owns output `codeSplitting`, `dir`, `file`, `format`, and `inlineDynamicImports`
|
|
690
|
+
- output stays single-file ESM so the local DO bundling story remains worker-friendly
|
|
691
|
+
- `rolldown.options.plugins` is the intended extension point for custom transforms and Rollup-compatible plugins
|
|
692
|
+
|
|
693
|
+
#### `vite`
|
|
694
|
+
|
|
695
|
+
`vite` is the Devflare-side Vite metadata namespace, not the place for raw Vite app config.
|
|
696
|
+
|
|
697
|
+
| Key | Shape | Current behavior |
|
|
698
|
+
|---|---|---|
|
|
699
|
+
| `plugins` | `unknown[]` | Accepted by the schema and normalized from the legacy top-level `plugins` alias |
|
|
700
|
+
| any other key | `unknown` | Preserved by the schema as Devflare-level Vite metadata, but raw Vite server/build/resolve/plugin wiring still belongs in local `vite.config.*` |
|
|
701
|
+
|
|
702
|
+
That distinction is intentional:
|
|
703
|
+
|
|
704
|
+
- put real Vite config in `vite.config.ts`
|
|
705
|
+
- use `devflare/vite` helpers when Devflare needs to participate in the Vite pipeline
|
|
706
|
+
- treat `config.vite` as Devflare-owned metadata, not as a drop-in replacement for Vite's own config file
|
|
707
|
+
|
|
708
|
+
#### `env`
|
|
709
|
+
|
|
710
|
+
`env` is `Record<string, EnvOverride>`, where each environment can currently override these keys:
|
|
711
|
+
|
|
712
|
+
- `name`
|
|
713
|
+
- `compatibilityDate`
|
|
714
|
+
- `compatibilityFlags`
|
|
715
|
+
- `files`
|
|
716
|
+
- `bindings`
|
|
717
|
+
- `triggers`
|
|
718
|
+
- `vars`
|
|
719
|
+
- `secrets`
|
|
720
|
+
- `routes`
|
|
721
|
+
- `assets`
|
|
722
|
+
- `limits`
|
|
723
|
+
- `observability`
|
|
724
|
+
- `migrations`
|
|
725
|
+
- `rolldown`
|
|
726
|
+
- `vite`
|
|
727
|
+
- `wrangler`
|
|
728
|
+
- deprecated `build`
|
|
729
|
+
- deprecated `plugins`
|
|
730
|
+
|
|
731
|
+
Current exclusions still matter:
|
|
732
|
+
|
|
733
|
+
- `accountId` is not supported inside `env`
|
|
734
|
+
- `wsRoutes` is not supported inside `env`
|
|
735
|
+
- nested `env` blocks are not part of the override shape
|
|
736
|
+
|
|
737
|
+
Merge behavior is also part of the contract:
|
|
738
|
+
|
|
739
|
+
- scalars override base values
|
|
740
|
+
- nested objects merge
|
|
741
|
+
- arrays append instead of replacing
|
|
742
|
+
- `null` and `undefined` do not delete inherited values
|
|
743
|
+
|
|
744
|
+
#### `wrangler`
|
|
745
|
+
|
|
746
|
+
`wrangler` currently exposes one native child key:
|
|
747
|
+
|
|
748
|
+
| Key | Shape | Current behavior |
|
|
749
|
+
|---|---|---|
|
|
750
|
+
| `passthrough` | `Record<string, unknown>` | Shallow-merged on top of the compiled Wrangler config. Use this for unsupported Wrangler keys or to take full ownership of `main`. |
|
|
751
|
+
|
|
752
|
+
#### Deprecated aliases
|
|
753
|
+
|
|
754
|
+
| Legacy key | Current canonical key | Notes |
|
|
755
|
+
|---|---|---|
|
|
756
|
+
| `build.target` | `rolldown.target` | Deprecated but still normalized |
|
|
757
|
+
| `build.minify` | `rolldown.minify` | Deprecated but still normalized |
|
|
758
|
+
| `build.sourcemap` | `rolldown.sourcemap` | Deprecated but still normalized |
|
|
759
|
+
| `build.rolldownOptions` | `rolldown.options` | Deprecated but still normalized |
|
|
760
|
+
| `plugins` | `vite.plugins` | Deprecated top-level alias; raw Vite plugin wiring still belongs in `vite.config.*` |
|
|
761
|
+
|
|
531
762
|
### Native config coverage vs `wrangler.passthrough`
|
|
532
763
|
|
|
533
764
|
Devflare natively models the common Worker config it actively composes around. It does **not** try to mirror every Wrangler field one-by-one as a first-class Devflare schema key.
|
|
@@ -579,7 +810,7 @@ Two practical rules:
|
|
|
579
810
|
| `entrypoints` | <code>string | false</code> | `**/ep.*.{ts,js}` | WorkerEntrypoint discovery glob |
|
|
580
811
|
| `workflows` | <code>string | false</code> | `**/wf.*.{ts,js}` | workflow discovery glob |
|
|
581
812
|
| `routes` | <code>{ dir, prefix? } | false</code> | `src/routes` when that directory exists | built-in file router configuration |
|
|
582
|
-
| `transport` |
|
|
813
|
+
| `transport` | <code>string | null</code> | `src/transport.{ts,js,mts,mjs}` when one of those files exists | custom transport definition file |
|
|
583
814
|
|
|
584
815
|
Discovery does not behave identically in every subsystem:
|
|
585
816
|
|
|
@@ -615,25 +846,48 @@ export default defineConfig({
|
|
|
615
846
|
})
|
|
616
847
|
```
|
|
617
848
|
|
|
618
|
-
`files.transport` is
|
|
849
|
+
`files.transport` is convention-first. `createTestContext()` auto-loads `src/transport.{ts,js,mts,mjs}` when present, a string value points at a different transport file, and `files.transport: null` disables transport loading explicitly. The file must export a named `transport` object.
|
|
619
850
|
|
|
620
851
|
There is no public `files.tail` config key today.
|
|
621
852
|
|
|
622
|
-
### `.env`, `vars`, `secrets`, and `config.env`
|
|
853
|
+
### `.env`, `.dev.vars`, `vars`, `secrets`, and `config.env`
|
|
623
854
|
|
|
624
855
|
Keep these layers separate:
|
|
625
856
|
|
|
626
857
|
| Layer | Holds values? | Compiled into generated config? | Use it for |
|
|
627
858
|
|---|---|---|---|
|
|
628
859
|
| `.env` / `process.env` | yes | indirectly, only when your config reads from it | local process-time inputs |
|
|
860
|
+
| `.env.dev` / `.env.<name>` | tool/runtime-dependent | indirectly at most, only if the surrounding tool has already populated `process.env` | local process-time variants, not a Devflare-native contract |
|
|
861
|
+
| `.dev.vars` / `.dev.vars.<name>` | yes | no | local runtime secret/value files in upstream Cloudflare tooling when applicable |
|
|
629
862
|
| `vars` | yes | yes | non-secret string bindings |
|
|
630
863
|
| `secrets` | no, declaration only | no | required/optional runtime secret bindings |
|
|
631
864
|
| `config.env` | yes, as config overlays | yes after merge | environment-specific config overrides |
|
|
632
865
|
|
|
633
|
-
#### `.env
|
|
866
|
+
#### `.env`, `.env.dev`, and process env
|
|
634
867
|
|
|
635
868
|
`loadConfig()` does not do dotenv loading by itself. The Devflare CLI runs under Bun, and Bun may auto-load `.env` files into `process.env`.
|
|
636
869
|
|
|
870
|
+
Important boundary:
|
|
871
|
+
|
|
872
|
+
- Devflare sets `dotenv: false` in its config loader
|
|
873
|
+
- Devflare does **not** define special first-class semantics for `.env.dev` or `.env.<name>`
|
|
874
|
+
- if those files affect `process.env`, that comes from the surrounding host tool/runtime rather than a Devflare-native loader
|
|
875
|
+
- config-time/build-time code can still read `process.env` inside `defineConfig()` or other Node-side tooling
|
|
876
|
+
|
|
877
|
+
Treat `.env*` files as **config/build-time inputs**, not as Devflare's runtime secret system.
|
|
878
|
+
|
|
879
|
+
#### `.dev.vars` and local runtime secrets
|
|
880
|
+
|
|
881
|
+
Devflare does **not** currently implement its own first-class `.dev.vars` / `.dev.vars.<name>` loader for worker-only dev mode or `createTestContext()`.
|
|
882
|
+
|
|
883
|
+
That means:
|
|
884
|
+
|
|
885
|
+
- do not document `.dev.vars*` as a guaranteed Devflare-native feature across all modes
|
|
886
|
+
- `secrets` declares the names of expected runtime secrets, but does not provide values
|
|
887
|
+
- worker-only dev and `createTestContext()` should not be described as automatically materializing secret values from `.dev.vars*`
|
|
888
|
+
|
|
889
|
+
In Vite-backed flows, some local runtime variable behavior may come from upstream Cloudflare/Vite tooling rather than from Devflare itself. Document that as inherited upstream behavior, not as a unified Devflare contract.
|
|
890
|
+
|
|
637
891
|
#### `vars`
|
|
638
892
|
|
|
639
893
|
Use `vars` for non-secret runtime values that can safely appear in generated config, such as public URLs, modes, IDs, and feature flags.
|
|
@@ -664,6 +918,135 @@ secrets: {
|
|
|
664
918
|
|
|
665
919
|
means “`API_KEY` is a required runtime secret,” not “optional secret with no requirements.”
|
|
666
920
|
|
|
921
|
+
In practice, secret **values** come from outside Devflare config:
|
|
922
|
+
|
|
923
|
+
- Cloudflare-stored runtime secrets in deployed environments
|
|
924
|
+
- explicit test injection or lower-level mocks in tests
|
|
925
|
+
- upstream local-dev tooling when you intentionally rely on it
|
|
926
|
+
|
|
927
|
+
Do not describe `secrets` as a place that stores values.
|
|
928
|
+
|
|
929
|
+
#### Example files such as `.env.example` and `.dev.vars.example`
|
|
930
|
+
|
|
931
|
+
Example files are a **team convention**, not a Devflare feature.
|
|
932
|
+
|
|
933
|
+
Current truthful guidance:
|
|
934
|
+
|
|
935
|
+
- use `.env.example` to document required config-time/build-time variables that your config or Node-side tooling reads from `process.env`
|
|
936
|
+
- use `.dev.vars.example` to document expected local runtime secret names **if your project chooses to rely on upstream `.dev.vars` workflows**
|
|
937
|
+
- keep example files committed with placeholder or fake values only
|
|
938
|
+
- do not claim that Devflare auto-generates, auto-loads, or validates these example files today
|
|
939
|
+
|
|
940
|
+
#### Canonical env and secrets layout
|
|
941
|
+
|
|
942
|
+
If you want the lowest-confusion setup, use this split:
|
|
943
|
+
|
|
944
|
+
- `.env.example` documents config-time/build-time inputs
|
|
945
|
+
- `.dev.vars.example` documents local runtime secret names **only if your project intentionally relies on upstream `.dev.vars` workflows**
|
|
946
|
+
- `devflare.config.ts` reads config-time values from `process.env`, puts safe runtime values in `vars`, and declares required runtime secret names in `secrets`
|
|
947
|
+
- deployed secret values live in Cloudflare, not in your repo
|
|
948
|
+
|
|
949
|
+
Recommended project shape:
|
|
950
|
+
|
|
951
|
+
```text
|
|
952
|
+
my-worker/
|
|
953
|
+
├─ .env.example
|
|
954
|
+
├─ .dev.vars.example # optional; only if you intentionally use upstream .dev.vars flows
|
|
955
|
+
├─ .gitignore
|
|
956
|
+
├─ devflare.config.ts
|
|
957
|
+
└─ src/
|
|
958
|
+
└─ fetch.ts
|
|
959
|
+
```
|
|
960
|
+
|
|
961
|
+
Example `.env.example`:
|
|
962
|
+
|
|
963
|
+
```dotenv
|
|
964
|
+
WORKER_NAME=my-worker
|
|
965
|
+
API_ORIGIN=http://localhost:3000
|
|
966
|
+
```
|
|
967
|
+
|
|
968
|
+
Example `.dev.vars.example`:
|
|
969
|
+
|
|
970
|
+
```dotenv
|
|
971
|
+
API_KEY=replace-me
|
|
972
|
+
SESSION_SECRET=replace-me
|
|
973
|
+
```
|
|
974
|
+
|
|
975
|
+
Typical git ignore pattern for user projects:
|
|
976
|
+
|
|
977
|
+
```gitignore
|
|
978
|
+
.env
|
|
979
|
+
.env.*
|
|
980
|
+
!.env.example
|
|
981
|
+
.dev.vars
|
|
982
|
+
.dev.vars.*
|
|
983
|
+
!.dev.vars.example
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
Example `devflare.config.ts`:
|
|
987
|
+
|
|
988
|
+
```ts
|
|
989
|
+
import { defineConfig } from 'devflare'
|
|
990
|
+
|
|
991
|
+
export default defineConfig({
|
|
992
|
+
name: process.env.WORKER_NAME ?? 'my-worker',
|
|
993
|
+
compatibilityDate: '2026-03-17',
|
|
994
|
+
files: {
|
|
995
|
+
fetch: 'src/fetch.ts'
|
|
996
|
+
},
|
|
997
|
+
vars: {
|
|
998
|
+
API_ORIGIN: process.env.API_ORIGIN ?? 'http://localhost:3000'
|
|
999
|
+
},
|
|
1000
|
+
secrets: {
|
|
1001
|
+
API_KEY: {},
|
|
1002
|
+
SESSION_SECRET: {}
|
|
1003
|
+
},
|
|
1004
|
+
env: {
|
|
1005
|
+
production: {
|
|
1006
|
+
vars: {
|
|
1007
|
+
API_ORIGIN: 'https://api.example.com'
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
})
|
|
1012
|
+
```
|
|
1013
|
+
|
|
1014
|
+
Example `src/fetch.ts`:
|
|
1015
|
+
|
|
1016
|
+
```ts
|
|
1017
|
+
import type { FetchEvent } from 'devflare/runtime'
|
|
1018
|
+
|
|
1019
|
+
export async function GET({ env }: FetchEvent<DevflareEnv>): Promise<Response> {
|
|
1020
|
+
return Response.json({
|
|
1021
|
+
origin: env.API_ORIGIN,
|
|
1022
|
+
hasApiKey: Boolean(env.API_KEY),
|
|
1023
|
+
hasSessionSecret: Boolean(env.SESSION_SECRET)
|
|
1024
|
+
})
|
|
1025
|
+
}
|
|
1026
|
+
```
|
|
1027
|
+
|
|
1028
|
+
Deployed runtime secrets should be created with Cloudflare/Wrangler tooling, not committed to config files or example files.
|
|
1029
|
+
|
|
1030
|
+
Typical deployed secret flow:
|
|
1031
|
+
|
|
1032
|
+
```bash
|
|
1033
|
+
bunx --bun wrangler secret put API_KEY
|
|
1034
|
+
bunx --bun wrangler secret put SESSION_SECRET
|
|
1035
|
+
```
|
|
1036
|
+
|
|
1037
|
+
If you use named Cloudflare environments, set the secret in that environment explicitly:
|
|
1038
|
+
|
|
1039
|
+
```bash
|
|
1040
|
+
bunx --bun wrangler secret put API_KEY --env production
|
|
1041
|
+
bunx --bun wrangler secret put SESSION_SECRET --env production
|
|
1042
|
+
```
|
|
1043
|
+
|
|
1044
|
+
Practical rule of thumb:
|
|
1045
|
+
|
|
1046
|
+
- if a value is needed while evaluating config, put it in the `.env*` / `process.env` bucket
|
|
1047
|
+
- if a value should exist as a runtime binding but must not be committed, declare it in `secrets`
|
|
1048
|
+
- if a project wants local runtime secret files, treat `.dev.vars*` as an upstream convention and document it explicitly per project
|
|
1049
|
+
|
|
667
1050
|
#### `devflare types`
|
|
668
1051
|
|
|
669
1052
|
`devflare types` generates `env.d.ts` from the resolved config plus discovered surfaces. The stable public result is typed `DevflareEnv` coverage for bindings such as `vars`, `secrets`, services, Durable Objects, and discovered entrypoints.
|
|
@@ -937,6 +1320,21 @@ Advanced members such as `.name`, `.config`, `.configPath`, and `.resolve()` are
|
|
|
937
1320
|
|
|
938
1321
|
## Development workflows
|
|
939
1322
|
|
|
1323
|
+
### Vite vs Rolldown: the truthful mental model
|
|
1324
|
+
|
|
1325
|
+
They are both important, but they are not two names for the same job.
|
|
1326
|
+
|
|
1327
|
+
| Tool | Role inside Devflare | When it matters most | What it is not |
|
|
1328
|
+
|---|---|---|---|
|
|
1329
|
+
| `Vite` | the optional outer dev/build host for packages that are already Vite apps or frameworks; Devflare plugs generated Worker config, config watching, auxiliary DO workers, and bridge behavior into that pipeline | packages with a local `vite.config.*`, SvelteKit, frontend HMR | not Devflare's own Worker bundler |
|
|
1330
|
+
| `Rolldown` | the inner code-transforming builder Devflare uses when Devflare itself bundles Worker code | Durable Object bundles, watch/rebuild, worker-side plugin transforms such as `.svelte` imported by a DO module | not the main app's Vite build |
|
|
1331
|
+
|
|
1332
|
+
Three practical consequences fall straight out of the implementation:
|
|
1333
|
+
|
|
1334
|
+
- remove `vite.config.*`, and Devflare drops back to worker-only mode instead of starting Vite
|
|
1335
|
+
- import `.svelte` from a Durable Object, and the compilation belongs to `rolldown.options.plugins`, not to the main Vite plugin chain
|
|
1336
|
+
- generated `.devflare/worker-entrypoints/main.ts` is separate glue code produced by Devflare when it needs to compose fetch, queue, scheduled, email, or route-tree surfaces into one Worker entry
|
|
1337
|
+
|
|
940
1338
|
### Operational decision rules
|
|
941
1339
|
|
|
942
1340
|
Use these rules in order:
|
|
@@ -948,6 +1346,278 @@ Use these rules in order:
|
|
|
948
1346
|
5. treat `.devflare/*`, `env.d.ts`, and generated Wrangler config as outputs, not authoring inputs
|
|
949
1347
|
6. remote mode is mainly for remote-oriented services such as AI and Vectorize, not a blanket “make everything remote” switch
|
|
950
1348
|
|
|
1349
|
+
### Vite-backed workflows
|
|
1350
|
+
|
|
1351
|
+
A package enters Vite-backed mode when it has a local `vite.config.*`. In that mode, Vite is the outer application pipeline: it owns the package's dev server and app build, while Devflare injects Worker-aware config, generated Wrangler output, auxiliary DO worker config, and bridge behavior into that Vite stack.
|
|
1352
|
+
|
|
1353
|
+
Current Vite-backed flow:
|
|
1354
|
+
|
|
1355
|
+
1. Devflare loads and validates `devflare.config.*`
|
|
1356
|
+
2. `devflarePlugin()` compiles that config into a generated `.devflare/wrangler.jsonc`
|
|
1357
|
+
3. Devflare may generate `.devflare/worker-entrypoints/main.ts` when multiple surfaces must be composed into one Worker entry
|
|
1358
|
+
4. if Durable Object files are discovered, Devflare builds an auxiliary DO worker config for Vite / Cloudflare interop
|
|
1359
|
+
5. in serve mode, Devflare watches the resolved Devflare config file and triggers a full reload when it changes
|
|
1360
|
+
6. if `wsRoutes` are configured, Devflare can proxy matching WebSocket upgrade paths to the Miniflare bridge
|
|
1361
|
+
7. on build, Devflare runs `bunx vite build` only after it has prepared the Worker config for that package
|
|
1362
|
+
|
|
1363
|
+
Two ownership rules matter here:
|
|
1364
|
+
|
|
1365
|
+
- setting `wrangler.passthrough.main` tells Devflare to preserve your explicit Worker `main` instead of generating a composed one
|
|
1366
|
+
- no local `vite.config.*` means none of this Vite-specific behavior runs; the package stays in worker-only mode
|
|
1367
|
+
|
|
1368
|
+
#### `devflare/vite` helpers
|
|
1369
|
+
|
|
1370
|
+
| Helper | Use it for | Timing |
|
|
1371
|
+
|---|---|---|
|
|
1372
|
+
| `devflarePlugin(options)` | generated `.devflare/wrangler.jsonc`, config watching, DO discovery, DO transforms, and WebSocket proxy wiring | include it in `vite.config.*` plugins |
|
|
1373
|
+
| `getCloudflareConfig(options)` | compiled programmatic config for `cloudflare({ config })` | call during Vite config creation |
|
|
1374
|
+
| `getDevflareConfigs(options)` | compiled config plus `auxiliaryWorkers` array for DO workers | call during Vite config creation |
|
|
1375
|
+
| `getPluginContext()` | read resolved plugin state such as `wranglerConfig`, `cloudflareConfig`, discovered DOs, and `projectRoot` | advanced use only, after Vite has resolved config |
|
|
1376
|
+
|
|
1377
|
+
`devflarePlugin(options)` currently supports these options:
|
|
1378
|
+
|
|
1379
|
+
| Option | Default | What it changes |
|
|
1380
|
+
|---|---|---|
|
|
1381
|
+
| `configPath` | auto-resolve local supported config | point Vite at a specific `devflare.config.*` file |
|
|
1382
|
+
| `environment` | no explicit override | resolve `config.env[name]` before compilation |
|
|
1383
|
+
| `doTransforms` | `true` | enable or disable Devflare's DO code transforms |
|
|
1384
|
+
| `watchConfig` | `true` | watch the resolved config file and full-reload on change |
|
|
1385
|
+
| `bridgePort` | `process.env.DEVFLARE_BRIDGE_PORT`, then `8787` when proxying | choose the Miniflare bridge port for WebSocket proxying |
|
|
1386
|
+
| `wsProxyPatterns` | `[]` | add extra WebSocket proxy patterns beyond configured `wsRoutes` |
|
|
1387
|
+
|
|
1388
|
+
Timing rule of thumb:
|
|
1389
|
+
|
|
1390
|
+
- if you need config while building the Vite config object, use `getCloudflareConfig()` or `getDevflareConfigs()`
|
|
1391
|
+
- if another Vite plugin needs to inspect the already-resolved Devflare state, `getPluginContext()` is the advanced hook
|
|
1392
|
+
|
|
1393
|
+
#### Minimal Vite wiring
|
|
1394
|
+
|
|
1395
|
+
```ts
|
|
1396
|
+
import { defineConfig } from 'vite'
|
|
1397
|
+
import { devflarePlugin } from 'devflare/vite'
|
|
1398
|
+
|
|
1399
|
+
export default defineConfig({
|
|
1400
|
+
plugins: [devflarePlugin()]
|
|
1401
|
+
})
|
|
1402
|
+
```
|
|
1403
|
+
|
|
1404
|
+
#### Explicit `@cloudflare/vite-plugin` wiring
|
|
1405
|
+
|
|
1406
|
+
```ts
|
|
1407
|
+
import { defineConfig } from 'vite'
|
|
1408
|
+
import { cloudflare } from '@cloudflare/vite-plugin'
|
|
1409
|
+
import { devflarePlugin, getDevflareConfigs } from 'devflare/vite'
|
|
1410
|
+
|
|
1411
|
+
export default defineConfig(async () => {
|
|
1412
|
+
const { cloudflareConfig, auxiliaryWorkers } = await getDevflareConfigs()
|
|
1413
|
+
|
|
1414
|
+
return {
|
|
1415
|
+
plugins: [
|
|
1416
|
+
devflarePlugin(),
|
|
1417
|
+
cloudflare({
|
|
1418
|
+
config: cloudflareConfig,
|
|
1419
|
+
auxiliaryWorkers: auxiliaryWorkers.length > 0 ? auxiliaryWorkers : undefined
|
|
1420
|
+
})
|
|
1421
|
+
]
|
|
1422
|
+
}
|
|
1423
|
+
})
|
|
1424
|
+
```
|
|
1425
|
+
|
|
1426
|
+
That is the current high-signal pattern when you want Vite to stay the package's app/build host while Devflare owns Worker config compilation and Durable Object discovery.
|
|
1427
|
+
|
|
1428
|
+
#### SvelteKit-backed Worker example
|
|
1429
|
+
|
|
1430
|
+
```ts
|
|
1431
|
+
// devflare.config.ts
|
|
1432
|
+
import { defineConfig } from 'devflare'
|
|
1433
|
+
|
|
1434
|
+
export default defineConfig({
|
|
1435
|
+
name: 'notes-app',
|
|
1436
|
+
files: {
|
|
1437
|
+
fetch: '.svelte-kit/cloudflare/_worker.js',
|
|
1438
|
+
durableObjects: 'src/do/**/*.ts',
|
|
1439
|
+
transport: 'src/transport.ts'
|
|
1440
|
+
},
|
|
1441
|
+
bindings: {
|
|
1442
|
+
durableObjects: {
|
|
1443
|
+
CHAT_ROOM: 'ChatRoom'
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
})
|
|
1447
|
+
```
|
|
1448
|
+
|
|
1449
|
+
```ts
|
|
1450
|
+
// vite.config.ts
|
|
1451
|
+
import { defineConfig } from 'vite'
|
|
1452
|
+
import { sveltekit } from '@sveltejs/kit/vite'
|
|
1453
|
+
import { devflarePlugin } from 'devflare/vite'
|
|
1454
|
+
|
|
1455
|
+
export default defineConfig({
|
|
1456
|
+
plugins: [
|
|
1457
|
+
devflarePlugin(),
|
|
1458
|
+
sveltekit()
|
|
1459
|
+
]
|
|
1460
|
+
})
|
|
1461
|
+
```
|
|
1462
|
+
|
|
1463
|
+
```ts
|
|
1464
|
+
// src/hooks.server.ts
|
|
1465
|
+
export { handle } from 'devflare/sveltekit'
|
|
1466
|
+
```
|
|
1467
|
+
|
|
1468
|
+
Use `createHandle({...})` from `devflare/sveltekit` when you need custom binding hints or want to compose Devflare with other SvelteKit handles via `sequence(...)`.
|
|
1469
|
+
|
|
1470
|
+
### Rolldown bundling and plugin workflows
|
|
1471
|
+
|
|
1472
|
+
`rolldown` is not just a namespace of knobs. Rolldown is the builder Devflare uses for the code Devflare actively bundles itself. Today that means the Durable Object path: Devflare discovers DO source files, applies its own transforms, lets user plugins transform imports, and emits runnable single-file ESM Worker modules that Miniflare can execute.
|
|
1473
|
+
|
|
1474
|
+
That is why `rolldown` is important but different from Vite:
|
|
1475
|
+
|
|
1476
|
+
- Vite may host the outer app or framework pipeline
|
|
1477
|
+
- Rolldown is the inner code-transform step that turns DO source into actual runnable worker code
|
|
1478
|
+
- if a Durable Object imports `.svelte`, that compilation belongs to the Rolldown plugin pipeline, not to the main Vite app plugin chain
|
|
1479
|
+
|
|
1480
|
+
It is still not Vite config, not a replacement for your app's `vite.config.*`, and not the place to configure the main fetch build.
|
|
1481
|
+
|
|
1482
|
+
Current DO bundler behavior:
|
|
1483
|
+
|
|
1484
|
+
- Devflare discovers DO files from `files.durableObjects`
|
|
1485
|
+
- discovered DO entries are bundled to worker-compatible ESM
|
|
1486
|
+
- code splitting is disabled so Devflare can emit a worker-friendly single-file bundle
|
|
1487
|
+
- user `rolldown.options.plugins` are merged into the bundle pipeline
|
|
1488
|
+
- internal externals cover `cloudflare:*`, `node:*`, and other worker/runtime modules that should stay external
|
|
1489
|
+
- Devflare also injects a `debug` alias shim so worker bundles do not accidentally drag in a Node-only debug dependency
|
|
1490
|
+
- this same DO bundling path still matters in unified Vite dev; Vite can host the app while Rolldown rebuilds DO worker code underneath it
|
|
1491
|
+
|
|
1492
|
+
Rolldown's plugin API is almost fully compatible with Rollup's, which is why Rollup-style plugins can often be passed through in `rolldown.options.plugins`. That said, compatibility is high, not magical: keep integration tests around nontrivial plugin stacks.
|
|
1493
|
+
|
|
1494
|
+
#### Minimal custom transform example
|
|
1495
|
+
|
|
1496
|
+
```ts
|
|
1497
|
+
import { defineConfig } from 'devflare'
|
|
1498
|
+
import type { Plugin as RolldownPlugin } from 'rolldown'
|
|
1499
|
+
|
|
1500
|
+
const inlineSvelteFixturePlugin: RolldownPlugin = {
|
|
1501
|
+
name: 'inline-svelte-fixture',
|
|
1502
|
+
transform(_code, id) {
|
|
1503
|
+
if (!id.endsWith('.svelte')) {
|
|
1504
|
+
return null
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
return {
|
|
1508
|
+
code: 'export default { render() { return { html: "<h1>Hello from Svelte</h1>" } } }',
|
|
1509
|
+
map: null
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
export default defineConfig({
|
|
1515
|
+
name: 'do-worker',
|
|
1516
|
+
files: {
|
|
1517
|
+
durableObjects: 'src/do/**/*.ts'
|
|
1518
|
+
},
|
|
1519
|
+
bindings: {
|
|
1520
|
+
durableObjects: {
|
|
1521
|
+
GREETER: 'Greeter'
|
|
1522
|
+
}
|
|
1523
|
+
},
|
|
1524
|
+
rolldown: {
|
|
1525
|
+
options: {
|
|
1526
|
+
plugins: [inlineSvelteFixturePlugin]
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
})
|
|
1530
|
+
```
|
|
1531
|
+
|
|
1532
|
+
That mirrors the kind of `.svelte` transform path the repo's own DO bundler tests exercise.
|
|
1533
|
+
|
|
1534
|
+
#### Svelte plugin example for Rolldown
|
|
1535
|
+
|
|
1536
|
+
This example is intentionally about a `.svelte` import inside a Durable Object module. In that situation, Rolldown — not the main Vite app build — is the plugin pipeline doing the compilation.
|
|
1537
|
+
|
|
1538
|
+
For this pattern you typically install `svelte`, `rollup-plugin-svelte`, and `@rollup/plugin-node-resolve` in the package that owns the Durable Object code.
|
|
1539
|
+
|
|
1540
|
+
```ts
|
|
1541
|
+
import { defineConfig } from 'devflare'
|
|
1542
|
+
import resolve from '@rollup/plugin-node-resolve'
|
|
1543
|
+
import type { Plugin as RolldownPlugin } from 'rolldown'
|
|
1544
|
+
import svelte from 'rollup-plugin-svelte'
|
|
1545
|
+
|
|
1546
|
+
export default defineConfig({
|
|
1547
|
+
name: 'chat-worker',
|
|
1548
|
+
files: {
|
|
1549
|
+
durableObjects: 'src/do/**/*.ts'
|
|
1550
|
+
},
|
|
1551
|
+
bindings: {
|
|
1552
|
+
durableObjects: {
|
|
1553
|
+
CHAT_ROOM: 'ChatRoom'
|
|
1554
|
+
}
|
|
1555
|
+
},
|
|
1556
|
+
rolldown: {
|
|
1557
|
+
target: 'es2022',
|
|
1558
|
+
sourcemap: true,
|
|
1559
|
+
options: {
|
|
1560
|
+
plugins: [
|
|
1561
|
+
svelte({
|
|
1562
|
+
emitCss: false,
|
|
1563
|
+
compilerOptions: {
|
|
1564
|
+
generate: 'ssr'
|
|
1565
|
+
}
|
|
1566
|
+
}) as unknown as RolldownPlugin,
|
|
1567
|
+
resolve({
|
|
1568
|
+
browser: true,
|
|
1569
|
+
exportConditions: ['svelte'],
|
|
1570
|
+
extensions: ['.svelte']
|
|
1571
|
+
}) as unknown as RolldownPlugin
|
|
1572
|
+
]
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
})
|
|
1576
|
+
```
|
|
1577
|
+
|
|
1578
|
+
```svelte
|
|
1579
|
+
<!-- src/do/Greeting.svelte -->
|
|
1580
|
+
<script lang='ts'>
|
|
1581
|
+
export let name: string
|
|
1582
|
+
</script>
|
|
1583
|
+
|
|
1584
|
+
<h1>Hello {name} from Svelte</h1>
|
|
1585
|
+
```
|
|
1586
|
+
|
|
1587
|
+
```ts
|
|
1588
|
+
// src/do/chat-room.ts
|
|
1589
|
+
import { DurableObject } from 'cloudflare:workers'
|
|
1590
|
+
import Greeting from './Greeting.svelte'
|
|
1591
|
+
|
|
1592
|
+
export class ChatRoom extends DurableObject {
|
|
1593
|
+
async fetch(): Promise<Response> {
|
|
1594
|
+
return new Response(Greeting.render({ name: 'Devflare' }).html, {
|
|
1595
|
+
headers: {
|
|
1596
|
+
'content-type': 'text/html; charset=utf-8'
|
|
1597
|
+
}
|
|
1598
|
+
})
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
```
|
|
1602
|
+
|
|
1603
|
+
What happens in this flow:
|
|
1604
|
+
|
|
1605
|
+
1. Devflare discovers `src/do/**/*.ts` from `files.durableObjects`
|
|
1606
|
+
2. the DO module imports `Greeting.svelte`
|
|
1607
|
+
3. Rolldown runs the configured plugin pipeline, including `rollup-plugin-svelte`
|
|
1608
|
+
4. the Svelte component becomes JavaScript before the DO bundle is written
|
|
1609
|
+
5. Devflare writes a runnable single-file Worker bundle for that DO
|
|
1610
|
+
|
|
1611
|
+
Why this example is shaped that way:
|
|
1612
|
+
|
|
1613
|
+
- `emitCss: false` keeps the DO bundle single-file instead of emitting a separate CSS asset pipeline
|
|
1614
|
+
- `generate: 'ssr'` fits the Worker-side rendering story better than a browser DOM target
|
|
1615
|
+
- `@rollup/plugin-node-resolve` helps `.svelte` files and `exports.svelte` packages resolve cleanly
|
|
1616
|
+
- some Rollup plugins need a type cast to satisfy Rolldown's TypeScript types even when the runtime hooks work fine
|
|
1617
|
+
- this example is specifically about worker-side component compilation inside a DO; if your Svelte code lives in the main app or SvelteKit shell, that outer build is still Vite's job
|
|
1618
|
+
|
|
1619
|
+
If a plugin relies on Rollup-only hooks that Rolldown does not support yet, keep that plugin in your main Vite build instead of the DO bundler.
|
|
1620
|
+
|
|
951
1621
|
### Daily development loop
|
|
952
1622
|
|
|
953
1623
|
Use the same CLI loop for both worker-only and Vite-backed packages. The presence of a local `vite.config.*` changes the mode automatically.
|
|
@@ -1013,7 +1683,8 @@ Current behavior:
|
|
|
1013
1683
|
- it resolves service bindings and cross-worker Durable Object references
|
|
1014
1684
|
- it can infer conventional fetch, queue, scheduled, and email handler files when present
|
|
1015
1685
|
- it also auto-detects `src/tail.ts` when present, even though there is no public `files.tail` config key
|
|
1016
|
-
- `
|
|
1686
|
+
- it auto-detects `src/transport.{ts,js,mts,mjs}` when present unless `files.transport` is `null`
|
|
1687
|
+
- it does not have a first-class `.dev.vars*` loader for populating declared secret values
|
|
1017
1688
|
|
|
1018
1689
|
Practical example:
|
|
1019
1690
|
|
|
@@ -1099,12 +1770,17 @@ Keep these caveats explicit:
|
|
|
1099
1770
|
- `_`-prefixed files and directories inside the route tree are ignored
|
|
1100
1771
|
- `vars` values are strings in the current native schema
|
|
1101
1772
|
- `secrets` declares runtime secret bindings; it does not store secret values
|
|
1773
|
+
- `.env*` and `.dev.vars*` are not a unified Devflare-native loading/validation system; any effect they have comes from Bun or upstream Cloudflare tooling, depending on the mode
|
|
1102
1774
|
- `wrangler.passthrough` is the escape hatch for unsupported Wrangler keys and is merged after native compilation
|
|
1103
1775
|
- named service entrypoints need deployment-time validation if they are critical to your app
|
|
1104
1776
|
- local R2 binding support is real, but there is still no stable public/browser local bucket URL contract to document as public API
|
|
1105
1777
|
- `sendEmail` is a supported outbound binding, while inbound email is a separate worker surface
|
|
1106
1778
|
- email and tail helpers have real, useful test paths, but they should not be described as identical to full Cloudflare ingress or tail replay
|
|
1107
1779
|
- Vite and Rolldown are different systems and should not be blurred together
|
|
1780
|
+
- `rolldown` config affects Durable Object bundling, not the main Vite app build
|
|
1781
|
+
- `wrangler.passthrough.main` suppresses Devflare's composed main-entry generation in higher-level build and Vite-backed flows
|
|
1782
|
+
- `getCloudflareConfig()` and `getDevflareConfigs()` are the safe config-time Vite helpers; `getPluginContext()` is advanced post-resolution state
|
|
1783
|
+
- Rollup-compatible plugins often work in `rolldown.options.plugins`, but compatibility is high-not-total and plugin-specific validation still matters
|
|
1108
1784
|
- higher-level flows may generate composed main worker entries more aggressively than older docs implied
|
|
1109
1785
|
|
|
1110
1786
|
---
|