@fragno-dev/db 0.0.1 → 0.1.0

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 (200) hide show
  1. package/.turbo/turbo-build.log +137 -13
  2. package/.turbo/turbo-test.log +36 -0
  3. package/CHANGELOG.md +7 -0
  4. package/dist/adapters/adapters.d.ts +18 -0
  5. package/dist/adapters/adapters.d.ts.map +1 -0
  6. package/dist/adapters/drizzle/drizzle-adapter.d.ts +21 -0
  7. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +1 -0
  8. package/dist/adapters/drizzle/drizzle-adapter.js +62 -0
  9. package/dist/adapters/drizzle/drizzle-adapter.js.map +1 -0
  10. package/dist/adapters/drizzle/drizzle-query.d.ts +17 -0
  11. package/dist/adapters/drizzle/drizzle-query.d.ts.map +1 -0
  12. package/dist/adapters/drizzle/drizzle-query.js +139 -0
  13. package/dist/adapters/drizzle/drizzle-query.js.map +1 -0
  14. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts +9 -0
  15. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts.map +1 -0
  16. package/dist/adapters/drizzle/drizzle-uow-compiler.js +300 -0
  17. package/dist/adapters/drizzle/drizzle-uow-compiler.js.map +1 -0
  18. package/dist/adapters/drizzle/drizzle-uow-decoder.js +82 -0
  19. package/dist/adapters/drizzle/drizzle-uow-decoder.js.map +1 -0
  20. package/dist/adapters/drizzle/drizzle-uow-executor.js +125 -0
  21. package/dist/adapters/drizzle/drizzle-uow-executor.js.map +1 -0
  22. package/dist/adapters/drizzle/generate.js +273 -0
  23. package/dist/adapters/drizzle/generate.js.map +1 -0
  24. package/dist/adapters/drizzle/join-column-utils.js +28 -0
  25. package/dist/adapters/drizzle/join-column-utils.js.map +1 -0
  26. package/dist/adapters/drizzle/shared.js +11 -0
  27. package/dist/adapters/drizzle/shared.js.map +1 -0
  28. package/dist/adapters/kysely/kysely-adapter.d.ts +23 -0
  29. package/dist/adapters/kysely/kysely-adapter.d.ts.map +1 -0
  30. package/dist/adapters/kysely/kysely-adapter.js +119 -0
  31. package/dist/adapters/kysely/kysely-adapter.js.map +1 -0
  32. package/dist/adapters/kysely/kysely-query-builder.js +306 -0
  33. package/dist/adapters/kysely/kysely-query-builder.js.map +1 -0
  34. package/dist/adapters/kysely/kysely-query-compiler.js +67 -0
  35. package/dist/adapters/kysely/kysely-query-compiler.js.map +1 -0
  36. package/dist/adapters/kysely/kysely-query.js +158 -0
  37. package/dist/adapters/kysely/kysely-query.js.map +1 -0
  38. package/dist/adapters/kysely/kysely-uow-compiler.js +139 -0
  39. package/dist/adapters/kysely/kysely-uow-compiler.js.map +1 -0
  40. package/dist/adapters/kysely/kysely-uow-executor.js +89 -0
  41. package/dist/adapters/kysely/kysely-uow-executor.js.map +1 -0
  42. package/dist/adapters/kysely/migration/execute.js +176 -0
  43. package/dist/adapters/kysely/migration/execute.js.map +1 -0
  44. package/dist/fragment.d.ts +54 -0
  45. package/dist/fragment.d.ts.map +1 -0
  46. package/dist/fragment.js +92 -0
  47. package/dist/fragment.js.map +1 -0
  48. package/dist/id.d.ts +2 -0
  49. package/dist/migration-engine/auto-from-schema.js +116 -0
  50. package/dist/migration-engine/auto-from-schema.js.map +1 -0
  51. package/dist/migration-engine/create.d.ts +41 -0
  52. package/dist/migration-engine/create.d.ts.map +1 -0
  53. package/dist/migration-engine/create.js +58 -0
  54. package/dist/migration-engine/create.js.map +1 -0
  55. package/dist/migration-engine/shared.d.ts +90 -0
  56. package/dist/migration-engine/shared.d.ts.map +1 -0
  57. package/dist/migration-engine/shared.js +8 -0
  58. package/dist/migration-engine/shared.js.map +1 -0
  59. package/dist/mod.d.ts +55 -2
  60. package/dist/mod.d.ts.map +1 -1
  61. package/dist/mod.js +111 -2
  62. package/dist/mod.js.map +1 -1
  63. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/column-builder.js +108 -0
  64. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/column-builder.js.map +1 -0
  65. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/column.js +55 -0
  66. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/column.js.map +1 -0
  67. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/entity.js +18 -0
  68. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/entity.js.map +1 -0
  69. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/columns/common.js +183 -0
  70. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/columns/common.js.map +1 -0
  71. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/columns/enum.js +58 -0
  72. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/columns/enum.js.map +1 -0
  73. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/foreign-keys.js +68 -0
  74. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/foreign-keys.js.map +1 -0
  75. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/unique-constraint.js +56 -0
  76. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/unique-constraint.js.map +1 -0
  77. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/utils/array.js +65 -0
  78. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/utils/array.js.map +1 -0
  79. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/conditions.js +81 -0
  80. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/conditions.js.map +1 -0
  81. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/select.js +13 -0
  82. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/select.js.map +1 -0
  83. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/functions/aggregate.js +10 -0
  84. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/functions/aggregate.js.map +1 -0
  85. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/sql.js +372 -0
  86. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/sql.js.map +1 -0
  87. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/subquery.js +23 -0
  88. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/subquery.js.map +1 -0
  89. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.js +62 -0
  90. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.js.map +1 -0
  91. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.utils.js +6 -0
  92. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.utils.js.map +1 -0
  93. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing-utils.js +8 -0
  94. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing-utils.js.map +1 -0
  95. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing.js +8 -0
  96. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing.js.map +1 -0
  97. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/view-common.js +6 -0
  98. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/view-common.js.map +1 -0
  99. package/dist/query/condition-builder.d.ts +41 -0
  100. package/dist/query/condition-builder.d.ts.map +1 -0
  101. package/dist/query/condition-builder.js +93 -0
  102. package/dist/query/condition-builder.js.map +1 -0
  103. package/dist/query/cursor.d.ts +88 -0
  104. package/dist/query/cursor.d.ts.map +1 -0
  105. package/dist/query/cursor.js +103 -0
  106. package/dist/query/cursor.js.map +1 -0
  107. package/dist/query/orm/orm.d.ts +18 -0
  108. package/dist/query/orm/orm.d.ts.map +1 -0
  109. package/dist/query/orm/orm.js +48 -0
  110. package/dist/query/orm/orm.js.map +1 -0
  111. package/dist/query/query.d.ts +79 -0
  112. package/dist/query/query.d.ts.map +1 -0
  113. package/dist/query/query.js +1 -0
  114. package/dist/query/result-transform.js +155 -0
  115. package/dist/query/result-transform.js.map +1 -0
  116. package/dist/query/unit-of-work.d.ts +435 -0
  117. package/dist/query/unit-of-work.d.ts.map +1 -0
  118. package/dist/query/unit-of-work.js +549 -0
  119. package/dist/query/unit-of-work.js.map +1 -0
  120. package/dist/schema/create.d.ts +273 -116
  121. package/dist/schema/create.d.ts.map +1 -1
  122. package/dist/schema/create.js +410 -222
  123. package/dist/schema/create.js.map +1 -1
  124. package/dist/schema/serialize.js +101 -0
  125. package/dist/schema/serialize.js.map +1 -0
  126. package/dist/schema-generator/schema-generator.d.ts +15 -0
  127. package/dist/schema-generator/schema-generator.d.ts.map +1 -0
  128. package/dist/shared/providers.d.ts +6 -0
  129. package/dist/shared/providers.d.ts.map +1 -0
  130. package/dist/util/import-generator.js +26 -0
  131. package/dist/util/import-generator.js.map +1 -0
  132. package/dist/util/parse.js +15 -0
  133. package/dist/util/parse.js.map +1 -0
  134. package/dist/util/types.d.ts +8 -0
  135. package/dist/util/types.d.ts.map +1 -0
  136. package/package.json +63 -2
  137. package/src/adapters/adapters.ts +22 -0
  138. package/src/adapters/drizzle/drizzle-adapter-pglite.test.ts +433 -0
  139. package/src/adapters/drizzle/drizzle-adapter.test.ts +122 -0
  140. package/src/adapters/drizzle/drizzle-adapter.ts +118 -0
  141. package/src/adapters/drizzle/drizzle-query.ts +234 -0
  142. package/src/adapters/drizzle/drizzle-uow-compiler.test.ts +1084 -0
  143. package/src/adapters/drizzle/drizzle-uow-compiler.ts +546 -0
  144. package/src/adapters/drizzle/drizzle-uow-decoder.ts +165 -0
  145. package/src/adapters/drizzle/drizzle-uow-executor.ts +213 -0
  146. package/src/adapters/drizzle/generate.test.ts +643 -0
  147. package/src/adapters/drizzle/generate.ts +481 -0
  148. package/src/adapters/drizzle/join-column-utils.test.ts +79 -0
  149. package/src/adapters/drizzle/join-column-utils.ts +39 -0
  150. package/src/adapters/drizzle/migrate-drizzle.test.ts +226 -0
  151. package/src/adapters/drizzle/shared.ts +22 -0
  152. package/src/adapters/drizzle/test-utils.ts +56 -0
  153. package/src/adapters/kysely/kysely-adapter-pglite.test.ts +789 -0
  154. package/src/adapters/kysely/kysely-adapter.ts +196 -0
  155. package/src/adapters/kysely/kysely-query-builder.test.ts +1344 -0
  156. package/src/adapters/kysely/kysely-query-builder.ts +611 -0
  157. package/src/adapters/kysely/kysely-query-compiler.ts +124 -0
  158. package/src/adapters/kysely/kysely-query.ts +254 -0
  159. package/src/adapters/kysely/kysely-uow-compiler.test.ts +916 -0
  160. package/src/adapters/kysely/kysely-uow-compiler.ts +271 -0
  161. package/src/adapters/kysely/kysely-uow-executor.ts +149 -0
  162. package/src/adapters/kysely/kysely-uow-joins.test.ts +811 -0
  163. package/src/adapters/kysely/migration/execute-mysql.test.ts +1173 -0
  164. package/src/adapters/kysely/migration/execute-postgres.test.ts +2657 -0
  165. package/src/adapters/kysely/migration/execute.ts +382 -0
  166. package/src/adapters/kysely/migration/kysely-migrator.test.ts +197 -0
  167. package/src/fragment.test.ts +287 -0
  168. package/src/fragment.ts +198 -0
  169. package/src/migration-engine/auto-from-schema.test.ts +118 -58
  170. package/src/migration-engine/auto-from-schema.ts +103 -32
  171. package/src/migration-engine/create.test.ts +34 -46
  172. package/src/migration-engine/create.ts +41 -26
  173. package/src/migration-engine/shared.ts +26 -6
  174. package/src/mod.ts +197 -1
  175. package/src/query/condition-builder.test.ts +379 -0
  176. package/src/query/condition-builder.ts +294 -0
  177. package/src/query/cursor.test.ts +296 -0
  178. package/src/query/cursor.ts +147 -0
  179. package/src/query/orm/orm.ts +92 -0
  180. package/src/query/query-type.test.ts +429 -0
  181. package/src/query/query.ts +200 -0
  182. package/src/query/result-transform.test.ts +795 -0
  183. package/src/query/result-transform.ts +247 -0
  184. package/src/query/unit-of-work-types.test.ts +192 -0
  185. package/src/query/unit-of-work.test.ts +947 -0
  186. package/src/query/unit-of-work.ts +1199 -0
  187. package/src/schema/create.test.ts +653 -110
  188. package/src/schema/create.ts +708 -337
  189. package/src/schema/serialize.test.ts +559 -0
  190. package/src/schema/serialize.ts +359 -0
  191. package/src/schema-generator/schema-generator.ts +12 -0
  192. package/src/shared/config.ts +0 -8
  193. package/src/util/import-generator.ts +28 -0
  194. package/src/util/parse.ts +16 -0
  195. package/src/util/types.ts +4 -0
  196. package/tsconfig.json +1 -1
  197. package/tsdown.config.ts +11 -1
  198. package/vitest.config.ts +3 -0
  199. /package/dist/{cuid.js → id.js} +0 -0
  200. /package/src/{cuid.ts → id.ts} +0 -0
@@ -1,4 +1,4 @@
1
- import { createId } from "../cuid.js";
1
+ import { createId } from "../id.js";
2
2
 
3
3
  //#region src/schema/create.ts
4
4
  var RelationInit = class {
@@ -12,37 +12,10 @@ var RelationInit = class {
12
12
  this.referencer = referencer;
13
13
  }
14
14
  };
15
- /**
16
- * Helper function to add an index to a table's index array
17
- */
18
- function addIndexToTable(indexes, name, columns, unique) {
19
- indexes.push({
20
- name,
21
- columns,
22
- unique
23
- });
24
- }
25
15
  var ExplicitRelationInit = class extends RelationInit {
26
- foreignKeyName;
27
- initForeignKey(ormName) {
28
- const columns = [];
29
- const referencedColumns = [];
30
- for (const [left, right] of this.on) {
31
- columns.push(this.referencer.columns[left]);
32
- referencedColumns.push(this.referencedTable.columns[right]);
33
- }
34
- return {
35
- columns,
36
- referencedColumns,
37
- referencedTable: this.referencedTable,
38
- table: this.referencer,
39
- name: this.foreignKeyName ?? `${this.referencer.ormName}_${this.referencedTable.ormName}_${ormName}_fk`
40
- };
41
- }
42
16
  init(ormName) {
43
17
  return {
44
18
  id: `${this.referencer.ormName}_${this.referencedTable.ormName}`,
45
- foreignKey: this.initForeignKey(ormName),
46
19
  on: this.on,
47
20
  name: ormName,
48
21
  referencer: this.referencer,
@@ -50,23 +23,16 @@ var ExplicitRelationInit = class extends RelationInit {
50
23
  type: this.type
51
24
  };
52
25
  }
53
- /**
54
- * Define custom foreign key name.
55
- */
56
- foreignKey(name) {
57
- this.foreignKeyName = name;
58
- return this;
59
- }
60
26
  };
61
- var Column = class Column {
27
+ var Column = class {
62
28
  type;
63
29
  name = "";
64
30
  ormName = "";
65
31
  isNullable = false;
66
- isUnique = false;
67
- isReference = false;
32
+ role = "regular";
33
+ isHidden = false;
68
34
  default;
69
- table = void 0;
35
+ tableName = "";
70
36
  constructor(type) {
71
37
  this.type = type;
72
38
  }
@@ -74,6 +40,10 @@ var Column = class Column {
74
40
  this.isNullable = nullable ?? true;
75
41
  return this;
76
42
  }
43
+ hidden(hidden) {
44
+ this.isHidden = hidden ?? true;
45
+ return this;
46
+ }
77
47
  /**
78
48
  * Generate default value on runtime
79
49
  */
@@ -90,20 +60,6 @@ var Column = class Column {
90
60
  this.default = { value };
91
61
  return this;
92
62
  }
93
- clone() {
94
- const clone = new Column(this.type);
95
- clone.name = this.name;
96
- clone.ormName = this.ormName;
97
- clone.isNullable = this.isNullable;
98
- clone.isUnique = this.isUnique;
99
- clone.isReference = this.isReference;
100
- clone.default = this.default;
101
- clone.table = this.table;
102
- return clone;
103
- }
104
- getUniqueConstraintName() {
105
- return `unique_c_${this.table.ormName}_${this.ormName}`;
106
- }
107
63
  /**
108
64
  * Generate default value for the column on runtime.
109
65
  */
@@ -114,26 +70,19 @@ var Column = class Column {
114
70
  if (this.default.runtime === "now") return new Date(Date.now());
115
71
  return this.default.runtime();
116
72
  }
117
- get $in() {
118
- throw new Error("Type inference only");
119
- }
120
- get $out() {
121
- throw new Error("Type inference only");
122
- }
73
+ /**
74
+ * @description This is used for type inference only. Runtime value will be undefined.
75
+ * @internal
76
+ */
77
+ get $in() {}
78
+ /**
79
+ * @description This is used for type inference only. Runtime value will be undefined.
80
+ * @internal
81
+ */
82
+ get $out() {}
123
83
  };
124
- var IdColumn = class IdColumn extends Column {
84
+ var IdColumn = class extends Column {
125
85
  id = true;
126
- clone() {
127
- const clone = new IdColumn(this.type);
128
- clone.name = this.name;
129
- clone.ormName = this.ormName;
130
- clone.isNullable = this.isNullable;
131
- clone.isUnique = this.isUnique;
132
- clone.isReference = this.isReference;
133
- clone.default = this.default;
134
- clone.table = this.table;
135
- return clone;
136
- }
137
86
  defaultTo$(fn) {
138
87
  return super.defaultTo$(fn);
139
88
  }
@@ -141,73 +90,206 @@ var IdColumn = class IdColumn extends Column {
141
90
  return super.defaultTo(value);
142
91
  }
143
92
  };
93
+ /**
94
+ * Internal ID column - used for database-native joins and foreign keys.
95
+ * Hidden from user API by default.
96
+ */
97
+ var InternalIdColumn = class extends Column {
98
+ role = "internal-id";
99
+ constructor() {
100
+ super("bigint");
101
+ this.hidden();
102
+ }
103
+ };
104
+ /**
105
+ * Version column - used for optimistic concurrency control.
106
+ * Automatically incremented on each update.
107
+ */
108
+ var VersionColumn = class extends Column {
109
+ role = "version";
110
+ constructor() {
111
+ super("integer");
112
+ this.defaultTo(0).hidden();
113
+ }
114
+ };
144
115
  function column(type) {
145
116
  return new Column(type);
146
117
  }
147
118
  /**
148
- * Create a reference column that points to another table.
119
+ * Create a reference column that points to another table's internal ID.
149
120
  * This is used for foreign key relationships.
121
+ * Always uses bigint to match the internal ID type.
150
122
  */
151
- function referenceColumn(type) {
152
- const col = new Column(type ?? "varchar(30)");
153
- col.isReference = true;
123
+ function referenceColumn() {
124
+ const col = new Column("bigint");
125
+ col.role = "reference";
154
126
  return col;
155
127
  }
128
+ /**
129
+ * Create an external ID column (user-facing).
130
+ * This is a CUID string that can be auto-generated or user-provided.
131
+ * Input accepts string | FragnoId | null, output returns FragnoId.
132
+ */
156
133
  function idColumn() {
157
134
  const col = new IdColumn("varchar(30)");
135
+ col.role = "external-id";
158
136
  col.defaultTo$("auto");
159
137
  return col;
160
138
  }
161
- var TableBuilder = class TableBuilder {
139
+ /**
140
+ * Create an internal ID column (database-native, hidden from user API).
141
+ * Used for joins and foreign keys.
142
+ * @internal
143
+ */
144
+ function internalIdColumn() {
145
+ const col = new InternalIdColumn();
146
+ col.role = "internal-id";
147
+ col.hidden();
148
+ return col;
149
+ }
150
+ /**
151
+ * Create a version column for optimistic concurrency control.
152
+ * @internal
153
+ */
154
+ function versionColumn() {
155
+ const col = new VersionColumn();
156
+ col.role = "version";
157
+ col.hidden();
158
+ return col;
159
+ }
160
+ /**
161
+ * FragnoId represents a unified ID object that can contain external ID, internal ID, or both.
162
+ * @internal
163
+ *
164
+ * For query inputs: externalId is sufficient (internalId is optional)
165
+ * For query results: both externalId and internalId are provided
166
+ */
167
+ var FragnoId = class FragnoId {
168
+ #externalId;
169
+ #internalId;
170
+ #version;
171
+ constructor({ externalId, internalId, version }) {
172
+ this.#externalId = externalId;
173
+ this.#internalId = internalId;
174
+ this.#version = version;
175
+ }
176
+ /**
177
+ * Create a FragnoId from just an external ID (for inputs)
178
+ */
179
+ static fromExternal(externalId, version) {
180
+ return new FragnoId({
181
+ externalId,
182
+ version
183
+ });
184
+ }
185
+ get version() {
186
+ return this.#version;
187
+ }
188
+ get externalId() {
189
+ return this.#externalId;
190
+ }
191
+ get internalId() {
192
+ return this.#internalId;
193
+ }
194
+ /**
195
+ * Get the appropriate ID for database operations
196
+ * Prefers internal ID if available, falls back to external ID
197
+ */
198
+ get databaseId() {
199
+ return this.#internalId ?? this.#externalId;
200
+ }
201
+ /**
202
+ * Convert to a plain object for serialization
203
+ */
204
+ toJSON() {
205
+ return {
206
+ externalId: this.#externalId,
207
+ internalId: this.#internalId?.toString()
208
+ };
209
+ }
210
+ toString() {
211
+ return this.#externalId;
212
+ }
213
+ valueOf() {
214
+ return this.#externalId;
215
+ }
216
+ };
217
+ /**
218
+ * FragnoReference represents a foreign key reference to another table's internal ID.
219
+ * Unlike FragnoId, it only contains the internal ID (bigint) of the referenced record.
220
+ * This is used for reference columns in query results.
221
+ * @internal
222
+ */
223
+ var FragnoReference = class FragnoReference {
224
+ #internalId;
225
+ constructor(internalId) {
226
+ this.#internalId = internalId;
227
+ }
228
+ /**
229
+ * Create a FragnoReference from an internal ID
230
+ */
231
+ static fromInternal(internalId) {
232
+ return new FragnoReference(internalId);
233
+ }
234
+ /**
235
+ * Get the internal ID for database operations
236
+ */
237
+ get internalId() {
238
+ return this.#internalId;
239
+ }
240
+ };
241
+ var TableBuilder = class {
162
242
  #name;
163
243
  #columns;
164
244
  #relations;
165
- #foreignKeys = [];
166
- #indexes = [];
167
- #version = 0;
245
+ #indexes;
168
246
  #ormName = "";
169
- #operations = [];
247
+ #columnOrder = [];
170
248
  constructor(name) {
171
249
  this.#name = name;
172
250
  this.#columns = {};
173
251
  this.#relations = {};
252
+ this.#indexes = {};
253
+ }
254
+ setColumns(columns) {
255
+ this.#columns = { ...columns };
256
+ }
257
+ setRelations(relations) {
258
+ this.#relations = { ...relations };
259
+ }
260
+ setIndexes(indexes) {
261
+ this.#indexes = { ...indexes };
262
+ }
263
+ getIndexes() {
264
+ return Object.values(this.#indexes);
265
+ }
266
+ getColumnOrder() {
267
+ return this.#columnOrder;
174
268
  }
175
269
  addColumn(ormName, colOrType) {
176
- this.#version++;
177
270
  const col = typeof colOrType === "string" ? column(colOrType) : colOrType;
178
- const builder = new TableBuilder(this.#name);
179
- builder.#columns = {
180
- ...this.#columns,
181
- [ormName]: col
182
- };
183
- builder.#relations = this.#relations;
184
- builder.#foreignKeys = this.#foreignKeys;
185
- builder.#indexes = this.#indexes;
186
- builder.#version = this.#version;
187
- builder.#ormName = this.#ormName;
188
- builder.#operations = this.#operations;
189
271
  col.ormName = ormName;
190
272
  col.name = ormName;
191
- return builder;
273
+ this.#columns[ormName] = col;
274
+ this.#columnOrder.push(ormName);
275
+ return this;
192
276
  }
193
277
  /**
194
- * Create an index on the specified columns. Increments the version counter.
278
+ * Create an index on the specified columns.
195
279
  */
196
280
  createIndex(name, columns, options) {
197
- this.#version++;
198
- const cols = columns.map((name$1) => {
199
- const column$1 = this.#columns[name$1];
200
- if (!column$1) throw new Error(`Unknown column name ${name$1}`);
281
+ const cols = columns.map((colName) => {
282
+ const column$1 = this.#columns[colName];
283
+ if (!column$1) throw new Error(`Unknown column name ${colName}`);
201
284
  return column$1;
202
285
  });
203
286
  const unique = options?.unique ?? false;
204
- addIndexToTable(this.#indexes, name, cols, unique);
205
- this.#operations.push({
206
- type: "add-index",
287
+ this.#indexes[name] = {
207
288
  name,
208
- columns,
289
+ columns: cols,
290
+ columnNames: columns,
209
291
  unique
210
- });
292
+ };
211
293
  return this;
212
294
  }
213
295
  /**
@@ -215,13 +297,26 @@ var TableBuilder = class TableBuilder {
215
297
  */
216
298
  build() {
217
299
  let idCol;
300
+ let internalIdCol;
301
+ let versionCol;
302
+ if (!this.#columns["_internalId"]) {
303
+ const col = internalIdColumn();
304
+ col.ormName = "_internalId";
305
+ col.name = "_internalId";
306
+ this.#columns["_internalId"] = col;
307
+ }
308
+ if (!this.#columns["_version"]) {
309
+ const col = versionColumn();
310
+ col.ormName = "_version";
311
+ col.name = "_version";
312
+ this.#columns["_version"] = col;
313
+ }
218
314
  const ormName = this.#ormName || this.#name;
219
- const table$1 = {
315
+ const table = {
220
316
  name: this.#name,
221
317
  ormName,
222
318
  columns: this.#columns,
223
319
  relations: this.#relations,
224
- foreignKeys: this.#foreignKeys,
225
320
  indexes: this.#indexes,
226
321
  getColumnByName: (name) => {
227
322
  return Object.values(this.#columns).find((c) => c.name === name);
@@ -229,165 +324,234 @@ var TableBuilder = class TableBuilder {
229
324
  getIdColumn: () => {
230
325
  return idCol;
231
326
  },
232
- clone: () => {
233
- const cloneColumns = {};
234
- for (const [k, v] of Object.entries(this.#columns)) cloneColumns[k] = v.clone();
235
- const builder = new TableBuilder(this.#name);
236
- builder.#columns = cloneColumns;
237
- builder.#relations = this.#relations;
238
- builder.#foreignKeys = [...this.#foreignKeys];
239
- builder.#indexes = [...this.#indexes];
240
- builder.#version = this.#version;
241
- builder.#ormName = this.#ormName;
242
- builder.#operations = [...this.#operations];
243
- return builder.build();
327
+ getInternalIdColumn: () => {
328
+ return internalIdCol;
329
+ },
330
+ getVersionColumn: () => {
331
+ return versionCol;
244
332
  }
245
333
  };
246
334
  for (const k in this.#columns) {
247
335
  const column$1 = this.#columns[k];
248
336
  if (!column$1) continue;
249
- column$1.table = table$1;
250
- if (column$1 instanceof IdColumn) idCol = column$1;
337
+ column$1.tableName = table.name;
338
+ if (column$1 instanceof IdColumn || column$1.role === "external-id") idCol = column$1;
339
+ if (column$1 instanceof InternalIdColumn || column$1.role === "internal-id") internalIdCol = column$1;
340
+ if (column$1 instanceof VersionColumn || column$1.role === "version") versionCol = column$1;
251
341
  }
252
342
  if (idCol === void 0) throw new Error(`there's no id column in your table ${this.#name}`);
253
- return table$1;
254
- }
255
- /**
256
- * Get the current version of the table builder.
257
- */
258
- getVersion() {
259
- return this.#version;
260
- }
261
- /**
262
- * Get the operations performed on this table.
263
- */
264
- getOperations() {
265
- return this.#operations;
343
+ if (internalIdCol === void 0) throw new Error(`there's no internal id column in your table ${this.#name}`);
344
+ if (versionCol === void 0) throw new Error(`there's no version column in your table ${this.#name}`);
345
+ return table;
266
346
  }
267
347
  };
268
- /**
269
- * Create a new table with callback pattern.
270
- */
271
- function table(name, callback) {
272
- const builder = new TableBuilder(name);
273
- return callback(builder).build();
274
- }
275
348
  var SchemaBuilder = class SchemaBuilder {
276
349
  #tables;
277
350
  #version = 0;
278
351
  #operations = [];
279
- constructor() {
280
- this.#tables = {};
352
+ constructor(existingSchema) {
353
+ if (existingSchema) {
354
+ this.#tables = existingSchema.tables;
355
+ this.#version = existingSchema.version;
356
+ this.#operations = [...existingSchema.operations];
357
+ } else this.#tables = {};
358
+ }
359
+ /**
360
+ * Add an existing schema to this builder.
361
+ * Merges tables and operations from the provided schema.
362
+ *
363
+ * @example
364
+ * ```ts
365
+ * const builder = new SchemaBuilder()
366
+ * .add(userSchema)
367
+ * .add(postSchema)
368
+ * .addTable("comments", ...);
369
+ * ```
370
+ */
371
+ mergeWithExistingSchema(schema$1) {
372
+ this.#tables = {
373
+ ...this.#tables,
374
+ ...schema$1.tables
375
+ };
376
+ this.#operations = [...this.#operations, ...schema$1.operations];
377
+ this.#version += schema$1.version;
378
+ return this;
281
379
  }
282
380
  /**
283
381
  * Add a table to the schema. Increments the version counter.
284
382
  */
285
383
  addTable(ormName, callback) {
286
384
  this.#version++;
287
- const tableBuilder = new TableBuilder(ormName);
288
- const result = callback(tableBuilder);
385
+ const result = callback(new TableBuilder(ormName));
289
386
  const builtTable = result.build();
290
387
  builtTable.ormName = ormName;
291
- const builder = new SchemaBuilder();
292
- builder.#tables = {
388
+ const subOperations = [];
389
+ const columnOrder = result.getColumnOrder();
390
+ for (const colName of columnOrder) {
391
+ const col = builtTable.columns[colName];
392
+ subOperations.push({
393
+ type: "add-column",
394
+ columnName: colName,
395
+ column: col
396
+ });
397
+ }
398
+ if (builtTable.columns["_internalId"]) subOperations.push({
399
+ type: "add-column",
400
+ columnName: "_internalId",
401
+ column: builtTable.columns["_internalId"]
402
+ });
403
+ if (builtTable.columns["_version"]) subOperations.push({
404
+ type: "add-column",
405
+ columnName: "_version",
406
+ column: builtTable.columns["_version"]
407
+ });
408
+ for (const idx of result.getIndexes()) subOperations.push({
409
+ type: "add-index",
410
+ name: idx.name,
411
+ columns: idx.columns.map((c) => c.ormName),
412
+ unique: idx.unique
413
+ });
414
+ this.#operations.push({
415
+ type: "add-table",
416
+ tableName: ormName,
417
+ operations: subOperations
418
+ });
419
+ this.#tables = {
293
420
  ...this.#tables,
294
421
  [ormName]: builtTable
295
422
  };
296
- const newOperations = [...this.#operations, {
297
- type: "add-table",
298
- tableName: ormName,
299
- table: builtTable
300
- }];
301
- const tableOps = result.getOperations();
302
- for (const tableOp of tableOps) if (tableOp.type === "add-index") {
303
- this.#version++;
304
- newOperations.push({
305
- type: "add-index",
306
- tableName: ormName,
307
- name: tableOp.name,
308
- columns: tableOp.columns,
309
- unique: tableOp.unique
310
- });
311
- }
312
- builder.#version = this.#version;
313
- builder.#operations = newOperations;
314
- return builder;
423
+ return this;
315
424
  }
316
425
  /**
317
- * Add a foreign key reference from this table to another table.
426
+ * Add a relation between two tables.
318
427
  *
319
- * @param tableName - The table that has the foreign key column
320
- * @param referenceName - A name for this reference (e.g., "author", "category")
321
- * @param config - Configuration specifying the foreign key mapping
428
+ * @param referenceName - A name for this relation (e.g., "author", "posts")
429
+ * @param config - Configuration specifying the relation type and foreign key mapping
322
430
  *
323
431
  * @example
324
432
  * ```ts
325
- * // Basic foreign key: post -> user
433
+ * // One-to-one or many-to-one: post -> user
326
434
  * schema(s => s
327
435
  * .addTable("users", t => t.addColumn("id", idColumn()))
328
436
  * .addTable("posts", t => t
329
437
  * .addColumn("id", idColumn())
330
- * .addColumn("authorId", referenceColumn()))
331
- * .addReference("posts", "author", {
332
- * columns: ["authorId"],
333
- * targetTable: "users",
334
- * targetColumns: ["id"],
438
+ * .addColumn("userId", referenceColumn()))
439
+ * .addReference("author", {
440
+ * type: "one",
441
+ * from: { table: "posts", column: "userId" },
442
+ * to: { table: "users", column: "id" },
335
443
  * })
336
444
  * )
337
445
  *
338
- * // Self-referencing foreign key
339
- * .addReference("users", "inviter", {
340
- * columns: ["invitedBy"],
341
- * targetTable: "users",
342
- * targetColumns: ["id"],
446
+ * // One-to-many (inverse relation): user -> posts
447
+ * .addReference("posts", {
448
+ * type: "many",
449
+ * from: { table: "users", column: "id" },
450
+ * to: { table: "posts", column: "userId" },
343
451
  * })
344
452
  *
345
- * // Multiple foreign keys - call addReference multiple times
346
- * .addReference("posts", "author", {
347
- * columns: ["authorId"],
348
- * targetTable: "users",
349
- * targetColumns: ["id"],
350
- * })
351
- * .addReference("posts", "category", {
352
- * columns: ["categoryId"],
353
- * targetTable: "categories",
354
- * targetColumns: ["id"],
453
+ * // Self-referencing foreign key
454
+ * .addReference("inviter", {
455
+ * type: "one",
456
+ * from: { table: "users", column: "invitedBy" },
457
+ * to: { table: "users", column: "id" },
355
458
  * })
356
459
  * ```
357
460
  */
358
- addReference(tableName, referenceName, config) {
461
+ addReference(referenceName, config) {
359
462
  this.#version++;
360
- const table$1 = this.#tables[tableName];
361
- const referencedTable = this.#tables[config.targetTable];
362
- if (!table$1) throw new Error(`Table ${tableName} not found in schema`);
363
- if (!referencedTable) throw new Error(`Referenced table ${config.targetTable} not found in schema`);
364
- const { columns, targetColumns } = config;
365
- if (columns.length !== targetColumns.length) throw new Error(`Reference ${referenceName}: columns and targetColumns must have the same length`);
366
- if (columns.length !== 1) throw new Error(`Reference ${referenceName}: currently only single column foreign keys are supported`);
367
- const columnName = columns[0];
368
- const targetColumnName = targetColumns[0];
369
- const column$1 = table$1.columns[columnName];
370
- const referencedColumn = referencedTable.columns[targetColumnName];
371
- if (!column$1) throw new Error(`Column ${columnName} not found in table ${tableName}`);
372
- if (!referencedColumn) throw new Error(`Column ${targetColumnName} not found in table ${config.targetTable}`);
373
- const init = new ExplicitRelationInit("one", referencedTable, table$1);
463
+ const table = this.#tables[config.from.table];
464
+ const referencedTable = this.#tables[config.to.table];
465
+ if (!table) throw new Error(`Table ${config.from.table} not found in schema`);
466
+ if (!referencedTable) throw new Error(`Referenced table ${config.to.table} not found in schema`);
467
+ const columnName = config.from.column;
468
+ const targetColumnName = config.to.column;
469
+ const actualTargetColumnName = targetColumnName === "id" ? "_internalId" : targetColumnName;
470
+ const column$1 = table.columns[columnName];
471
+ const referencedColumn = referencedTable.columns[actualTargetColumnName];
472
+ if (!column$1) throw new Error(`Column ${columnName} not found in table ${config.from.table}`);
473
+ if (!referencedColumn) throw new Error(`Column ${actualTargetColumnName} not found in table ${config.to.table}`);
474
+ if (column$1.role === "reference" && column$1.type !== "bigint") throw new Error(`Reference column ${columnName} must be of type bigint to match internal ID type`);
475
+ const init = new ExplicitRelationInit(config.type, referencedTable, table);
374
476
  init.on.push([columnName, targetColumnName]);
375
477
  const relation = init.init(referenceName);
376
- table$1.relations[referenceName] = relation;
377
- table$1.foreignKeys.push(relation.foreignKey);
478
+ table.relations[referenceName] = relation;
378
479
  this.#operations.push({
379
480
  type: "add-reference",
380
- tableName,
481
+ tableName: config.from.table,
381
482
  referenceName,
382
483
  config: {
383
- columns,
384
- targetTable: config.targetTable,
385
- targetColumns
484
+ type: config.type,
485
+ from: {
486
+ table: config.from.table,
487
+ column: columnName
488
+ },
489
+ to: {
490
+ table: config.to.table,
491
+ column: actualTargetColumnName
492
+ }
386
493
  }
387
494
  });
388
495
  return this;
389
496
  }
390
497
  /**
498
+ * Alter an existing table by adding columns or indexes.
499
+ * This is used for append-only schema modifications.
500
+ *
501
+ * @param tableName - The name of the table to modify
502
+ * @param callback - A callback that receives a table builder for adding columns/indexes
503
+ *
504
+ * @example
505
+ * ```ts
506
+ * // Add a new column to an existing table
507
+ * schema(s => s
508
+ * .addTable("users", t => t
509
+ * .addColumn("id", idColumn())
510
+ * .addColumn("name", column("string")))
511
+ * .alterTable("users", t => t
512
+ * .addColumn("email", column("string"))
513
+ * .addColumn("age", column("integer").nullable())
514
+ * .createIndex("idx_email", ["email"]))
515
+ * )
516
+ * ```
517
+ */
518
+ alterTable(tableName, callback) {
519
+ const table = this.#tables[tableName];
520
+ if (!table) throw new Error(`Table ${tableName} not found in schema`);
521
+ const tableBuilder = new TableBuilder(tableName);
522
+ tableBuilder.setColumns(table.columns);
523
+ tableBuilder.setRelations(table.relations);
524
+ tableBuilder.setIndexes(table.indexes);
525
+ const existingColumns = new Set(Object.keys(table.columns));
526
+ const existingIndexes = new Set(Object.keys(table.indexes));
527
+ const resultBuilder = callback(tableBuilder);
528
+ const newTable = resultBuilder.build();
529
+ const subOperations = [];
530
+ const columnOrder = resultBuilder.getColumnOrder();
531
+ for (const colName of columnOrder) if (!existingColumns.has(colName)) subOperations.push({
532
+ type: "add-column",
533
+ columnName: colName,
534
+ column: newTable.columns[colName]
535
+ });
536
+ for (const idx of resultBuilder.getIndexes()) if (!existingIndexes.has(idx.name)) subOperations.push({
537
+ type: "add-index",
538
+ name: idx.name,
539
+ columns: idx.columns.map((c) => c.ormName),
540
+ unique: idx.unique
541
+ });
542
+ if (subOperations.length > 0) {
543
+ this.#version++;
544
+ this.#operations.push({
545
+ type: "alter-table",
546
+ tableName,
547
+ operations: subOperations
548
+ });
549
+ }
550
+ this.#tables[tableName] = newTable;
551
+ for (const col of Object.values(newTable.columns)) col.tableName = newTable.name;
552
+ return this;
553
+ }
554
+ /**
391
555
  * Build the final schema. This should be called after all tables are added.
392
556
  */
393
557
  build() {
@@ -400,12 +564,36 @@ var SchemaBuilder = class SchemaBuilder {
400
564
  operations,
401
565
  clone: () => {
402
566
  const cloneTables = {};
403
- for (const [k, v] of Object.entries(tables)) cloneTables[k] = v.clone();
404
- const builder = new SchemaBuilder();
405
- builder.#tables = cloneTables;
406
- builder.#version = version;
407
- builder.#operations = [...operations];
408
- return builder.build();
567
+ for (const [k, v] of Object.entries(tables)) {
568
+ const clonedColumns = {};
569
+ for (const [colName, col] of Object.entries(v.columns)) {
570
+ let clonedCol;
571
+ if (col instanceof InternalIdColumn) clonedCol = new InternalIdColumn();
572
+ else if (col instanceof VersionColumn) clonedCol = new VersionColumn();
573
+ else if (col instanceof IdColumn) clonedCol = new IdColumn(col.type);
574
+ else clonedCol = new Column(col.type);
575
+ clonedCol.name = col.name;
576
+ clonedCol.ormName = col.ormName;
577
+ clonedCol.isNullable = col.isNullable;
578
+ clonedCol.role = col.role;
579
+ clonedCol.isHidden = col.isHidden;
580
+ clonedCol.default = col.default;
581
+ clonedCol.tableName = col.tableName;
582
+ clonedColumns[colName] = clonedCol;
583
+ }
584
+ cloneTables[k] = {
585
+ ...v,
586
+ columns: clonedColumns
587
+ };
588
+ }
589
+ return new SchemaBuilder({
590
+ version,
591
+ tables: cloneTables,
592
+ operations: [...operations],
593
+ clone: () => {
594
+ throw new Error("Cannot clone during clone");
595
+ }
596
+ }).build();
409
597
  }
410
598
  };
411
599
  }
@@ -422,16 +610,16 @@ var SchemaBuilder = class SchemaBuilder {
422
610
  function schema(callback) {
423
611
  return callback(new SchemaBuilder()).build();
424
612
  }
425
- function compileForeignKey(key) {
613
+ function compileForeignKey(key, nameType = "orm") {
426
614
  return {
427
615
  name: key.name,
428
- table: key.table.name,
429
- referencedTable: key.referencedTable.name,
430
- referencedColumns: key.referencedColumns.map((col) => col.name),
431
- columns: key.columns.map((col) => col.name)
616
+ table: nameType === "sql" ? key.table.name : key.table.ormName,
617
+ referencedTable: nameType === "sql" ? key.referencedTable.name : key.referencedTable.ormName,
618
+ referencedColumns: key.referencedColumns.map((col) => nameType === "sql" ? col.name : col.ormName),
619
+ columns: key.columns.map((col) => nameType === "sql" ? col.name : col.ormName)
432
620
  };
433
621
  }
434
622
 
435
623
  //#endregion
436
- export { Column, ExplicitRelationInit, IdColumn, SchemaBuilder, TableBuilder, column, compileForeignKey, idColumn, referenceColumn, schema, table };
624
+ export { Column, ExplicitRelationInit, FragnoId, FragnoReference, IdColumn, InternalIdColumn, SchemaBuilder, TableBuilder, VersionColumn, column, compileForeignKey, idColumn, internalIdColumn, referenceColumn, schema, versionColumn };
437
625
  //# sourceMappingURL=create.js.map