@nunofyobiz/effect-extras 2.0.0 → 3.0.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/README.md +38 -3
- package/dist/ArrayX.d.ts +381 -0
- package/dist/ArrayX.d.ts.map +1 -0
- package/dist/ArrayX.js +493 -0
- package/dist/ArrayX.js.map +1 -0
- package/dist/BigIntX.d.ts +24 -0
- package/dist/BigIntX.d.ts.map +1 -0
- package/dist/BigIntX.js +30 -0
- package/dist/BigIntX.js.map +1 -0
- package/dist/BooleanX.d.ts +25 -0
- package/dist/BooleanX.d.ts.map +1 -0
- package/dist/BooleanX.js +25 -0
- package/dist/BooleanX.js.map +1 -0
- package/dist/DurationX.d.ts +73 -0
- package/dist/DurationX.d.ts.map +1 -0
- package/dist/DurationX.js +91 -0
- package/dist/DurationX.js.map +1 -0
- package/dist/EffectX.d.ts +120 -0
- package/dist/EffectX.d.ts.map +1 -0
- package/dist/EffectX.js +140 -0
- package/dist/EffectX.js.map +1 -0
- package/dist/FormDataX.d.ts +49 -0
- package/dist/FormDataX.d.ts.map +1 -0
- package/dist/FormDataX.js +42 -0
- package/dist/FormDataX.js.map +1 -0
- package/dist/InclusiveOr.d.ts +1123 -0
- package/dist/InclusiveOr.d.ts.map +1 -0
- package/dist/InclusiveOr.js +1074 -0
- package/dist/InclusiveOr.js.map +1 -0
- package/dist/MapX.d.ts +32 -0
- package/dist/MapX.d.ts.map +1 -0
- package/dist/MapX.js +49 -0
- package/dist/MapX.js.map +1 -0
- package/dist/NonNullableX.d.ts +174 -0
- package/dist/NonNullableX.d.ts.map +1 -0
- package/dist/NonNullableX.js +217 -0
- package/dist/NonNullableX.js.map +1 -0
- package/dist/NumberX.d.ts +178 -0
- package/dist/NumberX.d.ts.map +1 -0
- package/dist/NumberX.js +214 -0
- package/dist/NumberX.js.map +1 -0
- package/dist/OptionX.d.ts +187 -0
- package/dist/OptionX.d.ts.map +1 -0
- package/dist/OptionX.js +201 -0
- package/dist/OptionX.js.map +1 -0
- package/dist/OrderX.d.ts +32 -0
- package/dist/OrderX.d.ts.map +1 -0
- package/dist/OrderX.js +32 -0
- package/dist/OrderX.js.map +1 -0
- package/dist/PredicateX.d.ts +108 -0
- package/dist/PredicateX.d.ts.map +1 -0
- package/dist/PredicateX.js +111 -0
- package/dist/PredicateX.js.map +1 -0
- package/dist/PromiseX.d.ts +32 -0
- package/dist/PromiseX.d.ts.map +1 -0
- package/dist/PromiseX.js +32 -0
- package/dist/PromiseX.js.map +1 -0
- package/dist/RecordX.d.ts +450 -0
- package/dist/RecordX.d.ts.map +1 -0
- package/dist/RecordX.js +487 -0
- package/dist/RecordX.js.map +1 -0
- package/dist/ResultX.d.ts +50 -0
- package/dist/ResultX.d.ts.map +1 -0
- package/dist/ResultX.js +50 -0
- package/dist/ResultX.js.map +1 -0
- package/dist/SchemaX.d.ts +249 -0
- package/dist/SchemaX.d.ts.map +1 -0
- package/dist/SchemaX.js +243 -0
- package/dist/SchemaX.js.map +1 -0
- package/dist/SetX.d.ts +121 -0
- package/dist/SetX.d.ts.map +1 -0
- package/dist/SetX.js +137 -0
- package/dist/SetX.js.map +1 -0
- package/dist/StringX.d.ts +131 -0
- package/dist/StringX.d.ts.map +1 -0
- package/dist/StringX.js +149 -0
- package/dist/StringX.js.map +1 -0
- package/dist/StructX.d.ts +219 -0
- package/dist/StructX.d.ts.map +1 -0
- package/dist/StructX.js +173 -0
- package/dist/StructX.js.map +1 -0
- package/dist/WarnResult.d.ts +1191 -0
- package/dist/WarnResult.d.ts.map +1 -0
- package/dist/WarnResult.js +991 -0
- package/dist/WarnResult.js.map +1 -0
- package/dist/index.d.ts +23 -3772
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -1011
- package/dist/index.js.map +1 -1
- package/package.json +18 -5
- package/src/{ArrayX/ArrayX.ts → ArrayX.ts} +6 -88
- package/src/{DurationX/DurationX.ts → DurationX.ts} +1 -1
- package/src/InclusiveOr.ts +1255 -0
- package/src/{NonNullableX/NonNullableX.ts → NonNullableX.ts} +5 -0
- package/src/{OptionX/OptionX.ts → OptionX.ts} +8 -2
- package/src/{PredicateX/PredicateX.ts → PredicateX.ts} +41 -0
- package/src/{RecordX/RecordX.ts → RecordX.ts} +184 -2
- package/src/StringX.ts +210 -0
- package/src/{WarnResult/WarnResult.ts → WarnResult.ts} +297 -227
- package/src/index.ts +22 -20
- package/src/ArrayX/index.ts +0 -1
- package/src/BigIntX/index.ts +0 -1
- package/src/BooleanX/index.ts +0 -1
- package/src/DurationX/index.ts +0 -1
- package/src/EffectX/index.ts +0 -1
- package/src/FormDataX/index.ts +0 -1
- package/src/MapX/index.ts +0 -1
- package/src/NonNullableX/index.ts +0 -2
- package/src/NumberX/index.ts +0 -1
- package/src/OptionX/index.ts +0 -1
- package/src/OrderX/index.ts +0 -1
- package/src/PredicateX/index.ts +0 -1
- package/src/PromiseX/index.ts +0 -1
- package/src/RecordX/index.ts +0 -1
- package/src/ResultX/index.ts +0 -1
- package/src/SchemaX/index.ts +0 -1
- package/src/SetX/index.ts +0 -1
- package/src/StringX/StringX.ts +0 -97
- package/src/StringX/index.ts +0 -1
- package/src/StructX/index.ts +0 -1
- package/src/WarnResult/index.ts +0 -1
- /package/src/{BigIntX/BigIntX.ts → BigIntX.ts} +0 -0
- /package/src/{BooleanX/BooleanX.ts → BooleanX.ts} +0 -0
- /package/src/{EffectX/EffectX.ts → EffectX.ts} +0 -0
- /package/src/{FormDataX/FormDataX.ts → FormDataX.ts} +0 -0
- /package/src/{MapX/MapX.ts → MapX.ts} +0 -0
- /package/src/{NumberX/NumberX.ts → NumberX.ts} +0 -0
- /package/src/{OrderX/OrderX.ts → OrderX.ts} +0 -0
- /package/src/{PromiseX/PromiseX.ts → PromiseX.ts} +0 -0
- /package/src/{ResultX/ResultX.ts → ResultX.ts} +0 -0
- /package/src/{SchemaX/SchemaX.ts → SchemaX.ts} +0 -0
- /package/src/{SetX/SetX.ts → SetX.ts} +0 -0
- /package/src/{StructX/StructX.ts → StructX.ts} +0 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic, framework-agnostic extensions to Effect's `Schema` module.
|
|
3
|
+
*
|
|
4
|
+
* @since 0.0.0
|
|
5
|
+
*/
|
|
6
|
+
import { Schema } from "effect";
|
|
7
|
+
/**
|
|
8
|
+
* A `Schema` for a non-empty string that is trimmed on both decode and encode.
|
|
9
|
+
*
|
|
10
|
+
* Leading and trailing whitespace is stripped, and the resulting value must be
|
|
11
|
+
* non-empty — so a whitespace-only input (e.g. `" "`) fails the
|
|
12
|
+
* `NonEmptyString` refinement after trimming. Use it wherever user-supplied text
|
|
13
|
+
* should be normalized and guaranteed to carry content.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { Effect, Schema } from "effect"
|
|
18
|
+
* import { SchemaX } from "@nunofyobiz/effect-extras"
|
|
19
|
+
*
|
|
20
|
+
* const decoded = Effect.runSync(
|
|
21
|
+
* Schema.decodeEffect(SchemaX.TrimmedNonEmptyString)(" hello "),
|
|
22
|
+
* )
|
|
23
|
+
* assert.deepStrictEqual(decoded, "hello")
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @category constructors
|
|
27
|
+
* @since 0.0.0
|
|
28
|
+
*/
|
|
29
|
+
export declare const TrimmedNonEmptyString: Schema.decodeTo<Schema.toType<Schema.NonEmptyString>, Schema.NonEmptyString, never, never>;
|
|
30
|
+
/**
|
|
31
|
+
* A `Schema` for a URL-safe file path built on top of {@link
|
|
32
|
+
* TrimmedNonEmptyString}.
|
|
33
|
+
*
|
|
34
|
+
* On decode the path is `decodeURIComponent`-ed (percent-escapes are expanded);
|
|
35
|
+
* on encode it is `encodeURIComponent`-ed back into its URL-safe form. The
|
|
36
|
+
* underlying value is also trimmed and required to be non-empty. Use it at the
|
|
37
|
+
* boundary between stored/transmitted encoded paths and the decoded paths your
|
|
38
|
+
* code works with.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* import { Effect, Schema } from "effect"
|
|
43
|
+
* import { SchemaX } from "@nunofyobiz/effect-extras"
|
|
44
|
+
*
|
|
45
|
+
* // Decoding expands percent-escapes
|
|
46
|
+
* const decoded = Effect.runSync(
|
|
47
|
+
* Schema.decodeEffect(SchemaX.URLSafeFilePath)("a%2Fb.txt"),
|
|
48
|
+
* )
|
|
49
|
+
* assert.deepStrictEqual(decoded, "a/b.txt")
|
|
50
|
+
*
|
|
51
|
+
* // Encoding produces the URL-safe form
|
|
52
|
+
* const encoded = Effect.runSync(
|
|
53
|
+
* Schema.encodeEffect(SchemaX.URLSafeFilePath)("a/b.txt"),
|
|
54
|
+
* )
|
|
55
|
+
* assert.deepStrictEqual(encoded, "a%2Fb.txt")
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @category constructors
|
|
59
|
+
* @since 0.0.0
|
|
60
|
+
*/
|
|
61
|
+
export declare const URLSafeFilePath: Schema.decodeTo<Schema.toType<Schema.decodeTo<Schema.toType<Schema.NonEmptyString>, Schema.NonEmptyString, never, never>>, Schema.decodeTo<Schema.toType<Schema.NonEmptyString>, Schema.NonEmptyString, never, never>, never, never>;
|
|
62
|
+
/**
|
|
63
|
+
* Transforms a `bigint` `Schema` so its value is clamped to be non-negative,
|
|
64
|
+
* mapping any value below `0n` up to `0n` on both decode and encode.
|
|
65
|
+
*
|
|
66
|
+
* Unlike a refinement that *rejects* negative input, this *coerces* it: a
|
|
67
|
+
* negative `bigint` decodes to `0n` rather than failing. Apply it to a `bigint`
|
|
68
|
+
* schema whenever negative magnitudes are meaningless and should be floored at
|
|
69
|
+
* zero rather than treated as errors.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* import { Effect, Schema } from "effect"
|
|
74
|
+
* import { SchemaX } from "@nunofyobiz/effect-extras"
|
|
75
|
+
*
|
|
76
|
+
* const NonNegative = SchemaX.nonNegativeBigInt(Schema.BigInt)
|
|
77
|
+
*
|
|
78
|
+
* // Negative values are clamped up to 0n
|
|
79
|
+
* assert.deepStrictEqual(
|
|
80
|
+
* Effect.runSync(Schema.decodeEffect(NonNegative)(-5n)),
|
|
81
|
+
* 0n,
|
|
82
|
+
* )
|
|
83
|
+
*
|
|
84
|
+
* // Non-negative values pass through unchanged
|
|
85
|
+
* assert.deepStrictEqual(
|
|
86
|
+
* Effect.runSync(Schema.decodeEffect(NonNegative)(7n)),
|
|
87
|
+
* 7n,
|
|
88
|
+
* )
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @category combinators
|
|
92
|
+
* @since 0.0.0
|
|
93
|
+
*/
|
|
94
|
+
export declare const nonNegativeBigInt: <S extends Schema.Schema<bigint>>(schema: S) => Schema.decodeTo<Schema.toType<S>, S, never, never>;
|
|
95
|
+
/**
|
|
96
|
+
* Extracts the "constructor input" type of a `Schema` — what `.make({...})`
|
|
97
|
+
* accepts.
|
|
98
|
+
*
|
|
99
|
+
* Differs from `S["Type"]` (the decoded type) in that fields carrying
|
|
100
|
+
* constructor defaults (e.g. an `Overrideable` timestamp) are *optional* in
|
|
101
|
+
* `MakeIn` but *required* in `Type`. Use it in signatures that accept a value to
|
|
102
|
+
* construct, so callers can pass a plain object literal without supplying the
|
|
103
|
+
* defaulted, override-branded fields.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```ts
|
|
107
|
+
* import { Schema } from "effect"
|
|
108
|
+
* import { SchemaX } from "@nunofyobiz/effect-extras"
|
|
109
|
+
*
|
|
110
|
+
* const Person = Schema.Struct({ name: Schema.String, age: Schema.Number })
|
|
111
|
+
*
|
|
112
|
+
* const input: SchemaX.MakeIn<typeof Person> = { name: "Ada", age: 36 }
|
|
113
|
+
*
|
|
114
|
+
* assert.deepStrictEqual(input, { name: "Ada", age: 36 })
|
|
115
|
+
* ```
|
|
116
|
+
*
|
|
117
|
+
* @category models
|
|
118
|
+
* @since 0.0.0
|
|
119
|
+
*/
|
|
120
|
+
export type MakeIn<S extends {
|
|
121
|
+
readonly "~type.make.in": unknown;
|
|
122
|
+
}> = S["~type.make.in"];
|
|
123
|
+
/**
|
|
124
|
+
* Returns a new `Schema.Struct` containing only the named `keys` of `schema`.
|
|
125
|
+
*
|
|
126
|
+
* Restores the v3 ergonomics of `mySchema.pick("a", "b")` — v4 removed the
|
|
127
|
+
* `.pick(...)` method from `Schema.Struct` instances, so this rebuilds it on top
|
|
128
|
+
* of v4's `mapFields` primitive. Each picked field keeps its original schema,
|
|
129
|
+
* including any refinements.
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* import { Effect, Schema } from "effect"
|
|
134
|
+
* import { SchemaX } from "@nunofyobiz/effect-extras"
|
|
135
|
+
*
|
|
136
|
+
* const Source = Schema.Struct({
|
|
137
|
+
* a: Schema.Number,
|
|
138
|
+
* b: Schema.String,
|
|
139
|
+
* c: Schema.Boolean,
|
|
140
|
+
* })
|
|
141
|
+
*
|
|
142
|
+
* const Picked = SchemaX.pick(Source, "a", "b")
|
|
143
|
+
*
|
|
144
|
+
* const decoded = Effect.runSync(
|
|
145
|
+
* Schema.decodeEffect(Picked)({ a: 1, b: "hi" }),
|
|
146
|
+
* )
|
|
147
|
+
* assert.deepStrictEqual(decoded, { a: 1, b: "hi" })
|
|
148
|
+
* ```
|
|
149
|
+
*
|
|
150
|
+
* @category combinators
|
|
151
|
+
* @since 0.0.0
|
|
152
|
+
*/
|
|
153
|
+
export declare const pick: <const Fields extends Schema.Struct.Fields, const Keys extends readonly (keyof Fields & string)[]>(schema: Schema.Struct<Fields>, ...keys: Keys) => Schema.Struct<Pick<Fields, Keys[number]>>;
|
|
154
|
+
/**
|
|
155
|
+
* Returns a new `Schema.Struct` with the named `keys` of `schema` removed.
|
|
156
|
+
*
|
|
157
|
+
* The complement of {@link pick}, restoring the v3 ergonomics of
|
|
158
|
+
* `mySchema.omit("a")` that v4 dropped from `Schema.Struct` instances. Every
|
|
159
|
+
* surviving field keeps its original schema, including any refinements.
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```ts
|
|
163
|
+
* import { Effect, Schema } from "effect"
|
|
164
|
+
* import { SchemaX } from "@nunofyobiz/effect-extras"
|
|
165
|
+
*
|
|
166
|
+
* const Source = Schema.Struct({
|
|
167
|
+
* a: Schema.Number,
|
|
168
|
+
* b: Schema.String,
|
|
169
|
+
* c: Schema.Boolean,
|
|
170
|
+
* })
|
|
171
|
+
*
|
|
172
|
+
* const Omitted = SchemaX.omit(Source, "c")
|
|
173
|
+
*
|
|
174
|
+
* const decoded = Effect.runSync(
|
|
175
|
+
* Schema.decodeEffect(Omitted)({ a: 1, b: "hi" }),
|
|
176
|
+
* )
|
|
177
|
+
* assert.deepStrictEqual(decoded, { a: 1, b: "hi" })
|
|
178
|
+
* ```
|
|
179
|
+
*
|
|
180
|
+
* @category combinators
|
|
181
|
+
* @since 0.0.0
|
|
182
|
+
*/
|
|
183
|
+
export declare const omit: <const Fields extends Schema.Struct.Fields, const Keys extends readonly (keyof Fields & string)[]>(schema: Schema.Struct<Fields>, ...keys: Keys) => Schema.Struct<Omit<Fields, Keys[number]>>;
|
|
184
|
+
/**
|
|
185
|
+
* Returns a new `Schema.Struct` in which every field of `schema` is made
|
|
186
|
+
* optional.
|
|
187
|
+
*
|
|
188
|
+
* Restores the v3 `Schema.partial(mySchema)` behaviour that v4 removed, by
|
|
189
|
+
* wrapping each field in `Schema.optional`. A decoded value may therefore omit
|
|
190
|
+
* any field; fields that *are* present still have to satisfy their original
|
|
191
|
+
* schema, refinements included.
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* ```ts
|
|
195
|
+
* import { Effect, Schema } from "effect"
|
|
196
|
+
* import { SchemaX } from "@nunofyobiz/effect-extras"
|
|
197
|
+
*
|
|
198
|
+
* const Source = Schema.Struct({ a: Schema.Number, b: Schema.String })
|
|
199
|
+
* const Partial = SchemaX.partial(Source)
|
|
200
|
+
*
|
|
201
|
+
* // All fields may be absent
|
|
202
|
+
* assert.deepStrictEqual(Effect.runSync(Schema.decodeEffect(Partial)({})), {})
|
|
203
|
+
*
|
|
204
|
+
* // A present subset still decodes
|
|
205
|
+
* assert.deepStrictEqual(
|
|
206
|
+
* Effect.runSync(Schema.decodeEffect(Partial)({ a: 1 })),
|
|
207
|
+
* { a: 1 },
|
|
208
|
+
* )
|
|
209
|
+
* ```
|
|
210
|
+
*
|
|
211
|
+
* @category combinators
|
|
212
|
+
* @since 0.0.0
|
|
213
|
+
*/
|
|
214
|
+
export declare const partial: <Fields extends Schema.Struct.Fields>(schema: Schema.Struct<Fields>) => Schema.Struct<{ [K in keyof Fields]: Schema.optional<Fields[K]>; }>;
|
|
215
|
+
/**
|
|
216
|
+
* Returns a new `Schema.Struct` containing only the named `keys` of `schema`,
|
|
217
|
+
* with every picked field made optional.
|
|
218
|
+
*
|
|
219
|
+
* Equivalent to `partial(pick(schema, ...keys))`, but reads more directly for
|
|
220
|
+
* the common "partial update over a subset of fields" pattern: select the
|
|
221
|
+
* mutable fields of an entity, then allow any of them to be omitted in the
|
|
222
|
+
* update payload. Composes {@link pick} and {@link partial} in one call.
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* ```ts
|
|
226
|
+
* import { Effect, Schema } from "effect"
|
|
227
|
+
* import { SchemaX } from "@nunofyobiz/effect-extras"
|
|
228
|
+
*
|
|
229
|
+
* const Source = Schema.Struct({
|
|
230
|
+
* a: Schema.Number,
|
|
231
|
+
* b: Schema.String,
|
|
232
|
+
* c: Schema.Boolean,
|
|
233
|
+
* })
|
|
234
|
+
*
|
|
235
|
+
* const Update = SchemaX.pickPartial(Source, "a", "b")
|
|
236
|
+
*
|
|
237
|
+
* // Only picked fields are known, and each may be omitted
|
|
238
|
+
* assert.deepStrictEqual(Effect.runSync(Schema.decodeEffect(Update)({})), {})
|
|
239
|
+
* assert.deepStrictEqual(
|
|
240
|
+
* Effect.runSync(Schema.decodeEffect(Update)({ a: 1 })),
|
|
241
|
+
* { a: 1 },
|
|
242
|
+
* )
|
|
243
|
+
* ```
|
|
244
|
+
*
|
|
245
|
+
* @category combinators
|
|
246
|
+
* @since 0.0.0
|
|
247
|
+
*/
|
|
248
|
+
export declare const pickPartial: <const Fields extends Schema.Struct.Fields, const Keys extends readonly (keyof Fields & string)[]>(schema: Schema.Struct<Fields>, ...keys: Keys) => Schema.Struct<{ [K in Keys[number]]: Schema.optional<Fields[K]>; }>;
|
|
249
|
+
//# sourceMappingURL=SchemaX.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaX.d.ts","sourceRoot":"","sources":["../src/SchemaX.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAU,MAAM,EAAwB,MAAM,QAAQ,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,qBAAqB,4FAKjC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,eAAe,sOAK3B,CAAC;AAaF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,iBAAiB,GAxC3B,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,uDAwCM,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS;IAAE,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAA;CAAE,IAChE,CAAC,CAAC,eAAe,CAAC,CAAC;AAQrB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,IAAI,GACf,KAAK,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,EACzC,KAAK,CAAC,IAAI,SAAS,SAAS,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,EAErD,QAAQ,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAC7B,GAAG,MAAM,IAAI,KACZ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAOxC,CAAC;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,IAAI,GACf,KAAK,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,EACzC,KAAK,CAAC,IAAI,SAAS,SAAS,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,EAErD,QAAQ,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAC7B,GAAG,MAAM,IAAI,KACZ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAOxC,CAAC;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,OAAO,GAAI,MAAM,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,EACzD,QAAQ,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAC5B,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAE,CAOhE,CAAC;AAEL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,WAAW,GACtB,KAAK,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,EACzC,KAAK,CAAC,IAAI,SAAS,SAAS,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,EAErD,QAAQ,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAC7B,GAAG,MAAM,IAAI,KACZ,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAE,CACpC,CAAC"}
|
package/dist/SchemaX.js
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic, framework-agnostic extensions to Effect's `Schema` module.
|
|
3
|
+
*
|
|
4
|
+
* @since 0.0.0
|
|
5
|
+
*/
|
|
6
|
+
import { BigInt, Schema, SchemaGetter, Struct } from "effect";
|
|
7
|
+
/**
|
|
8
|
+
* A `Schema` for a non-empty string that is trimmed on both decode and encode.
|
|
9
|
+
*
|
|
10
|
+
* Leading and trailing whitespace is stripped, and the resulting value must be
|
|
11
|
+
* non-empty — so a whitespace-only input (e.g. `" "`) fails the
|
|
12
|
+
* `NonEmptyString` refinement after trimming. Use it wherever user-supplied text
|
|
13
|
+
* should be normalized and guaranteed to carry content.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { Effect, Schema } from "effect"
|
|
18
|
+
* import { SchemaX } from "@nunofyobiz/effect-extras"
|
|
19
|
+
*
|
|
20
|
+
* const decoded = Effect.runSync(
|
|
21
|
+
* Schema.decodeEffect(SchemaX.TrimmedNonEmptyString)(" hello "),
|
|
22
|
+
* )
|
|
23
|
+
* assert.deepStrictEqual(decoded, "hello")
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @category constructors
|
|
27
|
+
* @since 0.0.0
|
|
28
|
+
*/
|
|
29
|
+
export const TrimmedNonEmptyString = /*#__PURE__*/Schema.NonEmptyString.pipe(/*#__PURE__*/Schema.decode({
|
|
30
|
+
decode: /*#__PURE__*/SchemaGetter.transform(s => s.trim()),
|
|
31
|
+
encode: /*#__PURE__*/SchemaGetter.transform(s => s.trim())
|
|
32
|
+
}));
|
|
33
|
+
/**
|
|
34
|
+
* A `Schema` for a URL-safe file path built on top of {@link
|
|
35
|
+
* TrimmedNonEmptyString}.
|
|
36
|
+
*
|
|
37
|
+
* On decode the path is `decodeURIComponent`-ed (percent-escapes are expanded);
|
|
38
|
+
* on encode it is `encodeURIComponent`-ed back into its URL-safe form. The
|
|
39
|
+
* underlying value is also trimmed and required to be non-empty. Use it at the
|
|
40
|
+
* boundary between stored/transmitted encoded paths and the decoded paths your
|
|
41
|
+
* code works with.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* import { Effect, Schema } from "effect"
|
|
46
|
+
* import { SchemaX } from "@nunofyobiz/effect-extras"
|
|
47
|
+
*
|
|
48
|
+
* // Decoding expands percent-escapes
|
|
49
|
+
* const decoded = Effect.runSync(
|
|
50
|
+
* Schema.decodeEffect(SchemaX.URLSafeFilePath)("a%2Fb.txt"),
|
|
51
|
+
* )
|
|
52
|
+
* assert.deepStrictEqual(decoded, "a/b.txt")
|
|
53
|
+
*
|
|
54
|
+
* // Encoding produces the URL-safe form
|
|
55
|
+
* const encoded = Effect.runSync(
|
|
56
|
+
* Schema.encodeEffect(SchemaX.URLSafeFilePath)("a/b.txt"),
|
|
57
|
+
* )
|
|
58
|
+
* assert.deepStrictEqual(encoded, "a%2Fb.txt")
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @category constructors
|
|
62
|
+
* @since 0.0.0
|
|
63
|
+
*/
|
|
64
|
+
export const URLSafeFilePath = /*#__PURE__*/TrimmedNonEmptyString.pipe(/*#__PURE__*/Schema.decode({
|
|
65
|
+
decode: /*#__PURE__*/SchemaGetter.transform(path => decodeURIComponent(path)),
|
|
66
|
+
encode: /*#__PURE__*/SchemaGetter.transform(path => encodeURIComponent(path))
|
|
67
|
+
}));
|
|
68
|
+
// Internal — only used to construct nonNegativeBigInt below.
|
|
69
|
+
const clampMinBigInt = min => schema => schema.pipe(Schema.decode({
|
|
70
|
+
decode: SchemaGetter.transform(value => BigInt.max(value, min)),
|
|
71
|
+
encode: SchemaGetter.transform(value => BigInt.max(value, min))
|
|
72
|
+
}));
|
|
73
|
+
/**
|
|
74
|
+
* Transforms a `bigint` `Schema` so its value is clamped to be non-negative,
|
|
75
|
+
* mapping any value below `0n` up to `0n` on both decode and encode.
|
|
76
|
+
*
|
|
77
|
+
* Unlike a refinement that *rejects* negative input, this *coerces* it: a
|
|
78
|
+
* negative `bigint` decodes to `0n` rather than failing. Apply it to a `bigint`
|
|
79
|
+
* schema whenever negative magnitudes are meaningless and should be floored at
|
|
80
|
+
* zero rather than treated as errors.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* import { Effect, Schema } from "effect"
|
|
85
|
+
* import { SchemaX } from "@nunofyobiz/effect-extras"
|
|
86
|
+
*
|
|
87
|
+
* const NonNegative = SchemaX.nonNegativeBigInt(Schema.BigInt)
|
|
88
|
+
*
|
|
89
|
+
* // Negative values are clamped up to 0n
|
|
90
|
+
* assert.deepStrictEqual(
|
|
91
|
+
* Effect.runSync(Schema.decodeEffect(NonNegative)(-5n)),
|
|
92
|
+
* 0n,
|
|
93
|
+
* )
|
|
94
|
+
*
|
|
95
|
+
* // Non-negative values pass through unchanged
|
|
96
|
+
* assert.deepStrictEqual(
|
|
97
|
+
* Effect.runSync(Schema.decodeEffect(NonNegative)(7n)),
|
|
98
|
+
* 7n,
|
|
99
|
+
* )
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* @category combinators
|
|
103
|
+
* @since 0.0.0
|
|
104
|
+
*/
|
|
105
|
+
export const nonNegativeBigInt = /*#__PURE__*/clampMinBigInt(0n);
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// Schema.Struct utilities — v4 removed the `.pick(...)`, `.omit(...)`, and
|
|
108
|
+
// `Schema.partial(...)` methods that v3 had on `Schema.Struct` instances. These
|
|
109
|
+
// helpers restore the same ergonomics on top of v4's `mapFields` primitive.
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
/**
|
|
112
|
+
* Returns a new `Schema.Struct` containing only the named `keys` of `schema`.
|
|
113
|
+
*
|
|
114
|
+
* Restores the v3 ergonomics of `mySchema.pick("a", "b")` — v4 removed the
|
|
115
|
+
* `.pick(...)` method from `Schema.Struct` instances, so this rebuilds it on top
|
|
116
|
+
* of v4's `mapFields` primitive. Each picked field keeps its original schema,
|
|
117
|
+
* including any refinements.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* import { Effect, Schema } from "effect"
|
|
122
|
+
* import { SchemaX } from "@nunofyobiz/effect-extras"
|
|
123
|
+
*
|
|
124
|
+
* const Source = Schema.Struct({
|
|
125
|
+
* a: Schema.Number,
|
|
126
|
+
* b: Schema.String,
|
|
127
|
+
* c: Schema.Boolean,
|
|
128
|
+
* })
|
|
129
|
+
*
|
|
130
|
+
* const Picked = SchemaX.pick(Source, "a", "b")
|
|
131
|
+
*
|
|
132
|
+
* const decoded = Effect.runSync(
|
|
133
|
+
* Schema.decodeEffect(Picked)({ a: 1, b: "hi" }),
|
|
134
|
+
* )
|
|
135
|
+
* assert.deepStrictEqual(decoded, { a: 1, b: "hi" })
|
|
136
|
+
* ```
|
|
137
|
+
*
|
|
138
|
+
* @category combinators
|
|
139
|
+
* @since 0.0.0
|
|
140
|
+
*/
|
|
141
|
+
export const pick = (schema, ...keys) => schema.mapFields(fields => Struct.pick(fields, keys));
|
|
142
|
+
/**
|
|
143
|
+
* Returns a new `Schema.Struct` with the named `keys` of `schema` removed.
|
|
144
|
+
*
|
|
145
|
+
* The complement of {@link pick}, restoring the v3 ergonomics of
|
|
146
|
+
* `mySchema.omit("a")` that v4 dropped from `Schema.Struct` instances. Every
|
|
147
|
+
* surviving field keeps its original schema, including any refinements.
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```ts
|
|
151
|
+
* import { Effect, Schema } from "effect"
|
|
152
|
+
* import { SchemaX } from "@nunofyobiz/effect-extras"
|
|
153
|
+
*
|
|
154
|
+
* const Source = Schema.Struct({
|
|
155
|
+
* a: Schema.Number,
|
|
156
|
+
* b: Schema.String,
|
|
157
|
+
* c: Schema.Boolean,
|
|
158
|
+
* })
|
|
159
|
+
*
|
|
160
|
+
* const Omitted = SchemaX.omit(Source, "c")
|
|
161
|
+
*
|
|
162
|
+
* const decoded = Effect.runSync(
|
|
163
|
+
* Schema.decodeEffect(Omitted)({ a: 1, b: "hi" }),
|
|
164
|
+
* )
|
|
165
|
+
* assert.deepStrictEqual(decoded, { a: 1, b: "hi" })
|
|
166
|
+
* ```
|
|
167
|
+
*
|
|
168
|
+
* @category combinators
|
|
169
|
+
* @since 0.0.0
|
|
170
|
+
*/
|
|
171
|
+
export const omit = (schema, ...keys) => schema.mapFields(fields => Struct.omit(fields, keys));
|
|
172
|
+
/**
|
|
173
|
+
* Returns a new `Schema.Struct` in which every field of `schema` is made
|
|
174
|
+
* optional.
|
|
175
|
+
*
|
|
176
|
+
* Restores the v3 `Schema.partial(mySchema)` behaviour that v4 removed, by
|
|
177
|
+
* wrapping each field in `Schema.optional`. A decoded value may therefore omit
|
|
178
|
+
* any field; fields that *are* present still have to satisfy their original
|
|
179
|
+
* schema, refinements included.
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* ```ts
|
|
183
|
+
* import { Effect, Schema } from "effect"
|
|
184
|
+
* import { SchemaX } from "@nunofyobiz/effect-extras"
|
|
185
|
+
*
|
|
186
|
+
* const Source = Schema.Struct({ a: Schema.Number, b: Schema.String })
|
|
187
|
+
* const Partial = SchemaX.partial(Source)
|
|
188
|
+
*
|
|
189
|
+
* // All fields may be absent
|
|
190
|
+
* assert.deepStrictEqual(Effect.runSync(Schema.decodeEffect(Partial)({})), {})
|
|
191
|
+
*
|
|
192
|
+
* // A present subset still decodes
|
|
193
|
+
* assert.deepStrictEqual(
|
|
194
|
+
* Effect.runSync(Schema.decodeEffect(Partial)({ a: 1 })),
|
|
195
|
+
* { a: 1 },
|
|
196
|
+
* )
|
|
197
|
+
* ```
|
|
198
|
+
*
|
|
199
|
+
* @category combinators
|
|
200
|
+
* @since 0.0.0
|
|
201
|
+
*/
|
|
202
|
+
export const partial = schema => schema.mapFields(fields => {
|
|
203
|
+
const result = {};
|
|
204
|
+
for (const key of Object.keys(fields)) {
|
|
205
|
+
result[key] = Schema.optional(fields[key]);
|
|
206
|
+
}
|
|
207
|
+
return result;
|
|
208
|
+
});
|
|
209
|
+
/**
|
|
210
|
+
* Returns a new `Schema.Struct` containing only the named `keys` of `schema`,
|
|
211
|
+
* with every picked field made optional.
|
|
212
|
+
*
|
|
213
|
+
* Equivalent to `partial(pick(schema, ...keys))`, but reads more directly for
|
|
214
|
+
* the common "partial update over a subset of fields" pattern: select the
|
|
215
|
+
* mutable fields of an entity, then allow any of them to be omitted in the
|
|
216
|
+
* update payload. Composes {@link pick} and {@link partial} in one call.
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```ts
|
|
220
|
+
* import { Effect, Schema } from "effect"
|
|
221
|
+
* import { SchemaX } from "@nunofyobiz/effect-extras"
|
|
222
|
+
*
|
|
223
|
+
* const Source = Schema.Struct({
|
|
224
|
+
* a: Schema.Number,
|
|
225
|
+
* b: Schema.String,
|
|
226
|
+
* c: Schema.Boolean,
|
|
227
|
+
* })
|
|
228
|
+
*
|
|
229
|
+
* const Update = SchemaX.pickPartial(Source, "a", "b")
|
|
230
|
+
*
|
|
231
|
+
* // Only picked fields are known, and each may be omitted
|
|
232
|
+
* assert.deepStrictEqual(Effect.runSync(Schema.decodeEffect(Update)({})), {})
|
|
233
|
+
* assert.deepStrictEqual(
|
|
234
|
+
* Effect.runSync(Schema.decodeEffect(Update)({ a: 1 })),
|
|
235
|
+
* { a: 1 },
|
|
236
|
+
* )
|
|
237
|
+
* ```
|
|
238
|
+
*
|
|
239
|
+
* @category combinators
|
|
240
|
+
* @since 0.0.0
|
|
241
|
+
*/
|
|
242
|
+
export const pickPartial = (schema, ...keys) => partial(pick(schema, ...keys));
|
|
243
|
+
//# sourceMappingURL=SchemaX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaX.js","names":["BigInt","Schema","SchemaGetter","Struct","TrimmedNonEmptyString","NonEmptyString","pipe","decode","transform","s","trim","encode","URLSafeFilePath","path","decodeURIComponent","encodeURIComponent","clampMinBigInt","min","schema","value","max","nonNegativeBigInt","pick","keys","mapFields","fields","omit","partial","result","key","Object","optional","pickPartial"],"sources":["../src/SchemaX.ts"],"sourcesContent":[null],"mappings":"AAAA;;;;;AAKA,SAASA,MAAM,EAAEC,MAAM,EAAEC,YAAY,EAAEC,MAAM,QAAQ,QAAQ;AAE7D;;;;;;;;;;;;;;;;;;;;;;AAsBA,OAAO,MAAMC,qBAAqB,gBAAGH,MAAM,CAACI,cAAc,CAACC,IAAI,cAC7DL,MAAM,CAACM,MAAM,CAAC;EACZA,MAAM,eAAEL,YAAY,CAACM,SAAS,CAAEC,CAAC,IAAKA,CAAC,CAACC,IAAI,EAAE,CAAC;EAC/CC,MAAM,eAAET,YAAY,CAACM,SAAS,CAAEC,CAAC,IAAKA,CAAC,CAACC,IAAI,EAAE;CAC/C,CAAC,CACH;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,OAAO,MAAME,eAAe,gBAAGR,qBAAqB,CAACE,IAAI,cACvDL,MAAM,CAACM,MAAM,CAAC;EACZA,MAAM,eAAEL,YAAY,CAACM,SAAS,CAAEK,IAAI,IAAKC,kBAAkB,CAACD,IAAI,CAAC,CAAC;EAClEF,MAAM,eAAET,YAAY,CAACM,SAAS,CAAEK,IAAI,IAAKE,kBAAkB,CAACF,IAAI,CAAC;CAClE,CAAC,CACH;AAED;AACA,MAAMG,cAAc,GACjBC,GAAW,IACsBC,MAAS,IACzCA,MAAM,CAACZ,IAAI,CACTL,MAAM,CAACM,MAAM,CAAC;EACZA,MAAM,EAAEL,YAAY,CAACM,SAAS,CAAEW,KAAK,IAAKnB,MAAM,CAACoB,GAAG,CAACD,KAAK,EAAEF,GAAG,CAAC,CAAC;EACjEN,MAAM,EAAET,YAAY,CAACM,SAAS,CAAEW,KAAK,IAAKnB,MAAM,CAACoB,GAAG,CAACD,KAAK,EAAEF,GAAG,CAAC;CACjE,CAAC,CACH;AAEL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,OAAO,MAAMI,iBAAiB,gBAAGL,cAAc,CAAC,EAAE,CAAC;AA8BnD;AACA;AACA;AACA;AACA;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,OAAO,MAAMM,IAAI,GAAGA,CAIlBJ,MAA6B,EAC7B,GAAGK,IAAU,KAEbL,MAAM,CAACM,SAAS,CACbC,MAAM,IACLtB,MAAM,CAACmB,IAAI,CAACG,MAAM,EAAEF,IAAiC,CAGpD,CACJ;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,OAAO,MAAMG,IAAI,GAAGA,CAIlBR,MAA6B,EAC7B,GAAGK,IAAU,KAEbL,MAAM,CAACM,SAAS,CACbC,MAAM,IACLtB,MAAM,CAACuB,IAAI,CAACD,MAAM,EAAEF,IAAiC,CAGpD,CACJ;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,OAAO,MAAMI,OAAO,GAClBT,MAA6B,IAE7BA,MAAM,CAACM,SAAS,CAAEC,MAAM,IAAI;EAC1B,MAAMG,MAAM,GAAyD,EAAE;EACvE,KAAK,MAAMC,GAAG,IAAIC,MAAM,CAACP,IAAI,CAACE,MAAM,CAAqB,EAAE;IACzDG,MAAM,CAACC,GAAG,CAAC,GAAG5B,MAAM,CAAC8B,QAAQ,CAACN,MAAM,CAACI,GAAG,CAAC,CAAC;EAC5C;EACA,OAAOD,MAA6D;AACtE,CAAC,CAAC;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,OAAO,MAAMI,WAAW,GAAGA,CAIzBd,MAA6B,EAC7B,GAAGK,IAAU,KAEbI,OAAO,CAACL,IAAI,CAACJ,MAAM,EAAE,GAAGK,IAAI,CAAC,CAAC","ignoreList":[]}
|
package/dist/SetX.d.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs a mutating function against a copy of `set`, leaving the original
|
|
3
|
+
* untouched, and returns the mutated copy.
|
|
4
|
+
*
|
|
5
|
+
* Use it to reuse imperative `Set` mutation code (`.add`, `.delete`) without
|
|
6
|
+
* sacrificing immutability: the callback may freely mutate the set it receives
|
|
7
|
+
* because it operates on a fresh clone. Supports both data-first and data-last
|
|
8
|
+
* (pipeable) call styles.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { SetX } from "@nunofyobiz/effect-extras"
|
|
13
|
+
* import { pipe } from "effect"
|
|
14
|
+
*
|
|
15
|
+
* const original = new Set(["a", "b"])
|
|
16
|
+
*
|
|
17
|
+
* const result = pipe(
|
|
18
|
+
* original,
|
|
19
|
+
* SetX.safelyMutate((set) => {
|
|
20
|
+
* set.delete("a")
|
|
21
|
+
* return set.add("c")
|
|
22
|
+
* })
|
|
23
|
+
* )
|
|
24
|
+
*
|
|
25
|
+
* assert.deepStrictEqual(result, new Set(["b", "c"]))
|
|
26
|
+
* // The original is left intact
|
|
27
|
+
* assert.deepStrictEqual(original, new Set(["a", "b"]))
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @category combinators
|
|
31
|
+
* @since 0.0.0
|
|
32
|
+
*/
|
|
33
|
+
export declare const safelyMutate: (<A>(mutate: (set: Set<A>) => Set<A>) => (set: Set<A>) => Set<A>) & (<A>(set: Set<A>, mutate: (set: Set<A>) => Set<A>) => Set<A>);
|
|
34
|
+
/**
|
|
35
|
+
* Returns a new `Set` with `value` added, leaving the input set unchanged.
|
|
36
|
+
*
|
|
37
|
+
* When `value` is already present the input set is returned as-is (no copy),
|
|
38
|
+
* making repeated adds of existing members allocation-free. Supports both
|
|
39
|
+
* data-first and data-last (pipeable) call styles.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* import { SetX } from "@nunofyobiz/effect-extras"
|
|
44
|
+
* import { pipe } from "effect"
|
|
45
|
+
*
|
|
46
|
+
* // Data-first — adds a new element into a fresh set
|
|
47
|
+
* assert.deepStrictEqual(
|
|
48
|
+
* SetX.add(new Set(["a", "b"]), "c"),
|
|
49
|
+
* new Set(["a", "b", "c"])
|
|
50
|
+
* )
|
|
51
|
+
*
|
|
52
|
+
* // Data-last — existing element leaves the set unchanged
|
|
53
|
+
* assert.deepStrictEqual(
|
|
54
|
+
* pipe(new Set(["a", "b"]), SetX.add("b")),
|
|
55
|
+
* new Set(["a", "b"])
|
|
56
|
+
* )
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @category combinators
|
|
60
|
+
* @since 0.0.0
|
|
61
|
+
*/
|
|
62
|
+
export declare const add: (<A>(value: A) => (set: Set<A>) => Set<A>) & (<A>(set: Set<A>, value: A) => Set<A>);
|
|
63
|
+
/**
|
|
64
|
+
* Returns a new `Set` with `value` removed, leaving the input set unchanged.
|
|
65
|
+
*
|
|
66
|
+
* When `value` is absent the input set is returned as-is (no copy). Supports both
|
|
67
|
+
* data-first and data-last (pipeable) call styles.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* import { SetX } from "@nunofyobiz/effect-extras"
|
|
72
|
+
* import { pipe } from "effect"
|
|
73
|
+
*
|
|
74
|
+
* // Data-first — removes an existing element into a fresh set
|
|
75
|
+
* assert.deepStrictEqual(
|
|
76
|
+
* SetX.remove(new Set(["a", "b", "c"]), "c"),
|
|
77
|
+
* new Set(["a", "b"])
|
|
78
|
+
* )
|
|
79
|
+
*
|
|
80
|
+
* // Data-last — absent element leaves the set unchanged
|
|
81
|
+
* assert.deepStrictEqual(
|
|
82
|
+
* pipe(new Set(["a", "b"]), SetX.remove("z")),
|
|
83
|
+
* new Set(["a", "b"])
|
|
84
|
+
* )
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* @category combinators
|
|
88
|
+
* @since 0.0.0
|
|
89
|
+
*/
|
|
90
|
+
export declare const remove: (<A>(value: A) => (set: Set<A>) => Set<A>) & (<A>(set: Set<A>, value: A) => Set<A>);
|
|
91
|
+
/**
|
|
92
|
+
* Returns a new `Set` with `value` added if it was absent or removed if it was
|
|
93
|
+
* present, leaving the input set unchanged.
|
|
94
|
+
*
|
|
95
|
+
* Use it for membership toggles (selection state, feature flags by key) where a
|
|
96
|
+
* value's presence should flip on each call. Supports both data-first and
|
|
97
|
+
* data-last (pipeable) call styles.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```ts
|
|
101
|
+
* import { SetX } from "@nunofyobiz/effect-extras"
|
|
102
|
+
* import { pipe } from "effect"
|
|
103
|
+
*
|
|
104
|
+
* // Data-first — absent value gets added
|
|
105
|
+
* assert.deepStrictEqual(
|
|
106
|
+
* SetX.toggle(new Set(["a", "b"]), "c"),
|
|
107
|
+
* new Set(["a", "b", "c"])
|
|
108
|
+
* )
|
|
109
|
+
*
|
|
110
|
+
* // Data-last — present value gets removed
|
|
111
|
+
* assert.deepStrictEqual(
|
|
112
|
+
* pipe(new Set(["a", "b", "c"]), SetX.toggle("b")),
|
|
113
|
+
* new Set(["a", "c"])
|
|
114
|
+
* )
|
|
115
|
+
* ```
|
|
116
|
+
*
|
|
117
|
+
* @category combinators
|
|
118
|
+
* @since 0.0.0
|
|
119
|
+
*/
|
|
120
|
+
export declare const toggle: (<A>(value: A) => (set: Set<A>) => Set<A>) & (<A>(set: Set<A>, value: A) => Set<A>);
|
|
121
|
+
//# sourceMappingURL=SetX.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SetX.d.ts","sourceRoot":"","sources":["../src/SetX.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,YAAY,IACtB,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,MAC9D,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAI3D,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,GAAG,IACb,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,MACvC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAKrC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,MAAM,IAChB,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,MACvC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAQpC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,MAAM,IAChB,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,MACvC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAKrC,CAAC"}
|