@playfast/reform 1.1.1 → 1.2.1
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 +82 -33
- package/src/boundary/boundary.ts +141 -32
- package/src/calc/asyncCalc.invalidate.test.ts +733 -32
- package/src/calc/asyncCalc.test.ts +397 -225
- package/src/calc/asyncCalc.ts +115 -100
- package/src/calc/asyncCalcTypes.ts +147 -0
- package/src/calc/calc.test.ts +13 -16
- package/src/calc/calc.ts +44 -18
- package/src/calc/calcFamily.test.ts +90 -32
- package/src/calc/calcFamily.ts +56 -25
- package/src/calc/compose.ts +1 -14
- package/src/channel/channel.ts +25 -6
- package/src/channel/{procedureRegistry.ts → procedures.ts} +41 -23
- package/src/compose/composition.test.ts +19 -0
- package/src/compose/composition.ts +168 -81
- package/src/compose/compositionTypes.ts +249 -0
- 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 +222 -262
- package/src/feature/feature.typecheck.ts +224 -91
- package/src/feature/featureBinding.ts +130 -20
- package/src/feature/featureClass.ts +162 -0
- package/src/feature/featureConfig.ts +192 -0
- package/src/feature/featureFactory.ts +163 -0
- package/src/feature/featureModule.ts +136 -0
- package/src/feature/featureModule.typecheck.ts +63 -0
- package/src/feature/featureNativeTree.ts +152 -0
- package/src/feature/featureRequirement.ts +82 -0
- package/src/feature/featureVariants.ts +234 -0
- package/src/feature/mountFeature.ts +54 -0
- package/src/graph/closure.ts +222 -0
- package/src/graph/services.ts +95 -0
- package/src/graph/summary.ts +134 -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 +61 -25
- package/src/internal/queryDriverHydrate.ts +45 -0
- package/src/internal/queryDriverStore.ts +8 -5
- package/src/internal/queryDriverTypes.ts +11 -11
- 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/store.test.ts +27 -6
- 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/pendingQueue.ts +145 -0
- package/src/remote/remoteState.test.ts +536 -354
- package/src/remote/remoteState.ts +145 -106
- package/src/remote/remoteState.typecheck.ts +47 -23
- package/src/remote/remoteStateMake.ts +97 -0
- package/src/remote/remoteStateSend.ts +95 -37
- package/src/remote/remoteStateTypes.ts +155 -0
- package/src/runtime/appRuntime.activation.test.ts +104 -0
- package/src/runtime/appRuntime.test.ts +187 -111
- package/src/runtime/appRuntime.ts +36 -130
- package/src/runtime/capturedAppRuntime.ts +274 -0
- package/src/runtime/eventBudget.test.ts +39 -12
- package/src/runtime/eventBudget.ts +9 -8
- package/src/runtime/featureMount.ts +94 -0
- package/src/runtime/hardening.test.ts +22 -13
- package/src/runtime/instrumentation.test.ts +213 -194
- package/src/runtime/instrumentation.ts +6 -11
- package/src/runtime/loop.test.ts +84 -7
- package/src/runtime/loop.ts +69 -40
- package/src/runtime/runtimeHandle.ts +124 -0
- 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 +39 -8
- 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 +84 -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/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/feature/feature.ts
CHANGED
|
@@ -1,291 +1,251 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { type CompositionClass } from '../compose/composition'
|
|
7
|
-
import { type UiContract } from '../compose/ui'
|
|
8
|
-
import { publish, type Tagged } from '../runtime/bus'
|
|
9
|
-
import type { AnyValue } from '../internal/variance'
|
|
1
|
+
import { Effect, type Schema } from 'effect'
|
|
2
|
+
import type { AnyComposition, CompositionClass } from '../compose/composition'
|
|
3
|
+
import type { UiContract } from '../compose/ui'
|
|
4
|
+
import { FeatureGraphValidTypeId } from '../graph/closure'
|
|
5
|
+
import type { EagerFeatureClass, LazyFeatureClass } from './featureClass'
|
|
10
6
|
import {
|
|
11
|
-
type
|
|
12
|
-
|
|
13
|
-
type
|
|
7
|
+
type EagerFeatureConfigExternalApi,
|
|
8
|
+
type ExactFeatureCompositionConfig,
|
|
9
|
+
type FeatureMountProps,
|
|
10
|
+
type FeatureUsesInput,
|
|
11
|
+
isMakeImplementationConfig,
|
|
12
|
+
type LazyFeatureConfigExternalApi,
|
|
13
|
+
} from './featureConfig'
|
|
14
|
+
import type { FeatureRequirement } from './featureRequirement'
|
|
15
|
+
import { makeEagerFeature, makeLazyFeature } from './featureVariants'
|
|
16
|
+
|
|
17
|
+
export type { EngineServices } from '../runtime/loop'
|
|
18
|
+
export { FeatureGraphValidTypeId }
|
|
19
|
+
export { FeatureInput } from './featureRequirement'
|
|
20
|
+
export type {
|
|
21
|
+
FeatureModuleInput,
|
|
22
|
+
FeatureRequirement,
|
|
23
|
+
ProvidedBy,
|
|
24
|
+
RequireCarrier,
|
|
25
|
+
} from './featureRequirement'
|
|
26
|
+
export { featureModule, featureModuleFromInput, lazyImport } from './featureModule'
|
|
27
|
+
export type { AnyLoadedModule, FeatureModule, LoadedModule, LoadedModuleCapture } from './featureModule'
|
|
28
|
+
export { FeatureBindingTypeId, isFeatureBinding, tree } from './featureBinding'
|
|
29
|
+
export type {
|
|
30
|
+
AnyFeatureBinding,
|
|
31
|
+
AnyFeatureBindingExternalApi,
|
|
32
|
+
CapturedFeatureBinding,
|
|
33
|
+
FailedProps,
|
|
34
|
+
FeatureBinding,
|
|
35
|
+
FeatureBindingCapture,
|
|
36
|
+
FeatureBindingType,
|
|
37
|
+
FeatureDefinition,
|
|
38
|
+
FeatureIdentityToken,
|
|
39
|
+
FeatureManifest,
|
|
40
|
+
FeatureOpenServices,
|
|
41
|
+
FeatureSupportOpenServices,
|
|
42
|
+
FeatureToken,
|
|
43
|
+
FeatureTreeCarrier,
|
|
44
|
+
ProvideableFeature,
|
|
14
45
|
} from './featureBinding'
|
|
15
|
-
export {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
} from './
|
|
23
|
-
export
|
|
24
|
-
|
|
25
|
-
// Features must only name EngineServices as open RIn — never provide them (shared engine)
|
|
26
|
-
export type EngineServices = Layer.Layer.Success<typeof Engine>
|
|
27
|
-
|
|
28
|
-
const FeatureInputBase: Context.TagClass<FeatureInput, 'reform/FeatureInput', unknown> = Context.Tag(
|
|
29
|
-
'reform/FeatureInput',
|
|
30
|
-
)<FeatureInput, unknown>()
|
|
31
|
-
export class FeatureInput extends FeatureInputBase {}
|
|
32
|
-
|
|
33
|
-
export type RequireCarrier =
|
|
34
|
-
| { readonly store: Context.Tag<AnyValue, AnyValue> }
|
|
35
|
-
| { readonly members: ReadonlyArray<{ readonly store: Context.Tag<AnyValue, AnyValue> }> }
|
|
36
|
-
|
|
37
|
-
export type FeatureRequirement = RequireCarrier | Context.Tag<AnyValue, AnyValue>
|
|
38
|
-
|
|
39
|
-
// Covariant RIn: layer reading outside EngineServices | ProvidedBy is unassignable
|
|
40
|
-
export type ProvidedBy<Requires extends ReadonlyArray<FeatureRequirement>> = {
|
|
41
|
-
[I in keyof Requires]: Requires[I] extends Context.Tag<infer Identifier, AnyValue>
|
|
42
|
-
? Identifier
|
|
43
|
-
: Requires[I] extends {
|
|
44
|
-
readonly members: infer M extends ReadonlyArray<unknown>
|
|
45
|
-
}
|
|
46
|
-
? StoresOf<M>
|
|
47
|
-
: Requires[I] extends { readonly store: Context.Tag<infer Svc, AnyValue> }
|
|
48
|
-
? Svc
|
|
49
|
-
: never
|
|
50
|
-
}[number]
|
|
51
|
-
|
|
52
|
-
export interface FeatureModule<
|
|
53
|
-
ROut,
|
|
54
|
-
Requires extends ReadonlyArray<FeatureRequirement>,
|
|
55
|
-
UsesInput extends boolean = false,
|
|
56
|
-
> {
|
|
57
|
-
readonly requires: Requires
|
|
58
|
-
readonly usesInput: UsesInput
|
|
59
|
-
readonly layer: Layer.Layer<
|
|
60
|
-
ROut,
|
|
61
|
-
never,
|
|
62
|
-
| EngineServices
|
|
63
|
-
| ProvidedBy<Requires>
|
|
64
|
-
| (UsesInput extends true ? FeatureInput : never)
|
|
65
|
-
>
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export const featureModule = <const Requires extends ReadonlyArray<FeatureRequirement>, ROut>(
|
|
69
|
-
requires: Requires,
|
|
70
|
-
layer: Layer.Layer<ROut, never, EngineServices | ProvidedBy<Requires>>,
|
|
71
|
-
): FeatureModule<ROut, Requires, false> => ({ requires, usesInput: false, layer })
|
|
72
|
-
|
|
73
|
-
export const featureModuleFromInput = <
|
|
74
|
-
const Requires extends ReadonlyArray<FeatureRequirement>,
|
|
75
|
-
ROut,
|
|
76
|
-
>(
|
|
77
|
-
requires: Requires,
|
|
78
|
-
layer: Layer.Layer<ROut, never, EngineServices | ProvidedBy<Requires> | FeatureInput>,
|
|
79
|
-
): FeatureModule<ROut, Requires, true> => ({ requires, usesInput: true, layer })
|
|
80
|
-
|
|
81
|
-
// Seals Promise import as Effect; rejection → FeatureLoadFailed
|
|
82
|
-
export const lazyImport = <M>(
|
|
83
|
-
thunk: () => Promise<{ readonly default: M }>,
|
|
84
|
-
): Effect.Effect<M, FeatureLoadFailed> =>
|
|
85
|
-
Effect.tryPromise({
|
|
86
|
-
try: thunk,
|
|
87
|
-
catch: (cause) => new FeatureLoadFailed({ cause }),
|
|
88
|
-
}).pipe(Effect.map((module) => module.default))
|
|
89
|
-
|
|
90
|
-
export interface FeatureClass<
|
|
91
|
-
P,
|
|
92
|
-
C extends UiContract,
|
|
93
|
-
ROut,
|
|
94
|
-
Requires extends ReadonlyArray<FeatureRequirement>,
|
|
95
|
-
SupportRequires extends ReadonlyArray<FeatureRequirement> = readonly [],
|
|
96
|
-
> {
|
|
97
|
-
new (): {}
|
|
98
|
-
readonly manifest: FeatureManifest
|
|
99
|
-
readonly Props: P
|
|
100
|
-
readonly Contract: C
|
|
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
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export interface EagerFeatureClass<
|
|
110
|
-
P,
|
|
111
|
-
C extends UiContract,
|
|
112
|
-
ROut,
|
|
113
|
-
Requires extends ReadonlyArray<FeatureRequirement>,
|
|
114
|
-
> extends FeatureClass<P, C, ROut, Requires> {
|
|
115
|
-
readonly eagerModule: FeatureModule<ROut, Requires, false>
|
|
116
|
-
readonly supportModule: undefined
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export interface LazyFeatureClass<
|
|
120
|
-
P,
|
|
121
|
-
C extends UiContract,
|
|
122
|
-
ROut,
|
|
123
|
-
Requires extends ReadonlyArray<FeatureRequirement>,
|
|
124
|
-
SupportRequires extends ReadonlyArray<FeatureRequirement> = readonly [],
|
|
125
|
-
> extends FeatureClass<P, C, ROut, Requires, SupportRequires> {
|
|
126
|
-
readonly eagerModule: undefined
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export type AnyFeature = FeatureClass<
|
|
130
|
-
AnyValue,
|
|
131
|
-
AnyValue,
|
|
132
|
-
AnyValue,
|
|
133
|
-
ReadonlyArray<FeatureRequirement>,
|
|
134
|
-
ReadonlyArray<FeatureRequirement>
|
|
135
|
-
>
|
|
136
|
-
|
|
137
|
-
export const isFeature = (candidate: unknown): candidate is AnyFeature =>
|
|
138
|
-
(typeof candidate === 'function' || typeof candidate === 'object') &&
|
|
139
|
-
candidate !== null &&
|
|
140
|
-
'manifest' in candidate &&
|
|
141
|
-
typeof candidate.manifest === 'object' &&
|
|
142
|
-
candidate.manifest !== null &&
|
|
143
|
-
'kind' in candidate.manifest &&
|
|
144
|
-
candidate.manifest.kind === 'Feature'
|
|
145
|
-
|
|
146
|
-
export interface Placeholders {
|
|
147
|
-
readonly loading: CompositionClass<AnyValue, UiContract>
|
|
148
|
-
readonly failed: CompositionClass<AnyValue, UiContract>
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
interface FeatureConfigBaseExternalApi<P, C extends UiContract> {
|
|
152
|
-
readonly composition: CompositionClass<P, C>
|
|
153
|
-
readonly boot?: ReadonlyArray<Tagged>
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
type EagerFeatureConfigExternalApi<
|
|
157
|
-
P,
|
|
158
|
-
C extends UiContract,
|
|
159
|
-
ROut,
|
|
160
|
-
Requires extends ReadonlyArray<FeatureRequirement>,
|
|
161
|
-
> = FeatureConfigBaseExternalApi<P, C> & {
|
|
162
|
-
readonly loadingStrategy?: 'default'
|
|
163
|
-
readonly module: FeatureModule<ROut, Requires, false>
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
type LazyFeatureConfigExternalApi<
|
|
167
|
-
P,
|
|
168
|
-
C extends UiContract,
|
|
169
|
-
ROut,
|
|
170
|
-
Requires extends ReadonlyArray<FeatureRequirement>,
|
|
171
|
-
SupportOut,
|
|
172
|
-
SupportRequires extends ReadonlyArray<FeatureRequirement>,
|
|
173
|
-
> = FeatureConfigBaseExternalApi<P, C> & {
|
|
174
|
-
readonly loadingStrategy: 'lazy'
|
|
175
|
-
readonly load: Effect.Effect<FeatureModule<ROut, Requires, boolean>, FeatureLoadFailed>
|
|
176
|
-
readonly placeholder: Placeholders
|
|
177
|
-
readonly eager?: FeatureModule<SupportOut, SupportRequires, false>
|
|
178
|
-
}
|
|
46
|
+
export type {
|
|
47
|
+
EagerFeatureNativeTree,
|
|
48
|
+
FeatureNativeTree,
|
|
49
|
+
LazyFeatureNativeTree,
|
|
50
|
+
} from './featureNativeTree'
|
|
51
|
+
export type { EagerFeatureClass, FeatureClass, LazyFeatureClass } from './featureClass'
|
|
52
|
+
export { isFeature } from './featureConfig'
|
|
53
|
+
export type { FeatureMountProps, Placeholders } from './featureConfig'
|
|
54
|
+
export { mountFeature } from './mountFeature'
|
|
179
55
|
|
|
180
56
|
export function make<
|
|
181
57
|
P,
|
|
182
58
|
C extends UiContract,
|
|
183
59
|
ROut,
|
|
184
|
-
|
|
60
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
61
|
+
OpenServices,
|
|
62
|
+
S extends ReadonlyArray<unknown>,
|
|
63
|
+
N extends string,
|
|
64
|
+
Identity,
|
|
65
|
+
const Composition extends CompositionClass<P, C, S, N, Identity>,
|
|
185
66
|
>(
|
|
186
67
|
name: string,
|
|
187
|
-
config: EagerFeatureConfigExternalApi<
|
|
188
|
-
|
|
189
|
-
|
|
68
|
+
config: EagerFeatureConfigExternalApi<
|
|
69
|
+
P,
|
|
70
|
+
C,
|
|
71
|
+
ROut,
|
|
72
|
+
DirectRequires,
|
|
73
|
+
OpenServices,
|
|
74
|
+
S,
|
|
75
|
+
N,
|
|
76
|
+
Identity
|
|
77
|
+
> & { readonly composition: Composition },
|
|
78
|
+
): EagerFeatureClass<
|
|
79
|
+
Identity,
|
|
190
80
|
P,
|
|
81
|
+
C,
|
|
82
|
+
ROut,
|
|
83
|
+
DirectRequires,
|
|
84
|
+
OpenServices,
|
|
85
|
+
S,
|
|
86
|
+
N,
|
|
87
|
+
Identity,
|
|
88
|
+
Composition
|
|
89
|
+
>
|
|
90
|
+
export function make<
|
|
91
|
+
CompositionProps,
|
|
191
92
|
C extends UiContract,
|
|
192
93
|
ROut,
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
94
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
95
|
+
OpenServices,
|
|
96
|
+
S extends ReadonlyArray<unknown>,
|
|
97
|
+
N extends string,
|
|
98
|
+
Identity,
|
|
99
|
+
const Composition extends CompositionClass<CompositionProps, C, S, N, Identity>,
|
|
100
|
+
const Loading extends AnyComposition,
|
|
101
|
+
const Failed extends AnyComposition,
|
|
102
|
+
const InputSchema extends Schema.Schema.AnyNoContext = never,
|
|
103
|
+
SupportOut = never,
|
|
104
|
+
SupportDirectRequires extends ReadonlyArray<FeatureRequirement> = readonly [],
|
|
105
|
+
SupportOpenServices = never,
|
|
196
106
|
>(
|
|
197
107
|
name: string,
|
|
198
108
|
config: LazyFeatureConfigExternalApi<
|
|
199
|
-
|
|
109
|
+
CompositionProps,
|
|
200
110
|
C,
|
|
201
111
|
ROut,
|
|
202
|
-
|
|
112
|
+
DirectRequires,
|
|
113
|
+
OpenServices,
|
|
203
114
|
SupportOut,
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
115
|
+
SupportDirectRequires,
|
|
116
|
+
SupportOpenServices,
|
|
117
|
+
S,
|
|
118
|
+
N,
|
|
119
|
+
Identity,
|
|
120
|
+
InputSchema,
|
|
121
|
+
Loading,
|
|
122
|
+
Failed
|
|
123
|
+
> & { readonly composition: Composition },
|
|
124
|
+
): LazyFeatureClass<
|
|
125
|
+
Identity,
|
|
126
|
+
FeatureMountProps<FeatureUsesInput<InputSchema>, CompositionProps, InputSchema>,
|
|
127
|
+
C,
|
|
128
|
+
ROut,
|
|
129
|
+
DirectRequires,
|
|
130
|
+
OpenServices,
|
|
131
|
+
SupportOut,
|
|
132
|
+
SupportDirectRequires,
|
|
133
|
+
SupportOpenServices,
|
|
134
|
+
FeatureUsesInput<InputSchema>,
|
|
135
|
+
S,
|
|
136
|
+
N,
|
|
137
|
+
CompositionProps,
|
|
138
|
+
Identity,
|
|
139
|
+
Composition
|
|
140
|
+
>
|
|
207
141
|
export function make<
|
|
208
|
-
|
|
142
|
+
CompositionProps,
|
|
209
143
|
C extends UiContract,
|
|
210
144
|
ROut,
|
|
211
|
-
|
|
145
|
+
DirectRequires extends ReadonlyArray<FeatureRequirement>,
|
|
146
|
+
OpenServices,
|
|
147
|
+
S extends ReadonlyArray<unknown>,
|
|
148
|
+
N extends string,
|
|
149
|
+
Identity,
|
|
150
|
+
Composition extends CompositionClass<CompositionProps, C, S, N, Identity>,
|
|
151
|
+
Loading extends AnyComposition,
|
|
152
|
+
Failed extends AnyComposition,
|
|
153
|
+
InputSchema extends Schema.Schema.AnyNoContext = never,
|
|
154
|
+
SupportOut = never,
|
|
155
|
+
SupportDirectRequires extends ReadonlyArray<FeatureRequirement> = readonly [],
|
|
156
|
+
SupportOpenServices = never,
|
|
212
157
|
>(
|
|
213
158
|
name: string,
|
|
214
|
-
config:
|
|
215
|
-
): LazyFeatureClass<P, C, ROut, Requires>
|
|
216
|
-
export function make(
|
|
217
|
-
name: string,
|
|
218
|
-
config:
|
|
159
|
+
config: (
|
|
219
160
|
| EagerFeatureConfigExternalApi<
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
161
|
+
CompositionProps,
|
|
162
|
+
C,
|
|
163
|
+
ROut,
|
|
164
|
+
DirectRequires,
|
|
165
|
+
OpenServices,
|
|
166
|
+
S,
|
|
167
|
+
N,
|
|
168
|
+
Identity
|
|
224
169
|
>
|
|
225
170
|
| 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
|
-
|
|
171
|
+
CompositionProps,
|
|
172
|
+
C,
|
|
173
|
+
ROut,
|
|
174
|
+
DirectRequires,
|
|
175
|
+
OpenServices,
|
|
176
|
+
SupportOut,
|
|
177
|
+
SupportDirectRequires,
|
|
178
|
+
SupportOpenServices,
|
|
179
|
+
S,
|
|
180
|
+
N,
|
|
181
|
+
Identity,
|
|
182
|
+
InputSchema,
|
|
183
|
+
Loading,
|
|
184
|
+
Failed
|
|
185
|
+
>
|
|
186
|
+
) &
|
|
187
|
+
ExactFeatureCompositionConfig<Composition>,
|
|
188
|
+
):
|
|
189
|
+
| EagerFeatureClass<
|
|
190
|
+
Identity,
|
|
191
|
+
CompositionProps,
|
|
192
|
+
C,
|
|
193
|
+
ROut,
|
|
194
|
+
DirectRequires,
|
|
195
|
+
OpenServices,
|
|
196
|
+
S,
|
|
197
|
+
N,
|
|
198
|
+
Identity,
|
|
199
|
+
Composition
|
|
200
|
+
>
|
|
201
|
+
| LazyFeatureClass<
|
|
202
|
+
Identity,
|
|
203
|
+
FeatureMountProps<FeatureUsesInput<InputSchema>, CompositionProps, InputSchema>,
|
|
204
|
+
C,
|
|
205
|
+
ROut,
|
|
206
|
+
DirectRequires,
|
|
207
|
+
OpenServices,
|
|
208
|
+
SupportOut,
|
|
209
|
+
SupportDirectRequires,
|
|
210
|
+
SupportOpenServices,
|
|
211
|
+
FeatureUsesInput<InputSchema>,
|
|
212
|
+
S,
|
|
213
|
+
N,
|
|
214
|
+
CompositionProps,
|
|
215
|
+
Identity,
|
|
216
|
+
Composition
|
|
217
|
+
> {
|
|
218
|
+
if (!isMakeImplementationConfig(config)) {
|
|
219
|
+
return Effect.runSync(Effect.dieMessage(`Invalid Feature config for ${name}`))
|
|
251
220
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
221
|
+
if (config.loadingStrategy === 'lazy') {
|
|
222
|
+
return makeLazyFeature<
|
|
223
|
+
CompositionProps,
|
|
224
|
+
C,
|
|
225
|
+
ROut,
|
|
226
|
+
DirectRequires,
|
|
227
|
+
OpenServices,
|
|
228
|
+
SupportOut,
|
|
229
|
+
SupportDirectRequires,
|
|
230
|
+
SupportOpenServices,
|
|
231
|
+
S,
|
|
232
|
+
N,
|
|
233
|
+
Identity,
|
|
234
|
+
Composition,
|
|
235
|
+
InputSchema,
|
|
236
|
+
Loading,
|
|
237
|
+
Failed
|
|
238
|
+
>(name, config)
|
|
261
239
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
240
|
+
return makeEagerFeature<
|
|
241
|
+
CompositionProps,
|
|
242
|
+
C,
|
|
243
|
+
ROut,
|
|
244
|
+
DirectRequires,
|
|
245
|
+
OpenServices,
|
|
246
|
+
S,
|
|
247
|
+
N,
|
|
248
|
+
Identity,
|
|
249
|
+
Composition
|
|
250
|
+
>(name, config)
|
|
271
251
|
}
|
|
272
|
-
|
|
273
|
-
// oxlint-disable-next-line reform-rules/prefer-effect-fn -- generic export: Effect.fn's inferred type isn't portable under isolatedDeclarations
|
|
274
|
-
export const mountFeature = <R>(
|
|
275
|
-
binding: FeatureBinding,
|
|
276
|
-
engineContext: Context.Context<R>,
|
|
277
|
-
props?: unknown,
|
|
278
|
-
): Effect.Effect<Context.Context<unknown>, FeatureLoadFailed, Scope.Scope> =>
|
|
279
|
-
Effect.gen(function* () {
|
|
280
|
-
const module = yield* binding.load
|
|
281
|
-
// oxlint-disable-next-line reform-rules/no-type-assertion -- documented erasure boundary: re-attach the concrete engine context to the type-erased `LoadedModule` layer (mirrors `buildRuntime`); RIn was verified cast-free at `provide`/scene wiring
|
|
282
|
-
const featureLayer = module.layer as Layer.Layer<unknown, never, R | FeatureInput>
|
|
283
|
-
const featureContext = Context.add(engineContext, FeatureInput, props)
|
|
284
|
-
const context = yield* Layer.build(
|
|
285
|
-
Layer.provideMerge(featureLayer, Layer.succeedContext(featureContext)),
|
|
286
|
-
)
|
|
287
|
-
yield* Effect.forEach(binding.boot, (event) => publish('High', event), { discard: true }).pipe(
|
|
288
|
-
Effect.provide(context),
|
|
289
|
-
)
|
|
290
|
-
return context
|
|
291
|
-
})
|