@onrails/maybe 0.2.3 → 0.3.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.
@@ -0,0 +1,283 @@
1
+ /**
2
+ * Tagged optional value — a discriminated union over `_tag` where absence
3
+ * (`None`) is an expected outcome, not a failure. Construct with {@link some} /
4
+ * {@link none}, narrow with {@link isSome} / {@link isNone}, and collapse with
5
+ * {@link match}.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * function findUser(id: string): Maybe<User> {
10
+ * return fromNullable(db.users.get(id));
11
+ * }
12
+ * ```
13
+ */
14
+ export type Maybe<T> = MaybeData<T> & MaybeMethods<T>;
15
+ /**
16
+ * Plain-data shape of a {@link Maybe}: what `JSON.parse`, `structuredClone`
17
+ * and `postMessage` hand back. It has no methods; lift it with `Maybe.from`.
18
+ */
19
+ export type MaybeData<T> = {
20
+ readonly _tag: "Some";
21
+ readonly value: T;
22
+ } | {
23
+ readonly _tag: "None";
24
+ };
25
+ /**
26
+ * Methods every live {@link Maybe} carries on its (non-enumerable) prototype.
27
+ * Core semantics, mirroring `ResultMethods`: `tap` does not swallow throws.
28
+ */
29
+ export interface MaybeMethods<T> {
30
+ /** Transform the `Some` value; `None` passes through. */
31
+ map<U>(fn: (value: T) => U): Maybe<U>;
32
+ /** Canonical bind; short-circuits on `None`. */
33
+ flatMap<U>(fn: (value: T) => Maybe<U>): Maybe<U>;
34
+ /** Alias of {@link MaybeMethods.flatMap}. */
35
+ andThen<U>(fn: (value: T) => Maybe<U>): Maybe<U>;
36
+ /** Fold both branches into one value. */
37
+ match<U>(onSome: (value: T) => U, onNone: () => U): U;
38
+ /** The `Some` value, or `defaultValue` on `None`. */
39
+ unwrapOr<U>(defaultValue: U): T | U;
40
+ /** Observe the `Some` value, pass the maybe through. */
41
+ tap(fn: (value: T) => void): Maybe<T>;
42
+ /** Observe `None`, pass the maybe through. */
43
+ tapNone(fn: () => void): Maybe<T>;
44
+ }
45
+ /** The `Some` branch of a {@link Maybe} — a present value tagged `"Some"`. */
46
+ export type Some<T> = Extract<Maybe<T>, {
47
+ _tag: "Some";
48
+ }>;
49
+ /** The `None` branch of a {@link Maybe} — expected absence, tagged `"None"`. */
50
+ export type None = Extract<Maybe<never>, {
51
+ _tag: "None";
52
+ }>;
53
+ /**
54
+ * Lifts a value into the `Some` branch.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * const m = some(1); // Maybe<number>
59
+ * ```
60
+ */
61
+ export declare const some: <T>(value: T) => Maybe<T>;
62
+ /**
63
+ * Fantasy Land `pure` — alias of {@link some}. One lift name shared across
64
+ * the trio (`of` / `Result.of` / `ResultAsync.of`) for generic and FL-style
65
+ * code.
66
+ *
67
+ * @example
68
+ * ```ts
69
+ * const m = of(1); // Maybe<number> — identical to some(1)
70
+ * ```
71
+ */
72
+ export declare const of: typeof some;
73
+ /**
74
+ * The `None` value — represents expected absence. Not a failure.
75
+ *
76
+ * @example
77
+ * ```ts
78
+ * const cached: Maybe<User> = cache.has(id) ? some(cache.get(id)) : none();
79
+ * ```
80
+ */
81
+ export declare const none: <T = never>() => Maybe<T>;
82
+ /**
83
+ * Value-side companion of the {@link Maybe} type. `from` lifts plain data back
84
+ * into a live `Maybe` at every deserialization sink (`JSON.parse`,
85
+ * `structuredClone`, `postMessage`, Redux rehydration). It trusts the shape,
86
+ * but an unknown `_tag` is a defect and throws a `TypeError` rather than
87
+ * silently becoming `None`.
88
+ *
89
+ * @example
90
+ * ```ts
91
+ * const live = Maybe.from<number>(JSON.parse(JSON.stringify(some(1))));
92
+ * live.map((n) => n + 1);
93
+ * ```
94
+ */
95
+ export declare const Maybe: {
96
+ readonly from: <T>(data: MaybeData<T>) => Maybe<T>;
97
+ };
98
+ /**
99
+ * Type-narrowing predicate: returns `true` when the value is `Some`.
100
+ *
101
+ * @example
102
+ * ```ts
103
+ * if (isSome(m)) {
104
+ * console.log(m.value); // narrowed to Some branch
105
+ * }
106
+ * ```
107
+ */
108
+ export declare const isSome: <T>(maybe: Maybe<T>) => maybe is Some<T>;
109
+ /**
110
+ * Type-narrowing predicate: returns `true` when the value is `None`.
111
+ *
112
+ * @example
113
+ * ```ts
114
+ * if (isNone(fromNullable(user))) {
115
+ * return redirect("/login"); // narrowed to None branch
116
+ * }
117
+ * ```
118
+ */
119
+ export declare const isNone: <T>(maybe: Maybe<T>) => maybe is None;
120
+ /**
121
+ * Lift a nullable value into `Maybe<T>` — `null` and `undefined` become
122
+ * `None`; anything else becomes `Some`.
123
+ *
124
+ * @example
125
+ * ```ts
126
+ * fromNullable(cache.get(key)); // Maybe<V>
127
+ * fromNullable(null); // None
128
+ * ```
129
+ */
130
+ export declare const fromNullable: <T>(value: T | null | undefined) => Maybe<T>;
131
+ /**
132
+ * Transform the `Some` value, passing `None` through unchanged. Dual-form.
133
+ *
134
+ * @example
135
+ * ```ts
136
+ * map(some(2), (n) => n * 3); // Some 6 — data-first
137
+ * pipe(fromNullable(input), map((s) => s.trim())); // curried
138
+ * ```
139
+ */
140
+ export declare const map: {
141
+ <T, U>(maybe: Maybe<T>, fn: (value: T) => U): Maybe<U>;
142
+ <T, U>(fn: (value: T) => U): (maybe: Maybe<T>) => Maybe<U>;
143
+ };
144
+ /**
145
+ * Canonical bind for `Maybe`. Chains a `Maybe`-returning step;
146
+ * short-circuits on `None`. Dual-form.
147
+ *
148
+ * @example
149
+ * ```ts
150
+ * flatMap(fromNullable(user), (u) =>
151
+ * u.active ? some(u) : none(),
152
+ * );
153
+ * ```
154
+ */
155
+ export declare const flatMap: {
156
+ <T, U>(maybe: Maybe<T>, fn: (value: T) => Maybe<U>): Maybe<U>;
157
+ <T, U>(fn: (value: T) => Maybe<U>): (maybe: Maybe<T>) => Maybe<U>;
158
+ };
159
+ /**
160
+ * Neverthrow-compat alias of {@link flatMap} — same dual-form shape. Prefer
161
+ * {@link flatMap} as the canonical name; reach for `andThen` only when porting
162
+ * neverthrow code or matching its vocabulary.
163
+ *
164
+ * @example
165
+ * ```ts
166
+ * andThen(fromNullable(user), (u) =>
167
+ * u.active ? some(u) : none(),
168
+ * );
169
+ * ```
170
+ */
171
+ export declare const andThen: {
172
+ <T, U>(maybe: Maybe<T>, fn: (value: T) => Maybe<U>): Maybe<U>;
173
+ <T, U>(fn: (value: T) => Maybe<U>): (maybe: Maybe<T>) => Maybe<U>;
174
+ };
175
+ /**
176
+ * Terminal collapse — fold both branches into a single value. Positional,
177
+ * dual-form. Same shape as `Result.match` for sibling consistency.
178
+ *
179
+ * For files that also import `match` from `ts-pattern`, use a namespace
180
+ * import (`import * as Maybe from "@onrails/maybe"` → `Maybe.match`) to
181
+ * dissolve the collision.
182
+ *
183
+ * @example
184
+ * ```ts
185
+ * const greeting = match(
186
+ * fromNullable(user),
187
+ * (u) => `hello ${u.name}`,
188
+ * () => "hello guest",
189
+ * );
190
+ * ```
191
+ */
192
+ export declare const match: {
193
+ <T, U>(maybe: Maybe<T>, onSome: (value: T) => U, onNone: () => U): U;
194
+ <T, U>(onSome: (value: T) => U, onNone: () => U): (maybe: Maybe<T>) => U;
195
+ };
196
+ export declare const unwrapOr: {
197
+ <T, U>(maybe: Maybe<T>, defaultValue: U): T | U;
198
+ <U>(defaultValue: U): <T>(maybe: Maybe<T>) => T | U;
199
+ };
200
+ /**
201
+ * Unwraps the `Some` value or throws if the value is `None`.
202
+ *
203
+ * @throws when the value is None — assertion-tier; use {@link match} / {@link unwrapOr} in business logic.
204
+ * Allowed in `*.spec.ts` / `*.test.ts`; flagged elsewhere by the plugins.
205
+ *
206
+ * @example
207
+ * ```ts
208
+ * expect(unwrap(parseUser(raw))).toEqual(expected);
209
+ * ```
210
+ */
211
+ export declare const unwrap: <T>(maybe: Maybe<T>) => T;
212
+ /**
213
+ * Drop every `None` and collect the remaining `Some` values into an array.
214
+ *
215
+ * @example
216
+ * ```ts
217
+ * compact([some(1), none(), some(2)]); // [1, 2]
218
+ * ```
219
+ */
220
+ export declare const compact: <T>(maybes: readonly Maybe<T>[]) => T[];
221
+ /**
222
+ * `compact(items.map(fn))` — map each item to `Maybe`, drop `None`,
223
+ * collect the rest.
224
+ *
225
+ * @example
226
+ * ```ts
227
+ * compactMap(rawRows, (row) =>
228
+ * row.deletedAt ? none() : some(row.id),
229
+ * );
230
+ * // string[]
231
+ * ```
232
+ */
233
+ export declare const compactMap: <T, U>(items: readonly T[], fn: (item: T) => Maybe<U>) => U[];
234
+ /**
235
+ * `flatMap(fromNullable(value), fn)` — lift a nullable then bind through
236
+ * a `Maybe`-returning step. Convenient for chaining lookups.
237
+ *
238
+ * @example
239
+ * ```ts
240
+ * optional(rawId, (id) => fromNullable(cache.get(id)));
241
+ * ```
242
+ */
243
+ export declare const optional: <T, U>(value: T | null | undefined, fn: (value: T) => Maybe<U>) => Maybe<U>;
244
+ /**
245
+ * Run a side effect on the `Some` value, pass the `Maybe` through unchanged.
246
+ * `None` is a no-op. Mirrors `tap` from `@onrails/result`. Dual-form.
247
+ *
248
+ * @example
249
+ * ```ts
250
+ * tap(some(2), (n) => console.log(n)); // logs 2, returns Some 2
251
+ * pipe(fromNullable(row), tap((r) => sink.push(r))); // curried — collect on Some
252
+ * ```
253
+ */
254
+ export declare const tap: {
255
+ <T>(maybe: Maybe<T>, fn: (value: T) => void): Maybe<T>;
256
+ <T>(fn: (value: T) => void): (maybe: Maybe<T>) => Maybe<T>;
257
+ };
258
+ /**
259
+ * Run a side effect when the `Maybe` is `None`, pass it through unchanged.
260
+ * `Some` is a no-op. The `None`-side mirror of {@link tap}. Dual-form.
261
+ *
262
+ * @example
263
+ * ```ts
264
+ * tapNone(none(), () => metrics.miss()); // runs effect, returns None
265
+ * pipe(fromNullable(hit), tapNone(() => metrics.miss())); // curried
266
+ * ```
267
+ */
268
+ export declare const tapNone: {
269
+ <T>(maybe: Maybe<T>, fn: () => void): Maybe<T>;
270
+ <T>(fn: () => void): (maybe: Maybe<T>) => Maybe<T>;
271
+ };
272
+ /**
273
+ * Debug printer — renders a maybe as `Some(…)` / `None` for logs. Payloads
274
+ * print as JSON (values are plain data by design); non-JSON payloads fall
275
+ * back to `String(...)`. Mirror of the result package's `show`.
276
+ *
277
+ * @example
278
+ * ```ts
279
+ * show(some(1)); // 'Some(1)'
280
+ * show(none()); // 'None'
281
+ * ```
282
+ */
283
+ export declare const show: <T>(maybe: Maybe<T>) => string;
@@ -0,0 +1,283 @@
1
+ /**
2
+ * Tagged optional value — a discriminated union over `_tag` where absence
3
+ * (`None`) is an expected outcome, not a failure. Construct with {@link some} /
4
+ * {@link none}, narrow with {@link isSome} / {@link isNone}, and collapse with
5
+ * {@link match}.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * function findUser(id: string): Maybe<User> {
10
+ * return fromNullable(db.users.get(id));
11
+ * }
12
+ * ```
13
+ */
14
+ export type Maybe<T> = MaybeData<T> & MaybeMethods<T>;
15
+ /**
16
+ * Plain-data shape of a {@link Maybe}: what `JSON.parse`, `structuredClone`
17
+ * and `postMessage` hand back. It has no methods; lift it with `Maybe.from`.
18
+ */
19
+ export type MaybeData<T> = {
20
+ readonly _tag: "Some";
21
+ readonly value: T;
22
+ } | {
23
+ readonly _tag: "None";
24
+ };
25
+ /**
26
+ * Methods every live {@link Maybe} carries on its (non-enumerable) prototype.
27
+ * Core semantics, mirroring `ResultMethods`: `tap` does not swallow throws.
28
+ */
29
+ export interface MaybeMethods<T> {
30
+ /** Transform the `Some` value; `None` passes through. */
31
+ map<U>(fn: (value: T) => U): Maybe<U>;
32
+ /** Canonical bind; short-circuits on `None`. */
33
+ flatMap<U>(fn: (value: T) => Maybe<U>): Maybe<U>;
34
+ /** Alias of {@link MaybeMethods.flatMap}. */
35
+ andThen<U>(fn: (value: T) => Maybe<U>): Maybe<U>;
36
+ /** Fold both branches into one value. */
37
+ match<U>(onSome: (value: T) => U, onNone: () => U): U;
38
+ /** The `Some` value, or `defaultValue` on `None`. */
39
+ unwrapOr<U>(defaultValue: U): T | U;
40
+ /** Observe the `Some` value, pass the maybe through. */
41
+ tap(fn: (value: T) => void): Maybe<T>;
42
+ /** Observe `None`, pass the maybe through. */
43
+ tapNone(fn: () => void): Maybe<T>;
44
+ }
45
+ /** The `Some` branch of a {@link Maybe} — a present value tagged `"Some"`. */
46
+ export type Some<T> = Extract<Maybe<T>, {
47
+ _tag: "Some";
48
+ }>;
49
+ /** The `None` branch of a {@link Maybe} — expected absence, tagged `"None"`. */
50
+ export type None = Extract<Maybe<never>, {
51
+ _tag: "None";
52
+ }>;
53
+ /**
54
+ * Lifts a value into the `Some` branch.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * const m = some(1); // Maybe<number>
59
+ * ```
60
+ */
61
+ export declare const some: <T>(value: T) => Maybe<T>;
62
+ /**
63
+ * Fantasy Land `pure` — alias of {@link some}. One lift name shared across
64
+ * the trio (`of` / `Result.of` / `ResultAsync.of`) for generic and FL-style
65
+ * code.
66
+ *
67
+ * @example
68
+ * ```ts
69
+ * const m = of(1); // Maybe<number> — identical to some(1)
70
+ * ```
71
+ */
72
+ export declare const of: typeof some;
73
+ /**
74
+ * The `None` value — represents expected absence. Not a failure.
75
+ *
76
+ * @example
77
+ * ```ts
78
+ * const cached: Maybe<User> = cache.has(id) ? some(cache.get(id)) : none();
79
+ * ```
80
+ */
81
+ export declare const none: <T = never>() => Maybe<T>;
82
+ /**
83
+ * Value-side companion of the {@link Maybe} type. `from` lifts plain data back
84
+ * into a live `Maybe` at every deserialization sink (`JSON.parse`,
85
+ * `structuredClone`, `postMessage`, Redux rehydration). It trusts the shape,
86
+ * but an unknown `_tag` is a defect and throws a `TypeError` rather than
87
+ * silently becoming `None`.
88
+ *
89
+ * @example
90
+ * ```ts
91
+ * const live = Maybe.from<number>(JSON.parse(JSON.stringify(some(1))));
92
+ * live.map((n) => n + 1);
93
+ * ```
94
+ */
95
+ export declare const Maybe: {
96
+ readonly from: <T>(data: MaybeData<T>) => Maybe<T>;
97
+ };
98
+ /**
99
+ * Type-narrowing predicate: returns `true` when the value is `Some`.
100
+ *
101
+ * @example
102
+ * ```ts
103
+ * if (isSome(m)) {
104
+ * console.log(m.value); // narrowed to Some branch
105
+ * }
106
+ * ```
107
+ */
108
+ export declare const isSome: <T>(maybe: Maybe<T>) => maybe is Some<T>;
109
+ /**
110
+ * Type-narrowing predicate: returns `true` when the value is `None`.
111
+ *
112
+ * @example
113
+ * ```ts
114
+ * if (isNone(fromNullable(user))) {
115
+ * return redirect("/login"); // narrowed to None branch
116
+ * }
117
+ * ```
118
+ */
119
+ export declare const isNone: <T>(maybe: Maybe<T>) => maybe is None;
120
+ /**
121
+ * Lift a nullable value into `Maybe<T>` — `null` and `undefined` become
122
+ * `None`; anything else becomes `Some`.
123
+ *
124
+ * @example
125
+ * ```ts
126
+ * fromNullable(cache.get(key)); // Maybe<V>
127
+ * fromNullable(null); // None
128
+ * ```
129
+ */
130
+ export declare const fromNullable: <T>(value: T | null | undefined) => Maybe<T>;
131
+ /**
132
+ * Transform the `Some` value, passing `None` through unchanged. Dual-form.
133
+ *
134
+ * @example
135
+ * ```ts
136
+ * map(some(2), (n) => n * 3); // Some 6 — data-first
137
+ * pipe(fromNullable(input), map((s) => s.trim())); // curried
138
+ * ```
139
+ */
140
+ export declare const map: {
141
+ <T, U>(maybe: Maybe<T>, fn: (value: T) => U): Maybe<U>;
142
+ <T, U>(fn: (value: T) => U): (maybe: Maybe<T>) => Maybe<U>;
143
+ };
144
+ /**
145
+ * Canonical bind for `Maybe`. Chains a `Maybe`-returning step;
146
+ * short-circuits on `None`. Dual-form.
147
+ *
148
+ * @example
149
+ * ```ts
150
+ * flatMap(fromNullable(user), (u) =>
151
+ * u.active ? some(u) : none(),
152
+ * );
153
+ * ```
154
+ */
155
+ export declare const flatMap: {
156
+ <T, U>(maybe: Maybe<T>, fn: (value: T) => Maybe<U>): Maybe<U>;
157
+ <T, U>(fn: (value: T) => Maybe<U>): (maybe: Maybe<T>) => Maybe<U>;
158
+ };
159
+ /**
160
+ * Neverthrow-compat alias of {@link flatMap} — same dual-form shape. Prefer
161
+ * {@link flatMap} as the canonical name; reach for `andThen` only when porting
162
+ * neverthrow code or matching its vocabulary.
163
+ *
164
+ * @example
165
+ * ```ts
166
+ * andThen(fromNullable(user), (u) =>
167
+ * u.active ? some(u) : none(),
168
+ * );
169
+ * ```
170
+ */
171
+ export declare const andThen: {
172
+ <T, U>(maybe: Maybe<T>, fn: (value: T) => Maybe<U>): Maybe<U>;
173
+ <T, U>(fn: (value: T) => Maybe<U>): (maybe: Maybe<T>) => Maybe<U>;
174
+ };
175
+ /**
176
+ * Terminal collapse — fold both branches into a single value. Positional,
177
+ * dual-form. Same shape as `Result.match` for sibling consistency.
178
+ *
179
+ * For files that also import `match` from `ts-pattern`, use a namespace
180
+ * import (`import * as Maybe from "@onrails/maybe"` → `Maybe.match`) to
181
+ * dissolve the collision.
182
+ *
183
+ * @example
184
+ * ```ts
185
+ * const greeting = match(
186
+ * fromNullable(user),
187
+ * (u) => `hello ${u.name}`,
188
+ * () => "hello guest",
189
+ * );
190
+ * ```
191
+ */
192
+ export declare const match: {
193
+ <T, U>(maybe: Maybe<T>, onSome: (value: T) => U, onNone: () => U): U;
194
+ <T, U>(onSome: (value: T) => U, onNone: () => U): (maybe: Maybe<T>) => U;
195
+ };
196
+ export declare const unwrapOr: {
197
+ <T, U>(maybe: Maybe<T>, defaultValue: U): T | U;
198
+ <U>(defaultValue: U): <T>(maybe: Maybe<T>) => T | U;
199
+ };
200
+ /**
201
+ * Unwraps the `Some` value or throws if the value is `None`.
202
+ *
203
+ * @throws when the value is None — assertion-tier; use {@link match} / {@link unwrapOr} in business logic.
204
+ * Allowed in `*.spec.ts` / `*.test.ts`; flagged elsewhere by the plugins.
205
+ *
206
+ * @example
207
+ * ```ts
208
+ * expect(unwrap(parseUser(raw))).toEqual(expected);
209
+ * ```
210
+ */
211
+ export declare const unwrap: <T>(maybe: Maybe<T>) => T;
212
+ /**
213
+ * Drop every `None` and collect the remaining `Some` values into an array.
214
+ *
215
+ * @example
216
+ * ```ts
217
+ * compact([some(1), none(), some(2)]); // [1, 2]
218
+ * ```
219
+ */
220
+ export declare const compact: <T>(maybes: readonly Maybe<T>[]) => T[];
221
+ /**
222
+ * `compact(items.map(fn))` — map each item to `Maybe`, drop `None`,
223
+ * collect the rest.
224
+ *
225
+ * @example
226
+ * ```ts
227
+ * compactMap(rawRows, (row) =>
228
+ * row.deletedAt ? none() : some(row.id),
229
+ * );
230
+ * // string[]
231
+ * ```
232
+ */
233
+ export declare const compactMap: <T, U>(items: readonly T[], fn: (item: T) => Maybe<U>) => U[];
234
+ /**
235
+ * `flatMap(fromNullable(value), fn)` — lift a nullable then bind through
236
+ * a `Maybe`-returning step. Convenient for chaining lookups.
237
+ *
238
+ * @example
239
+ * ```ts
240
+ * optional(rawId, (id) => fromNullable(cache.get(id)));
241
+ * ```
242
+ */
243
+ export declare const optional: <T, U>(value: T | null | undefined, fn: (value: T) => Maybe<U>) => Maybe<U>;
244
+ /**
245
+ * Run a side effect on the `Some` value, pass the `Maybe` through unchanged.
246
+ * `None` is a no-op. Mirrors `tap` from `@onrails/result`. Dual-form.
247
+ *
248
+ * @example
249
+ * ```ts
250
+ * tap(some(2), (n) => console.log(n)); // logs 2, returns Some 2
251
+ * pipe(fromNullable(row), tap((r) => sink.push(r))); // curried — collect on Some
252
+ * ```
253
+ */
254
+ export declare const tap: {
255
+ <T>(maybe: Maybe<T>, fn: (value: T) => void): Maybe<T>;
256
+ <T>(fn: (value: T) => void): (maybe: Maybe<T>) => Maybe<T>;
257
+ };
258
+ /**
259
+ * Run a side effect when the `Maybe` is `None`, pass it through unchanged.
260
+ * `Some` is a no-op. The `None`-side mirror of {@link tap}. Dual-form.
261
+ *
262
+ * @example
263
+ * ```ts
264
+ * tapNone(none(), () => metrics.miss()); // runs effect, returns None
265
+ * pipe(fromNullable(hit), tapNone(() => metrics.miss())); // curried
266
+ * ```
267
+ */
268
+ export declare const tapNone: {
269
+ <T>(maybe: Maybe<T>, fn: () => void): Maybe<T>;
270
+ <T>(fn: () => void): (maybe: Maybe<T>) => Maybe<T>;
271
+ };
272
+ /**
273
+ * Debug printer — renders a maybe as `Some(…)` / `None` for logs. Payloads
274
+ * print as JSON (values are plain data by design); non-JSON payloads fall
275
+ * back to `String(...)`. Mirror of the result package's `show`.
276
+ *
277
+ * @example
278
+ * ```ts
279
+ * show(some(1)); // 'Some(1)'
280
+ * show(none()); // 'None'
281
+ * ```
282
+ */
283
+ export declare const show: <T>(maybe: Maybe<T>) => string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onrails/maybe",
3
- "version": "0.2.3",
3
+ "version": "0.3.0",
4
4
  "description": "Tagged Maybe for expected absence — pure tagged unions, Result interop, tree-shakeable",
5
5
  "license": "MIT",
6
6
  "author": "Alan R. Soares",
@@ -43,23 +43,38 @@
43
43
  ],
44
44
  "exports": {
45
45
  ".": {
46
- "types": "./dist/index.d.ts",
47
- "import": "./dist/index.js",
48
- "require": "./dist/index.cjs"
46
+ "import": {
47
+ "types": "./dist/index.d.ts",
48
+ "default": "./dist/index.js"
49
+ },
50
+ "require": {
51
+ "types": "./dist/index.d.cts",
52
+ "default": "./dist/index.cjs"
53
+ }
49
54
  },
50
55
  "./fluent": {
51
- "types": "./dist/fluent.d.ts",
52
- "import": "./dist/fluent.js",
53
- "require": "./dist/fluent.cjs"
56
+ "import": {
57
+ "types": "./dist/fluent.d.ts",
58
+ "default": "./dist/fluent.js"
59
+ },
60
+ "require": {
61
+ "types": "./dist/fluent.d.cts",
62
+ "default": "./dist/fluent.cjs"
63
+ }
54
64
  },
55
65
  "./interop": {
56
- "types": "./dist/interop.d.ts",
57
- "import": "./dist/interop.js",
58
- "require": "./dist/interop.cjs"
66
+ "import": {
67
+ "types": "./dist/interop.d.ts",
68
+ "default": "./dist/interop.js"
69
+ },
70
+ "require": {
71
+ "types": "./dist/interop.d.cts",
72
+ "default": "./dist/interop.cjs"
73
+ }
59
74
  }
60
75
  },
61
76
  "peerDependencies": {
62
- "@onrails/result": "0.2.0"
77
+ "@onrails/result": "^0.4.2"
63
78
  },
64
79
  "peerDependenciesMeta": {
65
80
  "@onrails/result": {
@@ -70,13 +85,13 @@
70
85
  "typecheck": "tsc --noEmit",
71
86
  "test": "bun test",
72
87
  "check": "bun typecheck && bun test",
73
- "build": "tsup",
88
+ "build": "tsup && tsc -p tsconfig.build.json && bun run ../../scripts/dts-to-cts.ts",
74
89
  "clean": "rm -rf dist",
75
90
  "prepublishOnly": "bun run build"
76
91
  },
77
92
  "devDependencies": {
78
- "@onrails/result": "0.2.0",
79
- "fast-check": "^3.23.2",
93
+ "@onrails/result": "0.4.2",
94
+ "fast-check": "^4.9.0",
80
95
  "ts-expect": "^1.3.0",
81
96
  "tsup": "^8.5.1"
82
97
  }