@lunora/cli 1.0.0-alpha.42 → 1.0.0-alpha.421
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/LICENSE.md +33 -0
- package/README.md +3 -1
- package/dist/bin.mjs +2 -10
- package/dist/index.d.mts +1069 -374
- package/dist/index.d.ts +1069 -374
- package/dist/index.mjs +1 -19
- package/dist/packem_chunks/dispatch.mjs +1 -0
- package/dist/packem_chunks/handler.mjs +23 -158
- package/dist/packem_chunks/handler10.mjs +1 -16
- package/dist/packem_chunks/handler11.mjs +1 -22
- package/dist/packem_chunks/handler12.mjs +1 -192
- package/dist/packem_chunks/handler13.mjs +1 -131
- package/dist/packem_chunks/handler14.mjs +3 -65
- package/dist/packem_chunks/handler15.mjs +1 -58
- package/dist/packem_chunks/handler16.mjs +1 -80
- package/dist/packem_chunks/handler17.mjs +1 -43
- package/dist/packem_chunks/handler18.mjs +7 -105
- package/dist/packem_chunks/handler19.mjs +2 -170
- package/dist/packem_chunks/handler2.mjs +1 -114
- package/dist/packem_chunks/handler20.mjs +1 -94
- package/dist/packem_chunks/handler21.mjs +3 -94
- package/dist/packem_chunks/handler22.mjs +3 -0
- package/dist/packem_chunks/handler23.mjs +1 -0
- package/dist/packem_chunks/handler24.mjs +2 -0
- package/dist/packem_chunks/handler25.mjs +99 -0
- package/dist/packem_chunks/handler26.mjs +2 -0
- package/dist/packem_chunks/handler27.mjs +9 -0
- package/dist/packem_chunks/handler28.mjs +1 -0
- package/dist/packem_chunks/handler3.mjs +1 -204
- package/dist/packem_chunks/handler4.mjs +1 -33
- package/dist/packem_chunks/handler5.mjs +3 -49
- package/dist/packem_chunks/handler6.mjs +1 -91
- package/dist/packem_chunks/handler7.mjs +1 -42
- package/dist/packem_chunks/handler8.mjs +1 -174
- package/dist/packem_chunks/handler9.mjs +2 -315
- package/dist/packem_chunks/runCodegenCommand.mjs +4 -52
- package/dist/packem_chunks/runDevCommand.mjs +2 -0
- package/dist/packem_chunks/runInitCommand.mjs +165 -1432
- package/dist/packem_chunks/runResetCommand.mjs +1 -41
- package/dist/packem_chunks/runRpcCommand.mjs +1 -68
- package/dist/packem_shared/COMMANDS-BCSDC-pv.mjs +1 -0
- package/dist/packem_shared/DEFAULT_IMPORT_BATCH_SIZE-CyIsI3S1.mjs +1 -0
- package/dist/packem_shared/EXIT_CODE-D_XCixv8.mjs +1 -0
- package/dist/packem_shared/admin-token-VdUnvnKW.mjs +1 -0
- package/dist/packem_shared/admin-url-DJB8P6Jh.mjs +1 -0
- package/dist/packem_shared/api-spec-lYyq4vL6.mjs +1 -0
- package/dist/packem_shared/binding-manifest-file-CQ1eQYy1.mjs +2 -0
- package/dist/packem_shared/buildRegistryIndex-Dc8D8AR6.mjs +1 -0
- package/dist/packem_shared/cap-error-body-YBKO32BF.mjs +1 -0
- package/dist/packem_shared/catalog-CahzmDLV.mjs +1 -0
- package/dist/packem_shared/cli-BbgDNGew.mjs +2 -0
- package/dist/packem_shared/cli-manifest-DoQ_3bzs.mjs +1 -0
- package/dist/packem_shared/cloudflare-credentials-BVmZnDZk.mjs +1 -0
- package/dist/packem_shared/codegen-error-AmH54ofi.mjs +3 -0
- package/dist/packem_shared/command-CB4JM-Jl.mjs +1 -0
- package/dist/packem_shared/commands-DvSfLvyt.mjs +13 -0
- package/dist/packem_shared/createLogger-4TujevyB.mjs +2 -0
- package/dist/packem_shared/createRecordingSpawner-Ch7zuQQE.mjs +1 -0
- package/dist/packem_shared/deploy-target-resolve-BTCW1Iv4.mjs +1 -0
- package/dist/packem_shared/diffSnapshots-htqNZT8Q.mjs +7 -0
- package/dist/packem_shared/docker-DpVxvYpL.mjs +1 -0
- package/dist/packem_shared/free-port-DjbFhaaT.mjs +1 -0
- package/dist/packem_shared/health-probe-Bw9JFfIy.mjs +1 -0
- package/dist/packem_shared/import-BRM1hs7j.mjs +12 -0
- package/dist/packem_shared/index-oHZBGBwB.mjs +1 -0
- package/dist/packem_shared/insertSchemaExtension-DuiV6cba.mjs +8 -0
- package/dist/packem_shared/lint-ignore-report-DKZagpqk.mjs +2 -0
- package/dist/packem_shared/mcp-config-file-CcDTeXIq.mjs +2 -0
- package/dist/packem_shared/open-url-EnKy--w-.mjs +1 -0
- package/dist/packem_shared/output-format-DWe_tkTR.mjs +2 -0
- package/dist/packem_shared/parseManifest-CwPTKdtS.mjs +1 -0
- package/dist/packem_shared/path-containment-CgxYZggb.mjs +1 -0
- package/dist/packem_shared/plan-DFY3CqHD.mjs +5 -0
- package/dist/packem_shared/planDevCommand-BDoJUgQ4.mjs +1 -0
- package/dist/packem_shared/platform-diagnostics-Cn2g6Jh-.mjs +4 -0
- package/dist/packem_shared/prompt-cancelled-BvsNxg_Q.mjs +1 -0
- package/dist/packem_shared/render-lunora-error-B6893vbU.mjs +2 -0
- package/dist/packem_shared/resolve-Bdc9KEUv.mjs +5 -0
- package/dist/packem_shared/resolve-target-C_ZloTvd.mjs +1 -0
- package/dist/packem_shared/runAddCommand-BChdJQ5L.mjs +1 -0
- package/dist/packem_shared/runDeployCommand-D40F3PLQ.mjs +1 -0
- package/dist/packem_shared/runExportCommand-slAq5BCF.mjs +5 -0
- package/dist/packem_shared/runMigrateGenerateCommand-BwemPIOz.mjs +11 -0
- package/dist/packem_shared/schemaIrToSnapshot-BHuNOfgs.mjs +1 -0
- package/dist/packem_shared/secret-key-8DPOH98z.mjs +1 -0
- package/dist/packem_shared/shared-D-zCOmgY.mjs +1 -0
- package/dist/packem_shared/storage-DNzYhXR-.mjs +1 -0
- package/dist/packem_shared/tui-prompts-B3YwUhGw.mjs +4 -0
- package/dist/packem_shared/variables-CPYyJtsL.mjs +1 -0
- package/dist/packem_shared/wrangler-name-Dsk5K1f-.mjs +1 -0
- package/dist/packem_shared/wrangler-secrets-CTQPpalP.mjs +1 -0
- package/package.json +39 -19
- package/skills/README.md +36 -17
- package/skills/lunora/SKILL.md +158 -65
- package/skills/lunora-cloudflare-audit/SKILL.md +163 -0
- package/skills/lunora-create-package/SKILL.md +97 -84
- package/skills/lunora-deploy/SKILL.md +175 -105
- package/skills/lunora-functions/SKILL.md +363 -56
- package/skills/lunora-migration-helper/SKILL.md +162 -137
- package/skills/lunora-performance-audit/SKILL.md +137 -95
- package/skills/lunora-quickstart/SKILL.md +136 -136
- package/skills/lunora-realtime/SKILL.md +217 -97
- package/skills/lunora-setup-auth/SKILL.md +162 -102
- package/skills/lunora-setup-hyperdrive/SKILL.md +130 -109
- package/skills/lunora-setup-hyperdrive-global/SKILL.md +93 -90
- package/skills/lunora-setup-mail/SKILL.md +85 -113
- package/skills/lunora-setup-scheduler/SKILL.md +132 -96
- package/skills/lunora-setup-storage/SKILL.md +189 -95
- package/dist/packem_chunks/planDevCommand.mjs +0 -541
- package/dist/packem_chunks/runDeployCommand.mjs +0 -594
- package/dist/packem_chunks/runMigrateGenerateCommand.mjs +0 -397
- package/dist/packem_shared/COMMANDS-B0ftFD_3.mjs +0 -948
- package/dist/packem_shared/DEFAULT_IMPORT_BATCH_SIZE-Ck-2bU08.mjs +0 -244
- package/dist/packem_shared/admin-url-4UzT-CI4.mjs +0 -19
- package/dist/packem_shared/api-spec-CtA6ilu4.mjs +0 -13
- package/dist/packem_shared/buildRegistryIndex-BcYe607_.mjs +0 -38
- package/dist/packem_shared/codegen-error-DJG-ghs_.mjs +0 -31
- package/dist/packem_shared/command-D3lB_4Az.mjs +0 -19
- package/dist/packem_shared/commands-B-gR09Z_.mjs +0 -845
- package/dist/packem_shared/createLogger-B40gPzQo.mjs +0 -78
- package/dist/packem_shared/createRecordingSpawner-DxI3mebw.mjs +0 -43
- package/dist/packem_shared/detect-package-manager-DYp7n3mJ.mjs +0 -61
- package/dist/packem_shared/diffSnapshots-BeDvvNiF.mjs +0 -161
- package/dist/packem_shared/docker-hMQ97KSQ.mjs +0 -21
- package/dist/packem_shared/insertSchemaExtension-DAqbfr9Z.mjs +0 -64
- package/dist/packem_shared/open-url-Dfq6fAyT.mjs +0 -41
- package/dist/packem_shared/output-format-wUvAN6AL.mjs +0 -17
- package/dist/packem_shared/parseArgs-YXFuKdEk.mjs +0 -56
- package/dist/packem_shared/parseManifest--vZf2FY1.mjs +0 -94
- package/dist/packem_shared/prompt-cancelled-APzX1Im-.mjs +0 -9
- package/dist/packem_shared/resolve-target-qbsJ_5sF.mjs +0 -16
- package/dist/packem_shared/runAddCommand-bnY6-HKb.mjs +0 -4
- package/dist/packem_shared/schema-drift-gate-BtBt0as0.mjs +0 -79
- package/dist/packem_shared/schemaIrToSnapshot-DdsljJT-.mjs +0 -43
- package/dist/packem_shared/storage-BIsph-Vk.mjs +0 -84
- package/dist/packem_shared/tui-prompts-BjEN8XgP.mjs +0 -658
- package/dist/packem_shared/wrangler-name-cy4yhm9j.mjs +0 -12
- package/dist/packem_shared/wrangler-secrets-P2_ZUR-k.mjs +0 -47
|
@@ -1,47 +1,36 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: lunora-create-package
|
|
3
|
-
description: Builds a reusable Lunora capability
|
|
4
|
-
`lunora registry add
|
|
5
|
-
|
|
3
|
+
description: Builds a reusable Lunora capability, either as a registry item that
|
|
4
|
+
`lunora add` / `lunora registry add` copies into an app's `lunora/`, or as a
|
|
5
|
+
publishable `@lunora/*` workspace package in the Lunora monorepo. Use when the
|
|
6
|
+
user wants to package schema + functions + wrangler bindings + env vars for
|
|
7
|
+
other apps, add or edit an item under `registry/<name>/` (`registry.json`),
|
|
8
|
+
run `vis generate lunora-package`, or wire a new `ctx.*` capability into
|
|
9
|
+
codegen.
|
|
6
10
|
---
|
|
7
11
|
|
|
8
12
|
# Lunora Create Package
|
|
9
13
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
**imported as a dependency**.
|
|
14
|
+
Pick the shape by whether the code is copied into the user's `lunora/` or
|
|
15
|
+
imported as a dependency:
|
|
13
16
|
|
|
14
|
-
| Shape
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
|
|
|
17
|
+
| Shape | Distribution | Use for |
|
|
18
|
+
| ------------- | -------------------------------- | ------------------------------------------------ |
|
|
19
|
+
| Registry item | `lunora registry add <name>` | App-owned code (schema/functions) the user edits |
|
|
20
|
+
| Workspace pkg | `import … from "@lunora/<name>"` | Library code consumed as a versioned dependency |
|
|
18
21
|
|
|
19
|
-
Many capabilities use
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
and `storage` all follow this pattern.
|
|
22
|
+
Many capabilities use both: a `@lunora/<name>` package holds the runtime and a
|
|
23
|
+
registry item scaffolds the glue (files under `lunora/<name>/`, bindings, env
|
|
24
|
+
vars). `auth`, `mail`, `ratelimit` and `storage` follow this pattern.
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
Skip this skill for a one-off feature in a single app (write it in `lunora/`),
|
|
27
|
+
or when the capability already exists (`lunora registry list`).
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
- Authoring a new capability (presence, search, payments, …) for other apps.
|
|
28
|
-
- Adding a new item to this repo's `registry/`.
|
|
29
|
+
## Path A: registry item
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
-
|
|
33
|
-
- The capability already exists as a registry item or `@lunora/*` package — use
|
|
34
|
-
it (`lunora registry list` to browse).
|
|
35
|
-
|
|
36
|
-
## Path A: Registry Item
|
|
37
|
-
|
|
38
|
-
A registry item is a directory under `registry/<name>/` with three files:
|
|
39
|
-
|
|
40
|
-
- `registry.json` — the manifest (deps, bindings, env vars, files, requires).
|
|
41
|
-
- `index.ts` (and any siblings) — the code copied into the user's project.
|
|
42
|
-
- `README.md` — install + configuration docs.
|
|
43
|
-
|
|
44
|
-
### Manifest shape
|
|
31
|
+
An item is a directory `registry/<name>/` holding `registry.json`, the source
|
|
32
|
+
files it copies, and a `README.md`. Validate against
|
|
33
|
+
`registry/schema/registry-item.schema.json`.
|
|
45
34
|
|
|
46
35
|
```jsonc
|
|
47
36
|
// registry/<name>/registry.json
|
|
@@ -50,80 +39,104 @@ A registry item is a directory under `registry/<name>/` with three files:
|
|
|
50
39
|
"name": "<name>",
|
|
51
40
|
"title": "Human Title",
|
|
52
41
|
"description": "One-paragraph summary shown in `lunora registry list`.",
|
|
53
|
-
"docs": "Post-install steps
|
|
54
|
-
"requires": [], // other
|
|
42
|
+
"docs": "Post-install steps printed after `lunora registry add`.",
|
|
43
|
+
"requires": [], // other items, installed first (e.g. auth-clerk requires auth)
|
|
55
44
|
"deps": { "@lunora/server": "workspace:*" },
|
|
45
|
+
"devDependencies": {},
|
|
56
46
|
"bindings": [
|
|
57
|
-
//
|
|
47
|
+
// structural edits applied to wrangler.jsonc
|
|
58
48
|
{ "path": ["d1_databases"], "value": [{ "binding": "DB", "database_name": "REPLACE_ME-db", "database_id": "<replace-with-d1-create-id>" }] },
|
|
59
49
|
],
|
|
60
50
|
"envVars": [{ "name": "MY_SECRET", "description": "What it is and how to generate it.", "secret": true }],
|
|
61
|
-
"files": [
|
|
51
|
+
"files": [
|
|
52
|
+
{ "from": "schema.ts", "to": "lunora/<name>/schema.ts", "merge": "schema-extension" },
|
|
53
|
+
{ "from": "<name>.ts", "to": "lunora/<name>/index.ts", "merge": "create-or-skip" },
|
|
54
|
+
],
|
|
62
55
|
}
|
|
63
56
|
```
|
|
64
57
|
|
|
65
|
-
- `files[].merge
|
|
66
|
-
`
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
58
|
+
- `files[].merge`: `create-or-skip` writes whole files and never clobbers a file
|
|
59
|
+
the user edited; `schema-extension` AST-merges into `lunora/schema.ts`.
|
|
60
|
+
- `envVars` land in `.dev.vars`. Non-secret vars get their `value`; secrets get
|
|
61
|
+
an empty placeholder plus a `wrangler secret put <NAME>` reminder.
|
|
62
|
+
- `entrypointReexports` (`[{ "module": "_generated/workflows" }]`) injects
|
|
63
|
+
`export * from './lunora/<module>'` into the worker entry of framework
|
|
64
|
+
(class B/C) projects, for items whose generated classes the worker must
|
|
65
|
+
export. No shipped item uses it yet.
|
|
66
|
+
- Function files import builders from `#lunora/_generated/server.js`, the
|
|
67
|
+
module codegen emits in a consumer project. `registry/tsconfig.json` stubs
|
|
68
|
+
that module so the item typechecks here.
|
|
69
|
+
- `deps` ranges are copied verbatim into the user's `package.json`. Use
|
|
70
|
+
`workspace:*` for `@lunora/*` (resolved at publish); any other range must
|
|
71
|
+
admit the version the workspace resolves, or `pnpm install` fails
|
|
72
|
+
(`scripts/check-registry-catalog-ranges.js`).
|
|
73
|
+
|
|
74
|
+
Verify:
|
|
74
75
|
|
|
75
76
|
```bash
|
|
76
|
-
lunora registry build
|
|
77
|
-
lunora registry build --check
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
lunora registry build --from ./registry # regenerate registry/index.json from the item dirs
|
|
78
|
+
lunora registry build --from ./registry --check # CI: index is current
|
|
79
|
+
pnpm run lint:types:registry # tsc over every item (builds packages first)
|
|
80
|
+
pnpm run lint:registry:items # manifest + generated-deps tests
|
|
81
|
+
lunora registry view <name> --from <repo>/registry # preview
|
|
82
|
+
lunora registry add <name> --from <repo>/registry --dry-run # in a scratch app
|
|
80
83
|
```
|
|
81
84
|
|
|
82
|
-
|
|
85
|
+
`registry/index.json` is generated; do not hand-edit it.
|
|
83
86
|
|
|
84
|
-
|
|
85
|
-
`--name=value` form):
|
|
87
|
+
## Path B: workspace package (Lunora monorepo)
|
|
86
88
|
|
|
87
89
|
```bash
|
|
88
|
-
vis generate lunora-package --name=search --description='Typed full-text search over Lunora tables'
|
|
90
|
+
vis generate lunora-package --name=search --description='Typed full-text search over Lunora tables' --category=add-on
|
|
89
91
|
```
|
|
90
92
|
|
|
91
|
-
|
|
92
|
-
`
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
Pass every option as `--name=value`; vis reads `--name search` as
|
|
94
|
+
`--name=true` plus a stray positional.
|
|
95
|
+
|
|
96
|
+
This writes `packages/search/` with `package.json` (ESM-only,
|
|
97
|
+
`"sideEffects": false`, catalog versions), `src/index.ts`, `tsconfig.json`,
|
|
98
|
+
`vitest.config.ts`, `packem.config.ts`, `eslint.config.js`,
|
|
99
|
+
`prettier.config.js`, `project.json` (tags `type:package` +
|
|
100
|
+
`category:<category>`), `.releaserc.json` and `README.md`. It does not create
|
|
101
|
+
`__tests__/` or `LICENSE.md`. Then:
|
|
95
102
|
|
|
96
|
-
|
|
103
|
+
1. `cp packages/config/LICENSE.md packages/search/LICENSE.md` (packem and
|
|
104
|
+
`files` expect it).
|
|
105
|
+
2. Add a row to `.agents/docs/packages.md`, and list the directory in one tier
|
|
106
|
+
of `scripts/api-snapshot.js` and the matching tier in `ROADMAP.md`. The
|
|
107
|
+
`pnpm install` postinstall checks (`check-agents-md-packages`,
|
|
108
|
+
`check-roadmap-tiers`) fail until both are done.
|
|
109
|
+
3. `pnpm install`, then add tests under `__tests__/`.
|
|
97
110
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
more than one export.
|
|
102
|
-
- **Use the dependency catalogs** in `pnpm-workspace.yaml` (`catalog:test`,
|
|
103
|
-
`catalog:lint`, …) — never hard-code a version that lives in a catalog.
|
|
104
|
-
- Tag `project.json` with `type:package` and a `category:<slug>`.
|
|
111
|
+
Repo conventions: relative imports without `.js`, named exports only (a
|
|
112
|
+
`default` only as a file's sole export), dependency versions via `catalog:*`
|
|
113
|
+
from `pnpm-workspace.yaml`.
|
|
105
114
|
|
|
106
|
-
|
|
115
|
+
Verify:
|
|
107
116
|
|
|
108
117
|
```bash
|
|
118
|
+
pnpm --filter "@lunora/search..." run build
|
|
109
119
|
pnpm --filter "@lunora/search" run lint:types
|
|
110
120
|
pnpm --filter "@lunora/search" run test
|
|
121
|
+
pnpm run lint:package-json
|
|
122
|
+
pnpm run api:update # writes api-snapshots/search.api.md from the fresh build; commit it
|
|
111
123
|
```
|
|
112
124
|
|
|
113
|
-
##
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
125
|
+
## Wiring a `ctx.*` capability into codegen
|
|
126
|
+
|
|
127
|
+
Codegen decides which `ctx.*` fields exist by detecting usage, so a new
|
|
128
|
+
binding-backed helper is a literal row in `CAPABILITY_ROWS`
|
|
129
|
+
(`packages/codegen/src/capabilities.ts`; `CAPABILITIES` is a read-only view of
|
|
130
|
+
it): its package, `ctx` property, tier
|
|
131
|
+
(`"every"` or `"action"`-only), ctx type fragment, ShardDO binding, and
|
|
132
|
+
`defineApp` method. Rate the feature for every target in the
|
|
133
|
+
`PlatformCapabilities` matrices in `@lunora/platform`
|
|
134
|
+
(`packages/platform/src/capabilities/`) as `native`, `emulated` or
|
|
135
|
+
`unsupported` in the same change. A feature a target leaves unrated is dropped
|
|
136
|
+
from that target's generated surface with a diagnostic. Declaration-gated
|
|
137
|
+
surfaces (flags, notify, containers, workflows, queues, agents) also have their
|
|
138
|
+
own emitters; some of them (flags, notify, containers, workflows) keep a row too,
|
|
139
|
+
for usage probing, so a row and a dedicated emitter can coexist.
|
|
140
|
+
|
|
141
|
+
Document in the README any `lunora/*.ts` declaration the user must add for
|
|
142
|
+
codegen to emit the typed surface.
|
|
@@ -1,150 +1,220 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: lunora-deploy
|
|
3
|
-
description: Deploys a Lunora app to Cloudflare.
|
|
4
|
-
bindings (SHARD/SESSION DOs, D1, R2), provisioning databases/buckets, secrets
|
|
5
|
-
(`wrangler secret` vs `.dev.vars`), the `lunora doctor` preflight, the
|
|
6
|
-
schema-drift gate, and dev-vs-prod separation.
|
|
3
|
+
description: Deploys a Lunora app to Cloudflare Workers + Durable Objects and gets wrangler.jsonc, remote resources and secrets to line up. Covers `lunora deploy` (and `--env`, `--dry-run`, `--preview`, `--migrate`), the `lunora doctor` / `lunora verify` / `lunora prepare` preflights, Durable Object bindings (SHARD, SHARD_REGISTRY, SCHEDULER), the `DB` D1 binding and its placeholder id, R2 buckets, production secrets (`lunora env push`, `wrangler secret put`) versus `.dev.vars`, the schema-drift gate, the architecture diff, and rollback with `lunora cloudflare deployments`. Use when the user asks to "deploy", "ship to production", "set up a staging environment", wire CI deploys, or when a deploy fails on a binding, a placeholder `database_id`, an unexported Durable Object class, a missing secret, or "schema drift gate blocked deploy".
|
|
7
4
|
---
|
|
8
5
|
|
|
9
6
|
# Lunora Deploy
|
|
10
7
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
Deploying a Lunora app means making `wrangler.jsonc`, the remote Cloudflare
|
|
9
|
+
resources (D1, R2, secrets) and the worker's exports agree. `lunora deploy`
|
|
10
|
+
automates most of that and refuses to ship when they don't.
|
|
11
|
+
|
|
12
|
+
Local development is `lunora dev` (see `lunora-quickstart`). If the deploy is
|
|
13
|
+
blocked by a breaking schema change, stage it with `lunora-migration-helper`
|
|
14
|
+
first.
|
|
15
|
+
|
|
16
|
+
## What `lunora deploy` does
|
|
17
|
+
|
|
18
|
+
In order, stopping at the first failure:
|
|
19
|
+
|
|
20
|
+
1. **Codegen** — regenerates `lunora/_generated/`. ERROR-level codegen
|
|
21
|
+
advisories fail the deploy in CI (`--strict-advisories` forces this locally,
|
|
22
|
+
`--no-strict-advisories` turns it off). Nothing here runs `tsc` and wrangler
|
|
23
|
+
strips types, so a project with a type error deploys — gate CI on
|
|
24
|
+
`lunora verify`, which does type-check.
|
|
25
|
+
2. **Schema-drift gate** — compares the schema with the committed baseline
|
|
26
|
+
`lunora/.lunora-schema.json` (details below).
|
|
27
|
+
3. **Architecture diff** — prints modules and edges (calls, table reads/writes,
|
|
28
|
+
enqueues) added or removed since the last successful deploy. Informational
|
|
29
|
+
only; the manifest is recorded in `.lunora/architecture[.<env>].json` after
|
|
30
|
+
wrangler succeeds.
|
|
31
|
+
4. **Binding reconcile** — writes the bindings the code implies into
|
|
32
|
+
`wrangler.jsonc`: Durable Object bindings plus their `new_sqlite_classes`
|
|
33
|
+
migration, the `DB` D1 binding for `.global()` tables, crons, and the
|
|
34
|
+
compatibility date. R2 buckets are not auto-written (the bucket name is
|
|
35
|
+
yours to choose); you get a warning instead.
|
|
36
|
+
5. **Read-only checks** — blocks on a D1 `database_id` still set to
|
|
37
|
+
`<replace-with-d1-create-id>`, on a loopback URL (`localhost`, `127.x`,
|
|
38
|
+
`::1`) in `vars`, on a missing container Dockerfile, or on no Docker engine
|
|
39
|
+
when a container builds locally.
|
|
40
|
+
6. **Validate `wrangler.jsonc`** — the `SHARD` binding to `ShardDO` (or
|
|
41
|
+
`LunoraDO` for apps that merge their DOs), a minimum `compatibility_date`,
|
|
42
|
+
DO classes registered in `migrations`, and the shape of every binding.
|
|
43
|
+
`compatibility_flags` are not checked; templates ship `nodejs_compat` for
|
|
44
|
+
dependencies that import `node:` builtins.
|
|
45
|
+
7. **Secrets gate** — lists the secrets the app's packages need and checks
|
|
46
|
+
which are set on the worker. Interactive runs offer to mint and push the
|
|
47
|
+
generatable ones (`BETTER_AUTH_SECRET`, `LUNORA_ADMIN_TOKEN`, …). In CI a
|
|
48
|
+
missing required secret aborts the deploy. Skipped for `--dry-run` /
|
|
49
|
+
`--preview`, and when the worker doesn't exist yet.
|
|
50
|
+
8. **Services, then `wrangler deploy`** — services declared in
|
|
51
|
+
`lunora.config` deploy first (`--skip-services` to skip), then the app.
|
|
52
|
+
9. **After a successful deploy** — records the URL as the project link
|
|
53
|
+
(`lunora link`), optionally runs `--migrate` and `--health-check`, and only
|
|
54
|
+
then re-blesses the schema baseline.
|
|
55
|
+
|
|
56
|
+
`lunora prepare` runs steps 1–6 without deploying (useful in CI), but it takes
|
|
57
|
+
no `--env`, so it validates the top-level config only. `lunora verify` runs
|
|
58
|
+
validation, a codegen dry run and `tsc --noEmit` without writing files, and does
|
|
59
|
+
take `--env`.
|
|
60
|
+
|
|
61
|
+
Flags worth knowing:
|
|
62
|
+
|
|
63
|
+
| Flag | Effect |
|
|
64
|
+
| -------------------------- | ------------------------------------------------------------------------------- |
|
|
65
|
+
| `--env <name>` | Deploy a wrangler environment; checks read that env's (non-inherited) bindings. |
|
|
66
|
+
| `--dry-run` | Run every gate and bundle without publishing; `wrangler.jsonc` edits roll back. |
|
|
67
|
+
| `--preview` | Upload a version (`wrangler versions upload`) with a preview URL; no traffic. |
|
|
68
|
+
| `--health-check` | Probe `/_lunora/health/ready` on the new version; fail if it never answers. |
|
|
69
|
+
| `--prebuilt` | Skip codegen and the drift gate when `lunora prepare` already ran in this job. |
|
|
70
|
+
| `--migrate` | Run every declared data migration (`up` is idempotent) against the live worker. |
|
|
71
|
+
| `--allow-schema-drift` | Deploy despite blocked drift; the baseline is not advanced. |
|
|
72
|
+
| `--update-schema-baseline` | Accept the current schema as the new baseline. |
|
|
73
|
+
|
|
74
|
+
`--migrate` is checked before wrangler runs, so a missing requirement aborts the
|
|
75
|
+
whole deploy:
|
|
76
|
+
|
|
77
|
+
- `--migrate-yes` — confirms running production data migrations.
|
|
78
|
+
- `--migrate-url <https://…>` — required unless this checkout is linked for the
|
|
79
|
+
same `--env` (a previous successful deploy links it automatically).
|
|
80
|
+
- An admin token — `--migrate-token` or `LUNORA_ADMIN_TOKEN`.
|
|
15
81
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
- A deploy fails on a binding, a placeholder id, or the schema-drift gate.
|
|
20
|
-
- Provisioning D1 / R2 / secrets for a Lunora app.
|
|
21
|
-
|
|
22
|
-
## When Not to Use
|
|
23
|
-
|
|
24
|
-
- Local development — that is `lunora dev` (see `lunora-quickstart`).
|
|
25
|
-
- A schema/data change that needs migrating — do that first with
|
|
26
|
-
`lunora-migration-helper`, then deploy.
|
|
27
|
-
|
|
28
|
-
## What `lunora deploy` Does
|
|
29
|
-
|
|
30
|
-
`lunora deploy` runs a fixed pipeline:
|
|
31
|
-
|
|
32
|
-
1. **Codegen** — regenerates `lunora/_generated/` and typechecks.
|
|
33
|
-
2. **Validate `wrangler.jsonc`** — required `compatibility_date`, the
|
|
34
|
-
`nodejs_compat` flag, and the `SHARD` Durable Object binding.
|
|
35
|
-
3. **Schema-drift gate** — blocks if the committed baseline
|
|
36
|
-
(`lunora/.lunora-schema.json`) drifted with a breaking change and no
|
|
37
|
-
accompanying migration. The baseline is re-blessed only after the deploy
|
|
38
|
-
succeeds.
|
|
39
|
-
4. **`wrangler deploy`** — builds and pushes the worker (and any container
|
|
40
|
-
images).
|
|
41
|
-
|
|
42
|
-
Useful flags: `--env <name>` (Cloudflare environment), `--migrate` (run pending
|
|
43
|
-
data migrations against the live worker after deploy, with `--migrate-token` /
|
|
44
|
-
`--migrate-url`), `--allow-schema-drift` (override the gate — use sparingly), and
|
|
45
|
-
`--update-schema-baseline` (re-bless the baseline with the current shape).
|
|
46
|
-
|
|
47
|
-
## Preflight: `lunora doctor`
|
|
48
|
-
|
|
49
|
-
Run the read-only preflight before deploying. It checks:
|
|
82
|
+
```bash
|
|
83
|
+
lunora deploy --migrate --migrate-yes --migrate-url https://app.example.com
|
|
84
|
+
```
|
|
50
85
|
|
|
51
|
-
|
|
52
|
-
- D1 `database_id`s are real, not placeholders (`<replace>` / empty).
|
|
53
|
-
- `send_email` destination addresses aren't placeholders.
|
|
54
|
-
- `.dev.vars` secret-looking keys are filled.
|
|
55
|
-
- Declared containers are exported by the worker entry.
|
|
86
|
+
## Preflight
|
|
56
87
|
|
|
57
88
|
```bash
|
|
58
|
-
lunora doctor
|
|
89
|
+
lunora doctor # read-only; exits 1 on any FAIL, WARN/INFO don't block
|
|
90
|
+
lunora doctor --format json # each finding carries a stable `code` for CI/agents
|
|
91
|
+
lunora verify --env production
|
|
59
92
|
```
|
|
60
93
|
|
|
61
|
-
`lunora
|
|
62
|
-
|
|
94
|
+
`lunora doctor` fails on a missing or invalid `wrangler.jsonc`, a missing
|
|
95
|
+
`SHARD` binding, a placeholder D1 id (`d1-placeholder-id`), and a binding whose
|
|
96
|
+
class the worker doesn't export (`wrangler-class-unexported`), and an Artifacts
|
|
97
|
+
namespace in the wrong jurisdiction. It warns on unfilled `.dev.vars` secrets,
|
|
98
|
+
placeholder `send_email` destinations, an account near its Durable Object class
|
|
99
|
+
cap, and a `cloudflare.config.ts` (`cf-config-present`).
|
|
63
100
|
|
|
64
|
-
## `wrangler.jsonc`
|
|
101
|
+
## `wrangler.jsonc`
|
|
65
102
|
|
|
66
|
-
|
|
67
|
-
|
|
103
|
+
Templates ship this shape. The `d1_databases` and `r2_buckets` entries are
|
|
104
|
+
only needed when the app uses `.global()` tables or auth (D1) and storage (R2):
|
|
68
105
|
|
|
69
106
|
```jsonc
|
|
70
107
|
{
|
|
71
108
|
"name": "my-app",
|
|
72
|
-
"main": "src/
|
|
73
|
-
"compatibility_date": "2026-
|
|
109
|
+
"main": "src/server.ts",
|
|
110
|
+
"compatibility_date": "2026-10-01",
|
|
74
111
|
"compatibility_flags": ["nodejs_compat"],
|
|
75
112
|
"durable_objects": {
|
|
76
113
|
"bindings": [
|
|
77
114
|
{ "name": "SHARD", "class_name": "ShardDO" },
|
|
78
|
-
{ "name": "
|
|
115
|
+
{ "name": "SHARD_REGISTRY", "class_name": "ShardRegistryDO" },
|
|
79
116
|
],
|
|
80
117
|
},
|
|
81
|
-
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["ShardDO", "
|
|
82
|
-
"
|
|
83
|
-
"
|
|
118
|
+
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["ShardDO", "ShardRegistryDO"] }],
|
|
119
|
+
"limits": { "cpu_ms": 30000 },
|
|
120
|
+
"d1_databases": [{ "binding": "DB", "database_name": "my-app", "database_id": "<replace-with-d1-create-id>" }],
|
|
121
|
+
"r2_buckets": [{ "binding": "UPLOADS", "bucket_name": "my-app-uploads" }],
|
|
84
122
|
}
|
|
85
123
|
```
|
|
86
124
|
|
|
87
|
-
|
|
88
|
-
bindings
|
|
89
|
-
|
|
125
|
+
Reconcile adds `SCHEDULER` → `SchedulerDO` when the app schedules work, and
|
|
126
|
+
bindings for generated containers, workflows and agents. Every `class_name`
|
|
127
|
+
must be exported by the worker entry or wrangler rejects the deploy.
|
|
128
|
+
|
|
129
|
+
Lunora writes the bindings but cannot create the remote resources:
|
|
90
130
|
|
|
91
131
|
```bash
|
|
92
|
-
wrangler d1 create my-app
|
|
93
|
-
wrangler r2 bucket create my-app-
|
|
132
|
+
wrangler d1 create my-app # paste the returned database_id into wrangler.jsonc
|
|
133
|
+
wrangler r2 bucket create my-app-uploads
|
|
94
134
|
```
|
|
95
135
|
|
|
96
|
-
|
|
97
|
-
`
|
|
98
|
-
|
|
99
|
-
container export proactively.
|
|
136
|
+
When using `--env`, remember that `vars`, `d1_databases`, `durable_objects` and
|
|
137
|
+
`containers` do not inherit in wrangler. Each environment needs its own entries,
|
|
138
|
+
including its own D1 database.
|
|
100
139
|
|
|
101
|
-
## Secrets
|
|
140
|
+
## Secrets
|
|
102
141
|
|
|
103
|
-
`.dev.vars` is
|
|
104
|
-
|
|
105
|
-
into Cloudflare:
|
|
142
|
+
`.dev.vars` is for development only: it is git-ignored and `wrangler deploy`
|
|
143
|
+
never uploads it. Production secrets live in Cloudflare:
|
|
106
144
|
|
|
107
145
|
```bash
|
|
108
|
-
|
|
109
|
-
|
|
146
|
+
lunora env diff --env production # keys local-only vs set remotely
|
|
147
|
+
lunora env push --env production --yes # uploads .dev.vars values; refuses placeholders
|
|
148
|
+
wrangler secret put RESEND_API_KEY --env production # set a prod-only value by hand
|
|
110
149
|
```
|
|
111
150
|
|
|
112
|
-
|
|
113
|
-
|
|
151
|
+
`lunora env push` uploads the values from `.dev.vars`. If production needs
|
|
152
|
+
different values than dev (it usually does for provider keys), set those with
|
|
153
|
+
`wrangler secret put` instead.
|
|
154
|
+
|
|
155
|
+
## Schema-drift gate
|
|
156
|
+
|
|
157
|
+
The gate blocks when the schema changed in a breaking way since
|
|
158
|
+
`lunora/.lunora-schema.json` and no new `defineMigration` on the affected table
|
|
159
|
+
covers it. The block message lists each change and a paste-ready
|
|
160
|
+
`lunora migrate create … --table …` command. Commit the baseline file so CI
|
|
161
|
+
and every machine gate against the same shape. It is advanced only after a
|
|
162
|
+
successful deploy, so a failed deploy never moves it past a change that didn't
|
|
163
|
+
ship.
|
|
164
|
+
|
|
165
|
+
Reach for `--allow-schema-drift` / `--update-schema-baseline` only when you know
|
|
166
|
+
existing data is compatible. Otherwise stage the change with
|
|
167
|
+
`lunora-migration-helper`.
|
|
168
|
+
|
|
169
|
+
## `.global()` table DDL
|
|
114
170
|
|
|
115
|
-
|
|
171
|
+
The runtime provisions `.global()` tables itself on first use
|
|
172
|
+
(`CREATE TABLE IF NOT EXISTS` plus additive `ADD COLUMN` / indexes), so additive
|
|
173
|
+
changes need no step. `lunora migrate generate` writes a reviewable SQL file for
|
|
174
|
+
D1-backed global tables, but no command applies it, `lunora deploy` included.
|
|
175
|
+
Destructive or hand-written statements in it (drops, a backfilling `UPDATE`, a
|
|
176
|
+
rename) must be applied by hand:
|
|
116
177
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
178
|
+
```bash
|
|
179
|
+
wrangler d1 execute DB --remote --file=lunora/migrations/<file>.sql
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
See `lunora-migration-helper` for the full flow.
|
|
121
183
|
|
|
122
|
-
|
|
123
|
-
migrate generate` before deploying; `@lunora/d1`'s runner applies them. For data
|
|
124
|
-
backfills, deploy first, then `lunora deploy --migrate` (or `lunora migrate up
|
|
125
|
-
--prod`). See `lunora-migration-helper`.
|
|
184
|
+
## Rollback
|
|
126
185
|
|
|
127
|
-
|
|
186
|
+
```bash
|
|
187
|
+
lunora cloudflare deployments list
|
|
188
|
+
lunora cloudflare deployments rollback --yes # previous version
|
|
189
|
+
lunora cloudflare deployments promote <version-id> --yes # send 100% of traffic to a version
|
|
190
|
+
```
|
|
128
191
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
`
|
|
192
|
+
Rolling back code does not roll back data migrations or D1 DDL.
|
|
193
|
+
|
|
194
|
+
## Common pitfalls
|
|
195
|
+
|
|
196
|
+
1. **Placeholder `database_id`.** Reconcile writes
|
|
197
|
+
`<replace-with-d1-create-id>`; deploy refuses it. Run `wrangler d1 create`
|
|
198
|
+
and paste the id.
|
|
199
|
+
2. **DO class not exported.** Export `ShardDO` (and any generated container /
|
|
200
|
+
workflow class) from the worker entry; `lunora doctor` names the gap.
|
|
201
|
+
3. **Secrets only in `.dev.vars`.** They never reach production. Push or
|
|
202
|
+
`wrangler secret put` them before the first request.
|
|
203
|
+
4. **Dev and prod sharing resources.** Give each environment its own D1
|
|
204
|
+
database, R2 buckets and secrets; never point a dev worker at prod data.
|
|
205
|
+
5. **Uncommitted schema baseline.** Commit `lunora/.lunora-schema.json` (and
|
|
206
|
+
`lunora/migrations/.snapshot.json` if you use `migrate generate`).
|
|
207
|
+
`lunora/_generated/` is regenerated by deploy; templates git-ignore it.
|
|
208
|
+
6. **Using `cf dev` / `cf build` / `cf deploy`.** They read
|
|
209
|
+
`cloudflare.config.ts`, which Lunora never updates
|
|
210
|
+
([#964](https://github.com/anolilab/lunora/issues/964)). Use `lunora dev` /
|
|
211
|
+
`lunora deploy`; `cf` resource commands (zones, DNS, KV) are fine.
|
|
140
212
|
|
|
141
213
|
## Checklist
|
|
142
214
|
|
|
143
|
-
- [ ] `lunora doctor`
|
|
144
|
-
- [ ]
|
|
145
|
-
|
|
146
|
-
- [ ]
|
|
147
|
-
- [ ]
|
|
148
|
-
- [ ]
|
|
149
|
-
- [ ] Schema changes migrated; the drift gate is green (no `--allow-schema-drift`).
|
|
150
|
-
- [ ] `lunora deploy` succeeded; `--migrate` run if data backfills were pending.
|
|
215
|
+
- [ ] `lunora doctor` has no FAIL; `lunora verify --env <name>` passes in CI.
|
|
216
|
+
- [ ] D1 / R2 resources created per environment; real ids in `wrangler.jsonc`.
|
|
217
|
+
- [ ] Every DO / container / workflow `class_name` is exported by the worker entry.
|
|
218
|
+
- [ ] Production secrets set (`lunora env diff --env <name>` shows nothing local-only that prod needs).
|
|
219
|
+
- [ ] Breaking schema changes staged with a migration; drift gate green.
|
|
220
|
+
- [ ] `lunora deploy --env <name> --health-check` succeeded; `--migrate --migrate-yes` run if backfills were pending.
|