@fragno-dev/test 2.0.0 → 2.0.2

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 (59) hide show
  1. package/.turbo/turbo-build.log +41 -31
  2. package/CHANGELOG.md +69 -0
  3. package/dist/adapters.d.ts +4 -7
  4. package/dist/adapters.d.ts.map +1 -1
  5. package/dist/adapters.js +18 -302
  6. package/dist/adapters.js.map +1 -1
  7. package/dist/db-test.d.ts +120 -18
  8. package/dist/db-test.d.ts.map +1 -1
  9. package/dist/db-test.js +203 -55
  10. package/dist/db-test.js.map +1 -1
  11. package/dist/durable-hooks.d.ts +6 -2
  12. package/dist/durable-hooks.d.ts.map +1 -1
  13. package/dist/durable-hooks.js +10 -5
  14. package/dist/durable-hooks.js.map +1 -1
  15. package/dist/index.d.ts +3 -3
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +1 -1
  18. package/dist/index.js.map +1 -1
  19. package/dist/model-checker-actors.d.ts.map +1 -1
  20. package/dist/model-checker-actors.js +1 -1
  21. package/dist/model-checker-actors.js.map +1 -1
  22. package/dist/model-checker-adapter.d.ts +1 -1
  23. package/dist/model-checker-adapter.d.ts.map +1 -1
  24. package/dist/model-checker-adapter.js.map +1 -1
  25. package/dist/model-checker.d.ts.map +1 -1
  26. package/dist/model-checker.js.map +1 -1
  27. package/dist/test-adapters/drizzle-pglite.js +116 -0
  28. package/dist/test-adapters/drizzle-pglite.js.map +1 -0
  29. package/dist/test-adapters/in-memory.js +39 -0
  30. package/dist/test-adapters/in-memory.js.map +1 -0
  31. package/dist/test-adapters/kysely-pglite.js +105 -0
  32. package/dist/test-adapters/kysely-pglite.js.map +1 -0
  33. package/dist/test-adapters/kysely-sqlite.js +87 -0
  34. package/dist/test-adapters/kysely-sqlite.js.map +1 -0
  35. package/dist/test-adapters/model-checker.js +41 -0
  36. package/dist/test-adapters/model-checker.js.map +1 -0
  37. package/dist/tsconfig.tsbuildinfo +1 -0
  38. package/package.json +32 -33
  39. package/src/adapter-conformance.test.ts +3 -1
  40. package/src/adapters.ts +24 -455
  41. package/src/db-roundtrip-guard.test.ts +206 -0
  42. package/src/db-test.test.ts +131 -77
  43. package/src/db-test.ts +530 -96
  44. package/src/durable-hooks.test.ts +58 -0
  45. package/src/durable-hooks.ts +23 -8
  46. package/src/index.test.ts +188 -104
  47. package/src/index.ts +6 -2
  48. package/src/model-checker-actors.test.ts +5 -2
  49. package/src/model-checker-actors.ts +2 -1
  50. package/src/model-checker-adapter.ts +3 -2
  51. package/src/model-checker.test.ts +4 -1
  52. package/src/model-checker.ts +4 -3
  53. package/src/test-adapters/drizzle-pglite.ts +162 -0
  54. package/src/test-adapters/in-memory.ts +56 -0
  55. package/src/test-adapters/kysely-pglite.ts +151 -0
  56. package/src/test-adapters/kysely-sqlite.ts +119 -0
  57. package/src/test-adapters/model-checker.ts +58 -0
  58. package/tsconfig.json +1 -1
  59. package/vitest.config.ts +1 -0
package/dist/db-test.d.ts CHANGED
@@ -1,24 +1,102 @@
1
1
  import { AdapterContext, SupportedAdapter } from "./adapters.js";
2
2
  import { BaseTestContext } from "./index.js";
3
- import { DatabaseAdapter } from "@fragno-dev/db";
3
+ import { DatabaseAdapter, FragnoPublicConfigWithDatabase } from "@fragno-dev/db";
4
4
  import { AnySchema } from "@fragno-dev/db/schema";
5
5
  import { SimpleQueryInterface } from "@fragno-dev/db/query";
6
- import { FragmentInstantiationBuilder, FragnoInstantiatedFragment, FragnoPublicConfig, RequestThisContext } from "@fragno-dev/core";
7
6
  import { AnyRouteOrFactory, FlattenRouteFactories } from "@fragno-dev/core/route";
7
+ import { FragmentDefinition, FragmentInstantiationBuilder, FragnoInstantiatedFragment, FragnoPublicConfig, RequestThisContext } from "@fragno-dev/core";
8
8
 
9
9
  //#region src/db-test.d.ts
10
10
  type BoundServices<T> = { [K in keyof T]: T[K] extends ((this: any, ...args: infer A) => infer R) ? (...args: A) => R : T[K] extends Record<string, unknown> ? BoundServices<T[K]> : T[K] };
11
- type ExtractSchemaFromDeps<TDeps> = TDeps extends {
11
+ type FragmentFactoryContext = {
12
+ adapter: DatabaseAdapter<any>;
13
+ test: BaseTestContext & AdapterContext<SupportedAdapter>;
14
+ };
15
+ type FragmentFactoryResult = FragmentInstantiationBuilder<any,
16
+ // eslint-disable-line @typescript-eslint/no-explicit-any
17
+ any,
18
+ // eslint-disable-line @typescript-eslint/no-explicit-any
19
+ any,
20
+ // eslint-disable-line @typescript-eslint/no-explicit-any
21
+ any,
22
+ // eslint-disable-line @typescript-eslint/no-explicit-any
23
+ any,
24
+ // eslint-disable-line @typescript-eslint/no-explicit-any
25
+ any,
26
+ // eslint-disable-line @typescript-eslint/no-explicit-any
27
+ any,
28
+ // eslint-disable-line @typescript-eslint/no-explicit-any
29
+ any,
30
+ // eslint-disable-line @typescript-eslint/no-explicit-any
31
+ any,
32
+ // eslint-disable-line @typescript-eslint/no-explicit-any
33
+ any,
34
+ // eslint-disable-line @typescript-eslint/no-explicit-any
35
+ any,
36
+ // eslint-disable-line @typescript-eslint/no-explicit-any
37
+ any> | FragnoInstantiatedFragment<any,
38
+ // eslint-disable-line @typescript-eslint/no-explicit-any
39
+ any,
40
+ // eslint-disable-line @typescript-eslint/no-explicit-any
41
+ any,
42
+ // eslint-disable-line @typescript-eslint/no-explicit-any
43
+ any,
44
+ // eslint-disable-line @typescript-eslint/no-explicit-any
45
+ any,
46
+ // eslint-disable-line @typescript-eslint/no-explicit-any
47
+ any,
48
+ // eslint-disable-line @typescript-eslint/no-explicit-any
49
+ any>;
50
+ type HandlerThisContextFromFactoryResult<T> = T extends FragmentInstantiationBuilder<any,
51
+ // eslint-disable-line @typescript-eslint/no-explicit-any
52
+ any,
53
+ // eslint-disable-line @typescript-eslint/no-explicit-any
54
+ any,
55
+ // eslint-disable-line @typescript-eslint/no-explicit-any
56
+ any,
57
+ // eslint-disable-line @typescript-eslint/no-explicit-any
58
+ any,
59
+ // eslint-disable-line @typescript-eslint/no-explicit-any
60
+ any,
61
+ // eslint-disable-line @typescript-eslint/no-explicit-any
62
+ any,
63
+ // eslint-disable-line @typescript-eslint/no-explicit-any
64
+ any,
65
+ // eslint-disable-line @typescript-eslint/no-explicit-any
66
+ infer THandlerThisContext, any,
67
+ // eslint-disable-line @typescript-eslint/no-explicit-any
68
+ any,
69
+ // eslint-disable-line @typescript-eslint/no-explicit-any
70
+ any> ? THandlerThisContext : T extends FragnoInstantiatedFragment<any,
71
+ // eslint-disable-line @typescript-eslint/no-explicit-any
72
+ any,
73
+ // eslint-disable-line @typescript-eslint/no-explicit-any
74
+ any,
75
+ // eslint-disable-line @typescript-eslint/no-explicit-any
76
+ any,
77
+ // eslint-disable-line @typescript-eslint/no-explicit-any
78
+ infer THandlerThisContext, any,
79
+ // eslint-disable-line @typescript-eslint/no-explicit-any
80
+ any> ? THandlerThisContext : RequestThisContext;
81
+ type FragmentResultFromFactoryResult<T> = T extends FragmentInstantiationBuilder<any,
82
+ // eslint-disable-line @typescript-eslint/no-explicit-any
83
+ any,
84
+ // eslint-disable-line @typescript-eslint/no-explicit-any
85
+ infer TDeps, infer TBaseServices, infer TServices, any,
86
+ // eslint-disable-line @typescript-eslint/no-explicit-any
87
+ any,
88
+ // eslint-disable-line @typescript-eslint/no-explicit-any
89
+ infer TServiceThisContext, infer THandlerThisContext, infer TRequestStorage, infer TRoutesOrFactories, any> ? FragmentResult<TDeps, BoundServices<TBaseServices & TServices>, TServiceThisContext, THandlerThisContext, TRequestStorage, FlattenRouteFactories<TRoutesOrFactories>, ExtractSchemaFromDeps<TDeps>> : T extends FragnoInstantiatedFragment<infer TRoutes, infer TDeps, infer TServices, infer TServiceThisContext, infer THandlerThisContext, infer TRequestStorage, any> ? FragmentResult<TDeps, BoundServices<TServices>, TServiceThisContext, THandlerThisContext, TRequestStorage, TRoutes, ExtractSchemaFromDeps<TDeps>> : never;
90
+ type ExtractSchemaFromDeps<TDeps$1> = TDeps$1 extends {
12
91
  schema: infer TSchema extends AnySchema;
13
92
  } ? TSchema : AnySchema;
14
- type AnyLinkedFragments = Record<string, any>;
15
- interface FragmentResult<TDeps, TServices extends Record<string, unknown>, TServiceThisContext extends RequestThisContext, THandlerThisContext extends RequestThisContext, TRequestStorage, TRoutes extends readonly any[],
16
- // eslint-disable-line @typescript-eslint/no-explicit-any
17
- TSchema$1 extends AnySchema, TLinkedFragments extends AnyLinkedFragments = {}> {
18
- fragment: FragnoInstantiatedFragment<TRoutes, TDeps, TServices, TServiceThisContext, THandlerThisContext, TRequestStorage, FragnoPublicConfig, TLinkedFragments>;
19
- services: TServices;
20
- deps: TDeps;
21
- callRoute: FragnoInstantiatedFragment<TRoutes, TDeps, TServices, TServiceThisContext, THandlerThisContext, TRequestStorage, FragnoPublicConfig, TLinkedFragments>["callRoute"];
93
+ interface FragmentResult<TDeps$1, TServices$1 extends Record<string, unknown>, TServiceThisContext$1 extends RequestThisContext, THandlerThisContext$1 extends RequestThisContext, TRequestStorage$1, TRoutes$1 extends readonly any[],
94
+ // eslint-disable-line @typescript-eslint/no-explicit-any
95
+ TSchema$1 extends AnySchema> {
96
+ fragment: FragnoInstantiatedFragment<TRoutes$1, TDeps$1, TServices$1, TServiceThisContext$1, THandlerThisContext$1, TRequestStorage$1, FragnoPublicConfig>;
97
+ services: TServices$1;
98
+ deps: TDeps$1;
99
+ callRoute: FragnoInstantiatedFragment<TRoutes$1, TDeps$1, TServices$1, TServiceThisContext$1, THandlerThisContext$1, TRequestStorage$1, FragnoPublicConfig>["callRoute"];
22
100
  db: SimpleQueryInterface<TSchema$1>;
23
101
  }
24
102
  type AnyFragmentResult = FragmentResult<any,
@@ -33,8 +111,6 @@ any,
33
111
  // eslint-disable-line @typescript-eslint/no-explicit-any
34
112
  any,
35
113
  // eslint-disable-line @typescript-eslint/no-explicit-any
36
- any,
37
- // eslint-disable-line @typescript-eslint/no-explicit-any
38
114
  any>;
39
115
  /**
40
116
  * Test context combining base and adapter-specific functionality
@@ -64,6 +140,11 @@ declare class DatabaseFragmentsTestBuilder<TFragments extends Record<string, Any
64
140
  * Set the test adapter configuration
65
141
  */
66
142
  withTestAdapter<TNewAdapter extends SupportedAdapter>(adapter: TNewAdapter): DatabaseFragmentsTestBuilder<TFragments, TNewAdapter, TFirstFragmentThisContext>;
143
+ /**
144
+ * Opt out of the default roundtrip guard (enabled by default), or override its configuration.
145
+ * Useful for allowing multi-roundtrip routes in tests.
146
+ */
147
+ withDbRoundtripGuard(guard?: FragnoPublicConfigWithDatabase["dbRoundtripGuard"]): DatabaseFragmentsTestBuilder<TFragments, TAdapter, TFirstFragmentThisContext>;
67
148
  /**
68
149
  * Add a fragment to the test setup
69
150
  *
@@ -71,11 +152,32 @@ declare class DatabaseFragmentsTestBuilder<TFragments extends Record<string, Any
71
152
  * @param builder - Pre-configured instantiation builder
72
153
  * @param options - Additional options (optional)
73
154
  */
74
- withFragment<TName extends string, TConfig, TOptions extends FragnoPublicConfig, TDeps, TBaseServices extends Record<string, unknown>, TServices extends Record<string, unknown>, TServiceDependencies, TPrivateServices extends Record<string, unknown>, TServiceThisContext extends RequestThisContext, THandlerThisContext extends RequestThisContext, TRequestStorage, TRoutesOrFactories extends readonly AnyRouteOrFactory[], TLinkedFragments extends AnyLinkedFragments>(name: TName, builder: FragmentInstantiationBuilder<TConfig, TOptions, TDeps, TBaseServices, TServices, TServiceDependencies, TPrivateServices, TServiceThisContext, THandlerThisContext, TRequestStorage, TRoutesOrFactories, TLinkedFragments>, options?: {
155
+ withFragment<TName extends string, TConfig, TOptions extends FragnoPublicConfig, TDeps$1, TBaseServices$1 extends Record<string, unknown>, TServices$1 extends Record<string, unknown>, TServiceDependencies, TPrivateServices extends Record<string, unknown>, TServiceThisContext$1 extends RequestThisContext, THandlerThisContext$1 extends RequestThisContext, TRequestStorage$1, TRoutesOrFactories$1 extends readonly AnyRouteOrFactory[], TInternalRoutes extends readonly AnyRouteOrFactory[]>(name: TName, builder: FragmentInstantiationBuilder<TConfig, TOptions, TDeps$1, TBaseServices$1, TServices$1, TServiceDependencies, TPrivateServices, TServiceThisContext$1, THandlerThisContext$1, TRequestStorage$1, TRoutesOrFactories$1, TInternalRoutes>, options?: {
156
+ migrateToVersion?: number;
157
+ }): DatabaseFragmentsTestBuilder<TFragments & { [K in TName]: FragmentResult<TDeps$1, BoundServices<TBaseServices$1 & TServices$1>, TServiceThisContext$1, THandlerThisContext$1, TRequestStorage$1, FlattenRouteFactories<TRoutesOrFactories$1>, ExtractSchemaFromDeps<TDeps$1>> }, TAdapter, keyof TFragments extends never ? THandlerThisContext$1 : TFirstFragmentThisContext>;
158
+ /**
159
+ * Add a pre-built fragment instance to the test setup
160
+ *
161
+ * @param name - Unique name for the fragment
162
+ * @param fragment - Already-built fragment instance
163
+ */
164
+ withFragmentInstance<TName extends string, TRoutes$1 extends readonly any[],
165
+ // eslint-disable-line @typescript-eslint/no-explicit-any
166
+ TDeps$1, TServices$1 extends Record<string, unknown>, TServiceThisContext$1 extends RequestThisContext, THandlerThisContext$1 extends RequestThisContext, TRequestStorage$1>(name: TName, fragment: FragnoInstantiatedFragment<TRoutes$1, TDeps$1, TServices$1, TServiceThisContext$1, THandlerThisContext$1, TRequestStorage$1, FragnoPublicConfig>, options?: {
167
+ migrateToVersion?: number;
168
+ }): DatabaseFragmentsTestBuilder<TFragments & { [K in TName]: FragmentResult<TDeps$1, BoundServices<TServices$1>, TServiceThisContext$1, THandlerThisContext$1, TRequestStorage$1, TRoutes$1, ExtractSchemaFromDeps<TDeps$1>> }, TAdapter, keyof TFragments extends never ? THandlerThisContext$1 : TFirstFragmentThisContext>;
169
+ /**
170
+ * Add a fragment factory to the test setup.
171
+ * The factory runs after the adapter is created.
172
+ *
173
+ * @param name - Unique name for the fragment
174
+ * @param definition - Fragment definition (used to extract schema/namespace)
175
+ * @param factory - Factory that returns a builder or a pre-built fragment
176
+ */
177
+ withFragmentFactory<TName extends string, TFactoryResult extends FragmentFactoryResult>(name: TName, definition: FragmentDefinition<any, any, any, any, any, any, any, any, any, any, any>, factory: (context: FragmentFactoryContext) => TFactoryResult, options?: {
75
178
  migrateToVersion?: number;
76
- }): DatabaseFragmentsTestBuilder<TFragments & { [K in TName]: FragmentResult<TDeps, BoundServices<TBaseServices & TServices>, TServiceThisContext, THandlerThisContext, TRequestStorage, FlattenRouteFactories<TRoutesOrFactories>, ExtractSchemaFromDeps<TDeps>,
77
- // Extract actual schema type from deps
78
- TLinkedFragments> }, TAdapter, keyof TFragments extends never ? THandlerThisContext : TFirstFragmentThisContext>;
179
+ config?: any;
180
+ }): DatabaseFragmentsTestBuilder<TFragments & { [K in TName]: FragmentResultFromFactoryResult<TFactoryResult> }, TAdapter, keyof TFragments extends never ? HandlerThisContextFromFactoryResult<TFactoryResult> : TFirstFragmentThisContext>;
79
181
  /**
80
182
  * Build the test setup and return fragments and test context
81
183
  */
@@ -125,5 +227,5 @@ declare class DatabaseFragmentsTestBuilder<TFragments extends Record<string, Any
125
227
  */
126
228
  declare function buildDatabaseFragmentsTest(): DatabaseFragmentsTestBuilder<{}, undefined, RequestThisContext>;
127
229
  //#endregion
128
- export { DatabaseFragmentsTestBuilder, buildDatabaseFragmentsTest };
230
+ export { AnyFragmentResult, DatabaseFragmentsTestBuilder, buildDatabaseFragmentsTest };
129
231
  //# sourceMappingURL=db-test.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"db-test.d.ts","names":[],"sources":["../src/db-test.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"db-test.d.ts","names":[],"sources":["../src/db-test.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/db-test.js CHANGED
@@ -2,12 +2,23 @@ import { createAdapter } from "./adapters.js";
2
2
  import { drainDurableHooks } from "./durable-hooks.js";
3
3
 
4
4
  //#region src/db-test.ts
5
+ const disableAutoSchedule = (options) => {
6
+ const durableHooks = options.durableHooks ?? {};
7
+ return {
8
+ ...options,
9
+ durableHooks: {
10
+ ...durableHooks,
11
+ autoSchedule: false
12
+ }
13
+ };
14
+ };
5
15
  /**
6
16
  * Builder for creating multiple database fragments for testing
7
17
  */
8
18
  var DatabaseFragmentsTestBuilder = class {
9
19
  #adapter;
10
20
  #fragments = /* @__PURE__ */ new Map();
21
+ #dbRoundtripGuard = true;
11
22
  /**
12
23
  * Set the test adapter configuration
13
24
  */
@@ -16,6 +27,14 @@ var DatabaseFragmentsTestBuilder = class {
16
27
  return this;
17
28
  }
18
29
  /**
30
+ * Opt out of the default roundtrip guard (enabled by default), or override its configuration.
31
+ * Useful for allowing multi-roundtrip routes in tests.
32
+ */
33
+ withDbRoundtripGuard(guard = false) {
34
+ this.#dbRoundtripGuard = guard;
35
+ return this;
36
+ }
37
+ /**
19
38
  * Add a fragment to the test setup
20
39
  *
21
40
  * @param name - Unique name for the fragment
@@ -24,6 +43,7 @@ var DatabaseFragmentsTestBuilder = class {
24
43
  */
25
44
  withFragment(name, builder, options) {
26
45
  this.#fragments.set(name, {
46
+ kind: "builder",
27
47
  definition: builder.definition,
28
48
  builder,
29
49
  migrateToVersion: options?.migrateToVersion
@@ -31,19 +51,49 @@ var DatabaseFragmentsTestBuilder = class {
31
51
  return this;
32
52
  }
33
53
  /**
54
+ * Add a pre-built fragment instance to the test setup
55
+ *
56
+ * @param name - Unique name for the fragment
57
+ * @param fragment - Already-built fragment instance
58
+ */
59
+ withFragmentInstance(name, fragment, options) {
60
+ this.#fragments.set(name, {
61
+ kind: "instance",
62
+ fragment,
63
+ migrateToVersion: options?.migrateToVersion
64
+ });
65
+ return this;
66
+ }
67
+ /**
68
+ * Add a fragment factory to the test setup.
69
+ * The factory runs after the adapter is created.
70
+ *
71
+ * @param name - Unique name for the fragment
72
+ * @param definition - Fragment definition (used to extract schema/namespace)
73
+ * @param factory - Factory that returns a builder or a pre-built fragment
74
+ */
75
+ withFragmentFactory(name, definition, factory, options) {
76
+ this.#fragments.set(name, {
77
+ kind: "factory",
78
+ definition,
79
+ factory,
80
+ config: options?.config,
81
+ migrateToVersion: options?.migrateToVersion
82
+ });
83
+ return this;
84
+ }
85
+ /**
34
86
  * Build the test setup and return fragments and test context
35
87
  */
36
88
  async build() {
37
89
  if (!this.#adapter) throw new Error("Test adapter must be set using withTestAdapter()");
38
- if (this.#fragments.size === 0) throw new Error("At least one fragment must be added using withFragment()");
90
+ if (this.#fragments.size === 0) throw new Error("At least one fragment must be added using withFragment(), withFragmentFactory(), or withFragmentInstance().");
39
91
  const adapterConfig = this.#adapter;
40
- const fragmentNames = Array.from(this.#fragments.keys());
41
- const fragmentConfigs = Array.from(this.#fragments.values());
92
+ const fragmentEntries = Array.from(this.#fragments.entries());
93
+ const fragmentNames = fragmentEntries.map(([name]) => name);
42
94
  const schemaConfigs = [];
43
- const builderConfigs = [];
44
- for (const fragmentConfig of fragmentConfigs) {
45
- const builder = fragmentConfig.builder;
46
- const definition = builder.definition;
95
+ const fragmentPlans = [];
96
+ const extractSchemaFromDefinition = (definition, actualConfig, actualOptions) => {
47
97
  let schema;
48
98
  let namespace;
49
99
  if (definition.dependencies) try {
@@ -62,10 +112,12 @@ var DatabaseFragmentsTestBuilder = class {
62
112
  contextStorage: { run: (_data, fn) => fn() },
63
113
  close: async () => {}
64
114
  };
65
- const actualConfig = builder.config ?? {};
66
115
  const deps = definition.dependencies({
67
- config: actualConfig,
68
- options: { databaseAdapter: mockAdapter }
116
+ config: actualConfig ?? {},
117
+ options: {
118
+ ...actualOptions,
119
+ databaseAdapter: mockAdapter
120
+ }
69
121
  });
70
122
  if (deps && typeof deps === "object" && "schema" in deps) {
71
123
  schema = deps.schema;
@@ -77,68 +129,164 @@ var DatabaseFragmentsTestBuilder = class {
77
129
  }
78
130
  if (!schema) throw new Error(`Fragment '${definition.name}' does not have a database schema. Make sure you're using defineFragment().extend(withDatabase(schema)).`);
79
131
  if (namespace === void 0) throw new Error(`Fragment '${definition.name}' does not have a namespace in dependencies. This should be automatically provided by withDatabase().`);
80
- schemaConfigs.push({
132
+ return {
81
133
  schema,
82
- namespace,
134
+ namespace
135
+ };
136
+ };
137
+ for (const [name, fragmentConfig] of fragmentEntries) {
138
+ if (fragmentConfig.kind === "builder") {
139
+ const builder = fragmentConfig.builder;
140
+ const definition = builder.definition;
141
+ const { schema, namespace } = extractSchemaFromDefinition(definition, builder.config ?? {}, builder.options ?? {});
142
+ schemaConfigs.push({
143
+ schema,
144
+ namespace,
145
+ migrateToVersion: fragmentConfig.migrateToVersion
146
+ });
147
+ fragmentPlans.push({
148
+ name,
149
+ kind: "builder",
150
+ schema,
151
+ namespace,
152
+ migrateToVersion: fragmentConfig.migrateToVersion,
153
+ builderConfig: {
154
+ builder: fragmentConfig.builder,
155
+ definition: fragmentConfig.definition,
156
+ config: builder.config ?? {},
157
+ routes: builder.routes ?? [],
158
+ options: builder.options ?? {}
159
+ }
160
+ });
161
+ continue;
162
+ }
163
+ if (fragmentConfig.kind === "factory") {
164
+ const definition = fragmentConfig.definition;
165
+ const { schema, namespace } = extractSchemaFromDefinition(definition, fragmentConfig.config ?? {});
166
+ schemaConfigs.push({
167
+ schema,
168
+ namespace,
169
+ migrateToVersion: fragmentConfig.migrateToVersion
170
+ });
171
+ fragmentPlans.push({
172
+ name,
173
+ kind: "factory",
174
+ schema,
175
+ namespace,
176
+ migrateToVersion: fragmentConfig.migrateToVersion,
177
+ factory: fragmentConfig.factory
178
+ });
179
+ continue;
180
+ }
181
+ const fragment = fragmentConfig.fragment;
182
+ const deps = fragment.$internal?.deps;
183
+ if (!deps?.schema) throw new Error(`Fragment '${name}' does not have a database schema in deps. Make sure you're using defineFragment().extend(withDatabase(schema)).`);
184
+ schemaConfigs.push({
185
+ schema: deps.schema,
186
+ namespace: deps.namespace ?? null,
83
187
  migrateToVersion: fragmentConfig.migrateToVersion
84
188
  });
85
- builderConfigs.push({
86
- config: builder.config ?? {},
87
- routes: builder.routes ?? [],
88
- options: builder.options ?? {}
189
+ fragmentPlans.push({
190
+ name,
191
+ kind: "instance",
192
+ schema: deps.schema,
193
+ namespace: deps.namespace ?? null,
194
+ migrateToVersion: fragmentConfig.migrateToVersion,
195
+ fragment
89
196
  });
90
197
  }
91
198
  const { testContext, adapter } = await createAdapter(adapterConfig, schemaConfigs);
199
+ const resolveDbRoundtripGuardOption = (options) => {
200
+ if (options && typeof options === "object") {
201
+ if (Object.prototype.hasOwnProperty.call(options, "dbRoundtripGuard")) return options.dbRoundtripGuard;
202
+ }
203
+ return this.#dbRoundtripGuard;
204
+ };
205
+ const mergeBuilderOptions = (options) => {
206
+ const resolvedOptions = disableAutoSchedule(options ?? {});
207
+ const merged = {
208
+ ...resolvedOptions,
209
+ databaseAdapter: adapter
210
+ };
211
+ const guardOption = resolveDbRoundtripGuardOption(resolvedOptions);
212
+ if (guardOption !== void 0) merged["dbRoundtripGuard"] = guardOption;
213
+ return merged;
214
+ };
92
215
  const createFragments = () => {
216
+ const resolveBuilderConfig = (builder) => ({
217
+ builder,
218
+ definition: builder.definition,
219
+ config: builder.config ?? {},
220
+ routes: builder.routes ?? [],
221
+ options: builder.options ?? {}
222
+ });
223
+ const isBuilder = (value) => Boolean(value) && typeof value === "object" && "build" in value && "definition" in value;
93
224
  const providedServicesByName = {};
94
- const fragmentResults$1 = [];
95
- for (let i = 0; i < fragmentConfigs.length; i++) {
96
- const fragmentConfig = fragmentConfigs[i];
97
- const builderConfig = builderConfigs[i];
98
- const namespace = schemaConfigs[i].namespace;
99
- const schema = schemaConfigs[i].schema;
100
- const orm = testContext.getOrm(namespace);
101
- const mergedOptions = {
102
- ...builderConfig.options,
103
- databaseAdapter: adapter
104
- };
105
- const fragment = fragmentConfig.builder.withOptions(mergedOptions).build();
225
+ const instanceResults = /* @__PURE__ */ new Map();
226
+ const builderConfigs = /* @__PURE__ */ new Map();
227
+ for (const plan of fragmentPlans) {
228
+ const orm = testContext.getOrm(plan.namespace);
229
+ let fragment;
230
+ let builderConfig = plan.builderConfig;
231
+ if (plan.kind === "factory") {
232
+ const result = plan.cachedFactoryResult ?? plan.factory({
233
+ adapter,
234
+ test: testContext
235
+ });
236
+ if (!plan.cachedFactoryResult) plan.cachedFactoryResult = result;
237
+ if (isBuilder(result)) builderConfig = resolveBuilderConfig(result);
238
+ else fragment = result;
239
+ }
240
+ const usesBuilder = plan.kind === "builder" || !!builderConfig;
241
+ if (usesBuilder) {
242
+ const resolvedBuilderConfig = builderConfig ?? plan.builderConfig;
243
+ const mergedOptions = mergeBuilderOptions(resolvedBuilderConfig.options);
244
+ fragment = resolvedBuilderConfig.builder.withOptions(mergedOptions).build();
245
+ builderConfigs.set(plan.name, resolvedBuilderConfig);
246
+ } else {
247
+ fragment = fragment ?? plan.fragment;
248
+ const deps = fragment.$internal?.deps;
249
+ if (deps?.databaseAdapter && deps.databaseAdapter !== adapter) throw new Error(`Fragment '${plan.name}' was built with a different database adapter instance. Use withFragment() or ensure the fragment uses the same adapter instance as the test builder.`);
250
+ }
251
+ if (!fragment) throw new Error(`Fragment '${plan.name}' did not return a valid fragment instance from its factory.`);
106
252
  for (const [serviceName, serviceImpl] of Object.entries(fragment.services)) providedServicesByName[serviceName] = {
107
253
  service: serviceImpl,
108
254
  orm
109
255
  };
110
- const deps = fragment.$internal?.deps;
111
- fragmentResults$1.push({
112
- fragment,
113
- services: fragment.services,
114
- deps: deps || {},
115
- callRoute: fragment.callRoute.bind(fragment),
116
- get db() {
117
- return orm;
118
- },
119
- _orm: orm,
120
- _schema: schema
121
- });
256
+ if (!usesBuilder) {
257
+ const deps = fragment.$internal?.deps;
258
+ instanceResults.set(plan.name, {
259
+ fragment,
260
+ services: fragment.services,
261
+ deps: deps || {},
262
+ callRoute: fragment.callRoute.bind(fragment),
263
+ get db() {
264
+ return orm;
265
+ },
266
+ _orm: orm,
267
+ _schema: plan.schema
268
+ });
269
+ }
122
270
  }
123
- for (let i = 0; i < fragmentConfigs.length; i++) {
124
- const fragmentConfig = fragmentConfigs[i];
125
- const definition = fragmentConfig.builder.definition;
126
- const builderConfig = builderConfigs[i];
127
- const namespace = schemaConfigs[i].namespace;
128
- const schema = schemaConfigs[i].schema;
129
- const orm = testContext.getOrm(namespace);
271
+ const fragmentResults$1 = [];
272
+ for (const plan of fragmentPlans) {
273
+ const orm = testContext.getOrm(plan.namespace);
274
+ if (instanceResults.has(plan.name)) {
275
+ fragmentResults$1.push(instanceResults.get(plan.name));
276
+ continue;
277
+ }
278
+ const builderConfig = builderConfigs.get(plan.name);
279
+ if (!builderConfig) throw new Error(`Fragment '${plan.name}' was expected to produce a builder for service wiring.`);
280
+ const definition = builderConfig.definition;
130
281
  const serviceImplementations = {};
131
282
  const serviceDependencies = definition.serviceDependencies;
132
283
  if (serviceDependencies) {
133
284
  for (const serviceName of Object.keys(serviceDependencies)) if (providedServicesByName[serviceName]) serviceImplementations[serviceName] = providedServicesByName[serviceName].service;
134
285
  }
135
- const mergedOptions = {
136
- ...builderConfig.options,
137
- databaseAdapter: adapter
138
- };
139
- const fragment = fragmentConfig.builder.withOptions(mergedOptions).withServices(serviceImplementations).build();
286
+ const mergedOptions = mergeBuilderOptions(builderConfig.options);
287
+ const fragment = builderConfig.builder.withOptions(mergedOptions).withServices(serviceImplementations).build();
140
288
  const deps = fragment.$internal?.deps;
141
- fragmentResults$1[i] = {
289
+ fragmentResults$1.push({
142
290
  fragment,
143
291
  services: fragment.services,
144
292
  deps: deps || {},
@@ -147,8 +295,8 @@ var DatabaseFragmentsTestBuilder = class {
147
295
  return orm;
148
296
  },
149
297
  _orm: orm,
150
- _schema: schema
151
- };
298
+ _schema: plan.schema
299
+ });
152
300
  }
153
301
  return fragmentResults$1;
154
302
  };