@playfast/reform 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -55
- package/package.json +17 -17
- package/src/boundary/boundary.test.ts +62 -16
- package/src/boundary/boundary.ts +141 -32
- package/src/calc/asyncCalc.invalidate.test.ts +516 -18
- package/src/calc/asyncCalc.test.ts +207 -175
- package/src/calc/asyncCalc.ts +168 -39
- package/src/calc/calc.test.ts +3 -5
- package/src/calc/calc.ts +44 -18
- package/src/calc/calcFamily.test.ts +80 -22
- package/src/calc/calcFamily.ts +56 -25
- package/src/calc/compose.ts +1 -14
- package/src/channel/channel.ts +128 -11
- package/src/compose/composition.test.ts +19 -0
- package/src/compose/composition.ts +346 -62
- package/src/compose/props.ts +13 -6
- package/src/compose/provide.ts +187 -46
- package/src/compose/slot.ts +156 -19
- package/src/compose/structure.test.ts +6 -3
- package/src/compose/structure.ts +106 -13
- package/src/compose/ui.test.ts +19 -3
- package/src/compose/ui.ts +147 -54
- package/src/compose/ui.typecheck.ts +40 -4
- package/src/definition/definition.ts +22 -9
- package/src/event/event.fromSource.test.ts +172 -0
- package/src/event/event.test.ts +10 -0
- package/src/event/event.ts +102 -18
- package/src/feature/feature.mount.test.ts +123 -56
- package/src/feature/feature.test.ts +67 -63
- package/src/feature/feature.ts +1317 -197
- package/src/feature/feature.typecheck.ts +253 -61
- package/src/graph/closure.ts +403 -0
- package/src/index.ts +171 -245
- package/src/internal/bucketCache.ts +39 -0
- package/src/internal/capture.ts +9 -4
- package/src/internal/env.ts +1 -3
- package/src/internal/errors.ts +21 -10
- package/src/internal/queryDriver.ts +120 -15
- package/src/internal/queryDriverStore.ts +8 -5
- package/src/internal/queryDriverTypes.ts +3 -1
- package/src/internal/reuse.test.ts +10 -3
- package/src/internal/reuse.ts +5 -2
- package/src/internal/scheduler.ts +4 -1
- package/src/internal/sources.ts +25 -11
- package/src/internal/track.ts +3 -2
- package/src/internal.ts +222 -0
- package/src/namespace/namespace.ts +46 -25
- package/src/procedure/procedure.ts +38 -11
- package/src/reducer/reducer.ts +78 -34
- package/src/remote/remoteState.test.ts +515 -339
- package/src/remote/remoteState.ts +572 -107
- package/src/remote/remoteState.typecheck.ts +47 -23
- package/src/runtime/appRuntime.activation.test.ts +100 -0
- package/src/runtime/appRuntime.test.ts +157 -105
- package/src/runtime/appRuntime.ts +394 -33
- package/src/runtime/eventBudget.test.ts +1 -4
- package/src/runtime/eventBudget.ts +9 -8
- package/src/runtime/hardening.test.ts +4 -9
- package/src/runtime/instrumentation.test.ts +174 -192
- package/src/runtime/instrumentation.ts +6 -11
- package/src/runtime/loop.test.ts +36 -0
- package/src/runtime/loop.ts +69 -40
- package/src/scene/featureScene.test.ts +4 -2
- package/src/scene/scene.ts +234 -64
- package/src/scene/seedScene.test.ts +69 -86
- package/src/state/state.nominal.typecheck.ts +68 -0
- package/src/state/state.test.ts +17 -0
- package/src/state/state.ts +79 -26
- package/src/state/stateFamily.test.ts +14 -0
- package/src/state/stateFamily.ts +55 -22
- package/src/state/stateGroup.ts +53 -17
- package/src/state/token.ts +40 -10
- package/src/synced/syncedStore.ts +46 -23
- package/src/testkit/flight.testkit.ts +75 -0
- package/src/wire/tree.test.ts +8 -4
- package/src/wire/triggers.test.ts +6 -2
- package/src/wire/triggers.ts +14 -10
- package/src/calc/asyncCalcDefinitions.ts +0 -48
- package/src/channel/procedureRegistry.ts +0 -90
- package/src/feature/featureBinding.ts +0 -48
- package/src/internal/ctx.ts +0 -9
- package/src/remote/remoteStateDefinition.ts +0 -135
- package/src/remote/remoteStateLayers.ts +0 -118
- package/src/remote/remoteStateLiveTypes.ts +0 -59
- package/src/remote/remoteStateSend.ts +0 -64
package/src/feature/feature.ts
CHANGED
|
@@ -1,84 +1,227 @@
|
|
|
1
|
-
import { Context, Effect, Layer, Option, type Scope } from 'effect'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { Context, Effect, Layer, Option, Schema, type Scope } from 'effect'
|
|
2
|
+
import {
|
|
3
|
+
type AnyComposition,
|
|
4
|
+
CompositionIdTypeId,
|
|
5
|
+
type CompositionClass,
|
|
6
|
+
type HasExactCompositionId,
|
|
7
|
+
type CompositionPropsReceiver,
|
|
8
|
+
} from '../compose/composition'
|
|
7
9
|
import { type UiContract } from '../compose/ui'
|
|
8
|
-
import {
|
|
9
|
-
import type { AnyValue } from '../internal/variance'
|
|
10
|
+
import { type Manifest, definitionClass } from '../definition/definition'
|
|
10
11
|
import {
|
|
11
|
-
type
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
type
|
|
18
|
-
|
|
19
|
-
type
|
|
20
|
-
|
|
21
|
-
type
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
12
|
+
type AnyFeatureGraphSummary,
|
|
13
|
+
type FeatureGraphSummary,
|
|
14
|
+
FeatureGraphSummaryTypeId,
|
|
15
|
+
FeatureGraphValidTypeId,
|
|
16
|
+
FeatureChildSummaryTypeId,
|
|
17
|
+
FeatureModuleGraphValidTypeId,
|
|
18
|
+
type FeatureSummaryCompositionIdentity,
|
|
19
|
+
type FeatureSummaryCompositionProps,
|
|
20
|
+
type FeatureSummaryContract,
|
|
21
|
+
type FeatureSummaryInput,
|
|
22
|
+
type FeatureSummaryName,
|
|
23
|
+
type FeatureSummaryOpenServices,
|
|
24
|
+
type FeatureSummaryStates,
|
|
25
|
+
type FeatureSummarySupportOpenServices,
|
|
26
|
+
type FeatureSummaryUsesInput,
|
|
27
|
+
type ModuleOpenServices,
|
|
28
|
+
type OpenServicesFromFeatureSlotWitnesses,
|
|
29
|
+
SlotBindingSummaryTypeId,
|
|
30
|
+
type ValidateFeatureGraphLayer,
|
|
31
|
+
} from '../graph/closure'
|
|
32
|
+
import { FeatureLoadFailed } from '../internal/errors'
|
|
33
|
+
import { Bus, publish, type Tagged } from '../runtime/bus'
|
|
34
|
+
import { type EngineServices } from '../runtime/loop'
|
|
35
|
+
|
|
36
|
+
export type { EngineServices } from '../runtime/loop'
|
|
37
|
+
export { FeatureGraphValidTypeId }
|
|
38
|
+
|
|
39
|
+
const FeatureInputBase: Context.TagClass<FeatureInput, 'reform/FeatureInput', unknown> =
|
|
40
|
+
Context.Tag('reform/FeatureInput')<FeatureInput, unknown>()
|
|
31
41
|
export class FeatureInput extends FeatureInputBase {}
|
|
32
42
|
|
|
43
|
+
// Context.Tag is invariant, so erased requirements use its structural identity carrier.
|
|
44
|
+
interface FeatureServiceTag<out Identifier = unknown, out Service = unknown> {
|
|
45
|
+
readonly [Context.TagTypeId]: object
|
|
46
|
+
readonly Identifier: Identifier
|
|
47
|
+
readonly Service: Service
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface StoredFeatureRequirement<out Identifier = unknown, out Service = unknown> {
|
|
51
|
+
readonly store: FeatureServiceTag<Identifier, Service>
|
|
52
|
+
}
|
|
53
|
+
|
|
33
54
|
export type RequireCarrier =
|
|
34
|
-
|
|
|
35
|
-
| {
|
|
55
|
+
| StoredFeatureRequirement
|
|
56
|
+
| {
|
|
57
|
+
readonly members: ReadonlyArray<StoredFeatureRequirement>
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type FeatureRequirement = RequireCarrier | FeatureServiceTag
|
|
61
|
+
|
|
62
|
+
type TagRequirement<Tag> =
|
|
63
|
+
Tag extends FeatureServiceTag<infer Identifier, infer _Service> ? Identifier : never
|
|
64
|
+
|
|
65
|
+
type StoredRequirementIdentifier<Carrier> = Carrier extends {
|
|
66
|
+
readonly store: infer Tag
|
|
67
|
+
}
|
|
68
|
+
? TagRequirement<Tag>
|
|
69
|
+
: never
|
|
70
|
+
|
|
71
|
+
type RequirementIdentifier<Requirement> = Requirement extends FeatureServiceTag
|
|
72
|
+
? TagRequirement<Requirement>
|
|
73
|
+
: Requirement extends {
|
|
74
|
+
readonly members: infer Members extends ReadonlyArray<StoredFeatureRequirement>
|
|
75
|
+
}
|
|
76
|
+
? StoredRequirementIdentifier<Members[number]>
|
|
77
|
+
: StoredRequirementIdentifier<Requirement>
|
|
78
|
+
|
|
79
|
+
export type ProvidedBy<Requires extends ReadonlyArray<FeatureRequirement>> = RequirementIdentifier<
|
|
80
|
+
Requires[number]
|
|
81
|
+
>
|
|
36
82
|
|
|
37
|
-
|
|
83
|
+
type DefaultFeatureOpenServices<ROut, DirectRequires extends ReadonlyArray<FeatureRequirement>> =
|
|
84
|
+
| ProvidedBy<DirectRequires>
|
|
85
|
+
| OpenServicesFromFeatureSlotWitnesses<ROut>
|
|
38
86
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
? Identifier
|
|
43
|
-
: Requires[I] extends {
|
|
44
|
-
readonly members: infer M extends ReadonlyArray<unknown>
|
|
87
|
+
type CompositionNames<ROut> = ROut extends {
|
|
88
|
+
readonly [CompositionIdTypeId]: {
|
|
89
|
+
readonly name: infer Name extends string
|
|
45
90
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
91
|
+
}
|
|
92
|
+
? Name
|
|
93
|
+
: never
|
|
94
|
+
|
|
95
|
+
type CompositionIdentities<ROut> = ROut extends {
|
|
96
|
+
readonly [CompositionIdTypeId]: {
|
|
97
|
+
readonly identity: infer Identity
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
? Identity
|
|
101
|
+
: never
|
|
102
|
+
|
|
103
|
+
type RootCompositionName<ROut> = [CompositionNames<ROut>] extends [never]
|
|
104
|
+
? string
|
|
105
|
+
: CompositionNames<ROut>
|
|
106
|
+
|
|
107
|
+
type RootCompositionIdentity<ROut> = [CompositionIdentities<ROut>] extends [never]
|
|
108
|
+
? unknown
|
|
109
|
+
: CompositionIdentities<ROut>
|
|
110
|
+
|
|
111
|
+
// Feature layers may require the shared engine but must never provide it.
|
|
112
|
+
export type FeatureModuleInput<OpenServices, UsesInput extends boolean> =
|
|
113
|
+
| EngineServices
|
|
114
|
+
| OpenServices
|
|
115
|
+
| (UsesInput extends true ? FeatureInput : never)
|
|
51
116
|
|
|
52
117
|
export interface FeatureModule<
|
|
53
118
|
ROut,
|
|
54
|
-
|
|
119
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
120
|
+
OpenServices = DefaultFeatureOpenServices<ROut, DirectRequires>,
|
|
55
121
|
UsesInput extends boolean = false,
|
|
56
|
-
|
|
57
|
-
|
|
122
|
+
Input = never,
|
|
123
|
+
> extends AnyLoadedModule {
|
|
124
|
+
readonly [FeatureModuleGraphValidTypeId]: FeatureModuleGraphValidTypeId
|
|
125
|
+
readonly requires: DirectRequires
|
|
58
126
|
readonly usesInput: UsesInput
|
|
59
|
-
readonly layer: Layer.Layer<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
127
|
+
readonly layer: Layer.Layer<ROut, never, FeatureModuleInput<OpenServices, UsesInput>>
|
|
128
|
+
readonly inputSchema: UsesInput extends true ? Schema.Schema.AnyNoContext : undefined
|
|
129
|
+
readonly Input: (input: Input) => void
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export type LoadedModuleCapture<Result> = <
|
|
133
|
+
ROut,
|
|
134
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
135
|
+
OpenServices,
|
|
136
|
+
UsesInput extends boolean,
|
|
137
|
+
Input,
|
|
138
|
+
>(
|
|
139
|
+
module: LoadedModule<ROut, DirectRequires, OpenServices, UsesInput, Input>,
|
|
140
|
+
) => Result
|
|
141
|
+
|
|
142
|
+
export interface AnyLoadedModule {
|
|
143
|
+
readonly capture: <Result>(visit: LoadedModuleCapture<Result>) => Result
|
|
66
144
|
}
|
|
67
145
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
146
|
+
type FeatureLayerOutput<L extends Layer.Layer.Any> = Layer.Layer.Success<L>
|
|
147
|
+
|
|
148
|
+
// Reject erased contexts before graph validation can mistake them for permissive inputs.
|
|
149
|
+
type ExactFeatureLayer<L extends Layer.Layer.Any, UsesInput extends boolean> = Layer.Layer<
|
|
150
|
+
FeatureLayerOutput<L>,
|
|
151
|
+
never,
|
|
152
|
+
FeatureModuleInput<ModuleOpenServices<L, UsesInput>, UsesInput>
|
|
153
|
+
> &
|
|
154
|
+
(unknown extends Layer.Layer.Context<L>
|
|
155
|
+
? {
|
|
156
|
+
readonly featureLayerContextMustBeExact: 'A feature layer context cannot be erased'
|
|
157
|
+
}
|
|
158
|
+
: object)
|
|
159
|
+
|
|
160
|
+
export const featureModule = <
|
|
161
|
+
const DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
162
|
+
L extends Layer.Layer.Any,
|
|
163
|
+
>(
|
|
164
|
+
requires: DirectRequires,
|
|
165
|
+
layer: L & ExactFeatureLayer<L, false> & ValidateFeatureGraphLayer<L, DirectRequires, false>,
|
|
166
|
+
): FeatureModule<
|
|
167
|
+
FeatureLayerOutput<L>,
|
|
168
|
+
DirectRequires,
|
|
169
|
+
ModuleOpenServices<L, false>,
|
|
170
|
+
false,
|
|
171
|
+
never
|
|
172
|
+
> => {
|
|
173
|
+
const module: FeatureModule<
|
|
174
|
+
FeatureLayerOutput<L>,
|
|
175
|
+
DirectRequires,
|
|
176
|
+
ModuleOpenServices<L, false>,
|
|
177
|
+
false,
|
|
178
|
+
never
|
|
179
|
+
> = {
|
|
180
|
+
[FeatureModuleGraphValidTypeId]: FeatureModuleGraphValidTypeId,
|
|
181
|
+
requires,
|
|
182
|
+
usesInput: false,
|
|
183
|
+
layer,
|
|
184
|
+
inputSchema: undefined,
|
|
185
|
+
Input: () => undefined,
|
|
186
|
+
capture: <Result>(visit: LoadedModuleCapture<Result>): Result => visit(module),
|
|
187
|
+
}
|
|
188
|
+
return module
|
|
189
|
+
}
|
|
72
190
|
|
|
73
191
|
export const featureModuleFromInput = <
|
|
74
|
-
const
|
|
75
|
-
|
|
192
|
+
const InputSchema extends Schema.Schema.AnyNoContext,
|
|
193
|
+
const DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
194
|
+
L extends Layer.Layer.Any,
|
|
76
195
|
>(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
196
|
+
input: InputSchema,
|
|
197
|
+
requires: DirectRequires,
|
|
198
|
+
layer: L & ExactFeatureLayer<L, true> & ValidateFeatureGraphLayer<L, DirectRequires, true>,
|
|
199
|
+
): FeatureModule<
|
|
200
|
+
FeatureLayerOutput<L>,
|
|
201
|
+
DirectRequires,
|
|
202
|
+
ModuleOpenServices<L, true>,
|
|
203
|
+
true,
|
|
204
|
+
Schema.Schema.Type<InputSchema>
|
|
205
|
+
> => {
|
|
206
|
+
const module: FeatureModule<
|
|
207
|
+
FeatureLayerOutput<L>,
|
|
208
|
+
DirectRequires,
|
|
209
|
+
ModuleOpenServices<L, true>,
|
|
210
|
+
true,
|
|
211
|
+
Schema.Schema.Type<InputSchema>
|
|
212
|
+
> = {
|
|
213
|
+
[FeatureModuleGraphValidTypeId]: FeatureModuleGraphValidTypeId,
|
|
214
|
+
requires,
|
|
215
|
+
usesInput: true,
|
|
216
|
+
layer,
|
|
217
|
+
inputSchema: input,
|
|
218
|
+
Input: () => undefined,
|
|
219
|
+
capture: <Result>(visit: LoadedModuleCapture<Result>): Result => visit(module),
|
|
220
|
+
}
|
|
221
|
+
return module
|
|
222
|
+
}
|
|
80
223
|
|
|
81
|
-
//
|
|
224
|
+
// Seal dynamic imports as typed Effects so chunk failures become FeatureLoadFailed.
|
|
82
225
|
export const lazyImport = <M>(
|
|
83
226
|
thunk: () => Promise<{ readonly default: M }>,
|
|
84
227
|
): Effect.Effect<M, FeatureLoadFailed> =>
|
|
@@ -87,205 +230,1182 @@ export const lazyImport = <M>(
|
|
|
87
230
|
catch: (cause) => new FeatureLoadFailed({ cause }),
|
|
88
231
|
}).pipe(Effect.map((module) => module.default))
|
|
89
232
|
|
|
90
|
-
export interface
|
|
91
|
-
|
|
92
|
-
|
|
233
|
+
export interface FailedProps {
|
|
234
|
+
readonly error: FeatureLoadFailed
|
|
235
|
+
readonly retry: () => void
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export interface FeatureManifest extends Manifest {
|
|
239
|
+
readonly kind: 'Feature'
|
|
240
|
+
readonly name: string
|
|
241
|
+
readonly strategy: 'lazy' | 'default'
|
|
242
|
+
readonly composition: Manifest & { readonly kind: 'Composition' }
|
|
243
|
+
readonly placeholder: Option.Option<{
|
|
244
|
+
readonly loading: Manifest & { readonly kind: 'Composition' }
|
|
245
|
+
readonly failed: Manifest & { readonly kind: 'Composition' }
|
|
246
|
+
}>
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export interface LoadedModule<
|
|
93
250
|
ROut,
|
|
94
|
-
|
|
95
|
-
|
|
251
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
252
|
+
OpenServices = DefaultFeatureOpenServices<ROut, DirectRequires>,
|
|
253
|
+
UsesInput extends boolean = false,
|
|
254
|
+
Input = never,
|
|
255
|
+
> extends FeatureModule<ROut, DirectRequires, OpenServices, UsesInput, Input> {}
|
|
256
|
+
|
|
257
|
+
export const FeatureBindingTypeId: unique symbol = Symbol.for('reform/FeatureBinding')
|
|
258
|
+
export type FeatureBindingTypeId = typeof FeatureBindingTypeId
|
|
259
|
+
export type FeatureBindingType = FeatureBindingTypeId
|
|
260
|
+
|
|
261
|
+
const FeatureTokenIdentityTypeId: unique symbol = Symbol('reform/FeatureTokenIdentity')
|
|
262
|
+
const FeatureNativeTypeId: unique symbol = Symbol('reform/FeatureNative')
|
|
263
|
+
|
|
264
|
+
export interface FeatureIdentityToken<out FeatureIdentity> {
|
|
265
|
+
readonly identity: symbol
|
|
266
|
+
readonly [FeatureTokenIdentityTypeId]: readonly [] | readonly [FeatureIdentity]
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export interface FeatureToken<
|
|
270
|
+
out FeatureIdentity,
|
|
271
|
+
out NativeTree extends object,
|
|
272
|
+
> extends FeatureIdentityToken<FeatureIdentity> {
|
|
273
|
+
readonly [FeatureNativeTypeId]: NativeTree
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export interface FeatureTreeCarrier {
|
|
277
|
+
readonly token: FeatureToken<unknown, object>
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
type Native<
|
|
281
|
+
Feature extends FeatureTreeCarrier,
|
|
282
|
+
Token extends Feature['token'] = Feature['token'],
|
|
283
|
+
> = Token[typeof FeatureNativeTypeId]
|
|
284
|
+
|
|
285
|
+
export const tree = <
|
|
286
|
+
Feature extends FeatureTreeCarrier,
|
|
287
|
+
Token extends Feature['token'] = Feature['token'],
|
|
288
|
+
>(
|
|
289
|
+
token: Token,
|
|
290
|
+
): Native<Feature, Token> => token[FeatureNativeTypeId]
|
|
291
|
+
|
|
292
|
+
export interface ProvideableFeature<
|
|
293
|
+
out FeatureIdentity,
|
|
294
|
+
out Summary extends AnyFeatureGraphSummary,
|
|
96
295
|
> {
|
|
97
296
|
new (): {}
|
|
98
297
|
readonly manifest: FeatureManifest
|
|
99
|
-
readonly
|
|
100
|
-
readonly
|
|
101
|
-
readonly composition: CompositionClass<P, C>
|
|
102
|
-
readonly Requires: Requires
|
|
103
|
-
readonly load: Effect.Effect<FeatureModule<ROut, Requires, boolean>, FeatureLoadFailed>
|
|
104
|
-
readonly binding: FeatureBinding
|
|
105
|
-
readonly eagerModule: FeatureModule<ROut, Requires, false> | undefined
|
|
106
|
-
readonly supportModule: FeatureModule<never, SupportRequires, false> | undefined
|
|
298
|
+
readonly token: FeatureIdentityToken<FeatureIdentity>
|
|
299
|
+
readonly summary: Summary
|
|
107
300
|
}
|
|
108
301
|
|
|
109
|
-
export interface
|
|
110
|
-
|
|
111
|
-
|
|
302
|
+
export interface FeatureDefinition<
|
|
303
|
+
out FeatureIdentity,
|
|
304
|
+
out Summary extends AnyFeatureGraphSummary,
|
|
305
|
+
out NativeTree extends object,
|
|
306
|
+
> extends ProvideableFeature<FeatureIdentity, Summary> {
|
|
307
|
+
readonly token: FeatureToken<FeatureIdentity, NativeTree>
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export type FeatureOpenServices<Feature extends { readonly summary: AnyFeatureGraphSummary }> =
|
|
311
|
+
FeatureSummaryOpenServices<Feature['summary']>
|
|
312
|
+
|
|
313
|
+
export type FeatureSupportOpenServices<
|
|
314
|
+
Feature extends { readonly summary: AnyFeatureGraphSummary },
|
|
315
|
+
> = FeatureSummarySupportOpenServices<Feature['summary']>
|
|
316
|
+
|
|
317
|
+
export interface AnyFeatureBindingExternalApi {
|
|
318
|
+
readonly [FeatureBindingTypeId]: FeatureBindingTypeId
|
|
319
|
+
readonly [FeatureGraphValidTypeId]: FeatureGraphValidTypeId
|
|
320
|
+
readonly capture: <Result>(visit: FeatureBindingCapture<Result>) => Result
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export type AnyFeatureBinding = AnyFeatureBindingExternalApi
|
|
324
|
+
|
|
325
|
+
export interface FeatureBinding<
|
|
326
|
+
Summary extends AnyFeatureGraphSummary,
|
|
327
|
+
ROut,
|
|
328
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
329
|
+
> extends AnyFeatureBindingExternalApi {
|
|
330
|
+
readonly manifest: FeatureManifest
|
|
331
|
+
readonly identity: symbol
|
|
332
|
+
readonly summary: Summary
|
|
333
|
+
readonly composition: CompositionClass<
|
|
334
|
+
FeatureSummaryCompositionProps<Summary>,
|
|
335
|
+
FeatureSummaryContract<Summary>,
|
|
336
|
+
FeatureSummaryStates<Summary>,
|
|
337
|
+
FeatureSummaryName<Summary>,
|
|
338
|
+
FeatureSummaryCompositionIdentity<Summary>
|
|
339
|
+
>
|
|
340
|
+
readonly strategy: 'lazy' | 'default'
|
|
341
|
+
readonly load: Effect.Effect<
|
|
342
|
+
LoadedModule<
|
|
343
|
+
ROut,
|
|
344
|
+
DirectRequires,
|
|
345
|
+
FeatureSummaryOpenServices<Summary>,
|
|
346
|
+
FeatureSummaryUsesInput<Summary>,
|
|
347
|
+
FeatureSummaryInput<Summary>
|
|
348
|
+
>,
|
|
349
|
+
FeatureLoadFailed
|
|
350
|
+
>
|
|
351
|
+
readonly placeholder: Option.Option<{
|
|
352
|
+
readonly loading: AnyComposition
|
|
353
|
+
readonly failed: AnyComposition
|
|
354
|
+
}>
|
|
355
|
+
readonly parseInput: (input: unknown) => Option.Option<unknown>
|
|
356
|
+
readonly boot: ReadonlyArray<Tagged>
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
export type CapturedFeatureBinding<
|
|
360
|
+
Summary extends AnyFeatureGraphSummary,
|
|
361
|
+
ROut,
|
|
362
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
363
|
+
> = FeatureBinding<Summary, ROut, DirectRequires>
|
|
364
|
+
|
|
365
|
+
export type FeatureBindingCapture<Result> = <
|
|
366
|
+
Summary extends AnyFeatureGraphSummary,
|
|
367
|
+
ROut,
|
|
368
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
369
|
+
>(
|
|
370
|
+
binding: FeatureBinding<Summary, ROut, DirectRequires>,
|
|
371
|
+
) => Result
|
|
372
|
+
|
|
373
|
+
export const isFeatureBinding = (candidate: unknown): candidate is AnyFeatureBinding =>
|
|
374
|
+
typeof candidate === 'object' &&
|
|
375
|
+
candidate !== null &&
|
|
376
|
+
FeatureBindingTypeId in candidate &&
|
|
377
|
+
FeatureGraphValidTypeId in candidate
|
|
378
|
+
|
|
379
|
+
export interface FeatureNativeTree<
|
|
380
|
+
Summary extends AnyFeatureGraphSummary,
|
|
381
|
+
ROut,
|
|
382
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
383
|
+
SupportOut,
|
|
384
|
+
SupportDirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
385
|
+
Composition extends CompositionClass<
|
|
386
|
+
FeatureSummaryCompositionProps<Summary>,
|
|
387
|
+
FeatureSummaryContract<Summary>,
|
|
388
|
+
FeatureSummaryStates<Summary>,
|
|
389
|
+
FeatureSummaryName<Summary>,
|
|
390
|
+
FeatureSummaryCompositionIdentity<Summary>
|
|
391
|
+
> = CompositionClass<
|
|
392
|
+
FeatureSummaryCompositionProps<Summary>,
|
|
393
|
+
FeatureSummaryContract<Summary>,
|
|
394
|
+
FeatureSummaryStates<Summary>,
|
|
395
|
+
FeatureSummaryName<Summary>,
|
|
396
|
+
FeatureSummaryCompositionIdentity<Summary>
|
|
397
|
+
>,
|
|
398
|
+
> {
|
|
399
|
+
readonly identity: symbol
|
|
400
|
+
readonly summary: Summary
|
|
401
|
+
readonly composition: Composition
|
|
402
|
+
readonly load: Effect.Effect<
|
|
403
|
+
FeatureModule<
|
|
404
|
+
ROut,
|
|
405
|
+
DirectRequires,
|
|
406
|
+
FeatureSummaryOpenServices<Summary>,
|
|
407
|
+
FeatureSummaryUsesInput<Summary>,
|
|
408
|
+
FeatureSummaryInput<Summary>
|
|
409
|
+
>,
|
|
410
|
+
FeatureLoadFailed
|
|
411
|
+
>
|
|
412
|
+
readonly binding: CapturedFeatureBinding<Summary, ROut, DirectRequires>
|
|
413
|
+
readonly eagerModule:
|
|
414
|
+
| FeatureModule<ROut, DirectRequires, FeatureSummaryOpenServices<Summary>, false, never>
|
|
415
|
+
| undefined
|
|
416
|
+
readonly supportModule:
|
|
417
|
+
| FeatureModule<
|
|
418
|
+
SupportOut,
|
|
419
|
+
SupportDirectRequires,
|
|
420
|
+
FeatureSummarySupportOpenServices<Summary>,
|
|
421
|
+
false,
|
|
422
|
+
never
|
|
423
|
+
>
|
|
424
|
+
| undefined
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
export interface EagerFeatureNativeTree<
|
|
428
|
+
Summary extends AnyFeatureGraphSummary,
|
|
112
429
|
ROut,
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
430
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
431
|
+
Composition extends CompositionClass<
|
|
432
|
+
FeatureSummaryCompositionProps<Summary>,
|
|
433
|
+
FeatureSummaryContract<Summary>,
|
|
434
|
+
FeatureSummaryStates<Summary>,
|
|
435
|
+
FeatureSummaryName<Summary>,
|
|
436
|
+
FeatureSummaryCompositionIdentity<Summary>
|
|
437
|
+
> = CompositionClass<
|
|
438
|
+
FeatureSummaryCompositionProps<Summary>,
|
|
439
|
+
FeatureSummaryContract<Summary>,
|
|
440
|
+
FeatureSummaryStates<Summary>,
|
|
441
|
+
FeatureSummaryName<Summary>,
|
|
442
|
+
FeatureSummaryCompositionIdentity<Summary>
|
|
443
|
+
>,
|
|
444
|
+
> extends FeatureNativeTree<Summary, ROut, DirectRequires, never, readonly [], Composition> {
|
|
445
|
+
readonly eagerModule: FeatureModule<
|
|
446
|
+
ROut,
|
|
447
|
+
DirectRequires,
|
|
448
|
+
FeatureSummaryOpenServices<Summary>,
|
|
449
|
+
false,
|
|
450
|
+
never
|
|
451
|
+
>
|
|
116
452
|
readonly supportModule: undefined
|
|
117
453
|
}
|
|
118
454
|
|
|
119
|
-
export interface
|
|
120
|
-
|
|
121
|
-
|
|
455
|
+
export interface LazyFeatureNativeTree<
|
|
456
|
+
Summary extends AnyFeatureGraphSummary,
|
|
457
|
+
ROut,
|
|
458
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
459
|
+
SupportOut,
|
|
460
|
+
SupportDirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
461
|
+
Composition extends CompositionClass<
|
|
462
|
+
FeatureSummaryCompositionProps<Summary>,
|
|
463
|
+
FeatureSummaryContract<Summary>,
|
|
464
|
+
FeatureSummaryStates<Summary>,
|
|
465
|
+
FeatureSummaryName<Summary>,
|
|
466
|
+
FeatureSummaryCompositionIdentity<Summary>
|
|
467
|
+
> = CompositionClass<
|
|
468
|
+
FeatureSummaryCompositionProps<Summary>,
|
|
469
|
+
FeatureSummaryContract<Summary>,
|
|
470
|
+
FeatureSummaryStates<Summary>,
|
|
471
|
+
FeatureSummaryName<Summary>,
|
|
472
|
+
FeatureSummaryCompositionIdentity<Summary>
|
|
473
|
+
>,
|
|
474
|
+
> extends FeatureNativeTree<
|
|
475
|
+
Summary,
|
|
122
476
|
ROut,
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
477
|
+
DirectRequires,
|
|
478
|
+
SupportOut,
|
|
479
|
+
SupportDirectRequires,
|
|
480
|
+
Composition
|
|
481
|
+
> {
|
|
126
482
|
readonly eagerModule: undefined
|
|
127
483
|
}
|
|
128
484
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
ReadonlyArray<
|
|
485
|
+
type FeatureSummaryOf<
|
|
486
|
+
FeatureIdentity,
|
|
487
|
+
MountProps,
|
|
488
|
+
CompositionProps,
|
|
489
|
+
C extends UiContract,
|
|
490
|
+
S extends ReadonlyArray<unknown>,
|
|
491
|
+
N extends string,
|
|
492
|
+
Identity,
|
|
493
|
+
OpenServices,
|
|
494
|
+
SupportOpenServices,
|
|
495
|
+
UsesInput extends boolean,
|
|
496
|
+
Input,
|
|
497
|
+
> = FeatureGraphSummary<
|
|
498
|
+
FeatureIdentity,
|
|
499
|
+
MountProps,
|
|
500
|
+
CompositionProps,
|
|
501
|
+
C,
|
|
502
|
+
S,
|
|
503
|
+
N,
|
|
504
|
+
Identity,
|
|
505
|
+
OpenServices,
|
|
506
|
+
SupportOpenServices,
|
|
507
|
+
UsesInput,
|
|
508
|
+
Input
|
|
509
|
+
>
|
|
510
|
+
|
|
511
|
+
export interface FeatureClass<
|
|
512
|
+
FeatureIdentity,
|
|
513
|
+
P,
|
|
514
|
+
C extends UiContract,
|
|
515
|
+
ROut,
|
|
516
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
517
|
+
OpenServices = DefaultFeatureOpenServices<ROut, DirectRequires>,
|
|
518
|
+
SupportOut = never,
|
|
519
|
+
SupportDirectRequires extends ReadonlyArray<FeatureRequirement> = readonly [],
|
|
520
|
+
SupportOpenServices = DefaultFeatureOpenServices<SupportOut, SupportDirectRequires>,
|
|
521
|
+
UsesInput extends boolean = false,
|
|
522
|
+
Input = UsesInput extends true ? P : never,
|
|
523
|
+
S extends ReadonlyArray<unknown> = ReadonlyArray<unknown>,
|
|
524
|
+
N extends string = RootCompositionName<ROut>,
|
|
525
|
+
CompositionProps = P,
|
|
526
|
+
Identity = RootCompositionIdentity<ROut>,
|
|
527
|
+
Composition extends CompositionClass<CompositionProps, C, S, N, Identity> = CompositionClass<
|
|
528
|
+
CompositionProps,
|
|
529
|
+
C,
|
|
530
|
+
S,
|
|
531
|
+
N,
|
|
532
|
+
Identity
|
|
533
|
+
>,
|
|
534
|
+
> extends FeatureDefinition<
|
|
535
|
+
FeatureIdentity,
|
|
536
|
+
FeatureSummaryOf<
|
|
537
|
+
FeatureIdentity,
|
|
538
|
+
P,
|
|
539
|
+
CompositionProps,
|
|
540
|
+
C,
|
|
541
|
+
S,
|
|
542
|
+
N,
|
|
543
|
+
Identity,
|
|
544
|
+
OpenServices,
|
|
545
|
+
SupportOpenServices,
|
|
546
|
+
UsesInput,
|
|
547
|
+
Input
|
|
548
|
+
>,
|
|
549
|
+
FeatureNativeTree<
|
|
550
|
+
FeatureSummaryOf<
|
|
551
|
+
FeatureIdentity,
|
|
552
|
+
P,
|
|
553
|
+
CompositionProps,
|
|
554
|
+
C,
|
|
555
|
+
S,
|
|
556
|
+
N,
|
|
557
|
+
Identity,
|
|
558
|
+
OpenServices,
|
|
559
|
+
SupportOpenServices,
|
|
560
|
+
UsesInput,
|
|
561
|
+
Input
|
|
562
|
+
>,
|
|
563
|
+
ROut,
|
|
564
|
+
DirectRequires,
|
|
565
|
+
SupportOut,
|
|
566
|
+
SupportDirectRequires,
|
|
567
|
+
Composition
|
|
568
|
+
>
|
|
569
|
+
> {}
|
|
570
|
+
|
|
571
|
+
export type EagerFeatureClass<
|
|
572
|
+
FeatureIdentity,
|
|
573
|
+
P,
|
|
574
|
+
C extends UiContract,
|
|
575
|
+
ROut,
|
|
576
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
577
|
+
OpenServices,
|
|
578
|
+
S extends ReadonlyArray<unknown>,
|
|
579
|
+
N extends string,
|
|
580
|
+
Identity,
|
|
581
|
+
Composition extends CompositionClass<P, C, S, N, Identity> = CompositionClass<
|
|
582
|
+
P,
|
|
583
|
+
C,
|
|
584
|
+
S,
|
|
585
|
+
N,
|
|
586
|
+
Identity
|
|
587
|
+
>,
|
|
588
|
+
> = FeatureDefinition<
|
|
589
|
+
FeatureIdentity,
|
|
590
|
+
FeatureSummaryOf<FeatureIdentity, P, P, C, S, N, Identity, OpenServices, never, false, never>,
|
|
591
|
+
EagerFeatureNativeTree<
|
|
592
|
+
FeatureSummaryOf<FeatureIdentity, P, P, C, S, N, Identity, OpenServices, never, false, never>,
|
|
593
|
+
ROut,
|
|
594
|
+
DirectRequires,
|
|
595
|
+
Composition
|
|
596
|
+
>
|
|
597
|
+
>
|
|
598
|
+
|
|
599
|
+
export type LazyFeatureClass<
|
|
600
|
+
FeatureIdentity,
|
|
601
|
+
P,
|
|
602
|
+
C extends UiContract,
|
|
603
|
+
ROut,
|
|
604
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
605
|
+
OpenServices,
|
|
606
|
+
SupportOut,
|
|
607
|
+
SupportDirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
608
|
+
SupportOpenServices,
|
|
609
|
+
UsesInput extends boolean,
|
|
610
|
+
S extends ReadonlyArray<unknown>,
|
|
611
|
+
N extends string,
|
|
612
|
+
CompositionProps,
|
|
613
|
+
Identity,
|
|
614
|
+
Composition extends CompositionClass<CompositionProps, C, S, N, Identity> = CompositionClass<
|
|
615
|
+
CompositionProps,
|
|
616
|
+
C,
|
|
617
|
+
S,
|
|
618
|
+
N,
|
|
619
|
+
Identity
|
|
620
|
+
>,
|
|
621
|
+
> = FeatureDefinition<
|
|
622
|
+
FeatureIdentity,
|
|
623
|
+
FeatureSummaryOf<
|
|
624
|
+
FeatureIdentity,
|
|
625
|
+
P,
|
|
626
|
+
CompositionProps,
|
|
627
|
+
C,
|
|
628
|
+
S,
|
|
629
|
+
N,
|
|
630
|
+
Identity,
|
|
631
|
+
OpenServices,
|
|
632
|
+
SupportOpenServices,
|
|
633
|
+
UsesInput,
|
|
634
|
+
UsesInput extends true ? P : never
|
|
635
|
+
>,
|
|
636
|
+
LazyFeatureNativeTree<
|
|
637
|
+
FeatureSummaryOf<
|
|
638
|
+
FeatureIdentity,
|
|
639
|
+
P,
|
|
640
|
+
CompositionProps,
|
|
641
|
+
C,
|
|
642
|
+
S,
|
|
643
|
+
N,
|
|
644
|
+
Identity,
|
|
645
|
+
OpenServices,
|
|
646
|
+
SupportOpenServices,
|
|
647
|
+
UsesInput,
|
|
648
|
+
UsesInput extends true ? P : never
|
|
649
|
+
>,
|
|
650
|
+
ROut,
|
|
651
|
+
DirectRequires,
|
|
652
|
+
SupportOut,
|
|
653
|
+
SupportDirectRequires,
|
|
654
|
+
Composition
|
|
655
|
+
>
|
|
135
656
|
>
|
|
136
657
|
|
|
137
|
-
|
|
658
|
+
interface RuntimeFeatureTree {
|
|
659
|
+
readonly composition: AnyComposition
|
|
660
|
+
readonly load: Effect.Effect<AnyLoadedModule, FeatureLoadFailed>
|
|
661
|
+
readonly binding: AnyFeatureBinding
|
|
662
|
+
readonly eagerModule: AnyLoadedModule | undefined
|
|
663
|
+
readonly supportModule: AnyLoadedModule | undefined
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
interface RuntimeFeature {
|
|
667
|
+
new (): {}
|
|
668
|
+
readonly manifest: FeatureManifest
|
|
669
|
+
readonly token: FeatureToken<unknown, RuntimeFeatureTree>
|
|
670
|
+
readonly summary: AnyFeatureGraphSummary
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
const isRuntimeFeatureToken = (
|
|
674
|
+
candidate: unknown,
|
|
675
|
+
): candidate is FeatureToken<unknown, RuntimeFeatureTree> =>
|
|
676
|
+
typeof candidate === 'object' && candidate !== null && FeatureNativeTypeId in candidate
|
|
677
|
+
|
|
678
|
+
export const isFeature = (candidate: unknown): candidate is RuntimeFeature =>
|
|
138
679
|
(typeof candidate === 'function' || typeof candidate === 'object') &&
|
|
139
680
|
candidate !== null &&
|
|
140
|
-
'
|
|
141
|
-
|
|
142
|
-
candidate.manifest !== null &&
|
|
143
|
-
'kind' in candidate.manifest &&
|
|
144
|
-
candidate.manifest.kind === 'Feature'
|
|
681
|
+
'token' in candidate &&
|
|
682
|
+
isRuntimeFeatureToken(candidate.token)
|
|
145
683
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
684
|
+
type PlaceholderComposition<P> = AnyComposition & CompositionPropsReceiver<P>
|
|
685
|
+
|
|
686
|
+
export interface Placeholders<P> {
|
|
687
|
+
readonly loading: PlaceholderComposition<P>
|
|
688
|
+
readonly failed: PlaceholderComposition<FailedProps>
|
|
149
689
|
}
|
|
150
690
|
|
|
151
|
-
|
|
152
|
-
|
|
691
|
+
export type FeatureMountProps<
|
|
692
|
+
UsesInput extends boolean,
|
|
693
|
+
CompositionProps,
|
|
694
|
+
InputSchema extends Schema.Schema.AnyNoContext,
|
|
695
|
+
> = UsesInput extends true ? Schema.Schema.Type<InputSchema> : CompositionProps
|
|
696
|
+
|
|
697
|
+
type FeatureUsesInput<InputSchema extends Schema.Schema.AnyNoContext> = [InputSchema] extends [
|
|
698
|
+
never,
|
|
699
|
+
]
|
|
700
|
+
? false
|
|
701
|
+
: true
|
|
702
|
+
|
|
703
|
+
type FeatureInputValue<InputSchema extends Schema.Schema.AnyNoContext> = [InputSchema] extends [
|
|
704
|
+
never,
|
|
705
|
+
]
|
|
706
|
+
? never
|
|
707
|
+
: Schema.Schema.Type<InputSchema>
|
|
708
|
+
|
|
709
|
+
interface FeatureConfigBaseExternalApi<
|
|
710
|
+
P,
|
|
711
|
+
C extends UiContract,
|
|
712
|
+
S extends ReadonlyArray<unknown>,
|
|
713
|
+
N extends string,
|
|
714
|
+
Identity,
|
|
715
|
+
> {
|
|
716
|
+
readonly composition: CompositionClass<P, C, S, N, Identity>
|
|
153
717
|
readonly boot?: ReadonlyArray<Tagged>
|
|
154
718
|
}
|
|
155
719
|
|
|
720
|
+
interface ExactFeatureCompositionConfig<Composition extends AnyComposition> {
|
|
721
|
+
readonly composition: Composition
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
type IncludesComposition<ROut, N extends string, Identity> =
|
|
725
|
+
HasExactCompositionId<ROut, N, Identity> extends true
|
|
726
|
+
? object
|
|
727
|
+
: {
|
|
728
|
+
readonly missingCompositionService: 'The feature module must provide its root composition'
|
|
729
|
+
}
|
|
730
|
+
|
|
156
731
|
type EagerFeatureConfigExternalApi<
|
|
157
732
|
P,
|
|
158
733
|
C extends UiContract,
|
|
159
734
|
ROut,
|
|
160
|
-
|
|
161
|
-
|
|
735
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
736
|
+
OpenServices,
|
|
737
|
+
S extends ReadonlyArray<unknown>,
|
|
738
|
+
N extends string,
|
|
739
|
+
Identity,
|
|
740
|
+
> = FeatureConfigBaseExternalApi<P, C, S, N, Identity> & {
|
|
162
741
|
readonly loadingStrategy?: 'default'
|
|
163
|
-
readonly module: FeatureModule<ROut,
|
|
742
|
+
readonly module: FeatureModule<ROut, DirectRequires, OpenServices, false, never> &
|
|
743
|
+
IncludesComposition<ROut, N, Identity>
|
|
164
744
|
}
|
|
165
745
|
|
|
166
746
|
type LazyFeatureConfigExternalApi<
|
|
167
|
-
|
|
747
|
+
CompositionProps,
|
|
168
748
|
C extends UiContract,
|
|
169
749
|
ROut,
|
|
170
|
-
|
|
750
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
751
|
+
OpenServices,
|
|
171
752
|
SupportOut,
|
|
172
|
-
|
|
173
|
-
|
|
753
|
+
SupportDirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
754
|
+
SupportOpenServices,
|
|
755
|
+
S extends ReadonlyArray<unknown>,
|
|
756
|
+
N extends string,
|
|
757
|
+
Identity,
|
|
758
|
+
InputSchema extends Schema.Schema.AnyNoContext,
|
|
759
|
+
Loading extends AnyComposition,
|
|
760
|
+
Failed extends AnyComposition,
|
|
761
|
+
> = FeatureConfigBaseExternalApi<CompositionProps, C, S, N, Identity> & {
|
|
762
|
+
readonly composition: CompositionClass<CompositionProps, C, S, N, Identity> &
|
|
763
|
+
CompositionPropsReceiver<
|
|
764
|
+
NoInfer<FeatureMountProps<FeatureUsesInput<InputSchema>, CompositionProps, InputSchema>>
|
|
765
|
+
>
|
|
174
766
|
readonly loadingStrategy: 'lazy'
|
|
175
|
-
readonly
|
|
176
|
-
readonly
|
|
177
|
-
|
|
767
|
+
readonly input?: InputSchema
|
|
768
|
+
readonly load: Effect.Effect<
|
|
769
|
+
FeatureModule<
|
|
770
|
+
ROut,
|
|
771
|
+
DirectRequires,
|
|
772
|
+
OpenServices,
|
|
773
|
+
FeatureUsesInput<InputSchema>,
|
|
774
|
+
FeatureInputValue<InputSchema>
|
|
775
|
+
> &
|
|
776
|
+
IncludesComposition<ROut, N, Identity>,
|
|
777
|
+
FeatureLoadFailed
|
|
778
|
+
>
|
|
779
|
+
readonly placeholder: {
|
|
780
|
+
readonly loading: Loading &
|
|
781
|
+
CompositionPropsReceiver<
|
|
782
|
+
NoInfer<FeatureMountProps<FeatureUsesInput<InputSchema>, CompositionProps, InputSchema>>
|
|
783
|
+
>
|
|
784
|
+
readonly failed: Failed & CompositionPropsReceiver<FailedProps>
|
|
785
|
+
}
|
|
786
|
+
readonly eager?: FeatureModule<
|
|
787
|
+
SupportOut,
|
|
788
|
+
SupportDirectRequires,
|
|
789
|
+
SupportOpenServices,
|
|
790
|
+
false,
|
|
791
|
+
never
|
|
792
|
+
>
|
|
793
|
+
} & (FeatureUsesInput<InputSchema> extends true ? { readonly input: InputSchema } : object)
|
|
794
|
+
|
|
795
|
+
type MakeImplementationConfigExternalApi =
|
|
796
|
+
| {
|
|
797
|
+
readonly composition: AnyComposition
|
|
798
|
+
readonly boot?: ReadonlyArray<Tagged>
|
|
799
|
+
readonly loadingStrategy?: 'default'
|
|
800
|
+
readonly module: AnyLoadedModule
|
|
801
|
+
}
|
|
802
|
+
| {
|
|
803
|
+
readonly composition: AnyComposition
|
|
804
|
+
readonly boot?: ReadonlyArray<Tagged>
|
|
805
|
+
readonly loadingStrategy: 'lazy'
|
|
806
|
+
readonly input?: Schema.Schema.Any
|
|
807
|
+
readonly load: Effect.Effect<AnyLoadedModule, FeatureLoadFailed>
|
|
808
|
+
readonly placeholder: {
|
|
809
|
+
readonly loading: AnyComposition
|
|
810
|
+
readonly failed: AnyComposition
|
|
811
|
+
}
|
|
812
|
+
readonly eager?: AnyLoadedModule
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
const isMakeImplementationConfig = (
|
|
816
|
+
candidate: unknown,
|
|
817
|
+
): candidate is MakeImplementationConfigExternalApi =>
|
|
818
|
+
typeof candidate === 'object' &&
|
|
819
|
+
candidate !== null &&
|
|
820
|
+
'composition' in candidate &&
|
|
821
|
+
(!('input' in candidate) || Schema.isSchema(candidate.input)) &&
|
|
822
|
+
('module' in candidate || ('load' in candidate && 'placeholder' in candidate))
|
|
823
|
+
|
|
824
|
+
type RuntimePlaceholders = {
|
|
825
|
+
readonly loading: AnyComposition
|
|
826
|
+
readonly failed: AnyComposition
|
|
178
827
|
}
|
|
179
828
|
|
|
180
|
-
|
|
829
|
+
const makeFeatureManifest = (
|
|
830
|
+
name: string,
|
|
831
|
+
strategy: 'lazy' | 'default',
|
|
832
|
+
composition: AnyComposition,
|
|
833
|
+
placeholder: Option.Option<RuntimePlaceholders>,
|
|
834
|
+
): FeatureManifest => ({
|
|
835
|
+
kind: 'Feature',
|
|
836
|
+
name,
|
|
837
|
+
strategy,
|
|
838
|
+
composition: composition.manifest,
|
|
839
|
+
placeholder: Option.map(placeholder, (placeholders) => ({
|
|
840
|
+
loading: placeholders.loading.manifest,
|
|
841
|
+
failed: placeholders.failed.manifest,
|
|
842
|
+
})),
|
|
843
|
+
})
|
|
844
|
+
|
|
845
|
+
const makeFeatureInputParser =
|
|
846
|
+
(
|
|
847
|
+
composition: AnyComposition,
|
|
848
|
+
inputSchema: Schema.Schema.AnyNoContext | undefined,
|
|
849
|
+
placeholder: Option.Option<RuntimePlaceholders>,
|
|
850
|
+
): ((input: unknown) => Option.Option<unknown>) =>
|
|
851
|
+
(input) =>
|
|
852
|
+
Option.flatMap(
|
|
853
|
+
Option.match(Option.fromNullable(inputSchema), {
|
|
854
|
+
onNone: () => Option.some(input),
|
|
855
|
+
onSome: (schema) => Schema.validateOption(schema)(input),
|
|
856
|
+
}),
|
|
857
|
+
(decoded) =>
|
|
858
|
+
Option.flatMap(composition.parseProps(decoded), () =>
|
|
859
|
+
Option.match(placeholder, {
|
|
860
|
+
onNone: () => Option.some(decoded),
|
|
861
|
+
onSome: (placeholders) =>
|
|
862
|
+
Option.map(placeholders.loading.parseProps(decoded), () => decoded),
|
|
863
|
+
}),
|
|
864
|
+
),
|
|
865
|
+
)
|
|
866
|
+
|
|
867
|
+
const makeFeatureSummary = <
|
|
868
|
+
FeatureIdentity,
|
|
869
|
+
MountProps,
|
|
870
|
+
CompositionProps,
|
|
871
|
+
C extends UiContract,
|
|
872
|
+
S extends ReadonlyArray<unknown>,
|
|
873
|
+
N extends string,
|
|
874
|
+
Identity,
|
|
875
|
+
OpenServices,
|
|
876
|
+
SupportOpenServices,
|
|
877
|
+
UsesInput extends boolean,
|
|
878
|
+
Input,
|
|
879
|
+
>(
|
|
880
|
+
composition: CompositionClass<CompositionProps, C, S, N, Identity>,
|
|
881
|
+
): FeatureSummaryOf<
|
|
882
|
+
FeatureIdentity,
|
|
883
|
+
MountProps,
|
|
884
|
+
CompositionProps,
|
|
885
|
+
C,
|
|
886
|
+
S,
|
|
887
|
+
N,
|
|
888
|
+
Identity,
|
|
889
|
+
OpenServices,
|
|
890
|
+
SupportOpenServices,
|
|
891
|
+
UsesInput,
|
|
892
|
+
Input
|
|
893
|
+
> => ({
|
|
894
|
+
[SlotBindingSummaryTypeId]: SlotBindingSummaryTypeId,
|
|
895
|
+
[FeatureChildSummaryTypeId]: {
|
|
896
|
+
featureIdentity: [],
|
|
897
|
+
compositionIdentity: [],
|
|
898
|
+
},
|
|
899
|
+
[FeatureGraphSummaryTypeId]: {
|
|
900
|
+
featureIdentity: [],
|
|
901
|
+
mountProps: [],
|
|
902
|
+
compositionProps: [],
|
|
903
|
+
contract: [],
|
|
904
|
+
states: [],
|
|
905
|
+
name: composition.manifest.name,
|
|
906
|
+
compositionIdentity: [],
|
|
907
|
+
openServices: [],
|
|
908
|
+
supportOpenServices: [],
|
|
909
|
+
usesInput: [],
|
|
910
|
+
input: [],
|
|
911
|
+
validated: FeatureModuleGraphValidTypeId,
|
|
912
|
+
},
|
|
913
|
+
})
|
|
914
|
+
|
|
915
|
+
const makeFeatureBinding = <
|
|
916
|
+
Summary extends AnyFeatureGraphSummary,
|
|
917
|
+
ROut,
|
|
918
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
919
|
+
>(
|
|
920
|
+
identity: symbol,
|
|
921
|
+
manifest: FeatureManifest,
|
|
922
|
+
summary: Summary,
|
|
923
|
+
composition: CompositionClass<
|
|
924
|
+
FeatureSummaryCompositionProps<Summary>,
|
|
925
|
+
FeatureSummaryContract<Summary>,
|
|
926
|
+
FeatureSummaryStates<Summary>,
|
|
927
|
+
FeatureSummaryName<Summary>,
|
|
928
|
+
FeatureSummaryCompositionIdentity<Summary>
|
|
929
|
+
>,
|
|
930
|
+
load: Effect.Effect<
|
|
931
|
+
LoadedModule<
|
|
932
|
+
ROut,
|
|
933
|
+
DirectRequires,
|
|
934
|
+
FeatureSummaryOpenServices<Summary>,
|
|
935
|
+
FeatureSummaryUsesInput<Summary>,
|
|
936
|
+
FeatureSummaryInput<Summary>
|
|
937
|
+
>,
|
|
938
|
+
FeatureLoadFailed
|
|
939
|
+
>,
|
|
940
|
+
placeholder: Option.Option<RuntimePlaceholders>,
|
|
941
|
+
inputSchema: Schema.Schema.AnyNoContext | undefined,
|
|
942
|
+
boot: ReadonlyArray<Tagged>,
|
|
943
|
+
): FeatureBinding<Summary, ROut, DirectRequires> => {
|
|
944
|
+
const binding: FeatureBinding<Summary, ROut, DirectRequires> = {
|
|
945
|
+
[FeatureBindingTypeId]: FeatureBindingTypeId,
|
|
946
|
+
[FeatureGraphValidTypeId]: FeatureGraphValidTypeId,
|
|
947
|
+
manifest,
|
|
948
|
+
identity,
|
|
949
|
+
summary,
|
|
950
|
+
composition,
|
|
951
|
+
strategy: manifest.strategy,
|
|
952
|
+
load,
|
|
953
|
+
placeholder,
|
|
954
|
+
parseInput: makeFeatureInputParser(composition, inputSchema, placeholder),
|
|
955
|
+
boot,
|
|
956
|
+
capture: <Result>(visit: FeatureBindingCapture<Result>): Result => visit(binding),
|
|
957
|
+
}
|
|
958
|
+
return binding
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
const makeEagerFeature = <
|
|
181
962
|
P,
|
|
182
963
|
C extends UiContract,
|
|
183
964
|
ROut,
|
|
184
|
-
|
|
965
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
966
|
+
OpenServices,
|
|
967
|
+
S extends ReadonlyArray<unknown>,
|
|
968
|
+
N extends string,
|
|
969
|
+
Identity,
|
|
970
|
+
Composition extends CompositionClass<P, C, S, N, Identity>,
|
|
185
971
|
>(
|
|
186
972
|
name: string,
|
|
187
|
-
config: EagerFeatureConfigExternalApi<P, C, ROut,
|
|
188
|
-
|
|
189
|
-
|
|
973
|
+
config: EagerFeatureConfigExternalApi<P, C, ROut, DirectRequires, OpenServices, S, N, Identity> &
|
|
974
|
+
ExactFeatureCompositionConfig<Composition>,
|
|
975
|
+
): EagerFeatureClass<
|
|
976
|
+
Identity,
|
|
190
977
|
P,
|
|
978
|
+
C,
|
|
979
|
+
ROut,
|
|
980
|
+
DirectRequires,
|
|
981
|
+
OpenServices,
|
|
982
|
+
S,
|
|
983
|
+
N,
|
|
984
|
+
Identity,
|
|
985
|
+
Composition
|
|
986
|
+
> => {
|
|
987
|
+
const featureIdentity = Symbol(name)
|
|
988
|
+
const placeholder = Option.none<RuntimePlaceholders>()
|
|
989
|
+
const manifest = makeFeatureManifest(name, 'default', config.composition, placeholder)
|
|
990
|
+
const load = Effect.succeed(config.module)
|
|
991
|
+
const summary = makeFeatureSummary<
|
|
992
|
+
Identity,
|
|
993
|
+
P,
|
|
994
|
+
P,
|
|
995
|
+
C,
|
|
996
|
+
S,
|
|
997
|
+
N,
|
|
998
|
+
Identity,
|
|
999
|
+
OpenServices,
|
|
1000
|
+
never,
|
|
1001
|
+
false,
|
|
1002
|
+
never
|
|
1003
|
+
>(config.composition)
|
|
1004
|
+
const binding = makeFeatureBinding<typeof summary, ROut, DirectRequires>(
|
|
1005
|
+
featureIdentity,
|
|
1006
|
+
manifest,
|
|
1007
|
+
summary,
|
|
1008
|
+
config.composition,
|
|
1009
|
+
load,
|
|
1010
|
+
placeholder,
|
|
1011
|
+
undefined,
|
|
1012
|
+
Option.getOrElse(Option.fromNullable(config.boot), () => []),
|
|
1013
|
+
)
|
|
1014
|
+
const native: EagerFeatureNativeTree<typeof summary, ROut, DirectRequires, Composition> = {
|
|
1015
|
+
identity: featureIdentity,
|
|
1016
|
+
summary,
|
|
1017
|
+
composition: config.composition,
|
|
1018
|
+
load,
|
|
1019
|
+
binding,
|
|
1020
|
+
eagerModule: config.module,
|
|
1021
|
+
supportModule: undefined,
|
|
1022
|
+
}
|
|
1023
|
+
const token: FeatureToken<Identity, typeof native> = {
|
|
1024
|
+
identity: featureIdentity,
|
|
1025
|
+
[FeatureTokenIdentityTypeId]: [],
|
|
1026
|
+
[FeatureNativeTypeId]: native,
|
|
1027
|
+
}
|
|
1028
|
+
return definitionClass<
|
|
1029
|
+
EagerFeatureClass<
|
|
1030
|
+
Identity,
|
|
1031
|
+
P,
|
|
1032
|
+
C,
|
|
1033
|
+
ROut,
|
|
1034
|
+
DirectRequires,
|
|
1035
|
+
OpenServices,
|
|
1036
|
+
S,
|
|
1037
|
+
N,
|
|
1038
|
+
Identity,
|
|
1039
|
+
Composition
|
|
1040
|
+
>
|
|
1041
|
+
>({
|
|
1042
|
+
manifest,
|
|
1043
|
+
summary,
|
|
1044
|
+
token,
|
|
1045
|
+
})
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
const makeLazyFeature = <
|
|
1049
|
+
CompositionProps,
|
|
191
1050
|
C extends UiContract,
|
|
192
1051
|
ROut,
|
|
193
|
-
|
|
1052
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
1053
|
+
OpenServices,
|
|
194
1054
|
SupportOut,
|
|
195
|
-
|
|
1055
|
+
SupportDirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
1056
|
+
SupportOpenServices,
|
|
1057
|
+
S extends ReadonlyArray<unknown>,
|
|
1058
|
+
N extends string,
|
|
1059
|
+
Identity,
|
|
1060
|
+
Composition extends CompositionClass<CompositionProps, C, S, N, Identity>,
|
|
1061
|
+
InputSchema extends Schema.Schema.AnyNoContext,
|
|
1062
|
+
Loading extends AnyComposition,
|
|
1063
|
+
Failed extends AnyComposition,
|
|
196
1064
|
>(
|
|
197
1065
|
name: string,
|
|
198
1066
|
config: LazyFeatureConfigExternalApi<
|
|
199
|
-
|
|
1067
|
+
CompositionProps,
|
|
1068
|
+
C,
|
|
1069
|
+
ROut,
|
|
1070
|
+
DirectRequires,
|
|
1071
|
+
OpenServices,
|
|
1072
|
+
SupportOut,
|
|
1073
|
+
SupportDirectRequires,
|
|
1074
|
+
SupportOpenServices,
|
|
1075
|
+
S,
|
|
1076
|
+
N,
|
|
1077
|
+
Identity,
|
|
1078
|
+
InputSchema,
|
|
1079
|
+
Loading,
|
|
1080
|
+
Failed
|
|
1081
|
+
> &
|
|
1082
|
+
ExactFeatureCompositionConfig<Composition>,
|
|
1083
|
+
): LazyFeatureClass<
|
|
1084
|
+
Identity,
|
|
1085
|
+
FeatureMountProps<FeatureUsesInput<InputSchema>, CompositionProps, InputSchema>,
|
|
1086
|
+
C,
|
|
1087
|
+
ROut,
|
|
1088
|
+
DirectRequires,
|
|
1089
|
+
OpenServices,
|
|
1090
|
+
SupportOut,
|
|
1091
|
+
SupportDirectRequires,
|
|
1092
|
+
SupportOpenServices,
|
|
1093
|
+
FeatureUsesInput<InputSchema>,
|
|
1094
|
+
S,
|
|
1095
|
+
N,
|
|
1096
|
+
CompositionProps,
|
|
1097
|
+
Identity,
|
|
1098
|
+
Composition
|
|
1099
|
+
> => {
|
|
1100
|
+
const featureIdentity = Symbol(name)
|
|
1101
|
+
const placeholder = Option.some<RuntimePlaceholders>(config.placeholder)
|
|
1102
|
+
const manifest = makeFeatureManifest(name, 'lazy', config.composition, placeholder)
|
|
1103
|
+
const inputSchema = 'input' in config ? config.input : undefined
|
|
1104
|
+
const summary = makeFeatureSummary<
|
|
1105
|
+
Identity,
|
|
1106
|
+
FeatureMountProps<FeatureUsesInput<InputSchema>, CompositionProps, InputSchema>,
|
|
1107
|
+
CompositionProps,
|
|
200
1108
|
C,
|
|
1109
|
+
S,
|
|
1110
|
+
N,
|
|
1111
|
+
Identity,
|
|
1112
|
+
OpenServices,
|
|
1113
|
+
SupportOpenServices,
|
|
1114
|
+
FeatureUsesInput<InputSchema>,
|
|
1115
|
+
FeatureInputValue<InputSchema>
|
|
1116
|
+
>(config.composition)
|
|
1117
|
+
const binding = makeFeatureBinding<typeof summary, ROut, DirectRequires>(
|
|
1118
|
+
featureIdentity,
|
|
1119
|
+
manifest,
|
|
1120
|
+
summary,
|
|
1121
|
+
config.composition,
|
|
1122
|
+
config.load,
|
|
1123
|
+
placeholder,
|
|
1124
|
+
inputSchema,
|
|
1125
|
+
Option.getOrElse(Option.fromNullable(config.boot), () => []),
|
|
1126
|
+
)
|
|
1127
|
+
const native: LazyFeatureNativeTree<
|
|
1128
|
+
typeof summary,
|
|
201
1129
|
ROut,
|
|
202
|
-
|
|
1130
|
+
DirectRequires,
|
|
203
1131
|
SupportOut,
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
1132
|
+
SupportDirectRequires,
|
|
1133
|
+
Composition
|
|
1134
|
+
> = {
|
|
1135
|
+
identity: featureIdentity,
|
|
1136
|
+
summary,
|
|
1137
|
+
composition: config.composition,
|
|
1138
|
+
load: config.load,
|
|
1139
|
+
binding,
|
|
1140
|
+
eagerModule: undefined,
|
|
1141
|
+
supportModule: config.eager,
|
|
1142
|
+
}
|
|
1143
|
+
const token: FeatureToken<Identity, typeof native> = {
|
|
1144
|
+
identity: featureIdentity,
|
|
1145
|
+
[FeatureTokenIdentityTypeId]: [],
|
|
1146
|
+
[FeatureNativeTypeId]: native,
|
|
1147
|
+
}
|
|
1148
|
+
return definitionClass<
|
|
1149
|
+
LazyFeatureClass<
|
|
1150
|
+
Identity,
|
|
1151
|
+
FeatureMountProps<FeatureUsesInput<InputSchema>, CompositionProps, InputSchema>,
|
|
1152
|
+
C,
|
|
1153
|
+
ROut,
|
|
1154
|
+
DirectRequires,
|
|
1155
|
+
OpenServices,
|
|
1156
|
+
SupportOut,
|
|
1157
|
+
SupportDirectRequires,
|
|
1158
|
+
SupportOpenServices,
|
|
1159
|
+
FeatureUsesInput<InputSchema>,
|
|
1160
|
+
S,
|
|
1161
|
+
N,
|
|
1162
|
+
CompositionProps,
|
|
1163
|
+
Identity,
|
|
1164
|
+
Composition
|
|
1165
|
+
>
|
|
1166
|
+
>({
|
|
1167
|
+
manifest,
|
|
1168
|
+
summary,
|
|
1169
|
+
token,
|
|
1170
|
+
})
|
|
1171
|
+
}
|
|
1172
|
+
|
|
207
1173
|
export function make<
|
|
208
1174
|
P,
|
|
209
1175
|
C extends UiContract,
|
|
210
1176
|
ROut,
|
|
211
|
-
|
|
1177
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
1178
|
+
OpenServices,
|
|
1179
|
+
S extends ReadonlyArray<unknown>,
|
|
1180
|
+
N extends string,
|
|
1181
|
+
Identity,
|
|
1182
|
+
const Composition extends CompositionClass<P, C, S, N, Identity>,
|
|
212
1183
|
>(
|
|
213
1184
|
name: string,
|
|
214
|
-
config:
|
|
215
|
-
|
|
216
|
-
|
|
1185
|
+
config: EagerFeatureConfigExternalApi<
|
|
1186
|
+
P,
|
|
1187
|
+
C,
|
|
1188
|
+
ROut,
|
|
1189
|
+
DirectRequires,
|
|
1190
|
+
OpenServices,
|
|
1191
|
+
S,
|
|
1192
|
+
N,
|
|
1193
|
+
Identity
|
|
1194
|
+
> & { readonly composition: Composition },
|
|
1195
|
+
): EagerFeatureClass<
|
|
1196
|
+
Identity,
|
|
1197
|
+
P,
|
|
1198
|
+
C,
|
|
1199
|
+
ROut,
|
|
1200
|
+
DirectRequires,
|
|
1201
|
+
OpenServices,
|
|
1202
|
+
S,
|
|
1203
|
+
N,
|
|
1204
|
+
Identity,
|
|
1205
|
+
Composition
|
|
1206
|
+
>
|
|
1207
|
+
export function make<
|
|
1208
|
+
CompositionProps,
|
|
1209
|
+
C extends UiContract,
|
|
1210
|
+
ROut,
|
|
1211
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
1212
|
+
OpenServices,
|
|
1213
|
+
S extends ReadonlyArray<unknown>,
|
|
1214
|
+
N extends string,
|
|
1215
|
+
Identity,
|
|
1216
|
+
const Composition extends CompositionClass<CompositionProps, C, S, N, Identity>,
|
|
1217
|
+
const Loading extends AnyComposition,
|
|
1218
|
+
const Failed extends AnyComposition,
|
|
1219
|
+
const InputSchema extends Schema.Schema.AnyNoContext = never,
|
|
1220
|
+
SupportOut = never,
|
|
1221
|
+
SupportDirectRequires extends ReadonlyArray<FeatureRequirement> = readonly [],
|
|
1222
|
+
SupportOpenServices = never,
|
|
1223
|
+
>(
|
|
217
1224
|
name: string,
|
|
218
|
-
config:
|
|
1225
|
+
config: LazyFeatureConfigExternalApi<
|
|
1226
|
+
CompositionProps,
|
|
1227
|
+
C,
|
|
1228
|
+
ROut,
|
|
1229
|
+
DirectRequires,
|
|
1230
|
+
OpenServices,
|
|
1231
|
+
SupportOut,
|
|
1232
|
+
SupportDirectRequires,
|
|
1233
|
+
SupportOpenServices,
|
|
1234
|
+
S,
|
|
1235
|
+
N,
|
|
1236
|
+
Identity,
|
|
1237
|
+
InputSchema,
|
|
1238
|
+
Loading,
|
|
1239
|
+
Failed
|
|
1240
|
+
> & { readonly composition: Composition },
|
|
1241
|
+
): LazyFeatureClass<
|
|
1242
|
+
Identity,
|
|
1243
|
+
FeatureMountProps<FeatureUsesInput<InputSchema>, CompositionProps, InputSchema>,
|
|
1244
|
+
C,
|
|
1245
|
+
ROut,
|
|
1246
|
+
DirectRequires,
|
|
1247
|
+
OpenServices,
|
|
1248
|
+
SupportOut,
|
|
1249
|
+
SupportDirectRequires,
|
|
1250
|
+
SupportOpenServices,
|
|
1251
|
+
FeatureUsesInput<InputSchema>,
|
|
1252
|
+
S,
|
|
1253
|
+
N,
|
|
1254
|
+
CompositionProps,
|
|
1255
|
+
Identity,
|
|
1256
|
+
Composition
|
|
1257
|
+
>
|
|
1258
|
+
export function make<
|
|
1259
|
+
CompositionProps,
|
|
1260
|
+
C extends UiContract,
|
|
1261
|
+
ROut,
|
|
1262
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
1263
|
+
OpenServices,
|
|
1264
|
+
S extends ReadonlyArray<unknown>,
|
|
1265
|
+
N extends string,
|
|
1266
|
+
Identity,
|
|
1267
|
+
Composition extends CompositionClass<CompositionProps, C, S, N, Identity>,
|
|
1268
|
+
Loading extends AnyComposition,
|
|
1269
|
+
Failed extends AnyComposition,
|
|
1270
|
+
InputSchema extends Schema.Schema.AnyNoContext = never,
|
|
1271
|
+
SupportOut = never,
|
|
1272
|
+
SupportDirectRequires extends ReadonlyArray<FeatureRequirement> = readonly [],
|
|
1273
|
+
SupportOpenServices = never,
|
|
1274
|
+
>(
|
|
1275
|
+
name: string,
|
|
1276
|
+
config: (
|
|
219
1277
|
| EagerFeatureConfigExternalApi<
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
1278
|
+
CompositionProps,
|
|
1279
|
+
C,
|
|
1280
|
+
ROut,
|
|
1281
|
+
DirectRequires,
|
|
1282
|
+
OpenServices,
|
|
1283
|
+
S,
|
|
1284
|
+
N,
|
|
1285
|
+
Identity
|
|
224
1286
|
>
|
|
225
1287
|
| LazyFeatureConfigExternalApi<
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
1288
|
+
CompositionProps,
|
|
1289
|
+
C,
|
|
1290
|
+
ROut,
|
|
1291
|
+
DirectRequires,
|
|
1292
|
+
OpenServices,
|
|
1293
|
+
SupportOut,
|
|
1294
|
+
SupportDirectRequires,
|
|
1295
|
+
SupportOpenServices,
|
|
1296
|
+
S,
|
|
1297
|
+
N,
|
|
1298
|
+
Identity,
|
|
1299
|
+
InputSchema,
|
|
1300
|
+
Loading,
|
|
1301
|
+
Failed
|
|
1302
|
+
>
|
|
1303
|
+
) &
|
|
1304
|
+
ExactFeatureCompositionConfig<Composition>,
|
|
1305
|
+
):
|
|
1306
|
+
| EagerFeatureClass<
|
|
1307
|
+
Identity,
|
|
1308
|
+
CompositionProps,
|
|
1309
|
+
C,
|
|
1310
|
+
ROut,
|
|
1311
|
+
DirectRequires,
|
|
1312
|
+
OpenServices,
|
|
1313
|
+
S,
|
|
1314
|
+
N,
|
|
1315
|
+
Identity,
|
|
1316
|
+
Composition
|
|
1317
|
+
>
|
|
1318
|
+
| LazyFeatureClass<
|
|
1319
|
+
Identity,
|
|
1320
|
+
FeatureMountProps<FeatureUsesInput<InputSchema>, CompositionProps, InputSchema>,
|
|
1321
|
+
C,
|
|
1322
|
+
ROut,
|
|
1323
|
+
DirectRequires,
|
|
1324
|
+
OpenServices,
|
|
1325
|
+
SupportOut,
|
|
1326
|
+
SupportDirectRequires,
|
|
1327
|
+
SupportOpenServices,
|
|
1328
|
+
FeatureUsesInput<InputSchema>,
|
|
1329
|
+
S,
|
|
1330
|
+
N,
|
|
1331
|
+
CompositionProps,
|
|
1332
|
+
Identity,
|
|
1333
|
+
Composition
|
|
1334
|
+
> {
|
|
1335
|
+
if (!isMakeImplementationConfig(config)) {
|
|
1336
|
+
return Effect.runSync(Effect.dieMessage(`Invalid Feature config for ${name}`))
|
|
251
1337
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
1338
|
+
if (config.loadingStrategy === 'lazy') {
|
|
1339
|
+
return makeLazyFeature<
|
|
1340
|
+
CompositionProps,
|
|
1341
|
+
C,
|
|
1342
|
+
ROut,
|
|
1343
|
+
DirectRequires,
|
|
1344
|
+
OpenServices,
|
|
1345
|
+
SupportOut,
|
|
1346
|
+
SupportDirectRequires,
|
|
1347
|
+
SupportOpenServices,
|
|
1348
|
+
S,
|
|
1349
|
+
N,
|
|
1350
|
+
Identity,
|
|
1351
|
+
Composition,
|
|
1352
|
+
InputSchema,
|
|
1353
|
+
Loading,
|
|
1354
|
+
Failed
|
|
1355
|
+
>(name, config)
|
|
261
1356
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
1357
|
+
return makeEagerFeature<
|
|
1358
|
+
CompositionProps,
|
|
1359
|
+
C,
|
|
1360
|
+
ROut,
|
|
1361
|
+
DirectRequires,
|
|
1362
|
+
OpenServices,
|
|
1363
|
+
S,
|
|
1364
|
+
N,
|
|
1365
|
+
Identity,
|
|
1366
|
+
Composition
|
|
1367
|
+
>(name, config)
|
|
271
1368
|
}
|
|
272
1369
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
1370
|
+
type MountFeature = <
|
|
1371
|
+
Summary extends AnyFeatureGraphSummary,
|
|
1372
|
+
ROut,
|
|
1373
|
+
const DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
1374
|
+
HostServices,
|
|
1375
|
+
>(
|
|
1376
|
+
binding: FeatureBinding<Summary, ROut, DirectRequires>,
|
|
1377
|
+
engineContext: Context.Context<
|
|
1378
|
+
HostServices | EngineServices | FeatureSummaryOpenServices<Summary>
|
|
1379
|
+
>,
|
|
1380
|
+
props?: FeatureSummaryInput<Summary>,
|
|
1381
|
+
) => Effect.Effect<
|
|
1382
|
+
Context.Context<HostServices | EngineServices | FeatureSummaryOpenServices<Summary> | ROut>,
|
|
1383
|
+
FeatureLoadFailed,
|
|
1384
|
+
Scope.Scope
|
|
1385
|
+
>
|
|
1386
|
+
|
|
1387
|
+
export const mountFeature: MountFeature = Effect.fn('mountFeature')(function* <
|
|
1388
|
+
Summary extends AnyFeatureGraphSummary,
|
|
1389
|
+
ROut,
|
|
1390
|
+
const DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
1391
|
+
HostServices,
|
|
1392
|
+
>(
|
|
1393
|
+
binding: FeatureBinding<Summary, ROut, DirectRequires>,
|
|
1394
|
+
engineContext: Context.Context<
|
|
1395
|
+
HostServices | EngineServices | FeatureSummaryOpenServices<Summary>
|
|
1396
|
+
>,
|
|
1397
|
+
props: FeatureSummaryInput<Summary> | undefined = undefined,
|
|
1398
|
+
): Effect.fn.Return<
|
|
1399
|
+
Context.Context<HostServices | EngineServices | FeatureSummaryOpenServices<Summary> | ROut>,
|
|
1400
|
+
FeatureLoadFailed,
|
|
1401
|
+
Scope.Scope
|
|
1402
|
+
> {
|
|
1403
|
+
const { layer } = yield* binding.load
|
|
1404
|
+
const bus = Context.get(engineContext, Bus)
|
|
1405
|
+
const featureContext = Context.add(engineContext, FeatureInput, props)
|
|
1406
|
+
const context = yield* Layer.build(Layer.provide(layer, Layer.succeedContext(featureContext)))
|
|
1407
|
+
yield* Effect.forEach(binding.boot, (event) => publish('High', event), {
|
|
1408
|
+
discard: true,
|
|
1409
|
+
}).pipe(Effect.provideService(Bus, bus))
|
|
1410
|
+
return Context.merge(engineContext, context)
|
|
1411
|
+
})
|