@lunora/codegen 1.0.0-alpha.12 → 1.0.0-alpha.13

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/dist/index.d.mts CHANGED
@@ -1626,5 +1626,52 @@ declare const validatorIrToJsonSchema: (validator: ValidatorIR) => JsonSchema;
1626
1626
  * the contract; clients switch on `error.code`. Kept sorted for stable output.
1627
1627
  */
1628
1628
  declare const LUNORA_ERROR_CODES: ReadonlyArray<string>;
1629
+ /**
1630
+ * Lunora-specific error→solution hints. A small rule table mapping the exact
1631
+ * messages Lunora throws — codegen/schema diagnostics, worker-entry export gaps,
1632
+ * and the runtime data-layer conflicts — to an actionable fix.
1633
+ *
1634
+ * This table is the single source of truth shared by every consumer that wants
1635
+ * to turn a raw Lunora error into a fix hint: the Vite error overlay
1636
+ * (`@lunora/vite`) renders the Markdown in the browser, and the standalone
1637
+ * `lunora dev` CLI prints it to the terminal. It lives in `@lunora/codegen`
1638
+ * because codegen owns most of the throw sites, so the hints stay next to the
1639
+ * code that produces the messages.
1640
+ *
1641
+ * Matching is on the **message text**. By the time a diagnostic reaches a
1642
+ * consumer it has often been flattened to a plain `{ message }` (the overlay
1643
+ * pushes codegen errors through `server.hot.send` with `name === "Error"`), so
1644
+ * the class identity is gone and the message is the only stable signal.
1645
+ *
1646
+ * Bodies are Markdown — the overlay renders them; the CLI prints them (lightly
1647
+ * de-marked) as-is.
1648
+ */
1649
+ /** A resolved hint for a recognized Lunora error. */
1650
+ interface LunoraSolution {
1651
+ /** Markdown body shown under the header. */
1652
+ body: string;
1653
+ /** Short header for the solution. */
1654
+ header: string;
1655
+ /** Stable id (used in DEBUG logs and tests). */
1656
+ id: string;
1657
+ }
1658
+ /** A single error→solution rule: a {@link LunoraSolution} plus its matcher. */
1659
+ interface LunoraSolutionRule extends LunoraSolution {
1660
+ /** True when this rule recognizes the error message. */
1661
+ test: (message: string) => boolean;
1662
+ }
1663
+ /**
1664
+ * The rules, ordered most- to least-specific: the dev-time codegen/schema rules
1665
+ * come first because they're the errors a developer hits while editing
1666
+ * `lunora/`, then the runtime data-layer conflicts that surface from the worker.
1667
+ * The first matching rule (in array order) wins.
1668
+ */
1669
+ declare const LUNORA_SOLUTION_RULES: ReadonlyArray<LunoraSolutionRule>;
1670
+ /**
1671
+ * Find the first Lunora solution whose rule matches `message`, or `undefined`
1672
+ * if none recognize it. Consumers turn the returned Markdown into their own
1673
+ * presentation (overlay panel, terminal hint, …).
1674
+ */
1675
+ declare const findLunoraSolution: (message: string) => LunoraSolution | undefined;
1629
1676
  declare const VERSION = "0.0.0";
1630
- export { type AuthApiCallIR, CONTAINERS_FILENAME, CodegenDiagnosticError, type CodegenOptions, type CodegenResult, type ContainerIR, type CronJobIR, type DriftChange, type EmitAppOptions, type FieldSnapshot, type FunctionIR, GENERATED_HEADER, type HttpRouteIR, type IndexIR, type IndexSnapshot, type InsertWriteIR, LUNORA_ERROR_CODES, type MaskProcedureIR, type MigrationIR, OPENRPC_VERSION, type OpenApiEmitInput, type OpenRpcEmitInput, type ProjectIR, QUEUES_FILENAME, type QueryReadIR, type QueueIR, type R2sqlCallIR, type RelationSnapshot, type RlsMetadataIR, type RlsPolicyIR, type RlsProcedureIR, type RlsRoleIR, SCHEMA_SNAPSHOT_FILENAME, SCHEMA_SNAPSHOT_VERSION, type SchemaDrift, type SchemaDriftDecision, type SchemaIR, type SchemaSnapshot, SchemaSnapshotParseError, type StorageRuleIR, type StorageRulesMetadataIR, type TableIR, type TableSnapshot, VERSION, type ValidatorIR, type VectorIndexIR, WORKFLOWS_FILENAME, type WorkflowIR, buildOpenApiDocument, buildOpenRpcDocument, buildSchemaSnapshot, createCodegenProject, diagnosticAt, diffSchemaSnapshots, discoverAuthApiCalls, discoverContainers, discoverCrons, discoverFunctions, discoverHttpRoutes, discoverInserts, discoverMaskProcedures, discoverMigrations, discoverNondeterministicCalls, discoverQueries, discoverQueues, discoverR2sqlCalls, discoverRlsMetadata, discoverRlsProcedures, discoverSchema, discoverStorageRulesMetadata, discoverWorkflows, emitApi, emitApp, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitOpenApi, emitOpenApiModule, emitOpenRpc, emitOpenRpcModule, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers, evaluateSchemaDrift, formatAdvisories, lintSchema, parseSchemaSnapshot, refreshCodegenProject, runCodegen, schemaFromIr, serializeSchemaSnapshot, validatorIrToJsonSchema };
1677
+ export { type AuthApiCallIR, CONTAINERS_FILENAME, CodegenDiagnosticError, type CodegenOptions, type CodegenResult, type ContainerIR, type CronJobIR, type DriftChange, type EmitAppOptions, type FieldSnapshot, type FunctionIR, GENERATED_HEADER, type HttpRouteIR, type IndexIR, type IndexSnapshot, type InsertWriteIR, LUNORA_ERROR_CODES, LUNORA_SOLUTION_RULES, type LunoraSolution, type LunoraSolutionRule, type MaskProcedureIR, type MigrationIR, OPENRPC_VERSION, type OpenApiEmitInput, type OpenRpcEmitInput, type ProjectIR, QUEUES_FILENAME, type QueryReadIR, type QueueIR, type R2sqlCallIR, type RelationSnapshot, type RlsMetadataIR, type RlsPolicyIR, type RlsProcedureIR, type RlsRoleIR, SCHEMA_SNAPSHOT_FILENAME, SCHEMA_SNAPSHOT_VERSION, type SchemaDrift, type SchemaDriftDecision, type SchemaIR, type SchemaSnapshot, SchemaSnapshotParseError, type StorageRuleIR, type StorageRulesMetadataIR, type TableIR, type TableSnapshot, VERSION, type ValidatorIR, type VectorIndexIR, WORKFLOWS_FILENAME, type WorkflowIR, buildOpenApiDocument, buildOpenRpcDocument, buildSchemaSnapshot, createCodegenProject, diagnosticAt, diffSchemaSnapshots, discoverAuthApiCalls, discoverContainers, discoverCrons, discoverFunctions, discoverHttpRoutes, discoverInserts, discoverMaskProcedures, discoverMigrations, discoverNondeterministicCalls, discoverQueries, discoverQueues, discoverR2sqlCalls, discoverRlsMetadata, discoverRlsProcedures, discoverSchema, discoverStorageRulesMetadata, discoverWorkflows, emitApi, emitApp, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitOpenApi, emitOpenApiModule, emitOpenRpc, emitOpenRpcModule, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers, evaluateSchemaDrift, findLunoraSolution, formatAdvisories, lintSchema, parseSchemaSnapshot, refreshCodegenProject, runCodegen, schemaFromIr, serializeSchemaSnapshot, validatorIrToJsonSchema };
package/dist/index.d.ts CHANGED
@@ -1626,5 +1626,52 @@ declare const validatorIrToJsonSchema: (validator: ValidatorIR) => JsonSchema;
1626
1626
  * the contract; clients switch on `error.code`. Kept sorted for stable output.
1627
1627
  */
1628
1628
  declare const LUNORA_ERROR_CODES: ReadonlyArray<string>;
1629
+ /**
1630
+ * Lunora-specific error→solution hints. A small rule table mapping the exact
1631
+ * messages Lunora throws — codegen/schema diagnostics, worker-entry export gaps,
1632
+ * and the runtime data-layer conflicts — to an actionable fix.
1633
+ *
1634
+ * This table is the single source of truth shared by every consumer that wants
1635
+ * to turn a raw Lunora error into a fix hint: the Vite error overlay
1636
+ * (`@lunora/vite`) renders the Markdown in the browser, and the standalone
1637
+ * `lunora dev` CLI prints it to the terminal. It lives in `@lunora/codegen`
1638
+ * because codegen owns most of the throw sites, so the hints stay next to the
1639
+ * code that produces the messages.
1640
+ *
1641
+ * Matching is on the **message text**. By the time a diagnostic reaches a
1642
+ * consumer it has often been flattened to a plain `{ message }` (the overlay
1643
+ * pushes codegen errors through `server.hot.send` with `name === "Error"`), so
1644
+ * the class identity is gone and the message is the only stable signal.
1645
+ *
1646
+ * Bodies are Markdown — the overlay renders them; the CLI prints them (lightly
1647
+ * de-marked) as-is.
1648
+ */
1649
+ /** A resolved hint for a recognized Lunora error. */
1650
+ interface LunoraSolution {
1651
+ /** Markdown body shown under the header. */
1652
+ body: string;
1653
+ /** Short header for the solution. */
1654
+ header: string;
1655
+ /** Stable id (used in DEBUG logs and tests). */
1656
+ id: string;
1657
+ }
1658
+ /** A single error→solution rule: a {@link LunoraSolution} plus its matcher. */
1659
+ interface LunoraSolutionRule extends LunoraSolution {
1660
+ /** True when this rule recognizes the error message. */
1661
+ test: (message: string) => boolean;
1662
+ }
1663
+ /**
1664
+ * The rules, ordered most- to least-specific: the dev-time codegen/schema rules
1665
+ * come first because they're the errors a developer hits while editing
1666
+ * `lunora/`, then the runtime data-layer conflicts that surface from the worker.
1667
+ * The first matching rule (in array order) wins.
1668
+ */
1669
+ declare const LUNORA_SOLUTION_RULES: ReadonlyArray<LunoraSolutionRule>;
1670
+ /**
1671
+ * Find the first Lunora solution whose rule matches `message`, or `undefined`
1672
+ * if none recognize it. Consumers turn the returned Markdown into their own
1673
+ * presentation (overlay panel, terminal hint, …).
1674
+ */
1675
+ declare const findLunoraSolution: (message: string) => LunoraSolution | undefined;
1629
1676
  declare const VERSION = "0.0.0";
1630
- export { type AuthApiCallIR, CONTAINERS_FILENAME, CodegenDiagnosticError, type CodegenOptions, type CodegenResult, type ContainerIR, type CronJobIR, type DriftChange, type EmitAppOptions, type FieldSnapshot, type FunctionIR, GENERATED_HEADER, type HttpRouteIR, type IndexIR, type IndexSnapshot, type InsertWriteIR, LUNORA_ERROR_CODES, type MaskProcedureIR, type MigrationIR, OPENRPC_VERSION, type OpenApiEmitInput, type OpenRpcEmitInput, type ProjectIR, QUEUES_FILENAME, type QueryReadIR, type QueueIR, type R2sqlCallIR, type RelationSnapshot, type RlsMetadataIR, type RlsPolicyIR, type RlsProcedureIR, type RlsRoleIR, SCHEMA_SNAPSHOT_FILENAME, SCHEMA_SNAPSHOT_VERSION, type SchemaDrift, type SchemaDriftDecision, type SchemaIR, type SchemaSnapshot, SchemaSnapshotParseError, type StorageRuleIR, type StorageRulesMetadataIR, type TableIR, type TableSnapshot, VERSION, type ValidatorIR, type VectorIndexIR, WORKFLOWS_FILENAME, type WorkflowIR, buildOpenApiDocument, buildOpenRpcDocument, buildSchemaSnapshot, createCodegenProject, diagnosticAt, diffSchemaSnapshots, discoverAuthApiCalls, discoverContainers, discoverCrons, discoverFunctions, discoverHttpRoutes, discoverInserts, discoverMaskProcedures, discoverMigrations, discoverNondeterministicCalls, discoverQueries, discoverQueues, discoverR2sqlCalls, discoverRlsMetadata, discoverRlsProcedures, discoverSchema, discoverStorageRulesMetadata, discoverWorkflows, emitApi, emitApp, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitOpenApi, emitOpenApiModule, emitOpenRpc, emitOpenRpcModule, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers, evaluateSchemaDrift, formatAdvisories, lintSchema, parseSchemaSnapshot, refreshCodegenProject, runCodegen, schemaFromIr, serializeSchemaSnapshot, validatorIrToJsonSchema };
1677
+ export { type AuthApiCallIR, CONTAINERS_FILENAME, CodegenDiagnosticError, type CodegenOptions, type CodegenResult, type ContainerIR, type CronJobIR, type DriftChange, type EmitAppOptions, type FieldSnapshot, type FunctionIR, GENERATED_HEADER, type HttpRouteIR, type IndexIR, type IndexSnapshot, type InsertWriteIR, LUNORA_ERROR_CODES, LUNORA_SOLUTION_RULES, type LunoraSolution, type LunoraSolutionRule, type MaskProcedureIR, type MigrationIR, OPENRPC_VERSION, type OpenApiEmitInput, type OpenRpcEmitInput, type ProjectIR, QUEUES_FILENAME, type QueryReadIR, type QueueIR, type R2sqlCallIR, type RelationSnapshot, type RlsMetadataIR, type RlsPolicyIR, type RlsProcedureIR, type RlsRoleIR, SCHEMA_SNAPSHOT_FILENAME, SCHEMA_SNAPSHOT_VERSION, type SchemaDrift, type SchemaDriftDecision, type SchemaIR, type SchemaSnapshot, SchemaSnapshotParseError, type StorageRuleIR, type StorageRulesMetadataIR, type TableIR, type TableSnapshot, VERSION, type ValidatorIR, type VectorIndexIR, WORKFLOWS_FILENAME, type WorkflowIR, buildOpenApiDocument, buildOpenRpcDocument, buildSchemaSnapshot, createCodegenProject, diagnosticAt, diffSchemaSnapshots, discoverAuthApiCalls, discoverContainers, discoverCrons, discoverFunctions, discoverHttpRoutes, discoverInserts, discoverMaskProcedures, discoverMigrations, discoverNondeterministicCalls, discoverQueries, discoverQueues, discoverR2sqlCalls, discoverRlsMetadata, discoverRlsProcedures, discoverSchema, discoverStorageRulesMetadata, discoverWorkflows, emitApi, emitApp, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitOpenApi, emitOpenApiModule, emitOpenRpc, emitOpenRpcModule, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers, evaluateSchemaDrift, findLunoraSolution, formatAdvisories, lintSchema, parseSchemaSnapshot, refreshCodegenProject, runCodegen, schemaFromIr, serializeSchemaSnapshot, validatorIrToJsonSchema };
package/dist/index.mjs CHANGED
@@ -24,6 +24,7 @@ export { SCHEMA_SNAPSHOT_FILENAME, createCodegenProject, refreshCodegenProject,
24
24
  export { SCHEMA_SNAPSHOT_VERSION, SchemaSnapshotParseError, buildSchemaSnapshot, diffSchemaSnapshots, evaluateSchemaDrift, parseSchemaSnapshot, serializeSchemaSnapshot } from './packem_shared/SCHEMA_SNAPSHOT_VERSION-wWGP2_5E.mjs';
25
25
  export { schemaFromIr } from './packem_shared/schemaFromIr-DTYsLBaA.mjs';
26
26
  export { LUNORA_ERROR_CODES, validatorIrToJsonSchema } from './packem_shared/LUNORA_ERROR_CODES-CySpQPD3.mjs';
27
+ export { LUNORA_SOLUTION_RULES, findLunoraSolution } from './packem_shared/LUNORA_SOLUTION_RULES-BTejmZp-.mjs';
27
28
 
28
29
  const VERSION = "0.0.0";
29
30
 
@@ -0,0 +1,131 @@
1
+ const LUNORA_SOLUTION_RULES = [
2
+ {
3
+ body: [
4
+ "Lunora codegen couldn't find a schema to generate from.",
5
+ "",
6
+ "Create `lunora/schema.ts` exporting a `defineSchema(...)` call:",
7
+ "",
8
+ "```ts",
9
+ 'import { defineSchema, defineTable, v } from "@lunora/server";',
10
+ "",
11
+ "export default defineSchema({",
12
+ " messages: defineTable({ body: v.string() }),",
13
+ "});",
14
+ "```",
15
+ "",
16
+ "Or run `lunora init` to scaffold Lunora (a sample `lunora/schema.ts` included) into your app."
17
+ ].join("\n"),
18
+ header: "No Lunora schema found",
19
+ id: "lunora-schema-missing",
20
+ test: (message) => message.includes("defineSchema() not found") || message.includes("schema.ts not found at")
21
+ },
22
+ {
23
+ body: [
24
+ "`defineSchema(...)` must be called with an **inline object literal** mapping table names to `defineTable(...)`:",
25
+ "",
26
+ "```ts",
27
+ "export default defineSchema({",
28
+ " todos: defineTable({ title: v.string(), done: v.boolean() }),",
29
+ "});",
30
+ "```",
31
+ "",
32
+ "Codegen reads the schema statically, so it can't follow a variable or a spread — pass the object literal directly."
33
+ ].join("\n"),
34
+ header: "`defineSchema()` needs an inline object literal",
35
+ id: "lunora-schema-not-object-literal",
36
+ test: (message) => message.includes("defineSchema() expects an object literal")
37
+ },
38
+ {
39
+ body: [
40
+ "This table name collides with a built-in `ctx.db` member, so the generated client can't expose it.",
41
+ "",
42
+ "Rename the table to anything that isn't a reserved name (the error lists them) — e.g. `userAccounts` instead of `insert`."
43
+ ].join("\n"),
44
+ header: "Table name is reserved",
45
+ id: "lunora-table-reserved",
46
+ test: (message) => message.includes("is reserved") && message.includes("ctx.db")
47
+ },
48
+ {
49
+ body: [
50
+ "Two tables resolve to the same name — usually a base table and a schema **extension** both defining it.",
51
+ "",
52
+ "Rename one of them, or drop the duplicate from the extension. Each table name must be unique across `defineSchema(...)` and every `.extend(...)`."
53
+ ].join("\n"),
54
+ header: "Duplicate table name",
55
+ id: "lunora-table-duplicate",
56
+ // Anchor on `.extend(` — the only Lunora throw for this is
57
+ // `defineSchema(...).extend(...): table "x" already exists …`. Matching a
58
+ // bare "already exists"/"extension" pair would false-positive on
59
+ // unrelated forwarded errors (e.g. a "file already exists" + "extension").
60
+ test: (message) => message.includes("already exists") && message.includes(".extend(")
61
+ },
62
+ {
63
+ body: [
64
+ '`.jurisdiction(...)` accepts only a **string literal** of `"eu"`, `"us"`, or `"fedramp"`:',
65
+ "",
66
+ "```ts",
67
+ 'defineSchema({ /* … */ }).jurisdiction("eu");',
68
+ "```"
69
+ ].join("\n"),
70
+ header: "Invalid `.jurisdiction(...)` value",
71
+ id: "lunora-jurisdiction",
72
+ test: (message) => message.includes("unknown jurisdiction") || message.includes("jurisdiction") && message.includes('"eu", "us", or "fedramp"')
73
+ },
74
+ {
75
+ body: [
76
+ "The `unique` flag on an index must be a **literal** `true` or `false`, not a computed value — codegen needs to read it statically:",
77
+ "",
78
+ "```ts",
79
+ 'defineTable({ email: v.string() }).index("by_email", ["email"], { unique: true });',
80
+ "```"
81
+ ].join("\n"),
82
+ header: "`unique` must be a literal",
83
+ id: "lunora-unique-literal",
84
+ test: (message) => message.includes("must be a literal") && message.includes("unique")
85
+ },
86
+ {
87
+ body: [
88
+ "A declared container/workflow class isn't re-exported by your worker entry, so `wrangler deploy` would reject it.",
89
+ "",
90
+ "Add the generated re-export shown in the error to your worker entry (e.g. `src/index.ts`):",
91
+ "",
92
+ "```ts",
93
+ 'export * from "./lunora/_generated/containers";',
94
+ "```"
95
+ ].join("\n"),
96
+ header: "Binding not exported by your worker entry",
97
+ id: "lunora-worker-entry-export-gap",
98
+ test: (message) => message.includes("not exported by your worker entry")
99
+ },
100
+ {
101
+ body: [
102
+ "A row with the same value already exists in a `unique` index.",
103
+ "",
104
+ "- If you meant to upsert, use `ctx.db.<table>().upsert(...)` (or `.patch(...)` an existing row) instead of `.insert(...)`.",
105
+ `- Otherwise pick a value that isn't already taken, and consider surfacing a friendly "already exists" message to the user.`
106
+ ].join("\n"),
107
+ header: "Unique constraint violation",
108
+ id: "lunora-runtime-unique",
109
+ test: (message) => message.includes("unique constraint violation on")
110
+ },
111
+ {
112
+ body: [
113
+ "Another write changed this row while your mutation was running (optimistic concurrency conflict).",
114
+ "",
115
+ "Re-read the row and retry the mutation with the fresh value. Lunora serializes a DO's mutations, so a persistent conflict usually means the handler conflicts **with itself** (e.g. a trigger or cascade touching the same row) — split that work rather than adding a retry loop."
116
+ ].join("\n"),
117
+ header: "Optimistic concurrency conflict",
118
+ id: "lunora-runtime-occ",
119
+ test: (message) => message.includes("optimistic concurrency conflict")
120
+ }
121
+ ];
122
+ const findLunoraSolution = (message) => {
123
+ for (const rule of LUNORA_SOLUTION_RULES) {
124
+ if (rule.test(message)) {
125
+ return { body: rule.body, header: rule.header, id: rule.id };
126
+ }
127
+ }
128
+ return void 0;
129
+ };
130
+
131
+ export { LUNORA_SOLUTION_RULES, findLunoraSolution };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/codegen",
3
- "version": "1.0.0-alpha.12",
3
+ "version": "1.0.0-alpha.13",
4
4
  "description": "Code generator for Lunora: emits _generated/{api,server,dataModel}.ts from your schema",
5
5
  "keywords": [
6
6
  "cloudflare",