@fragno-dev/db 0.1.13 → 0.1.15

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 (178) hide show
  1. package/.turbo/turbo-build.log +179 -132
  2. package/CHANGELOG.md +30 -0
  3. package/dist/adapters/adapters.d.ts +27 -1
  4. package/dist/adapters/adapters.d.ts.map +1 -1
  5. package/dist/adapters/adapters.js.map +1 -1
  6. package/dist/adapters/drizzle/drizzle-adapter.d.ts +5 -1
  7. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +1 -1
  8. package/dist/adapters/drizzle/drizzle-adapter.js +15 -3
  9. package/dist/adapters/drizzle/drizzle-adapter.js.map +1 -1
  10. package/dist/adapters/drizzle/drizzle-query.js +7 -5
  11. package/dist/adapters/drizzle/drizzle-query.js.map +1 -1
  12. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts +0 -1
  13. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts.map +1 -1
  14. package/dist/adapters/drizzle/drizzle-uow-compiler.js +76 -44
  15. package/dist/adapters/drizzle/drizzle-uow-compiler.js.map +1 -1
  16. package/dist/adapters/drizzle/drizzle-uow-decoder.js +23 -16
  17. package/dist/adapters/drizzle/drizzle-uow-decoder.js.map +1 -1
  18. package/dist/adapters/drizzle/drizzle-uow-executor.js +18 -7
  19. package/dist/adapters/drizzle/drizzle-uow-executor.js.map +1 -1
  20. package/dist/adapters/drizzle/generate.d.ts +4 -1
  21. package/dist/adapters/drizzle/generate.d.ts.map +1 -1
  22. package/dist/adapters/drizzle/generate.js +11 -18
  23. package/dist/adapters/drizzle/generate.js.map +1 -1
  24. package/dist/adapters/drizzle/shared.d.ts +14 -1
  25. package/dist/adapters/drizzle/shared.d.ts.map +1 -0
  26. package/dist/adapters/kysely/kysely-adapter.d.ts +5 -1
  27. package/dist/adapters/kysely/kysely-adapter.d.ts.map +1 -1
  28. package/dist/adapters/kysely/kysely-adapter.js +14 -3
  29. package/dist/adapters/kysely/kysely-adapter.js.map +1 -1
  30. package/dist/adapters/kysely/kysely-query-builder.js +1 -1
  31. package/dist/adapters/kysely/kysely-query-compiler.js +3 -2
  32. package/dist/adapters/kysely/kysely-query-compiler.js.map +1 -1
  33. package/dist/adapters/kysely/kysely-query.d.ts +1 -0
  34. package/dist/adapters/kysely/kysely-query.d.ts.map +1 -1
  35. package/dist/adapters/kysely/kysely-query.js +28 -19
  36. package/dist/adapters/kysely/kysely-query.js.map +1 -1
  37. package/dist/adapters/kysely/kysely-shared.d.ts +14 -0
  38. package/dist/adapters/kysely/kysely-shared.d.ts.map +1 -0
  39. package/dist/adapters/kysely/kysely-shared.js +16 -1
  40. package/dist/adapters/kysely/kysely-shared.js.map +1 -1
  41. package/dist/adapters/kysely/kysely-uow-compiler.js +68 -16
  42. package/dist/adapters/kysely/kysely-uow-compiler.js.map +1 -1
  43. package/dist/adapters/kysely/kysely-uow-executor.js +8 -4
  44. package/dist/adapters/kysely/kysely-uow-executor.js.map +1 -1
  45. package/dist/adapters/kysely/migration/execute-base.js +1 -1
  46. package/dist/adapters/kysely/migration/execute-base.js.map +1 -1
  47. package/dist/db-fragment-definition-builder.d.ts +152 -0
  48. package/dist/db-fragment-definition-builder.d.ts.map +1 -0
  49. package/dist/db-fragment-definition-builder.js +137 -0
  50. package/dist/db-fragment-definition-builder.js.map +1 -0
  51. package/dist/fragments/internal-fragment.d.ts +19 -0
  52. package/dist/fragments/internal-fragment.d.ts.map +1 -0
  53. package/dist/fragments/internal-fragment.js +39 -0
  54. package/dist/fragments/internal-fragment.js.map +1 -0
  55. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  56. package/dist/migration-engine/generation-engine.js +35 -15
  57. package/dist/migration-engine/generation-engine.js.map +1 -1
  58. package/dist/mod.d.ts +8 -18
  59. package/dist/mod.d.ts.map +1 -1
  60. package/dist/mod.js +7 -34
  61. package/dist/mod.js.map +1 -1
  62. package/dist/node_modules/.pnpm/rou3@0.7.8/node_modules/rou3/dist/index.js +165 -0
  63. package/dist/node_modules/.pnpm/rou3@0.7.8/node_modules/rou3/dist/index.js.map +1 -0
  64. package/dist/packages/fragno/dist/api/bind-services.js +20 -0
  65. package/dist/packages/fragno/dist/api/bind-services.js.map +1 -0
  66. package/dist/packages/fragno/dist/api/error.js +48 -0
  67. package/dist/packages/fragno/dist/api/error.js.map +1 -0
  68. package/dist/packages/fragno/dist/api/fragment-definition-builder.js +320 -0
  69. package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +1 -0
  70. package/dist/packages/fragno/dist/api/fragment-instantiator.js +487 -0
  71. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +1 -0
  72. package/dist/packages/fragno/dist/api/fragno-response.js +73 -0
  73. package/dist/packages/fragno/dist/api/fragno-response.js.map +1 -0
  74. package/dist/packages/fragno/dist/api/internal/response-stream.js +81 -0
  75. package/dist/packages/fragno/dist/api/internal/response-stream.js.map +1 -0
  76. package/dist/packages/fragno/dist/api/internal/route.js +10 -0
  77. package/dist/packages/fragno/dist/api/internal/route.js.map +1 -0
  78. package/dist/packages/fragno/dist/api/mutable-request-state.js +97 -0
  79. package/dist/packages/fragno/dist/api/mutable-request-state.js.map +1 -0
  80. package/dist/packages/fragno/dist/api/request-context-storage.js +43 -0
  81. package/dist/packages/fragno/dist/api/request-context-storage.js.map +1 -0
  82. package/dist/packages/fragno/dist/api/request-input-context.js +118 -0
  83. package/dist/packages/fragno/dist/api/request-input-context.js.map +1 -0
  84. package/dist/packages/fragno/dist/api/request-middleware.js +83 -0
  85. package/dist/packages/fragno/dist/api/request-middleware.js.map +1 -0
  86. package/dist/packages/fragno/dist/api/request-output-context.js +119 -0
  87. package/dist/packages/fragno/dist/api/request-output-context.js.map +1 -0
  88. package/dist/packages/fragno/dist/api/route.js +17 -0
  89. package/dist/packages/fragno/dist/api/route.js.map +1 -0
  90. package/dist/packages/fragno/dist/internal/symbols.js +10 -0
  91. package/dist/packages/fragno/dist/internal/symbols.js.map +1 -0
  92. package/dist/query/cursor.d.ts +10 -2
  93. package/dist/query/cursor.d.ts.map +1 -1
  94. package/dist/query/cursor.js +11 -4
  95. package/dist/query/cursor.js.map +1 -1
  96. package/dist/query/execute-unit-of-work.d.ts +123 -0
  97. package/dist/query/execute-unit-of-work.d.ts.map +1 -0
  98. package/dist/query/execute-unit-of-work.js +184 -0
  99. package/dist/query/execute-unit-of-work.js.map +1 -0
  100. package/dist/query/query.d.ts +3 -3
  101. package/dist/query/query.d.ts.map +1 -1
  102. package/dist/query/result-transform.js +4 -2
  103. package/dist/query/result-transform.js.map +1 -1
  104. package/dist/query/retry-policy.d.ts +88 -0
  105. package/dist/query/retry-policy.d.ts.map +1 -0
  106. package/dist/query/retry-policy.js +61 -0
  107. package/dist/query/retry-policy.js.map +1 -0
  108. package/dist/query/unit-of-work.d.ts +171 -32
  109. package/dist/query/unit-of-work.d.ts.map +1 -1
  110. package/dist/query/unit-of-work.js +530 -133
  111. package/dist/query/unit-of-work.js.map +1 -1
  112. package/dist/schema/serialize.js +12 -7
  113. package/dist/schema/serialize.js.map +1 -1
  114. package/dist/with-database.d.ts +28 -0
  115. package/dist/with-database.d.ts.map +1 -0
  116. package/dist/with-database.js +34 -0
  117. package/dist/with-database.js.map +1 -0
  118. package/package.json +10 -3
  119. package/src/adapters/adapters.ts +30 -0
  120. package/src/adapters/drizzle/drizzle-adapter-pglite.test.ts +86 -17
  121. package/src/adapters/drizzle/drizzle-adapter-sqlite.test.ts +291 -7
  122. package/src/adapters/drizzle/drizzle-adapter.test.ts +3 -51
  123. package/src/adapters/drizzle/drizzle-adapter.ts +35 -7
  124. package/src/adapters/drizzle/drizzle-query.ts +25 -15
  125. package/src/adapters/drizzle/drizzle-uow-compiler-mysql.test.ts +1442 -0
  126. package/src/adapters/drizzle/drizzle-uow-compiler-sqlite.test.ts +1414 -0
  127. package/src/adapters/drizzle/drizzle-uow-compiler.test.ts +78 -61
  128. package/src/adapters/drizzle/drizzle-uow-compiler.ts +123 -42
  129. package/src/adapters/drizzle/drizzle-uow-decoder.ts +34 -27
  130. package/src/adapters/drizzle/drizzle-uow-executor.ts +41 -8
  131. package/src/adapters/drizzle/generate.test.ts +102 -269
  132. package/src/adapters/drizzle/generate.ts +12 -30
  133. package/src/adapters/drizzle/test-utils.ts +36 -5
  134. package/src/adapters/kysely/kysely-adapter-pglite.test.ts +66 -22
  135. package/src/adapters/kysely/kysely-adapter-sqlite.test.ts +156 -0
  136. package/src/adapters/kysely/kysely-adapter.ts +25 -2
  137. package/src/adapters/kysely/kysely-query-compiler.ts +3 -8
  138. package/src/adapters/kysely/kysely-query.ts +57 -37
  139. package/src/adapters/kysely/kysely-shared.ts +34 -0
  140. package/src/adapters/kysely/kysely-uow-compiler.test.ts +62 -74
  141. package/src/adapters/kysely/kysely-uow-compiler.ts +92 -24
  142. package/src/adapters/kysely/kysely-uow-executor.ts +26 -7
  143. package/src/adapters/kysely/kysely-uow-joins.test.ts +33 -50
  144. package/src/adapters/kysely/migration/execute-base.ts +1 -1
  145. package/src/db-fragment-definition-builder.test.ts +887 -0
  146. package/src/db-fragment-definition-builder.ts +506 -0
  147. package/src/db-fragment-instantiator.test.ts +467 -0
  148. package/src/db-fragment-integration.test.ts +408 -0
  149. package/src/fragments/internal-fragment.test.ts +160 -0
  150. package/src/fragments/internal-fragment.ts +85 -0
  151. package/src/migration-engine/generation-engine.test.ts +58 -15
  152. package/src/migration-engine/generation-engine.ts +78 -25
  153. package/src/mod.ts +35 -43
  154. package/src/query/cursor.test.ts +119 -0
  155. package/src/query/cursor.ts +17 -4
  156. package/src/query/execute-unit-of-work.test.ts +1310 -0
  157. package/src/query/execute-unit-of-work.ts +463 -0
  158. package/src/query/query.ts +4 -4
  159. package/src/query/result-transform.test.ts +129 -0
  160. package/src/query/result-transform.ts +4 -1
  161. package/src/query/retry-policy.test.ts +217 -0
  162. package/src/query/retry-policy.ts +141 -0
  163. package/src/query/unit-of-work-coordinator.test.ts +833 -0
  164. package/src/query/unit-of-work-types.test.ts +15 -2
  165. package/src/query/unit-of-work.test.ts +878 -200
  166. package/src/query/unit-of-work.ts +963 -321
  167. package/src/schema/serialize.ts +22 -11
  168. package/src/with-database.ts +140 -0
  169. package/tsdown.config.ts +1 -0
  170. package/dist/fragment.d.ts +0 -54
  171. package/dist/fragment.d.ts.map +0 -1
  172. package/dist/fragment.js +0 -92
  173. package/dist/fragment.js.map +0 -1
  174. package/dist/shared/settings-schema.js +0 -36
  175. package/dist/shared/settings-schema.js.map +0 -1
  176. package/src/fragment.test.ts +0 -341
  177. package/src/fragment.ts +0 -198
  178. package/src/shared/settings-schema.ts +0 -61
@@ -1,6 +1,7 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
  import { column, idColumn, referenceColumn, schema } from "../../schema/create";
3
3
  import { generateSchema } from "./generate";
4
+ import { settingsSchema } from "../../fragments/internal-fragment";
4
5
 
5
6
  describe("generateSchema", () => {
6
7
  const testSchema = schema((s) => {
@@ -35,26 +36,10 @@ describe("generateSchema", () => {
35
36
  it("should generate PostgreSQL schema", () => {
36
37
  const generated = generateSchema([{ namespace: "test", schema: testSchema }], "postgresql");
37
38
  expect(generated).toMatchInlineSnapshot(`
38
- "import { pgTable, varchar, text, bigserial, integer, uniqueIndex, index, bigint, foreignKey } from "drizzle-orm/pg-core"
39
+ "import { pgTable, varchar, text, integer, bigserial, uniqueIndex, index, bigint, foreignKey } from "drizzle-orm/pg-core"
39
40
  import { createId } from "@fragno-dev/db/id"
40
41
  import { relations } from "drizzle-orm"
41
42
 
42
- // ============================================================================
43
- // Settings Table (shared across all fragments)
44
- // ============================================================================
45
-
46
- export const fragno_db_settings = pgTable("fragno_db_settings", {
47
- id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
48
- key: text("key").notNull(),
49
- value: text("value").notNull(),
50
- _internalId: bigserial("_internalId", { mode: "number" }).primaryKey().notNull(),
51
- _version: integer("_version").notNull().default(0)
52
- }, (table) => [
53
- uniqueIndex("unique_key").on(table.key)
54
- ])
55
-
56
- export const fragnoDbSettingSchemaVersion = 1;
57
-
58
43
  // ============================================================================
59
44
  // Fragment: test
60
45
  // ============================================================================
@@ -122,26 +107,10 @@ describe("generateSchema", () => {
122
107
  it("should generate MySQL schema", () => {
123
108
  const generated = generateSchema([{ namespace: "test", schema: testSchema }], "mysql");
124
109
  expect(generated).toMatchInlineSnapshot(`
125
- "import { mysqlTable, varchar, text, bigint, integer, uniqueIndex, index, foreignKey } from "drizzle-orm/mysql-core"
110
+ "import { mysqlTable, varchar, text, int, bigint, uniqueIndex, index, foreignKey } from "drizzle-orm/mysql-core"
126
111
  import { createId } from "@fragno-dev/db/id"
127
112
  import { relations } from "drizzle-orm"
128
113
 
129
- // ============================================================================
130
- // Settings Table (shared across all fragments)
131
- // ============================================================================
132
-
133
- export const fragno_db_settings = mysqlTable("fragno_db_settings", {
134
- id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
135
- key: text("key").notNull(),
136
- value: text("value").notNull(),
137
- _internalId: bigint("_internalId").primaryKey().autoincrement().notNull(),
138
- _version: integer("_version").notNull().default(0)
139
- }, (table) => [
140
- uniqueIndex("unique_key").on(table.key)
141
- ])
142
-
143
- export const fragnoDbSettingSchemaVersion = 1;
144
-
145
114
  // ============================================================================
146
115
  // Fragment: test
147
116
  // ============================================================================
@@ -150,9 +119,9 @@ describe("generateSchema", () => {
150
119
  id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
151
120
  name: text("name").notNull(),
152
121
  email: text("email").notNull(),
153
- age: integer("age"),
154
- _internalId: bigint("_internalId").primaryKey().autoincrement().notNull(),
155
- _version: integer("_version").notNull().default(0)
122
+ age: int("age"),
123
+ _internalId: bigint("_internalId", { mode: "number" }).primaryKey().autoincrement().notNull(),
124
+ _version: int("_version").notNull().default(0)
156
125
  }, (table) => [
157
126
  uniqueIndex("idx_email_test").on(table.email),
158
127
  index("idx_name_test").on(table.name)
@@ -162,10 +131,10 @@ describe("generateSchema", () => {
162
131
  id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
163
132
  title: text("title").notNull(),
164
133
  content: text("content").notNull(),
165
- userId: bigint("userId").notNull(),
166
- viewCount: integer("viewCount").notNull().default(0),
167
- _internalId: bigint("_internalId").primaryKey().autoincrement().notNull(),
168
- _version: integer("_version").notNull().default(0)
134
+ userId: bigint("userId", { mode: "number" }).notNull(),
135
+ viewCount: int("viewCount").notNull().default(0),
136
+ _internalId: bigint("_internalId", { mode: "number" }).primaryKey().autoincrement().notNull(),
137
+ _version: int("_version").notNull().default(0)
169
138
  }, (table) => [
170
139
  foreignKey({
171
140
  columns: [table.userId],
@@ -213,22 +182,6 @@ describe("generateSchema", () => {
213
182
  import { createId } from "@fragno-dev/db/id"
214
183
  import { relations } from "drizzle-orm"
215
184
 
216
- // ============================================================================
217
- // Settings Table (shared across all fragments)
218
- // ============================================================================
219
-
220
- export const fragno_db_settings = sqliteTable("fragno_db_settings", {
221
- id: text("id").notNull().$defaultFn(() => createId()),
222
- key: text("key").notNull(),
223
- value: text("value").notNull(),
224
- _internalId: integer("_internalId").primaryKey({ autoIncrement: true }).notNull(),
225
- _version: integer("_version").notNull().default(0)
226
- }, (table) => [
227
- uniqueIndex("unique_key").on(table.key)
228
- ])
229
-
230
- export const fragnoDbSettingSchemaVersion = 1;
231
-
232
185
  // ============================================================================
233
186
  // Fragment: test
234
187
  // ============================================================================
@@ -308,25 +261,9 @@ describe("generateSchema", () => {
308
261
  "postgresql",
309
262
  );
310
263
  expect(generated).toMatchInlineSnapshot(`
311
- "import { pgTable, varchar, text, bigserial, integer, uniqueIndex, timestamp } from "drizzle-orm/pg-core"
264
+ "import { pgTable, varchar, timestamp, bigserial, integer } from "drizzle-orm/pg-core"
312
265
  import { createId } from "@fragno-dev/db/id"
313
266
 
314
- // ============================================================================
315
- // Settings Table (shared across all fragments)
316
- // ============================================================================
317
-
318
- export const fragno_db_settings = pgTable("fragno_db_settings", {
319
- id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
320
- key: text("key").notNull(),
321
- value: text("value").notNull(),
322
- _internalId: bigserial("_internalId", { mode: "number" }).primaryKey().notNull(),
323
- _version: integer("_version").notNull().default(0)
324
- }, (table) => [
325
- uniqueIndex("unique_key").on(table.key)
326
- ])
327
-
328
- export const fragnoDbSettingSchemaVersion = 1;
329
-
330
267
  // ============================================================================
331
268
  // Fragment: test
332
269
  // ============================================================================
@@ -361,25 +298,9 @@ describe("generateSchema", () => {
361
298
  "postgresql",
362
299
  );
363
300
  expect(generated).toMatchInlineSnapshot(`
364
- "import { pgTable, varchar, text, bigserial, integer, uniqueIndex, timestamp } from "drizzle-orm/pg-core"
301
+ "import { pgTable, varchar, timestamp, bigserial, integer } from "drizzle-orm/pg-core"
365
302
  import { createId } from "@fragno-dev/db/id"
366
303
 
367
- // ============================================================================
368
- // Settings Table (shared across all fragments)
369
- // ============================================================================
370
-
371
- export const fragno_db_settings = pgTable("fragno_db_settings", {
372
- id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
373
- key: text("key").notNull(),
374
- value: text("value").notNull(),
375
- _internalId: bigserial("_internalId", { mode: "number" }).primaryKey().notNull(),
376
- _version: integer("_version").notNull().default(0)
377
- }, (table) => [
378
- uniqueIndex("unique_key").on(table.key)
379
- ])
380
-
381
- export const fragnoDbSettingSchemaVersion = 1;
382
-
383
304
  // ============================================================================
384
305
  // Fragment: test
385
306
  // ============================================================================
@@ -410,7 +331,7 @@ describe("generateSchema", () => {
410
331
 
411
332
  const generated = generateSchema([{ namespace: "test", schema: binarySchema }], "postgresql");
412
333
  expect(generated).toMatchInlineSnapshot(`
413
- "import { pgTable, varchar, text, bigserial, integer, uniqueIndex, customType } from "drizzle-orm/pg-core"
334
+ "import { pgTable, varchar, customType, bigserial, integer } from "drizzle-orm/pg-core"
414
335
  import { createId } from "@fragno-dev/db/id"
415
336
  const customBinary = customType<
416
337
  {
@@ -429,22 +350,6 @@ describe("generateSchema", () => {
429
350
  }
430
351
  });
431
352
 
432
- // ============================================================================
433
- // Settings Table (shared across all fragments)
434
- // ============================================================================
435
-
436
- export const fragno_db_settings = pgTable("fragno_db_settings", {
437
- id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
438
- key: text("key").notNull(),
439
- value: text("value").notNull(),
440
- _internalId: bigserial("_internalId", { mode: "number" }).primaryKey().notNull(),
441
- _version: integer("_version").notNull().default(0)
442
- }, (table) => [
443
- uniqueIndex("unique_key").on(table.key)
444
- ])
445
-
446
- export const fragnoDbSettingSchemaVersion = 1;
447
-
448
353
  // ============================================================================
449
354
  // Fragment: test
450
355
  // ============================================================================
@@ -496,26 +401,10 @@ describe("generateSchema", () => {
496
401
  "postgresql",
497
402
  );
498
403
  expect(generated).toMatchInlineSnapshot(`
499
- "import { pgTable, varchar, text, bigserial, integer, uniqueIndex, bigint, foreignKey, index } from "drizzle-orm/pg-core"
404
+ "import { pgTable, varchar, text, bigserial, integer, bigint, foreignKey, index } from "drizzle-orm/pg-core"
500
405
  import { createId } from "@fragno-dev/db/id"
501
406
  import { relations } from "drizzle-orm"
502
407
 
503
- // ============================================================================
504
- // Settings Table (shared across all fragments)
505
- // ============================================================================
506
-
507
- export const fragno_db_settings = pgTable("fragno_db_settings", {
508
- id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
509
- key: text("key").notNull(),
510
- value: text("value").notNull(),
511
- _internalId: bigserial("_internalId", { mode: "number" }).primaryKey().notNull(),
512
- _version: integer("_version").notNull().default(0)
513
- }, (table) => [
514
- uniqueIndex("unique_key").on(table.key)
515
- ])
516
-
517
- export const fragnoDbSettingSchemaVersion = 1;
518
-
519
408
  // ============================================================================
520
409
  // Fragment: test
521
410
  // ============================================================================
@@ -576,26 +465,10 @@ describe("generateSchema", () => {
576
465
  it("should generate MySQL schema with many relations", () => {
577
466
  const generated = generateSchema([{ namespace: "test", schema: oneToManySchema }], "mysql");
578
467
  expect(generated).toMatchInlineSnapshot(`
579
- "import { mysqlTable, varchar, text, bigint, integer, uniqueIndex, foreignKey, index } from "drizzle-orm/mysql-core"
468
+ "import { mysqlTable, varchar, text, bigint, int, foreignKey, index } from "drizzle-orm/mysql-core"
580
469
  import { createId } from "@fragno-dev/db/id"
581
470
  import { relations } from "drizzle-orm"
582
471
 
583
- // ============================================================================
584
- // Settings Table (shared across all fragments)
585
- // ============================================================================
586
-
587
- export const fragno_db_settings = mysqlTable("fragno_db_settings", {
588
- id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
589
- key: text("key").notNull(),
590
- value: text("value").notNull(),
591
- _internalId: bigint("_internalId").primaryKey().autoincrement().notNull(),
592
- _version: integer("_version").notNull().default(0)
593
- }, (table) => [
594
- uniqueIndex("unique_key").on(table.key)
595
- ])
596
-
597
- export const fragnoDbSettingSchemaVersion = 1;
598
-
599
472
  // ============================================================================
600
473
  // Fragment: test
601
474
  // ============================================================================
@@ -603,16 +476,16 @@ describe("generateSchema", () => {
603
476
  export const users_test = mysqlTable("users_test", {
604
477
  id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
605
478
  name: text("name").notNull(),
606
- _internalId: bigint("_internalId").primaryKey().autoincrement().notNull(),
607
- _version: integer("_version").notNull().default(0)
479
+ _internalId: bigint("_internalId", { mode: "number" }).primaryKey().autoincrement().notNull(),
480
+ _version: int("_version").notNull().default(0)
608
481
  })
609
482
 
610
483
  export const posts_test = mysqlTable("posts_test", {
611
484
  id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
612
485
  title: text("title").notNull(),
613
- userId: bigint("userId").notNull(),
614
- _internalId: bigint("_internalId").primaryKey().autoincrement().notNull(),
615
- _version: integer("_version").notNull().default(0)
486
+ userId: bigint("userId", { mode: "number" }).notNull(),
487
+ _internalId: bigint("_internalId", { mode: "number" }).primaryKey().autoincrement().notNull(),
488
+ _version: int("_version").notNull().default(0)
616
489
  }, (table) => [
617
490
  foreignKey({
618
491
  columns: [table.userId],
@@ -656,26 +529,10 @@ describe("generateSchema", () => {
656
529
  it("should generate SQLite schema with many relations", () => {
657
530
  const generated = generateSchema([{ namespace: "test", schema: oneToManySchema }], "sqlite");
658
531
  expect(generated).toMatchInlineSnapshot(`
659
- "import { sqliteTable, text, integer, uniqueIndex, foreignKey, index } from "drizzle-orm/sqlite-core"
532
+ "import { sqliteTable, text, integer, foreignKey, index } from "drizzle-orm/sqlite-core"
660
533
  import { createId } from "@fragno-dev/db/id"
661
534
  import { relations } from "drizzle-orm"
662
535
 
663
- // ============================================================================
664
- // Settings Table (shared across all fragments)
665
- // ============================================================================
666
-
667
- export const fragno_db_settings = sqliteTable("fragno_db_settings", {
668
- id: text("id").notNull().$defaultFn(() => createId()),
669
- key: text("key").notNull(),
670
- value: text("value").notNull(),
671
- _internalId: integer("_internalId").primaryKey({ autoIncrement: true }).notNull(),
672
- _version: integer("_version").notNull().default(0)
673
- }, (table) => [
674
- uniqueIndex("unique_key").on(table.key)
675
- ])
676
-
677
- export const fragnoDbSettingSchemaVersion = 1;
678
-
679
536
  // ============================================================================
680
537
  // Fragment: test
681
538
  // ============================================================================
@@ -772,26 +629,10 @@ describe("generateSchema", () => {
772
629
  // Should have schema export
773
630
  expect(generated).toContain("export const test_schema = {");
774
631
  expect(generated).toMatchInlineSnapshot(`
775
- "import { pgTable, varchar, text, bigserial, integer, uniqueIndex, bigint } from "drizzle-orm/pg-core"
632
+ "import { pgTable, varchar, text, bigserial, integer, bigint } from "drizzle-orm/pg-core"
776
633
  import { createId } from "@fragno-dev/db/id"
777
634
  import { relations } from "drizzle-orm"
778
635
 
779
- // ============================================================================
780
- // Settings Table (shared across all fragments)
781
- // ============================================================================
782
-
783
- export const fragno_db_settings = pgTable("fragno_db_settings", {
784
- id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
785
- key: text("key").notNull(),
786
- value: text("value").notNull(),
787
- _internalId: bigserial("_internalId", { mode: "number" }).primaryKey().notNull(),
788
- _version: integer("_version").notNull().default(0)
789
- }, (table) => [
790
- uniqueIndex("unique_key").on(table.key)
791
- ])
792
-
793
- export const fragnoDbSettingSchemaVersion = 1;
794
-
795
636
  // ============================================================================
796
637
  // Fragment: test
797
638
  // ============================================================================
@@ -864,26 +705,10 @@ describe("generateSchema", () => {
864
705
  expect(fkMatches).toHaveLength(1);
865
706
 
866
707
  expect(generated).toMatchInlineSnapshot(`
867
- "import { pgTable, varchar, text, bigserial, integer, uniqueIndex, bigint, foreignKey } from "drizzle-orm/pg-core"
708
+ "import { pgTable, varchar, text, bigint, bigserial, integer, foreignKey } from "drizzle-orm/pg-core"
868
709
  import { createId } from "@fragno-dev/db/id"
869
710
  import { relations } from "drizzle-orm"
870
711
 
871
- // ============================================================================
872
- // Settings Table (shared across all fragments)
873
- // ============================================================================
874
-
875
- export const fragno_db_settings = pgTable("fragno_db_settings", {
876
- id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
877
- key: text("key").notNull(),
878
- value: text("value").notNull(),
879
- _internalId: bigserial("_internalId", { mode: "number" }).primaryKey().notNull(),
880
- _version: integer("_version").notNull().default(0)
881
- }, (table) => [
882
- uniqueIndex("unique_key").on(table.key)
883
- ])
884
-
885
- export const fragnoDbSettingSchemaVersion = 1;
886
-
887
712
  // ============================================================================
888
713
  // Fragment: test
889
714
  // ============================================================================
@@ -950,26 +775,10 @@ describe("generateSchema", () => {
950
775
  "postgresql",
951
776
  );
952
777
  expect(generated).toMatchInlineSnapshot(`
953
- "import { pgTable, varchar, text, bigserial, integer, uniqueIndex, bigint, foreignKey, index } from "drizzle-orm/pg-core"
778
+ "import { pgTable, varchar, text, bigint, bigserial, integer, foreignKey, index } from "drizzle-orm/pg-core"
954
779
  import { createId } from "@fragno-dev/db/id"
955
780
  import { relations } from "drizzle-orm"
956
781
 
957
- // ============================================================================
958
- // Settings Table (shared across all fragments)
959
- // ============================================================================
960
-
961
- export const fragno_db_settings = pgTable("fragno_db_settings", {
962
- id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
963
- key: text("key").notNull(),
964
- value: text("value").notNull(),
965
- _internalId: bigserial("_internalId", { mode: "number" }).primaryKey().notNull(),
966
- _version: integer("_version").notNull().default(0)
967
- }, (table) => [
968
- uniqueIndex("unique_key").on(table.key)
969
- ])
970
-
971
- export const fragnoDbSettingSchemaVersion = 1;
972
-
973
782
  // ============================================================================
974
783
  // Fragment: test
975
784
  // ============================================================================
@@ -1013,26 +822,10 @@ describe("generateSchema", () => {
1013
822
  it("should generate MySQL self-referencing foreign key using table parameter", () => {
1014
823
  const generated = generateSchema([{ namespace: "test", schema: selfRefSchema }], "mysql");
1015
824
  expect(generated).toMatchInlineSnapshot(`
1016
- "import { mysqlTable, varchar, text, bigint, integer, uniqueIndex, foreignKey, index } from "drizzle-orm/mysql-core"
825
+ "import { mysqlTable, varchar, text, bigint, int, foreignKey, index } from "drizzle-orm/mysql-core"
1017
826
  import { createId } from "@fragno-dev/db/id"
1018
827
  import { relations } from "drizzle-orm"
1019
828
 
1020
- // ============================================================================
1021
- // Settings Table (shared across all fragments)
1022
- // ============================================================================
1023
-
1024
- export const fragno_db_settings = mysqlTable("fragno_db_settings", {
1025
- id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
1026
- key: text("key").notNull(),
1027
- value: text("value").notNull(),
1028
- _internalId: bigint("_internalId").primaryKey().autoincrement().notNull(),
1029
- _version: integer("_version").notNull().default(0)
1030
- }, (table) => [
1031
- uniqueIndex("unique_key").on(table.key)
1032
- ])
1033
-
1034
- export const fragnoDbSettingSchemaVersion = 1;
1035
-
1036
829
  // ============================================================================
1037
830
  // Fragment: test
1038
831
  // ============================================================================
@@ -1040,9 +833,9 @@ describe("generateSchema", () => {
1040
833
  export const comment_test = mysqlTable("comment_test", {
1041
834
  id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
1042
835
  content: text("content").notNull(),
1043
- parentId: bigint("parentId"),
1044
- _internalId: bigint("_internalId").primaryKey().autoincrement().notNull(),
1045
- _version: integer("_version").notNull().default(0)
836
+ parentId: bigint("parentId", { mode: "number" }),
837
+ _internalId: bigint("_internalId", { mode: "number" }).primaryKey().autoincrement().notNull(),
838
+ _version: int("_version").notNull().default(0)
1046
839
  }, (table) => [
1047
840
  foreignKey({
1048
841
  columns: [table.parentId],
@@ -1076,26 +869,10 @@ describe("generateSchema", () => {
1076
869
  it("should generate SQLite self-referencing foreign key using table parameter", () => {
1077
870
  const generated = generateSchema([{ namespace: "test", schema: selfRefSchema }], "sqlite");
1078
871
  expect(generated).toMatchInlineSnapshot(`
1079
- "import { sqliteTable, text, integer, uniqueIndex, foreignKey, index } from "drizzle-orm/sqlite-core"
872
+ "import { sqliteTable, text, integer, foreignKey, index } from "drizzle-orm/sqlite-core"
1080
873
  import { createId } from "@fragno-dev/db/id"
1081
874
  import { relations } from "drizzle-orm"
1082
875
 
1083
- // ============================================================================
1084
- // Settings Table (shared across all fragments)
1085
- // ============================================================================
1086
-
1087
- export const fragno_db_settings = sqliteTable("fragno_db_settings", {
1088
- id: text("id").notNull().$defaultFn(() => createId()),
1089
- key: text("key").notNull(),
1090
- value: text("value").notNull(),
1091
- _internalId: integer("_internalId").primaryKey({ autoIncrement: true }).notNull(),
1092
- _version: integer("_version").notNull().default(0)
1093
- }, (table) => [
1094
- uniqueIndex("unique_key").on(table.key)
1095
- ])
1096
-
1097
- export const fragnoDbSettingSchemaVersion = 1;
1098
-
1099
876
  // ============================================================================
1100
877
  // Fragment: test
1101
878
  // ============================================================================
@@ -1209,26 +986,10 @@ describe("generateSchema", () => {
1209
986
  expect(generated).toContain('pgTable("posts_my_fragment_v2"');
1210
987
 
1211
988
  expect(generated).toMatchInlineSnapshot(`
1212
- "import { pgTable, varchar, text, bigserial, integer, uniqueIndex, index, bigint, foreignKey } from "drizzle-orm/pg-core"
989
+ "import { pgTable, varchar, text, integer, bigserial, uniqueIndex, index, bigint, foreignKey } from "drizzle-orm/pg-core"
1213
990
  import { createId } from "@fragno-dev/db/id"
1214
991
  import { relations } from "drizzle-orm"
1215
992
 
1216
- // ============================================================================
1217
- // Settings Table (shared across all fragments)
1218
- // ============================================================================
1219
-
1220
- export const fragno_db_settings = pgTable("fragno_db_settings", {
1221
- id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
1222
- key: text("key").notNull(),
1223
- value: text("value").notNull(),
1224
- _internalId: bigserial("_internalId", { mode: "number" }).primaryKey().notNull(),
1225
- _version: integer("_version").notNull().default(0)
1226
- }, (table) => [
1227
- uniqueIndex("unique_key").on(table.key)
1228
- ])
1229
-
1230
- export const fragnoDbSettingSchemaVersion = 1;
1231
-
1232
993
  // ============================================================================
1233
994
  // Fragment: my-fragment-v2
1234
995
  // ============================================================================
@@ -1291,4 +1052,76 @@ describe("generateSchema", () => {
1291
1052
  `);
1292
1053
  });
1293
1054
  });
1055
+
1056
+ describe("schema generation", () => {
1057
+ it("should generate settings schema and multiple user fragments", () => {
1058
+ // settingsSchema is imported at the top to simulate what happens with linked internal fragments
1059
+ const fragment1Schema = schema((s) => {
1060
+ return s.addTable("users", (t) => {
1061
+ return t.addColumn("id", idColumn()).addColumn("name", column("string"));
1062
+ });
1063
+ });
1064
+
1065
+ const fragment2Schema = schema((s) => {
1066
+ return s.addTable("posts", (t) => {
1067
+ return t.addColumn("id", idColumn()).addColumn("title", column("string"));
1068
+ });
1069
+ });
1070
+
1071
+ // De-duplication happens in generation-engine.ts before calling generateSchema
1072
+ // This test verifies generateSchema works correctly with already-deduplicated inputs
1073
+ const generated = generateSchema(
1074
+ [
1075
+ { namespace: "", schema: settingsSchema }, // Internal fragment (namespace: "")
1076
+ { namespace: "fragment1", schema: fragment1Schema },
1077
+ { namespace: "fragment2", schema: fragment2Schema },
1078
+ ],
1079
+ "postgresql",
1080
+ );
1081
+
1082
+ // Count how many times fragno_db_settings appears in the output
1083
+ const settingsTableMatches = generated.match(/export const fragno_db_settings = /g);
1084
+ expect(settingsTableMatches).toHaveLength(1);
1085
+
1086
+ // Verify it appears before the fragment tables
1087
+ const lines = generated.split("\n");
1088
+ const settingsIndex = lines.findIndex((line) =>
1089
+ line.includes("export const fragno_db_settings"),
1090
+ );
1091
+ const usersIndex = lines.findIndex((line) => line.includes("export const users_fragment1"));
1092
+ const postsIndex = lines.findIndex((line) => line.includes("export const posts_fragment2"));
1093
+
1094
+ expect(settingsIndex).toBeLessThan(usersIndex);
1095
+ expect(settingsIndex).toBeLessThan(postsIndex);
1096
+
1097
+ // Verify the structure includes all expected tables
1098
+ expect(generated).toContain("export const fragno_db_settings");
1099
+ expect(generated).toContain("export const users_fragment1");
1100
+ expect(generated).toContain("export const posts_fragment2");
1101
+ expect(generated).toContain("export const fragment1_schema");
1102
+ expect(generated).toContain("export const fragment2_schema");
1103
+ });
1104
+
1105
+ it("should generate schema for single fragment with custom namespace", () => {
1106
+ // Test a simple single-schema generation
1107
+ const sharedSchema = schema((s) => {
1108
+ return s.addTable("shared_table", (t) => {
1109
+ return t.addColumn("id", idColumn()).addColumn("data", column("string"));
1110
+ });
1111
+ });
1112
+
1113
+ // De-duplication happens in generation-engine.ts, so we pass pre-deduplicated input
1114
+ const generated = generateSchema(
1115
+ [{ namespace: "namespace1", schema: sharedSchema }],
1116
+ "postgresql",
1117
+ );
1118
+
1119
+ // Should generate the schema with the provided namespace
1120
+ const sharedTableMatches = generated.match(/export const shared_table_/g);
1121
+ expect(sharedTableMatches).toHaveLength(1);
1122
+
1123
+ expect(generated).toContain("export const shared_table_namespace1");
1124
+ expect(generated).toContain("export const namespace1_schema");
1125
+ });
1126
+ });
1294
1127
  });
@@ -10,7 +10,6 @@ import {
10
10
  import type { SQLProvider } from "../../shared/providers";
11
11
  import { schemaToDBType, type DBTypeLiteral } from "../../schema/serialize";
12
12
  import { createTableNameMapper, sanitizeNamespace } from "./shared";
13
- import { settingsSchema, SETTINGS_TABLE_NAME } from "../../shared/settings-schema";
14
13
 
15
14
  // ============================================================================
16
15
  // PROVIDER CONFIGURATION
@@ -184,7 +183,11 @@ function mapDBTypeToDrizzleFunction(
184
183
  case "longblob":
185
184
  return { name: generateBinaryCustomType(ctx, customTypes), isCustomType: true };
186
185
  case "bigint":
187
- return { name: "bigint" };
186
+ // MySQL bigint requires mode parameter
187
+ return { name: "bigint", params: [`{ mode: "number" }`] };
188
+ case "integer":
189
+ // MySQL uses "int" not "integer" in Drizzle ORM
190
+ return { name: "int" };
188
191
  default:
189
192
  if (dbType.startsWith("varchar(")) {
190
193
  const length = parseVarchar(dbType);
@@ -606,20 +609,8 @@ export interface GenerateSchemaOptions {
606
609
  /**
607
610
  * Generate a settings table for storing fragment versions
608
611
  */
609
- function generateSettingsTable(ctx: GeneratorContext): string {
610
- // Use centralized settings schema
611
-
612
- // Extract the table from the schema
613
- const settingsTable =
614
- settingsSchema.tables[SETTINGS_TABLE_NAME as keyof typeof settingsSchema.tables];
615
-
616
- // Generate the table using the existing generateTable function
617
- const customTypes: string[] = [];
618
- return generateTable(ctx, settingsTable, customTypes);
619
- }
620
-
621
612
  /**
622
- * Generate a schema file from one or more fragments with a shared settings table
613
+ * Generate a schema file from one or more fragments with automatic de-duplication
623
614
  */
624
615
  export function generateSchema(
625
616
  fragments: { namespace: string; schema: AnySchema }[],
@@ -630,18 +621,7 @@ export function generateSchema(
630
621
  const customTypes: string[] = [];
631
622
  const sections: string[] = [];
632
623
 
633
- // Generate settings table first
634
- sections.push("");
635
- sections.push("// ============================================================================");
636
- sections.push("// Settings Table (shared across all fragments)");
637
- sections.push("// ============================================================================");
638
- sections.push("");
639
- sections.push(generateSettingsTable(ctx));
640
- sections.push("");
641
- sections.push(`export const fragnoDbSettingSchemaVersion = ${settingsSchema.version};`);
642
-
643
- // Generate each fragment's tables
644
- for (const { namespace, schema } of fragments) {
624
+ for (const { schema, namespace } of fragments) {
645
625
  const fragmentTables: string[] = [];
646
626
 
647
627
  // Add section header
@@ -691,9 +671,11 @@ export function generateSchema(
691
671
  }
692
672
  }
693
673
 
694
- // Generate schema export object
695
- fragmentTables.push("");
696
- fragmentTables.push(generateFragmentSchemaExport(schema, namespace, tablesWithRelations));
674
+ // Generate schema export object (skip for empty namespace to avoid duplicate _schema exports)
675
+ if (namespace !== "") {
676
+ fragmentTables.push("");
677
+ fragmentTables.push(generateFragmentSchemaExport(schema, namespace, tablesWithRelations));
678
+ }
697
679
 
698
680
  sections.push(...fragmentTables);
699
681
  }