@systemfsoftware/effect-cell-types 7.0.1 → 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,44 @@
1
1
  # @systemfsoftware/effect-cell-types
2
2
 
3
+ ## 8.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - `collectAll` now declares an error channel of `never`: the composed cell cannot fail, because every per-item refusal is delivered to the fold as a `Result`. Composed cells no longer carry the item error channel in their type.
8
+
9
+ `Workflow.andThen` now composes two total workflows (components whose error channel is `never`) into a total workflow. Error-carrying chains are unchanged.
10
+
11
+ `Workflow.make` and `Workflow.total` now refuse decision unions whose variants declare the family brand as a narrow unique-symbol type instead of the documented class-field idiom. Declare the brand as a `readonly [T] = T` field on each `S.TaggedClass` variant: the field initializer widens the slot to the general `symbol` type, and the predicate keys on that widened slot. A `typeof`-annotated slot stays narrow and is refused with `UnsharedTypeId` — including the idiom hand-written as an interface. An interface annotating the slot as plain `symbol` is structurally identical to the class idiom and is accepted.
12
+
13
+ ## 8.0.0
14
+
15
+ ### Major Changes
16
+
17
+ - The exported `Cell.run` helper is removed. Run a cell through its own arrow instead: `cell.run(input)` replaces `Cell.run(cell, input)`, in both the data-first and the curried form. The helper only forwarded to that arrow, so a migrated call site behaves identically.
18
+
19
+ The `Policy` type and `Cell.withPolicy` are removed. An execution strategy — retry, timeout, a restart cap — belongs to the interpreter: it is the only place that knows the write's idempotence and the deadline, and a strategy declared on the published value imposed re-execution of side effects on every consumer. Wrap the run at the edge with Effect's own combinators instead: `Effect.retry(cell.run(input), { times })`.
20
+
21
+ ### Minor Changes
22
+
23
+ - `Cell.gate` runs one Cell only when another's response carries a value: the value admits it to the inner Cell and the composed response wraps the inner response, carrying nothing skips the inner Cell entirely, and both Cells' error and service channels union.
24
+
25
+ `Cell.collect` runs one Cell per item, in order, then folds the responses with a plain function. The first refusal fails the composed Cell with that item's own refusal. `Cell.collectAll` is the accumulate opt-in: an item's refusal travels to the fold as data, so the fold always runs over every result.
26
+
27
+ Both combinators are callable in the curried and data-first styles, and neither requires a workflow brand at its call site.
28
+
29
+ - Two constructors join `Workflow.make`.
30
+
31
+ `Workflow.total` brands a decision that cannot fail. A decider whose error channel is `never` no
32
+ longer becomes a workflow that cannot be called; it carries the workflow brand and is accepted
33
+ wherever a branded decision is, including `Cell.layer`'s `decide` slot. Like `make`, it takes the
34
+ command schema class first, and it still refuses a decision with a single variant or a variant
35
+ carrying no `_tag` to dispatch on.
36
+
37
+ `Workflow.andThen` chains two workflows. The first workflow's decision becomes the second workflow's
38
+ command, the composed workflow's error channel is the union of both components, and a refusal from
39
+ the first short-circuits — the second never runs. The second workflow's command class is passed as a
40
+ value, so the composed signature carries no adapter function.
41
+
3
42
  ## 7.0.1
4
43
 
5
44
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import * as Effect$1 from "effect/Effect";
2
- import { Effect } from "effect/Effect";
1
+ import * as Effect from "effect/Effect";
2
+ import * as Option from "effect/Option";
3
3
  import * as Result$1 from "effect/Result";
4
4
  import { Result } from "effect/Result";
5
5
  import { Kind, TypeLambda } from "effect/HKT";
@@ -13,12 +13,8 @@ declare const IO_CELLS: {
13
13
  };
14
14
  type IoCellClassification = typeof IO_CELLS;
15
15
  type PhaseName = 'read' | 'decode' | 'decide' | 'encode' | 'write';
16
- declare namespace Policy_d_exports {
17
- export { Policy };
18
- }
19
- type Policy<A, E, R> = (self: Effect<A, E, R>) => Effect<A, E, R>;
20
16
  declare namespace Workflow_d_exports {
21
- export { Inhabited, SingleVariantDecision, UninhabitedDecision, UninhabitedError, UnsharedTypeId, UntaggedDecision, UntaggedError, Workflow, WorkflowBrand, make };
17
+ export { Inhabited, SingleVariantDecision, UninhabitedDecision, UninhabitedError, UnsharedTypeId, UntaggedDecision, UntaggedError, Workflow, WorkflowBrand, andThen$1 as andThen, make, total };
22
18
  }
23
19
  declare const WorkflowTypeId: unique symbol;
24
20
  type WorkflowTypeId = typeof WorkflowTypeId;
@@ -43,10 +39,11 @@ interface UntaggedDecision {
43
39
  interface UnsharedTypeId {
44
40
  readonly __WORKFLOW_DECISION_VARIANTS_DO_NOT_SHARE_A_TYPE_ID__: 'the decision variants must share one TypeId — a Symbol.for family brand on each variant class';
45
41
  }
46
- type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
47
42
  type AtLeastTwoDistinct<T, U = T> = U extends unknown ? [T] extends [U] ? false : true : never;
48
43
  type TaggedMembers<D> = D extends unknown ? '_tag' extends keyof D ? [D['_tag']] extends [string] ? true : false : false : never;
49
- type SharedTypeId<D, I = UnionToIntersection<D>> = [keyof { [K in keyof I as I[K] extends K ? (D extends { readonly [P in K]: K; } ? K : never) : never]: 0; }] extends [never] ? UnsharedTypeId : unknown;
44
+ type MutuallyAssignable<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false;
45
+ type BrandSlotIsTheGeneralSymbol<D, K extends PropertyKey> = D extends unknown ? K extends keyof D ? MutuallyAssignable<D[K], symbol> : false : never;
46
+ type SharedTypeId<D> = [{ [K in keyof D]: [K] extends [symbol] ? ([BrandSlotIsTheGeneralSymbol<D, K>] extends [true] ? K : never) : never; }[keyof D]] extends [never] ? UnsharedTypeId : unknown;
50
47
  type DecisionShape<D> = [unknown] extends [D] ? unknown : AtLeastTwoDistinct<D> extends false ? SingleVariantDecision : boolean extends TaggedMembers<D> ? UntaggedDecision : SharedTypeId<D>;
51
48
  type Workflow<Command, Decision, DecisionError> = [Decision] extends [never] ? UninhabitedDecision : [DecisionError] extends [never] ? UninhabitedError : ((command: Command) => Result<Decision, DecisionError>) & WorkflowBrand;
52
49
  type DispatchableTag<E> = '_tag' extends keyof E ? [E['_tag']] extends [string] ? unknown : UntaggedError : UntaggedError;
@@ -54,8 +51,40 @@ type Inhabited<Decision, DecisionError> = [Decision] extends [never] ? Uninhabit
54
51
  declare const make: <Self, S extends Schema.Constraint & {
55
52
  readonly fields: Schema.Struct.Fields;
56
53
  }, Inherited, D, E>(_command: Schema.Class<Self, S, Inherited>, decide: (command: Self) => Result<D, E> & Inhabited<D, E>) => Workflow<Self, D, E>;
54
+ /**
55
+ * Brands a decision that cannot fail. `make` refuses a `never` error channel outright
56
+ * (`UninhabitedError`); this is the door for the decider that genuinely decides everything.
57
+ * The decision must still choose between at least two tagged variants sharing one TypeId, so
58
+ * `SingleVariantDecision`, `UntaggedDecision`, and `UnsharedTypeId` still fire.
59
+ *
60
+ * The command schema class comes first, exactly as in {@link make}, so the command channel
61
+ * stays pinned to the class rather than an inferred annotation. The decider's return carries
62
+ * `DecisionShape` written out: the `Workflow` alias is a deferred conditional, and in
63
+ * parameter position it collapses the whole parameter to `unknown` while the decision
64
+ * channel is still generic.
65
+ */
66
+ declare const total: <Self, S extends Schema.Constraint & {
67
+ readonly fields: Schema.Struct.Fields;
68
+ }, Inherited, D>(_command: Schema.Class<Self, S, Inherited>, decide: (command: Self) => Result<D, never> & DecisionShape<D>) => ((command: Self) => Result<D, never>) & WorkflowBrand;
69
+ /**
70
+ * Composes two workflows: what the upstream decides becomes the command the downstream decides
71
+ * on, and a refusal short-circuits the pair. The return type dispatches on the component error
72
+ * union — two components that cannot fail publish the total form, because the `Workflow` alias
73
+ * refuses a `never` channel; a carried error publishes the union as before.
74
+ */
75
+ declare const andThen$1: <Ctx, SelfA, SA extends Schema.Constraint & {
76
+ readonly fields: Schema.Struct.Fields;
77
+ }, InheritedA, D1, E1, SelfB extends {
78
+ readonly decision: D1;
79
+ readonly ctx: Ctx;
80
+ }, D2, E2>(_commandA: Schema.Class<SelfA, SA, InheritedA>, upstream: ((command: SelfA) => Result<D1, E1>) & WorkflowBrand, commandB: {
81
+ new (props: {
82
+ readonly decision: D1;
83
+ readonly ctx: Ctx;
84
+ }): SelfB;
85
+ }, ctx: NoInfer<Ctx>, downstream: ((command: SelfB) => Result<D2, E2>) & WorkflowBrand) => [E1 | E2] extends [never] ? ((command: SelfA) => Result<D2, never>) & WorkflowBrand : Workflow<SelfA, D2, E1 | E2>;
57
86
  declare namespace Cell_d_exports {
58
- export { Cell, CellTypeId, DESCRIPTION_MODULE, IO_CELLS, IoCellClassification, Kind$1 as Kind, PhaseName, Run, TypeLambda$1 as TypeLambda, Vocabulary, andThen, layer, map, mapInput, provide, run, vocabulary, withPolicy, zip };
87
+ export { Cell, CellTypeId, DESCRIPTION_MODULE, IO_CELLS, IoCellClassification, Kind$1 as Kind, PhaseName, Run, TypeLambda$1 as TypeLambda, Vocabulary, andThen, collect, collectAll, gate, layer, map, mapInput, provide, vocabulary, zip };
59
88
  }
60
89
  /**
61
90
  * The nominal brand every `Cell` carries. `Cell.layer` is the only door that applies it.
@@ -73,7 +102,7 @@ type CellTypeId = typeof CellTypeId;
73
102
  */
74
103
  interface Cell<in I, out A, out E = never, out R = never> {
75
104
  readonly [CellTypeId]: CellTypeId;
76
- readonly run: (input: I) => Effect$1.Effect<A, E, R>;
105
+ readonly run: (input: I) => Effect.Effect<A, E, R>;
77
106
  }
78
107
  /**
79
108
  * The type lambda for {@link Cell}, admitting Cell to `Kind` positions.
@@ -92,9 +121,9 @@ type Kind$1<I, E, R, A> = Kind<TypeLambda$1, I, E, R, A>;
92
121
  */
93
122
  type Run<I, A, E, R> = Cell<I, A, E, R>['run'];
94
123
  interface LayerCore<I, Raw, RE, RR, Dec, DE, Resp, WE, WR> {
95
- readonly read: (command: I) => Effect$1.Effect<Raw, RE, RR>;
124
+ readonly read: (command: I) => Effect.Effect<Raw, RE, RR>;
96
125
  readonly decide: ((decoded: Raw) => Result$1.Result<Dec, DE>) & WorkflowBrand;
97
- readonly write: (output: Result$1.Result<Dec, DE>, raw: Raw) => Effect$1.Effect<Resp, WE, WR>;
126
+ readonly write: (output: Result$1.Result<Dec, DE>, raw: Raw) => Effect.Effect<Resp, WE, WR>;
98
127
  }
99
128
  interface LayerShortSpec<I, Raw, RE, RR, Dec, DE, Resp, WE, WR> extends LayerCore<I, Raw, RE, RR, Dec, DE, Resp, WE, WR> {
100
129
  readonly decode?: never;
@@ -104,7 +133,7 @@ interface LayerLongSpec<I, Raw, RE, RR, Dcd, DecE, Dec, DE, Out, Resp, WE, WR> e
104
133
  readonly decode: (raw: Raw) => Result$1.Result<Dcd, DecE>;
105
134
  readonly decide: ((decoded: Dcd) => Result$1.Result<Dec, DE>) & WorkflowBrand;
106
135
  readonly encode: (outcome: Result$1.Result<Dec, DE>) => Out;
107
- readonly write: (output: Out, raw: Raw) => Effect$1.Effect<Resp, WE, WR>;
136
+ readonly write: (output: Out, raw: Raw) => Effect.Effect<Resp, WE, WR>;
108
137
  }
109
138
  /**
110
139
  * Builds a Cell from one sandwich.
@@ -133,10 +162,6 @@ interface LayerLongSpec<I, Raw, RE, RR, Dcd, DecE, Dec, DE, Out, Resp, WE, WR> e
133
162
  */
134
163
  declare function layer<I, Raw, RE, RR, Dec, DE, Resp, WE, WR>(spec: LayerShortSpec<I, Raw, RE, RR, Dec, DE, Resp, WE, WR>): Cell<I, Resp, RE | WE, RR | WR>;
135
164
  declare function layer<I, Raw, RE, RR, Dcd, DecE, Dec, DE, Out, Resp, WE, WR>(spec: LayerLongSpec<I, Raw, RE, RR, Dcd, DecE, Dec, DE, Out, Resp, WE, WR>): Cell<I, Resp, RE | DecE | WE, RR | WR>;
136
- declare const run: {
137
- <I>(input: I): <A, E, R>(self: Cell<I, A, E, R>) => Effect$1.Effect<A, E, R>;
138
- <I, A, E, R>(self: Cell<I, A, E, R>, input: I): Effect$1.Effect<A, E, R>;
139
- };
140
165
  /**
141
166
  * Transforms the Cell's response.
142
167
  */
@@ -167,6 +192,31 @@ declare const zip: {
167
192
  <I, B, E2, R2>(that: Cell<I, B, E2, R2>): <A, E, R>(self: Cell<I, A, E, R>) => Cell<I, readonly [A, B], E | E2, R | R2>;
168
193
  <I, A, E, R, B, E2, R2>(self: Cell<I, A, E, R>, that: Cell<I, B, E2, R2>): Cell<I, readonly [A, B], E | E2, R | R2>;
169
194
  };
195
+ /**
196
+ * Runs the inner Cell on the value this Cell read, yielding `Option.none` when it read none.
197
+ * A skip is an absence, never a refusal; the error and service channels union.
198
+ */
199
+ declare const gate: {
200
+ <Raw, A, E2, R2>(inner: Cell<Raw, A, E2, R2>): <I, E, R>(self: Cell<I, Option.Option<Raw>, E, R>) => Cell<I, Option.Option<A>, E | E2, R | R2>;
201
+ <I, Raw, E, R, A, E2, R2>(self: Cell<I, Option.Option<Raw>, E, R>, inner: Cell<Raw, A, E2, R2>): Cell<I, Option.Option<A>, E | E2, R | R2>;
202
+ };
203
+ /**
204
+ * Runs the Cell once per item, in order, and folds the responses into one value. The error
205
+ * and service channels are unchanged; the first refusal ends the run.
206
+ */
207
+ declare const collect: {
208
+ <I, A, E, R, B>(fold: (responses: readonly A[]) => B): (self: Cell<I, A, E, R>) => Cell<readonly I[], B, E, R>;
209
+ <I, A, E, R, B>(self: Cell<I, A, E, R>, fold: (responses: readonly A[]) => B): Cell<readonly I[], B, E, R>;
210
+ };
211
+ /**
212
+ * Runs the Cell once per item, in order, and folds every outcome — each a `Result.Result` —
213
+ * into one value. Unlike {@link collect}, no refusal ends the run: every item is attempted
214
+ * and its failure travels to the fold.
215
+ */
216
+ declare const collectAll: {
217
+ <I, A, E, R, B>(fold: (results: readonly Result$1.Result<A, E>[]) => B): (self: Cell<I, A, E, R>) => Cell<readonly I[], B, never, R>;
218
+ <I, A, E, R, B>(self: Cell<I, A, E, R>, fold: (results: readonly Result$1.Result<A, E>[]) => B): Cell<readonly I[], B, never, R>;
219
+ };
170
220
  /**
171
221
  * Provides a Layer to the Cell, eliminating the services the layer builds from `R`. This is
172
222
  * the one composition-root elimination; the resulting Cell still demands the layer's input
@@ -176,14 +226,6 @@ declare const provide: {
176
226
  <RIn, LE, ROut>(layer: Layer<ROut, LE, RIn>): <I, A, E, R>(self: Cell<I, A, E, R>) => Cell<I, A, E | LE, RIn | Exclude<R, ROut>>;
177
227
  <I, A, E, R, RIn, LE, ROut>(self: Cell<I, A, E, R>, layer: Layer<ROut, LE, RIn>): Cell<I, A, E | LE, RIn | Exclude<R, ROut>>;
178
228
  };
179
- /**
180
- * Wraps the Cell's run in a `Policy` — retry, timeout, and their kin — preserving every
181
- * channel.
182
- */
183
- declare const withPolicy: {
184
- <A, E, R>(policy: Policy<A, E, R>): <I>(self: Cell<I, A, E, R>) => Cell<I, A, E, R>;
185
- <I, A, E, R>(self: Cell<I, A, E, R>, policy: Policy<A, E, R>): Cell<I, A, E, R>;
186
- };
187
229
  /**
188
230
  * The facts the lint plugin judges a spec body by, as a const table. The order the
189
231
  * interpreter runs is the text of {@link layerRunner}; the table states only what a
@@ -199,4 +241,4 @@ interface Vocabulary {
199
241
  }
200
242
  declare const vocabulary: Vocabulary;
201
243
  //#endregion
202
- export { Cell_d_exports as Cell, Policy_d_exports as Policy, Workflow_d_exports as Workflow };
244
+ export { Cell_d_exports as Cell, Workflow_d_exports as Workflow };
package/dist/index.mjs CHANGED
@@ -1,7 +1,9 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
- import * as Effect$1 from "effect/Effect";
2
+ import * as Effect from "effect/Effect";
3
3
  import { dual } from "effect/Function";
4
+ import * as Option from "effect/Option";
4
5
  import * as Result$1 from "effect/Result";
6
+ import { flatMap } from "effect/Result";
5
7
  //#region src/Facts.ts
6
8
  const DESCRIPTION_MODULE = "@systemfsoftware/effect-cell-types";
7
9
  const IO_CELLS = {
@@ -10,10 +12,42 @@ const IO_CELLS = {
10
12
  };
11
13
  //#endregion
12
14
  //#region src/Workflow.ts
13
- var Workflow_exports = /* @__PURE__ */ __exportAll({ make: () => make$1 });
15
+ var Workflow_exports = /* @__PURE__ */ __exportAll({
16
+ andThen: () => andThen$1,
17
+ make: () => make$1,
18
+ total: () => total
19
+ });
14
20
  const make$1 = (_command, decide) => {
15
21
  return decide;
16
22
  };
23
+ /**
24
+ * Brands a decision that cannot fail. `make` refuses a `never` error channel outright
25
+ * (`UninhabitedError`); this is the door for the decider that genuinely decides everything.
26
+ * The decision must still choose between at least two tagged variants sharing one TypeId, so
27
+ * `SingleVariantDecision`, `UntaggedDecision`, and `UnsharedTypeId` still fire.
28
+ *
29
+ * The command schema class comes first, exactly as in {@link make}, so the command channel
30
+ * stays pinned to the class rather than an inferred annotation. The decider's return carries
31
+ * `DecisionShape` written out: the `Workflow` alias is a deferred conditional, and in
32
+ * parameter position it collapses the whole parameter to `unknown` while the decision
33
+ * channel is still generic.
34
+ */
35
+ const total = (_command, decide) => {
36
+ return decide;
37
+ };
38
+ /**
39
+ * Composes two workflows: what the upstream decides becomes the command the downstream decides
40
+ * on, and a refusal short-circuits the pair. The return type dispatches on the component error
41
+ * union — two components that cannot fail publish the total form, because the `Workflow` alias
42
+ * refuses a `never` channel; a carried error publishes the union as before.
43
+ */
44
+ const andThen$1 = (_commandA, upstream, commandB, ctx, downstream) => {
45
+ const composed = (command) => flatMap(upstream(command), (decision) => downstream(new commandB({
46
+ decision,
47
+ ctx
48
+ })));
49
+ return composed;
50
+ };
17
51
  //#endregion
18
52
  //#region src/Cell.ts
19
53
  var Cell_exports = /* @__PURE__ */ __exportAll({
@@ -21,13 +55,14 @@ var Cell_exports = /* @__PURE__ */ __exportAll({
21
55
  DESCRIPTION_MODULE: () => DESCRIPTION_MODULE,
22
56
  IO_CELLS: () => IO_CELLS,
23
57
  andThen: () => andThen,
58
+ collect: () => collect,
59
+ collectAll: () => collectAll,
60
+ gate: () => gate,
24
61
  layer: () => layer,
25
62
  map: () => map,
26
63
  mapInput: () => mapInput,
27
64
  provide: () => provide,
28
- run: () => run,
29
65
  vocabulary: () => vocabulary,
30
- withPolicy: () => withPolicy,
31
66
  zip: () => zip
32
67
  });
33
68
  /**
@@ -44,16 +79,16 @@ const make = (run) => ({
44
79
  * a decide refusal is the outcome the encode and write receive, not a failure.
45
80
  */
46
81
  const layerRunner = (spec) => {
47
- if ("decode" in spec && "encode" in spec) return (input) => Effect$1.gen(function* () {
82
+ if ("decode" in spec && "encode" in spec) return (input) => Effect.gen(function* () {
48
83
  const raw = yield* spec.read(input);
49
84
  const decoded = yield* Result$1.match(spec.decode(raw), {
50
- onFailure: Effect$1.fail,
51
- onSuccess: Effect$1.succeed
85
+ onFailure: Effect.fail,
86
+ onSuccess: Effect.succeed
52
87
  });
53
88
  const outcome = spec.decide(decoded);
54
89
  return yield* spec.write(spec.encode(outcome), raw);
55
90
  });
56
- return (input) => Effect$1.gen(function* () {
91
+ return (input) => Effect.gen(function* () {
57
92
  const raw = yield* spec.read(input);
58
93
  const outcome = spec.decide(raw);
59
94
  return yield* spec.write(outcome, raw);
@@ -62,11 +97,10 @@ const layerRunner = (spec) => {
62
97
  function layer(spec) {
63
98
  return make(layerRunner(spec));
64
99
  }
65
- const run = dual(2, (self, input) => self.run(input));
66
100
  /**
67
101
  * Transforms the Cell's response.
68
102
  */
69
- const map = dual(2, (self, f) => make((input) => Effect$1.map(self.run(input), f)));
103
+ const map = dual(2, (self, f) => make((input) => Effect.map(self.run(input), f)));
70
104
  /**
71
105
  * Transforms the Cell's input.
72
106
  */
@@ -75,23 +109,37 @@ const mapInput = dual(2, (self, f) => make((input) => self.run(f(input))));
75
109
  * Feeds this Cell's response to the next Cell as its input. The error and service channels
76
110
  * union.
77
111
  */
78
- const andThen = dual(2, (self, that) => make((input) => Effect$1.flatMap(self.run(input), (response) => that.run(response))));
112
+ const andThen = dual(2, (self, that) => make((input) => Effect.flatMap(self.run(input), (response) => that.run(response))));
79
113
  /**
80
114
  * Runs both Cells against the same input and tuples the responses. Fails fast: when one
81
115
  * side refuses, the other's write never runs.
82
116
  */
83
- const zip = dual(2, (self, that) => make((input) => Effect$1.zipWith(self.run(input), that.run(input), (a, b) => [a, b])));
117
+ const zip = dual(2, (self, that) => make((input) => Effect.zipWith(self.run(input), that.run(input), (a, b) => [a, b])));
118
+ /**
119
+ * Runs the inner Cell on the value this Cell read, yielding `Option.none` when it read none.
120
+ * A skip is an absence, never a refusal; the error and service channels union.
121
+ */
122
+ const gate = dual(2, (self, inner) => make((input) => Effect.flatMap(self.run(input), (read) => Option.match(read, {
123
+ onNone: () => Effect.succeed(Option.none()),
124
+ onSome: (raw) => Effect.map(inner.run(raw), Option.some)
125
+ }))));
126
+ /**
127
+ * Runs the Cell once per item, in order, and folds the responses into one value. The error
128
+ * and service channels are unchanged; the first refusal ends the run.
129
+ */
130
+ const collect = dual(2, (self, fold) => make((items) => Effect.map(Effect.forEach(items, (item) => self.run(item)), (responses) => fold(responses))));
131
+ /**
132
+ * Runs the Cell once per item, in order, and folds every outcome — each a `Result.Result` —
133
+ * into one value. Unlike {@link collect}, no refusal ends the run: every item is attempted
134
+ * and its failure travels to the fold.
135
+ */
136
+ const collectAll = dual(2, (self, fold) => make((items) => Effect.map(Effect.forEach(items, (item) => Effect.result(self.run(item))), (results) => fold(results))));
84
137
  /**
85
138
  * Provides a Layer to the Cell, eliminating the services the layer builds from `R`. This is
86
139
  * the one composition-root elimination; the resulting Cell still demands the layer's input
87
140
  * services. A missing provide is a compile error at the run site.
88
141
  */
89
- const provide = dual(2, (self, layer) => make((input) => Effect$1.provide(self.run(input), layer)));
90
- /**
91
- * Wraps the Cell's run in a `Policy` — retry, timeout, and their kin — preserving every
92
- * channel.
93
- */
94
- const withPolicy = dual(2, (self, policy) => make((input) => policy(self.run(input))));
142
+ const provide = dual(2, (self, layer) => make((input) => Effect.provide(self.run(input), layer)));
95
143
  const vocabulary = {
96
144
  module: DESCRIPTION_MODULE,
97
145
  ioCells: IO_CELLS,
@@ -103,7 +151,4 @@ const vocabulary = {
103
151
  composer: "layer"
104
152
  };
105
153
  //#endregion
106
- //#region src/Policy.ts
107
- var Policy_exports = /* @__PURE__ */ __exportAll({});
108
- //#endregion
109
- export { Cell_exports as Cell, Policy_exports as Policy, Workflow_exports as Workflow };
154
+ export { Cell_exports as Cell, Workflow_exports as Workflow };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@systemfsoftware/effect-cell-types",
3
3
  "license": "Apache-2.0",
4
- "version": "7.0.1",
4
+ "version": "8.1.0",
5
5
  "author": "Ryan Lee <drdgvhbh@gmail.com>",
6
6
  "repository": {
7
7
  "type": "git",
@@ -43,9 +43,9 @@
43
43
  "tstyche": "^7.1.0",
44
44
  "vitest": "^4",
45
45
  "@systemfsoftware/effect-gherkin-spec": "4.0.2",
46
+ "@systemfsoftware/oxlint-config": "^0.1.0",
46
47
  "@systemfsoftware/tsconfig": "^1.3.4",
47
- "@systemfsoftware/vitest-config": "^0.1.0",
48
- "@systemfsoftware/oxlint-config": "^0.1.0"
48
+ "@systemfsoftware/vitest-config": "^0.1.0"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "effect": "4.0.0-rc.112"