@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.
Files changed (133) hide show
  1. package/README.md +38 -3
  2. package/dist/ArrayX.d.ts +381 -0
  3. package/dist/ArrayX.d.ts.map +1 -0
  4. package/dist/ArrayX.js +493 -0
  5. package/dist/ArrayX.js.map +1 -0
  6. package/dist/BigIntX.d.ts +24 -0
  7. package/dist/BigIntX.d.ts.map +1 -0
  8. package/dist/BigIntX.js +30 -0
  9. package/dist/BigIntX.js.map +1 -0
  10. package/dist/BooleanX.d.ts +25 -0
  11. package/dist/BooleanX.d.ts.map +1 -0
  12. package/dist/BooleanX.js +25 -0
  13. package/dist/BooleanX.js.map +1 -0
  14. package/dist/DurationX.d.ts +73 -0
  15. package/dist/DurationX.d.ts.map +1 -0
  16. package/dist/DurationX.js +91 -0
  17. package/dist/DurationX.js.map +1 -0
  18. package/dist/EffectX.d.ts +120 -0
  19. package/dist/EffectX.d.ts.map +1 -0
  20. package/dist/EffectX.js +140 -0
  21. package/dist/EffectX.js.map +1 -0
  22. package/dist/FormDataX.d.ts +49 -0
  23. package/dist/FormDataX.d.ts.map +1 -0
  24. package/dist/FormDataX.js +42 -0
  25. package/dist/FormDataX.js.map +1 -0
  26. package/dist/InclusiveOr.d.ts +1123 -0
  27. package/dist/InclusiveOr.d.ts.map +1 -0
  28. package/dist/InclusiveOr.js +1074 -0
  29. package/dist/InclusiveOr.js.map +1 -0
  30. package/dist/MapX.d.ts +32 -0
  31. package/dist/MapX.d.ts.map +1 -0
  32. package/dist/MapX.js +49 -0
  33. package/dist/MapX.js.map +1 -0
  34. package/dist/NonNullableX.d.ts +174 -0
  35. package/dist/NonNullableX.d.ts.map +1 -0
  36. package/dist/NonNullableX.js +217 -0
  37. package/dist/NonNullableX.js.map +1 -0
  38. package/dist/NumberX.d.ts +178 -0
  39. package/dist/NumberX.d.ts.map +1 -0
  40. package/dist/NumberX.js +214 -0
  41. package/dist/NumberX.js.map +1 -0
  42. package/dist/OptionX.d.ts +187 -0
  43. package/dist/OptionX.d.ts.map +1 -0
  44. package/dist/OptionX.js +201 -0
  45. package/dist/OptionX.js.map +1 -0
  46. package/dist/OrderX.d.ts +32 -0
  47. package/dist/OrderX.d.ts.map +1 -0
  48. package/dist/OrderX.js +32 -0
  49. package/dist/OrderX.js.map +1 -0
  50. package/dist/PredicateX.d.ts +108 -0
  51. package/dist/PredicateX.d.ts.map +1 -0
  52. package/dist/PredicateX.js +111 -0
  53. package/dist/PredicateX.js.map +1 -0
  54. package/dist/PromiseX.d.ts +32 -0
  55. package/dist/PromiseX.d.ts.map +1 -0
  56. package/dist/PromiseX.js +32 -0
  57. package/dist/PromiseX.js.map +1 -0
  58. package/dist/RecordX.d.ts +450 -0
  59. package/dist/RecordX.d.ts.map +1 -0
  60. package/dist/RecordX.js +487 -0
  61. package/dist/RecordX.js.map +1 -0
  62. package/dist/ResultX.d.ts +50 -0
  63. package/dist/ResultX.d.ts.map +1 -0
  64. package/dist/ResultX.js +50 -0
  65. package/dist/ResultX.js.map +1 -0
  66. package/dist/SchemaX.d.ts +249 -0
  67. package/dist/SchemaX.d.ts.map +1 -0
  68. package/dist/SchemaX.js +243 -0
  69. package/dist/SchemaX.js.map +1 -0
  70. package/dist/SetX.d.ts +121 -0
  71. package/dist/SetX.d.ts.map +1 -0
  72. package/dist/SetX.js +137 -0
  73. package/dist/SetX.js.map +1 -0
  74. package/dist/StringX.d.ts +131 -0
  75. package/dist/StringX.d.ts.map +1 -0
  76. package/dist/StringX.js +149 -0
  77. package/dist/StringX.js.map +1 -0
  78. package/dist/StructX.d.ts +219 -0
  79. package/dist/StructX.d.ts.map +1 -0
  80. package/dist/StructX.js +173 -0
  81. package/dist/StructX.js.map +1 -0
  82. package/dist/WarnResult.d.ts +1191 -0
  83. package/dist/WarnResult.d.ts.map +1 -0
  84. package/dist/WarnResult.js +991 -0
  85. package/dist/WarnResult.js.map +1 -0
  86. package/dist/index.d.ts +23 -3772
  87. package/dist/index.d.ts.map +1 -0
  88. package/dist/index.js +22 -1011
  89. package/dist/index.js.map +1 -1
  90. package/package.json +18 -5
  91. package/src/{ArrayX/ArrayX.ts → ArrayX.ts} +6 -88
  92. package/src/{DurationX/DurationX.ts → DurationX.ts} +1 -1
  93. package/src/InclusiveOr.ts +1255 -0
  94. package/src/{NonNullableX/NonNullableX.ts → NonNullableX.ts} +5 -0
  95. package/src/{OptionX/OptionX.ts → OptionX.ts} +8 -2
  96. package/src/{PredicateX/PredicateX.ts → PredicateX.ts} +41 -0
  97. package/src/{RecordX/RecordX.ts → RecordX.ts} +184 -2
  98. package/src/StringX.ts +210 -0
  99. package/src/{WarnResult/WarnResult.ts → WarnResult.ts} +297 -227
  100. package/src/index.ts +22 -20
  101. package/src/ArrayX/index.ts +0 -1
  102. package/src/BigIntX/index.ts +0 -1
  103. package/src/BooleanX/index.ts +0 -1
  104. package/src/DurationX/index.ts +0 -1
  105. package/src/EffectX/index.ts +0 -1
  106. package/src/FormDataX/index.ts +0 -1
  107. package/src/MapX/index.ts +0 -1
  108. package/src/NonNullableX/index.ts +0 -2
  109. package/src/NumberX/index.ts +0 -1
  110. package/src/OptionX/index.ts +0 -1
  111. package/src/OrderX/index.ts +0 -1
  112. package/src/PredicateX/index.ts +0 -1
  113. package/src/PromiseX/index.ts +0 -1
  114. package/src/RecordX/index.ts +0 -1
  115. package/src/ResultX/index.ts +0 -1
  116. package/src/SchemaX/index.ts +0 -1
  117. package/src/SetX/index.ts +0 -1
  118. package/src/StringX/StringX.ts +0 -97
  119. package/src/StringX/index.ts +0 -1
  120. package/src/StructX/index.ts +0 -1
  121. package/src/WarnResult/index.ts +0 -1
  122. /package/src/{BigIntX/BigIntX.ts → BigIntX.ts} +0 -0
  123. /package/src/{BooleanX/BooleanX.ts → BooleanX.ts} +0 -0
  124. /package/src/{EffectX/EffectX.ts → EffectX.ts} +0 -0
  125. /package/src/{FormDataX/FormDataX.ts → FormDataX.ts} +0 -0
  126. /package/src/{MapX/MapX.ts → MapX.ts} +0 -0
  127. /package/src/{NumberX/NumberX.ts → NumberX.ts} +0 -0
  128. /package/src/{OrderX/OrderX.ts → OrderX.ts} +0 -0
  129. /package/src/{PromiseX/PromiseX.ts → PromiseX.ts} +0 -0
  130. /package/src/{ResultX/ResultX.ts → ResultX.ts} +0 -0
  131. /package/src/{SchemaX/SchemaX.ts → SchemaX.ts} +0 -0
  132. /package/src/{SetX/SetX.ts → SetX.ts} +0 -0
  133. /package/src/{StructX/StructX.ts → StructX.ts} +0 -0
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Generic, framework-agnostic extensions to Effect's `Struct` module.
3
+ *
4
+ * @since 0.0.0
5
+ */
6
+ import { Option, Predicate, Record, pipe } from "effect";
7
+ import { dual } from "effect/Function";
8
+ /**
9
+ * Builds a singleton record `{ [name]: value }` when `value` is defined, or an
10
+ * empty object `{}` when it is `undefined` — meant to be spread into an object
11
+ * literal.
12
+ *
13
+ * This is the canonical fix for `exactOptionalPropertyTypes: true` (which this
14
+ * repo enables for Effect Schema). Under that flag, spreading
15
+ * `{ key: maybeUndefined }` into an object whose key is `key?: T` is a type
16
+ * error: the property must be *absent*, not present-but-`undefined`. Spreading
17
+ * `...defined("key", maybeUndefined)` instead conditionally omits the property
18
+ * altogether. Note that `null` and other falsy-but-defined values (`0`, `""`,
19
+ * `false`) are kept — only `undefined` is dropped.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * import { StructX } from "@nunofyobiz/effect-extras"
24
+ *
25
+ * // Defined value → singleton record
26
+ * assert.deepStrictEqual(StructX.defined("name", "Ada"), { name: "Ada" })
27
+ *
28
+ * // undefined → property omitted entirely
29
+ * assert.deepStrictEqual(StructX.defined("name", undefined), {})
30
+ *
31
+ * // Falsy-but-defined values are kept
32
+ * assert.deepStrictEqual(StructX.defined("name", 0), { name: 0 })
33
+ *
34
+ * // Typical use: spread to conditionally include an optional field
35
+ * const maybeAge: number | undefined = undefined
36
+ * assert.deepStrictEqual({ id: 1, ...StructX.defined("age", maybeAge) }, {
37
+ * id: 1,
38
+ * })
39
+ * ```
40
+ *
41
+ * @category constructors
42
+ * @since 0.0.0
43
+ */
44
+ export const defined = (name, value) => Predicate.isUndefined(value) ? {} : Record.singleton(name, value);
45
+ /**
46
+ * Removes every property whose value is `undefined` from `record`, narrowing
47
+ * each remaining property type to exclude `undefined`.
48
+ *
49
+ * The bulk counterpart of {@link defined}: instead of building one optional
50
+ * field, it filters a whole object. Very useful for update/patch actions where
51
+ * `undefined` means "leave this field unchanged" while every other value —
52
+ * including `null`, `0`, `""`, `false`, and `Option.none()` — means "set the
53
+ * field to exactly this".
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * import { StructX } from "@nunofyobiz/effect-extras"
58
+ *
59
+ * // Drops `b` (undefined) but keeps every other value, including null/0/false
60
+ * assert.deepStrictEqual(
61
+ * StructX.filterDefined({ a: "x", b: undefined, c: 0, d: null, e: false }),
62
+ * { a: "x", c: 0, d: null, e: false },
63
+ * )
64
+ * ```
65
+ *
66
+ * @category filtering
67
+ * @since 0.0.0
68
+ */
69
+ export const filterDefined = record => Object.entries(record).reduce((accumulator, [key, value]) => ({
70
+ ...accumulator,
71
+ ...defined(key, value)
72
+ }), {});
73
+ /**
74
+ * Builds a singleton record `{ [name]: value }` when `value` is `Some`, or an
75
+ * empty object `{}` when it is `None` — meant to be spread into an object
76
+ * literal.
77
+ *
78
+ * The `Option`-valued sibling of {@link defined}: where `defined` keys off
79
+ * `undefined`, this keys off `Option` presence. Spread `...some("key", opt)` to
80
+ * conditionally include a field only when the `Option` carries a value, which
81
+ * stays correct under `exactOptionalPropertyTypes: true`.
82
+ *
83
+ * @example
84
+ * ```ts
85
+ * import { Option } from "effect"
86
+ * import { StructX } from "@nunofyobiz/effect-extras"
87
+ *
88
+ * // Some → singleton record
89
+ * assert.deepStrictEqual(StructX.some("name", Option.some("Ada")), {
90
+ * name: "Ada",
91
+ * })
92
+ *
93
+ * // None → property omitted entirely
94
+ * assert.deepStrictEqual(StructX.some("name", Option.none()), {})
95
+ * ```
96
+ *
97
+ * @category constructors
98
+ * @since 0.0.0
99
+ */
100
+ export const some = (name, value) => Option.match(value, {
101
+ onSome: someValue => Record.singleton(name, someValue),
102
+ onNone: () => ({})
103
+ });
104
+ /**
105
+ * Like {@link some}, but with swapped argument order for piping. Returns a
106
+ * singleton record `{ [name]: value }` when the Option is `Some`, or an
107
+ * empty object `{}` when `None`.
108
+ *
109
+ * Internal-only — exists to support {@link pickSome} in data-last form.
110
+ * Not exported because the codebase has no direct callers.
111
+ */
112
+ const someSingleton = /*#__PURE__*/dual(2, (value, name) => some(name, value));
113
+ export function pickSome(record, key, renameKeyTo) {
114
+ return pipe(Record.get(record, key), Option.flatten, someSingleton(renameKeyTo ?? key));
115
+ }
116
+ /**
117
+ * Builds a singleton record `{ [name]: value }` when `value` is truthy, or an
118
+ * empty object `{}` otherwise — meant to be spread into an object literal.
119
+ *
120
+ * Stricter than {@link defined}: it drops not just `undefined` but every falsy
121
+ * value (`null`, `false`, `0`, `""`, `NaN`), and narrows the value type
122
+ * accordingly. Use it to spread a field only when it carries a meaningful,
123
+ * non-falsy value.
124
+ *
125
+ * @example
126
+ * ```ts
127
+ * import { StructX } from "@nunofyobiz/effect-extras"
128
+ *
129
+ * // Truthy value → singleton record
130
+ * assert.deepStrictEqual(StructX.truthy("name", "Ada"), { name: "Ada" })
131
+ *
132
+ * // Falsy values → property omitted entirely
133
+ * assert.deepStrictEqual(StructX.truthy("name", ""), {})
134
+ * assert.deepStrictEqual(StructX.truthy("name", 0), {})
135
+ * assert.deepStrictEqual(StructX.truthy("name", false), {})
136
+ * ```
137
+ *
138
+ * @category constructors
139
+ * @since 0.0.0
140
+ */
141
+ export const truthy = (name, value) => Predicate.isTruthy(value) ? Record.singleton(name, value) : {};
142
+ /**
143
+ * Returns `true` when `object` has `key` set to a non-nullish value, narrowing
144
+ * that property to `NonNullable` on the type level.
145
+ *
146
+ * A type guard combining `hasProperty` with a nullish check: after a successful
147
+ * test, TypeScript treats `object[key]` as present and free of `null` /
148
+ * `undefined`. Handy as a predicate passed to `Array.filter` to keep only the
149
+ * elements whose `key` is populated.
150
+ *
151
+ * @example
152
+ * ```ts
153
+ * import { pipe } from "effect"
154
+ * import { StructX } from "@nunofyobiz/effect-extras"
155
+ *
156
+ * // data-first
157
+ * assert.deepStrictEqual(
158
+ * StructX.hasNotNullableProperty({ id: "1" }, "id"),
159
+ * true,
160
+ * )
161
+ *
162
+ * // data-last (pipeable); a null value fails the guard
163
+ * assert.deepStrictEqual(
164
+ * pipe({ id: null }, StructX.hasNotNullableProperty("id")),
165
+ * false,
166
+ * )
167
+ * ```
168
+ *
169
+ * @category refinements
170
+ * @since 0.0.0
171
+ */
172
+ export const hasNotNullableProperty = /*#__PURE__*/dual(2, (object, key) => Predicate.hasProperty(object, key) && Predicate.isNotNullish(object[key]));
173
+ //# sourceMappingURL=StructX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StructX.js","names":["Option","Predicate","Record","pipe","dual","defined","name","value","isUndefined","singleton","filterDefined","record","Object","entries","reduce","accumulator","key","some","match","onSome","someValue","onNone","someSingleton","pickSome","renameKeyTo","get","flatten","truthy","isTruthy","hasNotNullableProperty","object","hasProperty","isNotNullish"],"sources":["../src/StructX.ts"],"sourcesContent":[null],"mappings":"AAAA;;;;;AAKA,SAASA,MAAM,EAAEC,SAAS,EAAEC,MAAM,EAAEC,IAAI,QAAQ,QAAQ;AACxD,SAASC,IAAI,QAAQ,iBAAiB;AAkCtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,OAAO,MAAMC,OAAO,GAAGA,CACrBC,IAAO,EACPC,KAAoB,KAEpBN,SAAS,CAACO,WAAW,CAACD,KAAK,CAAC,GACxB,EAAE,GACFL,MAAM,CAACO,SAAS,CAACH,IAAI,EAAEC,KAA8B,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,OAAO,MAAMG,aAAa,GACxBC,MAAS,IAETC,MAAM,CAACC,OAAO,CAACF,MAAM,CAAC,CAACG,MAAM,CAC3B,CAACC,WAAW,EAAE,CAACC,GAAG,EAAET,KAAK,CAAC,MAAM;EAAE,GAAGQ,WAAW;EAAE,GAAGV,OAAO,CAACW,GAAG,EAAET,KAAK;AAAC,CAAE,CAAC,EAC3E,EAA2D,CAC5D;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,OAAO,MAAMU,IAAI,GAAGA,CAClBX,IAAO,EACPC,KAAuB,KAEvBP,MAAM,CAACkB,KAAK,CAACX,KAAK,EAAE;EAClBY,MAAM,EAAGC,SAAS,IAAKlB,MAAM,CAACO,SAAS,CAACH,IAAI,EAAEc,SAAS,CAAC;EACxDC,MAAM,EAAEA,CAAA,MAAO,EAAE;CAClB,CAAC;AAEJ;;;;;;;;AAQA,MAAMC,aAAa,gBAQflB,IAAI,CACN,CAAC,EACD,CACEG,KAAuB,EACvBD,IAAO,KACmBW,IAAI,CAACX,IAAI,EAAEC,KAAK,CAAC,CAC9C;AA6CD,OAAM,SAAUgB,QAAQA,CACtBZ,MAAoC,EACpCK,GAAO,EACPQ,WAAgB;EAEhB,OAAOrB,IAAI,CACTD,MAAM,CAACuB,GAAG,CAACd,MAAM,EAAEK,GAAG,CAAC,EACvBhB,MAAM,CAAC0B,OAAO,EACdJ,aAAa,CAACE,WAAW,IAAIR,GAAG,CAAC,CAClC;AACH;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,OAAO,MAAMW,MAAM,GAAGA,CACpBrB,IAAO,EACPC,KAAQ,KAERN,SAAS,CAAC2B,QAAQ,CAACrB,KAAK,CAAC,GACrBL,MAAM,CAACO,SAAS,CAACH,IAAI,EAAEC,KAAgD,CAAC,GACxE,EAAE;AAER;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,OAAO,MAAMsB,sBAAsB,gBAAGzB,IAAI,CASxC,CAAC,EACD,CACE0B,MAAS,EACTd,GAAM,KAENf,SAAS,CAAC8B,WAAW,CAACD,MAAM,EAAEd,GAAG,CAAC,IAAIf,SAAS,CAAC+B,YAAY,CAACF,MAAM,CAACd,GAAG,CAAC,CAAC,CAC5E","ignoreList":[]}