@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
@@ -0,0 +1,234 @@
1
+ import { Effect, Option, type Schema } from 'effect'
2
+ import type { AnyComposition, CompositionClass } from '../compose/composition'
3
+ import type { UiContract } from '../compose/ui'
4
+ import { definitionClass } from '../definition/definition'
5
+ import {
6
+ FeatureNativeTypeId,
7
+ type FeatureToken,
8
+ FeatureTokenIdentityTypeId,
9
+ } from './featureBinding'
10
+ import type { EagerFeatureClass, LazyFeatureClass } from './featureClass'
11
+ import type {
12
+ EagerFeatureConfigExternalApi,
13
+ ExactFeatureCompositionConfig,
14
+ FeatureInputValue,
15
+ FeatureMountProps,
16
+ FeatureUsesInput,
17
+ LazyFeatureConfigExternalApi,
18
+ RuntimePlaceholders,
19
+ } from './featureConfig'
20
+ import { makeFeatureBinding, makeFeatureManifest, makeFeatureSummary } from './featureFactory'
21
+ import type { EagerFeatureNativeTree, LazyFeatureNativeTree } from './featureNativeTree'
22
+ import type { FeatureRequirement } from './featureRequirement'
23
+
24
+ export const makeEagerFeature = <
25
+ P,
26
+ C extends UiContract,
27
+ ROut,
28
+ DirectRequires extends ReadonlyArray<FeatureRequirement>,
29
+ OpenServices,
30
+ S extends ReadonlyArray<unknown>,
31
+ N extends string,
32
+ Identity,
33
+ Composition extends CompositionClass<P, C, S, N, Identity>,
34
+ >(
35
+ name: string,
36
+ config: EagerFeatureConfigExternalApi<P, C, ROut, DirectRequires, OpenServices, S, N, Identity> &
37
+ ExactFeatureCompositionConfig<Composition>,
38
+ ): EagerFeatureClass<
39
+ Identity,
40
+ P,
41
+ C,
42
+ ROut,
43
+ DirectRequires,
44
+ OpenServices,
45
+ S,
46
+ N,
47
+ Identity,
48
+ Composition
49
+ > => {
50
+ const featureIdentity = Symbol(name)
51
+ const placeholder = Option.none<RuntimePlaceholders>()
52
+ const manifest = makeFeatureManifest(name, 'default', config.composition, placeholder)
53
+ const load = Effect.succeed(config.module)
54
+ const summary = makeFeatureSummary<
55
+ Identity,
56
+ P,
57
+ P,
58
+ C,
59
+ S,
60
+ N,
61
+ Identity,
62
+ OpenServices,
63
+ never,
64
+ false,
65
+ never
66
+ >(config.composition)
67
+ const binding = makeFeatureBinding<typeof summary, ROut, DirectRequires>(
68
+ featureIdentity,
69
+ manifest,
70
+ summary,
71
+ config.composition,
72
+ load,
73
+ placeholder,
74
+ undefined,
75
+ Option.getOrElse(Option.fromNullable(config.boot), () => []),
76
+ )
77
+ const native: EagerFeatureNativeTree<typeof summary, ROut, DirectRequires, Composition> = {
78
+ identity: featureIdentity,
79
+ summary,
80
+ composition: config.composition,
81
+ load,
82
+ binding,
83
+ eagerModule: config.module,
84
+ supportModule: undefined,
85
+ }
86
+ const token: FeatureToken<Identity, typeof native> = {
87
+ identity: featureIdentity,
88
+ [FeatureTokenIdentityTypeId]: [],
89
+ [FeatureNativeTypeId]: native,
90
+ }
91
+ return definitionClass<
92
+ EagerFeatureClass<
93
+ Identity,
94
+ P,
95
+ C,
96
+ ROut,
97
+ DirectRequires,
98
+ OpenServices,
99
+ S,
100
+ N,
101
+ Identity,
102
+ Composition
103
+ >
104
+ >({
105
+ manifest,
106
+ summary,
107
+ token,
108
+ })
109
+ }
110
+
111
+ export const makeLazyFeature = <
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
+ Composition extends CompositionClass<CompositionProps, C, S, N, Identity>,
124
+ InputSchema extends Schema.Schema.AnyNoContext,
125
+ Loading extends AnyComposition,
126
+ Failed extends AnyComposition,
127
+ >(
128
+ name: string,
129
+ config: LazyFeatureConfigExternalApi<
130
+ CompositionProps,
131
+ C,
132
+ ROut,
133
+ DirectRequires,
134
+ OpenServices,
135
+ SupportOut,
136
+ SupportDirectRequires,
137
+ SupportOpenServices,
138
+ S,
139
+ N,
140
+ Identity,
141
+ InputSchema,
142
+ Loading,
143
+ Failed
144
+ > &
145
+ ExactFeatureCompositionConfig<Composition>,
146
+ ): LazyFeatureClass<
147
+ Identity,
148
+ FeatureMountProps<FeatureUsesInput<InputSchema>, CompositionProps, InputSchema>,
149
+ C,
150
+ ROut,
151
+ DirectRequires,
152
+ OpenServices,
153
+ SupportOut,
154
+ SupportDirectRequires,
155
+ SupportOpenServices,
156
+ FeatureUsesInput<InputSchema>,
157
+ S,
158
+ N,
159
+ CompositionProps,
160
+ Identity,
161
+ Composition
162
+ > => {
163
+ const featureIdentity = Symbol(name)
164
+ const placeholder = Option.some<RuntimePlaceholders>(config.placeholder)
165
+ const manifest = makeFeatureManifest(name, 'lazy', config.composition, placeholder)
166
+ const inputSchema = 'input' in config ? config.input : undefined
167
+ const summary = makeFeatureSummary<
168
+ Identity,
169
+ FeatureMountProps<FeatureUsesInput<InputSchema>, CompositionProps, InputSchema>,
170
+ CompositionProps,
171
+ C,
172
+ S,
173
+ N,
174
+ Identity,
175
+ OpenServices,
176
+ SupportOpenServices,
177
+ FeatureUsesInput<InputSchema>,
178
+ FeatureInputValue<InputSchema>
179
+ >(config.composition)
180
+ const binding = makeFeatureBinding<typeof summary, ROut, DirectRequires>(
181
+ featureIdentity,
182
+ manifest,
183
+ summary,
184
+ config.composition,
185
+ config.load,
186
+ placeholder,
187
+ inputSchema,
188
+ Option.getOrElse(Option.fromNullable(config.boot), () => []),
189
+ )
190
+ const native: LazyFeatureNativeTree<
191
+ typeof summary,
192
+ ROut,
193
+ DirectRequires,
194
+ SupportOut,
195
+ SupportDirectRequires,
196
+ Composition
197
+ > = {
198
+ identity: featureIdentity,
199
+ summary,
200
+ composition: config.composition,
201
+ load: config.load,
202
+ binding,
203
+ eagerModule: undefined,
204
+ supportModule: config.eager,
205
+ }
206
+ const token: FeatureToken<Identity, typeof native> = {
207
+ identity: featureIdentity,
208
+ [FeatureTokenIdentityTypeId]: [],
209
+ [FeatureNativeTypeId]: native,
210
+ }
211
+ return definitionClass<
212
+ LazyFeatureClass<
213
+ Identity,
214
+ FeatureMountProps<FeatureUsesInput<InputSchema>, CompositionProps, InputSchema>,
215
+ C,
216
+ ROut,
217
+ DirectRequires,
218
+ OpenServices,
219
+ SupportOut,
220
+ SupportDirectRequires,
221
+ SupportOpenServices,
222
+ FeatureUsesInput<InputSchema>,
223
+ S,
224
+ N,
225
+ CompositionProps,
226
+ Identity,
227
+ Composition
228
+ >
229
+ >({
230
+ manifest,
231
+ summary,
232
+ token,
233
+ })
234
+ }
@@ -0,0 +1,54 @@
1
+ import { Context, Effect, Layer, type Scope } from 'effect'
2
+ import type {
3
+ AnyFeatureGraphSummary,
4
+ FeatureSummaryInput,
5
+ FeatureSummaryOpenServices,
6
+ } from '../graph/closure'
7
+ import type { FeatureLoadFailed } from '../internal/errors'
8
+ import { Bus, publish } from '../runtime/bus'
9
+ import type { EngineServices } from '../runtime/loop'
10
+ import type { FeatureBinding } from './featureBinding'
11
+ import { FeatureInput, type FeatureRequirement } from './featureRequirement'
12
+
13
+ type MountFeature = <
14
+ Summary extends AnyFeatureGraphSummary,
15
+ ROut,
16
+ const DirectRequires extends ReadonlyArray<FeatureRequirement>,
17
+ HostServices,
18
+ >(
19
+ binding: FeatureBinding<Summary, ROut, DirectRequires>,
20
+ engineContext: Context.Context<
21
+ HostServices | EngineServices | FeatureSummaryOpenServices<Summary>
22
+ >,
23
+ props?: FeatureSummaryInput<Summary>,
24
+ ) => Effect.Effect<
25
+ Context.Context<HostServices | EngineServices | FeatureSummaryOpenServices<Summary> | ROut>,
26
+ FeatureLoadFailed,
27
+ Scope.Scope
28
+ >
29
+
30
+ export const mountFeature: MountFeature = Effect.fn('mountFeature')(function* <
31
+ Summary extends AnyFeatureGraphSummary,
32
+ ROut,
33
+ const DirectRequires extends ReadonlyArray<FeatureRequirement>,
34
+ HostServices,
35
+ >(
36
+ binding: FeatureBinding<Summary, ROut, DirectRequires>,
37
+ engineContext: Context.Context<
38
+ HostServices | EngineServices | FeatureSummaryOpenServices<Summary>
39
+ >,
40
+ props: FeatureSummaryInput<Summary> | undefined = undefined,
41
+ ): Effect.fn.Return<
42
+ Context.Context<HostServices | EngineServices | FeatureSummaryOpenServices<Summary> | ROut>,
43
+ FeatureLoadFailed,
44
+ Scope.Scope
45
+ > {
46
+ const { layer } = yield* binding.load
47
+ const bus = Context.get(engineContext, Bus)
48
+ const featureContext = Context.add(engineContext, FeatureInput, props)
49
+ const context = yield* Layer.build(Layer.provide(layer, Layer.succeedContext(featureContext)))
50
+ yield* Effect.forEach(binding.boot, (event) => publish('High', event), {
51
+ discard: true,
52
+ }).pipe(Effect.provideService(Bus, bus))
53
+ return Context.merge(engineContext, context)
54
+ })
@@ -1,232 +1,51 @@
1
- import { Layer } from 'effect'
1
+ import type { Layer } from 'effect'
2
2
  import { CompositionIdTypeId } from '../compose/composition'
3
- import type { UiContract } from '../compose/ui'
4
3
  import { SlotServiceTypeId } from '../compose/slot'
5
- import type { FeatureInput, FeatureRequirement, ProvidedBy } from '../feature/feature'
4
+ import type { FeatureRequirement, ProvidedBy } from '../feature/feature'
6
5
  import type { EngineServices } from '../runtime/loop'
7
- import type { StateStore } from '../state/state'
8
- import type { StateFamilyStore } from '../state/stateFamily'
9
-
10
- export const FeatureGraphValidTypeId: unique symbol = Symbol.for('reform/FeatureGraphValid')
11
- export type FeatureGraphValidTypeId = typeof FeatureGraphValidTypeId
12
-
13
- export const FeatureModuleGraphValidTypeId: unique symbol = Symbol.for(
14
- 'reform/FeatureModuleGraphValid',
15
- )
16
- export type FeatureModuleGraphValidTypeId = typeof FeatureModuleGraphValidTypeId
17
-
18
- export const FeatureChildSummaryTypeId: unique symbol = Symbol.for('reform/FeatureChildSummary')
19
- export type FeatureChildSummaryTypeId = typeof FeatureChildSummaryTypeId
20
-
21
- export const FeatureGraphSummaryTypeId: unique symbol = Symbol.for('reform/FeatureGraphSummary')
22
- export type FeatureGraphSummaryTypeId = typeof FeatureGraphSummaryTypeId
23
-
24
- export const SlotBindingSummaryTypeId: unique symbol = Symbol.for('reform/SlotBindingSummary')
25
- export type SlotBindingSummaryTypeId = typeof SlotBindingSummaryTypeId
26
-
27
- export interface SlotBindingSummary {
28
- readonly [SlotBindingSummaryTypeId]: SlotBindingSummaryTypeId
29
- }
30
-
31
- /**
32
- * The constant-size proof published after a Feature's current module has passed
33
- * graph validation. Type-only facts use empty-or-singleton tuples so the runtime
34
- * summary stays compact while direct indexed access recovers their exact types.
35
- */
36
- export interface FeatureGraphSummary<
37
- out FeatureIdentity,
38
- out MountProps,
39
- out CompositionProps,
40
- out C extends UiContract,
41
- out S extends ReadonlyArray<unknown>,
42
- out N extends string,
43
- out CompositionIdentity,
44
- out OpenServices,
45
- out SupportOpenServices,
46
- out UsesInput extends boolean,
47
- out Input,
48
- > extends SlotBindingSummary {
49
- readonly [FeatureGraphSummaryTypeId]: {
50
- readonly featureIdentity: readonly [] | readonly [FeatureIdentity]
51
- readonly mountProps: readonly [] | readonly [MountProps]
52
- readonly compositionProps: readonly [] | readonly [CompositionProps]
53
- readonly contract: readonly [] | readonly [C]
54
- readonly states: readonly [] | readonly [S]
55
- readonly name: N
56
- readonly compositionIdentity: readonly [] | readonly [CompositionIdentity]
57
- readonly openServices: readonly [] | readonly [OpenServices]
58
- readonly supportOpenServices: readonly [] | readonly [SupportOpenServices]
59
- readonly usesInput: readonly [] | readonly [UsesInput]
60
- readonly input: readonly [] | readonly [Input]
61
- readonly validated: FeatureModuleGraphValidTypeId
62
- }
63
- readonly [FeatureChildSummaryTypeId]: {
64
- readonly featureIdentity: readonly [] | readonly [FeatureIdentity]
65
- readonly compositionIdentity: readonly [] | readonly [CompositionIdentity]
66
- }
67
- }
68
-
69
- export type FeatureChildSummary<
70
- FeatureIdentity,
71
- MountProps,
72
- CompositionProps,
73
- C extends UiContract,
74
- S extends ReadonlyArray<unknown>,
75
- N extends string,
76
- CompositionIdentity,
77
- OpenServices,
78
- SupportOpenServices,
79
- UsesInput extends boolean,
80
- Input,
81
- > = FeatureGraphSummary<
82
- FeatureIdentity,
83
- MountProps,
84
- CompositionProps,
85
- C,
86
- S,
87
- N,
88
- CompositionIdentity,
89
- OpenServices,
90
- SupportOpenServices,
91
- UsesInput,
92
- Input
93
- >
94
-
95
- export type AnyFeatureGraphSummary = FeatureGraphSummary<
96
- unknown,
97
- unknown,
98
- unknown,
99
- UiContract,
100
- ReadonlyArray<unknown>,
101
- string,
102
- unknown,
103
- unknown,
104
- unknown,
105
- boolean,
106
- unknown
107
- >
108
-
109
- export type FeatureSummaryIdentity<Summary extends AnyFeatureGraphSummary> =
110
- Summary[FeatureGraphSummaryTypeId]['featureIdentity'][number]
111
- export type FeatureSummaryMountProps<Summary extends AnyFeatureGraphSummary> =
112
- Summary[FeatureGraphSummaryTypeId]['mountProps'][number]
113
- export type FeatureSummaryCompositionProps<Summary extends AnyFeatureGraphSummary> =
114
- Summary[FeatureGraphSummaryTypeId]['compositionProps'][number]
115
- export type FeatureSummaryContract<Summary extends AnyFeatureGraphSummary> =
116
- Summary[FeatureGraphSummaryTypeId]['contract'][number]
117
- export type FeatureSummaryStates<Summary extends AnyFeatureGraphSummary> =
118
- Summary[FeatureGraphSummaryTypeId]['states'][number]
119
- export type FeatureSummaryName<Summary extends AnyFeatureGraphSummary> =
120
- Summary[FeatureGraphSummaryTypeId]['name']
121
- export type FeatureSummaryCompositionIdentity<Summary extends AnyFeatureGraphSummary> =
122
- Summary[FeatureGraphSummaryTypeId]['compositionIdentity'][number]
123
- export type FeatureSummaryOpenServices<Summary extends AnyFeatureGraphSummary> =
124
- Summary[FeatureGraphSummaryTypeId]['openServices'][number]
125
- export type FeatureSummarySupportOpenServices<Summary extends AnyFeatureGraphSummary> =
126
- Summary[FeatureGraphSummaryTypeId]['supportOpenServices'][number]
127
- export type FeatureSummaryUsesInput<Summary extends AnyFeatureGraphSummary> =
128
- Summary[FeatureGraphSummaryTypeId]['usesInput'][number]
129
- export type FeatureSummaryInput<Summary extends AnyFeatureGraphSummary> =
130
- Summary[FeatureGraphSummaryTypeId]['input'][number]
131
-
132
- export const CompositionChildSummaryTypeId: unique symbol = Symbol.for(
133
- 'reform/CompositionChildSummary',
134
- )
135
- export type CompositionChildSummaryTypeId = typeof CompositionChildSummaryTypeId
136
-
137
- export interface CompositionChildSummary<out CompositionIdentity> extends SlotBindingSummary {
138
- readonly [CompositionChildSummaryTypeId]: {
139
- readonly compositionIdentity: CompositionIdentity
140
- }
141
- }
142
-
143
- type IsAny<Value> = 0 extends 1 & Value ? true : false
144
-
145
- type IsErased<Value> = IsAny<Value> extends true ? true : unknown extends Value ? true : false
146
-
147
- type ExactStateStoreName<Service> =
148
- IsAny<Service> extends true
149
- ? never
150
- : Service extends StateStore<infer Name, infer _Value>
151
- ? string extends Name
152
- ? never
153
- : Name
154
- : never
155
-
156
- type ExactStateFamilyStoreName<Service> =
157
- IsAny<Service> extends true
158
- ? never
159
- : Service extends StateFamilyStore<infer Name, infer _Key, infer _Value>
160
- ? string extends Name
161
- ? never
162
- : Name
163
- : never
164
-
165
- type ServiceIsProvided<Required, Provided> =
166
- IsErased<Provided> extends true
167
- ? false
168
- : Required extends StateStore<infer Name, infer _Value>
169
- ? Name extends ExactStateStoreName<Provided>
170
- ? true
171
- : false
172
- : Required extends StateFamilyStore<infer Name, infer _Key, infer _Value>
173
- ? Name extends ExactStateFamilyStoreName<Provided>
174
- ? true
175
- : false
176
- : [Required] extends [Provided]
177
- ? true
178
- : false
179
-
180
- /**
181
- * Remove only services the provider can satisfy by their runtime Context tag.
182
- * Named State/StateFamily identifiers intentionally do not collapse into their
183
- * structurally broader Store/FamilyStore service APIs.
184
- */
185
- export type ExactServiceExclude<Required, Provided> = Required extends unknown
186
- ? ServiceIsProvided<Required, Provided> extends true
187
- ? never
188
- : Required
189
- : never
190
-
191
- type ExactServiceExtract<Required, Provided> = Required extends unknown
192
- ? ServiceIsProvided<Required, Provided> extends true
193
- ? Required
194
- : never
195
- : never
196
-
197
- type GraphValidationPassed = object
198
-
199
- type ExactIdentity<Identity> = IsErased<Identity> extends true ? never : Identity
200
-
201
- type InputService<UsesInput extends boolean> = UsesInput extends true ? FeatureInput : never
202
-
203
- export type OpenServicesFromFeatureSlotWitnesses<Services> = Services extends {
204
- readonly [SlotServiceTypeId]: {
205
- readonly binding: FeatureChildSummary<
206
- infer _FeatureIdentity,
207
- infer _MountProps,
208
- infer _CompositionProps,
209
- infer _Contract,
210
- infer _States,
211
- infer _Name,
212
- infer _CompositionIdentity,
213
- infer OpenServices,
214
- infer SupportOpenServices,
215
- infer _UsesInput,
216
- infer _Input
217
- >
218
- }
219
- }
220
- ? OpenServices | SupportOpenServices
221
- : never
222
-
223
- export type DescendantOpenServices<L extends Layer.Layer.Any> =
224
- OpenServicesFromFeatureSlotWitnesses<Layer.Layer.Success<L>>
225
-
226
- export type ModuleOpenServices<L extends Layer.Layer.Any, UsesInput extends boolean> = Exclude<
227
- Layer.Layer.Context<L>,
228
- EngineServices | InputService<UsesInput>
229
- >
6
+ import type {
7
+ ExactIdentity,
8
+ ExactServiceExclude,
9
+ ExactServiceExtract,
10
+ GraphValidationPassed,
11
+ InputService,
12
+ IsErased,
13
+ } from './services'
14
+ import type { CompositionChildSummary } from './summary'
15
+ import type { DescendantOpenServices } from './services'
16
+
17
+ export {
18
+ CompositionChildSummaryTypeId,
19
+ FeatureChildSummaryTypeId,
20
+ FeatureGraphSummaryTypeId,
21
+ FeatureGraphValidTypeId,
22
+ FeatureModuleGraphValidTypeId,
23
+ SlotBindingSummaryTypeId,
24
+ } from './summary'
25
+ export type {
26
+ AnyFeatureGraphSummary,
27
+ CompositionChildSummary,
28
+ FeatureChildSummary,
29
+ FeatureGraphSummary,
30
+ FeatureSummaryCompositionIdentity,
31
+ FeatureSummaryCompositionProps,
32
+ FeatureSummaryContract,
33
+ FeatureSummaryIdentity,
34
+ FeatureSummaryInput,
35
+ FeatureSummaryMountProps,
36
+ FeatureSummaryName,
37
+ FeatureSummaryOpenServices,
38
+ FeatureSummaryStates,
39
+ FeatureSummarySupportOpenServices,
40
+ FeatureSummaryUsesInput,
41
+ SlotBindingSummary,
42
+ } from './summary'
43
+ export type {
44
+ DescendantOpenServices,
45
+ ExactServiceExclude,
46
+ ModuleOpenServices,
47
+ OpenServicesFromFeatureSlotWitnesses,
48
+ } from './services'
230
49
 
231
50
  type LayerErrorIsNever<L extends Layer.Layer.Any> =
232
51
  IsErased<Layer.Layer.Error<L>> extends true
@@ -0,0 +1,95 @@
1
+ import type { Layer } from 'effect'
2
+ import { SlotServiceTypeId } from '../compose/slot'
3
+ import type { FeatureInput } from '../feature/feature'
4
+ import type { EngineServices } from '../runtime/loop'
5
+ import type { StateStore } from '../state/state'
6
+ import type { StateFamilyStore } from '../state/stateFamily'
7
+ import type { FeatureChildSummary } from './summary'
8
+
9
+ export type IsAny<Value> = 0 extends 1 & Value ? true : false
10
+
11
+ export type IsErased<Value> = IsAny<Value> extends true ? true : unknown extends Value ? true : false
12
+
13
+ export type ExactStateStoreName<Service> =
14
+ IsAny<Service> extends true
15
+ ? never
16
+ : Service extends StateStore<infer Name, infer _Value>
17
+ ? string extends Name
18
+ ? never
19
+ : Name
20
+ : never
21
+
22
+ export type ExactStateFamilyStoreName<Service> =
23
+ IsAny<Service> extends true
24
+ ? never
25
+ : Service extends StateFamilyStore<infer Name, infer _Key, infer _Value>
26
+ ? string extends Name
27
+ ? never
28
+ : Name
29
+ : never
30
+
31
+ export type ServiceIsProvided<Required, Provided> =
32
+ IsErased<Provided> extends true
33
+ ? false
34
+ : Required extends StateStore<infer Name, infer _Value>
35
+ ? Name extends ExactStateStoreName<Provided>
36
+ ? true
37
+ : false
38
+ : Required extends StateFamilyStore<infer Name, infer _Key, infer _Value>
39
+ ? Name extends ExactStateFamilyStoreName<Provided>
40
+ ? true
41
+ : false
42
+ : [Required] extends [Provided]
43
+ ? true
44
+ : false
45
+
46
+ /**
47
+ * Remove only services the provider can satisfy by their runtime Context tag.
48
+ * Named State/StateFamily identifiers intentionally do not collapse into their
49
+ * structurally broader Store/FamilyStore service APIs.
50
+ */
51
+ export type ExactServiceExclude<Required, Provided> = Required extends unknown
52
+ ? ServiceIsProvided<Required, Provided> extends true
53
+ ? never
54
+ : Required
55
+ : never
56
+
57
+ export type ExactServiceExtract<Required, Provided> = Required extends unknown
58
+ ? ServiceIsProvided<Required, Provided> extends true
59
+ ? Required
60
+ : never
61
+ : never
62
+
63
+ export type GraphValidationPassed = object
64
+
65
+ export type ExactIdentity<Identity> = IsErased<Identity> extends true ? never : Identity
66
+
67
+ export type InputService<UsesInput extends boolean> = UsesInput extends true ? FeatureInput : never
68
+
69
+ export type OpenServicesFromFeatureSlotWitnesses<Services> = Services extends {
70
+ readonly [SlotServiceTypeId]: {
71
+ readonly binding: FeatureChildSummary<
72
+ infer _FeatureIdentity,
73
+ infer _MountProps,
74
+ infer _CompositionProps,
75
+ infer _Contract,
76
+ infer _States,
77
+ infer _Name,
78
+ infer _CompositionIdentity,
79
+ infer OpenServices,
80
+ infer SupportOpenServices,
81
+ infer _UsesInput,
82
+ infer _Input
83
+ >
84
+ }
85
+ }
86
+ ? OpenServices | SupportOpenServices
87
+ : never
88
+
89
+ export type DescendantOpenServices<L extends Layer.Layer.Any> =
90
+ OpenServicesFromFeatureSlotWitnesses<Layer.Layer.Success<L>>
91
+
92
+ export type ModuleOpenServices<L extends Layer.Layer.Any, UsesInput extends boolean> = Exclude<
93
+ Layer.Layer.Context<L>,
94
+ EngineServices | InputService<UsesInput>
95
+ >