@typeonce/ritmo 0.6.0 → 0.7.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.
Files changed (125) hide show
  1. package/README.md +2 -0
  2. package/dist/Brand.d.ts +9 -4
  3. package/dist/Brand.d.ts.map +1 -1
  4. package/dist/Brand.js +9 -4
  5. package/dist/Brand.js.map +1 -1
  6. package/dist/Clock.d.ts +186 -0
  7. package/dist/Clock.d.ts.map +1 -0
  8. package/dist/Clock.js +111 -0
  9. package/dist/Clock.js.map +1 -0
  10. package/dist/Command.d.ts +157 -33
  11. package/dist/Command.d.ts.map +1 -1
  12. package/dist/Command.js +49 -15
  13. package/dist/Command.js.map +1 -1
  14. package/dist/Debug.d.ts +104 -12
  15. package/dist/Debug.d.ts.map +1 -1
  16. package/dist/Debug.js.map +1 -1
  17. package/dist/Decode.d.ts +1 -1
  18. package/dist/Decode.js +1 -1
  19. package/dist/Descriptor.d.ts +31 -21
  20. package/dist/Descriptor.d.ts.map +1 -1
  21. package/dist/Descriptor.js +21 -12
  22. package/dist/Descriptor.js.map +1 -1
  23. package/dist/Entity.d.ts +14 -5
  24. package/dist/Entity.d.ts.map +1 -1
  25. package/dist/Entity.js +2 -2
  26. package/dist/Entity.js.map +1 -1
  27. package/dist/EntityScope.d.ts +6 -0
  28. package/dist/EntityScope.d.ts.map +1 -1
  29. package/dist/EntityScope.js +6 -0
  30. package/dist/EntityScope.js.map +1 -1
  31. package/dist/HostClock.d.ts +49 -0
  32. package/dist/HostClock.d.ts.map +1 -0
  33. package/dist/HostClock.js +46 -0
  34. package/dist/HostClock.js.map +1 -0
  35. package/dist/Inspector.d.ts +7 -1
  36. package/dist/Inspector.d.ts.map +1 -1
  37. package/dist/Inspector.js.map +1 -1
  38. package/dist/Machine.d.ts +12 -3
  39. package/dist/Machine.d.ts.map +1 -1
  40. package/dist/Machine.js +4 -1
  41. package/dist/Machine.js.map +1 -1
  42. package/dist/Query.d.ts +28 -24
  43. package/dist/Query.d.ts.map +1 -1
  44. package/dist/Query.js +0 -24
  45. package/dist/Query.js.map +1 -1
  46. package/dist/Runtime.d.ts +36 -16
  47. package/dist/Runtime.d.ts.map +1 -1
  48. package/dist/Runtime.js +230 -67
  49. package/dist/Runtime.js.map +1 -1
  50. package/dist/Schedule.d.ts +217 -10
  51. package/dist/Schedule.d.ts.map +1 -1
  52. package/dist/Schedule.js +5 -0
  53. package/dist/Schedule.js.map +1 -1
  54. package/dist/Schema.d.ts +61 -25
  55. package/dist/Schema.d.ts.map +1 -1
  56. package/dist/Schema.js +0 -8
  57. package/dist/Schema.js.map +1 -1
  58. package/dist/System.d.ts +149 -52
  59. package/dist/System.d.ts.map +1 -1
  60. package/dist/System.js +52 -6
  61. package/dist/System.js.map +1 -1
  62. package/dist/index.d.ts +8 -7
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +8 -7
  65. package/dist/index.js.map +1 -1
  66. package/dist/internal/cells.d.ts +3 -3
  67. package/dist/internal/cells.d.ts.map +1 -1
  68. package/dist/internal/cells.js +9 -11
  69. package/dist/internal/cells.js.map +1 -1
  70. package/dist/internal/debug.d.ts +6 -0
  71. package/dist/internal/debug.d.ts.map +1 -1
  72. package/dist/internal/debug.js +95 -1
  73. package/dist/internal/debug.js.map +1 -1
  74. package/dist/internal/game.d.ts.map +1 -1
  75. package/dist/internal/game.js +9 -2
  76. package/dist/internal/game.js.map +1 -1
  77. package/dist/internal/order.d.ts +10 -0
  78. package/dist/internal/order.d.ts.map +1 -0
  79. package/dist/internal/order.js +120 -0
  80. package/dist/internal/order.js.map +1 -0
  81. package/dist/internal/queries.js +2 -2
  82. package/dist/internal/queries.js.map +1 -1
  83. package/package.json +1 -1
  84. package/src/Brand.ts +9 -4
  85. package/src/Clock.ts +311 -0
  86. package/src/Command.ts +271 -73
  87. package/src/Debug.ts +111 -10
  88. package/src/Decode.ts +1 -1
  89. package/src/Descriptor.ts +37 -27
  90. package/src/Entity.ts +15 -5
  91. package/src/EntityScope.ts +6 -0
  92. package/src/HostClock.ts +64 -0
  93. package/src/Inspector.ts +7 -2
  94. package/src/Machine.ts +13 -3
  95. package/src/Query.ts +41 -33
  96. package/src/Runtime.ts +273 -91
  97. package/src/Schedule.ts +380 -13
  98. package/src/Schema.ts +70 -41
  99. package/src/System.ts +174 -88
  100. package/src/index.ts +8 -7
  101. package/src/internal/cells.ts +10 -12
  102. package/src/internal/debug.ts +104 -4
  103. package/src/internal/game.ts +11 -3
  104. package/src/internal/order.ts +140 -0
  105. package/src/internal/queries.ts +3 -3
  106. package/dist/Definition.d.ts +0 -99
  107. package/dist/Definition.d.ts.map +0 -1
  108. package/dist/Definition.js +0 -68
  109. package/dist/Definition.js.map +0 -1
  110. package/dist/Feature.d.ts +0 -106
  111. package/dist/Feature.d.ts.map +0 -1
  112. package/dist/Feature.js +0 -87
  113. package/dist/Feature.js.map +0 -1
  114. package/dist/Fx.d.ts +0 -128
  115. package/dist/Fx.d.ts.map +0 -1
  116. package/dist/Fx.js +0 -112
  117. package/dist/Fx.js.map +0 -1
  118. package/dist/internal/definition.d.ts +0 -17
  119. package/dist/internal/definition.d.ts.map +0 -1
  120. package/dist/internal/definition.js +0 -25
  121. package/dist/internal/definition.js.map +0 -1
  122. package/src/Definition.ts +0 -106
  123. package/src/Feature.ts +0 -241
  124. package/src/Fx.ts +0 -176
  125. package/src/internal/definition.ts +0 -56
package/src/Feature.ts DELETED
@@ -1,241 +0,0 @@
1
- /**
2
- * Pre-bind features: reusable slices that contribute a schema fragment and the
3
- * schedules that operate on it.
4
- *
5
- * A feature builds its schedules only after the final merged schema is bound,
6
- * and its builder can only reach descriptors from its own fragment and from
7
- * the features it `requires`.
8
- *
9
- * @module Feature
10
- * @docGroup core
11
- *
12
- * @example
13
- * ```ts
14
- * const Combat = Schema.Feature.define("Combat", {
15
- * schema: CombatSchema,
16
- * requires: [Core],
17
- * build: (Game) => ({ update: [Game.Schedule(Attack, Game.Schedule.applyDeferred())] })
18
- * })
19
- *
20
- * const project = Schema.Feature.compose({ root: Root, features: [Core, Combat] })
21
- * const runtime = project.Game.Runtime.make({ services: project.Game.Runtime.services() })
22
- * runtime.tick(...project.schedules.update)
23
- * ```
24
- */
25
- import { buildSchema } from "./internal/fragments.ts"
26
- import { makeGame } from "./internal/game.ts"
27
- import type * as Schedule from "./Schedule.ts"
28
- import type { MergeSchemaDefinitions, Schema, SchemaDefinition, ValidateFragments } from "./Schema.ts"
29
-
30
- type EmptySchema = SchemaDefinition<{}, {}, {}, {}>
31
-
32
- type AnyFeature = {
33
- readonly kind: "feature"
34
- readonly name: string
35
- readonly schema: Schema.Any
36
- readonly requires: ReadonlyArray<AnyFeature>
37
- readonly build: unknown
38
- readonly output: FeatureBuildOutput
39
- }
40
-
41
- type AnySchedule = Schedule.ScheduleDefinition<any, any, any, any, any>
42
-
43
- /**
44
- * What a feature builder returns: bootstrap and update schedules, plus any
45
- * other values the feature wants to expose on the composed project.
46
- */
47
- export type FeatureBuildOutput = {
48
- readonly bootstrap?: ReadonlyArray<AnySchedule>
49
- readonly update?: ReadonlyArray<AnySchedule>
50
- }
51
-
52
- /**
53
- * The bound authoring surface a feature builder receives. It is the normal
54
- * `Game` API restricted to the descriptors the feature can see; runtimes are
55
- * built from the composed project instead.
56
- */
57
- export type FeatureBuildGame<Accessible extends Schema.Any, Root = unknown> =
58
- Omit<Schema.Game<Accessible, Root>, "Runtime">
59
-
60
- type FeatureBuildFunction<
61
- Accessible extends Schema.Any,
62
- Output extends FeatureBuildOutput = FeatureBuildOutput
63
- > = (Game: FeatureBuildGame<Accessible>) => Output
64
-
65
- export interface FeatureDefinition<
66
- Name extends string = string,
67
- FeatureSchema extends Schema.Any = Schema.Any,
68
- Requires extends ReadonlyArray<AnyFeature> = ReadonlyArray<AnyFeature>,
69
- Output extends FeatureBuildOutput = FeatureBuildOutput
70
- > {
71
- readonly kind: "feature"
72
- readonly name: Name
73
- readonly schema: FeatureSchema
74
- readonly requires: Requires
75
- readonly build: FeatureBuildFunction<MergeSchemaDefinitions<FeatureSchema, MergeFeatureSchemas<Requires>>, Output>
76
- readonly output: Output
77
- }
78
-
79
- type MergeFeatureSchemas<Features extends ReadonlyArray<AnyFeature>> =
80
- Features extends readonly [infer Head extends AnyFeature, ...infer Tail extends Array<AnyFeature>]
81
- ? MergeSchemaDefinitions<FeatureClosureSchema<Head>, MergeFeatureSchemas<Tail>>
82
- : EmptySchema
83
-
84
- type FeatureClosureSchema<F extends AnyFeature> =
85
- F extends FeatureDefinition<any, infer FeatureSchema extends Schema.Any, infer Requires extends ReadonlyArray<AnyFeature>, any>
86
- ? MergeSchemaDefinitions<FeatureSchema, MergeFeatureSchemas<Requires>>
87
- : EmptySchema
88
-
89
- type FeatureNames<Features extends ReadonlyArray<AnyFeature>> = Features[number]["name"]
90
-
91
- type DuplicateFeatureNames<
92
- Features extends ReadonlyArray<AnyFeature>,
93
- Seen extends string = never
94
- > = Features extends readonly [infer Head extends AnyFeature, ...infer Tail extends Array<AnyFeature>]
95
- ? Head["name"] extends Seen
96
- ? Head["name"] | DuplicateFeatureNames<Tail, Seen>
97
- : DuplicateFeatureNames<Tail, Seen | Head["name"]>
98
- : never
99
-
100
- type MissingFeatureDependencies<Features extends ReadonlyArray<AnyFeature>> =
101
- Exclude<Features[number]["requires"][number]["name"], FeatureNames<Features>>
102
-
103
- type FeatureSchemas<Features extends ReadonlyArray<AnyFeature>> = {
104
- readonly [K in keyof Features]: Features[K]["schema"]
105
- }
106
-
107
- /**
108
- * Rejects duplicate feature names, missing required features, and schema
109
- * fragments whose keys or descriptor names collide.
110
- */
111
- type ValidateFeatureSelection<Features extends ReadonlyArray<AnyFeature>> =
112
- [DuplicateFeatureNames<Features>] extends [never]
113
- ? [MissingFeatureDependencies<Features>] extends [never]
114
- ? ValidateFragments<FeatureSchemas<Features>>
115
- : { readonly __fixFeatureDependencies__: MissingFeatureDependencies<Features> }
116
- : { readonly __fixFeatureSelection__: DuplicateFeatureNames<Features> }
117
-
118
- type RebindFeatureSchedule<ScheduleValue, S extends Schema.Any, Root> =
119
- ScheduleValue extends Schedule.ScheduleDefinition<any, infer Requirements, any, infer Carried, infer Failure>
120
- ? Schedule.ScheduleDefinition<S, Requirements, Root, Carried, Failure>
121
- : never
122
-
123
- type FeatureScheduleArray<Output, Key extends "bootstrap" | "update"> =
124
- Key extends keyof Output
125
- ? Extract<Output[Key], ReadonlyArray<AnySchedule>>
126
- : readonly []
127
-
128
- type NormalizeFeatureOutput<Output extends object, S extends Schema.Any, Root> = {
129
- readonly [K in Exclude<keyof Output, "bootstrap" | "update">]: Output[K]
130
- } & {
131
- readonly bootstrap: ReadonlyArray<RebindFeatureSchedule<FeatureScheduleArray<Output, "bootstrap">[number], S, Root>>
132
- readonly update: ReadonlyArray<RebindFeatureSchedule<FeatureScheduleArray<Output, "update">[number], S, Root>>
133
- }
134
-
135
- type FeatureOutputRecord<Features extends ReadonlyArray<AnyFeature>, S extends Schema.Any, Root> = {
136
- readonly [K in FeatureNames<Features>]:
137
- NormalizeFeatureOutput<Extract<Features[number], { readonly name: K }>["output"], S, Root>
138
- }
139
-
140
- /**
141
- * The result of composing features: the merged schema, the bound `Game`,
142
- * each feature's normalized output, and the aggregated schedules in feature
143
- * order.
144
- */
145
- export interface ComposedFeatureProject<
146
- Features extends ReadonlyArray<AnyFeature>,
147
- Root = unknown,
148
- S extends Schema.Any = MergeFeatureSchemas<Features>
149
- > {
150
- readonly schema: S
151
- readonly Game: Schema.Game<S, Root>
152
- readonly features: FeatureOutputRecord<Features, S, Root>
153
- readonly schedules: {
154
- readonly bootstrap: ReadonlyArray<FeatureOutputRecord<Features, S, Root>[FeatureNames<Features>]["bootstrap"][number]>
155
- readonly update: ReadonlyArray<FeatureOutputRecord<Features, S, Root>[FeatureNames<Features>]["update"][number]>
156
- }
157
- }
158
-
159
- /**
160
- * Defines one pre-bind feature.
161
- */
162
- export const define = <
163
- const Name extends string,
164
- FeatureSchema extends Schema.Any,
165
- const Requires extends ReadonlyArray<AnyFeature> = [],
166
- Output extends FeatureBuildOutput = FeatureBuildOutput
167
- >(
168
- name: Name,
169
- options: {
170
- readonly schema: FeatureSchema
171
- readonly requires?: Requires
172
- readonly build: FeatureBuildFunction<MergeSchemaDefinitions<FeatureSchema, MergeFeatureSchemas<Requires>>, Output>
173
- }
174
- ): FeatureDefinition<Name, FeatureSchema, Requires, Output> => ({
175
- kind: "feature",
176
- name,
177
- schema: options.schema,
178
- requires: (options.requires ?? []) as Requires,
179
- build: options.build,
180
- output: undefined as unknown as Output
181
- })
182
-
183
- /**
184
- * Composes features into one merged schema and one bound `Game`, then builds
185
- * every feature against it.
186
- *
187
- * Aggregated schedule order is the selected feature order, not dependency
188
- * order. Run them with `runtime.tick(...project.schedules.update)`.
189
- */
190
- export const compose = <
191
- Root,
192
- const Features extends readonly [AnyFeature, ...Array<AnyFeature>]
193
- >(options: {
194
- readonly root: Root
195
- readonly features: Features
196
- } & ValidateFeatureSelection<Features>): ComposedFeatureProject<Features, Root> => {
197
- const featureNames = new Set<string>()
198
- for (const feature of options.features) {
199
- if (featureNames.has(feature.name)) {
200
- throw new Error(`Duplicate feature name: ${feature.name}`)
201
- }
202
- featureNames.add(feature.name)
203
- }
204
- for (const feature of options.features) {
205
- for (const requirement of feature.requires) {
206
- if (!featureNames.has(requirement.name)) {
207
- throw new Error(`Missing required feature: ${requirement.name}`)
208
- }
209
- }
210
- }
211
-
212
- const schema = buildSchema(options.features.map((feature) => feature.schema))
213
- const Game = makeGame(schema, options.root)
214
- const features: Record<string, object> = Object.create(null)
215
- const bootstrap: Array<AnySchedule> = []
216
- const update: Array<AnySchedule> = []
217
-
218
- for (const feature of options.features) {
219
- const built = (feature.build as (Game: unknown) => FeatureBuildOutput & Record<string, unknown>)(Game)
220
- const normalized = {
221
- ...built,
222
- bootstrap: [...(built.bootstrap ?? [])],
223
- update: [...(built.update ?? [])]
224
- }
225
- bootstrap.push(...normalized.bootstrap)
226
- update.push(...normalized.update)
227
- features[feature.name] = normalized
228
- }
229
-
230
- return {
231
- schema,
232
- Game,
233
- features,
234
- schedules: { bootstrap, update }
235
- } as unknown as ComposedFeatureProject<Features, Root>
236
- }
237
-
238
- export const Feature = {
239
- define,
240
- compose
241
- }
package/src/Fx.ts DELETED
@@ -1,176 +0,0 @@
1
- /**
2
- * Small explicit effect type used for systems and runtime orchestration.
3
- *
4
- * `Fx` models delayed computation with typed success, failure, and environment
5
- * channels. Expected failures are returned as `Result` values; exceptions are
6
- * reserved for unexpected defects in user code.
7
- *
8
- * Systems that cannot fail return nothing. A system returns an `Fx` when it
9
- * has an expected failure: `Fx.fail(...)` rolls back the system's ECS writes
10
- * and surfaces a typed `SystemFailure` from `runtime.tick(...)`. `map` and
11
- * `flatMap` compose such effects.
12
- *
13
- * @example
14
- * ```ts
15
- * // Build one small delayed computation.
16
- * const program = Fx.map(Fx.succeed(1), (value) => value + 1)
17
- *
18
- * // Execute it explicitly at the runtime boundary.
19
- * const result = Fx.runSync(program)
20
- * ```
21
- *
22
- * @module Fx
23
- * @docGroup runtime
24
- *
25
- * @groupDescription Namespaces
26
- * Grouped helper types that extract success, error, and environment information from effects.
27
- *
28
- * @groupDescription Interfaces
29
- * Public effect contracts used by systems and runtime orchestration.
30
- *
31
- * @groupDescription Type Aliases
32
- * Shared helper types derived from one `Fx` value.
33
- *
34
- * @groupDescription Functions
35
- * Minimal constructors and combinators for explicit delayed computations.
36
- */
37
- import * as Result from "./Result.ts"
38
-
39
- /**
40
- * String-literal type id used to mirror Effect's current `~effect/...` style.
41
- */
42
- export type FxTypeId = "~ritmo/Fx"
43
-
44
- /**
45
- * Runtime value for the `Fx` type id.
46
- */
47
- const fxTypeId: FxTypeId = "~ritmo/Fx"
48
-
49
- /**
50
- * A minimal Effect-style computation used by the runtime.
51
- *
52
- * `Fx<A, E, R>` models a computation that succeeds with `A`, may fail with `E`,
53
- * and requires an environment `R`.
54
- */
55
- export interface Fx<A, E = never, R = unknown> {
56
- readonly [fxTypeId]: {
57
- readonly _A: (_: never) => A
58
- readonly _E: (_: never) => E
59
- readonly _R: (_: R) => void
60
- }
61
- readonly run: (environment: R) => Result.Result<A, E>
62
- }
63
-
64
- /**
65
- * Type-level helpers for `Fx`.
66
- */
67
- export namespace Fx {
68
- /**
69
- * Extracts the success type from an effect.
70
- */
71
- export type Success<T extends Fx<any, any, any>> = T extends Fx<infer A, infer _E, infer _R> ? A : never
72
- /**
73
- * Extracts the error type from an effect.
74
- */
75
- export type Error<T extends Fx<any, any, any>> = T extends Fx<infer _A, infer E, infer _R> ? E : never
76
- /**
77
- * Extracts the required environment from an effect.
78
- */
79
- export type Context<T extends Fx<any, any, any>> = T extends Fx<infer _A, infer _E, infer R> ? R : never
80
- }
81
-
82
- /**
83
- * Low-level constructor for `Fx`.
84
- *
85
- * All public constructors eventually delegate here so the runtime shape stays
86
- * consistent.
87
- */
88
- const make = <A, E, R>(run: (environment: R) => Result.Result<A, E>): Fx<A, E, R> =>
89
- ({
90
- [fxTypeId]: {
91
- _A: (_: never) => undefined as A,
92
- _E: (_: never) => undefined as E,
93
- _R: (_: R) => undefined
94
- },
95
- run
96
- }) as Fx<A, E, R>
97
-
98
- /**
99
- * Creates an effect that immediately succeeds with a value.
100
- *
101
- * Use this for pure values that should still participate in the typed effect
102
- * composition model.
103
- */
104
- export const succeed = <A, R = unknown>(value: A): Fx<A, never, R> =>
105
- make(() => Result.success(value))
106
-
107
- /**
108
- * Wraps a synchronous computation in an `Fx`.
109
- *
110
- * This is the most common constructor for system implementations in the current
111
- * runtime because systems are executed synchronously.
112
- */
113
- export const sync = <A, R = unknown>(evaluate: () => A): Fx<A, never, R> =>
114
- make(() => Result.success(evaluate()))
115
-
116
- /**
117
- * Creates an effect that returns one expected failure when run.
118
- */
119
- export const fail = <E, R = unknown>(error: E): Fx<never, E, R> =>
120
- make(() => Result.failure(error))
121
-
122
- /**
123
- * Transforms the success value of an effect.
124
- */
125
- export const map = <A, B, E, R>(
126
- self: Fx<A, E, R>,
127
- f: (value: A) => B
128
- ): Fx<B, E, R> => make((environment) => {
129
- const result = self.run(environment)
130
- return result.ok ? Result.success(f(result.value)) : result
131
- })
132
-
133
- /**
134
- * Sequences two effects, allowing the second one to depend on the first result.
135
- */
136
- export const flatMap = <A, B, E1, E2, R1, R2>(
137
- self: Fx<A, E1, R1>,
138
- f: (value: A) => Fx<B, E2, R2>
139
- ): Fx<B, E1 | E2, R1 & R2> => make<B, E1 | E2, R1 & R2>((environment) => {
140
- const first = self.run(environment as R1)
141
- return first.ok ? f(first.value).run(environment as R2) : first
142
- })
143
-
144
- /**
145
- * Reads the whole effect environment.
146
- *
147
- * Use this when a system helper wants access to all declared services at once.
148
- */
149
- export const access = <R>(): Fx<R, never, R> =>
150
- make((environment) => Result.success(environment))
151
-
152
- /**
153
- * Reads a single service from the environment by key.
154
- *
155
- * This is useful for small helpers that need one dependency without threading
156
- * the entire environment type manually.
157
- */
158
- export const accessService = <R, K extends keyof R>(key: K): Fx<R[K], never, R> =>
159
- make((environment) => Result.success(environment[key]))
160
-
161
- /**
162
- * Supplies the environment needed by an effect.
163
- */
164
- export const provide = <A, E, R>(
165
- self: Fx<A, E, R>,
166
- environment: R
167
- ): Fx<A, E, unknown> => make(() => self.run(environment))
168
-
169
- /**
170
- * Runs an effect that no longer requires any environment.
171
- *
172
- * The runtime uses this at the edge after it has provided the services declared
173
- * by a system spec.
174
- */
175
- export const runSync = <A, E>(self: Fx<A, E, unknown>): Result.Result<A, E> =>
176
- self.run(undefined)
@@ -1,56 +0,0 @@
1
- import * as Result from "../Result.ts"
2
-
3
- export type Entry<Value, Error> = Result.Result<Value, Error>
4
-
5
- export type ResultConstructor<Value, Raw, Error> = {
6
- readonly result: (raw: Raw) => Result.Result<Value, Error>
7
- }
8
-
9
- type AnyEntry = Result.Result<any, any>
10
-
11
- export type Entries = Readonly<Record<string, AnyEntry>>
12
-
13
- export type SuccessOf<Input extends Entries> = {
14
- readonly [Key in keyof Input]:
15
- Input[Key] extends Result.Result<infer Value, any> ? Value : never
16
- }
17
-
18
- export type ErrorOf<Input extends Entries> = {
19
- readonly [Key in keyof Input]:
20
- Input[Key] extends Result.Result<any, infer Error> ? Error | null : never
21
- }
22
-
23
- export const entry = <Value, Raw, Error>(
24
- constructor: ResultConstructor<Value, Raw, Error>,
25
- raw: Raw
26
- ): Entry<Value, Error> => constructor.result(raw)
27
-
28
- export const all = <Input extends Entries>(
29
- input: Input
30
- ): Result.Result<SuccessOf<Input>, ErrorOf<Input>> => {
31
- const values: Record<string, unknown> = {}
32
- const errors: Record<string, unknown> = {}
33
- let hasFailure = false
34
-
35
- for (const key of Object.keys(input)) {
36
- const entry = input[key]
37
- if (entry === undefined) {
38
- continue
39
- }
40
-
41
- if (entry.ok) {
42
- values[key] = entry.value
43
- errors[key] = null
44
- continue
45
- }
46
-
47
- hasFailure = true
48
- errors[key] = entry.error
49
- }
50
-
51
- if (hasFailure) {
52
- return Result.failure(errors as ErrorOf<Input>)
53
- }
54
-
55
- return Result.success(values as SuccessOf<Input>)
56
- }