neoorm 0.9.5 → 0.9.7

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 (117) hide show
  1. package/AGENTS.md +46 -0
  2. package/dist/bin/neoorm.d.ts.map +1 -1
  3. package/dist/bin/neoorm.js +213 -135
  4. package/dist/bin/neoorm.js.map +1 -1
  5. package/dist/codegen/column-ts.d.ts.map +1 -1
  6. package/dist/codegen/column-ts.js +5 -2
  7. package/dist/codegen/column-ts.js.map +1 -1
  8. package/dist/codegen/emit-query-types.d.ts.map +1 -1
  9. package/dist/codegen/emit-query-types.js +35 -0
  10. package/dist/codegen/emit-query-types.js.map +1 -1
  11. package/dist/codegen/generate.d.ts +25 -1
  12. package/dist/codegen/generate.d.ts.map +1 -1
  13. package/dist/codegen/generate.js +80 -17
  14. package/dist/codegen/generate.js.map +1 -1
  15. package/dist/codegen/schema-to-manifest.d.ts.map +1 -1
  16. package/dist/codegen/schema-to-manifest.js +65 -0
  17. package/dist/codegen/schema-to-manifest.js.map +1 -1
  18. package/dist/codegen/validation/from-manifest.d.ts.map +1 -1
  19. package/dist/codegen/validation/from-manifest.js +12 -2
  20. package/dist/codegen/validation/from-manifest.js.map +1 -1
  21. package/dist/config.d.ts +6 -0
  22. package/dist/config.d.ts.map +1 -1
  23. package/dist/config.js +28 -0
  24. package/dist/config.js.map +1 -1
  25. package/dist/dialect/sqlite.test.js +9 -0
  26. package/dist/dialect/sqlite.test.js.map +1 -1
  27. package/dist/index.d.ts +4 -2
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +2 -1
  30. package/dist/index.js.map +1 -1
  31. package/dist/introspect/mysql/to-manifest.d.ts.map +1 -1
  32. package/dist/introspect/mysql/to-manifest.js +2 -1
  33. package/dist/introspect/mysql/to-manifest.js.map +1 -1
  34. package/dist/introspect/pull.d.ts +5 -0
  35. package/dist/introspect/pull.d.ts.map +1 -1
  36. package/dist/introspect/pull.js +160 -22
  37. package/dist/introspect/pull.js.map +1 -1
  38. package/dist/introspect/sqlite/to-manifest.d.ts.map +1 -1
  39. package/dist/introspect/sqlite/to-manifest.js +2 -1
  40. package/dist/introspect/sqlite/to-manifest.js.map +1 -1
  41. package/dist/introspect/table-map.d.ts +9 -0
  42. package/dist/introspect/table-map.d.ts.map +1 -0
  43. package/dist/introspect/table-map.js +21 -0
  44. package/dist/introspect/table-map.js.map +1 -0
  45. package/dist/introspect/to-manifest.d.ts.map +1 -1
  46. package/dist/introspect/to-manifest.js +2 -1
  47. package/dist/introspect/to-manifest.js.map +1 -1
  48. package/dist/migrate/dev-workflow.d.ts +36 -0
  49. package/dist/migrate/dev-workflow.d.ts.map +1 -0
  50. package/dist/migrate/dev-workflow.js +96 -0
  51. package/dist/migrate/dev-workflow.js.map +1 -0
  52. package/dist/migrate/runner.d.ts.map +1 -1
  53. package/dist/migrate/runner.js +23 -5
  54. package/dist/migrate/runner.js.map +1 -1
  55. package/dist/runtime/driver-sqlite.test.js +115 -0
  56. package/dist/runtime/driver-sqlite.test.js.map +1 -1
  57. package/dist/runtime/driver.d.ts +8 -0
  58. package/dist/runtime/driver.d.ts.map +1 -1
  59. package/dist/runtime/driver.js +51 -97
  60. package/dist/runtime/driver.js.map +1 -1
  61. package/dist/runtime/error-codes.d.ts +4 -0
  62. package/dist/runtime/error-codes.d.ts.map +1 -1
  63. package/dist/runtime/error-codes.js +4 -0
  64. package/dist/runtime/error-codes.js.map +1 -1
  65. package/dist/runtime/mysql-driver.d.ts.map +1 -1
  66. package/dist/runtime/mysql-driver.js +5 -1
  67. package/dist/runtime/mysql-driver.js.map +1 -1
  68. package/dist/runtime/mysql-family-pool.test.js +14 -1
  69. package/dist/runtime/mysql-family-pool.test.js.map +1 -1
  70. package/dist/runtime/mysql-placeholders.d.ts.map +1 -1
  71. package/dist/runtime/mysql-placeholders.js +12 -0
  72. package/dist/runtime/mysql-placeholders.js.map +1 -1
  73. package/dist/runtime/mysql-placeholders.test.js +15 -0
  74. package/dist/runtime/mysql-placeholders.test.js.map +1 -1
  75. package/dist/runtime/query/compile-where.d.ts.map +1 -1
  76. package/dist/runtime/query/compile-where.js +26 -1
  77. package/dist/runtime/query/compile-where.js.map +1 -1
  78. package/dist/runtime/query/find-or-create.test.js +19 -0
  79. package/dist/runtime/query/find-or-create.test.js.map +1 -1
  80. package/dist/runtime/query/update.d.ts.map +1 -1
  81. package/dist/runtime/query/update.js +9 -1
  82. package/dist/runtime/query/update.js.map +1 -1
  83. package/dist/runtime/query/upsert.d.ts.map +1 -1
  84. package/dist/runtime/query/upsert.js +12 -3
  85. package/dist/runtime/query/upsert.js.map +1 -1
  86. package/dist/runtime/regex-guard.d.ts +28 -0
  87. package/dist/runtime/regex-guard.d.ts.map +1 -0
  88. package/dist/runtime/regex-guard.js +124 -0
  89. package/dist/runtime/regex-guard.js.map +1 -0
  90. package/dist/runtime/regex-guard.test.d.ts +2 -0
  91. package/dist/runtime/regex-guard.test.d.ts.map +1 -0
  92. package/dist/runtime/regex-guard.test.js +63 -0
  93. package/dist/runtime/regex-guard.test.js.map +1 -0
  94. package/dist/runtime/sqlite-open.d.ts.map +1 -1
  95. package/dist/runtime/sqlite-open.js +22 -7
  96. package/dist/runtime/sqlite-open.js.map +1 -1
  97. package/dist/runtime/sqlite-open.test.d.ts +2 -0
  98. package/dist/runtime/sqlite-open.test.d.ts.map +1 -0
  99. package/dist/runtime/sqlite-open.test.js +66 -0
  100. package/dist/runtime/sqlite-open.test.js.map +1 -0
  101. package/dist/seed/runner.d.ts +46 -0
  102. package/dist/seed/runner.d.ts.map +1 -0
  103. package/dist/seed/runner.js +99 -0
  104. package/dist/seed/runner.js.map +1 -0
  105. package/dist/sql/split-statements.d.ts +15 -0
  106. package/dist/sql/split-statements.d.ts.map +1 -0
  107. package/dist/sql/split-statements.js +132 -0
  108. package/dist/sql/split-statements.js.map +1 -0
  109. package/docs/cli.md +30 -2
  110. package/docs/configuration.md +2 -0
  111. package/docs/migrate-dev-workflow.md +84 -0
  112. package/docs/migrations.md +14 -3
  113. package/docs/seeding.md +67 -0
  114. package/docs/sqlite.md +2 -0
  115. package/llms-full.txt +3547 -0
  116. package/llms.txt +40 -0
  117. package/package.json +5 -2
@@ -0,0 +1,99 @@
1
+ import { stat } from "node:fs/promises";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { schemaError } from "../runtime/error-builders.js";
4
+ import { SchemaErrorCode } from "../runtime/error-codes.js";
5
+ import { importTsModule } from "../utils/load-ts.js";
6
+ const SEED_EXTENSIONS = [".ts", ".mts", ".cts"];
7
+ function isRecord(value) {
8
+ return value !== null && typeof value === "object" && !Array.isArray(value);
9
+ }
10
+ async function isFile(path) {
11
+ try {
12
+ return (await stat(path)).isFile();
13
+ }
14
+ catch {
15
+ return false;
16
+ }
17
+ }
18
+ async function firstExisting(paths) {
19
+ for (const path of paths) {
20
+ if (await isFile(path)) {
21
+ return path;
22
+ }
23
+ }
24
+ return undefined;
25
+ }
26
+ function seedFileSuggestions(lookedFor) {
27
+ return [
28
+ `Create ${lookedFor[0]} exporting \`export async function seed(db) { ... }\``,
29
+ "Or pass an explicit path with --file <path>",
30
+ ];
31
+ }
32
+ /**
33
+ * Resolve which seed file to run. Precedence: `--file` → config
34
+ * `seed.file` → `seeds/<env>.ts` → `seed.ts` next to the schema.
35
+ * Throws `invalid_seed` when nothing resolves.
36
+ */
37
+ export async function resolveSeedFile(options) {
38
+ if (options.file) {
39
+ return resolve(options.cwd, options.file);
40
+ }
41
+ if (options.configFile) {
42
+ return resolve(options.cwd, options.configFile);
43
+ }
44
+ const schemaDir = dirname(options.schemaPath);
45
+ if (options.env) {
46
+ const candidates = SEED_EXTENSIONS.map((ext) => join(schemaDir, "seeds", `${options.env}${ext}`));
47
+ const found = await firstExisting(candidates);
48
+ if (!found) {
49
+ throw schemaError(SchemaErrorCode.invalid_seed, `No seed file found for --env "${options.env}". Looked for: ${candidates.join(", ")}.`, undefined, seedFileSuggestions(candidates));
50
+ }
51
+ return found;
52
+ }
53
+ const candidates = SEED_EXTENSIONS.map((ext) => join(schemaDir, `seed${ext}`));
54
+ const found = await firstExisting(candidates);
55
+ if (!found) {
56
+ throw schemaError(SchemaErrorCode.invalid_seed, `No seed file found. Looked for: ${candidates.join(", ")}.`, undefined, seedFileSuggestions(candidates));
57
+ }
58
+ return found;
59
+ }
60
+ /**
61
+ * Load the `seed(db)` export from a seed file. Accepts a named `seed`
62
+ * export or a default-exported function.
63
+ */
64
+ export async function loadSeedFunction(seedPath) {
65
+ let mod;
66
+ try {
67
+ mod = await importTsModule(seedPath);
68
+ }
69
+ catch (err) {
70
+ throw schemaError(SchemaErrorCode.invalid_seed, `Could not load seed file "${seedPath}": ${err instanceof Error ? err.message : String(err)}`, undefined, ["Check the path and that the file compiles"]);
71
+ }
72
+ const exported = mod.seed;
73
+ const defaultExport = mod.default;
74
+ const fromDefault = typeof defaultExport === "function"
75
+ ? defaultExport
76
+ : isRecord(defaultExport)
77
+ ? defaultExport.seed
78
+ : undefined;
79
+ const fn = exported ?? fromDefault;
80
+ if (typeof fn !== "function") {
81
+ throw schemaError(SchemaErrorCode.invalid_seed, `Seed file "${seedPath}" must export a seed function: \`export async function seed(db) { ... }\`.`, undefined, ["Export a named `seed` function or a default function"]);
82
+ }
83
+ return fn;
84
+ }
85
+ /**
86
+ * Run a seed file inside a single transaction. Any failure rolls the whole
87
+ * seed back, so failed runs are safe to retry. Execution errors propagate
88
+ * unwrapped so their original code and context are preserved.
89
+ */
90
+ export async function runSeed(db, seedPath) {
91
+ const seed = await loadSeedFunction(seedPath);
92
+ await db.$transaction(async (tx) => {
93
+ // The runtime shape is identical for every manifest (repositories by
94
+ // accessor); only the static table types differ, so seed files may
95
+ // annotate with their own `TransactionClient<typeof schema._tables>`.
96
+ await seed(tx);
97
+ });
98
+ }
99
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/seed/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export type SplitStatementsOptions = {
2
+ /**
3
+ * Treat `\` as an escape character inside quoted strings and quoted
4
+ * identifiers (MySQL/MariaDB string syntax). Off by default: SQLite and
5
+ * PostgreSQL treat a backslash as a literal character in strings.
6
+ */
7
+ backslashEscapes?: boolean;
8
+ };
9
+ /**
10
+ * Split a SQL script into individual statements on `;` boundaries, honoring
11
+ * quoted strings, quoted identifiers (backticks/double quotes), and
12
+ * line/block comments — so `;` inside any of them never splits.
13
+ */
14
+ export declare function splitStatements(sql: string, options?: SplitStatementsOptions): string[];
15
+ //# sourceMappingURL=split-statements.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"split-statements.d.ts","sourceRoot":"","sources":["../../src/sql/split-statements.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAAG;IACpC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,eAAe,CAC9B,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,sBAAsB,GAC9B,MAAM,EAAE,CA6HV"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Split a SQL script into individual statements on `;` boundaries, honoring
3
+ * quoted strings, quoted identifiers (backticks/double quotes), and
4
+ * line/block comments — so `;` inside any of them never splits.
5
+ */
6
+ export function splitStatements(sql, options) {
7
+ const backslash = options?.backslashEscapes === true;
8
+ const statements = [];
9
+ let current = "";
10
+ let inSingle = false;
11
+ let inDouble = false;
12
+ let inBacktick = false;
13
+ let inLineComment = false;
14
+ let inBlockComment = false;
15
+ for (let i = 0; i < sql.length; i++) {
16
+ const ch = sql[i];
17
+ const next = sql[i + 1];
18
+ if (inLineComment) {
19
+ current += ch;
20
+ if (ch === "\n")
21
+ inLineComment = false;
22
+ continue;
23
+ }
24
+ if (inBlockComment) {
25
+ current += ch;
26
+ if (ch === "*" && next === "/") {
27
+ current += next;
28
+ i++;
29
+ inBlockComment = false;
30
+ }
31
+ continue;
32
+ }
33
+ if (inSingle) {
34
+ current += ch;
35
+ if (backslash && ch === "\\") {
36
+ if (next !== undefined) {
37
+ current += next;
38
+ i++;
39
+ }
40
+ continue;
41
+ }
42
+ if (ch === "'") {
43
+ if (next === "'") {
44
+ current += next;
45
+ i++;
46
+ }
47
+ else {
48
+ inSingle = false;
49
+ }
50
+ }
51
+ continue;
52
+ }
53
+ if (inDouble) {
54
+ current += ch;
55
+ if (backslash && ch === "\\") {
56
+ if (next !== undefined) {
57
+ current += next;
58
+ i++;
59
+ }
60
+ continue;
61
+ }
62
+ if (ch === '"') {
63
+ if (next === '"') {
64
+ current += next;
65
+ i++;
66
+ }
67
+ else {
68
+ inDouble = false;
69
+ }
70
+ }
71
+ continue;
72
+ }
73
+ if (inBacktick) {
74
+ current += ch;
75
+ if (backslash && ch === "\\") {
76
+ if (next !== undefined) {
77
+ current += next;
78
+ i++;
79
+ }
80
+ continue;
81
+ }
82
+ if (ch === "`") {
83
+ if (next === "`") {
84
+ current += next;
85
+ i++;
86
+ }
87
+ else {
88
+ inBacktick = false;
89
+ }
90
+ }
91
+ continue;
92
+ }
93
+ if (ch === "-" && next === "-") {
94
+ inLineComment = true;
95
+ current += ch;
96
+ continue;
97
+ }
98
+ if (ch === "/" && next === "*") {
99
+ inBlockComment = true;
100
+ current += ch;
101
+ continue;
102
+ }
103
+ if (ch === "'") {
104
+ inSingle = true;
105
+ current += ch;
106
+ continue;
107
+ }
108
+ if (ch === '"') {
109
+ inDouble = true;
110
+ current += ch;
111
+ continue;
112
+ }
113
+ if (ch === "`") {
114
+ inBacktick = true;
115
+ current += ch;
116
+ continue;
117
+ }
118
+ if (ch === ";") {
119
+ if (current.trim().length > 0) {
120
+ statements.push(current.trim());
121
+ }
122
+ current = "";
123
+ continue;
124
+ }
125
+ current += ch;
126
+ }
127
+ if (current.trim().length > 0) {
128
+ statements.push(current.trim());
129
+ }
130
+ return statements.length > 0 ? statements : [sql];
131
+ }
132
+ //# sourceMappingURL=split-statements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"split-statements.js","sourceRoot":"","sources":["../../src/sql/split-statements.ts"],"names":[],"mappings":"AASA;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC9B,GAAW,EACX,OAAgC;IAEhC,MAAM,SAAS,GAAG,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACrD,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,cAAc,GAAG,KAAK,CAAC;IAE3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QAClB,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAExB,IAAI,aAAa,EAAE,CAAC;YACnB,OAAO,IAAI,EAAE,CAAC;YACd,IAAI,EAAE,KAAK,IAAI;gBAAE,aAAa,GAAG,KAAK,CAAC;YACvC,SAAS;QACV,CAAC;QACD,IAAI,cAAc,EAAE,CAAC;YACpB,OAAO,IAAI,EAAE,CAAC;YACd,IAAI,EAAE,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBAChC,OAAO,IAAI,IAAI,CAAC;gBAChB,CAAC,EAAE,CAAC;gBACJ,cAAc,GAAG,KAAK,CAAC;YACxB,CAAC;YACD,SAAS;QACV,CAAC;QACD,IAAI,QAAQ,EAAE,CAAC;YACd,OAAO,IAAI,EAAE,CAAC;YACd,IAAI,SAAS,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;gBAC9B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;oBACxB,OAAO,IAAI,IAAI,CAAC;oBAChB,CAAC,EAAE,CAAC;gBACL,CAAC;gBACD,SAAS;YACV,CAAC;YACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;gBAChB,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;oBAClB,OAAO,IAAI,IAAI,CAAC;oBAChB,CAAC,EAAE,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACP,QAAQ,GAAG,KAAK,CAAC;gBAClB,CAAC;YACF,CAAC;YACD,SAAS;QACV,CAAC;QACD,IAAI,QAAQ,EAAE,CAAC;YACd,OAAO,IAAI,EAAE,CAAC;YACd,IAAI,SAAS,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;gBAC9B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;oBACxB,OAAO,IAAI,IAAI,CAAC;oBAChB,CAAC,EAAE,CAAC;gBACL,CAAC;gBACD,SAAS;YACV,CAAC;YACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;gBAChB,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;oBAClB,OAAO,IAAI,IAAI,CAAC;oBAChB,CAAC,EAAE,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACP,QAAQ,GAAG,KAAK,CAAC;gBAClB,CAAC;YACF,CAAC;YACD,SAAS;QACV,CAAC;QACD,IAAI,UAAU,EAAE,CAAC;YAChB,OAAO,IAAI,EAAE,CAAC;YACd,IAAI,SAAS,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;gBAC9B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;oBACxB,OAAO,IAAI,IAAI,CAAC;oBAChB,CAAC,EAAE,CAAC;gBACL,CAAC;gBACD,SAAS;YACV,CAAC;YACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;gBAChB,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;oBAClB,OAAO,IAAI,IAAI,CAAC;oBAChB,CAAC,EAAE,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACP,UAAU,GAAG,KAAK,CAAC;gBACpB,CAAC;YACF,CAAC;YACD,SAAS;QACV,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YAChC,aAAa,GAAG,IAAI,CAAC;YACrB,OAAO,IAAI,EAAE,CAAC;YACd,SAAS;QACV,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YAChC,cAAc,GAAG,IAAI,CAAC;YACtB,OAAO,IAAI,EAAE,CAAC;YACd,SAAS;QACV,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAChB,QAAQ,GAAG,IAAI,CAAC;YAChB,OAAO,IAAI,EAAE,CAAC;YACd,SAAS;QACV,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAChB,QAAQ,GAAG,IAAI,CAAC;YAChB,OAAO,IAAI,EAAE,CAAC;YACd,SAAS;QACV,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAChB,UAAU,GAAG,IAAI,CAAC;YAClB,OAAO,IAAI,EAAE,CAAC;YACd,SAAS;QACV,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAChB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC/B,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YACjC,CAAC;YACD,OAAO,GAAG,EAAE,CAAC;YACb,SAAS;QACV,CAAC;QACD,OAAO,IAAI,EAAE,CAAC;IACf,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AACnD,CAAC"}
package/docs/cli.md CHANGED
@@ -30,7 +30,7 @@ neoorm generate [options]
30
30
  ```
31
31
 
32
32
  Options:
33
- - `-n, --name <name>` — migration name (e.g. `--name add_users`). Required when a migration is created; prompts interactively on a TTY when omitted, errors in CI. Folders are `<timestamp>_<slug>` with the slug capped at 50 chars. No-change runs (client regeneration only) succeed without `--name`.
33
+ - `-n, --name <name>` — migration name (e.g. `--name add_users`). Only needed when a migration is created: prompts on a TTY at that point, errors in CI. Folders are `<timestamp>_<slug>` with the slug capped at 50 chars. No-change runs (client regeneration only) and pending-apply-only `dev` runs never prompt and succeed without `--name`.
34
34
  - `--accept-data-loss` — include destructive DDL changes (column drops, type changes)
35
35
 
36
36
  ## `neoorm migrate dev`
@@ -41,7 +41,22 @@ Apply pending migrations, then generate a new migration if the schema changed. I
41
41
  neoorm migrate dev --name <name>
42
42
  ```
43
43
 
44
- - `-n, --name <name>` — same as `generate`: required when `dev` creates a migration, prompts on a TTY, errors in CI. Not used by `deploy`, `status`, `reset`, or `down`.
44
+ - `-n, --name <name>` — same as `generate`: only needed when `dev` creates a migration, prompts on a TTY at that point, errors in CI. Applying pending migrations never requires `--name`. Not used by `deploy`, `status`, `reset`, or `down`.
45
+
46
+ ## `neoorm migrate diff`
47
+
48
+ Preview the migration SQL `generate` / `migrate dev` would write, without writing anything.
49
+
50
+ ```
51
+ neoorm migrate diff [--accept-data-loss] [--json]
52
+ ```
53
+
54
+ Read-only: diffs `schema.ts` against `snapshot.json` only. No database connection, no files written, and `--name` is never needed (ignored if passed). Shows the exact statements that would go into `migration.sql`, so you can inspect a change before naming it.
55
+
56
+ - `--accept-data-loss` — include destructive DDL in the preview (by default destructive changes are reported as blocked, same as `generate`)
57
+ - `--json` — print `{ schemaChanged, sql, blocked, destructiveBlocked, warnings }` instead of human-readable text
58
+
59
+ Exit code is `1` when destructive changes would block the migration (mirrors `generate`), `0` otherwise. For already-written but unapplied migrations, use `migrate status`.
45
60
 
46
61
  ## `neoorm migrate deploy`
47
62
 
@@ -86,6 +101,19 @@ neoorm migrate reset --force [--skip-apply]
86
101
 
87
102
  PostgreSQL: the connecting role owns the recreated schema. `PUBLIC` is not granted.
88
103
 
104
+ ## `neoorm seed`
105
+
106
+ Run a seed script against the database inside a single transaction. Any failure rolls the whole seed back.
107
+
108
+ ```
109
+ neoorm seed [--env <name>] [--file <path>]
110
+ ```
111
+
112
+ - `--env <name>` — run `seeds/<name>.ts` (next to `schema.ts`) instead of `seed.ts`
113
+ - `--file <path>` — run a specific seed file (wins over `--env` and config)
114
+
115
+ Resolution order: `--file` → config `seed.file` → `seeds/<env>.ts` → `seed.ts`. The client is compiled from `schema.ts`, so seeding works on a fresh checkout with no codegen. Write idempotent seeds (`upsert`, `findOrCreate`, `createMany` with `skipDuplicates`) — re-runs are by convention, there is no seed ledger. See [Seeding](seeding.md).
116
+
89
117
  ## `neoorm docs`
90
118
 
91
119
  Serve the NeoOrm documentation locally in your browser.
@@ -33,6 +33,8 @@ CLI commands load `.env` from the project directory before evaluating this file,
33
33
  | `generate.zod` | `boolean` | `false` | Emit Select/Create/Update Zod schemas to `out/zod.ts`. See [Zod schemas](zod.md). |
34
34
  | `generate.typebox` | `boolean` | `false` | Emit Select/Create/Update TypeBox schemas to `out/typebox.ts`. See [TypeBox schemas](typebox.md). |
35
35
  | `generate.elysia` | `boolean` | `false` | Emit Select/Create/Update Elysia `t` schemas to `out/elysia.ts`. See [Elysia schemas](elysia.md). |
36
+ | `seed.file` | `string` | unset | Default seed file, project-root relative. CLI `--file` overrides it. See [Seeding](seeding.md). |
37
+ | `seed.env` | `string` | unset | Default environment: runs `seeds/<env>.ts` next to the schema. CLI `--env` overrides it. |
36
38
 
37
39
  ### Validation emit
38
40
 
@@ -0,0 +1,84 @@
1
+ # `migrate dev` Workflow
2
+
3
+ This guide records the workflow contract and the implementation changes behind `neoorm migrate dev`. The refactor preserves the command's migration order and user-visible output timing.
4
+
5
+ ## Runtime contract
6
+
7
+ `runMigrateDev` derives `migrationsDir` from `outDir` and runs the complete sequence inside `withMigrateDevLock`:
8
+
9
+ 1. Read the snapshot, compile the target schema, reconcile pending `CREATE TABLE` migrations against the live database, then apply remaining pending migrations.
10
+ 2. Generate from the current schema. If generation fails with the existing missing-migration-name error, no explicit name was supplied, and the CLI provided an interactive prompt callback, ask once and retry once. Other errors propagate unchanged. If generation needs no migration, it does not prompt.
11
+ 3. Emit the generation summary and warnings, then reconcile a newly written migration against existing tables or apply it when reconciliation did not record it.
12
+ 4. Return whether destructive changes were blocked; the CLI sets `process.exitCode` after the workflow completes.
13
+
14
+ The lock covers snapshot reading, both reconciliation/deployment phases, generation, and the optional prompt. Progress events keep the CLI output at the same stage as before: pending-migration output precedes a possible prompt, while generation output precedes post-generation reconciliation/application.
15
+
16
+ ## File-by-file changes
17
+
18
+ ### `src/migrate/dev-workflow.ts`
19
+
20
+ - **Before:** The ordered `migrate dev` sequence had no dedicated workflow module; the CLI path coordinated it.
21
+ - **After:** `runMigrateDev` owns snapshot reading, initial reconciliation/deployment, generation, the optional one-shot prompt/retry, and post-generation reconciliation/deployment. A typed progress-event union reports completed stages, while existing migration and code-generation helpers remain responsible for their work. The migration directory is derived from `outDir`.
22
+ - **Why it is useful:** The lock scope and ordering have one owner, and the workflow can be tested through a small interface without a CLI/TTY harness.
23
+
24
+ ### `src/bin/neoorm.ts`
25
+
26
+ - **Before:** The CLI command path contained the `migrate dev` orchestration alongside the separate `migrate deploy` path.
27
+ - **After:** `migrate dev` calls `runMigrateDev`, adapts its progress events to the existing console output, supplies the prompt callback only for interactive runs, and handles the returned destructive-blocked status. `migrate deploy` remains on its separate path.
28
+ - **Why it is useful:** Terminal interaction and presentation stay in the CLI, while moving orchestration does not delay or reorder output around the prompt.
29
+
30
+ ### `src/codegen/generate.ts`
31
+
32
+ - **Before:** The missing-migration-name predicate lived in the CLI even though both regular `generate` and `migrate dev` use it.
33
+ - **After:** The same predicate lives beside `missingMigrationNameError` in the code-generation module and is shared by both callers.
34
+ - **Why it is useful:** There is one definition of the narrow prompt-eligibility check; its error conditions are unchanged, not broadened into general error handling.
35
+
36
+ ### `test/migrate-dev-workflow.test.ts`
37
+
38
+ - **Before:** Existing tests covered migration, generation, and lock helpers separately, but not their ordering at the workflow boundary.
39
+ - **After:** Real in-memory SQLite tests verify that a pending migration is applied and the lock remains held when the controlled name prompt runs, and that an unchanged schema completes without prompting or creating another migration.
40
+ - **Why it is useful:** The regression coverage checks observable database state and timing rather than mocked helper forwarding or CLI wiring.
41
+
42
+ ### `docs/migrations.md`
43
+
44
+ - **Before:** The migration guide described command behavior but did not state the full `migrate dev` lock interval.
45
+ - **After:** It documents that the lock starts before pending reconciliation and remains held through the optional name prompt, generation, and post-generation reconciliation/application; it links to this implementation guide.
46
+ - **Why it is useful:** Readers can reason about concurrency and prompt timing from the documented contract.
47
+
48
+ ### `llms-full.txt`
49
+
50
+ - **Before:** The generated documentation aggregate did not include the updated lock-lifetime note or this guide.
51
+ - **After:** Regeneration mirrors the migration-guide update and includes the new workflow page.
52
+ - **Why it is useful:** The aggregate stays aligned with the source documentation instead of presenting stale workflow details.
53
+
54
+ ### `examples/blog/seed.ts`
55
+
56
+ - **Before:** The schema was imported as a runtime value even though it was used only for a type.
57
+ - **After:** The import is type-only.
58
+ - **Why it is useful:** TypeScript erases the import from emitted JavaScript, and lint no longer reports the type-only usage.
59
+
60
+ ### `docs/migrate-dev-workflow.md`
61
+
62
+ - **Before:** There was no durable, file-by-file record of the workflow ownership, preserved behavior, and verification.
63
+ - **After:** This page records the execution contract, concrete before/after changes, and their rationale.
64
+ - **Why it is useful:** Future maintenance can distinguish an ownership refactor from an intended behavior change.
65
+
66
+ ## Preserved behavior and scope
67
+
68
+ - Pending migrations are reconciled and applied before a missing name can be requested.
69
+ - The prompt is limited to the existing missing-name condition and is attempted at most once; unchanged schemas do not prompt.
70
+ - The migrate-dev lock remains held during the prompt and until post-generation reconciliation/application finishes.
71
+ - The existing second schema compilation remains; this change does not optimize it.
72
+ - `migrate deploy` keeps its separate execution path.
73
+
74
+ ## Verification
75
+
76
+ The implementation verification below was recorded before this documentation continuation; it was not rerun as part of the documentation-only changes:
77
+
78
+ - `bun run build` — passed.
79
+ - `bun run test` — 128 files passed, 4 skipped; 1,215 tests passed, 42 skipped.
80
+ - `bun run typecheck` and `bun run lint` — passed; lint was clean.
81
+ - Focused migration suites — 4 files and 34 tests passed.
82
+ - CLI fixture smoke — `migrate dev --name initial`, a no-name no-op `migrate dev`, and a no-op `migrate deploy` each exited 0; the SQLite database had the expected table and one applied ledger entry.
83
+
84
+ The generated documentation is refreshed with `bun run docs:llms` after editing this page.
@@ -5,8 +5,9 @@
5
5
  | Command | Description |
6
6
  |---------|-------------|
7
7
  | `neoorm init` | Scaffold `neoorm.config.ts`, `schema.ts`, `.env.example` only (no codegen or migrations; run `neoorm migrate dev` after) |
8
- | `neoorm generate --name <name>` | Emit manifest, typed client, models, includes, and migrations |
9
- | `neoorm migrate dev --name <name>` | Apply pending migrations (or record colliding CREATE TABLE files against the live schema), then generate a new one if `schema.ts` changed |
8
+ | `neoorm generate [--name <name>]` | Emit manifest, typed client, models, includes, and migrations (`--name` only when a migration is created) |
9
+ | `neoorm migrate dev [--name <name>]` | Apply pending migrations (or record colliding CREATE TABLE files against the live schema), then generate a new one if `schema.ts` changed (`--name` only when a new migration is created) |
10
+ | `neoorm migrate diff [--accept-data-loss] [--json]` | Preview the SQL a new migration would contain — no files written, no `--name` needed |
10
11
  | `neoorm migrate deploy` | Apply pending migrations (throws `migration_drift` if a pending `CREATE TABLE` targets a relation that already exists) |
11
12
  | `neoorm migrate status` | List applied vs pending migrations |
12
13
  | `neoorm migrate down [--steps N]` | Roll back the last N applied migrations (default 1) |
@@ -25,7 +26,10 @@
25
26
  | Migration created | New `migrations/<timestamp>_<name>/migration.sql` written |
26
27
  | Migration blocked | Destructive or manual changes prevented writing SQL |
27
28
 
28
- Migration names are slugified (`Add Users` → `add_users`, capped at 50 chars) and prefixed with a timestamp so folders sort in apply order. `--name` is required when a migration is created: the CLI prompts on a TTY and errors in non-interactive runs. Runs with no schema changes (client regeneration only) succeed without `--name`. Older `*_migration` folders still apply in order.
29
+ Migration names are slugified (`Add Users` → `add_users`, capped at 50 chars) and prefixed with a timestamp so folders sort in apply order. `--name` is only needed when a migration is created: the CLI prompts on a TTY at that point (after pending migrations are applied in `dev`) and errors in non-interactive runs. Runs with no schema changes (client regeneration only) and pending-apply-only `dev` runs succeed without `--name` and never prompt. Older `*_migration` folders still apply in order.
30
+
31
+ `migrate dev` holds its lock from before pending reconciliation through the optional name prompt, generation, and post-generation reconciliation/application.
32
+ For the implementation ordering and regression coverage, see [the workflow guide](migrate-dev-workflow.md).
29
33
 
30
34
  When migration is blocked, 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:
31
35
 
@@ -33,6 +37,13 @@ When migration is blocked, the CLI explains why — for example unsupported type
33
37
  neoorm generate --name add_users --accept-data-loss
34
38
  ```
35
39
 
40
+ To inspect the SQL before naming the migration, preview it first (read-only, needs no `--name`):
41
+
42
+ ```bash
43
+ neoorm migrate diff
44
+ neoorm migrate diff --json
45
+ ```
46
+
36
47
  ## Existing tables vs pending CREATE TABLE
37
48
 
38
49
  `generate` diffs `snapshot.json`. If that file is missing, the first migration is a full `CREATE TABLE` script. `migrate deploy` will not run that SQL when those relations already exist (for example after `db push`). It throws `migration_drift` before any user statement.
@@ -0,0 +1,67 @@
1
+ # Seeding
2
+
3
+ `neoorm seed` runs a seed script against the database inside a single transaction. Any failure rolls the whole seed back, so failed runs are safe to retry.
4
+
5
+ ```
6
+ neoorm seed [--env <name>] [--file <path>]
7
+ ```
8
+
9
+ ## Seed files
10
+
11
+ By convention the seed lives next to the schema as `seed.ts` and exports a `seed(db)` function. `db` is a transaction-scoped client, so every write in the file is atomic:
12
+
13
+ ```ts
14
+ // seed.ts
15
+ import type { TransactionClient } from "neoorm";
16
+ import { schema } from "./schema.js";
17
+
18
+ export async function seed(db: TransactionClient<typeof schema._tables>) {
19
+ await db.users.upsert({
20
+ where: { email: "admin@example.com" },
21
+ create: { email: "admin@example.com", name: "Admin" },
22
+ update: {},
23
+ });
24
+ await db.tags.createMany({
25
+ data: [
26
+ { slug: "news", name: "News" },
27
+ { slug: "guides", name: "Guides" },
28
+ ],
29
+ skipDuplicates: true,
30
+ });
31
+ }
32
+ ```
33
+
34
+ Annotating with `TransactionClient<typeof schema._tables>` gives fully typed repositories — the same types as the generated client. A default-exported function works too, and `SeedContext` from `neoorm` is available for manifest-agnostic helpers.
35
+
36
+ ## Environments
37
+
38
+ `--env <name>` runs `seeds/<name>.ts` instead of `seed.ts`:
39
+
40
+ ```bash
41
+ neoorm seed --env dev
42
+ neoorm seed --file ./seeds/manual.ts
43
+ ```
44
+
45
+ `--file` wins over `--env`, and both win over config (see below).
46
+
47
+ ## Idempotency
48
+
49
+ Seeds are re-run by convention — there is no seed ledger. Write seeds so running them twice is safe: `upsert`, `findOrCreate`, and `createMany({ skipDuplicates: true })` are the building blocks. The transaction guarantees all-or-nothing per run, not across runs.
50
+
51
+ ## Configuration
52
+
53
+ Pin defaults in `neoorm.config.ts` (CLI flags override them):
54
+
55
+ ```ts
56
+ export default defineConfig({
57
+ // ...
58
+ seed: { env: "dev", file: "./seeds/base.ts" },
59
+ });
60
+ ```
61
+
62
+ | Key | Type | Description |
63
+ |-----|------|-------------|
64
+ | `seed.file` | `string` | Default seed file, project-root relative |
65
+ | `seed.env` | `string` | Default environment, runs `seeds/<env>.ts` next to the schema |
66
+
67
+ See [Configuration](configuration.md) for the full config reference.
package/docs/sqlite.md CHANGED
@@ -60,6 +60,8 @@ const db = createNeoOrmClient(manifest, {
60
60
 
61
61
  `busyTimeout` can also be a millisecond wait (`sqlite: { busyTimeout: 10_000 }`).
62
62
 
63
+ SQLite runs `search`/`REGEXP` patterns in-process as JavaScript `RegExp`, so a catastrophic-backtracking pattern (e.g. `(a+)+$`) could freeze the whole process. neoorm rejects patterns that nest unbounded quantifiers; pass `sqlite: { unsafeAllowRegex: true }` to allow them anyway.
64
+
63
65
  ### Custom driver
64
66
 
65
67
  Pass any object implementing `prepare(sql)`, `exec(sql)`, and `close()` — the `node:sqlite` and `bun:sqlite` APIs both match. Useful for sandboxed runtimes or existing database handles: