@fragno-dev/db 0.1.13 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/.turbo/turbo-build.log +179 -132
  2. package/CHANGELOG.md +30 -0
  3. package/dist/adapters/adapters.d.ts +27 -1
  4. package/dist/adapters/adapters.d.ts.map +1 -1
  5. package/dist/adapters/adapters.js.map +1 -1
  6. package/dist/adapters/drizzle/drizzle-adapter.d.ts +5 -1
  7. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +1 -1
  8. package/dist/adapters/drizzle/drizzle-adapter.js +15 -3
  9. package/dist/adapters/drizzle/drizzle-adapter.js.map +1 -1
  10. package/dist/adapters/drizzle/drizzle-query.js +7 -5
  11. package/dist/adapters/drizzle/drizzle-query.js.map +1 -1
  12. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts +0 -1
  13. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts.map +1 -1
  14. package/dist/adapters/drizzle/drizzle-uow-compiler.js +76 -44
  15. package/dist/adapters/drizzle/drizzle-uow-compiler.js.map +1 -1
  16. package/dist/adapters/drizzle/drizzle-uow-decoder.js +23 -16
  17. package/dist/adapters/drizzle/drizzle-uow-decoder.js.map +1 -1
  18. package/dist/adapters/drizzle/drizzle-uow-executor.js +18 -7
  19. package/dist/adapters/drizzle/drizzle-uow-executor.js.map +1 -1
  20. package/dist/adapters/drizzle/generate.d.ts +4 -1
  21. package/dist/adapters/drizzle/generate.d.ts.map +1 -1
  22. package/dist/adapters/drizzle/generate.js +11 -18
  23. package/dist/adapters/drizzle/generate.js.map +1 -1
  24. package/dist/adapters/drizzle/shared.d.ts +14 -1
  25. package/dist/adapters/drizzle/shared.d.ts.map +1 -0
  26. package/dist/adapters/kysely/kysely-adapter.d.ts +5 -1
  27. package/dist/adapters/kysely/kysely-adapter.d.ts.map +1 -1
  28. package/dist/adapters/kysely/kysely-adapter.js +14 -3
  29. package/dist/adapters/kysely/kysely-adapter.js.map +1 -1
  30. package/dist/adapters/kysely/kysely-query-builder.js +1 -1
  31. package/dist/adapters/kysely/kysely-query-compiler.js +3 -2
  32. package/dist/adapters/kysely/kysely-query-compiler.js.map +1 -1
  33. package/dist/adapters/kysely/kysely-query.d.ts +1 -0
  34. package/dist/adapters/kysely/kysely-query.d.ts.map +1 -1
  35. package/dist/adapters/kysely/kysely-query.js +28 -19
  36. package/dist/adapters/kysely/kysely-query.js.map +1 -1
  37. package/dist/adapters/kysely/kysely-shared.d.ts +14 -0
  38. package/dist/adapters/kysely/kysely-shared.d.ts.map +1 -0
  39. package/dist/adapters/kysely/kysely-shared.js +16 -1
  40. package/dist/adapters/kysely/kysely-shared.js.map +1 -1
  41. package/dist/adapters/kysely/kysely-uow-compiler.js +68 -16
  42. package/dist/adapters/kysely/kysely-uow-compiler.js.map +1 -1
  43. package/dist/adapters/kysely/kysely-uow-executor.js +8 -4
  44. package/dist/adapters/kysely/kysely-uow-executor.js.map +1 -1
  45. package/dist/adapters/kysely/migration/execute-base.js +1 -1
  46. package/dist/adapters/kysely/migration/execute-base.js.map +1 -1
  47. package/dist/db-fragment-definition-builder.d.ts +152 -0
  48. package/dist/db-fragment-definition-builder.d.ts.map +1 -0
  49. package/dist/db-fragment-definition-builder.js +137 -0
  50. package/dist/db-fragment-definition-builder.js.map +1 -0
  51. package/dist/fragments/internal-fragment.d.ts +19 -0
  52. package/dist/fragments/internal-fragment.d.ts.map +1 -0
  53. package/dist/fragments/internal-fragment.js +39 -0
  54. package/dist/fragments/internal-fragment.js.map +1 -0
  55. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  56. package/dist/migration-engine/generation-engine.js +35 -15
  57. package/dist/migration-engine/generation-engine.js.map +1 -1
  58. package/dist/mod.d.ts +8 -18
  59. package/dist/mod.d.ts.map +1 -1
  60. package/dist/mod.js +7 -34
  61. package/dist/mod.js.map +1 -1
  62. package/dist/node_modules/.pnpm/rou3@0.7.8/node_modules/rou3/dist/index.js +165 -0
  63. package/dist/node_modules/.pnpm/rou3@0.7.8/node_modules/rou3/dist/index.js.map +1 -0
  64. package/dist/packages/fragno/dist/api/bind-services.js +20 -0
  65. package/dist/packages/fragno/dist/api/bind-services.js.map +1 -0
  66. package/dist/packages/fragno/dist/api/error.js +48 -0
  67. package/dist/packages/fragno/dist/api/error.js.map +1 -0
  68. package/dist/packages/fragno/dist/api/fragment-definition-builder.js +320 -0
  69. package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +1 -0
  70. package/dist/packages/fragno/dist/api/fragment-instantiator.js +487 -0
  71. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +1 -0
  72. package/dist/packages/fragno/dist/api/fragno-response.js +73 -0
  73. package/dist/packages/fragno/dist/api/fragno-response.js.map +1 -0
  74. package/dist/packages/fragno/dist/api/internal/response-stream.js +81 -0
  75. package/dist/packages/fragno/dist/api/internal/response-stream.js.map +1 -0
  76. package/dist/packages/fragno/dist/api/internal/route.js +10 -0
  77. package/dist/packages/fragno/dist/api/internal/route.js.map +1 -0
  78. package/dist/packages/fragno/dist/api/mutable-request-state.js +97 -0
  79. package/dist/packages/fragno/dist/api/mutable-request-state.js.map +1 -0
  80. package/dist/packages/fragno/dist/api/request-context-storage.js +43 -0
  81. package/dist/packages/fragno/dist/api/request-context-storage.js.map +1 -0
  82. package/dist/packages/fragno/dist/api/request-input-context.js +118 -0
  83. package/dist/packages/fragno/dist/api/request-input-context.js.map +1 -0
  84. package/dist/packages/fragno/dist/api/request-middleware.js +83 -0
  85. package/dist/packages/fragno/dist/api/request-middleware.js.map +1 -0
  86. package/dist/packages/fragno/dist/api/request-output-context.js +119 -0
  87. package/dist/packages/fragno/dist/api/request-output-context.js.map +1 -0
  88. package/dist/packages/fragno/dist/api/route.js +17 -0
  89. package/dist/packages/fragno/dist/api/route.js.map +1 -0
  90. package/dist/packages/fragno/dist/internal/symbols.js +10 -0
  91. package/dist/packages/fragno/dist/internal/symbols.js.map +1 -0
  92. package/dist/query/cursor.d.ts +10 -2
  93. package/dist/query/cursor.d.ts.map +1 -1
  94. package/dist/query/cursor.js +11 -4
  95. package/dist/query/cursor.js.map +1 -1
  96. package/dist/query/execute-unit-of-work.d.ts +123 -0
  97. package/dist/query/execute-unit-of-work.d.ts.map +1 -0
  98. package/dist/query/execute-unit-of-work.js +184 -0
  99. package/dist/query/execute-unit-of-work.js.map +1 -0
  100. package/dist/query/query.d.ts +3 -3
  101. package/dist/query/query.d.ts.map +1 -1
  102. package/dist/query/result-transform.js +4 -2
  103. package/dist/query/result-transform.js.map +1 -1
  104. package/dist/query/retry-policy.d.ts +88 -0
  105. package/dist/query/retry-policy.d.ts.map +1 -0
  106. package/dist/query/retry-policy.js +61 -0
  107. package/dist/query/retry-policy.js.map +1 -0
  108. package/dist/query/unit-of-work.d.ts +171 -32
  109. package/dist/query/unit-of-work.d.ts.map +1 -1
  110. package/dist/query/unit-of-work.js +530 -133
  111. package/dist/query/unit-of-work.js.map +1 -1
  112. package/dist/schema/serialize.js +12 -7
  113. package/dist/schema/serialize.js.map +1 -1
  114. package/dist/with-database.d.ts +28 -0
  115. package/dist/with-database.d.ts.map +1 -0
  116. package/dist/with-database.js +34 -0
  117. package/dist/with-database.js.map +1 -0
  118. package/package.json +10 -3
  119. package/src/adapters/adapters.ts +30 -0
  120. package/src/adapters/drizzle/drizzle-adapter-pglite.test.ts +86 -17
  121. package/src/adapters/drizzle/drizzle-adapter-sqlite.test.ts +291 -7
  122. package/src/adapters/drizzle/drizzle-adapter.test.ts +3 -51
  123. package/src/adapters/drizzle/drizzle-adapter.ts +35 -7
  124. package/src/adapters/drizzle/drizzle-query.ts +25 -15
  125. package/src/adapters/drizzle/drizzle-uow-compiler-mysql.test.ts +1442 -0
  126. package/src/adapters/drizzle/drizzle-uow-compiler-sqlite.test.ts +1414 -0
  127. package/src/adapters/drizzle/drizzle-uow-compiler.test.ts +78 -61
  128. package/src/adapters/drizzle/drizzle-uow-compiler.ts +123 -42
  129. package/src/adapters/drizzle/drizzle-uow-decoder.ts +34 -27
  130. package/src/adapters/drizzle/drizzle-uow-executor.ts +41 -8
  131. package/src/adapters/drizzle/generate.test.ts +102 -269
  132. package/src/adapters/drizzle/generate.ts +12 -30
  133. package/src/adapters/drizzle/test-utils.ts +36 -5
  134. package/src/adapters/kysely/kysely-adapter-pglite.test.ts +66 -22
  135. package/src/adapters/kysely/kysely-adapter-sqlite.test.ts +156 -0
  136. package/src/adapters/kysely/kysely-adapter.ts +25 -2
  137. package/src/adapters/kysely/kysely-query-compiler.ts +3 -8
  138. package/src/adapters/kysely/kysely-query.ts +57 -37
  139. package/src/adapters/kysely/kysely-shared.ts +34 -0
  140. package/src/adapters/kysely/kysely-uow-compiler.test.ts +62 -74
  141. package/src/adapters/kysely/kysely-uow-compiler.ts +92 -24
  142. package/src/adapters/kysely/kysely-uow-executor.ts +26 -7
  143. package/src/adapters/kysely/kysely-uow-joins.test.ts +33 -50
  144. package/src/adapters/kysely/migration/execute-base.ts +1 -1
  145. package/src/db-fragment-definition-builder.test.ts +887 -0
  146. package/src/db-fragment-definition-builder.ts +506 -0
  147. package/src/db-fragment-instantiator.test.ts +467 -0
  148. package/src/db-fragment-integration.test.ts +408 -0
  149. package/src/fragments/internal-fragment.test.ts +160 -0
  150. package/src/fragments/internal-fragment.ts +85 -0
  151. package/src/migration-engine/generation-engine.test.ts +58 -15
  152. package/src/migration-engine/generation-engine.ts +78 -25
  153. package/src/mod.ts +35 -43
  154. package/src/query/cursor.test.ts +119 -0
  155. package/src/query/cursor.ts +17 -4
  156. package/src/query/execute-unit-of-work.test.ts +1310 -0
  157. package/src/query/execute-unit-of-work.ts +463 -0
  158. package/src/query/query.ts +4 -4
  159. package/src/query/result-transform.test.ts +129 -0
  160. package/src/query/result-transform.ts +4 -1
  161. package/src/query/retry-policy.test.ts +217 -0
  162. package/src/query/retry-policy.ts +141 -0
  163. package/src/query/unit-of-work-coordinator.test.ts +833 -0
  164. package/src/query/unit-of-work-types.test.ts +15 -2
  165. package/src/query/unit-of-work.test.ts +878 -200
  166. package/src/query/unit-of-work.ts +963 -321
  167. package/src/schema/serialize.ts +22 -11
  168. package/src/with-database.ts +140 -0
  169. package/tsdown.config.ts +1 -0
  170. package/dist/fragment.d.ts +0 -54
  171. package/dist/fragment.d.ts.map +0 -1
  172. package/dist/fragment.js +0 -92
  173. package/dist/fragment.js.map +0 -1
  174. package/dist/shared/settings-schema.js +0 -36
  175. package/dist/shared/settings-schema.js.map +0 -1
  176. package/src/fragment.test.ts +0 -341
  177. package/src/fragment.ts +0 -198
  178. package/src/shared/settings-schema.ts +0 -61
@@ -0,0 +1,320 @@
1
+ //#region ../fragno/dist/api/fragment-definition-builder.js
2
+ /**
3
+ * Builder class for creating fragment definitions.
4
+ * This provides a fluent API for defining fragments with type safety.
5
+ */
6
+ var FragmentDefinitionBuilder = class FragmentDefinitionBuilder$1 {
7
+ #name;
8
+ #dependencies;
9
+ #baseServices;
10
+ #namedServices;
11
+ #privateServices;
12
+ #serviceDependencies;
13
+ #createRequestStorage;
14
+ #createThisContext;
15
+ #getExternalStorage;
16
+ #linkedFragments;
17
+ constructor(name, state) {
18
+ this.#name = name;
19
+ if (state) {
20
+ this.#dependencies = state.dependencies;
21
+ this.#baseServices = state.baseServices;
22
+ this.#namedServices = state.namedServices;
23
+ this.#privateServices = state.privateServices;
24
+ this.#serviceDependencies = state.serviceDependencies;
25
+ this.#createRequestStorage = state.createRequestStorage;
26
+ this.#createThisContext = state.createThisContext;
27
+ this.#getExternalStorage = state.getExternalStorage;
28
+ this.#linkedFragments = state.linkedFragments;
29
+ }
30
+ }
31
+ get name() {
32
+ return this.#name;
33
+ }
34
+ /**
35
+ * Define dependencies for this fragment.
36
+ * Dependencies are available to services and handlers.
37
+ *
38
+ * **IMPORTANT**: This method resets all services, storage, and context configurations.
39
+ * Always call `withDependencies` early in the builder chain, before defining services
40
+ * or request storage/context.
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * // ✅ GOOD: Dependencies set first
45
+ * defineFragment("my-fragment")
46
+ * .withDependencies(() => ({ apiKey: "..." }))
47
+ * .withRequestStorage(({ deps }) => ({ userId: deps.apiKey }))
48
+ * .providesService("myService", ...)
49
+ *
50
+ * // ❌ BAD: Dependencies set late (erases storage setup)
51
+ * defineFragment("my-fragment")
52
+ * .withRequestStorage(() => ({ userId: "..." })) // This gets erased!
53
+ * .withDependencies(() => ({ apiKey: "..." }))
54
+ * ```
55
+ */
56
+ withDependencies(fn) {
57
+ if (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.`);
58
+ return new FragmentDefinitionBuilder$1(this.#name, {
59
+ dependencies: fn,
60
+ baseServices: void 0,
61
+ namedServices: void 0,
62
+ privateServices: void 0,
63
+ serviceDependencies: this.#serviceDependencies,
64
+ createRequestStorage: void 0,
65
+ createThisContext: void 0,
66
+ getExternalStorage: void 0,
67
+ linkedFragments: this.#linkedFragments
68
+ });
69
+ }
70
+ /**
71
+ * Define base (unnamed) services for this fragment.
72
+ * Base services are accessible directly on the fragment instance.
73
+ */
74
+ providesBaseService(fn) {
75
+ return new FragmentDefinitionBuilder$1(this.#name, {
76
+ dependencies: this.#dependencies,
77
+ baseServices: fn,
78
+ namedServices: this.#namedServices,
79
+ privateServices: this.#privateServices,
80
+ serviceDependencies: this.#serviceDependencies,
81
+ createRequestStorage: this.#createRequestStorage,
82
+ createThisContext: this.#createThisContext,
83
+ getExternalStorage: this.#getExternalStorage,
84
+ linkedFragments: this.#linkedFragments
85
+ });
86
+ }
87
+ /**
88
+ * Provide a named service that other fragments or users can use.
89
+ * Named services are accessible as fragment.serviceName.method()
90
+ */
91
+ providesService(serviceName, fn) {
92
+ const newNamedServices = {
93
+ ...this.#namedServices,
94
+ [serviceName]: fn
95
+ };
96
+ return new FragmentDefinitionBuilder$1(this.#name, {
97
+ dependencies: this.#dependencies,
98
+ baseServices: this.#baseServices,
99
+ namedServices: newNamedServices,
100
+ privateServices: this.#privateServices,
101
+ serviceDependencies: this.#serviceDependencies,
102
+ createRequestStorage: this.#createRequestStorage,
103
+ createThisContext: this.#createThisContext,
104
+ getExternalStorage: this.#getExternalStorage,
105
+ linkedFragments: this.#linkedFragments
106
+ });
107
+ }
108
+ /**
109
+ * Provide a private service that is only accessible to the fragment author.
110
+ * Private services are NOT exposed on the fragment instance, but can be used
111
+ * when defining other services (baseServices, namedServices, and other privateServices).
112
+ * Private services are instantiated in order, so earlier private services are available
113
+ * to later ones.
114
+ */
115
+ providesPrivateService(serviceName, fn) {
116
+ const newPrivateServices = {
117
+ ...this.#privateServices,
118
+ [serviceName]: fn
119
+ };
120
+ return new FragmentDefinitionBuilder$1(this.#name, {
121
+ dependencies: this.#dependencies,
122
+ baseServices: this.#baseServices,
123
+ namedServices: this.#namedServices,
124
+ privateServices: newPrivateServices,
125
+ serviceDependencies: this.#serviceDependencies,
126
+ createRequestStorage: this.#createRequestStorage,
127
+ createThisContext: this.#createThisContext,
128
+ linkedFragments: this.#linkedFragments
129
+ });
130
+ }
131
+ /**
132
+ * Declare that this fragment uses a required service provided by the runtime.
133
+ */
134
+ usesService(serviceName) {
135
+ const newServiceDependencies = {
136
+ ...this.#serviceDependencies,
137
+ [serviceName]: {
138
+ name: serviceName,
139
+ required: true
140
+ }
141
+ };
142
+ return new FragmentDefinitionBuilder$1(this.#name, {
143
+ dependencies: this.#dependencies,
144
+ baseServices: this.#baseServices,
145
+ namedServices: this.#namedServices,
146
+ privateServices: this.#privateServices,
147
+ serviceDependencies: newServiceDependencies,
148
+ createRequestStorage: this.#createRequestStorage,
149
+ createThisContext: this.#createThisContext,
150
+ linkedFragments: this.#linkedFragments
151
+ });
152
+ }
153
+ /**
154
+ * Declare that this fragment uses an optional service provided by the runtime.
155
+ */
156
+ usesOptionalService(serviceName) {
157
+ const newServiceDependencies = {
158
+ ...this.#serviceDependencies,
159
+ [serviceName]: {
160
+ name: serviceName,
161
+ required: false
162
+ }
163
+ };
164
+ return new FragmentDefinitionBuilder$1(this.#name, {
165
+ dependencies: this.#dependencies,
166
+ baseServices: this.#baseServices,
167
+ namedServices: this.#namedServices,
168
+ privateServices: this.#privateServices,
169
+ serviceDependencies: newServiceDependencies,
170
+ createRequestStorage: this.#createRequestStorage,
171
+ createThisContext: this.#createThisContext,
172
+ linkedFragments: this.#linkedFragments
173
+ });
174
+ }
175
+ /**
176
+ * Define the type and initial data stored in AsyncLocalStorage for per-request isolation.
177
+ * This should be called before withThisContext if you need to store request-specific data.
178
+ *
179
+ * @param initializer Function that returns the initial storage data for each request
180
+ *
181
+ * @example
182
+ * ```typescript
183
+ * .withRequestStorage(({ config, options, deps }) => ({
184
+ * counter: 0,
185
+ * userId: deps.currentUserId
186
+ * }))
187
+ * .withThisContext(({ storage }) => ({
188
+ * serviceContext: {
189
+ * get counter() { return storage.getStore()!.counter; }
190
+ * },
191
+ * handlerContext: {
192
+ * get counter() { return storage.getStore()!.counter; }
193
+ * }
194
+ * }))
195
+ * ```
196
+ */
197
+ withRequestStorage(initializer) {
198
+ const preservedExternalStorage = this.#getExternalStorage ? this.#getExternalStorage : void 0;
199
+ return new FragmentDefinitionBuilder$1(this.#name, {
200
+ dependencies: this.#dependencies,
201
+ baseServices: this.#baseServices,
202
+ namedServices: this.#namedServices,
203
+ privateServices: this.#privateServices,
204
+ serviceDependencies: this.#serviceDependencies,
205
+ createRequestStorage: initializer,
206
+ createThisContext: void 0,
207
+ getExternalStorage: preservedExternalStorage,
208
+ linkedFragments: this.#linkedFragments
209
+ });
210
+ }
211
+ /**
212
+ * Use an externally-provided RequestContextStorage instance.
213
+ * This allows multiple fragments to share the same storage instance.
214
+ * Useful when fragments need to coordinate (e.g., database fragments sharing adapter storage).
215
+ * Note: You must still call withRequestStorage to provide the initial storage data.
216
+ *
217
+ * @example
218
+ * ```typescript
219
+ * .withExternalRequestStorage(({ options }) =>
220
+ * options.databaseAdapter.contextStorage
221
+ * )
222
+ * .withRequestStorage(({ options }) => ({
223
+ * uow: options.databaseAdapter.db.createUnitOfWork()
224
+ * }))
225
+ * ```
226
+ */
227
+ withExternalRequestStorage(getStorage) {
228
+ return new FragmentDefinitionBuilder$1(this.#name, {
229
+ dependencies: this.#dependencies,
230
+ baseServices: this.#baseServices,
231
+ namedServices: this.#namedServices,
232
+ privateServices: this.#privateServices,
233
+ serviceDependencies: this.#serviceDependencies,
234
+ createRequestStorage: void 0,
235
+ createThisContext: void 0,
236
+ getExternalStorage: getStorage,
237
+ linkedFragments: this.#linkedFragments
238
+ });
239
+ }
240
+ /**
241
+ * Set the this contexts for services and handlers in this fragment.
242
+ * Both contexts should contain only methods or getters that read from storage.
243
+ * This ensures proper per-request isolation via AsyncLocalStorage.
244
+ *
245
+ * @example
246
+ * ```ts
247
+ * .withThisContext(({ storage }) => ({
248
+ * serviceContext: {
249
+ * get myNumber() { return storage.getStore()?.myNumber ?? 0; }
250
+ * },
251
+ * handlerContext: {
252
+ * get myNumber() { return storage.getStore()?.myNumber ?? 0; }
253
+ * }
254
+ * }))
255
+ * ```
256
+ */
257
+ withThisContext(fn) {
258
+ return new FragmentDefinitionBuilder$1(this.#name, {
259
+ dependencies: this.#dependencies,
260
+ baseServices: this.#baseServices,
261
+ namedServices: this.#namedServices,
262
+ privateServices: this.#privateServices,
263
+ serviceDependencies: this.#serviceDependencies,
264
+ createRequestStorage: this.#createRequestStorage,
265
+ createThisContext: fn,
266
+ getExternalStorage: this.#getExternalStorage,
267
+ linkedFragments: this.#linkedFragments
268
+ });
269
+ }
270
+ /**
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.
274
+ */
275
+ withLinkedFragment(name, callback) {
276
+ const newLinkedFragments = {
277
+ ...this.#linkedFragments,
278
+ [name]: callback
279
+ };
280
+ return new FragmentDefinitionBuilder$1(this.#name, {
281
+ dependencies: this.#dependencies,
282
+ baseServices: this.#baseServices,
283
+ namedServices: this.#namedServices,
284
+ privateServices: this.#privateServices,
285
+ serviceDependencies: this.#serviceDependencies,
286
+ createRequestStorage: this.#createRequestStorage,
287
+ createThisContext: this.#createThisContext,
288
+ getExternalStorage: this.#getExternalStorage,
289
+ linkedFragments: newLinkedFragments
290
+ });
291
+ }
292
+ /**
293
+ * Extend this builder with a transformation function.
294
+ * This enables fluent API extensions like `.extend(withDatabase(schema))`.
295
+ */
296
+ extend(transformer) {
297
+ return transformer(this);
298
+ }
299
+ /**
300
+ * Build the final fragment definition
301
+ */
302
+ build() {
303
+ return {
304
+ name: this.#name,
305
+ dependencies: this.#dependencies,
306
+ baseServices: this.#baseServices,
307
+ namedServices: this.#namedServices,
308
+ privateServices: this.#privateServices,
309
+ serviceDependencies: this.#serviceDependencies,
310
+ createRequestStorage: this.#createRequestStorage,
311
+ createThisContext: this.#createThisContext,
312
+ getExternalStorage: this.#getExternalStorage,
313
+ linkedFragments: this.#linkedFragments
314
+ };
315
+ }
316
+ };
317
+
318
+ //#endregion
319
+ export { FragmentDefinitionBuilder };
320
+ //# sourceMappingURL=fragment-definition-builder.js.map
@@ -0,0 +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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"}