@playfast/reform 1.0.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 +103 -56
- package/package.json +17 -17
- package/src/boundary/boundary.test.ts +63 -49
- package/src/boundary/boundary.ts +144 -113
- package/src/calc/asyncCalc.invalidate.test.ts +518 -32
- package/src/calc/asyncCalc.test.ts +207 -213
- package/src/calc/asyncCalc.ts +131 -154
- package/src/calc/asyncData.ts +0 -37
- package/src/calc/calc.test.ts +7 -33
- package/src/calc/calc.ts +44 -58
- package/src/calc/calcFamily.test.ts +80 -34
- package/src/calc/calcFamily.ts +54 -65
- package/src/calc/compose.test.ts +1 -12
- package/src/calc/compose.ts +1 -36
- package/src/calc/queryState.ts +0 -23
- package/src/channel/channel.ts +126 -111
- package/src/compose/composition.test.ts +19 -0
- package/src/compose/composition.ts +351 -127
- package/src/compose/host.ts +0 -6
- package/src/compose/props.ts +13 -12
- package/src/compose/provide.ts +189 -62
- package/src/compose/slot.ts +158 -49
- package/src/compose/structure.test.ts +6 -9
- package/src/compose/structure.ts +108 -79
- package/src/compose/ui.test.ts +19 -7
- package/src/compose/ui.ts +155 -156
- package/src/compose/ui.typecheck.ts +40 -18
- package/src/definition/definition.ts +22 -41
- package/src/event/event.fromSource.test.ts +172 -0
- package/src/event/event.test.ts +10 -3
- package/src/event/event.ts +102 -27
- package/src/event/eventGroup.ts +0 -1
- package/src/feature/feature.mount.test.ts +122 -43
- package/src/feature/feature.test.ts +46 -21
- package/src/feature/feature.ts +1347 -256
- package/src/feature/feature.typecheck.ts +273 -68
- package/src/graph/closure.ts +403 -0
- package/src/index.ts +68 -126
- package/src/internal/bucketCache.ts +39 -0
- package/src/internal/capture.ts +9 -24
- package/src/internal/env.ts +7 -0
- package/src/internal/errors.test.ts +0 -6
- package/src/internal/errors.ts +37 -60
- package/src/internal/inspect.test.ts +0 -6
- package/src/internal/inspect.ts +0 -12
- package/src/internal/queryDriver.ts +105 -201
- package/src/internal/queryDriverStore.ts +156 -0
- package/src/internal/queryDriverTypes.ts +59 -0
- package/src/internal/queryEvents.ts +0 -12
- package/src/internal/queryStore.ts +0 -14
- package/src/internal/reuse.test.ts +10 -14
- package/src/internal/reuse.ts +5 -30
- package/src/internal/scheduler.ts +4 -44
- package/src/internal/seeds.ts +0 -14
- package/src/internal/sources.ts +26 -49
- package/src/internal/stateRegistry.ts +0 -14
- package/src/internal/store.test.ts +1 -3
- package/src/internal/store.ts +0 -37
- package/src/internal/track.ts +3 -20
- package/src/internal/variance.ts +5 -0
- package/src/internal.ts +222 -0
- package/src/namespace/namespace.test.ts +46 -0
- package/src/namespace/namespace.ts +106 -0
- package/src/procedure/procedure.ts +40 -35
- package/src/reducer/reducer.ts +78 -52
- package/src/remote/remoteState.test.ts +590 -397
- package/src/remote/remoteState.ts +425 -347
- package/src/remote/remoteState.typecheck.ts +47 -56
- package/src/runtime/appRuntime.activation.test.ts +100 -0
- package/src/runtime/appRuntime.test.ts +249 -0
- package/src/runtime/appRuntime.ts +415 -97
- package/src/runtime/bus.ts +2 -15
- package/src/runtime/eventBudget.test.ts +152 -0
- package/src/runtime/eventBudget.ts +120 -0
- package/src/runtime/hardening.test.ts +73 -13
- package/src/runtime/instrumentation.test.ts +55 -52
- package/src/runtime/instrumentation.ts +6 -60
- package/src/runtime/loop.test.ts +36 -17
- package/src/runtime/loop.ts +87 -88
- package/src/runtime/queries.ts +0 -17
- package/src/scene/featureScene.test.ts +61 -0
- package/src/scene/scene.ts +247 -104
- package/src/scene/seedScene.test.ts +42 -79
- package/src/state/state.nominal.typecheck.ts +68 -0
- package/src/state/state.test.ts +17 -0
- package/src/state/state.ts +80 -46
- package/src/state/stateFamily.test.ts +16 -11
- package/src/state/stateFamily.ts +55 -65
- package/src/state/stateGroup.ts +53 -64
- package/src/state/token.ts +40 -23
- package/src/synced/syncedStore.ts +46 -58
- package/src/testkit/flight.testkit.ts +75 -0
- package/src/ui/node.ts +0 -6
- package/src/ui/trigger.ts +0 -5
- package/src/wire/tree.test.ts +8 -7
- package/src/wire/tree.ts +0 -39
- package/src/wire/triggers.test.ts +6 -6
- package/src/wire/triggers.ts +14 -32
- package/src/internal/ctx.ts +0 -16
package/src/feature/feature.ts
CHANGED
|
@@ -1,94 +1,227 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
10
|
+
import { type Manifest, definitionClass } from '../definition/definition'
|
|
11
|
+
import {
|
|
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>()
|
|
41
|
+
export class FeatureInput extends FeatureInputBase {}
|
|
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
|
+
|
|
32
54
|
export type RequireCarrier =
|
|
33
|
-
|
|
|
34
|
-
| {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
+
>
|
|
82
|
+
|
|
83
|
+
type DefaultFeatureOpenServices<ROut, DirectRequires extends ReadonlyArray<FeatureRequirement>> =
|
|
84
|
+
| ProvidedBy<DirectRequires>
|
|
85
|
+
| OpenServicesFromFeatureSlotWitnesses<ROut>
|
|
86
|
+
|
|
87
|
+
type CompositionNames<ROut> = ROut extends {
|
|
88
|
+
readonly [CompositionIdTypeId]: {
|
|
89
|
+
readonly name: infer Name extends string
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
? Name
|
|
93
|
+
: never
|
|
94
|
+
|
|
95
|
+
type CompositionIdentities<ROut> = ROut extends {
|
|
96
|
+
readonly [CompositionIdTypeId]: {
|
|
97
|
+
readonly identity: infer Identity
|
|
48
98
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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)
|
|
116
|
+
|
|
117
|
+
export interface FeatureModule<
|
|
118
|
+
ROut,
|
|
119
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
120
|
+
OpenServices = DefaultFeatureOpenServices<ROut, DirectRequires>,
|
|
121
|
+
UsesInput extends boolean = false,
|
|
122
|
+
Input = never,
|
|
123
|
+
> extends AnyLoadedModule {
|
|
124
|
+
readonly [FeatureModuleGraphValidTypeId]: FeatureModuleGraphValidTypeId
|
|
125
|
+
readonly requires: DirectRequires
|
|
126
|
+
readonly usesInput: UsesInput
|
|
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
|
|
144
|
+
}
|
|
145
|
+
|
|
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
|
+
}
|
|
190
|
+
|
|
191
|
+
export const featureModuleFromInput = <
|
|
192
|
+
const InputSchema extends Schema.Schema.AnyNoContext,
|
|
193
|
+
const DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
194
|
+
L extends Layer.Layer.Any,
|
|
195
|
+
>(
|
|
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
|
+
}
|
|
223
|
+
|
|
224
|
+
// Seal dynamic imports as typed Effects so chunk failures become FeatureLoadFailed.
|
|
92
225
|
export const lazyImport = <M>(
|
|
93
226
|
thunk: () => Promise<{ readonly default: M }>,
|
|
94
227
|
): Effect.Effect<M, FeatureLoadFailed> =>
|
|
@@ -97,18 +230,11 @@ export const lazyImport = <M>(
|
|
|
97
230
|
catch: (cause) => new FeatureLoadFailed({ cause }),
|
|
98
231
|
}).pipe(Effect.map((module) => module.default))
|
|
99
232
|
|
|
100
|
-
/** The props the host injects into a lazy feature's `failed` placeholder. */
|
|
101
233
|
export interface FailedProps {
|
|
102
234
|
readonly error: FeatureLoadFailed
|
|
103
235
|
readonly retry: () => void
|
|
104
236
|
}
|
|
105
237
|
|
|
106
|
-
/**
|
|
107
|
-
* The reflectable shape of a feature: its strategy, the composition it mounts,
|
|
108
|
-
* and (when lazy) its placeholder compositions — all as manifests, so the editor
|
|
109
|
-
* route-map renders the whole feature graph with no chunk loaded. `boot` is
|
|
110
|
-
* runtime data and lives on the `FeatureBinding`, not here.
|
|
111
|
-
*/
|
|
112
238
|
export interface FeatureManifest extends Manifest {
|
|
113
239
|
readonly kind: 'Feature'
|
|
114
240
|
readonly name: string
|
|
@@ -120,201 +246,1166 @@ export interface FeatureManifest extends Manifest {
|
|
|
120
246
|
}>
|
|
121
247
|
}
|
|
122
248
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
*/
|
|
131
|
-
export interface LoadedModule {
|
|
132
|
-
readonly requires: ReadonlyArray<RequireCarrier>
|
|
133
|
-
readonly layer: Layer.Layer<never, never, unknown>
|
|
134
|
-
}
|
|
249
|
+
export interface LoadedModule<
|
|
250
|
+
ROut,
|
|
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> {}
|
|
135
256
|
|
|
136
|
-
/** Nominal brand identifying the value a `provide(slot, Feature)` puts under a slot tag. */
|
|
137
257
|
export const FeatureBindingTypeId: unique symbol = Symbol.for('reform/FeatureBinding')
|
|
138
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')
|
|
139
263
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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,
|
|
295
|
+
> {
|
|
296
|
+
new (): {}
|
|
297
|
+
readonly manifest: FeatureManifest
|
|
298
|
+
readonly token: FeatureIdentityToken<FeatureIdentity>
|
|
299
|
+
readonly summary: Summary
|
|
300
|
+
}
|
|
301
|
+
|
|
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 {
|
|
150
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 {
|
|
151
330
|
readonly manifest: FeatureManifest
|
|
152
|
-
readonly
|
|
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
|
+
>
|
|
153
340
|
readonly strategy: 'lazy' | 'default'
|
|
154
|
-
readonly load: Effect.Effect<
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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>
|
|
160
356
|
readonly boot: ReadonlyArray<Tagged>
|
|
161
357
|
}
|
|
162
358
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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,
|
|
429
|
+
ROut,
|
|
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
|
+
>
|
|
452
|
+
readonly supportModule: undefined
|
|
453
|
+
}
|
|
454
|
+
|
|
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,
|
|
476
|
+
ROut,
|
|
477
|
+
DirectRequires,
|
|
478
|
+
SupportOut,
|
|
479
|
+
SupportDirectRequires,
|
|
480
|
+
Composition
|
|
481
|
+
> {
|
|
482
|
+
readonly eagerModule: undefined
|
|
483
|
+
}
|
|
484
|
+
|
|
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
|
+
>
|
|
166
510
|
|
|
167
|
-
/**
|
|
168
|
-
* A feature *definition*: a reflectable manifest (`kind: 'Feature'`) that carries
|
|
169
|
-
* the eager half (composition + placeholders) and an Effect `load` for the heavy
|
|
170
|
-
* `.live` half. `Props`/`Contract` flow from the composition; `Requires` is the
|
|
171
|
-
* shared-carrier tuple the loaded module declares. `load` is an `Effect`, never a
|
|
172
|
-
* Promise — consumers `yield* Feature.load`.
|
|
173
|
-
*/
|
|
174
511
|
export interface FeatureClass<
|
|
512
|
+
FeatureIdentity,
|
|
175
513
|
P,
|
|
176
514
|
C extends UiContract,
|
|
177
515
|
ROut,
|
|
178
|
-
|
|
179
|
-
|
|
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
|
+
>
|
|
656
|
+
>
|
|
657
|
+
|
|
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 {
|
|
180
667
|
new (): {}
|
|
181
668
|
readonly manifest: FeatureManifest
|
|
182
|
-
|
|
183
|
-
readonly
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
/** The eagerly-available module — present only for `loadingStrategy: 'default'`. */
|
|
193
|
-
readonly eagerModule: FeatureModule<ROut, Requires> | undefined
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
export type AnyFeature = FeatureClass<any, any, any, ReadonlyArray<RequireCarrier>>
|
|
197
|
-
|
|
198
|
-
/** Whether a value is a feature definition (its target shape in `provide(slot, Feature)`). */
|
|
199
|
-
export const isFeature = (candidate: unknown): candidate is AnyFeature =>
|
|
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 =>
|
|
200
679
|
(typeof candidate === 'function' || typeof candidate === 'object') &&
|
|
201
680
|
candidate !== null &&
|
|
202
|
-
'
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
681
|
+
'token' in candidate &&
|
|
682
|
+
isRuntimeFeatureToken(candidate.token)
|
|
683
|
+
|
|
684
|
+
type PlaceholderComposition<P> = AnyComposition & CompositionPropsReceiver<P>
|
|
685
|
+
|
|
686
|
+
export interface Placeholders<P> {
|
|
687
|
+
readonly loading: PlaceholderComposition<P>
|
|
688
|
+
readonly failed: PlaceholderComposition<FailedProps>
|
|
689
|
+
}
|
|
690
|
+
|
|
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<
|
|
221
710
|
P,
|
|
222
711
|
C extends UiContract,
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
712
|
+
S extends ReadonlyArray<unknown>,
|
|
713
|
+
N extends string,
|
|
714
|
+
Identity,
|
|
715
|
+
> {
|
|
716
|
+
readonly composition: CompositionClass<P, C, S, N, Identity>
|
|
227
717
|
readonly boot?: ReadonlyArray<Tagged>
|
|
228
|
-
}
|
|
718
|
+
}
|
|
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
|
+
|
|
731
|
+
type EagerFeatureConfigExternalApi<
|
|
732
|
+
P,
|
|
733
|
+
C extends UiContract,
|
|
734
|
+
ROut,
|
|
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> & {
|
|
741
|
+
readonly loadingStrategy?: 'default'
|
|
742
|
+
readonly module: FeatureModule<ROut, DirectRequires, OpenServices, false, never> &
|
|
743
|
+
IncludesComposition<ROut, N, Identity>
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
type LazyFeatureConfigExternalApi<
|
|
747
|
+
CompositionProps,
|
|
748
|
+
C extends UiContract,
|
|
749
|
+
ROut,
|
|
750
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
751
|
+
OpenServices,
|
|
752
|
+
SupportOut,
|
|
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
|
+
>
|
|
766
|
+
readonly loadingStrategy: 'lazy'
|
|
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 =
|
|
229
796
|
| {
|
|
230
|
-
|
|
231
|
-
|
|
797
|
+
readonly composition: AnyComposition
|
|
798
|
+
readonly boot?: ReadonlyArray<Tagged>
|
|
232
799
|
readonly loadingStrategy?: 'default'
|
|
233
|
-
readonly module:
|
|
800
|
+
readonly module: AnyLoadedModule
|
|
234
801
|
}
|
|
235
802
|
| {
|
|
236
|
-
|
|
803
|
+
readonly composition: AnyComposition
|
|
804
|
+
readonly boot?: ReadonlyArray<Tagged>
|
|
237
805
|
readonly loadingStrategy: 'lazy'
|
|
238
|
-
readonly
|
|
239
|
-
readonly
|
|
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
|
|
240
813
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
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
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
const makeFeatureManifest = (
|
|
251
830
|
name: string,
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
placeholder: Option.fromNullable(placeholder).pipe(
|
|
266
|
-
Option.map((placeholders) => ({
|
|
267
|
-
loading: placeholders.loading.manifest,
|
|
268
|
-
failed: placeholders.failed.manifest,
|
|
269
|
-
})),
|
|
270
|
-
),
|
|
271
|
-
}
|
|
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
|
+
})
|
|
272
844
|
|
|
273
|
-
|
|
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> = {
|
|
274
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 = <
|
|
962
|
+
P,
|
|
963
|
+
C extends UiContract,
|
|
964
|
+
ROut,
|
|
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>,
|
|
971
|
+
>(
|
|
972
|
+
name: string,
|
|
973
|
+
config: EagerFeatureConfigExternalApi<P, C, ROut, DirectRequires, OpenServices, S, N, Identity> &
|
|
974
|
+
ExactFeatureCompositionConfig<Composition>,
|
|
975
|
+
): EagerFeatureClass<
|
|
976
|
+
Identity,
|
|
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,
|
|
275
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,
|
|
276
1017
|
composition: config.composition,
|
|
277
|
-
strategy,
|
|
278
|
-
// The host is strategy-uniform: `default`'s `load` resolves immediately. The
|
|
279
|
-
// assignment to the erased `LoadedModule` needs no cast — see `LoadedModule`.
|
|
280
1018
|
load,
|
|
281
|
-
|
|
282
|
-
|
|
1019
|
+
binding,
|
|
1020
|
+
eagerModule: config.module,
|
|
1021
|
+
supportModule: undefined,
|
|
283
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
|
+
}
|
|
284
1047
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
1048
|
+
const makeLazyFeature = <
|
|
1049
|
+
CompositionProps,
|
|
1050
|
+
C extends UiContract,
|
|
1051
|
+
ROut,
|
|
1052
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
1053
|
+
OpenServices,
|
|
1054
|
+
SupportOut,
|
|
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,
|
|
1064
|
+
>(
|
|
1065
|
+
name: string,
|
|
1066
|
+
config: LazyFeatureConfigExternalApi<
|
|
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,
|
|
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,
|
|
1129
|
+
ROut,
|
|
1130
|
+
DirectRequires,
|
|
1131
|
+
SupportOut,
|
|
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,
|
|
320
1170
|
})
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
export function make<
|
|
1174
|
+
P,
|
|
1175
|
+
C extends UiContract,
|
|
1176
|
+
ROut,
|
|
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>,
|
|
1183
|
+
>(
|
|
1184
|
+
name: string,
|
|
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
|
+
>(
|
|
1224
|
+
name: string,
|
|
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: (
|
|
1277
|
+
| EagerFeatureConfigExternalApi<
|
|
1278
|
+
CompositionProps,
|
|
1279
|
+
C,
|
|
1280
|
+
ROut,
|
|
1281
|
+
DirectRequires,
|
|
1282
|
+
OpenServices,
|
|
1283
|
+
S,
|
|
1284
|
+
N,
|
|
1285
|
+
Identity
|
|
1286
|
+
>
|
|
1287
|
+
| LazyFeatureConfigExternalApi<
|
|
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}`))
|
|
1337
|
+
}
|
|
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)
|
|
1356
|
+
}
|
|
1357
|
+
return makeEagerFeature<
|
|
1358
|
+
CompositionProps,
|
|
1359
|
+
C,
|
|
1360
|
+
ROut,
|
|
1361
|
+
DirectRequires,
|
|
1362
|
+
OpenServices,
|
|
1363
|
+
S,
|
|
1364
|
+
N,
|
|
1365
|
+
Identity,
|
|
1366
|
+
Composition
|
|
1367
|
+
>(name, config)
|
|
1368
|
+
}
|
|
1369
|
+
|
|
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
|
+
})
|