neoorm 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +223 -12
  2. package/dist/bin/neoorm.js +50 -29
  3. package/dist/bin/neoorm.js.map +1 -1
  4. package/dist/codegen/diff-manifest.d.ts +4 -1
  5. package/dist/codegen/diff-manifest.d.ts.map +1 -1
  6. package/dist/codegen/diff-manifest.js +85 -4
  7. package/dist/codegen/diff-manifest.js.map +1 -1
  8. package/dist/codegen/generate-summary.d.ts +21 -0
  9. package/dist/codegen/generate-summary.d.ts.map +1 -0
  10. package/dist/codegen/generate-summary.js +101 -0
  11. package/dist/codegen/generate-summary.js.map +1 -0
  12. package/dist/codegen/generate.d.ts +6 -1
  13. package/dist/codegen/generate.d.ts.map +1 -1
  14. package/dist/codegen/generate.js +21 -8
  15. package/dist/codegen/generate.js.map +1 -1
  16. package/dist/codegen/manifest-relations.d.ts.map +1 -1
  17. package/dist/codegen/manifest-relations.js +9 -2
  18. package/dist/codegen/manifest-relations.js.map +1 -1
  19. package/dist/codegen/schema-to-manifest.d.ts +4 -1
  20. package/dist/codegen/schema-to-manifest.d.ts.map +1 -1
  21. package/dist/codegen/schema-to-manifest.js +58 -12
  22. package/dist/codegen/schema-to-manifest.js.map +1 -1
  23. package/dist/config.d.ts +1 -0
  24. package/dist/config.d.ts.map +1 -1
  25. package/dist/config.js.map +1 -1
  26. package/dist/dialect/postgres.d.ts +3 -0
  27. package/dist/dialect/postgres.d.ts.map +1 -1
  28. package/dist/dialect/postgres.js +51 -1
  29. package/dist/dialect/postgres.js.map +1 -1
  30. package/dist/dialect/types.d.ts +12 -1
  31. package/dist/dialect/types.d.ts.map +1 -1
  32. package/dist/index.d.ts +5 -4
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +3 -3
  35. package/dist/index.js.map +1 -1
  36. package/dist/introspect/queries.d.ts +5 -0
  37. package/dist/introspect/queries.d.ts.map +1 -1
  38. package/dist/introspect/queries.js +17 -0
  39. package/dist/introspect/queries.js.map +1 -1
  40. package/dist/introspect/to-manifest.d.ts.map +1 -1
  41. package/dist/introspect/to-manifest.js +58 -14
  42. package/dist/introspect/to-manifest.js.map +1 -1
  43. package/dist/migrate/runner.d.ts +21 -0
  44. package/dist/migrate/runner.d.ts.map +1 -1
  45. package/dist/migrate/runner.js +99 -6
  46. package/dist/migrate/runner.js.map +1 -1
  47. package/dist/plugins/builtin.d.ts +35 -2
  48. package/dist/plugins/builtin.d.ts.map +1 -1
  49. package/dist/plugins/builtin.js +312 -1
  50. package/dist/plugins/builtin.js.map +1 -1
  51. package/dist/plugins/registry.d.ts.map +1 -1
  52. package/dist/plugins/registry.js +3 -1
  53. package/dist/plugins/registry.js.map +1 -1
  54. package/dist/runtime/client.d.ts +3 -0
  55. package/dist/runtime/client.d.ts.map +1 -1
  56. package/dist/runtime/client.js +11 -12
  57. package/dist/runtime/client.js.map +1 -1
  58. package/dist/runtime/executor.d.ts +1 -0
  59. package/dist/runtime/executor.d.ts.map +1 -1
  60. package/dist/runtime/executor.js +27 -4
  61. package/dist/runtime/executor.js.map +1 -1
  62. package/dist/runtime/query/compile.d.ts +6 -1
  63. package/dist/runtime/query/compile.d.ts.map +1 -1
  64. package/dist/runtime/query/compile.js +38 -6
  65. package/dist/runtime/query/compile.js.map +1 -1
  66. package/dist/runtime/query/create.d.ts +7 -0
  67. package/dist/runtime/query/create.d.ts.map +1 -1
  68. package/dist/runtime/query/create.js +50 -104
  69. package/dist/runtime/query/create.js.map +1 -1
  70. package/dist/runtime/query/delete.d.ts.map +1 -1
  71. package/dist/runtime/query/delete.js +9 -3
  72. package/dist/runtime/query/delete.js.map +1 -1
  73. package/dist/runtime/query/find.d.ts.map +1 -1
  74. package/dist/runtime/query/find.js +15 -11
  75. package/dist/runtime/query/find.js.map +1 -1
  76. package/dist/runtime/query/primary-key.d.ts +11 -1
  77. package/dist/runtime/query/primary-key.d.ts.map +1 -1
  78. package/dist/runtime/query/primary-key.js +55 -0
  79. package/dist/runtime/query/primary-key.js.map +1 -1
  80. package/dist/runtime/query/relation-writes.d.ts +24 -0
  81. package/dist/runtime/query/relation-writes.d.ts.map +1 -0
  82. package/dist/runtime/query/relation-writes.js +325 -0
  83. package/dist/runtime/query/relation-writes.js.map +1 -0
  84. package/dist/runtime/query/unique.d.ts.map +1 -1
  85. package/dist/runtime/query/unique.js +1 -5
  86. package/dist/runtime/query/unique.js.map +1 -1
  87. package/dist/runtime/query/update.d.ts.map +1 -1
  88. package/dist/runtime/query/update.js +45 -28
  89. package/dist/runtime/query/update.js.map +1 -1
  90. package/dist/runtime/types.d.ts +3 -2
  91. package/dist/runtime/types.d.ts.map +1 -1
  92. package/dist/schema/column-where.d.ts +18 -15
  93. package/dist/schema/column-where.d.ts.map +1 -1
  94. package/dist/schema/column.d.ts +2 -2
  95. package/dist/schema/column.d.ts.map +1 -1
  96. package/dist/schema/column.js +1 -1
  97. package/dist/schema/column.js.map +1 -1
  98. package/dist/schema/index.d.ts +4 -4
  99. package/dist/schema/index.d.ts.map +1 -1
  100. package/dist/schema/index.js +1 -1
  101. package/dist/schema/index.js.map +1 -1
  102. package/dist/schema/nested-relation-types.d.ts +60 -0
  103. package/dist/schema/nested-relation-types.d.ts.map +1 -0
  104. package/dist/schema/nested-relation-types.js +2 -0
  105. package/dist/schema/nested-relation-types.js.map +1 -0
  106. package/dist/schema/relation-types.d.ts +122 -22
  107. package/dist/schema/relation-types.d.ts.map +1 -1
  108. package/dist/schema/types.d.ts +27 -38
  109. package/dist/schema/types.d.ts.map +1 -1
  110. package/package.json +1 -1
package/README.md CHANGED
@@ -43,6 +43,7 @@ export default defineConfig({
43
43
  datasource: {
44
44
  provider: "postgresql",
45
45
  url: process.env.DATABASE_URL!,
46
+ enum: "check", // "check" (default) | "union" | "native"
46
47
  },
47
48
  });
48
49
  ```
@@ -81,20 +82,118 @@ Column field names use camelCase in TypeScript. By default, SQL column names are
81
82
 
82
83
  ### Column types
83
84
 
84
- | Builder | SQL type | Notes |
85
- |---------|----------|-------|
86
- | `id.primary()` | `TEXT` | App-generated string IDs (e.g. `user_a1b2c3d4`) |
87
- | `uuid()` | `UUID` | Defaults to UUID v7; pass `{ version: 4 }` for v4 |
88
- | `uuid().primary()` | `UUID` | Primary key; auto-generated on create if omitted |
89
- | `text()` | `TEXT` | |
90
- | `bool()` | `BOOLEAN` | |
91
- | `int()` | `INTEGER` | |
92
- | `timestamp()` | `TIMESTAMPTZ` | Use `.defaultNow()` for `DEFAULT NOW()` |
85
+ | Builder | SQL type | TypeScript | Notes |
86
+ |---------|----------|------------|-------|
87
+ | `id.primary()` | `TEXT` | `string` | App-generated string IDs (e.g. `user_a1b2c3d4`) |
88
+ | `uuid()` | `UUID` | `string` | Defaults to UUID v7; pass `{ version: 4 }` for v4 |
89
+ | `uuid().primary()` | `UUID` | `string` | Primary key; auto-generated on create if omitted |
90
+ | `serial()` | `INTEGER GENERATED BY DEFAULT AS IDENTITY` | `number` | Auto-increment; omit on insert, DB assigns via `RETURNING` |
91
+ | `serial().primary()` | same | `number` | Integer PK with DB-generated values |
92
+ | `text()` | `TEXT` | `string \| null` | |
93
+ | `bool()` | `BOOLEAN` | `boolean \| null` | |
94
+ | `int()` | `INTEGER` | `number \| null` | |
95
+ | `timestamp()` | `TIMESTAMPTZ` | `Date \| null` | Use `.defaultNow()` for `DEFAULT NOW()` |
96
+ | `json()` | `JSON` | `unknown \| null` | Generic: `json<MyType>()` |
97
+ | `jsonb()` | `JSONB` | `unknown \| null` | Generic: `jsonb<MyType>()` |
98
+ | `decimal()` / `numeric()` | `NUMERIC` or `NUMERIC(p,s)` | `string \| null` | Use strings to avoid float precision loss |
99
+ | `enumType(["a", "b"])` | mode-dependent | union literals | See [Enum columns](#enum-columns) |
100
+ | `bytea()` | `BYTEA` | `Buffer \| null` | Binary data |
101
+ | `textArray()` | `TEXT[]` | `string[] \| null` | |
102
+ | `intArray()` | `INTEGER[]` | `number[] \| null` | |
103
+ | `citext()` | `CITEXT` | `string \| null` | Case-insensitive text; requires `citext` extension |
93
104
 
94
105
  All column builders support `.notNull()`, `.unique()`, `.default(value)`, `.defaultNow()`, `.primary()`, and `.map(name)`.
95
106
 
96
107
  Foreign keys use `fk("target_table.target_column", { as, inverse, nullable?, onDelete? })`.
97
108
 
109
+ ### Enum columns
110
+
111
+ Define allowed values in the schema:
112
+
113
+ ```ts
114
+ import { enumType, table } from "neoorm/schema";
115
+
116
+ posts: table("posts", {
117
+ status: enumType(["draft", "published", "archived"] as const)
118
+ .notNull()
119
+ .default("draft"),
120
+ })
121
+ ```
122
+
123
+ Control how enums are stored via `datasource.enum` in `neoorm.config.ts`:
124
+
125
+ | Mode | SQL | DB enforcement |
126
+ |------|-----|----------------|
127
+ | `check` (default) | `TEXT` + `CHECK (...)` | yes |
128
+ | `union` | `TEXT` | no (TypeScript union only) |
129
+ | `native` | Postgres `CREATE TYPE ... AS ENUM` | yes |
130
+
131
+ ```ts
132
+ export default defineConfig({
133
+ schema: "./schema.ts",
134
+ out: "./neoorm",
135
+ datasource: {
136
+ provider: "postgresql",
137
+ url: process.env.DATABASE_URL!,
138
+ enum: "check", // or "union" | "native"
139
+ },
140
+ });
141
+ ```
142
+
143
+ Optional custom SQL type name for native mode: `enumType(["draft", "published"], { name: "post_status" })`.
144
+
145
+ Query and mutate enum columns like strings with compile-time union checking:
146
+
147
+ ```ts
148
+ await db.posts.findMany({ where: { status: "published" } });
149
+ await db.posts.create({ data: { title: "Hello", status: "draft" } });
150
+ ```
151
+
152
+ ### JSON and decimal columns
153
+
154
+ ```ts
155
+ posts: table("posts", {
156
+ metadata: jsonb<{ tags: string[]; featured?: boolean }>(),
157
+ price: decimal({ precision: 10, scale: 2 }).default("0.00"),
158
+ })
159
+ ```
160
+
161
+ ```ts
162
+ // jsonb — equality match on the full object
163
+ await db.posts.findMany({
164
+ where: { metadata: { featured: true, category: "engineering" } },
165
+ });
166
+
167
+ // decimal — compare as strings
168
+ await db.posts.findMany({
169
+ where: { price: { gte: "9.99", lte: "49.99" } },
170
+ });
171
+
172
+ await db.posts.create({
173
+ data: {
174
+ title: "Premium",
175
+ price: "19.99",
176
+ metadata: { featured: true, tags: ["orm"] },
177
+ },
178
+ });
179
+ ```
180
+
181
+ ### Serial primary keys
182
+
183
+ ```ts
184
+ items: table("items", {
185
+ id: serial().primary(),
186
+ name: text().notNull(),
187
+ })
188
+ ```
189
+
190
+ Omit `id` on insert — the database assigns it and `RETURNING` populates the result:
191
+
192
+ ```ts
193
+ const item = await db.items.create({ data: { name: "Widget" } });
194
+ // item.id is the DB-generated integer
195
+ ```
196
+
98
197
  ### UUID columns
99
198
 
100
199
  ```ts
@@ -158,6 +257,55 @@ manyToMany(schema.posts, schema.tags, {
158
257
  });
159
258
  ```
160
259
 
260
+ ## Relation writes
261
+
262
+ `create` and `update` accept nested relation writes alongside scalar fields. Relation-only updates are supported (no scalar `SET` required).
263
+
264
+ | Relation kind | Operations |
265
+ |---------------|------------|
266
+ | **To-one** (outgoing FK) | `connect`, `create`, `disconnect` (nullable FK only) |
267
+ | **One-to-many** (inverse) | `create`, `connect`, `disconnect`, `set` |
268
+ | **Many-to-many** | `connect`, `connectOrCreate`, `disconnect`, `set` |
269
+
270
+ ```ts
271
+ // To-one on update
272
+ await db.posts.update({
273
+ where: { id: postId },
274
+ data: { author: { connect: { id: userId } } },
275
+ });
276
+
277
+ // Nested create on one-to-many (full nested relation writes inside create items)
278
+ await db.posts.update({
279
+ where: { id: postId },
280
+ data: {
281
+ comments: {
282
+ create: [{ body: "Hi", author: { connect: { id: userId } } }],
283
+ connect: [{ id: commentId }],
284
+ disconnect: [{ id: oldCommentId }], // or `true` to unlink all
285
+ set: [{ id: commentId }], // replace all links
286
+ },
287
+ },
288
+ });
289
+
290
+ // M2M on create or update
291
+ await db.posts.update({
292
+ where: { id: postId },
293
+ data: {
294
+ tags: {
295
+ connect: [{ id: tagId }],
296
+ set: [{ id: tagId }],
297
+ connectOrCreate: [
298
+ { where: { slug: "orm" }, create: { slug: "orm", name: "ORM" } },
299
+ ],
300
+ },
301
+ },
302
+ });
303
+ ```
304
+
305
+ Within a single relation field, operations run in order: `disconnect` → `set` → `connect` / `connectOrCreate` → `create`. Mixing `set` with `connect` or `create` is discouraged — `set` replaces the full link set.
306
+
307
+ `updateMany` does not support relation writes. Nested `delete` on relations is not supported yet.
308
+
161
309
  ## Where clauses
162
310
 
163
311
  `findMany`, `findFirst`, `findUnique`, `count`, `update`, `updateMany`, `delete`, and `deleteMany` all accept a typed `where` argument.
@@ -266,14 +414,28 @@ const [user, post] = await db.$transaction([
266
414
  (tx) => tx.posts.create({ data: { title: "Hello" } }),
267
415
  ]);
268
416
 
269
- // Options
417
+ // Options (outermost transaction only)
270
418
  await db.$transaction(fn, {
271
419
  isolationLevel: "Serializable", // ReadUncommitted | ReadCommitted | RepeatableRead | Serializable
272
420
  readOnly: true,
273
421
  });
422
+
423
+ // Nested $transaction uses PostgreSQL savepoints on the same connection.
424
+ // A nested failure rolls back only that block; the outer transaction can continue.
425
+ await db.$transaction(async (tx) => {
426
+ await tx.users.create({ data: { email: "outer@example.com" } });
427
+
428
+ await tx.$transaction(async (nested) => {
429
+ await nested.posts.create({
430
+ data: { title: "Nested", body: "...", authorId: "user_1" },
431
+ });
432
+ }).catch(() => undefined);
433
+
434
+ // Outer writes are kept even if the nested block failed.
435
+ });
274
436
  ```
275
437
 
276
- Nested `create` calls inside a transaction do not start a separate transaction.
438
+ Nested `create` calls inside a transaction do not start a separate transaction. Nested `$transaction` calls use savepoints; `readOnly` and `isolationLevel` apply only to the outermost `BEGIN`.
277
439
 
278
440
  ## CLI
279
441
 
@@ -282,10 +444,43 @@ Nested `create` calls inside a transaction do not start a separate transaction.
282
444
  | `neoorm generate` | Emit manifest, typed client, models, includes, and migrations |
283
445
  | `neoorm migrate dev` | Apply pending migrations, then generate a new one if the schema changed |
284
446
  | `neoorm migrate deploy` | Apply pending migrations |
447
+ | `neoorm migrate status` | List applied vs pending migrations |
448
+ | `neoorm migrate reset --force` | Drop public schema and re-apply migrations (local dev) |
285
449
  | `neoorm db push` | Push the current snapshot schema to the database |
286
450
  | `neoorm db pull` | Introspect the database into a schema file |
287
451
 
288
- `generate` always rewrites generated TypeScript files. Migration SQL is created only when the schema diff produces changes (new tables/columns, column renames via `.map()`).
452
+ ### Generate outcomes
453
+
454
+ `neoorm generate` always refreshes generated TypeScript files (`client.ts`, `manifest.ts`, `models.ts`, etc.). It prints one of four outcomes:
455
+
456
+ | Outcome | Meaning |
457
+ |---------|---------|
458
+ | **Schema unchanged** | Snapshot hash matches — no manifest or migration changes |
459
+ | **Client regenerated** | Manifest changed but no database DDL was needed (e.g. `enumMode`, relation metadata) |
460
+ | **Migration created** | New `migrations/<timestamp>/migration.sql` written |
461
+ | **Migration blocked** | Destructive or manual changes prevented writing SQL |
462
+
463
+ When migration is blocked or skipped, the CLI explains why — for example unsupported type casts (`alter_column_type_manual`), enum value changes, or destructive drops. Re-run with `--accept-data-loss` to include destructive DDL, or write a manual migration for unsupported type changes.
464
+
465
+ ```bash
466
+ neoorm generate --accept-data-loss
467
+ ```
468
+
469
+ ### Migration status and reset
470
+
471
+ ```bash
472
+ neoorm migrate status
473
+ ```
474
+
475
+ Shows applied migrations (with timestamps), pending folders on disk, and warnings for drift (applied in DB but missing on disk).
476
+
477
+ ```bash
478
+ neoorm migrate reset --force
479
+ ```
480
+
481
+ Drops the `public` schema and re-applies all migrations from disk. Requires `--force`. Use `--skip-apply` to only drop the schema without re-applying.
482
+
483
+ `generate` creates migration SQL only when the schema diff produces DDL changes (new tables/columns, column renames via `.map()`, etc.).
289
484
 
290
485
  ## Plugins
291
486
 
@@ -319,6 +514,22 @@ await db.places.findMany({
319
514
 
320
515
  PostGIS columns are stored as geometry/geography in PostgreSQL and exposed as GeoJSON in TypeScript.
321
516
 
517
+ ### Citext
518
+
519
+ `citext()` is registered as a separate plugin that enables the `citext` extension when used in a schema:
520
+
521
+ ```ts
522
+ import { citext, table } from "neoorm/schema";
523
+
524
+ users: table("users", {
525
+ email: citext().notNull().unique(),
526
+ })
527
+ ```
528
+
529
+ ## Examples
530
+
531
+ The [blog example](examples/blog/schema.ts) demonstrates relations, many-to-many, `jsonb`, `decimal`, and `enumType` columns. See [queries.example.ts](examples/blog/queries.example.ts) for typed queries and mutations using those types.
532
+
322
533
  ## API surface
323
534
 
324
535
  | Import | Purpose |
@@ -3,8 +3,8 @@ import { Command } from "commander";
3
3
  import { join, resolve } from "node:path";
4
4
  import { Pool } from "pg";
5
5
  import { loadConfig } from "../config.js";
6
- import { generateFromSchema } from "../codegen/generate.js";
7
- import { migrateDeploy, dbPush, dbPushWarnings } from "../migrate/runner.js";
6
+ import { generateFromSchema, formatGenerateSummary } from "../codegen/generate.js";
7
+ import { migrateDeploy, migrateReset, migrateStatus, formatMigrateStatus, dbPush, dbPushWarnings, } from "../migrate/runner.js";
8
8
  import { introspectPostgres } from "../introspect/pull.js";
9
9
  import { writeFile } from "node:fs/promises";
10
10
  const program = new Command();
@@ -21,22 +21,12 @@ program
21
21
  const config = await loadConfig(cwd);
22
22
  const schemaPath = resolve(cwd, config.schema);
23
23
  const outDir = resolve(cwd, config.out);
24
- const { migrationName, schemaChanged, warnings, destructiveBlocked } = await generateFromSchema(schemaPath, outDir, {
24
+ const { warnings, summary } = await generateFromSchema(schemaPath, outDir, {
25
25
  ...(options.acceptDataLoss ? { acceptDataLoss: true } : {}),
26
+ ...(config.datasource.enum ? { enumMode: config.datasource.enum } : {}),
26
27
  });
27
- console.log(`Generated client at ${outDir}/client.ts`);
28
- console.log(`Generated manifest at ${outDir}/manifest.ts`);
29
- if (migrationName) {
30
- console.log(`Created migration: ${migrationName}`);
31
- }
32
- else if (destructiveBlocked) {
33
- console.log("Destructive schema changes detected — no migration written");
34
- }
35
- else if (schemaChanged) {
36
- console.log("Manifest updated (no migration SQL needed)");
37
- }
38
- else {
39
- console.log("No schema changes detected");
28
+ for (const line of formatGenerateSummary(summary, outDir)) {
29
+ console.log(line);
40
30
  }
41
31
  for (const warning of warnings) {
42
32
  console.warn(`Warning: ${warning}`);
@@ -45,8 +35,10 @@ program
45
35
  program
46
36
  .command("migrate")
47
37
  .description("Run migrations")
48
- .argument("[subcommand]", "dev | deploy")
38
+ .argument("[subcommand]", "dev | deploy | status | reset")
49
39
  .option("--accept-data-loss", "Include destructive schema changes in generated migrations")
40
+ .option("--force", "Required for reset — drops the public schema and all data")
41
+ .option("--skip-apply", "With reset, only drop schema without re-applying migrations")
50
42
  .action(async (subcommand, options) => {
51
43
  const cwd = process.cwd();
52
44
  const config = await loadConfig(cwd);
@@ -54,6 +46,33 @@ program
54
46
  const migrationsDir = join(outDir, "migrations");
55
47
  const pool = new Pool({ connectionString: config.datasource.url });
56
48
  try {
49
+ if (subcommand === "status") {
50
+ const status = await migrateStatus(pool, migrationsDir);
51
+ for (const line of formatMigrateStatus(status, migrationsDir)) {
52
+ console.log(line);
53
+ }
54
+ return;
55
+ }
56
+ if (subcommand === "reset") {
57
+ const { reapplied } = await migrateReset(pool, migrationsDir, {
58
+ force: options.force ?? false,
59
+ ...(options.skipApply ? { skipApply: true } : {}),
60
+ });
61
+ console.log("✓ Database schema reset (public schema dropped and recreated)");
62
+ if (options.skipApply) {
63
+ console.log(" Skipped re-applying migrations (--skip-apply)");
64
+ }
65
+ else if (reapplied.length === 0) {
66
+ console.log(" No migrations on disk to apply");
67
+ }
68
+ else {
69
+ console.log(` Re-applied ${reapplied.length} migration(s):`);
70
+ for (const name of reapplied) {
71
+ console.log(` - ${name}`);
72
+ }
73
+ }
74
+ return;
75
+ }
57
76
  if (subcommand === "deploy" || subcommand === "dev") {
58
77
  const applied = await migrateDeploy(pool, migrationsDir);
59
78
  if (applied.length === 0) {
@@ -66,27 +85,28 @@ program
66
85
  }
67
86
  }
68
87
  if (subcommand === "dev") {
69
- const { generateFromSchema } = await import("../codegen/generate.js");
70
88
  const schemaPath = resolve(cwd, config.schema);
71
- const { migrationName, warnings, destructiveBlocked } = await generateFromSchema(schemaPath, outDir, {
89
+ const { warnings, summary, migrationName } = await generateFromSchema(schemaPath, outDir, {
72
90
  ...(options.acceptDataLoss ? { acceptDataLoss: true } : {}),
91
+ ...(config.datasource.enum ? { enumMode: config.datasource.enum } : {}),
73
92
  });
93
+ for (const line of formatGenerateSummary(summary, outDir)) {
94
+ console.log(line);
95
+ }
74
96
  for (const warning of warnings) {
75
97
  console.warn(`Warning: ${warning}`);
76
98
  }
77
99
  if (migrationName) {
78
- await migrateDeploy(pool, join(outDir, "migrations"));
79
- console.log(`Created and applied: ${migrationName}`);
80
- }
81
- else if (destructiveBlocked) {
82
- console.log("Destructive schema changes detected — no migration created");
100
+ const newlyApplied = await migrateDeploy(pool, join(outDir, "migrations"));
101
+ if (newlyApplied.length > 0) {
102
+ console.log(`Applied new migration: ${newlyApplied.join(", ")}`);
103
+ }
83
104
  }
84
105
  }
106
+ return;
85
107
  }
86
- else {
87
- console.error("Usage: neoorm migrate dev | deploy");
88
- process.exit(1);
89
- }
108
+ console.error("Usage: neoorm migrate dev | deploy | status | reset");
109
+ process.exit(1);
90
110
  }
91
111
  finally {
92
112
  await pool.end();
@@ -111,7 +131,8 @@ program
111
131
  console.error("Run neoorm generate first");
112
132
  process.exit(1);
113
133
  }
114
- const { appliedStatements, destructiveBlocked } = await dbPush(pool, manifest, { ...(options.acceptDataLoss ? { acceptDataLoss: true } : {}) });
134
+ const { appliedStatements, destructiveBlocked } = await dbPush(pool, manifest, { ...(options.acceptDataLoss ? { acceptDataLoss: true } : {}),
135
+ });
115
136
  for (const warning of dbPushWarnings(destructiveBlocked)) {
116
137
  console.warn(`Warning: ${warning}`);
117
138
  }
@@ -1 +1 @@
1
- {"version":3,"file":"neoorm.js","sourceRoot":"","sources":["../../src/bin/neoorm.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"neoorm.js","sourceRoot":"","sources":["../../src/bin/neoorm.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,14 @@
1
1
  import type { DestructiveChange, Manifest, ManifestColumn, ManifestDiff, TableDiff } from "../dialect/types.js";
2
2
  export declare function columnSqlType(col: ManifestColumn, manifest?: Manifest): string;
3
3
  export declare function columnsEqual(a: ManifestColumn, b: ManifestColumn, manifest?: Manifest): boolean;
4
- export declare function buildMigrationSql(tableDiffs: TableDiff[], extensions?: string[], manifest?: Manifest): string[];
4
+ export declare function buildMigrationSql(tableDiffs: TableDiff[], extensions?: string[], manifest?: Manifest, newEnumTypes?: Record<string, {
5
+ values: readonly string[];
6
+ }>): string[];
5
7
  export declare function diffManifest(prev: Manifest | null, next: Manifest): ManifestDiff;
6
8
  export declare function resolveMigrationSql(diff: ManifestDiff, prev: Manifest | null, next: Manifest, acceptDataLoss: boolean): {
7
9
  sql: string[];
8
10
  blocked: DestructiveChange[];
9
11
  };
12
+ export declare function explainNoMigrationSql(prev: Manifest | null, next: Manifest, diff: ManifestDiff): string[];
10
13
  export declare function formatDestructiveWarnings(destructive: DestructiveChange[]): string[];
11
14
  //# sourceMappingURL=diff-manifest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"diff-manifest.d.ts","sourceRoot":"","sources":["../../src/codegen/diff-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,iBAAiB,EAEjB,QAAQ,EACR,cAAc,EAGd,YAAY,EACZ,SAAS,EACV,MAAM,qBAAqB,CAAC;AAgB7B,wBAAgB,aAAa,CAC3B,GAAG,EAAE,cAAc,EACnB,QAAQ,CAAC,EAAE,QAAQ,GAClB,MAAM,CAER;AAuCD,wBAAgB,YAAY,CAC1B,CAAC,EAAE,cAAc,EACjB,CAAC,EAAE,cAAc,EACjB,QAAQ,CAAC,EAAE,QAAQ,GAClB,OAAO,CAYT;AAqbD,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,SAAS,EAAE,EACvB,UAAU,GAAE,MAAM,EAAO,EACzB,QAAQ,CAAC,EAAE,QAAQ,GAClB,MAAM,EAAE,CAqCV;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,QAAQ,GAAG,IAAI,EACrB,IAAI,EAAE,QAAQ,GACb,YAAY,CA6Cd;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,QAAQ,GAAG,IAAI,EACrB,IAAI,EAAE,QAAQ,EACd,cAAc,EAAE,OAAO,GACtB;IAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,iBAAiB,EAAE,CAAA;CAAE,CAgDjD;AAED,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,iBAAiB,EAAE,GAC/B,MAAM,EAAE,CAuBV"}
1
+ {"version":3,"file":"diff-manifest.d.ts","sourceRoot":"","sources":["../../src/codegen/diff-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,iBAAiB,EAEjB,QAAQ,EACR,cAAc,EAGd,YAAY,EACZ,SAAS,EACV,MAAM,qBAAqB,CAAC;AAiB7B,wBAAgB,aAAa,CAC3B,GAAG,EAAE,cAAc,EACnB,QAAQ,CAAC,EAAE,QAAQ,GAClB,MAAM,CAER;AAuCD,wBAAgB,YAAY,CAC1B,CAAC,EAAE,cAAc,EACjB,CAAC,EAAE,cAAc,EACjB,QAAQ,CAAC,EAAE,QAAQ,GAClB,OAAO,CAaT;AA0bD,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,SAAS,EAAE,EACvB,UAAU,GAAE,MAAM,EAAO,EACzB,QAAQ,CAAC,EAAE,QAAQ,EACnB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC,GAC3D,MAAM,EAAE,CAyCV;AAiCD,wBAAgB,YAAY,CAC1B,IAAI,EAAE,QAAQ,GAAG,IAAI,EACrB,IAAI,EAAE,QAAQ,GACb,YAAY,CAoDd;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,QAAQ,GAAG,IAAI,EACrB,IAAI,EAAE,QAAQ,EACd,cAAc,EAAE,OAAO,GACtB;IAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,iBAAiB,EAAE,CAAA;CAAE,CAkDjD;AAcD,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,QAAQ,GAAG,IAAI,EACrB,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,YAAY,GACjB,MAAM,EAAE,CAoDV;AAED,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,iBAAiB,EAAE,GAC/B,MAAM,EAAE,CAyBV"}
@@ -1,4 +1,4 @@
1
- import { postgresDialect, resolveFkConstraintName, resolveIndexSqlName, resolveUniqueConstraintName, canAutoCastType, resolveColumnSqlType, } from "../dialect/postgres.js";
1
+ import { postgresDialect, resolveFkConstraintName, resolveIndexSqlName, resolveUniqueConstraintName, canAutoCastType, resolveColumnSqlType, emitCreateEnumTypes, } from "../dialect/postgres.js";
2
2
  function tablesBySqlName(manifest) {
3
3
  return new Map(Object.values(manifest.tables).map((table) => [table.sqlName, table]));
4
4
  }
@@ -36,6 +36,7 @@ export function columnsEqual(a, b, manifest) {
36
36
  a.primary === b.primary &&
37
37
  defaultsEqual(a, b) &&
38
38
  typeOptionsEqual(a.typeOptions, b.typeOptions) &&
39
+ a.checkExpression === b.checkExpression &&
39
40
  columnSqlType(a, manifest) === columnSqlType(b, manifest) &&
40
41
  (a.kind !== "fk" ||
41
42
  (a.fkTarget === b.fkTarget && a.onDelete === b.onDelete)));
@@ -172,6 +173,10 @@ function buildColumnAlter(prevCol, nextCol, prevTable, alterSqlName, prevManifes
172
173
  if (prevCol.primary !== nextCol.primary) {
173
174
  hasAlter = true;
174
175
  }
176
+ if (prevCol.checkExpression !== nextCol.checkExpression) {
177
+ alter.setCheckExpression = nextCol.checkExpression ?? null;
178
+ hasAlter = true;
179
+ }
175
180
  return hasAlter ? alter : null;
176
181
  }
177
182
  function diffColumns(prevTable, nextTable, prevManifest, nextManifest) {
@@ -372,11 +377,14 @@ function stripDestructiveFromDiff(diff) {
372
377
  (stripped.fkChanges?.length ?? 0) > 0;
373
378
  return hasChanges ? stripped : null;
374
379
  }
375
- export function buildMigrationSql(tableDiffs, extensions = [], manifest) {
380
+ export function buildMigrationSql(tableDiffs, extensions = [], manifest, newEnumTypes) {
376
381
  const sql = [];
377
382
  if (extensions.length > 0) {
378
383
  sql.push(...postgresDialect.emitCreateExtensions(extensions));
379
384
  }
385
+ if (newEnumTypes && Object.keys(newEnumTypes).length > 0) {
386
+ sql.push(...emitCreateEnumTypes(newEnumTypes));
387
+ }
380
388
  const alterDiffs = tableDiffs.filter((d) => !d.create && !d.drop);
381
389
  const dropDiffs = tableDiffs.filter((d) => d.drop);
382
390
  const createDiffs = tableDiffs.filter((d) => d.create);
@@ -402,11 +410,36 @@ export function buildMigrationSql(tableDiffs, extensions = [], manifest) {
402
410
  }
403
411
  return sql;
404
412
  }
413
+ function diffEnumTypes(prev, next) {
414
+ const destructive = [];
415
+ const newEnumTypes = {};
416
+ const prevEnums = prev?.enumTypes ?? {};
417
+ const nextEnums = next.enumTypes ?? {};
418
+ for (const [name, definition] of Object.entries(nextEnums)) {
419
+ const prevDefinition = prevEnums[name];
420
+ if (!prevDefinition) {
421
+ newEnumTypes[name] = definition;
422
+ continue;
423
+ }
424
+ if (JSON.stringify(prevDefinition.values) !== JSON.stringify(definition.values)) {
425
+ destructive.push({
426
+ kind: "alter_enum_manual",
427
+ table: name,
428
+ detail: `Enum type "${name}" values changed — manual migration required`,
429
+ sql: `-- ALTER TYPE ${name} ... (manual)`,
430
+ });
431
+ }
432
+ }
433
+ return { newEnumTypes, destructive };
434
+ }
405
435
  export function diffManifest(prev, next) {
406
436
  if (!prev) {
407
437
  const sql = [];
408
438
  const extensions = next.extensions ?? [];
409
439
  sql.push(...postgresDialect.emitCreateExtensions(extensions));
440
+ if (next.enumTypes) {
441
+ sql.push(...emitCreateEnumTypes(next.enumTypes));
442
+ }
410
443
  const tables = Object.values(next.tables);
411
444
  for (const table of tables) {
412
445
  sql.push(postgresDialect.emitCreateTable(table, { manifest: next }));
@@ -425,6 +458,7 @@ export function diffManifest(prev, next) {
425
458
  const destructive = [];
426
459
  const prevExtensions = new Set(prev.extensions ?? []);
427
460
  const newExtensions = (next.extensions ?? []).filter((ext) => !prevExtensions.has(ext));
461
+ const { newEnumTypes, destructive: enumDestructive } = diffEnumTypes(prev, next);
428
462
  for (const sqlName of allSqlNames) {
429
463
  const prevTable = prevBySql.get(sqlName);
430
464
  const nextTable = nextBySql.get(sqlName);
@@ -434,12 +468,14 @@ export function diffManifest(prev, next) {
434
468
  tableDiffs.push(diff);
435
469
  destructive.push(...classifyDestructive(diff, prevTable));
436
470
  }
437
- const sql = buildMigrationSql(tableDiffs, newExtensions, next);
471
+ destructive.push(...enumDestructive);
472
+ const sql = buildMigrationSql(tableDiffs, newExtensions, next, newEnumTypes);
438
473
  return { isInitial: false, sql, destructive };
439
474
  }
440
475
  export function resolveMigrationSql(diff, prev, next, acceptDataLoss) {
441
476
  if (acceptDataLoss) {
442
- const blocked = diff.destructive.filter((change) => change.kind === "alter_column_type_manual");
477
+ const blocked = diff.destructive.filter((change) => change.kind === "alter_column_type_manual" ||
478
+ change.kind === "alter_enum_manual");
443
479
  if (blocked.length === 0) {
444
480
  return { sql: diff.sql, blocked: [] };
445
481
  }
@@ -477,6 +513,49 @@ export function resolveMigrationSql(diff, prev, next, acceptDataLoss) {
477
513
  blocked: diff.destructive,
478
514
  };
479
515
  }
516
+ function relationsSignature(manifest) {
517
+ const parts = [];
518
+ for (const table of Object.values(manifest.tables)) {
519
+ for (const rel of table.relations) {
520
+ parts.push(`${table.sqlName}:${rel.name}:${rel.inverse}:${rel.targetAccessor}:${rel.cardinality}`);
521
+ }
522
+ }
523
+ return parts.sort().join("|");
524
+ }
525
+ export function explainNoMigrationSql(prev, next, diff) {
526
+ const reasons = [];
527
+ if (!prev) {
528
+ return ["Initial schema — run generate again if no migration was expected."];
529
+ }
530
+ for (const change of diff.destructive) {
531
+ if (change.kind === "alter_column_type_manual" ||
532
+ change.kind === "alter_enum_manual") {
533
+ reasons.push(formatDestructiveWarnings([change])[0]);
534
+ }
535
+ }
536
+ if (prev.enumMode !== next.enumMode) {
537
+ reasons.push(`enumMode changed (${prev.enumMode ?? "check"} → ${next.enumMode ?? "check"}) — no DDL emitted`);
538
+ }
539
+ const prevExtensions = new Set(prev.extensions ?? []);
540
+ const addedExtensions = (next.extensions ?? []).filter((ext) => !prevExtensions.has(ext));
541
+ if (addedExtensions.length === 0 &&
542
+ JSON.stringify(prev.extensions ?? []) !== JSON.stringify(next.extensions ?? [])) {
543
+ reasons.push("extensions metadata changed — no new CREATE EXTENSION statements");
544
+ }
545
+ if (JSON.stringify(prev.manyToMany) !== JSON.stringify(next.manyToMany)) {
546
+ reasons.push("manyToMany relation metadata changed — no DDL emitted");
547
+ }
548
+ if (relationsSignature(prev) !== relationsSignature(next)) {
549
+ reasons.push("relation names or inverses changed — no DDL emitted");
550
+ }
551
+ if (diff.destructive.length > 0 && diff.sql.length === 0) {
552
+ reasons.push("Destructive changes detected; safe subset produced no SQL. Re-run with --accept-data-loss or write a manual migration.");
553
+ }
554
+ if (reasons.length === 0) {
555
+ reasons.push("Manifest updated for codegen; database schema is already compatible.");
556
+ }
557
+ return reasons;
558
+ }
480
559
  export function formatDestructiveWarnings(destructive) {
481
560
  return destructive.map((change) => {
482
561
  switch (change.kind) {
@@ -494,6 +573,8 @@ export function formatDestructiveWarnings(destructive) {
494
573
  return `${change.detail} — this may affect referential integrity`;
495
574
  case "alter_primary_key":
496
575
  return `${change.detail} — primary key changes require manual migration`;
576
+ case "alter_enum_manual":
577
+ return `${change.detail} — enum value changes require manual migration`;
497
578
  default: {
498
579
  const _exhaustive = change.kind;
499
580
  return _exhaustive;