@fragno-dev/core 0.1.7 → 0.1.9
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.
- package/.turbo/turbo-build.log +131 -64
- package/CHANGELOG.md +19 -0
- package/dist/api/api.d.ts +38 -2
- package/dist/api/api.d.ts.map +1 -0
- package/dist/api/api.js +9 -2
- package/dist/api/api.js.map +1 -0
- package/dist/api/bind-services.d.ts +6 -0
- package/dist/api/bind-services.d.ts.map +1 -0
- package/dist/api/bind-services.js +20 -0
- package/dist/api/bind-services.js.map +1 -0
- package/dist/api/error.d.ts +26 -0
- package/dist/api/error.d.ts.map +1 -0
- package/dist/{api-DngJDcmO.js → api/error.js} +2 -8
- package/dist/api/error.js.map +1 -0
- package/dist/api/fragment-definition-builder.d.ts +313 -0
- package/dist/api/fragment-definition-builder.d.ts.map +1 -0
- package/dist/api/fragment-definition-builder.js +326 -0
- package/dist/api/fragment-definition-builder.js.map +1 -0
- package/dist/api/fragment-instantiator.d.ts +216 -0
- package/dist/api/fragment-instantiator.d.ts.map +1 -0
- package/dist/api/fragment-instantiator.js +487 -0
- package/dist/api/fragment-instantiator.js.map +1 -0
- package/dist/api/fragno-response.d.ts +30 -0
- package/dist/api/fragno-response.d.ts.map +1 -0
- package/dist/api/fragno-response.js +73 -0
- package/dist/api/fragno-response.js.map +1 -0
- package/dist/api/internal/path.d.ts +50 -0
- package/dist/api/internal/path.d.ts.map +1 -0
- package/dist/api/internal/path.js +76 -0
- package/dist/api/internal/path.js.map +1 -0
- package/dist/api/internal/response-stream.d.ts +43 -0
- package/dist/api/internal/response-stream.d.ts.map +1 -0
- package/dist/api/internal/response-stream.js +81 -0
- package/dist/api/internal/response-stream.js.map +1 -0
- package/dist/api/internal/route.js +10 -0
- package/dist/api/internal/route.js.map +1 -0
- package/dist/api/mutable-request-state.d.ts +82 -0
- package/dist/api/mutable-request-state.d.ts.map +1 -0
- package/dist/api/mutable-request-state.js +97 -0
- package/dist/api/mutable-request-state.js.map +1 -0
- package/dist/api/request-context-storage.d.ts +42 -0
- package/dist/api/request-context-storage.d.ts.map +1 -0
- package/dist/api/request-context-storage.js +43 -0
- package/dist/api/request-context-storage.js.map +1 -0
- package/dist/api/request-input-context.d.ts +89 -0
- package/dist/api/request-input-context.d.ts.map +1 -0
- package/dist/api/request-input-context.js +118 -0
- package/dist/api/request-input-context.js.map +1 -0
- package/dist/api/request-middleware.d.ts +50 -0
- package/dist/api/request-middleware.d.ts.map +1 -0
- package/dist/api/request-middleware.js +83 -0
- package/dist/api/request-middleware.js.map +1 -0
- package/dist/api/request-output-context.d.ts +41 -0
- package/dist/api/request-output-context.d.ts.map +1 -0
- package/dist/api/request-output-context.js +119 -0
- package/dist/api/request-output-context.js.map +1 -0
- package/dist/api/route-handler-input-options.d.ts +21 -0
- package/dist/api/route-handler-input-options.d.ts.map +1 -0
- package/dist/api/route.d.ts +54 -3
- package/dist/api/route.d.ts.map +1 -0
- package/dist/api/route.js +29 -2
- package/dist/api/route.js.map +1 -0
- package/dist/api/shared-types.d.ts +47 -0
- package/dist/api/shared-types.d.ts.map +1 -0
- package/dist/api/shared-types.js +1 -0
- package/dist/client/client-error.d.ts +60 -0
- package/dist/client/client-error.d.ts.map +1 -0
- package/dist/client/client-error.js +92 -0
- package/dist/client/client-error.js.map +1 -0
- package/dist/client/client.d.ts +210 -4
- package/dist/client/client.d.ts.map +1 -0
- package/dist/client/client.js +397 -6
- package/dist/client/client.js.map +1 -0
- package/dist/client/client.svelte.d.ts +5 -3
- package/dist/client/client.svelte.d.ts.map +1 -1
- package/dist/client/client.svelte.js +1 -5
- package/dist/client/client.svelte.js.map +1 -1
- package/dist/client/internal/fetcher-merge.js +36 -0
- package/dist/client/internal/fetcher-merge.js.map +1 -0
- package/dist/client/internal/ndjson-streaming.js +139 -0
- package/dist/client/internal/ndjson-streaming.js.map +1 -0
- package/dist/client/react.d.ts +5 -3
- package/dist/client/react.d.ts.map +1 -1
- package/dist/client/react.js +3 -5
- package/dist/client/react.js.map +1 -1
- package/dist/client/solid.d.ts +5 -3
- package/dist/client/solid.d.ts.map +1 -1
- package/dist/client/solid.js +2 -5
- package/dist/client/solid.js.map +1 -1
- package/dist/client/vanilla.d.ts +5 -3
- package/dist/client/vanilla.d.ts.map +1 -1
- package/dist/client/vanilla.js +2 -43
- package/dist/client/vanilla.js.map +1 -1
- package/dist/client/vue.d.ts +5 -3
- package/dist/client/vue.d.ts.map +1 -1
- package/dist/client/vue.js +1 -5
- package/dist/client/vue.js.map +1 -1
- package/dist/http/http-status.d.ts +26 -0
- package/dist/http/http-status.d.ts.map +1 -0
- package/dist/integrations/react-ssr.js +1 -1
- package/dist/internal/symbols.d.ts +9 -0
- package/dist/internal/symbols.d.ts.map +1 -0
- package/dist/internal/symbols.js +10 -0
- package/dist/internal/symbols.js.map +1 -0
- package/dist/mod-client.d.ts +36 -0
- package/dist/mod-client.d.ts.map +1 -0
- package/dist/mod-client.js +21 -0
- package/dist/mod-client.js.map +1 -0
- package/dist/mod.d.ts +7 -4
- package/dist/mod.js +4 -6
- package/dist/request/request.d.ts +4 -0
- package/dist/request/request.js +5 -0
- package/dist/test/test.d.ts +62 -35
- package/dist/test/test.d.ts.map +1 -1
- package/dist/test/test.js +75 -40
- package/dist/test/test.js.map +1 -1
- package/dist/util/async.js +40 -0
- package/dist/util/async.js.map +1 -0
- package/dist/util/content-type.js +49 -0
- package/dist/util/content-type.js.map +1 -0
- package/dist/util/nanostores.js +31 -0
- package/dist/util/nanostores.js.map +1 -0
- package/dist/{ssr-BByDVfFD.js → util/ssr.js} +2 -2
- package/dist/util/ssr.js.map +1 -0
- package/dist/util/types-util.d.ts +8 -0
- package/dist/util/types-util.d.ts.map +1 -0
- package/package.json +19 -12
- package/src/api/api.ts +41 -6
- package/src/api/bind-services.ts +42 -0
- package/src/api/fragment-definition-builder.extend.test.ts +810 -0
- package/src/api/fragment-definition-builder.test.ts +499 -0
- package/src/api/fragment-definition-builder.ts +1088 -0
- package/src/api/fragment-instantiator.test.ts +1488 -0
- package/src/api/fragment-instantiator.ts +1053 -0
- package/src/api/fragment-services.test.ts +727 -0
- package/src/api/request-context-storage.ts +64 -0
- package/src/api/request-middleware.test.ts +301 -225
- package/src/api/route.test.ts +87 -1
- package/src/api/route.ts +345 -24
- package/src/api/shared-types.ts +43 -0
- package/src/client/client-builder.test.ts +23 -23
- package/src/client/client.ssr.test.ts +3 -3
- package/src/client/client.svelte.test.ts +15 -15
- package/src/client/client.test.ts +22 -22
- package/src/client/client.ts +72 -12
- package/src/client/internal/fetcher-merge.ts +1 -1
- package/src/client/react.test.ts +2 -2
- package/src/client/solid.test.ts +2 -2
- package/src/client/vanilla.test.ts +2 -2
- package/src/client/vue.test.ts +2 -2
- package/src/internal/symbols.ts +5 -0
- package/src/mod-client.ts +59 -0
- package/src/mod.ts +26 -9
- package/src/request/request.ts +8 -0
- package/src/test/test.test.ts +200 -381
- package/src/test/test.ts +190 -117
- package/tsdown.config.ts +8 -5
- package/dist/api/fragment-builder.d.ts +0 -4
- package/dist/api/fragment-builder.js +0 -3
- package/dist/api/fragment-instantiation.d.ts +0 -4
- package/dist/api/fragment-instantiation.js +0 -6
- package/dist/api-BWN97TOr.d.ts +0 -377
- package/dist/api-BWN97TOr.d.ts.map +0 -1
- package/dist/api-DngJDcmO.js.map +0 -1
- package/dist/client-C5LsYHEI.js +0 -782
- package/dist/client-C5LsYHEI.js.map +0 -1
- package/dist/fragment-builder-DOnCVBqc.js +0 -47
- package/dist/fragment-builder-DOnCVBqc.js.map +0 -1
- package/dist/fragment-builder-MGr68GNb.d.ts +0 -409
- package/dist/fragment-builder-MGr68GNb.d.ts.map +0 -1
- package/dist/fragment-instantiation-C4wvwl6V.js +0 -446
- package/dist/fragment-instantiation-C4wvwl6V.js.map +0 -1
- package/dist/request-output-context-CdIjwmEN.js +0 -320
- package/dist/request-output-context-CdIjwmEN.js.map +0 -1
- package/dist/route-Bl9Zr1Yv.d.ts +0 -26
- package/dist/route-Bl9Zr1Yv.d.ts.map +0 -1
- package/dist/route-C5Uryylh.js +0 -21
- package/dist/route-C5Uryylh.js.map +0 -1
- package/dist/ssr-BByDVfFD.js.map +0 -1
- package/src/api/fragment-builder.ts +0 -80
- package/src/api/fragment-instantiation.test.ts +0 -460
- package/src/api/fragment-instantiation.ts +0 -499
- package/src/api/fragment.test.ts +0 -537
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import { FragnoPublicConfig } from "./shared-types.js";
|
|
2
|
+
import { RequestThisContext } from "./api.js";
|
|
3
|
+
import { RequestContextStorage } from "./request-context-storage.js";
|
|
4
|
+
import { AnyFragnoInstantiatedFragment, FragnoInstantiatedFragment } from "./fragment-instantiator.js";
|
|
5
|
+
|
|
6
|
+
//#region src/api/fragment-definition-builder.d.ts
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Metadata for a service dependency
|
|
10
|
+
*/
|
|
11
|
+
interface ServiceMetadata {
|
|
12
|
+
/** Name of the service */
|
|
13
|
+
name: string;
|
|
14
|
+
/** Whether this service is required (false means optional) */
|
|
15
|
+
required: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Callback that instantiates a linked fragment.
|
|
19
|
+
* Receives the same context as the main fragment and returns an instantiated fragment.
|
|
20
|
+
*/
|
|
21
|
+
type LinkedFragmentCallback<TConfig, TOptions extends FragnoPublicConfig, TServiceDependencies> = (context: {
|
|
22
|
+
config: TConfig;
|
|
23
|
+
options: TOptions;
|
|
24
|
+
serviceDependencies?: TServiceDependencies;
|
|
25
|
+
}) => FragnoInstantiatedFragment<any, any, any, any, any, any, any>;
|
|
26
|
+
/**
|
|
27
|
+
* Extract the services type from a FragnoInstantiatedFragment
|
|
28
|
+
*/
|
|
29
|
+
type ExtractLinkedServices<T> = T extends ((...args: never[]) => FragnoInstantiatedFragment<any, any, infer TServices, any, any, any, any>) ? TServices : never;
|
|
30
|
+
/**
|
|
31
|
+
* Context passed to the request context factory function.
|
|
32
|
+
*/
|
|
33
|
+
type RequestContextFactoryContext<TConfig, TOptions extends FragnoPublicConfig, TDeps, TRequestStorage> = {
|
|
34
|
+
config: TConfig;
|
|
35
|
+
options: TOptions;
|
|
36
|
+
deps: TDeps;
|
|
37
|
+
storage: RequestContextStorage<TRequestStorage>;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Context object passed to service constructor functions
|
|
41
|
+
*/
|
|
42
|
+
type ServiceContext<TConfig, TOptions, TDeps, TServiceDependencies, TPrivateServices, TServiceThisContext extends RequestThisContext> = {
|
|
43
|
+
config: TConfig;
|
|
44
|
+
options: TOptions;
|
|
45
|
+
deps: TDeps;
|
|
46
|
+
serviceDeps: TServiceDependencies;
|
|
47
|
+
privateServices: TPrivateServices;
|
|
48
|
+
/**
|
|
49
|
+
* Helper to define services with proper `this` context typing.
|
|
50
|
+
* Use this to wrap your service methods when they need access to `this`.
|
|
51
|
+
*/
|
|
52
|
+
defineService: <T>(svc: T & ThisType<TServiceThisContext>) => T;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Service constructor function type
|
|
56
|
+
*/
|
|
57
|
+
type ServiceConstructorFn<TConfig, TOptions, TDeps, TServiceDependencies, TPrivateServices, TService, TServiceThisContext extends RequestThisContext> = (context: ServiceContext<TConfig, TOptions, TDeps, TServiceDependencies, TPrivateServices, TServiceThisContext>) => TService;
|
|
58
|
+
/**
|
|
59
|
+
* Fragment definition interface that supports both regular and database fragments.
|
|
60
|
+
* This is the core definition that will be used for fragment instantiation.
|
|
61
|
+
*/
|
|
62
|
+
interface FragmentDefinition<TConfig, TOptions extends FragnoPublicConfig, TDeps, TBaseServices, TServices$1, TServiceDependencies, TPrivateServices, TServiceThisContext extends RequestThisContext, THandlerThisContext extends RequestThisContext, TRequestStorage = {}, TLinkedFragments extends Record<string, AnyFragnoInstantiatedFragment> = {}> {
|
|
63
|
+
name: string;
|
|
64
|
+
dependencies?: (context: {
|
|
65
|
+
config: TConfig;
|
|
66
|
+
options: TOptions;
|
|
67
|
+
}) => TDeps;
|
|
68
|
+
baseServices?: ServiceConstructorFn<TConfig, TOptions, TDeps, TServiceDependencies, TPrivateServices, TBaseServices, TServiceThisContext>;
|
|
69
|
+
namedServices?: { [K in keyof TServices$1]: ServiceConstructorFn<TConfig, TOptions, TDeps, TServiceDependencies, TPrivateServices, TServices$1[K], TServiceThisContext> };
|
|
70
|
+
privateServices?: { [K in keyof TPrivateServices]: ServiceConstructorFn<TConfig, TOptions, TDeps, TServiceDependencies, TPrivateServices,
|
|
71
|
+
// Private services can access other private services
|
|
72
|
+
TPrivateServices[K], TServiceThisContext> };
|
|
73
|
+
serviceDependencies?: { [K in keyof TServiceDependencies]: ServiceMetadata };
|
|
74
|
+
/**
|
|
75
|
+
* Optional factory function to create the initial request storage data.
|
|
76
|
+
* This is called at the start of each request to initialize the storage.
|
|
77
|
+
* The returned object can be mutated throughout the request lifecycle.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* createRequestStorage: ({ config, options, deps }) => ({
|
|
82
|
+
* counter: 0,
|
|
83
|
+
* userId: deps.currentUserId
|
|
84
|
+
* })
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
createRequestStorage?: (context: {
|
|
88
|
+
config: TConfig;
|
|
89
|
+
options: TOptions;
|
|
90
|
+
deps: TDeps;
|
|
91
|
+
}) => TRequestStorage;
|
|
92
|
+
/**
|
|
93
|
+
* Optional factory function to create the this contexts for services and handlers.
|
|
94
|
+
* Returns separate contexts: serviceContext (may be restricted) and handlerContext (full access).
|
|
95
|
+
* Both contexts should contain only methods or getters that read from storage.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* createThisContext: ({ storage }) => ({
|
|
100
|
+
* serviceContext: {
|
|
101
|
+
* getUnitOfWork: () => restrictedUOW // Without execute methods
|
|
102
|
+
* },
|
|
103
|
+
* handlerContext: {
|
|
104
|
+
* getUnitOfWork: () => fullUOW // With execute methods
|
|
105
|
+
* }
|
|
106
|
+
* })
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
createThisContext?: (context: RequestContextFactoryContext<TConfig, TOptions, TDeps, TRequestStorage>) => {
|
|
110
|
+
serviceContext: TServiceThisContext;
|
|
111
|
+
handlerContext: THandlerThisContext;
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Optional factory function to get an external RequestContextStorage instance.
|
|
115
|
+
* When provided, this storage will be used instead of creating a new one.
|
|
116
|
+
* This allows multiple fragments to share the same storage (e.g., database fragments sharing adapter storage).
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```ts
|
|
120
|
+
* getExternalStorage: ({ options }) => options.databaseAdapter.contextStorage
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
getExternalStorage?: (context: {
|
|
124
|
+
config: TConfig;
|
|
125
|
+
options: TOptions;
|
|
126
|
+
deps: TDeps;
|
|
127
|
+
}) => RequestContextStorage<TRequestStorage>;
|
|
128
|
+
/**
|
|
129
|
+
* Optional linked fragments that will be automatically instantiated with this fragment.
|
|
130
|
+
* Linked fragments are service-only and share the same config/options as the parent.
|
|
131
|
+
*/
|
|
132
|
+
linkedFragments?: { [K in keyof TLinkedFragments]: LinkedFragmentCallback<TConfig, TOptions, TServiceDependencies> };
|
|
133
|
+
$serviceThisContext?: TServiceThisContext;
|
|
134
|
+
$handlerThisContext?: THandlerThisContext;
|
|
135
|
+
$requestStorage?: TRequestStorage;
|
|
136
|
+
$linkedFragments?: TLinkedFragments;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Builder class for creating fragment definitions.
|
|
140
|
+
* This provides a fluent API for defining fragments with type safety.
|
|
141
|
+
*/
|
|
142
|
+
declare class FragmentDefinitionBuilder<TConfig, TOptions extends FragnoPublicConfig, TDeps, TBaseServices, TServices$1, TServiceDependencies, TPrivateServices, TServiceThisContext extends RequestThisContext, THandlerThisContext extends RequestThisContext, TRequestStorage = {}, TLinkedFragments extends Record<string, AnyFragnoInstantiatedFragment> = {}> {
|
|
143
|
+
#private;
|
|
144
|
+
constructor(name: string, state?: {
|
|
145
|
+
dependencies?: (context: {
|
|
146
|
+
config: TConfig;
|
|
147
|
+
options: TOptions;
|
|
148
|
+
}) => TDeps;
|
|
149
|
+
baseServices?: ServiceConstructorFn<TConfig, TOptions, TDeps, TServiceDependencies, TPrivateServices, TBaseServices, TServiceThisContext>;
|
|
150
|
+
namedServices?: { [K in keyof TServices$1]: ServiceConstructorFn<TConfig, TOptions, TDeps, TServiceDependencies, TPrivateServices, TServices$1[K], TServiceThisContext> };
|
|
151
|
+
privateServices?: { [K in keyof TPrivateServices]: ServiceConstructorFn<TConfig, TOptions, TDeps, TServiceDependencies, TPrivateServices, TPrivateServices[K], TServiceThisContext> };
|
|
152
|
+
serviceDependencies?: { [K in keyof TServiceDependencies]: ServiceMetadata };
|
|
153
|
+
createRequestStorage?: (context: {
|
|
154
|
+
config: TConfig;
|
|
155
|
+
options: TOptions;
|
|
156
|
+
deps: TDeps;
|
|
157
|
+
}) => TRequestStorage;
|
|
158
|
+
createThisContext?: (context: RequestContextFactoryContext<TConfig, TOptions, TDeps, TRequestStorage>) => {
|
|
159
|
+
serviceContext: TServiceThisContext;
|
|
160
|
+
handlerContext: THandlerThisContext;
|
|
161
|
+
};
|
|
162
|
+
getExternalStorage?: (context: {
|
|
163
|
+
config: TConfig;
|
|
164
|
+
options: TOptions;
|
|
165
|
+
deps: TDeps;
|
|
166
|
+
}) => RequestContextStorage<TRequestStorage>;
|
|
167
|
+
linkedFragments?: { [K in keyof TLinkedFragments]: LinkedFragmentCallback<TConfig, TOptions, TServiceDependencies> };
|
|
168
|
+
});
|
|
169
|
+
get name(): string;
|
|
170
|
+
/**
|
|
171
|
+
* Define dependencies for this fragment.
|
|
172
|
+
* Dependencies are available to services and handlers.
|
|
173
|
+
*
|
|
174
|
+
* **IMPORTANT**: This method resets all services, storage, and context configurations.
|
|
175
|
+
* Always call `withDependencies` early in the builder chain, before defining services
|
|
176
|
+
* or request storage/context.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```typescript
|
|
180
|
+
* // ✅ GOOD: Dependencies set first
|
|
181
|
+
* defineFragment("my-fragment")
|
|
182
|
+
* .withDependencies(() => ({ apiKey: "..." }))
|
|
183
|
+
* .withRequestStorage(({ deps }) => ({ userId: deps.apiKey }))
|
|
184
|
+
* .providesService("myService", ...)
|
|
185
|
+
*
|
|
186
|
+
* // ❌ BAD: Dependencies set late (erases storage setup)
|
|
187
|
+
* defineFragment("my-fragment")
|
|
188
|
+
* .withRequestStorage(() => ({ userId: "..." })) // This gets erased!
|
|
189
|
+
* .withDependencies(() => ({ apiKey: "..." }))
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
withDependencies<TNewDeps>(fn: (context: {
|
|
193
|
+
config: TConfig;
|
|
194
|
+
options: TOptions;
|
|
195
|
+
}) => TNewDeps): FragmentDefinitionBuilder<TConfig, TOptions, TNewDeps, {}, {}, TServiceDependencies, {}, TServiceThisContext, THandlerThisContext, TRequestStorage, TLinkedFragments>;
|
|
196
|
+
/**
|
|
197
|
+
* Define base (unnamed) services for this fragment.
|
|
198
|
+
* Base services are accessible directly on the fragment instance.
|
|
199
|
+
*/
|
|
200
|
+
providesBaseService<TNewService>(fn: ServiceConstructorFn<TConfig, TOptions, TDeps, TServiceDependencies, TPrivateServices, TNewService, TServiceThisContext>): FragmentDefinitionBuilder<TConfig, TOptions, TDeps, TNewService, TServices$1, TServiceDependencies, TPrivateServices, TServiceThisContext, THandlerThisContext, TRequestStorage, TLinkedFragments>;
|
|
201
|
+
/**
|
|
202
|
+
* Provide a named service that other fragments or users can use.
|
|
203
|
+
* Named services are accessible as fragment.serviceName.method()
|
|
204
|
+
*/
|
|
205
|
+
providesService<TServiceName extends string, TService>(serviceName: TServiceName, fn: ServiceConstructorFn<TConfig, TOptions, TDeps, TServiceDependencies, TPrivateServices, TService, TServiceThisContext>): FragmentDefinitionBuilder<TConfig, TOptions, TDeps, TBaseServices, TServices$1 & { [K in TServiceName]: TService }, TServiceDependencies, TPrivateServices, TServiceThisContext, THandlerThisContext, TRequestStorage, TLinkedFragments>;
|
|
206
|
+
/**
|
|
207
|
+
* Provide a private service that is only accessible to the fragment author.
|
|
208
|
+
* Private services are NOT exposed on the fragment instance, but can be used
|
|
209
|
+
* when defining other services (baseServices, namedServices, and other privateServices).
|
|
210
|
+
* Private services are instantiated in order, so earlier private services are available
|
|
211
|
+
* to later ones.
|
|
212
|
+
*/
|
|
213
|
+
providesPrivateService<TServiceName extends string, TService>(serviceName: TServiceName, fn: ServiceConstructorFn<TConfig, TOptions, TDeps, TServiceDependencies, TPrivateServices, TService, TServiceThisContext>): FragmentDefinitionBuilder<TConfig, TOptions, TDeps, TBaseServices, TServices$1, TServiceDependencies, TPrivateServices & { [K in TServiceName]: TService }, TServiceThisContext, THandlerThisContext, TRequestStorage, TLinkedFragments>;
|
|
214
|
+
/**
|
|
215
|
+
* Declare that this fragment uses a required service provided by the runtime.
|
|
216
|
+
*/
|
|
217
|
+
usesService<TServiceName extends string, TService>(serviceName: TServiceName): FragmentDefinitionBuilder<TConfig, TOptions, TDeps, TBaseServices, TServices$1, TServiceDependencies & { [K in TServiceName]: TService }, TPrivateServices, TServiceThisContext, THandlerThisContext, TRequestStorage, TLinkedFragments>;
|
|
218
|
+
/**
|
|
219
|
+
* Declare that this fragment uses an optional service provided by the runtime.
|
|
220
|
+
*/
|
|
221
|
+
usesOptionalService<TServiceName extends string, TService>(serviceName: TServiceName): FragmentDefinitionBuilder<TConfig, TOptions, TDeps, TBaseServices, TServices$1, TServiceDependencies & { [K in TServiceName]: TService | undefined }, TPrivateServices, TServiceThisContext, THandlerThisContext, TRequestStorage, TLinkedFragments>;
|
|
222
|
+
/**
|
|
223
|
+
* Define the type and initial data stored in AsyncLocalStorage for per-request isolation.
|
|
224
|
+
* This should be called before withThisContext if you need to store request-specific data.
|
|
225
|
+
*
|
|
226
|
+
* @param initializer Function that returns the initial storage data for each request
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* ```typescript
|
|
230
|
+
* .withRequestStorage(({ config, options, deps }) => ({
|
|
231
|
+
* counter: 0,
|
|
232
|
+
* userId: deps.currentUserId
|
|
233
|
+
* }))
|
|
234
|
+
* .withThisContext(({ storage }) => ({
|
|
235
|
+
* serviceContext: {
|
|
236
|
+
* get counter() { return storage.getStore()!.counter; }
|
|
237
|
+
* },
|
|
238
|
+
* handlerContext: {
|
|
239
|
+
* get counter() { return storage.getStore()!.counter; }
|
|
240
|
+
* }
|
|
241
|
+
* }))
|
|
242
|
+
* ```
|
|
243
|
+
*/
|
|
244
|
+
withRequestStorage<TNewRequestStorage>(initializer: (context: {
|
|
245
|
+
config: TConfig;
|
|
246
|
+
options: TOptions;
|
|
247
|
+
deps: TDeps;
|
|
248
|
+
}) => TNewRequestStorage): FragmentDefinitionBuilder<TConfig, TOptions, TDeps, TBaseServices, TServices$1, TServiceDependencies, TPrivateServices, TServiceThisContext, THandlerThisContext, TNewRequestStorage, TLinkedFragments>;
|
|
249
|
+
/**
|
|
250
|
+
* Use an externally-provided RequestContextStorage instance.
|
|
251
|
+
* This allows multiple fragments to share the same storage instance.
|
|
252
|
+
* Useful when fragments need to coordinate (e.g., database fragments sharing adapter storage).
|
|
253
|
+
* Note: You must still call withRequestStorage to provide the initial storage data.
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* ```typescript
|
|
257
|
+
* .withExternalRequestStorage(({ options }) =>
|
|
258
|
+
* options.databaseAdapter.contextStorage
|
|
259
|
+
* )
|
|
260
|
+
* .withRequestStorage(({ options }) => ({
|
|
261
|
+
* uow: options.databaseAdapter.db.createUnitOfWork()
|
|
262
|
+
* }))
|
|
263
|
+
* ```
|
|
264
|
+
*/
|
|
265
|
+
withExternalRequestStorage<TNewStorage>(getStorage: (context: {
|
|
266
|
+
config: TConfig;
|
|
267
|
+
options: TOptions;
|
|
268
|
+
deps: TDeps;
|
|
269
|
+
}) => RequestContextStorage<TNewStorage>): FragmentDefinitionBuilder<TConfig, TOptions, TDeps, TBaseServices, TServices$1, TServiceDependencies, TPrivateServices, TServiceThisContext, THandlerThisContext, TNewStorage, TLinkedFragments>;
|
|
270
|
+
/**
|
|
271
|
+
* Set the this contexts for services and handlers in this fragment.
|
|
272
|
+
* Both contexts should contain only methods or getters that read from storage.
|
|
273
|
+
* This ensures proper per-request isolation via AsyncLocalStorage.
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* ```ts
|
|
277
|
+
* .withThisContext(({ storage }) => ({
|
|
278
|
+
* serviceContext: {
|
|
279
|
+
* get myNumber() { return storage.getStore()?.myNumber ?? 0; }
|
|
280
|
+
* },
|
|
281
|
+
* handlerContext: {
|
|
282
|
+
* get myNumber() { return storage.getStore()?.myNumber ?? 0; }
|
|
283
|
+
* }
|
|
284
|
+
* }))
|
|
285
|
+
* ```
|
|
286
|
+
*/
|
|
287
|
+
withThisContext<TNewServiceThisContext extends RequestThisContext, TNewHandlerThisContext extends RequestThisContext>(fn: (context: RequestContextFactoryContext<TConfig, TOptions, TDeps, TRequestStorage>) => {
|
|
288
|
+
serviceContext: TNewServiceThisContext;
|
|
289
|
+
handlerContext: TNewHandlerThisContext;
|
|
290
|
+
}): FragmentDefinitionBuilder<TConfig, TOptions, TDeps, TBaseServices, TServices$1, TServiceDependencies, TPrivateServices, TNewServiceThisContext, TNewHandlerThisContext, TRequestStorage, TLinkedFragments>;
|
|
291
|
+
/**
|
|
292
|
+
* Register a linked fragment that will be automatically instantiated.
|
|
293
|
+
* Linked fragments are service-only (no routes) and share the same config/options as the parent.
|
|
294
|
+
* All services from the linked fragment will be available as private services.
|
|
295
|
+
*/
|
|
296
|
+
withLinkedFragment<const TName extends string, TCallback extends LinkedFragmentCallback<TConfig, TOptions, TServiceDependencies>>(name: TName, callback: TCallback): FragmentDefinitionBuilder<TConfig, TOptions, TDeps, TBaseServices, TServices$1, TServiceDependencies, TPrivateServices & ExtractLinkedServices<TCallback>, TServiceThisContext, THandlerThisContext, TRequestStorage, TLinkedFragments & { [K in TName]: ReturnType<TCallback> }>;
|
|
297
|
+
/**
|
|
298
|
+
* Extend this builder with a transformation function.
|
|
299
|
+
* This enables fluent API extensions like `.extend(withDatabase(schema))`.
|
|
300
|
+
*/
|
|
301
|
+
extend<const TNewBuilder>(transformer: (builder: this) => TNewBuilder): TNewBuilder;
|
|
302
|
+
/**
|
|
303
|
+
* Build the final fragment definition
|
|
304
|
+
*/
|
|
305
|
+
build(): FragmentDefinition<TConfig, TOptions, TDeps, TBaseServices, TServices$1, TServiceDependencies, TPrivateServices, TServiceThisContext, THandlerThisContext, TRequestStorage, TLinkedFragments>;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Create a new fragment definition builder
|
|
309
|
+
*/
|
|
310
|
+
declare function defineFragment<TConfig = {}, TOptions extends FragnoPublicConfig = FragnoPublicConfig, TServiceThisContext extends RequestThisContext = RequestThisContext, THandlerThisContext extends RequestThisContext = RequestThisContext, TRequestStorage = {}>(name: string): FragmentDefinitionBuilder<TConfig, TOptions, {}, {}, {}, {}, {}, TServiceThisContext, THandlerThisContext, TRequestStorage, {}>;
|
|
311
|
+
//#endregion
|
|
312
|
+
export { ExtractLinkedServices, FragmentDefinition, FragmentDefinitionBuilder, LinkedFragmentCallback, RequestContextFactoryContext, ServiceConstructorFn, ServiceContext, defineFragment };
|
|
313
|
+
//# sourceMappingURL=fragment-definition-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fragment-definition-builder.d.ts","names":[],"sources":["../../src/api/fragment-definition-builder.ts"],"sourcesContent":[],"mappings":"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"}
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
//#region src/api/fragment-definition-builder.ts
|
|
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 {
|
|
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(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(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(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(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(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(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(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(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(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(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
|
+
* Create a new fragment definition builder
|
|
319
|
+
*/
|
|
320
|
+
function defineFragment(name) {
|
|
321
|
+
return new FragmentDefinitionBuilder(name);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
//#endregion
|
|
325
|
+
export { FragmentDefinitionBuilder, defineFragment };
|
|
326
|
+
//# sourceMappingURL=fragment-definition-builder.js.map
|