@fragno-dev/db 0.2.1 → 0.3.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 (362) hide show
  1. package/.turbo/turbo-build.log +206 -140
  2. package/CHANGELOG.md +67 -0
  3. package/README.md +30 -9
  4. package/dist/adapters/adapters.d.ts +23 -21
  5. package/dist/adapters/adapters.d.ts.map +1 -1
  6. package/dist/adapters/adapters.js.map +1 -1
  7. package/dist/adapters/generic-sql/driver-config.d.ts +16 -1
  8. package/dist/adapters/generic-sql/driver-config.d.ts.map +1 -1
  9. package/dist/adapters/generic-sql/driver-config.js +23 -1
  10. package/dist/adapters/generic-sql/driver-config.js.map +1 -1
  11. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts +27 -9
  12. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -1
  13. package/dist/adapters/generic-sql/generic-sql-adapter.js +55 -16
  14. package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -1
  15. package/dist/adapters/generic-sql/generic-sql-uow-executor.js +129 -3
  16. package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -1
  17. package/dist/adapters/generic-sql/migration/dialect/mysql.js +24 -5
  18. package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -1
  19. package/dist/adapters/generic-sql/migration/dialect/postgres.js +6 -5
  20. package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -1
  21. package/dist/adapters/generic-sql/migration/dialect/sqlite.js +21 -10
  22. package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -1
  23. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -1
  24. package/dist/adapters/generic-sql/migration/prepared-migrations.js +8 -8
  25. package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -1
  26. package/dist/adapters/generic-sql/migration/sql-generator.js +74 -51
  27. package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -1
  28. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +6 -5
  29. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -1
  30. package/dist/adapters/generic-sql/query/cursor-utils.js +42 -4
  31. package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -1
  32. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +25 -17
  33. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -1
  34. package/dist/adapters/generic-sql/query/select-builder.js +5 -3
  35. package/dist/adapters/generic-sql/query/select-builder.js.map +1 -1
  36. package/dist/adapters/generic-sql/query/sql-query-compiler.js +15 -12
  37. package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -1
  38. package/dist/adapters/generic-sql/query/where-builder.js +38 -28
  39. package/dist/adapters/generic-sql/query/where-builder.js.map +1 -1
  40. package/dist/adapters/generic-sql/sqlite-storage.d.ts +13 -0
  41. package/dist/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
  42. package/dist/adapters/generic-sql/sqlite-storage.js +15 -0
  43. package/dist/adapters/generic-sql/sqlite-storage.js.map +1 -0
  44. package/dist/adapters/generic-sql/uow-decoder.js +7 -3
  45. package/dist/adapters/generic-sql/uow-decoder.js.map +1 -1
  46. package/dist/adapters/generic-sql/uow-encoder.js +28 -8
  47. package/dist/adapters/generic-sql/uow-encoder.js.map +1 -1
  48. package/dist/adapters/in-memory/condition-evaluator.js +131 -0
  49. package/dist/adapters/in-memory/condition-evaluator.js.map +1 -0
  50. package/dist/adapters/in-memory/errors.d.ts +13 -0
  51. package/dist/adapters/in-memory/errors.d.ts.map +1 -0
  52. package/dist/adapters/in-memory/errors.js +23 -0
  53. package/dist/adapters/in-memory/errors.js.map +1 -0
  54. package/dist/adapters/in-memory/in-memory-adapter.d.ts +27 -0
  55. package/dist/adapters/in-memory/in-memory-adapter.d.ts.map +1 -0
  56. package/dist/adapters/in-memory/in-memory-adapter.js +176 -0
  57. package/dist/adapters/in-memory/in-memory-adapter.js.map +1 -0
  58. package/dist/adapters/in-memory/in-memory-uow.js +648 -0
  59. package/dist/adapters/in-memory/in-memory-uow.js.map +1 -0
  60. package/dist/adapters/in-memory/index.d.ts +4 -0
  61. package/dist/adapters/in-memory/index.js +4 -0
  62. package/dist/adapters/in-memory/options.d.ts +28 -0
  63. package/dist/adapters/in-memory/options.d.ts.map +1 -0
  64. package/dist/adapters/in-memory/options.js +61 -0
  65. package/dist/adapters/in-memory/options.js.map +1 -0
  66. package/dist/adapters/in-memory/reference-resolution.js +26 -0
  67. package/dist/adapters/in-memory/reference-resolution.js.map +1 -0
  68. package/dist/adapters/in-memory/sorted-array-index.js +129 -0
  69. package/dist/adapters/in-memory/sorted-array-index.js.map +1 -0
  70. package/dist/adapters/in-memory/store.js +71 -0
  71. package/dist/adapters/in-memory/store.js.map +1 -0
  72. package/dist/adapters/in-memory/value-comparison.js +28 -0
  73. package/dist/adapters/in-memory/value-comparison.js.map +1 -0
  74. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -1
  75. package/dist/adapters/shared/uow-operation-compiler.js +11 -11
  76. package/dist/adapters/shared/uow-operation-compiler.js.map +1 -1
  77. package/dist/adapters/sql/index.d.ts +5 -0
  78. package/dist/adapters/sql/index.js +4 -0
  79. package/dist/db-fragment-definition-builder.d.ts +45 -96
  80. package/dist/db-fragment-definition-builder.d.ts.map +1 -1
  81. package/dist/db-fragment-definition-builder.js +121 -99
  82. package/dist/db-fragment-definition-builder.js.map +1 -1
  83. package/dist/dispatchers/cloudflare-do/index.d.ts +26 -0
  84. package/dist/dispatchers/cloudflare-do/index.d.ts.map +1 -0
  85. package/dist/dispatchers/cloudflare-do/index.js +63 -0
  86. package/dist/dispatchers/cloudflare-do/index.js.map +1 -0
  87. package/dist/dispatchers/node/index.d.ts +17 -0
  88. package/dist/dispatchers/node/index.d.ts.map +1 -0
  89. package/dist/dispatchers/node/index.js +59 -0
  90. package/dist/dispatchers/node/index.js.map +1 -0
  91. package/dist/fragments/internal-fragment.d.ts +172 -9
  92. package/dist/fragments/internal-fragment.d.ts.map +1 -1
  93. package/dist/fragments/internal-fragment.js +193 -74
  94. package/dist/fragments/internal-fragment.js.map +1 -1
  95. package/dist/fragments/internal-fragment.routes.js +29 -0
  96. package/dist/fragments/internal-fragment.routes.js.map +1 -0
  97. package/dist/fragments/internal-fragment.schema.d.ts +9 -0
  98. package/dist/fragments/internal-fragment.schema.d.ts.map +1 -0
  99. package/dist/fragments/internal-fragment.schema.js +22 -0
  100. package/dist/fragments/internal-fragment.schema.js.map +1 -0
  101. package/dist/hooks/durable-hooks-processor.d.ts +14 -0
  102. package/dist/hooks/durable-hooks-processor.d.ts.map +1 -0
  103. package/dist/hooks/durable-hooks-processor.js +32 -0
  104. package/dist/hooks/durable-hooks-processor.js.map +1 -0
  105. package/dist/hooks/hooks.d.ts +47 -4
  106. package/dist/hooks/hooks.d.ts.map +1 -1
  107. package/dist/hooks/hooks.js +106 -39
  108. package/dist/hooks/hooks.js.map +1 -1
  109. package/dist/migration-engine/auto-from-schema.js +14 -11
  110. package/dist/migration-engine/auto-from-schema.js.map +1 -1
  111. package/dist/migration-engine/generation-engine.d.ts +16 -10
  112. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  113. package/dist/migration-engine/generation-engine.js +72 -33
  114. package/dist/migration-engine/generation-engine.js.map +1 -1
  115. package/dist/migration-engine/shared.js.map +1 -1
  116. package/dist/mod.d.ts +17 -10
  117. package/dist/mod.d.ts.map +1 -1
  118. package/dist/mod.js +14 -8
  119. package/dist/mod.js.map +1 -1
  120. package/dist/naming/sql-naming.d.ts +19 -0
  121. package/dist/naming/sql-naming.d.ts.map +1 -0
  122. package/dist/naming/sql-naming.js +116 -0
  123. package/dist/naming/sql-naming.js.map +1 -0
  124. package/dist/node_modules/.pnpm/{rou3@0.7.10 → rou3@0.7.12}/node_modules/rou3/dist/index.js +8 -5
  125. package/dist/node_modules/.pnpm/rou3@0.7.12/node_modules/rou3/dist/index.js.map +1 -0
  126. package/dist/outbox/outbox-builder.js +156 -0
  127. package/dist/outbox/outbox-builder.js.map +1 -0
  128. package/dist/outbox/outbox.d.ts +52 -0
  129. package/dist/outbox/outbox.d.ts.map +1 -0
  130. package/dist/outbox/outbox.js +37 -0
  131. package/dist/outbox/outbox.js.map +1 -0
  132. package/dist/packages/fragno/dist/api/fragment-definition-builder.js +3 -2
  133. package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +1 -1
  134. package/dist/packages/fragno/dist/api/fragment-instantiator.js +164 -20
  135. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +1 -1
  136. package/dist/packages/fragno/dist/api/request-input-context.js +67 -0
  137. package/dist/packages/fragno/dist/api/request-input-context.js.map +1 -1
  138. package/dist/packages/fragno/dist/api/route.js +14 -1
  139. package/dist/packages/fragno/dist/api/route.js.map +1 -1
  140. package/dist/packages/fragno/dist/internal/trace-context.js +12 -0
  141. package/dist/packages/fragno/dist/internal/trace-context.js.map +1 -0
  142. package/dist/query/column-defaults.js +20 -4
  143. package/dist/query/column-defaults.js.map +1 -1
  144. package/dist/query/cursor.d.ts +3 -1
  145. package/dist/query/cursor.d.ts.map +1 -1
  146. package/dist/query/cursor.js +45 -14
  147. package/dist/query/cursor.js.map +1 -1
  148. package/dist/query/db-now.d.ts +8 -0
  149. package/dist/query/db-now.d.ts.map +1 -0
  150. package/dist/query/db-now.js +7 -0
  151. package/dist/query/db-now.js.map +1 -0
  152. package/dist/query/serialize/create-sql-serializer.js +3 -2
  153. package/dist/query/serialize/create-sql-serializer.js.map +1 -1
  154. package/dist/query/serialize/dialect/mysql-serializer.js +12 -6
  155. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -1
  156. package/dist/query/serialize/dialect/postgres-serializer.js +25 -7
  157. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -1
  158. package/dist/query/serialize/dialect/sqlite-serializer.js +55 -11
  159. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -1
  160. package/dist/query/serialize/sql-serializer.js +2 -2
  161. package/dist/query/serialize/sql-serializer.js.map +1 -1
  162. package/dist/query/simple-query-interface.d.ts +6 -1
  163. package/dist/query/simple-query-interface.d.ts.map +1 -1
  164. package/dist/query/unit-of-work/execute-unit-of-work.d.ts +351 -100
  165. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -1
  166. package/dist/query/unit-of-work/execute-unit-of-work.js +440 -267
  167. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -1
  168. package/dist/query/unit-of-work/unit-of-work.d.ts +67 -22
  169. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
  170. package/dist/query/unit-of-work/unit-of-work.js +110 -13
  171. package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
  172. package/dist/query/value-decoding.js +8 -5
  173. package/dist/query/value-decoding.js.map +1 -1
  174. package/dist/query/value-encoding.js +29 -9
  175. package/dist/query/value-encoding.js.map +1 -1
  176. package/dist/schema/create.d.ts +40 -14
  177. package/dist/schema/create.d.ts.map +1 -1
  178. package/dist/schema/create.js +82 -42
  179. package/dist/schema/create.js.map +1 -1
  180. package/dist/schema/generate-id.d.ts +20 -0
  181. package/dist/schema/generate-id.d.ts.map +1 -0
  182. package/dist/schema/generate-id.js +28 -0
  183. package/dist/schema/generate-id.js.map +1 -0
  184. package/dist/schema/type-conversion/create-sql-type-mapper.js +3 -2
  185. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -1
  186. package/dist/schema/type-conversion/dialect/sqlite.js +9 -0
  187. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -1
  188. package/dist/schema/validator.d.ts +10 -0
  189. package/dist/schema/validator.d.ts.map +1 -0
  190. package/dist/schema/validator.js +123 -0
  191. package/dist/schema/validator.js.map +1 -0
  192. package/dist/schema-output/drizzle.d.ts +30 -0
  193. package/dist/schema-output/drizzle.d.ts.map +1 -0
  194. package/dist/{adapters/drizzle/generate.js → schema-output/drizzle.js} +82 -56
  195. package/dist/schema-output/drizzle.js.map +1 -0
  196. package/dist/schema-output/prisma.d.ts +17 -0
  197. package/dist/schema-output/prisma.d.ts.map +1 -0
  198. package/dist/schema-output/prisma.js +296 -0
  199. package/dist/schema-output/prisma.js.map +1 -0
  200. package/dist/util/default-database-adapter.js +61 -0
  201. package/dist/util/default-database-adapter.js.map +1 -0
  202. package/dist/with-database.d.ts +1 -1
  203. package/dist/with-database.d.ts.map +1 -1
  204. package/dist/with-database.js +12 -3
  205. package/dist/with-database.js.map +1 -1
  206. package/package.json +43 -28
  207. package/src/adapters/adapters.ts +30 -24
  208. package/src/adapters/drizzle/migrate-drizzle.test.ts +54 -33
  209. package/src/adapters/drizzle/migration-parity-drizzle-kit.test.ts +599 -0
  210. package/src/adapters/drizzle/test-utils.ts +12 -8
  211. package/src/adapters/generic-sql/driver-config.ts +38 -0
  212. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +5 -5
  213. package/src/adapters/generic-sql/generic-sql-adapter.ts +110 -24
  214. package/src/adapters/generic-sql/generic-sql-uow-executor.test.ts +54 -0
  215. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +231 -3
  216. package/src/adapters/generic-sql/migration/adapter-migration-parity.test.ts +118 -0
  217. package/src/adapters/generic-sql/migration/dialect/mysql.test.ts +26 -8
  218. package/src/adapters/generic-sql/migration/dialect/mysql.ts +46 -8
  219. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +25 -7
  220. package/src/adapters/generic-sql/migration/dialect/postgres.ts +8 -4
  221. package/src/adapters/generic-sql/migration/dialect/sqlite.test.ts +47 -8
  222. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +27 -12
  223. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +128 -39
  224. package/src/adapters/generic-sql/migration/prepared-migrations.ts +15 -8
  225. package/src/adapters/generic-sql/migration/sql-generator.ts +142 -65
  226. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +9 -6
  227. package/src/adapters/generic-sql/query/cursor-utils.test.ts +271 -0
  228. package/src/adapters/generic-sql/query/cursor-utils.ts +41 -6
  229. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +27 -27
  230. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +38 -24
  231. package/src/adapters/generic-sql/query/select-builder.test.ts +15 -11
  232. package/src/adapters/generic-sql/query/select-builder.ts +6 -2
  233. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +52 -2
  234. package/src/adapters/generic-sql/query/sql-query-compiler.ts +50 -15
  235. package/src/adapters/generic-sql/query/where-builder.test.ts +91 -17
  236. package/src/adapters/generic-sql/query/where-builder.ts +90 -38
  237. package/src/adapters/{kysely/kysely-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-migrations.test.ts} +6 -6
  238. package/src/adapters/generic-sql/sql-adapter-pglite-pagination.test.ts +806 -0
  239. package/src/adapters/{drizzle/drizzle-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-queries.test.ts} +11 -11
  240. package/src/adapters/generic-sql/{test/generic-drizzle-adapter-sqlite3.test.ts → sql-adapter-sqlite3-driver.test.ts} +49 -35
  241. package/src/adapters/{drizzle/drizzle-adapter-sqlite3.test.ts → generic-sql/sql-adapter-sqlite3-uow.test.ts} +48 -32
  242. package/src/adapters/{kysely/kysely-adapter-sqlocal.test.ts → generic-sql/sql-adapter-sqlocal.test.ts} +6 -6
  243. package/src/adapters/generic-sql/sqlite-storage.ts +20 -0
  244. package/src/adapters/generic-sql/uow-decoder.test.ts +1 -1
  245. package/src/adapters/generic-sql/uow-decoder.ts +21 -3
  246. package/src/adapters/generic-sql/uow-encoder.test.ts +33 -2
  247. package/src/adapters/generic-sql/uow-encoder.ts +50 -11
  248. package/src/adapters/in-memory/condition-evaluator.test.ts +193 -0
  249. package/src/adapters/in-memory/condition-evaluator.ts +275 -0
  250. package/src/adapters/in-memory/errors.ts +20 -0
  251. package/src/adapters/in-memory/in-memory-adapter.ts +277 -0
  252. package/src/adapters/in-memory/in-memory-uow.mutations.test.ts +296 -0
  253. package/src/adapters/in-memory/in-memory-uow.retrieval.test.ts +100 -0
  254. package/src/adapters/in-memory/in-memory-uow.ts +1348 -0
  255. package/src/adapters/in-memory/index.ts +3 -0
  256. package/src/adapters/in-memory/options.test.ts +41 -0
  257. package/src/adapters/in-memory/options.ts +87 -0
  258. package/src/adapters/in-memory/reference-resolution.test.ts +50 -0
  259. package/src/adapters/in-memory/reference-resolution.ts +67 -0
  260. package/src/adapters/in-memory/sorted-array-index.test.ts +123 -0
  261. package/src/adapters/in-memory/sorted-array-index.ts +228 -0
  262. package/src/adapters/in-memory/store.test.ts +68 -0
  263. package/src/adapters/in-memory/store.ts +145 -0
  264. package/src/adapters/in-memory/value-comparison.ts +53 -0
  265. package/src/adapters/in-memory/value-normalization.test.ts +57 -0
  266. package/src/adapters/prisma/prisma-adapter-sqlite3.test.ts +1163 -0
  267. package/src/adapters/shared/from-unit-of-work-compiler.ts +3 -1
  268. package/src/adapters/shared/uow-operation-compiler.ts +26 -16
  269. package/src/adapters/sql/index.ts +12 -0
  270. package/src/db-fragment-definition-builder.test.ts +88 -54
  271. package/src/db-fragment-definition-builder.ts +201 -322
  272. package/src/db-fragment-instantiator.test.ts +169 -101
  273. package/src/db-fragment-integration.test.ts +301 -149
  274. package/src/dispatchers/cloudflare-do/index.test.ts +73 -0
  275. package/src/dispatchers/cloudflare-do/index.ts +104 -0
  276. package/src/dispatchers/node/index.test.ts +91 -0
  277. package/src/dispatchers/node/index.ts +87 -0
  278. package/src/fragments/internal-fragment.routes.ts +42 -0
  279. package/src/fragments/internal-fragment.schema.ts +51 -0
  280. package/src/fragments/internal-fragment.test.ts +730 -274
  281. package/src/fragments/internal-fragment.ts +447 -154
  282. package/src/hooks/durable-hooks-processor.test.ts +117 -0
  283. package/src/hooks/durable-hooks-processor.ts +67 -0
  284. package/src/hooks/hooks.test.ts +411 -259
  285. package/src/hooks/hooks.ts +265 -66
  286. package/src/migration-engine/auto-from-schema.test.ts +14 -14
  287. package/src/migration-engine/auto-from-schema.ts +5 -2
  288. package/src/migration-engine/create.test.ts +2 -2
  289. package/src/migration-engine/generation-engine.test.ts +229 -104
  290. package/src/migration-engine/generation-engine.ts +94 -64
  291. package/src/migration-engine/shared.ts +1 -0
  292. package/src/mod.ts +78 -30
  293. package/src/naming/sql-naming.ts +180 -0
  294. package/src/outbox/outbox-builder.ts +241 -0
  295. package/src/outbox/outbox.test.ts +253 -0
  296. package/src/outbox/outbox.ts +137 -0
  297. package/src/query/column-defaults.ts +41 -3
  298. package/src/query/condition-builder.test.ts +3 -3
  299. package/src/query/cursor.test.ts +116 -18
  300. package/src/query/cursor.ts +75 -26
  301. package/src/query/db-now.ts +6 -0
  302. package/src/query/query-type.test.ts +2 -2
  303. package/src/query/serialize/create-sql-serializer.ts +7 -2
  304. package/src/query/serialize/dialect/mysql-serializer.ts +12 -4
  305. package/src/query/serialize/dialect/postgres-serializer.ts +34 -4
  306. package/src/query/serialize/dialect/sqlite-serializer.test.ts +51 -1
  307. package/src/query/serialize/dialect/sqlite-serializer.ts +92 -9
  308. package/src/query/serialize/sql-serializer.ts +4 -4
  309. package/src/query/simple-query-interface.ts +5 -0
  310. package/src/query/unit-of-work/execute-unit-of-work.test.ts +1512 -1458
  311. package/src/query/unit-of-work/execute-unit-of-work.ts +1708 -596
  312. package/src/query/unit-of-work/tx-builder.test.ts +1041 -0
  313. package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +32 -32
  314. package/src/query/unit-of-work/unit-of-work-types.test.ts +1 -1
  315. package/src/query/unit-of-work/unit-of-work.test.ts +231 -36
  316. package/src/query/unit-of-work/unit-of-work.ts +229 -31
  317. package/src/query/value-decoding.test.ts +13 -2
  318. package/src/query/value-decoding.ts +17 -4
  319. package/src/query/value-encoding.test.ts +85 -2
  320. package/src/query/value-encoding.ts +56 -6
  321. package/src/schema/create.test.ts +129 -42
  322. package/src/schema/create.ts +187 -47
  323. package/src/schema/generate-id.test.ts +57 -0
  324. package/src/schema/generate-id.ts +38 -0
  325. package/src/schema/serialize.test.ts +14 -2
  326. package/src/schema/type-conversion/create-sql-type-mapper.ts +7 -2
  327. package/src/schema/type-conversion/dialect/sqlite.ts +18 -0
  328. package/src/schema/type-conversion/type-mapping.test.ts +25 -1
  329. package/src/schema/validator.test.ts +197 -0
  330. package/src/schema/validator.ts +231 -0
  331. package/src/{adapters/drizzle/generate.test.ts → schema-output/drizzle.test.ts} +179 -129
  332. package/src/{adapters/drizzle/generate.ts → schema-output/drizzle.ts} +143 -93
  333. package/src/schema-output/prisma.test.ts +536 -0
  334. package/src/schema-output/prisma.ts +573 -0
  335. package/src/util/default-database-adapter.ts +106 -0
  336. package/src/with-database.ts +22 -3
  337. package/tsdown.config.ts +6 -4
  338. package/dist/adapters/drizzle/drizzle-adapter.d.ts +0 -20
  339. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +0 -1
  340. package/dist/adapters/drizzle/drizzle-adapter.js +0 -27
  341. package/dist/adapters/drizzle/drizzle-adapter.js.map +0 -1
  342. package/dist/adapters/drizzle/generate.d.ts +0 -30
  343. package/dist/adapters/drizzle/generate.d.ts.map +0 -1
  344. package/dist/adapters/drizzle/generate.js.map +0 -1
  345. package/dist/adapters/kysely/kysely-adapter.d.ts +0 -19
  346. package/dist/adapters/kysely/kysely-adapter.d.ts.map +0 -1
  347. package/dist/adapters/kysely/kysely-adapter.js +0 -17
  348. package/dist/adapters/kysely/kysely-adapter.js.map +0 -1
  349. package/dist/adapters/shared/table-name-mapper.d.ts +0 -12
  350. package/dist/adapters/shared/table-name-mapper.d.ts.map +0 -1
  351. package/dist/adapters/shared/table-name-mapper.js +0 -43
  352. package/dist/adapters/shared/table-name-mapper.js.map +0 -1
  353. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js.map +0 -1
  354. package/dist/schema-generator/schema-generator.d.ts +0 -15
  355. package/dist/schema-generator/schema-generator.d.ts.map +0 -1
  356. package/src/adapters/drizzle/drizzle-adapter.ts +0 -39
  357. package/src/adapters/kysely/kysely-adapter.ts +0 -27
  358. package/src/adapters/shared/table-name-mapper.ts +0 -50
  359. package/src/schema-generator/schema-generator.ts +0 -12
  360. package/src/shared/config.ts +0 -10
  361. package/src/shared/connection-pool.ts +0 -24
  362. package/src/shared/prisma.ts +0 -45
@@ -0,0 +1,19 @@
1
+ //#region src/naming/sql-naming.d.ts
2
+ type NamespaceScope = "suffix" | "schema";
3
+ interface SqlNamingStrategy {
4
+ namespaceScope: NamespaceScope;
5
+ namespaceToSchema: (namespace: string) => string;
6
+ tableName: (logicalTable: string, namespace: string | null) => string;
7
+ columnName: (logicalColumn: string, logicalTable: string) => string;
8
+ indexName: (logicalIndex: string, logicalTable: string, namespace: string | null) => string;
9
+ uniqueIndexName: (logicalIndex: string, logicalTable: string, namespace: string | null) => string;
10
+ foreignKeyName: (params: {
11
+ logicalTable: string;
12
+ logicalReferencedTable: string;
13
+ referenceName: string;
14
+ namespace: string | null;
15
+ }) => string;
16
+ }
17
+ //#endregion
18
+ export { SqlNamingStrategy };
19
+ //# sourceMappingURL=sql-naming.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-naming.d.ts","names":[],"sources":["../../src/naming/sql-naming.ts"],"sourcesContent":[],"mappings":";AAGY,KAAA,cAAA,GAAc,QAAA,GAAA,QAAA;AAET,UAAA,iBAAA,CAAiB;kBAChB"}
@@ -0,0 +1,116 @@
1
+ import { createHash } from "node:crypto";
2
+
3
+ //#region src/naming/sql-naming.ts
4
+ const normalizeNamespace = (namespace) => namespace && namespace.length > 0 ? namespace : null;
5
+ const buildNamespaceSuffix = (namespace) => {
6
+ const sanitized = normalizeNamespace(namespace);
7
+ return sanitized ? `_${sanitized}` : "";
8
+ };
9
+ const MAX_IDENTIFIER_LENGTH = 63;
10
+ const HASH_LENGTH = 8;
11
+ const withHash = (value) => {
12
+ return `${value}_${createHash("sha1").update(value).digest("hex").slice(0, 8)}`;
13
+ };
14
+ const truncateWithHash = (value) => {
15
+ if (value.length <= MAX_IDENTIFIER_LENGTH) return value;
16
+ const hash = createHash("sha1").update(value).digest("hex").slice(0, HASH_LENGTH);
17
+ return `${value.slice(0, MAX_IDENTIFIER_LENGTH - HASH_LENGTH)}${hash}`;
18
+ };
19
+ const buildIndexName = (prefix, logicalIndex, logicalTable, namespace) => {
20
+ return `${prefix}_${withHash(`${logicalTable}_${logicalIndex}${buildNamespaceSuffix(namespace)}`)}`;
21
+ };
22
+ const suffixNamingStrategy = {
23
+ namespaceScope: "suffix",
24
+ namespaceToSchema: (namespace) => namespace,
25
+ tableName: (logicalTable, namespace) => {
26
+ const sanitized = normalizeNamespace(namespace);
27
+ return truncateWithHash(sanitized ? `${logicalTable}_${sanitized}` : logicalTable);
28
+ },
29
+ columnName: (logicalColumn) => logicalColumn,
30
+ indexName: (logicalIndex, logicalTable, namespace) => truncateWithHash(buildIndexName("idx", logicalIndex, logicalTable, namespace)),
31
+ uniqueIndexName: (logicalIndex, logicalTable, namespace) => truncateWithHash(buildIndexName("uidx", logicalIndex, logicalTable, namespace)),
32
+ foreignKeyName: ({ logicalTable, logicalReferencedTable, referenceName, namespace }) => {
33
+ return truncateWithHash(`fk_${withHash(`${logicalTable}_${logicalReferencedTable}_${referenceName}${buildNamespaceSuffix(namespace)}`)}`);
34
+ }
35
+ };
36
+ const schemaNamingStrategy = {
37
+ namespaceScope: "schema",
38
+ namespaceToSchema: (namespace) => namespace,
39
+ tableName: (logicalTable) => truncateWithHash(logicalTable),
40
+ columnName: (logicalColumn) => logicalColumn,
41
+ indexName: (logicalIndex) => truncateWithHash(logicalIndex),
42
+ uniqueIndexName: (logicalIndex) => truncateWithHash(logicalIndex),
43
+ foreignKeyName: ({ logicalTable, logicalReferencedTable, referenceName }) => truncateWithHash(`fk_${logicalTable}_${logicalReferencedTable}_${referenceName}`)
44
+ };
45
+ var NamingResolver = class {
46
+ #namespace;
47
+ #strategy;
48
+ #tableNameMap = {};
49
+ #columnNameMaps = /* @__PURE__ */ new Map();
50
+ constructor(schema, namespace, strategy) {
51
+ this.#namespace = namespace;
52
+ this.#strategy = strategy;
53
+ for (const table of Object.values(schema.tables)) {
54
+ const physicalTable = this.getTableName(table.name);
55
+ this.#tableNameMap[physicalTable] = table.name;
56
+ const columnMap = {};
57
+ for (const column of Object.values(table.columns)) {
58
+ const physicalColumn = this.getColumnName(table.name, column.name);
59
+ columnMap[physicalColumn] = column.name;
60
+ }
61
+ this.#columnNameMaps.set(table.name, columnMap);
62
+ }
63
+ }
64
+ get namespace() {
65
+ return this.#namespace;
66
+ }
67
+ get strategy() {
68
+ return this.#strategy;
69
+ }
70
+ getSchemaName() {
71
+ if (this.#strategy.namespaceScope !== "schema") return null;
72
+ if (!this.#namespace || this.#namespace.length === 0) return null;
73
+ return this.#strategy.namespaceToSchema(this.#namespace);
74
+ }
75
+ getTableName(logicalTable) {
76
+ return this.#strategy.tableName(logicalTable, this.#namespace);
77
+ }
78
+ getColumnName(logicalTable, logicalColumn) {
79
+ return this.#strategy.columnName(logicalColumn, logicalTable);
80
+ }
81
+ getIndexName(logicalIndex, logicalTable) {
82
+ return this.#strategy.indexName(logicalIndex, logicalTable, this.#namespace);
83
+ }
84
+ getUniqueIndexName(logicalIndex, logicalTable) {
85
+ return this.#strategy.uniqueIndexName(logicalIndex, logicalTable, this.#namespace);
86
+ }
87
+ getForeignKeyName(params) {
88
+ return this.#strategy.foreignKeyName({
89
+ ...params,
90
+ namespace: this.#namespace
91
+ });
92
+ }
93
+ getTableNameMap() {
94
+ return { ...this.#tableNameMap };
95
+ }
96
+ getColumnNameMap(table) {
97
+ const tableName = typeof table === "string" ? table : table.name;
98
+ const map = this.#columnNameMaps.get(tableName);
99
+ return map ? { ...map } : {};
100
+ }
101
+ };
102
+ const createNamingResolver = (schema, namespace, strategy) => new NamingResolver(schema, namespace, strategy);
103
+ /**
104
+ * Sanitizes a namespace for use in SQL identifiers and TypeScript exports.
105
+ * Converts dashes to underscores to ensure compatibility with SQL identifiers.
106
+ *
107
+ * @example
108
+ * sanitizeNamespace("my-fragment") // => "my_fragment"
109
+ */
110
+ function sanitizeNamespace(namespace) {
111
+ return namespace.replace(/-/g, "_");
112
+ }
113
+
114
+ //#endregion
115
+ export { createNamingResolver, sanitizeNamespace, schemaNamingStrategy, suffixNamingStrategy };
116
+ //# sourceMappingURL=sql-naming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-naming.js","names":["suffixNamingStrategy: SqlNamingStrategy","schemaNamingStrategy: SqlNamingStrategy","#namespace","#strategy","#tableNameMap","#columnNameMaps","columnMap: Record<string, string>"],"sources":["../../src/naming/sql-naming.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { AnySchema, AnyTable } from \"../schema/create\";\n\nexport type NamespaceScope = \"suffix\" | \"schema\";\n\nexport interface SqlNamingStrategy {\n namespaceScope: NamespaceScope;\n namespaceToSchema: (namespace: string) => string;\n\n tableName: (logicalTable: string, namespace: string | null) => string;\n columnName: (logicalColumn: string, logicalTable: string) => string;\n\n indexName: (logicalIndex: string, logicalTable: string, namespace: string | null) => string;\n uniqueIndexName: (logicalIndex: string, logicalTable: string, namespace: string | null) => string;\n foreignKeyName: (params: {\n logicalTable: string;\n logicalReferencedTable: string;\n referenceName: string;\n namespace: string | null;\n }) => string;\n}\n\nconst normalizeNamespace = (namespace: string | null) =>\n namespace && namespace.length > 0 ? namespace : null;\n\nconst buildNamespaceSuffix = (namespace: string | null) => {\n const sanitized = normalizeNamespace(namespace);\n return sanitized ? `_${sanitized}` : \"\";\n};\n\nconst MAX_IDENTIFIER_LENGTH = 63;\nconst HASH_LENGTH = 8;\n\nconst withHash = (value: string) => {\n const hash = createHash(\"sha1\").update(value).digest(\"hex\").slice(0, 8);\n return `${value}_${hash}`;\n};\n\nconst truncateWithHash = (value: string) => {\n if (value.length <= MAX_IDENTIFIER_LENGTH) {\n return value;\n }\n const hash = createHash(\"sha1\").update(value).digest(\"hex\").slice(0, HASH_LENGTH);\n return `${value.slice(0, MAX_IDENTIFIER_LENGTH - HASH_LENGTH)}${hash}`;\n};\n\nconst buildIndexName = (\n prefix: \"idx\" | \"uidx\",\n logicalIndex: string,\n logicalTable: string,\n namespace: string | null,\n) => {\n const base = `${logicalTable}_${logicalIndex}${buildNamespaceSuffix(namespace)}`;\n return `${prefix}_${withHash(base)}`;\n};\n\nexport const suffixNamingStrategy: SqlNamingStrategy = {\n namespaceScope: \"suffix\",\n namespaceToSchema: (namespace) => namespace,\n tableName: (logicalTable, namespace) => {\n const sanitized = normalizeNamespace(namespace);\n return truncateWithHash(sanitized ? `${logicalTable}_${sanitized}` : logicalTable);\n },\n columnName: (logicalColumn) => logicalColumn,\n indexName: (logicalIndex, logicalTable, namespace) =>\n truncateWithHash(buildIndexName(\"idx\", logicalIndex, logicalTable, namespace)),\n uniqueIndexName: (logicalIndex, logicalTable, namespace) =>\n truncateWithHash(buildIndexName(\"uidx\", logicalIndex, logicalTable, namespace)),\n foreignKeyName: ({ logicalTable, logicalReferencedTable, referenceName, namespace }) => {\n const base = `${logicalTable}_${logicalReferencedTable}_${referenceName}${buildNamespaceSuffix(namespace)}`;\n return truncateWithHash(`fk_${withHash(base)}`);\n },\n};\n\nexport const schemaNamingStrategy: SqlNamingStrategy = {\n namespaceScope: \"schema\",\n namespaceToSchema: (namespace) => namespace,\n tableName: (logicalTable) => truncateWithHash(logicalTable),\n columnName: (logicalColumn) => logicalColumn,\n indexName: (logicalIndex) => truncateWithHash(logicalIndex),\n uniqueIndexName: (logicalIndex) => truncateWithHash(logicalIndex),\n foreignKeyName: ({ logicalTable, logicalReferencedTable, referenceName }) =>\n truncateWithHash(`fk_${logicalTable}_${logicalReferencedTable}_${referenceName}`),\n};\n\nexport class NamingResolver {\n readonly #namespace: string | null;\n readonly #strategy: SqlNamingStrategy;\n readonly #tableNameMap: Record<string, string> = {};\n readonly #columnNameMaps = new Map<string, Record<string, string>>();\n\n constructor(schema: AnySchema, namespace: string | null, strategy: SqlNamingStrategy) {\n this.#namespace = namespace;\n this.#strategy = strategy;\n\n for (const table of Object.values(schema.tables)) {\n const physicalTable = this.getTableName(table.name);\n this.#tableNameMap[physicalTable] = table.name;\n\n const columnMap: Record<string, string> = {};\n for (const column of Object.values(table.columns)) {\n const physicalColumn = this.getColumnName(table.name, column.name);\n columnMap[physicalColumn] = column.name;\n }\n this.#columnNameMaps.set(table.name, columnMap);\n }\n }\n\n get namespace(): string | null {\n return this.#namespace;\n }\n\n get strategy(): SqlNamingStrategy {\n return this.#strategy;\n }\n\n getSchemaName(): string | null {\n if (this.#strategy.namespaceScope !== \"schema\") {\n return null;\n }\n if (!this.#namespace || this.#namespace.length === 0) {\n return null;\n }\n return this.#strategy.namespaceToSchema(this.#namespace);\n }\n\n getTableName(logicalTable: string): string {\n return this.#strategy.tableName(logicalTable, this.#namespace);\n }\n\n getColumnName(logicalTable: string, logicalColumn: string): string {\n return this.#strategy.columnName(logicalColumn, logicalTable);\n }\n\n getIndexName(logicalIndex: string, logicalTable: string): string {\n return this.#strategy.indexName(logicalIndex, logicalTable, this.#namespace);\n }\n\n getUniqueIndexName(logicalIndex: string, logicalTable: string): string {\n return this.#strategy.uniqueIndexName(logicalIndex, logicalTable, this.#namespace);\n }\n\n getForeignKeyName(params: {\n logicalTable: string;\n logicalReferencedTable: string;\n referenceName: string;\n }): string {\n return this.#strategy.foreignKeyName({\n ...params,\n namespace: this.#namespace,\n });\n }\n\n getTableNameMap(): Record<string, string> {\n return { ...this.#tableNameMap };\n }\n\n getColumnNameMap(table: AnyTable | string): Record<string, string> {\n const tableName = typeof table === \"string\" ? table : table.name;\n const map = this.#columnNameMaps.get(tableName);\n return map ? { ...map } : {};\n }\n}\n\nexport const createNamingResolver = (\n schema: AnySchema,\n namespace: string | null,\n strategy: SqlNamingStrategy,\n): NamingResolver => new NamingResolver(schema, namespace, strategy);\n\n/**\n * Sanitizes a namespace for use in SQL identifiers and TypeScript exports.\n * Converts dashes to underscores to ensure compatibility with SQL identifiers.\n *\n * @example\n * sanitizeNamespace(\"my-fragment\") // => \"my_fragment\"\n */\nexport function sanitizeNamespace(namespace: string): string {\n return namespace.replace(/-/g, \"_\");\n}\n"],"mappings":";;;AAsBA,MAAM,sBAAsB,cAC1B,aAAa,UAAU,SAAS,IAAI,YAAY;AAElD,MAAM,wBAAwB,cAA6B;CACzD,MAAM,YAAY,mBAAmB,UAAU;AAC/C,QAAO,YAAY,IAAI,cAAc;;AAGvC,MAAM,wBAAwB;AAC9B,MAAM,cAAc;AAEpB,MAAM,YAAY,UAAkB;AAElC,QAAO,GAAG,MAAM,GADH,WAAW,OAAO,CAAC,OAAO,MAAM,CAAC,OAAO,MAAM,CAAC,MAAM,GAAG,EAAE;;AAIzE,MAAM,oBAAoB,UAAkB;AAC1C,KAAI,MAAM,UAAU,sBAClB,QAAO;CAET,MAAM,OAAO,WAAW,OAAO,CAAC,OAAO,MAAM,CAAC,OAAO,MAAM,CAAC,MAAM,GAAG,YAAY;AACjF,QAAO,GAAG,MAAM,MAAM,GAAG,wBAAwB,YAAY,GAAG;;AAGlE,MAAM,kBACJ,QACA,cACA,cACA,cACG;AAEH,QAAO,GAAG,OAAO,GAAG,SADP,GAAG,aAAa,GAAG,eAAe,qBAAqB,UAAU,GAC5C;;AAGpC,MAAaA,uBAA0C;CACrD,gBAAgB;CAChB,oBAAoB,cAAc;CAClC,YAAY,cAAc,cAAc;EACtC,MAAM,YAAY,mBAAmB,UAAU;AAC/C,SAAO,iBAAiB,YAAY,GAAG,aAAa,GAAG,cAAc,aAAa;;CAEpF,aAAa,kBAAkB;CAC/B,YAAY,cAAc,cAAc,cACtC,iBAAiB,eAAe,OAAO,cAAc,cAAc,UAAU,CAAC;CAChF,kBAAkB,cAAc,cAAc,cAC5C,iBAAiB,eAAe,QAAQ,cAAc,cAAc,UAAU,CAAC;CACjF,iBAAiB,EAAE,cAAc,wBAAwB,eAAe,gBAAgB;AAEtF,SAAO,iBAAiB,MAAM,SADjB,GAAG,aAAa,GAAG,uBAAuB,GAAG,gBAAgB,qBAAqB,UAAU,GAC7D,GAAG;;CAElD;AAED,MAAaC,uBAA0C;CACrD,gBAAgB;CAChB,oBAAoB,cAAc;CAClC,YAAY,iBAAiB,iBAAiB,aAAa;CAC3D,aAAa,kBAAkB;CAC/B,YAAY,iBAAiB,iBAAiB,aAAa;CAC3D,kBAAkB,iBAAiB,iBAAiB,aAAa;CACjE,iBAAiB,EAAE,cAAc,wBAAwB,oBACvD,iBAAiB,MAAM,aAAa,GAAG,uBAAuB,GAAG,gBAAgB;CACpF;AAED,IAAa,iBAAb,MAA4B;CAC1B,CAASC;CACT,CAASC;CACT,CAASC,eAAwC,EAAE;CACnD,CAASC,iCAAkB,IAAI,KAAqC;CAEpE,YAAY,QAAmB,WAA0B,UAA6B;AACpF,QAAKH,YAAa;AAClB,QAAKC,WAAY;AAEjB,OAAK,MAAM,SAAS,OAAO,OAAO,OAAO,OAAO,EAAE;GAChD,MAAM,gBAAgB,KAAK,aAAa,MAAM,KAAK;AACnD,SAAKC,aAAc,iBAAiB,MAAM;GAE1C,MAAME,YAAoC,EAAE;AAC5C,QAAK,MAAM,UAAU,OAAO,OAAO,MAAM,QAAQ,EAAE;IACjD,MAAM,iBAAiB,KAAK,cAAc,MAAM,MAAM,OAAO,KAAK;AAClE,cAAU,kBAAkB,OAAO;;AAErC,SAAKD,eAAgB,IAAI,MAAM,MAAM,UAAU;;;CAInD,IAAI,YAA2B;AAC7B,SAAO,MAAKH;;CAGd,IAAI,WAA8B;AAChC,SAAO,MAAKC;;CAGd,gBAA+B;AAC7B,MAAI,MAAKA,SAAU,mBAAmB,SACpC,QAAO;AAET,MAAI,CAAC,MAAKD,aAAc,MAAKA,UAAW,WAAW,EACjD,QAAO;AAET,SAAO,MAAKC,SAAU,kBAAkB,MAAKD,UAAW;;CAG1D,aAAa,cAA8B;AACzC,SAAO,MAAKC,SAAU,UAAU,cAAc,MAAKD,UAAW;;CAGhE,cAAc,cAAsB,eAA+B;AACjE,SAAO,MAAKC,SAAU,WAAW,eAAe,aAAa;;CAG/D,aAAa,cAAsB,cAA8B;AAC/D,SAAO,MAAKA,SAAU,UAAU,cAAc,cAAc,MAAKD,UAAW;;CAG9E,mBAAmB,cAAsB,cAA8B;AACrE,SAAO,MAAKC,SAAU,gBAAgB,cAAc,cAAc,MAAKD,UAAW;;CAGpF,kBAAkB,QAIP;AACT,SAAO,MAAKC,SAAU,eAAe;GACnC,GAAG;GACH,WAAW,MAAKD;GACjB,CAAC;;CAGJ,kBAA0C;AACxC,SAAO,EAAE,GAAG,MAAKE,cAAe;;CAGlC,iBAAiB,OAAkD;EACjE,MAAM,YAAY,OAAO,UAAU,WAAW,QAAQ,MAAM;EAC5D,MAAM,MAAM,MAAKC,eAAgB,IAAI,UAAU;AAC/C,SAAO,MAAM,EAAE,GAAG,KAAK,GAAG,EAAE;;;AAIhC,MAAa,wBACX,QACA,WACA,aACmB,IAAI,eAAe,QAAQ,WAAW,SAAS;;;;;;;;AASpE,SAAgB,kBAAkB,WAA2B;AAC3D,QAAO,UAAU,QAAQ,MAAM,IAAI"}
@@ -1,4 +1,4 @@
1
- //#region ../../node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.mjs
1
+ //#region ../../node_modules/.pnpm/rou3@0.7.12/node_modules/rou3/dist/index.mjs
2
2
  const NullProtoObj = /* @__PURE__ */ (() => {
3
3
  const e = function() {};
4
4
  return e.prototype = Object.create(null), Object.freeze(e.prototype), e;
@@ -19,7 +19,7 @@ function splitPath(path) {
19
19
  function getMatchParams(segments, paramsMap) {
20
20
  const params = new NullProtoObj();
21
21
  for (const [index, name] of paramsMap) {
22
- const segment = index < 0 ? segments.slice(-1 * index).join("/") : segments[index];
22
+ const segment = index < 0 ? segments.slice(-(index + 1)).join("/") : segments[index];
23
23
  if (typeof name === "string") params[name] = segment;
24
24
  else {
25
25
  const match = segment.match(name);
@@ -34,18 +34,19 @@ function getMatchParams(segments, paramsMap) {
34
34
  function addRoute(ctx, method = "", path, data) {
35
35
  method = method.toUpperCase();
36
36
  if (path.charCodeAt(0) !== 47) path = `/${path}`;
37
+ path = path.replace(/\\:/g, "%3A");
37
38
  const segments = splitPath(path);
38
39
  let node = ctx.root;
39
40
  let _unnamedParamIndex = 0;
40
41
  const paramsMap = [];
41
42
  const paramsRegexp = [];
42
43
  for (let i = 0; i < segments.length; i++) {
43
- const segment = segments[i];
44
+ let segment = segments[i];
44
45
  if (segment.startsWith("**")) {
45
46
  if (!node.wildcard) node.wildcard = { key: "**" };
46
47
  node = node.wildcard;
47
48
  paramsMap.push([
48
- -i,
49
+ -(i + 1),
49
50
  segment.split(":")[1] || "_",
50
51
  segment.length === 2
51
52
  ]);
@@ -75,6 +76,8 @@ function addRoute(ctx, method = "", path, data) {
75
76
  ]);
76
77
  continue;
77
78
  }
79
+ if (segment === "\\*") segment = segments[i] = "*";
80
+ else if (segment === "\\*\\*") segment = segments[i] = "**";
78
81
  const child = node.static?.[segment];
79
82
  if (child) node = child;
80
83
  else {
@@ -92,7 +95,7 @@ function addRoute(ctx, method = "", path, data) {
92
95
  paramsRegexp,
93
96
  paramsMap: hasParams ? paramsMap : void 0
94
97
  });
95
- if (!hasParams) ctx.static[path] = node;
98
+ if (!hasParams) ctx.static["/" + segments.join("/")] = node;
96
99
  }
97
100
  function getParamRegexp(segment) {
98
101
  const regex = segment.replace(/:(\w+)/g, (_, id) => `(?<${id}>[^/]+)`).replace(/\./g, "\\.");
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../../../../../../node_modules/.pnpm/rou3@0.7.12/node_modules/rou3/dist/index.mjs"],"sourcesContent":["const NullProtoObj = /* @__PURE__ */ (() => {\n\tconst e = function() {};\n\treturn e.prototype = Object.create(null), Object.freeze(e.prototype), e;\n})();\n\n/**\n* Create a new router context.\n*/\nfunction createRouter() {\n\treturn {\n\t\troot: { key: \"\" },\n\t\tstatic: new NullProtoObj()\n\t};\n}\n\nfunction splitPath(path) {\n\tconst [_, ...s] = path.split(\"/\");\n\treturn s[s.length - 1] === \"\" ? s.slice(0, -1) : s;\n}\nfunction getMatchParams(segments, paramsMap) {\n\tconst params = new NullProtoObj();\n\tfor (const [index, name] of paramsMap) {\n\t\tconst segment = index < 0 ? segments.slice(-(index + 1)).join(\"/\") : segments[index];\n\t\tif (typeof name === \"string\") params[name] = segment;\n\t\telse {\n\t\t\tconst match = segment.match(name);\n\t\t\tif (match) for (const key in match.groups) params[key] = match.groups[key];\n\t\t}\n\t}\n\treturn params;\n}\n\n/**\n* Add a route to the router context.\n*/\nfunction addRoute(ctx, method = \"\", path, data) {\n\tmethod = method.toUpperCase();\n\tif (path.charCodeAt(0) !== 47) path = `/${path}`;\n\tpath = path.replace(/\\\\:/g, \"%3A\");\n\tconst segments = splitPath(path);\n\tlet node = ctx.root;\n\tlet _unnamedParamIndex = 0;\n\tconst paramsMap = [];\n\tconst paramsRegexp = [];\n\tfor (let i = 0; i < segments.length; i++) {\n\t\tlet segment = segments[i];\n\t\tif (segment.startsWith(\"**\")) {\n\t\t\tif (!node.wildcard) node.wildcard = { key: \"**\" };\n\t\t\tnode = node.wildcard;\n\t\t\tparamsMap.push([\n\t\t\t\t-(i + 1),\n\t\t\t\tsegment.split(\":\")[1] || \"_\",\n\t\t\t\tsegment.length === 2\n\t\t\t]);\n\t\t\tbreak;\n\t\t}\n\t\tif (segment === \"*\" || segment.includes(\":\")) {\n\t\t\tif (!node.param) node.param = { key: \"*\" };\n\t\t\tnode = node.param;\n\t\t\tif (segment === \"*\") paramsMap.push([\n\t\t\t\ti,\n\t\t\t\t`_${_unnamedParamIndex++}`,\n\t\t\t\ttrue\n\t\t\t]);\n\t\t\telse if (segment.includes(\":\", 1)) {\n\t\t\t\tconst regexp = getParamRegexp(segment);\n\t\t\t\tparamsRegexp[i] = regexp;\n\t\t\t\tnode.hasRegexParam = true;\n\t\t\t\tparamsMap.push([\n\t\t\t\t\ti,\n\t\t\t\t\tregexp,\n\t\t\t\t\tfalse\n\t\t\t\t]);\n\t\t\t} else paramsMap.push([\n\t\t\t\ti,\n\t\t\t\tsegment.slice(1),\n\t\t\t\tfalse\n\t\t\t]);\n\t\t\tcontinue;\n\t\t}\n\t\tif (segment === \"\\\\*\") segment = segments[i] = \"*\";\n\t\telse if (segment === \"\\\\*\\\\*\") segment = segments[i] = \"**\";\n\t\tconst child = node.static?.[segment];\n\t\tif (child) node = child;\n\t\telse {\n\t\t\tconst staticNode = { key: segment };\n\t\t\tif (!node.static) node.static = new NullProtoObj();\n\t\t\tnode.static[segment] = staticNode;\n\t\t\tnode = staticNode;\n\t\t}\n\t}\n\tconst hasParams = paramsMap.length > 0;\n\tif (!node.methods) node.methods = new NullProtoObj();\n\tnode.methods[method] ??= [];\n\tnode.methods[method].push({\n\t\tdata: data || null,\n\t\tparamsRegexp,\n\t\tparamsMap: hasParams ? paramsMap : void 0\n\t});\n\tif (!hasParams) ctx.static[\"/\" + segments.join(\"/\")] = node;\n}\nfunction getParamRegexp(segment) {\n\tconst regex = segment.replace(/:(\\w+)/g, (_, id) => `(?<${id}>[^/]+)`).replace(/\\./g, \"\\\\.\");\n\treturn /* @__PURE__ */ new RegExp(`^${regex}$`);\n}\n\n/**\n* Find a route by path.\n*/\nfunction findRoute(ctx, method = \"\", path, opts) {\n\tif (path.charCodeAt(path.length - 1) === 47) path = path.slice(0, -1);\n\tconst staticNode = ctx.static[path];\n\tif (staticNode && staticNode.methods) {\n\t\tconst staticMatch = staticNode.methods[method] || staticNode.methods[\"\"];\n\t\tif (staticMatch !== void 0) return staticMatch[0];\n\t}\n\tconst segments = splitPath(path);\n\tconst match = _lookupTree(ctx, ctx.root, method, segments, 0)?.[0];\n\tif (match === void 0) return;\n\tif (opts?.params === false) return match;\n\treturn {\n\t\tdata: match.data,\n\t\tparams: match.paramsMap ? getMatchParams(segments, match.paramsMap) : void 0\n\t};\n}\nfunction _lookupTree(ctx, node, method, segments, index) {\n\tif (index === segments.length) {\n\t\tif (node.methods) {\n\t\t\tconst match = node.methods[method] || node.methods[\"\"];\n\t\t\tif (match) return match;\n\t\t}\n\t\tif (node.param && node.param.methods) {\n\t\t\tconst match = node.param.methods[method] || node.param.methods[\"\"];\n\t\t\tif (match) {\n\t\t\t\tconst pMap = match[0].paramsMap;\n\t\t\t\tif (pMap?.[pMap?.length - 1]?.[2]) return match;\n\t\t\t}\n\t\t}\n\t\tif (node.wildcard && node.wildcard.methods) {\n\t\t\tconst match = node.wildcard.methods[method] || node.wildcard.methods[\"\"];\n\t\t\tif (match) {\n\t\t\t\tconst pMap = match[0].paramsMap;\n\t\t\t\tif (pMap?.[pMap?.length - 1]?.[2]) return match;\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\tconst segment = segments[index];\n\tif (node.static) {\n\t\tconst staticChild = node.static[segment];\n\t\tif (staticChild) {\n\t\t\tconst match = _lookupTree(ctx, staticChild, method, segments, index + 1);\n\t\t\tif (match) return match;\n\t\t}\n\t}\n\tif (node.param) {\n\t\tconst match = _lookupTree(ctx, node.param, method, segments, index + 1);\n\t\tif (match) {\n\t\t\tif (node.param.hasRegexParam) {\n\t\t\t\tconst exactMatch = match.find((m) => m.paramsRegexp[index]?.test(segment)) || match.find((m) => !m.paramsRegexp[index]);\n\t\t\t\treturn exactMatch ? [exactMatch] : void 0;\n\t\t\t}\n\t\t\treturn match;\n\t\t}\n\t}\n\tif (node.wildcard && node.wildcard.methods) return node.wildcard.methods[method] || node.wildcard.methods[\"\"];\n}\n\n/**\n* Remove a route from the router context.\n*/\nfunction removeRoute(ctx, method, path) {\n\tconst segments = splitPath(path);\n\treturn _remove(ctx.root, method || \"\", segments, 0);\n}\nfunction _remove(node, method, segments, index) {\n\tif (index === segments.length) {\n\t\tif (node.methods && method in node.methods) {\n\t\t\tdelete node.methods[method];\n\t\t\tif (Object.keys(node.methods).length === 0) node.methods = void 0;\n\t\t}\n\t\treturn;\n\t}\n\tconst segment = segments[index];\n\tif (segment === \"*\") {\n\t\tif (node.param) {\n\t\t\t_remove(node.param, method, segments, index + 1);\n\t\t\tif (_isEmptyNode(node.param)) node.param = void 0;\n\t\t}\n\t\treturn;\n\t}\n\tif (segment.startsWith(\"**\")) {\n\t\tif (node.wildcard) {\n\t\t\t_remove(node.wildcard, method, segments, index + 1);\n\t\t\tif (_isEmptyNode(node.wildcard)) node.wildcard = void 0;\n\t\t}\n\t\treturn;\n\t}\n\tconst childNode = node.static?.[segment];\n\tif (childNode) {\n\t\t_remove(childNode, method, segments, index + 1);\n\t\tif (_isEmptyNode(childNode)) {\n\t\t\tdelete node.static[segment];\n\t\t\tif (Object.keys(node.static).length === 0) node.static = void 0;\n\t\t}\n\t}\n}\nfunction _isEmptyNode(node) {\n\treturn node.methods === void 0 && node.static === void 0 && node.param === void 0 && node.wildcard === void 0;\n}\n\n/**\n* Find all route patterns that match the given path.\n*/\nfunction findAllRoutes(ctx, method = \"\", path, opts) {\n\tif (path.charCodeAt(path.length - 1) === 47) path = path.slice(0, -1);\n\tconst segments = splitPath(path);\n\tconst matches = _findAll(ctx, ctx.root, method, segments, 0);\n\tif (opts?.params === false) return matches;\n\treturn matches.map((m) => {\n\t\treturn {\n\t\t\tdata: m.data,\n\t\t\tparams: m.paramsMap ? getMatchParams(segments, m.paramsMap) : void 0\n\t\t};\n\t});\n}\nfunction _findAll(ctx, node, method, segments, index, matches = []) {\n\tconst segment = segments[index];\n\tif (node.wildcard && node.wildcard.methods) {\n\t\tconst match = node.wildcard.methods[method] || node.wildcard.methods[\"\"];\n\t\tif (match) matches.push(...match);\n\t}\n\tif (node.param) {\n\t\t_findAll(ctx, node.param, method, segments, index + 1, matches);\n\t\tif (index === segments.length && node.param.methods) {\n\t\t\tconst match = node.param.methods[method] || node.param.methods[\"\"];\n\t\t\tif (match) {\n\t\t\t\tconst pMap = match[0].paramsMap;\n\t\t\t\tif (pMap?.[pMap?.length - 1]?.[2]) matches.push(...match);\n\t\t\t}\n\t\t}\n\t}\n\tconst staticChild = node.static?.[segment];\n\tif (staticChild) _findAll(ctx, staticChild, method, segments, index + 1, matches);\n\tif (index === segments.length && node.methods) {\n\t\tconst match = node.methods[method] || node.methods[\"\"];\n\t\tif (match) matches.push(...match);\n\t}\n\treturn matches;\n}\n\nfunction routeToRegExp(route = \"/\") {\n\tconst reSegments = [];\n\tlet idCtr = 0;\n\tfor (const segment of route.split(\"/\")) {\n\t\tif (!segment) continue;\n\t\tif (segment === \"*\") reSegments.push(`(?<_${idCtr++}>[^/]*)`);\n\t\telse if (segment.startsWith(\"**\")) reSegments.push(segment === \"**\" ? \"?(?<_>.*)\" : `?(?<${segment.slice(3)}>.+)`);\n\t\telse if (segment.includes(\":\")) reSegments.push(segment.replace(/:(\\w+)/g, (_, id) => `(?<${id}>[^/]+)`).replace(/\\./g, \"\\\\.\"));\n\t\telse reSegments.push(segment);\n\t}\n\treturn /* @__PURE__ */ new RegExp(`^/${reSegments.join(\"/\")}/?$`);\n}\n\nexport { NullProtoObj, addRoute, createRouter, findAllRoutes, findRoute, removeRoute, routeToRegExp };"],"x_google_ignoreList":[0],"mappings":"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"}
@@ -0,0 +1,156 @@
1
+ import { FragnoId, FragnoReference } from "../schema/create.js";
2
+ import { internalSchema } from "../fragments/internal-fragment.schema.js";
3
+ import { encodeVersionstamp, versionstampToHex } from "./outbox.js";
4
+
5
+ //#region src/outbox/outbox-builder.ts
6
+ const INTERNAL_TABLE_NAMES = new Set(Object.keys(internalSchema.tables));
7
+ function buildOutboxPlan(operations) {
8
+ const drafts = [];
9
+ const lookups = [];
10
+ for (const op of operations) {
11
+ if (op.type === "check") continue;
12
+ if (isInternalMutation(op)) continue;
13
+ const table = getTable(op.schema, op.table);
14
+ const schemaName = op.namespace ?? "";
15
+ const namespace = op.namespace ? op.namespace : void 0;
16
+ const mutationIndex = drafts.length;
17
+ if (op.type === "create") {
18
+ drafts.push({
19
+ op: "create",
20
+ schema: schemaName,
21
+ namespace,
22
+ table: op.table,
23
+ externalId: op.generatedExternalId,
24
+ values: encodeOutboxValues({
25
+ table,
26
+ values: op.values,
27
+ mutationIndex,
28
+ namespace,
29
+ lookups
30
+ })
31
+ });
32
+ continue;
33
+ }
34
+ if (op.type === "update") {
35
+ drafts.push({
36
+ op: "update",
37
+ schema: schemaName,
38
+ namespace,
39
+ table: op.table,
40
+ externalId: getExternalId(op.id),
41
+ set: encodeOutboxValues({
42
+ table,
43
+ values: op.set,
44
+ mutationIndex,
45
+ namespace,
46
+ lookups
47
+ }),
48
+ checkVersion: op.checkVersion && op.id instanceof FragnoId ? op.id.version : void 0
49
+ });
50
+ continue;
51
+ }
52
+ if (op.type === "delete") drafts.push({
53
+ op: "delete",
54
+ schema: schemaName,
55
+ namespace,
56
+ table: op.table,
57
+ externalId: getExternalId(op.id),
58
+ checkVersion: op.checkVersion && op.id instanceof FragnoId ? op.id.version : void 0
59
+ });
60
+ }
61
+ return {
62
+ drafts,
63
+ lookups
64
+ };
65
+ }
66
+ function finalizeOutboxPayload(plan, transactionVersion) {
67
+ return {
68
+ version: 1,
69
+ mutations: plan.drafts.map((draft, index) => {
70
+ const versionstamp = versionstampToHex(encodeVersionstamp(transactionVersion, index));
71
+ return {
72
+ ...draft,
73
+ versionstamp
74
+ };
75
+ })
76
+ };
77
+ }
78
+ function encodeOutboxValues(options) {
79
+ const { table, values, mutationIndex, namespace, lookups } = options;
80
+ const output = {};
81
+ for (const [key, value] of Object.entries(values)) {
82
+ if (value === void 0) continue;
83
+ if (table.columns[key]?.role === "reference") {
84
+ output[key] = resolveReferenceValue({
85
+ value,
86
+ mutationIndex,
87
+ columnName: key,
88
+ table,
89
+ namespace,
90
+ lookups
91
+ });
92
+ continue;
93
+ }
94
+ if (value instanceof FragnoId) {
95
+ output[key] = value.externalId;
96
+ continue;
97
+ }
98
+ output[key] = value;
99
+ }
100
+ return output;
101
+ }
102
+ function resolveReferenceValue(options) {
103
+ const { value, mutationIndex, columnName, table, namespace, lookups } = options;
104
+ if (value === null) return null;
105
+ if (value instanceof FragnoId) return value.externalId;
106
+ if (typeof value === "string") return value;
107
+ if (value instanceof FragnoReference) return createReferencePlaceholder({
108
+ internalId: value.internalId,
109
+ mutationIndex,
110
+ columnName,
111
+ table,
112
+ namespace,
113
+ lookups
114
+ });
115
+ if (typeof value === "bigint" || typeof value === "number") return createReferencePlaceholder({
116
+ internalId: value,
117
+ mutationIndex,
118
+ columnName,
119
+ table,
120
+ namespace,
121
+ lookups
122
+ });
123
+ return value;
124
+ }
125
+ function createReferencePlaceholder(options) {
126
+ const { internalId, mutationIndex, columnName, table, namespace, lookups } = options;
127
+ const key = `${mutationIndex}.${columnName}`;
128
+ const referencedTable = resolveReferencedTable(table, columnName);
129
+ lookups.push({
130
+ key,
131
+ internalId,
132
+ table: referencedTable,
133
+ namespace
134
+ });
135
+ return { __fragno_ref: key };
136
+ }
137
+ function resolveReferencedTable(table, columnName) {
138
+ for (const relation of Object.values(table.relations)) if (relation.on.some(([localColumn]) => localColumn === columnName)) return relation.table;
139
+ throw new Error(`Reference column ${columnName} not found in table ${table.name}`);
140
+ }
141
+ function getExternalId(id) {
142
+ return typeof id === "string" ? id : id.externalId;
143
+ }
144
+ function isInternalMutation(op) {
145
+ if (op.schema === internalSchema) return true;
146
+ return op.namespace === "" && INTERNAL_TABLE_NAMES.has(op.table);
147
+ }
148
+ function getTable(schema, tableName) {
149
+ const table = schema.tables[tableName];
150
+ if (!table) throw new Error(`Invalid table name ${tableName}.`);
151
+ return table;
152
+ }
153
+
154
+ //#endregion
155
+ export { buildOutboxPlan, finalizeOutboxPayload };
156
+ //# sourceMappingURL=outbox-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox-builder.js","names":["drafts: OutboxMutationDraft[]","lookups: OutboxRefLookup[]","output: Record<string, unknown>"],"sources":["../../src/outbox/outbox-builder.ts"],"sourcesContent":["import type { MutationOperation } from \"../query/unit-of-work/unit-of-work\";\nimport type { AnySchema, AnyTable } from \"../schema/create\";\nimport { FragnoId, FragnoReference } from \"../schema/create\";\nimport { internalSchema } from \"../fragments/internal-fragment.schema\";\nimport type { OutboxRefLookup, OutboxPayload, OutboxMutation } from \"./outbox\";\nimport { encodeVersionstamp, versionstampToHex } from \"./outbox\";\n\nconst INTERNAL_TABLE_NAMES = new Set(Object.keys(internalSchema.tables));\n\ntype OutboxMutationDraft = OutboxMutation extends infer T\n ? T extends OutboxMutation\n ? Omit<T, \"versionstamp\"> & { versionstamp?: string }\n : never\n : never;\n\nexport type OutboxPlan = {\n drafts: OutboxMutationDraft[];\n lookups: OutboxRefLookup[];\n};\n\nexport function buildOutboxPlan(operations: MutationOperation<AnySchema>[]): OutboxPlan {\n const drafts: OutboxMutationDraft[] = [];\n const lookups: OutboxRefLookup[] = [];\n\n for (const op of operations) {\n if (op.type === \"check\") {\n continue;\n }\n\n if (isInternalMutation(op)) {\n continue;\n }\n\n const table = getTable(op.schema, op.table);\n const schemaName = op.namespace ?? \"\";\n const namespace = op.namespace ? op.namespace : undefined;\n const mutationIndex = drafts.length;\n\n if (op.type === \"create\") {\n drafts.push({\n op: \"create\",\n schema: schemaName,\n namespace,\n table: op.table,\n externalId: op.generatedExternalId,\n values: encodeOutboxValues({\n table,\n values: op.values,\n mutationIndex,\n namespace,\n lookups,\n }),\n });\n continue;\n }\n\n if (op.type === \"update\") {\n drafts.push({\n op: \"update\",\n schema: schemaName,\n namespace,\n table: op.table,\n externalId: getExternalId(op.id),\n set: encodeOutboxValues({\n table,\n values: op.set,\n mutationIndex,\n namespace,\n lookups,\n }),\n checkVersion: op.checkVersion && op.id instanceof FragnoId ? op.id.version : undefined,\n });\n continue;\n }\n\n if (op.type === \"delete\") {\n drafts.push({\n op: \"delete\",\n schema: schemaName,\n namespace,\n table: op.table,\n externalId: getExternalId(op.id),\n checkVersion: op.checkVersion && op.id instanceof FragnoId ? op.id.version : undefined,\n });\n }\n }\n\n return { drafts, lookups };\n}\n\nexport function finalizeOutboxPayload(plan: OutboxPlan, transactionVersion: bigint): OutboxPayload {\n const mutations: OutboxMutation[] = plan.drafts.map((draft, index) => {\n const versionstamp = versionstampToHex(encodeVersionstamp(transactionVersion, index));\n return { ...draft, versionstamp } as OutboxMutation;\n });\n\n return {\n version: 1,\n mutations,\n };\n}\n\nfunction encodeOutboxValues(options: {\n table: AnyTable;\n values: Record<string, unknown>;\n mutationIndex: number;\n namespace?: string;\n lookups: OutboxRefLookup[];\n}): Record<string, unknown> {\n const { table, values, mutationIndex, namespace, lookups } = options;\n const output: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(values)) {\n if (value === undefined) {\n continue;\n }\n\n const column = table.columns[key];\n\n if (column?.role === \"reference\") {\n const resolved = resolveReferenceValue({\n value,\n mutationIndex,\n columnName: key,\n table,\n namespace,\n lookups,\n });\n output[key] = resolved;\n continue;\n }\n\n if (value instanceof FragnoId) {\n output[key] = value.externalId;\n continue;\n }\n\n output[key] = value;\n }\n\n return output;\n}\n\nfunction resolveReferenceValue(options: {\n value: unknown;\n mutationIndex: number;\n columnName: string;\n table: AnyTable;\n namespace?: string;\n lookups: OutboxRefLookup[];\n}): unknown {\n const { value, mutationIndex, columnName, table, namespace, lookups } = options;\n\n if (value === null) {\n return null;\n }\n\n if (value instanceof FragnoId) {\n return value.externalId;\n }\n\n if (typeof value === \"string\") {\n return value;\n }\n\n if (value instanceof FragnoReference) {\n return createReferencePlaceholder({\n internalId: value.internalId,\n mutationIndex,\n columnName,\n table,\n namespace,\n lookups,\n });\n }\n\n if (typeof value === \"bigint\" || typeof value === \"number\") {\n return createReferencePlaceholder({\n internalId: value,\n mutationIndex,\n columnName,\n table,\n namespace,\n lookups,\n });\n }\n\n return value;\n}\n\nfunction createReferencePlaceholder(options: {\n internalId: bigint | number;\n mutationIndex: number;\n columnName: string;\n table: AnyTable;\n namespace?: string;\n lookups: OutboxRefLookup[];\n}): { __fragno_ref: string } {\n const { internalId, mutationIndex, columnName, table, namespace, lookups } = options;\n const key = `${mutationIndex}.${columnName}`;\n const referencedTable = resolveReferencedTable(table, columnName);\n\n lookups.push({\n key,\n internalId,\n table: referencedTable,\n namespace,\n });\n\n return { __fragno_ref: key };\n}\n\nfunction resolveReferencedTable(table: AnyTable, columnName: string): AnyTable {\n for (const relation of Object.values(table.relations)) {\n if (relation.on.some(([localColumn]) => localColumn === columnName)) {\n return relation.table;\n }\n }\n\n throw new Error(`Reference column ${columnName} not found in table ${table.name}`);\n}\n\nfunction getExternalId(id: FragnoId | string): string {\n return typeof id === \"string\" ? id : id.externalId;\n}\n\nfunction isInternalMutation(op: MutationOperation<AnySchema>): boolean {\n if (op.schema === internalSchema) {\n return true;\n }\n\n return op.namespace === \"\" && INTERNAL_TABLE_NAMES.has(op.table);\n}\n\nfunction getTable(schema: AnySchema, tableName: string): AnyTable {\n const table = schema.tables[tableName];\n if (!table) {\n throw new Error(`Invalid table name ${tableName}.`);\n }\n return table;\n}\n"],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import { FragnoId } from "../schema/create.js";
2
+
3
+ //#region src/outbox/outbox.d.ts
4
+ type OutboxConfig = {
5
+ enabled: boolean;
6
+ };
7
+ type OutboxPayload = {
8
+ version: 1;
9
+ mutations: OutboxMutation[];
10
+ };
11
+ type OutboxMutation = {
12
+ op: "create";
13
+ schema: string;
14
+ namespace?: string;
15
+ table: string;
16
+ externalId: string;
17
+ versionstamp: string;
18
+ values: Record<string, unknown>;
19
+ } | {
20
+ op: "update";
21
+ schema: string;
22
+ namespace?: string;
23
+ table: string;
24
+ externalId: string;
25
+ versionstamp: string;
26
+ set: Record<string, unknown>;
27
+ checkVersion?: number;
28
+ } | {
29
+ op: "delete";
30
+ schema: string;
31
+ namespace?: string;
32
+ table: string;
33
+ externalId: string;
34
+ versionstamp: string;
35
+ checkVersion?: number;
36
+ };
37
+ type OutboxRefMap = Record<string, string>;
38
+ type OutboxPayloadSerialized = {
39
+ json: unknown;
40
+ meta?: Record<string, unknown>;
41
+ };
42
+ type OutboxEntry = {
43
+ id: FragnoId;
44
+ versionstamp: string;
45
+ uowId: string;
46
+ payload: OutboxPayloadSerialized;
47
+ refMap?: OutboxRefMap;
48
+ createdAt: Date;
49
+ };
50
+ //#endregion
51
+ export { OutboxConfig, OutboxEntry, OutboxMutation, OutboxPayload, OutboxRefMap };
52
+ //# sourceMappingURL=outbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox.d.ts","names":[],"sources":["../../src/outbox/outbox.ts"],"sourcesContent":[],"mappings":";;;KAEY,YAAA;;AAAZ,CAAA;AAcY,KALA,aAAA,GAKc;EA8Bd,OAAA,EAAA,CAAA;EAEA,SAAA,EAnCC,cAmCD,EAAuB;AAKnC,CAAA;AACM,KAtCM,cAAA,GAsCN;EAGK,EAAA,EAAA,QAAA;EACA,MAAA,EAAA,MAAA;EACE,SAAA,CAAA,EAAA,MAAA;EAAI,KAAA,EAAA,MAAA;;;UAnCH;;;;;;;;OASH;;;;;;;;;;;KAaC,YAAA,GAAe;KAEf,uBAAA;;SAEH;;KAGG,WAAA;MACN;;;WAGK;WACA;aACE"}
@@ -0,0 +1,37 @@
1
+ //#region src/outbox/outbox.ts
2
+ function encodeVersionstamp(transactionVersion, userVersion) {
3
+ if (userVersion < 0 || userVersion > 65535) throw new Error(`Invalid outbox user version: ${userVersion}`);
4
+ const txBytes = bigintToBytes(transactionVersion, 10);
5
+ const userBytes = new Uint8Array(2);
6
+ userBytes[0] = userVersion >> 8 & 255;
7
+ userBytes[1] = userVersion & 255;
8
+ const combined = new Uint8Array(12);
9
+ combined.set(txBytes, 0);
10
+ combined.set(userBytes, 10);
11
+ return combined;
12
+ }
13
+ function versionstampToHex(bytes) {
14
+ let hex = "";
15
+ for (const byte of bytes) hex += byte.toString(16).padStart(2, "0");
16
+ return hex;
17
+ }
18
+ function parseOutboxVersionValue(value) {
19
+ if (typeof value === "bigint") return value;
20
+ if (typeof value === "number") return BigInt(value);
21
+ if (typeof value === "string") return BigInt(value);
22
+ throw new Error(`Invalid outbox version value: ${String(value)}`);
23
+ }
24
+ function bigintToBytes(value, length) {
25
+ const bytes = new Uint8Array(length);
26
+ let remaining = value;
27
+ for (let i = length - 1; i >= 0; i -= 1) {
28
+ bytes[i] = Number(remaining & 255n);
29
+ remaining >>= 8n;
30
+ }
31
+ if (remaining !== 0n) throw new Error(`Outbox version ${value} exceeds ${length * 8} bits`);
32
+ return bytes;
33
+ }
34
+
35
+ //#endregion
36
+ export { encodeVersionstamp, parseOutboxVersionValue, versionstampToHex };
37
+ //# sourceMappingURL=outbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox.js","names":[],"sources":["../../src/outbox/outbox.ts"],"sourcesContent":["import type { AnyTable, FragnoId } from \"../schema/create\";\n\nexport type OutboxConfig = {\n enabled: boolean;\n};\n\nexport type OutboxVersionstampStrategy =\n | \"update-returning\"\n | \"insert-on-conflict-returning\"\n | \"insert-on-duplicate-last-insert-id\";\n\nexport type OutboxPayload = {\n version: 1;\n mutations: OutboxMutation[];\n};\n\nexport type OutboxMutation =\n | {\n op: \"create\";\n schema: string;\n namespace?: string;\n table: string;\n externalId: string;\n versionstamp: string;\n values: Record<string, unknown>;\n }\n | {\n op: \"update\";\n schema: string;\n namespace?: string;\n table: string;\n externalId: string;\n versionstamp: string;\n set: Record<string, unknown>;\n checkVersion?: number;\n }\n | {\n op: \"delete\";\n schema: string;\n namespace?: string;\n table: string;\n externalId: string;\n versionstamp: string;\n checkVersion?: number;\n };\n\nexport type OutboxRefMap = Record<string, string>;\n\nexport type OutboxPayloadSerialized = {\n json: unknown;\n meta?: Record<string, unknown>;\n};\n\nexport type OutboxEntry = {\n id: FragnoId;\n versionstamp: string;\n uowId: string;\n payload: OutboxPayloadSerialized;\n refMap?: OutboxRefMap;\n createdAt: Date;\n};\n\nexport type OutboxRefLookup = {\n key: string;\n internalId: bigint | number;\n table: AnyTable;\n namespace?: string;\n};\n\nexport function encodeVersionstamp(transactionVersion: bigint, userVersion: number): Uint8Array {\n if (userVersion < 0 || userVersion > 0xffff) {\n throw new Error(`Invalid outbox user version: ${userVersion}`);\n }\n\n const txBytes = bigintToBytes(transactionVersion, 10);\n const userBytes = new Uint8Array(2);\n userBytes[0] = (userVersion >> 8) & 0xff;\n userBytes[1] = userVersion & 0xff;\n\n const combined = new Uint8Array(12);\n combined.set(txBytes, 0);\n combined.set(userBytes, 10);\n\n return combined;\n}\n\nexport function versionstampToHex(bytes: Uint8Array): string {\n let hex = \"\";\n for (const byte of bytes) {\n hex += byte.toString(16).padStart(2, \"0\");\n }\n return hex;\n}\n\nexport function hexToVersionstamp(hex: string): Uint8Array {\n if (hex.length % 2 !== 0) {\n throw new Error(`Invalid versionstamp hex length: ${hex.length}`);\n }\n\n const bytes = new Uint8Array(hex.length / 2);\n for (let i = 0; i < hex.length; i += 2) {\n bytes[i / 2] = Number.parseInt(hex.slice(i, i + 2), 16);\n }\n return bytes;\n}\n\nexport function parseOutboxVersionValue(value: unknown): bigint {\n if (typeof value === \"bigint\") {\n return value;\n }\n\n if (typeof value === \"number\") {\n return BigInt(value);\n }\n\n if (typeof value === \"string\") {\n return BigInt(value);\n }\n\n throw new Error(`Invalid outbox version value: ${String(value)}`);\n}\n\nfunction bigintToBytes(value: bigint, length: number): Uint8Array {\n const bytes = new Uint8Array(length);\n let remaining = value;\n\n for (let i = length - 1; i >= 0; i -= 1) {\n bytes[i] = Number(remaining & 0xffn);\n remaining >>= 8n;\n }\n\n if (remaining !== 0n) {\n throw new Error(`Outbox version ${value} exceeds ${length * 8} bits`);\n }\n\n return bytes;\n}\n"],"mappings":";AAqEA,SAAgB,mBAAmB,oBAA4B,aAAiC;AAC9F,KAAI,cAAc,KAAK,cAAc,MACnC,OAAM,IAAI,MAAM,gCAAgC,cAAc;CAGhE,MAAM,UAAU,cAAc,oBAAoB,GAAG;CACrD,MAAM,YAAY,IAAI,WAAW,EAAE;AACnC,WAAU,KAAM,eAAe,IAAK;AACpC,WAAU,KAAK,cAAc;CAE7B,MAAM,WAAW,IAAI,WAAW,GAAG;AACnC,UAAS,IAAI,SAAS,EAAE;AACxB,UAAS,IAAI,WAAW,GAAG;AAE3B,QAAO;;AAGT,SAAgB,kBAAkB,OAA2B;CAC3D,IAAI,MAAM;AACV,MAAK,MAAM,QAAQ,MACjB,QAAO,KAAK,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI;AAE3C,QAAO;;AAeT,SAAgB,wBAAwB,OAAwB;AAC9D,KAAI,OAAO,UAAU,SACnB,QAAO;AAGT,KAAI,OAAO,UAAU,SACnB,QAAO,OAAO,MAAM;AAGtB,KAAI,OAAO,UAAU,SACnB,QAAO,OAAO,MAAM;AAGtB,OAAM,IAAI,MAAM,iCAAiC,OAAO,MAAM,GAAG;;AAGnE,SAAS,cAAc,OAAe,QAA4B;CAChE,MAAM,QAAQ,IAAI,WAAW,OAAO;CACpC,IAAI,YAAY;AAEhB,MAAK,IAAI,IAAI,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;AACvC,QAAM,KAAK,OAAO,YAAY,KAAM;AACpC,gBAAc;;AAGhB,KAAI,cAAc,GAChB,OAAM,IAAI,MAAM,kBAAkB,MAAM,WAAW,SAAS,EAAE,OAAO;AAGvE,QAAO"}
@@ -269,8 +269,9 @@ var FragmentDefinitionBuilder = class FragmentDefinitionBuilder$1 {
269
269
  }
270
270
  /**
271
271
  * Register a linked fragment that will be automatically instantiated.
272
- * Linked fragments are service-only (no routes) and share the same config/options as the parent.
273
- * All services from the linked fragment will be available as private services.
272
+ * Linked fragments share the same config/options as the parent and their services
273
+ * are exposed as private services. Routes are not exposed by default, but the
274
+ * instantiator may mount internal linked fragment routes under an internal prefix.
274
275
  */
275
276
  withLinkedFragment(name, callback) {
276
277
  const newLinkedFragments = {
@@ -1 +1 @@
1
- {"version":3,"file":"fragment-definition-builder.js","names":["FragmentDefinitionBuilder","#name","#dependencies","#baseServices","#namedServices","#privateServices","#serviceDependencies","#createRequestStorage","#createThisContext","#getExternalStorage","#linkedFragments"],"sources":["../../../../../../fragno/dist/api/fragment-definition-builder.js"],"sourcesContent":["//#region src/api/fragment-definition-builder.ts\n/**\n* Builder class for creating fragment definitions.\n* This provides a fluent API for defining fragments with type safety.\n*/\nvar FragmentDefinitionBuilder = class FragmentDefinitionBuilder {\n\t#name;\n\t#dependencies;\n\t#baseServices;\n\t#namedServices;\n\t#privateServices;\n\t#serviceDependencies;\n\t#createRequestStorage;\n\t#createThisContext;\n\t#getExternalStorage;\n\t#linkedFragments;\n\tconstructor(name, state) {\n\t\tthis.#name = name;\n\t\tif (state) {\n\t\t\tthis.#dependencies = state.dependencies;\n\t\t\tthis.#baseServices = state.baseServices;\n\t\t\tthis.#namedServices = state.namedServices;\n\t\t\tthis.#privateServices = state.privateServices;\n\t\t\tthis.#serviceDependencies = state.serviceDependencies;\n\t\t\tthis.#createRequestStorage = state.createRequestStorage;\n\t\t\tthis.#createThisContext = state.createThisContext;\n\t\t\tthis.#getExternalStorage = state.getExternalStorage;\n\t\t\tthis.#linkedFragments = state.linkedFragments;\n\t\t}\n\t}\n\tget name() {\n\t\treturn this.#name;\n\t}\n\t/**\n\t* Define dependencies for this fragment.\n\t* Dependencies are available to services and handlers.\n\t*\n\t* **IMPORTANT**: This method resets all services, storage, and context configurations.\n\t* Always call `withDependencies` early in the builder chain, before defining services\n\t* or request storage/context.\n\t*\n\t* @example\n\t* ```typescript\n\t* // ✅ GOOD: Dependencies set first\n\t* defineFragment(\"my-fragment\")\n\t* .withDependencies(() => ({ apiKey: \"...\" }))\n\t* .withRequestStorage(({ deps }) => ({ userId: deps.apiKey }))\n\t* .providesService(\"myService\", ...)\n\t*\n\t* // ❌ BAD: Dependencies set late (erases storage setup)\n\t* defineFragment(\"my-fragment\")\n\t* .withRequestStorage(() => ({ userId: \"...\" })) // This gets erased!\n\t* .withDependencies(() => ({ apiKey: \"...\" }))\n\t* ```\n\t*/\n\twithDependencies(fn) {\n\t\tif (this.#baseServices || this.#namedServices || this.#privateServices || this.#createRequestStorage || this.#createThisContext || this.#getExternalStorage) console.warn(`[Fragno] Warning: withDependencies() on fragment \"${this.#name}\" is resetting previously configured services, request storage, or request context. To avoid this, call withDependencies() earlier in the builder chain, before configuring services or storage.`);\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: fn,\n\t\t\tbaseServices: void 0,\n\t\t\tnamedServices: void 0,\n\t\t\tprivateServices: void 0,\n\t\t\tserviceDependencies: this.#serviceDependencies,\n\t\t\tcreateRequestStorage: void 0,\n\t\t\tcreateThisContext: void 0,\n\t\t\tgetExternalStorage: void 0,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t});\n\t}\n\t/**\n\t* Define base (unnamed) services for this fragment.\n\t* Base services are accessible directly on the fragment instance.\n\t*/\n\tprovidesBaseService(fn) {\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: fn,\n\t\t\tnamedServices: this.#namedServices,\n\t\t\tprivateServices: this.#privateServices,\n\t\t\tserviceDependencies: this.#serviceDependencies,\n\t\t\tcreateRequestStorage: this.#createRequestStorage,\n\t\t\tcreateThisContext: this.#createThisContext,\n\t\t\tgetExternalStorage: this.#getExternalStorage,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t});\n\t}\n\t/**\n\t* Provide a named service that other fragments or users can use.\n\t* Named services are accessible as fragment.serviceName.method()\n\t*/\n\tprovidesService(serviceName, fn) {\n\t\tconst newNamedServices = {\n\t\t\t...this.#namedServices,\n\t\t\t[serviceName]: fn\n\t\t};\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: this.#baseServices,\n\t\t\tnamedServices: newNamedServices,\n\t\t\tprivateServices: this.#privateServices,\n\t\t\tserviceDependencies: this.#serviceDependencies,\n\t\t\tcreateRequestStorage: this.#createRequestStorage,\n\t\t\tcreateThisContext: this.#createThisContext,\n\t\t\tgetExternalStorage: this.#getExternalStorage,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t});\n\t}\n\t/**\n\t* Provide a private service that is only accessible to the fragment author.\n\t* Private services are NOT exposed on the fragment instance, but can be used\n\t* when defining other services (baseServices, namedServices, and other privateServices).\n\t* Private services are instantiated in order, so earlier private services are available\n\t* to later ones.\n\t*/\n\tprovidesPrivateService(serviceName, fn) {\n\t\tconst newPrivateServices = {\n\t\t\t...this.#privateServices,\n\t\t\t[serviceName]: fn\n\t\t};\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: this.#baseServices,\n\t\t\tnamedServices: this.#namedServices,\n\t\t\tprivateServices: newPrivateServices,\n\t\t\tserviceDependencies: this.#serviceDependencies,\n\t\t\tcreateRequestStorage: this.#createRequestStorage,\n\t\t\tcreateThisContext: this.#createThisContext,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t});\n\t}\n\t/**\n\t* Declare that this fragment uses a required service provided by the runtime.\n\t*/\n\tusesService(serviceName) {\n\t\tconst newServiceDependencies = {\n\t\t\t...this.#serviceDependencies,\n\t\t\t[serviceName]: {\n\t\t\t\tname: serviceName,\n\t\t\t\trequired: true\n\t\t\t}\n\t\t};\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: this.#baseServices,\n\t\t\tnamedServices: this.#namedServices,\n\t\t\tprivateServices: this.#privateServices,\n\t\t\tserviceDependencies: newServiceDependencies,\n\t\t\tcreateRequestStorage: this.#createRequestStorage,\n\t\t\tcreateThisContext: this.#createThisContext,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t});\n\t}\n\t/**\n\t* Declare that this fragment uses an optional service provided by the runtime.\n\t*/\n\tusesOptionalService(serviceName) {\n\t\tconst newServiceDependencies = {\n\t\t\t...this.#serviceDependencies,\n\t\t\t[serviceName]: {\n\t\t\t\tname: serviceName,\n\t\t\t\trequired: false\n\t\t\t}\n\t\t};\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: this.#baseServices,\n\t\t\tnamedServices: this.#namedServices,\n\t\t\tprivateServices: this.#privateServices,\n\t\t\tserviceDependencies: newServiceDependencies,\n\t\t\tcreateRequestStorage: this.#createRequestStorage,\n\t\t\tcreateThisContext: this.#createThisContext,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t});\n\t}\n\t/**\n\t* Define the type and initial data stored in AsyncLocalStorage for per-request isolation.\n\t* This should be called before withThisContext if you need to store request-specific data.\n\t*\n\t* @param initializer Function that returns the initial storage data for each request\n\t*\n\t* @example\n\t* ```typescript\n\t* .withRequestStorage(({ config, options, deps }) => ({\n\t* counter: 0,\n\t* userId: deps.currentUserId\n\t* }))\n\t* .withThisContext(({ storage }) => ({\n\t* serviceContext: {\n\t* get counter() { return storage.getStore()!.counter; }\n\t* },\n\t* handlerContext: {\n\t* get counter() { return storage.getStore()!.counter; }\n\t* }\n\t* }))\n\t* ```\n\t*/\n\twithRequestStorage(initializer) {\n\t\tconst preservedExternalStorage = this.#getExternalStorage ? this.#getExternalStorage : void 0;\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: this.#baseServices,\n\t\t\tnamedServices: this.#namedServices,\n\t\t\tprivateServices: this.#privateServices,\n\t\t\tserviceDependencies: this.#serviceDependencies,\n\t\t\tcreateRequestStorage: initializer,\n\t\t\tcreateThisContext: void 0,\n\t\t\tgetExternalStorage: preservedExternalStorage,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t});\n\t}\n\t/**\n\t* Use an externally-provided RequestContextStorage instance.\n\t* This allows multiple fragments to share the same storage instance.\n\t* Useful when fragments need to coordinate (e.g., database fragments sharing adapter storage).\n\t* Note: You must still call withRequestStorage to provide the initial storage data.\n\t*\n\t* @example\n\t* ```typescript\n\t* .withExternalRequestStorage(({ options }) =>\n\t* options.databaseAdapter.contextStorage\n\t* )\n\t* .withRequestStorage(({ options }) => ({\n\t* uow: options.databaseAdapter.db.createUnitOfWork()\n\t* }))\n\t* ```\n\t*/\n\twithExternalRequestStorage(getStorage) {\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: this.#baseServices,\n\t\t\tnamedServices: this.#namedServices,\n\t\t\tprivateServices: this.#privateServices,\n\t\t\tserviceDependencies: this.#serviceDependencies,\n\t\t\tcreateRequestStorage: void 0,\n\t\t\tcreateThisContext: void 0,\n\t\t\tgetExternalStorage: getStorage,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t});\n\t}\n\t/**\n\t* Set the this contexts for services and handlers in this fragment.\n\t* Both contexts should contain only methods or getters that read from storage.\n\t* This ensures proper per-request isolation via AsyncLocalStorage.\n\t*\n\t* @example\n\t* ```ts\n\t* .withThisContext(({ storage }) => ({\n\t* serviceContext: {\n\t* get myNumber() { return storage.getStore()?.myNumber ?? 0; }\n\t* },\n\t* handlerContext: {\n\t* get myNumber() { return storage.getStore()?.myNumber ?? 0; }\n\t* }\n\t* }))\n\t* ```\n\t*/\n\twithThisContext(fn) {\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: this.#baseServices,\n\t\t\tnamedServices: this.#namedServices,\n\t\t\tprivateServices: this.#privateServices,\n\t\t\tserviceDependencies: this.#serviceDependencies,\n\t\t\tcreateRequestStorage: this.#createRequestStorage,\n\t\t\tcreateThisContext: fn,\n\t\t\tgetExternalStorage: this.#getExternalStorage,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t});\n\t}\n\t/**\n\t* Register a linked fragment that will be automatically instantiated.\n\t* Linked fragments are service-only (no routes) and share the same config/options as the parent.\n\t* All services from the linked fragment will be available as private services.\n\t*/\n\twithLinkedFragment(name, callback) {\n\t\tconst newLinkedFragments = {\n\t\t\t...this.#linkedFragments,\n\t\t\t[name]: callback\n\t\t};\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: this.#baseServices,\n\t\t\tnamedServices: this.#namedServices,\n\t\t\tprivateServices: this.#privateServices,\n\t\t\tserviceDependencies: this.#serviceDependencies,\n\t\t\tcreateRequestStorage: this.#createRequestStorage,\n\t\t\tcreateThisContext: this.#createThisContext,\n\t\t\tgetExternalStorage: this.#getExternalStorage,\n\t\t\tlinkedFragments: newLinkedFragments\n\t\t});\n\t}\n\t/**\n\t* Extend this builder with a transformation function.\n\t* This enables fluent API extensions like `.extend(withDatabase(schema))`.\n\t*/\n\textend(transformer) {\n\t\treturn transformer(this);\n\t}\n\t/**\n\t* Build the final fragment definition\n\t*/\n\tbuild() {\n\t\treturn {\n\t\t\tname: this.#name,\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: this.#baseServices,\n\t\t\tnamedServices: this.#namedServices,\n\t\t\tprivateServices: this.#privateServices,\n\t\t\tserviceDependencies: this.#serviceDependencies,\n\t\t\tcreateRequestStorage: this.#createRequestStorage,\n\t\t\tcreateThisContext: this.#createThisContext,\n\t\t\tgetExternalStorage: this.#getExternalStorage,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t};\n\t}\n};\n/**\n* Create a new fragment definition builder\n*/\nfunction defineFragment(name) {\n\treturn new FragmentDefinitionBuilder(name);\n}\n\n//#endregion\nexport { FragmentDefinitionBuilder, defineFragment };\n//# sourceMappingURL=fragment-definition-builder.js.map"],"mappings":"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"}
1
+ {"version":3,"file":"fragment-definition-builder.js","names":["FragmentDefinitionBuilder","#name","#dependencies","#baseServices","#namedServices","#privateServices","#serviceDependencies","#createRequestStorage","#createThisContext","#getExternalStorage","#linkedFragments"],"sources":["../../../../../../fragno/dist/api/fragment-definition-builder.js"],"sourcesContent":["//#region src/api/fragment-definition-builder.ts\n/**\n* Builder class for creating fragment definitions.\n* This provides a fluent API for defining fragments with type safety.\n*/\nvar FragmentDefinitionBuilder = class FragmentDefinitionBuilder {\n\t#name;\n\t#dependencies;\n\t#baseServices;\n\t#namedServices;\n\t#privateServices;\n\t#serviceDependencies;\n\t#createRequestStorage;\n\t#createThisContext;\n\t#getExternalStorage;\n\t#linkedFragments;\n\tconstructor(name, state) {\n\t\tthis.#name = name;\n\t\tif (state) {\n\t\t\tthis.#dependencies = state.dependencies;\n\t\t\tthis.#baseServices = state.baseServices;\n\t\t\tthis.#namedServices = state.namedServices;\n\t\t\tthis.#privateServices = state.privateServices;\n\t\t\tthis.#serviceDependencies = state.serviceDependencies;\n\t\t\tthis.#createRequestStorage = state.createRequestStorage;\n\t\t\tthis.#createThisContext = state.createThisContext;\n\t\t\tthis.#getExternalStorage = state.getExternalStorage;\n\t\t\tthis.#linkedFragments = state.linkedFragments;\n\t\t}\n\t}\n\tget name() {\n\t\treturn this.#name;\n\t}\n\t/**\n\t* Define dependencies for this fragment.\n\t* Dependencies are available to services and handlers.\n\t*\n\t* **IMPORTANT**: This method resets all services, storage, and context configurations.\n\t* Always call `withDependencies` early in the builder chain, before defining services\n\t* or request storage/context.\n\t*\n\t* @example\n\t* ```typescript\n\t* // ✅ GOOD: Dependencies set first\n\t* defineFragment(\"my-fragment\")\n\t* .withDependencies(() => ({ apiKey: \"...\" }))\n\t* .withRequestStorage(({ deps }) => ({ userId: deps.apiKey }))\n\t* .providesService(\"myService\", ...)\n\t*\n\t* // ❌ BAD: Dependencies set late (erases storage setup)\n\t* defineFragment(\"my-fragment\")\n\t* .withRequestStorage(() => ({ userId: \"...\" })) // This gets erased!\n\t* .withDependencies(() => ({ apiKey: \"...\" }))\n\t* ```\n\t*/\n\twithDependencies(fn) {\n\t\tif (this.#baseServices || this.#namedServices || this.#privateServices || this.#createRequestStorage || this.#createThisContext || this.#getExternalStorage) console.warn(`[Fragno] Warning: withDependencies() on fragment \"${this.#name}\" is resetting previously configured services, request storage, or request context. To avoid this, call withDependencies() earlier in the builder chain, before configuring services or storage.`);\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: fn,\n\t\t\tbaseServices: void 0,\n\t\t\tnamedServices: void 0,\n\t\t\tprivateServices: void 0,\n\t\t\tserviceDependencies: this.#serviceDependencies,\n\t\t\tcreateRequestStorage: void 0,\n\t\t\tcreateThisContext: void 0,\n\t\t\tgetExternalStorage: void 0,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t});\n\t}\n\t/**\n\t* Define base (unnamed) services for this fragment.\n\t* Base services are accessible directly on the fragment instance.\n\t*/\n\tprovidesBaseService(fn) {\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: fn,\n\t\t\tnamedServices: this.#namedServices,\n\t\t\tprivateServices: this.#privateServices,\n\t\t\tserviceDependencies: this.#serviceDependencies,\n\t\t\tcreateRequestStorage: this.#createRequestStorage,\n\t\t\tcreateThisContext: this.#createThisContext,\n\t\t\tgetExternalStorage: this.#getExternalStorage,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t});\n\t}\n\t/**\n\t* Provide a named service that other fragments or users can use.\n\t* Named services are accessible as fragment.serviceName.method()\n\t*/\n\tprovidesService(serviceName, fn) {\n\t\tconst newNamedServices = {\n\t\t\t...this.#namedServices,\n\t\t\t[serviceName]: fn\n\t\t};\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: this.#baseServices,\n\t\t\tnamedServices: newNamedServices,\n\t\t\tprivateServices: this.#privateServices,\n\t\t\tserviceDependencies: this.#serviceDependencies,\n\t\t\tcreateRequestStorage: this.#createRequestStorage,\n\t\t\tcreateThisContext: this.#createThisContext,\n\t\t\tgetExternalStorage: this.#getExternalStorage,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t});\n\t}\n\t/**\n\t* Provide a private service that is only accessible to the fragment author.\n\t* Private services are NOT exposed on the fragment instance, but can be used\n\t* when defining other services (baseServices, namedServices, and other privateServices).\n\t* Private services are instantiated in order, so earlier private services are available\n\t* to later ones.\n\t*/\n\tprovidesPrivateService(serviceName, fn) {\n\t\tconst newPrivateServices = {\n\t\t\t...this.#privateServices,\n\t\t\t[serviceName]: fn\n\t\t};\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: this.#baseServices,\n\t\t\tnamedServices: this.#namedServices,\n\t\t\tprivateServices: newPrivateServices,\n\t\t\tserviceDependencies: this.#serviceDependencies,\n\t\t\tcreateRequestStorage: this.#createRequestStorage,\n\t\t\tcreateThisContext: this.#createThisContext,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t});\n\t}\n\t/**\n\t* Declare that this fragment uses a required service provided by the runtime.\n\t*/\n\tusesService(serviceName) {\n\t\tconst newServiceDependencies = {\n\t\t\t...this.#serviceDependencies,\n\t\t\t[serviceName]: {\n\t\t\t\tname: serviceName,\n\t\t\t\trequired: true\n\t\t\t}\n\t\t};\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: this.#baseServices,\n\t\t\tnamedServices: this.#namedServices,\n\t\t\tprivateServices: this.#privateServices,\n\t\t\tserviceDependencies: newServiceDependencies,\n\t\t\tcreateRequestStorage: this.#createRequestStorage,\n\t\t\tcreateThisContext: this.#createThisContext,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t});\n\t}\n\t/**\n\t* Declare that this fragment uses an optional service provided by the runtime.\n\t*/\n\tusesOptionalService(serviceName) {\n\t\tconst newServiceDependencies = {\n\t\t\t...this.#serviceDependencies,\n\t\t\t[serviceName]: {\n\t\t\t\tname: serviceName,\n\t\t\t\trequired: false\n\t\t\t}\n\t\t};\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: this.#baseServices,\n\t\t\tnamedServices: this.#namedServices,\n\t\t\tprivateServices: this.#privateServices,\n\t\t\tserviceDependencies: newServiceDependencies,\n\t\t\tcreateRequestStorage: this.#createRequestStorage,\n\t\t\tcreateThisContext: this.#createThisContext,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t});\n\t}\n\t/**\n\t* Define the type and initial data stored in AsyncLocalStorage for per-request isolation.\n\t* This should be called before withThisContext if you need to store request-specific data.\n\t*\n\t* @param initializer Function that returns the initial storage data for each request\n\t*\n\t* @example\n\t* ```typescript\n\t* .withRequestStorage(({ config, options, deps }) => ({\n\t* counter: 0,\n\t* userId: deps.currentUserId\n\t* }))\n\t* .withThisContext(({ storage }) => ({\n\t* serviceContext: {\n\t* get counter() { return storage.getStore()!.counter; }\n\t* },\n\t* handlerContext: {\n\t* get counter() { return storage.getStore()!.counter; }\n\t* }\n\t* }))\n\t* ```\n\t*/\n\twithRequestStorage(initializer) {\n\t\tconst preservedExternalStorage = this.#getExternalStorage ? this.#getExternalStorage : void 0;\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: this.#baseServices,\n\t\t\tnamedServices: this.#namedServices,\n\t\t\tprivateServices: this.#privateServices,\n\t\t\tserviceDependencies: this.#serviceDependencies,\n\t\t\tcreateRequestStorage: initializer,\n\t\t\tcreateThisContext: void 0,\n\t\t\tgetExternalStorage: preservedExternalStorage,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t});\n\t}\n\t/**\n\t* Use an externally-provided RequestContextStorage instance.\n\t* This allows multiple fragments to share the same storage instance.\n\t* Useful when fragments need to coordinate (e.g., database fragments sharing adapter storage).\n\t* Note: You must still call withRequestStorage to provide the initial storage data.\n\t*\n\t* @example\n\t* ```typescript\n\t* .withExternalRequestStorage(({ options }) =>\n\t* options.databaseAdapter.contextStorage\n\t* )\n\t* .withRequestStorage(({ options }) => ({\n\t* uow: options.databaseAdapter.db.createUnitOfWork()\n\t* }))\n\t* ```\n\t*/\n\twithExternalRequestStorage(getStorage) {\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: this.#baseServices,\n\t\t\tnamedServices: this.#namedServices,\n\t\t\tprivateServices: this.#privateServices,\n\t\t\tserviceDependencies: this.#serviceDependencies,\n\t\t\tcreateRequestStorage: void 0,\n\t\t\tcreateThisContext: void 0,\n\t\t\tgetExternalStorage: getStorage,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t});\n\t}\n\t/**\n\t* Set the this contexts for services and handlers in this fragment.\n\t* Both contexts should contain only methods or getters that read from storage.\n\t* This ensures proper per-request isolation via AsyncLocalStorage.\n\t*\n\t* @example\n\t* ```ts\n\t* .withThisContext(({ storage }) => ({\n\t* serviceContext: {\n\t* get myNumber() { return storage.getStore()?.myNumber ?? 0; }\n\t* },\n\t* handlerContext: {\n\t* get myNumber() { return storage.getStore()?.myNumber ?? 0; }\n\t* }\n\t* }))\n\t* ```\n\t*/\n\twithThisContext(fn) {\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: this.#baseServices,\n\t\t\tnamedServices: this.#namedServices,\n\t\t\tprivateServices: this.#privateServices,\n\t\t\tserviceDependencies: this.#serviceDependencies,\n\t\t\tcreateRequestStorage: this.#createRequestStorage,\n\t\t\tcreateThisContext: fn,\n\t\t\tgetExternalStorage: this.#getExternalStorage,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t});\n\t}\n\t/**\n\t* Register a linked fragment that will be automatically instantiated.\n\t* Linked fragments share the same config/options as the parent and their services\n\t* are exposed as private services. Routes are not exposed by default, but the\n\t* instantiator may mount internal linked fragment routes under an internal prefix.\n\t*/\n\twithLinkedFragment(name, callback) {\n\t\tconst newLinkedFragments = {\n\t\t\t...this.#linkedFragments,\n\t\t\t[name]: callback\n\t\t};\n\t\treturn new FragmentDefinitionBuilder(this.#name, {\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: this.#baseServices,\n\t\t\tnamedServices: this.#namedServices,\n\t\t\tprivateServices: this.#privateServices,\n\t\t\tserviceDependencies: this.#serviceDependencies,\n\t\t\tcreateRequestStorage: this.#createRequestStorage,\n\t\t\tcreateThisContext: this.#createThisContext,\n\t\t\tgetExternalStorage: this.#getExternalStorage,\n\t\t\tlinkedFragments: newLinkedFragments\n\t\t});\n\t}\n\t/**\n\t* Extend this builder with a transformation function.\n\t* This enables fluent API extensions like `.extend(withDatabase(schema))`.\n\t*/\n\textend(transformer) {\n\t\treturn transformer(this);\n\t}\n\t/**\n\t* Build the final fragment definition\n\t*/\n\tbuild() {\n\t\treturn {\n\t\t\tname: this.#name,\n\t\t\tdependencies: this.#dependencies,\n\t\t\tbaseServices: this.#baseServices,\n\t\t\tnamedServices: this.#namedServices,\n\t\t\tprivateServices: this.#privateServices,\n\t\t\tserviceDependencies: this.#serviceDependencies,\n\t\t\tcreateRequestStorage: this.#createRequestStorage,\n\t\t\tcreateThisContext: this.#createThisContext,\n\t\t\tgetExternalStorage: this.#getExternalStorage,\n\t\t\tlinkedFragments: this.#linkedFragments\n\t\t};\n\t}\n};\n/**\n* Create a new fragment definition builder\n*/\nfunction defineFragment(name) {\n\treturn new FragmentDefinitionBuilder(name);\n}\n\n//#endregion\nexport { FragmentDefinitionBuilder, defineFragment };\n//# sourceMappingURL=fragment-definition-builder.js.map"],"mappings":"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"}