@playfast/reform 1.2.0 → 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.
Files changed (50) hide show
  1. package/package.json +1 -1
  2. package/src/boundary/boundary.test.ts +26 -23
  3. package/src/calc/asyncCalc.invalidate.test.ts +258 -55
  4. package/src/calc/asyncCalc.test.ts +225 -85
  5. package/src/calc/asyncCalc.ts +27 -141
  6. package/src/calc/asyncCalcTypes.ts +147 -0
  7. package/src/calc/calc.test.ts +10 -11
  8. package/src/calc/calcFamily.test.ts +12 -12
  9. package/src/channel/channel.ts +8 -106
  10. package/src/channel/procedures.ts +108 -0
  11. package/src/compose/composition.ts +49 -246
  12. package/src/compose/compositionTypes.ts +249 -0
  13. package/src/event/event.fromSource.test.ts +12 -12
  14. package/src/feature/feature.ts +50 -1210
  15. package/src/feature/feature.typecheck.ts +2 -61
  16. package/src/feature/featureBinding.ts +158 -0
  17. package/src/feature/featureClass.ts +162 -0
  18. package/src/feature/featureConfig.ts +192 -0
  19. package/src/feature/featureFactory.ts +163 -0
  20. package/src/feature/featureModule.ts +136 -0
  21. package/src/feature/featureModule.typecheck.ts +63 -0
  22. package/src/feature/featureNativeTree.ts +152 -0
  23. package/src/feature/featureRequirement.ts +82 -0
  24. package/src/feature/featureVariants.ts +234 -0
  25. package/src/feature/mountFeature.ts +54 -0
  26. package/src/graph/closure.ts +45 -226
  27. package/src/graph/services.ts +95 -0
  28. package/src/graph/summary.ts +134 -0
  29. package/src/internal/queryDriver.ts +20 -89
  30. package/src/internal/queryDriverHydrate.ts +45 -0
  31. package/src/internal/queryDriverTypes.ts +8 -10
  32. package/src/internal/store.test.ts +27 -6
  33. package/src/remote/pendingQueue.ts +145 -0
  34. package/src/remote/remoteState.test.ts +28 -22
  35. package/src/remote/remoteState.ts +63 -489
  36. package/src/remote/remoteStateMake.ts +97 -0
  37. package/src/remote/remoteStateSend.ts +122 -0
  38. package/src/remote/remoteStateTypes.ts +155 -0
  39. package/src/runtime/appRuntime.activation.test.ts +9 -5
  40. package/src/runtime/appRuntime.test.ts +40 -16
  41. package/src/runtime/appRuntime.ts +17 -472
  42. package/src/runtime/capturedAppRuntime.ts +274 -0
  43. package/src/runtime/eventBudget.test.ts +38 -8
  44. package/src/runtime/featureMount.ts +94 -0
  45. package/src/runtime/hardening.test.ts +18 -4
  46. package/src/runtime/instrumentation.test.ts +49 -12
  47. package/src/runtime/loop.test.ts +51 -10
  48. package/src/runtime/runtimeHandle.ts +124 -0
  49. package/src/state/stateFamily.test.ts +25 -8
  50. package/src/testkit/flight.testkit.ts +9 -0
@@ -1,4 +1,4 @@
1
- import { Context, Layer, Schema as S } from 'effect'
1
+ import { Layer, Schema as S } from 'effect'
2
2
  import * as Composition from '../compose/composition'
3
3
  import { provide } from '../compose/provide'
4
4
  import {
@@ -12,61 +12,10 @@ import {
12
12
  import { mount } from '../compose/structure'
13
13
  import { type Contract, type UiClass, ui } from '../compose/ui'
14
14
  import { scene } from '../scene/scene'
15
- import * as State from '../state/state'
16
- import * as StateGroup from '../state/stateGroup'
17
15
  import { type EngineServices, type FeatureModule, featureModule, lazyImport } from './feature'
18
16
  import * as Feature from './feature'
17
+ import { Clock, okService } from './featureModule.typecheck'
19
18
 
20
- const FeedStateBase: State.StateClass<'feed', string> = State.make('feed', S.String)
21
- class FeedState extends FeedStateBase {}
22
- const FilterStateBase: State.StateClass<'filter', string> = State.make('filter', S.String)
23
- class FilterState extends FilterStateBase {}
24
- const TodosStatesBase: StateGroup.StateGroupClass<readonly [typeof FeedState, typeof FilterState]> =
25
- StateGroup.make(FeedState, FilterState)
26
- class TodosStates extends TodosStatesBase {}
27
-
28
- interface ClockService {
29
- readonly now: () => number
30
- }
31
- const ClockBase: Context.TagClass<Clock, 'feature.typecheck.Clock', ClockService> = Context.Tag(
32
- 'feature.typecheck.Clock',
33
- )<Clock, ClockService>()
34
- class Clock extends ClockBase {}
35
-
36
- declare const readsFeed: Layer.Layer<
37
- { readonly _out: true },
38
- never,
39
- State.StateStore<'feed', string> | EngineServices
40
- >
41
-
42
- declare const readsTodos: Layer.Layer<
43
- { readonly _out: true },
44
- never,
45
- State.StateStore<'feed', string> | State.StateStore<'filter', string> | EngineServices
46
- >
47
-
48
- const okState: FeatureModule<{ readonly _out: true }, readonly [typeof FeedState]> = featureModule(
49
- [FeedState],
50
- readsFeed,
51
- )
52
-
53
- const okGroup: FeatureModule<{ readonly _out: true }, readonly [typeof TodosStates]> =
54
- featureModule([TodosStates], readsTodos)
55
-
56
- const badEmpty =
57
- // @ts-expect-error feature layer reads a store it does not declare in `requires`
58
- featureModule([], readsFeed)
59
-
60
- declare const readsClock: Layer.Layer<{ readonly _clock: true }, never, Clock | EngineServices>
61
-
62
- const okService: FeatureModule<{ readonly _clock: true }, readonly [typeof Clock]> = featureModule(
63
- [Clock],
64
- readsClock,
65
- )
66
-
67
- const badService =
68
- // @ts-expect-error feature layer reads an ordinary Context service it did not declare
69
- featureModule([], readsClock)
70
19
 
71
20
  const AppUiBase: UiClass<{ props: { readonly a: string }; events: {} }, 'AppUi'> = ui('AppUi')<{
72
21
  props: { readonly a: string }
@@ -143,9 +92,6 @@ declare const broadRootLayer: Layer.Layer<Composition.CompositionId<string, unkn
143
92
  // @ts-expect-error a broad composition identifier does not prove the exact scene root
144
93
  const broadRootScene = scene(AppComp, { provide: [broadRootLayer] })
145
94
 
146
- declare const privateEngine: Layer.Layer<EngineServices, never, EngineServices>
147
- // @ts-expect-error a Feature module cannot provide its own Engine services
148
- const invalidPrivateEngine = featureModule([], privateEngine)
149
95
 
150
96
  const wired = provide(AppFeatureSlot, AppFeature)
151
97
 
@@ -297,10 +243,6 @@ void featureTypeProofs
297
243
  void appNative
298
244
  void otherNative
299
245
  void AppFeatureTwin
300
- void okState
301
- void okGroup
302
- void badEmpty
303
- void badService
304
246
  void EmptyAppFeature
305
247
  void ExactUnionAppFeature
306
248
  void UnknownRootAppFeature
@@ -308,6 +250,5 @@ void BroadRootAppFeature
308
250
  void exactUnionScene
309
251
  void unknownRootScene
310
252
  void broadRootScene
311
- void invalidPrivateEngine
312
253
 
313
254
  export {}
@@ -0,0 +1,158 @@
1
+ import type { Effect, Option } from 'effect'
2
+ import type { AnyComposition, CompositionClass } from '../compose/composition'
3
+ import type { Manifest } from '../definition/definition'
4
+ import {
5
+ type AnyFeatureGraphSummary,
6
+ FeatureGraphValidTypeId,
7
+ type FeatureSummaryCompositionIdentity,
8
+ type FeatureSummaryCompositionProps,
9
+ type FeatureSummaryContract,
10
+ type FeatureSummaryInput,
11
+ type FeatureSummaryName,
12
+ type FeatureSummaryOpenServices,
13
+ type FeatureSummaryStates,
14
+ type FeatureSummarySupportOpenServices,
15
+ type FeatureSummaryUsesInput,
16
+ } from '../graph/closure'
17
+ import type { FeatureLoadFailed } from '../internal/errors'
18
+ import type { Tagged } from '../runtime/bus'
19
+ import type { LoadedModule } from './featureModule'
20
+ import type { FeatureRequirement } from './featureRequirement'
21
+
22
+ export interface FailedProps {
23
+ readonly error: FeatureLoadFailed
24
+ readonly retry: () => void
25
+ }
26
+
27
+ export interface FeatureManifest extends Manifest {
28
+ readonly kind: 'Feature'
29
+ readonly name: string
30
+ readonly strategy: 'lazy' | 'default'
31
+ readonly composition: Manifest & { readonly kind: 'Composition' }
32
+ readonly placeholder: Option.Option<{
33
+ readonly loading: Manifest & { readonly kind: 'Composition' }
34
+ readonly failed: Manifest & { readonly kind: 'Composition' }
35
+ }>
36
+ }
37
+
38
+ export const FeatureBindingTypeId: unique symbol = Symbol.for('reform/FeatureBinding')
39
+ export type FeatureBindingTypeId = typeof FeatureBindingTypeId
40
+ export type FeatureBindingType = FeatureBindingTypeId
41
+
42
+ export const FeatureTokenIdentityTypeId: unique symbol = Symbol('reform/FeatureTokenIdentity')
43
+ export const FeatureNativeTypeId: unique symbol = Symbol('reform/FeatureNative')
44
+
45
+ export interface FeatureIdentityToken<out FeatureIdentity> {
46
+ readonly identity: symbol
47
+ readonly [FeatureTokenIdentityTypeId]: readonly [] | readonly [FeatureIdentity]
48
+ }
49
+
50
+ export interface FeatureToken<
51
+ out FeatureIdentity,
52
+ out NativeTree extends object,
53
+ > extends FeatureIdentityToken<FeatureIdentity> {
54
+ readonly [FeatureNativeTypeId]: NativeTree
55
+ }
56
+
57
+ export interface FeatureTreeCarrier {
58
+ readonly token: FeatureToken<unknown, object>
59
+ }
60
+
61
+ type Native<
62
+ Feature extends FeatureTreeCarrier,
63
+ Token extends Feature['token'] = Feature['token'],
64
+ > = Token[typeof FeatureNativeTypeId]
65
+
66
+ export const tree = <
67
+ Feature extends FeatureTreeCarrier,
68
+ Token extends Feature['token'] = Feature['token'],
69
+ >(
70
+ token: Token,
71
+ ): Native<Feature, Token> => token[FeatureNativeTypeId]
72
+
73
+ export interface ProvideableFeature<
74
+ out FeatureIdentity,
75
+ out Summary extends AnyFeatureGraphSummary,
76
+ > {
77
+ new (): {}
78
+ readonly manifest: FeatureManifest
79
+ readonly token: FeatureIdentityToken<FeatureIdentity>
80
+ readonly summary: Summary
81
+ }
82
+
83
+ export interface FeatureDefinition<
84
+ out FeatureIdentity,
85
+ out Summary extends AnyFeatureGraphSummary,
86
+ out NativeTree extends object,
87
+ > extends ProvideableFeature<FeatureIdentity, Summary> {
88
+ readonly token: FeatureToken<FeatureIdentity, NativeTree>
89
+ }
90
+
91
+ export type FeatureOpenServices<Feature extends { readonly summary: AnyFeatureGraphSummary }> =
92
+ FeatureSummaryOpenServices<Feature['summary']>
93
+
94
+ export type FeatureSupportOpenServices<
95
+ Feature extends { readonly summary: AnyFeatureGraphSummary },
96
+ > = FeatureSummarySupportOpenServices<Feature['summary']>
97
+
98
+ export interface AnyFeatureBindingExternalApi {
99
+ readonly [FeatureBindingTypeId]: FeatureBindingTypeId
100
+ readonly [FeatureGraphValidTypeId]: FeatureGraphValidTypeId
101
+ readonly capture: <Result>(visit: FeatureBindingCapture<Result>) => Result
102
+ }
103
+
104
+ export type AnyFeatureBinding = AnyFeatureBindingExternalApi
105
+
106
+ export interface FeatureBinding<
107
+ Summary extends AnyFeatureGraphSummary,
108
+ ROut,
109
+ DirectRequires extends ReadonlyArray<FeatureRequirement>,
110
+ > extends AnyFeatureBindingExternalApi {
111
+ readonly manifest: FeatureManifest
112
+ readonly identity: symbol
113
+ readonly summary: Summary
114
+ readonly composition: CompositionClass<
115
+ FeatureSummaryCompositionProps<Summary>,
116
+ FeatureSummaryContract<Summary>,
117
+ FeatureSummaryStates<Summary>,
118
+ FeatureSummaryName<Summary>,
119
+ FeatureSummaryCompositionIdentity<Summary>
120
+ >
121
+ readonly strategy: 'lazy' | 'default'
122
+ readonly load: Effect.Effect<
123
+ LoadedModule<
124
+ ROut,
125
+ DirectRequires,
126
+ FeatureSummaryOpenServices<Summary>,
127
+ FeatureSummaryUsesInput<Summary>,
128
+ FeatureSummaryInput<Summary>
129
+ >,
130
+ FeatureLoadFailed
131
+ >
132
+ readonly placeholder: Option.Option<{
133
+ readonly loading: AnyComposition
134
+ readonly failed: AnyComposition
135
+ }>
136
+ readonly parseInput: (input: unknown) => Option.Option<unknown>
137
+ readonly boot: ReadonlyArray<Tagged>
138
+ }
139
+
140
+ export type CapturedFeatureBinding<
141
+ Summary extends AnyFeatureGraphSummary,
142
+ ROut,
143
+ DirectRequires extends ReadonlyArray<FeatureRequirement>,
144
+ > = FeatureBinding<Summary, ROut, DirectRequires>
145
+
146
+ export type FeatureBindingCapture<Result> = <
147
+ Summary extends AnyFeatureGraphSummary,
148
+ ROut,
149
+ DirectRequires extends ReadonlyArray<FeatureRequirement>,
150
+ >(
151
+ binding: FeatureBinding<Summary, ROut, DirectRequires>,
152
+ ) => Result
153
+
154
+ export const isFeatureBinding = (candidate: unknown): candidate is AnyFeatureBinding =>
155
+ typeof candidate === 'object' &&
156
+ candidate !== null &&
157
+ FeatureBindingTypeId in candidate &&
158
+ FeatureGraphValidTypeId in candidate
@@ -0,0 +1,162 @@
1
+ import type { CompositionClass } from '../compose/composition'
2
+ import type { UiContract } from '../compose/ui'
3
+ import type { FeatureDefinition } from './featureBinding'
4
+ import type {
5
+ EagerFeatureNativeTree,
6
+ FeatureNativeTree,
7
+ FeatureSummaryOf,
8
+ LazyFeatureNativeTree,
9
+ } from './featureNativeTree'
10
+ import type {
11
+ DefaultFeatureOpenServices,
12
+ FeatureRequirement,
13
+ RootCompositionIdentity,
14
+ RootCompositionName,
15
+ } from './featureRequirement'
16
+
17
+ export interface FeatureClass<
18
+ FeatureIdentity,
19
+ P,
20
+ C extends UiContract,
21
+ ROut,
22
+ DirectRequires extends ReadonlyArray<FeatureRequirement>,
23
+ OpenServices = DefaultFeatureOpenServices<ROut, DirectRequires>,
24
+ SupportOut = never,
25
+ SupportDirectRequires extends ReadonlyArray<FeatureRequirement> = readonly [],
26
+ SupportOpenServices = DefaultFeatureOpenServices<SupportOut, SupportDirectRequires>,
27
+ UsesInput extends boolean = false,
28
+ Input = UsesInput extends true ? P : never,
29
+ S extends ReadonlyArray<unknown> = ReadonlyArray<unknown>,
30
+ N extends string = RootCompositionName<ROut>,
31
+ CompositionProps = P,
32
+ Identity = RootCompositionIdentity<ROut>,
33
+ Composition extends CompositionClass<CompositionProps, C, S, N, Identity> = CompositionClass<
34
+ CompositionProps,
35
+ C,
36
+ S,
37
+ N,
38
+ Identity
39
+ >,
40
+ > extends FeatureDefinition<
41
+ FeatureIdentity,
42
+ FeatureSummaryOf<
43
+ FeatureIdentity,
44
+ P,
45
+ CompositionProps,
46
+ C,
47
+ S,
48
+ N,
49
+ Identity,
50
+ OpenServices,
51
+ SupportOpenServices,
52
+ UsesInput,
53
+ Input
54
+ >,
55
+ FeatureNativeTree<
56
+ FeatureSummaryOf<
57
+ FeatureIdentity,
58
+ P,
59
+ CompositionProps,
60
+ C,
61
+ S,
62
+ N,
63
+ Identity,
64
+ OpenServices,
65
+ SupportOpenServices,
66
+ UsesInput,
67
+ Input
68
+ >,
69
+ ROut,
70
+ DirectRequires,
71
+ SupportOut,
72
+ SupportDirectRequires,
73
+ Composition
74
+ >
75
+ > {}
76
+
77
+ export type EagerFeatureClass<
78
+ FeatureIdentity,
79
+ P,
80
+ C extends UiContract,
81
+ ROut,
82
+ DirectRequires extends ReadonlyArray<FeatureRequirement>,
83
+ OpenServices,
84
+ S extends ReadonlyArray<unknown>,
85
+ N extends string,
86
+ Identity,
87
+ Composition extends CompositionClass<P, C, S, N, Identity> = CompositionClass<
88
+ P,
89
+ C,
90
+ S,
91
+ N,
92
+ Identity
93
+ >,
94
+ > = FeatureDefinition<
95
+ FeatureIdentity,
96
+ FeatureSummaryOf<FeatureIdentity, P, P, C, S, N, Identity, OpenServices, never, false, never>,
97
+ EagerFeatureNativeTree<
98
+ FeatureSummaryOf<FeatureIdentity, P, P, C, S, N, Identity, OpenServices, never, false, never>,
99
+ ROut,
100
+ DirectRequires,
101
+ Composition
102
+ >
103
+ >
104
+
105
+ export type LazyFeatureClass<
106
+ FeatureIdentity,
107
+ P,
108
+ C extends UiContract,
109
+ ROut,
110
+ DirectRequires extends ReadonlyArray<FeatureRequirement>,
111
+ OpenServices,
112
+ SupportOut,
113
+ SupportDirectRequires extends ReadonlyArray<FeatureRequirement>,
114
+ SupportOpenServices,
115
+ UsesInput extends boolean,
116
+ S extends ReadonlyArray<unknown>,
117
+ N extends string,
118
+ CompositionProps,
119
+ Identity,
120
+ Composition extends CompositionClass<CompositionProps, C, S, N, Identity> = CompositionClass<
121
+ CompositionProps,
122
+ C,
123
+ S,
124
+ N,
125
+ Identity
126
+ >,
127
+ > = FeatureDefinition<
128
+ FeatureIdentity,
129
+ FeatureSummaryOf<
130
+ FeatureIdentity,
131
+ P,
132
+ CompositionProps,
133
+ C,
134
+ S,
135
+ N,
136
+ Identity,
137
+ OpenServices,
138
+ SupportOpenServices,
139
+ UsesInput,
140
+ UsesInput extends true ? P : never
141
+ >,
142
+ LazyFeatureNativeTree<
143
+ FeatureSummaryOf<
144
+ FeatureIdentity,
145
+ P,
146
+ CompositionProps,
147
+ C,
148
+ S,
149
+ N,
150
+ Identity,
151
+ OpenServices,
152
+ SupportOpenServices,
153
+ UsesInput,
154
+ UsesInput extends true ? P : never
155
+ >,
156
+ ROut,
157
+ DirectRequires,
158
+ SupportOut,
159
+ SupportDirectRequires,
160
+ Composition
161
+ >
162
+ >
@@ -0,0 +1,192 @@
1
+ import type { Effect } from 'effect'
2
+ import { Schema } from 'effect'
3
+ import type {
4
+ AnyComposition,
5
+ CompositionClass,
6
+ CompositionPropsReceiver,
7
+ HasExactCompositionId,
8
+ } from '../compose/composition'
9
+ import type { UiContract } from '../compose/ui'
10
+ import type { AnyFeatureGraphSummary } from '../graph/closure'
11
+ import type { FeatureLoadFailed } from '../internal/errors'
12
+ import type { Tagged } from '../runtime/bus'
13
+ import {
14
+ type AnyFeatureBinding,
15
+ type FailedProps,
16
+ type FeatureManifest,
17
+ FeatureNativeTypeId,
18
+ type FeatureToken,
19
+ } from './featureBinding'
20
+ import type { AnyLoadedModule, FeatureModule } from './featureModule'
21
+ import type { FeatureRequirement } from './featureRequirement'
22
+
23
+ export interface RuntimeFeatureTree {
24
+ readonly composition: AnyComposition
25
+ readonly load: Effect.Effect<AnyLoadedModule, FeatureLoadFailed>
26
+ readonly binding: AnyFeatureBinding
27
+ readonly eagerModule: AnyLoadedModule | undefined
28
+ readonly supportModule: AnyLoadedModule | undefined
29
+ }
30
+
31
+ export interface RuntimeFeature {
32
+ new (): {}
33
+ readonly manifest: FeatureManifest
34
+ readonly token: FeatureToken<unknown, RuntimeFeatureTree>
35
+ readonly summary: AnyFeatureGraphSummary
36
+ }
37
+
38
+ const isRuntimeFeatureToken = (
39
+ candidate: unknown,
40
+ ): candidate is FeatureToken<unknown, RuntimeFeatureTree> =>
41
+ typeof candidate === 'object' && candidate !== null && FeatureNativeTypeId in candidate
42
+
43
+ export const isFeature = (candidate: unknown): candidate is RuntimeFeature =>
44
+ (typeof candidate === 'function' || typeof candidate === 'object') &&
45
+ candidate !== null &&
46
+ 'token' in candidate &&
47
+ isRuntimeFeatureToken(candidate.token)
48
+
49
+ export type PlaceholderComposition<P> = AnyComposition & CompositionPropsReceiver<P>
50
+
51
+ export interface Placeholders<P> {
52
+ readonly loading: PlaceholderComposition<P>
53
+ readonly failed: PlaceholderComposition<FailedProps>
54
+ }
55
+
56
+ export type FeatureMountProps<
57
+ UsesInput extends boolean,
58
+ CompositionProps,
59
+ InputSchema extends Schema.Schema.AnyNoContext,
60
+ > = UsesInput extends true ? Schema.Schema.Type<InputSchema> : CompositionProps
61
+
62
+ export type FeatureUsesInput<InputSchema extends Schema.Schema.AnyNoContext> = [InputSchema] extends [
63
+ never,
64
+ ]
65
+ ? false
66
+ : true
67
+
68
+ export type FeatureInputValue<InputSchema extends Schema.Schema.AnyNoContext> = [InputSchema] extends [
69
+ never,
70
+ ]
71
+ ? never
72
+ : Schema.Schema.Type<InputSchema>
73
+
74
+ export interface FeatureConfigBaseExternalApi<
75
+ P,
76
+ C extends UiContract,
77
+ S extends ReadonlyArray<unknown>,
78
+ N extends string,
79
+ Identity,
80
+ > {
81
+ readonly composition: CompositionClass<P, C, S, N, Identity>
82
+ readonly boot?: ReadonlyArray<Tagged>
83
+ }
84
+
85
+ export interface ExactFeatureCompositionConfig<Composition extends AnyComposition> {
86
+ readonly composition: Composition
87
+ }
88
+
89
+ export type IncludesComposition<ROut, N extends string, Identity> =
90
+ HasExactCompositionId<ROut, N, Identity> extends true
91
+ ? object
92
+ : {
93
+ readonly missingCompositionService: 'The feature module must provide its root composition'
94
+ }
95
+
96
+ export type EagerFeatureConfigExternalApi<
97
+ P,
98
+ C extends UiContract,
99
+ ROut,
100
+ DirectRequires extends ReadonlyArray<FeatureRequirement>,
101
+ OpenServices,
102
+ S extends ReadonlyArray<unknown>,
103
+ N extends string,
104
+ Identity,
105
+ > = FeatureConfigBaseExternalApi<P, C, S, N, Identity> & {
106
+ readonly loadingStrategy?: 'default'
107
+ readonly module: FeatureModule<ROut, DirectRequires, OpenServices, false, never> &
108
+ IncludesComposition<ROut, N, Identity>
109
+ }
110
+
111
+ export type LazyFeatureConfigExternalApi<
112
+ CompositionProps,
113
+ C extends UiContract,
114
+ ROut,
115
+ DirectRequires extends ReadonlyArray<FeatureRequirement>,
116
+ OpenServices,
117
+ SupportOut,
118
+ SupportDirectRequires extends ReadonlyArray<FeatureRequirement>,
119
+ SupportOpenServices,
120
+ S extends ReadonlyArray<unknown>,
121
+ N extends string,
122
+ Identity,
123
+ InputSchema extends Schema.Schema.AnyNoContext,
124
+ Loading extends AnyComposition,
125
+ Failed extends AnyComposition,
126
+ > = FeatureConfigBaseExternalApi<CompositionProps, C, S, N, Identity> & {
127
+ readonly composition: CompositionClass<CompositionProps, C, S, N, Identity> &
128
+ CompositionPropsReceiver<
129
+ NoInfer<FeatureMountProps<FeatureUsesInput<InputSchema>, CompositionProps, InputSchema>>
130
+ >
131
+ readonly loadingStrategy: 'lazy'
132
+ readonly input?: InputSchema
133
+ readonly load: Effect.Effect<
134
+ FeatureModule<
135
+ ROut,
136
+ DirectRequires,
137
+ OpenServices,
138
+ FeatureUsesInput<InputSchema>,
139
+ FeatureInputValue<InputSchema>
140
+ > &
141
+ IncludesComposition<ROut, N, Identity>,
142
+ FeatureLoadFailed
143
+ >
144
+ readonly placeholder: {
145
+ readonly loading: Loading &
146
+ CompositionPropsReceiver<
147
+ NoInfer<FeatureMountProps<FeatureUsesInput<InputSchema>, CompositionProps, InputSchema>>
148
+ >
149
+ readonly failed: Failed & CompositionPropsReceiver<FailedProps>
150
+ }
151
+ readonly eager?: FeatureModule<
152
+ SupportOut,
153
+ SupportDirectRequires,
154
+ SupportOpenServices,
155
+ false,
156
+ never
157
+ >
158
+ } & (FeatureUsesInput<InputSchema> extends true ? { readonly input: InputSchema } : object)
159
+
160
+ export type MakeImplementationConfigExternalApi =
161
+ | {
162
+ readonly composition: AnyComposition
163
+ readonly boot?: ReadonlyArray<Tagged>
164
+ readonly loadingStrategy?: 'default'
165
+ readonly module: AnyLoadedModule
166
+ }
167
+ | {
168
+ readonly composition: AnyComposition
169
+ readonly boot?: ReadonlyArray<Tagged>
170
+ readonly loadingStrategy: 'lazy'
171
+ readonly input?: Schema.Schema.Any
172
+ readonly load: Effect.Effect<AnyLoadedModule, FeatureLoadFailed>
173
+ readonly placeholder: {
174
+ readonly loading: AnyComposition
175
+ readonly failed: AnyComposition
176
+ }
177
+ readonly eager?: AnyLoadedModule
178
+ }
179
+
180
+ export const isMakeImplementationConfig = (
181
+ candidate: unknown,
182
+ ): candidate is MakeImplementationConfigExternalApi =>
183
+ typeof candidate === 'object' &&
184
+ candidate !== null &&
185
+ 'composition' in candidate &&
186
+ (!('input' in candidate) || Schema.isSchema(candidate.input)) &&
187
+ ('module' in candidate || ('load' in candidate && 'placeholder' in candidate))
188
+
189
+ export type RuntimePlaceholders = {
190
+ readonly loading: AnyComposition
191
+ readonly failed: AnyComposition
192
+ }