@othree.io/optional 2.3.2 → 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 CHANGED
@@ -1,2 +1,230 @@
1
- # optional
1
+ # @othree.io/optional
2
2
 
3
+ A TypeScript implementation of the Optional/Maybe monad for handling nullable values and errors without explicit null checks.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @othree.io/optional
9
+ ```
10
+
11
+ ## Quick start
12
+
13
+ ```typescript
14
+ import { Optional, Empty, Try, TryAsync } from '@othree.io/optional'
15
+
16
+ const name = Optional('Alice')
17
+ name.get() // 'Alice'
18
+ name.isPresent // true
19
+
20
+ const nothing = Empty<string>()
21
+ nothing.isEmpty // true
22
+ nothing.orElse('default') // 'default'
23
+ ```
24
+
25
+ ## Creating Optionals
26
+
27
+ ### Wrapping a value
28
+
29
+ ```typescript
30
+ const maybeUser = Optional(user) // present if user is not null/undefined
31
+ const empty = Optional(undefined) // empty
32
+ const empty = Optional(null) // empty
33
+ ```
34
+
35
+ ### Empty with an error
36
+
37
+ ```typescript
38
+ const failed = Optional(undefined, new Error('Not found'))
39
+ failed.isEmpty // true
40
+ failed.getError() // Error('Not found')
41
+ ```
42
+
43
+ ### Empty shorthand
44
+
45
+ ```typescript
46
+ const empty = Empty<string>() // empty, no error
47
+ const failed = Empty<string>(new Error('Not found')) // empty, with error
48
+ ```
49
+
50
+ ### Wrapping code that might throw
51
+
52
+ ```typescript
53
+ const result = Try(() => JSON.parse(raw))
54
+ // present with parsed value, or empty with the caught error
55
+
56
+ const result = await TryAsync(() => fetch('/api/user').then(r => r.json()))
57
+ // same, but for async operations
58
+ ```
59
+
60
+ ## Extracting values
61
+
62
+ ### get
63
+
64
+ Returns the value or throws. If the Optional carries an error, that error is thrown. Otherwise an `EmptyOptionalError` is thrown.
65
+
66
+ ```typescript
67
+ Optional('hello').get() // 'hello'
68
+ Empty().get() // throws EmptyOptionalError
69
+ Empty(new Error('!')).get() // throws Error('!')
70
+ ```
71
+
72
+ ### orElse
73
+
74
+ Returns the value or the provided fallback. If the Optional is in an error state, the error is thrown instead of returning the fallback.
75
+
76
+ ```typescript
77
+ Optional('hello').orElse('world') // 'hello'
78
+ Empty().orElse('world') // 'world'
79
+ ```
80
+
81
+ ### orThrow
82
+
83
+ Returns the value or throws the provided error. If the Optional already carries an error, that original error is thrown.
84
+
85
+ ```typescript
86
+ Optional('hello').orThrow(new Error('!')) // 'hello'
87
+ Empty().orThrow(new Error('!')) // throws Error('!')
88
+ ```
89
+
90
+ ## Transforming values
91
+
92
+ ### map / mapAsync
93
+
94
+ Transforms the value if present. If the callback returns an Optional, it is automatically flattened.
95
+
96
+ ```typescript
97
+ Optional({ name: 'Alice' })
98
+ .map(user => user.name)
99
+ .get() // 'Alice'
100
+
101
+ Optional({ name: 'Alice' })
102
+ .map(user => Optional(user.name))
103
+ .get() // 'Alice' (flattened)
104
+
105
+ // Empty Optionals pass through untouched
106
+ Empty<string>()
107
+ .map(s => s.toUpperCase())
108
+ .isEmpty // true
109
+
110
+ // Async version
111
+ const upper = await Optional('hello')
112
+ .mapAsync(async s => s.toUpperCase())
113
+ // upper.get() === 'HELLO'
114
+ ```
115
+
116
+ ### orMap / orMapAsync
117
+
118
+ Transforms the value only when the Optional is empty **and not in an error state**. Useful for providing computed fallbacks.
119
+
120
+ ```typescript
121
+ Empty<number>()
122
+ .orMap(() => 42)
123
+ .get() // 42
124
+
125
+ // Error state is preserved, orMap is skipped
126
+ Try(() => { throw new Error('!') })
127
+ .orMap(() => 42)
128
+ .isEmpty // true, error is preserved
129
+ ```
130
+
131
+ ### catch / catchAsync
132
+
133
+ Handles the error when the Optional is empty **and in an error state**. Allows recovery from errors.
134
+
135
+ ```typescript
136
+ Try(() => { throw new Error('KAPOW!') })
137
+ .catch(e => 'recovered')
138
+ .get() // 'recovered'
139
+
140
+ // Async version
141
+ const result = await Try(() => { throw new Error('!') })
142
+ .catchAsync(async e => 'recovered')
143
+ // result.get() === 'recovered'
144
+ ```
145
+
146
+ ## Checking state
147
+
148
+ ```typescript
149
+ const opt = Optional('hello')
150
+ opt.isPresent // true
151
+ opt.isEmpty // false
152
+
153
+ const empty = Empty()
154
+ empty.isPresent // false
155
+ empty.isEmpty // true
156
+ ```
157
+
158
+ ## Error inspection
159
+
160
+ ```typescript
161
+ const failed = Optional(undefined, new Error('Not found'))
162
+ failed.getError() // Error('Not found')
163
+
164
+ Optional('hello').getError() // undefined
165
+ ```
166
+
167
+ ## Type guard
168
+
169
+ ```typescript
170
+ import { isOptional } from '@othree.io/optional'
171
+
172
+ isOptional(Optional('hello')) // true
173
+ isOptional('hello') // false
174
+ ```
175
+
176
+ ## Automatic flattening
177
+
178
+ Nested Optionals are flattened both at runtime and at the type level:
179
+
180
+ ```typescript
181
+ const nested = Optional(Optional(Optional('hello')))
182
+ nested.get() // 'hello'
183
+
184
+ // Type-level: Optional<Optional<string>> resolves to Optional<string>
185
+ ```
186
+
187
+ ## Chaining
188
+
189
+ Methods can be chained for expressive pipelines:
190
+
191
+ ```typescript
192
+ const displayName = Try(() => fetchUser())
193
+ .map(user => user.profile)
194
+ .map(profile => profile.displayName)
195
+ .catch(e => 'Anonymous')
196
+ .orElse('Guest')
197
+ ```
198
+
199
+ ## Three-state model
200
+
201
+ An Optional can be in one of three states:
202
+
203
+ | State | `isPresent` | `isEmpty` | `getError()` | Behavior |
204
+ |---|---|---|---|---|
205
+ | **Present** | `true` | `false` | `undefined` | Value is available |
206
+ | **Empty** | `false` | `true` | `undefined` | No value, no error |
207
+ | **Error** | `false` | `true` | `Error` | No value, has error |
208
+
209
+ This distinction matters for `orElse`, `orMap`, and `catch`:
210
+
211
+ - `orElse` / `orMap` activate on **empty** state, but throw on **error** state
212
+ - `catch` activates only on **error** state
213
+ - `map` activates only on **present** state
214
+
215
+ ## API reference
216
+
217
+ | Method | Signature | Description |
218
+ |---|---|---|
219
+ | `get()` | `() => T` | Extract value or throw |
220
+ | `orElse(value)` | `(value: T) => T` | Value or fallback (throws on error) |
221
+ | `orThrow(error)` | `(error: Error) => T` | Value or throw custom error |
222
+ | `map(fn)` | `<A>(fn: (v: T) => A \| Optional<A>) => Optional<A>` | Transform if present |
223
+ | `mapAsync(fn)` | `<A>(fn: (v: T) => Promise<A \| Optional<A>>) => Promise<Optional<A>>` | Async transform if present |
224
+ | `orMap(fn)` | `<A>(fn: () => A \| Optional<A>) => Optional<A \| T>` | Transform if empty (no error) |
225
+ | `orMapAsync(fn)` | `<A>(fn: () => Promise<A \| Optional<A>>) => Promise<Optional<A \| T>>` | Async transform if empty |
226
+ | `catch(fn)` | `<A>(fn: (e: Error) => A \| Optional<A>) => Optional<A \| T>` | Recover from error |
227
+ | `catchAsync(fn)` | `<A>(fn: (e: Error) => Promise<A \| Optional<A>>) => Promise<Optional<A \| T>>` | Async recover from error |
228
+ | `getError()` | `() => any` | Get the error, if any |
229
+ | `isEmpty` | `boolean` | `true` if no value |
230
+ | `isPresent` | `boolean` | `true` if value exists |
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA0B","sourcesContent":["export * from './optional'\n"]}
@@ -15,11 +15,13 @@ export interface Maybe<T, E extends Error> {
15
15
  readonly isEmpty: boolean;
16
16
  readonly isPresent: boolean;
17
17
  }
18
- export declare type Optional<T> = Maybe<T, Error>;
18
+ type UnwrapOptional<T> = T extends Maybe<infer U, Error> ? U : T;
19
+ export type Optional<T> = Maybe<UnwrapOptional<T>, Error>;
19
20
  export declare function Empty<T>(error?: Error): Optional<T>;
20
21
  export declare class EmptyOptionalError extends Error {
21
22
  static ERROR: string;
22
23
  constructor();
23
24
  }
24
25
  export declare function Optional<T>(value: Optional<T> | T | undefined | null, error?: Error): Optional<T>;
26
+ export {};
25
27
  //# sourceMappingURL=optional.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional.d.ts","sourceRoot":"","sources":["../../src/optional.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,11 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.Optional = exports.EmptyOptionalError = exports.Empty = exports.TryAsync = exports.Try = exports.isOptional = void 0;
3
+ exports.EmptyOptionalError = void 0;
4
+ exports.isOptional = isOptional;
5
+ exports.Try = Try;
6
+ exports.TryAsync = TryAsync;
7
+ exports.Empty = Empty;
8
+ exports.Optional = Optional;
13
9
  function isOptional(optional) {
14
10
  return Boolean(optional &&
15
11
  typeof optional.get === 'function' &&
@@ -25,7 +21,6 @@ function isOptional(optional) {
25
21
  typeof optional.isEmpty === 'boolean' &&
26
22
  typeof optional.isPresent === 'boolean');
27
23
  }
28
- exports.isOptional = isOptional;
29
24
  function Try(thunk) {
30
25
  try {
31
26
  const value = thunk();
@@ -38,34 +33,29 @@ function Try(thunk) {
38
33
  return Optional(undefined, error);
39
34
  }
40
35
  }
41
- exports.Try = Try;
42
- function TryAsync(thunk) {
43
- return __awaiter(this, void 0, void 0, function* () {
44
- try {
45
- const value = yield thunk();
46
- if (isOptional(value)) {
47
- return value;
48
- }
49
- return Optional(value);
50
- }
51
- catch (error) {
52
- return Optional(undefined, error);
36
+ async function TryAsync(thunk) {
37
+ try {
38
+ const value = await thunk();
39
+ if (isOptional(value)) {
40
+ return value;
53
41
  }
54
- });
42
+ return Optional(value);
43
+ }
44
+ catch (error) {
45
+ return Optional(undefined, error);
46
+ }
55
47
  }
56
- exports.TryAsync = TryAsync;
57
48
  function Empty(error) {
58
49
  return Optional(undefined, error);
59
50
  }
60
- exports.Empty = Empty;
61
51
  class EmptyOptionalError extends Error {
52
+ static ERROR = 'EmptyOptionalError';
62
53
  constructor() {
63
54
  super('Optional is empty');
64
55
  this.name = EmptyOptionalError.ERROR;
65
56
  }
66
57
  }
67
58
  exports.EmptyOptionalError = EmptyOptionalError;
68
- EmptyOptionalError.ERROR = 'EmptyOptionalError';
69
59
  function Optional(value, error) {
70
60
  const getValue = (value) => {
71
61
  if (isOptional(value)) {
@@ -97,7 +87,10 @@ function Optional(value, error) {
97
87
  },
98
88
  orThrow: (error) => {
99
89
  if (isEmpty) {
100
- throw error;
90
+ if (!theError) {
91
+ throw error;
92
+ }
93
+ throw theError;
101
94
  }
102
95
  return theValue;
103
96
  },
@@ -144,5 +137,4 @@ function Optional(value, error) {
144
137
  isPresent: isPresent
145
138
  });
146
139
  }
147
- exports.Optional = Optional;
148
140
  //# sourceMappingURL=optional.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional.js","sourceRoot":"","sources":["../../src/optional.ts"],"names":[],"mappings":"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","sourcesContent":["\nexport function isOptional(optional: any): optional is Optional<any> {\n return Boolean(optional &&\n typeof optional.get === 'function' &&\n typeof optional.orElse === 'function' &&\n typeof optional.orThrow === 'function' &&\n typeof optional.map === 'function' &&\n typeof optional.mapAsync === 'function' &&\n typeof optional.orMap === 'function' &&\n typeof optional.orMapAsync === 'function' &&\n typeof optional.catch === 'function' &&\n typeof optional.catchAsync === 'function' &&\n typeof optional.getError === 'function' &&\n typeof optional.isEmpty === 'boolean' &&\n typeof optional.isPresent === 'boolean')\n}\n\nexport function Try<T>(thunk: () => Optional<T> | T): Optional<T> {\n try {\n const value = thunk()\n if (isOptional(value)) {\n return value as Optional<T>\n }\n return Optional(value as T)\n } catch (error) {\n return Optional<T>(undefined!, error as Error)\n }\n}\n\nexport async function TryAsync<T>(thunk: () => Promise<Optional<T> | T>): Promise<Optional<T>> {\n try {\n const value = await thunk()\n if (isOptional(value)) {\n return value as Optional<T>\n }\n return Optional(value as T)\n } catch (error) {\n return Optional<T>(undefined!, error as Error)\n }\n}\n\nexport interface Maybe<T, E extends Error> {\n readonly get: () => T\n readonly orElse: (value: T) => T\n readonly orThrow: (error: E) => T\n readonly map: <A>(callback: (value: T) => Optional<A> | A) => Optional<A>\n readonly mapAsync: <A>(callback: (value: T) => Promise<Optional<A> | A>) => Promise<Optional<A>>\n readonly orMap: <A>(callback: () => Optional<A> | A) => Optional<A | T>\n readonly orMapAsync: <A>(callback: () => Promise<Optional<A> | A>) => Promise<Optional<A | T>>\n readonly getError: () => any\n readonly catch: <A>(callback: (error: E) => Optional<A> | A) => Optional<A | T>\n readonly catchAsync: <A>(callback: (error: E) => Promise<Optional<A> | A>) => Promise<Optional<A | T>>\n readonly isEmpty: boolean\n readonly isPresent: boolean\n}\n\ntype UnwrapOptional<T> = T extends Maybe<infer U, Error> ? U : T\nexport type Optional<T> = Maybe<UnwrapOptional<T>, Error>\n\nexport function Empty<T>(error?: Error): Optional<T> {\n return Optional<T>(undefined!, error)\n}\n\nexport class EmptyOptionalError extends Error {\n static ERROR = 'EmptyOptionalError'\n\n constructor() {\n super('Optional is empty')\n\n this.name = EmptyOptionalError.ERROR\n }\n}\n\nexport function Optional<T>(value: Optional<T> | T | undefined | null, error?: Error): Optional<T>\nexport function Optional(value: any, error?: any): any {\n const getValue = (value: any) => {\n if (isOptional(value)) {\n return value.isPresent ? value.get() : undefined\n }\n\n return value\n }\n const theValue = getValue(value)\n const theError = isOptional(value) && !error ? value.getError() : error\n const isEmpty = typeof theValue === 'undefined' || theValue === null\n const isPresent = !isEmpty\n\n return Object.freeze({\n get: () => {\n if (isEmpty) {\n if (!theError) {\n throw new EmptyOptionalError()\n } else {\n throw theError\n }\n }\n\n return theValue\n },\n orElse: function (elseValue: any) {\n if (isEmpty && !theError) {\n return elseValue\n }\n\n return this.get()\n },\n orThrow: (error: Error) => {\n if (isEmpty) {\n if (!theError) {\n throw error\n }\n\n throw theError\n }\n\n return theValue\n },\n map: (callback: (value: any) => any) => {\n if (isPresent) {\n return Try(() => callback(theValue))\n }\n\n return Optional(undefined!, theError)\n },\n mapAsync: (callback: (value: any) => any) => {\n if (isPresent) {\n return TryAsync(() => callback(theValue))\n }\n\n return Promise.resolve(Optional(undefined!, theError))\n },\n orMap: (callback: () => any) => {\n if (isEmpty && !theError) {\n return Try(() => callback())\n }\n\n return Optional(theValue!, theError)\n },\n orMapAsync: (callback: () => any) => {\n if (isEmpty && !theError) {\n return TryAsync(() => callback())\n }\n\n return Promise.resolve(Optional(theValue!, theError))\n },\n getError: () => {\n return theError\n },\n catch: (callback: (error: Error) => any) => {\n if (isEmpty && theError) {\n return Try(() => callback(theError))\n }\n\n return Optional(theValue!, theError)\n },\n catchAsync: (callback: (error: Error) => any) => {\n if (isEmpty && theError) {\n return TryAsync(() => callback(theError))\n }\n\n return Promise.resolve(Optional(theValue!, theError))\n },\n isEmpty: isEmpty,\n isPresent: isPresent\n })\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export * from './optional';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA","sourcesContent":["export * from './optional'\n"]}
@@ -0,0 +1,131 @@
1
+ export function isOptional(optional) {
2
+ return Boolean(optional &&
3
+ typeof optional.get === 'function' &&
4
+ typeof optional.orElse === 'function' &&
5
+ typeof optional.orThrow === 'function' &&
6
+ typeof optional.map === 'function' &&
7
+ typeof optional.mapAsync === 'function' &&
8
+ typeof optional.orMap === 'function' &&
9
+ typeof optional.orMapAsync === 'function' &&
10
+ typeof optional.catch === 'function' &&
11
+ typeof optional.catchAsync === 'function' &&
12
+ typeof optional.getError === 'function' &&
13
+ typeof optional.isEmpty === 'boolean' &&
14
+ typeof optional.isPresent === 'boolean');
15
+ }
16
+ export function Try(thunk) {
17
+ try {
18
+ const value = thunk();
19
+ if (isOptional(value)) {
20
+ return value;
21
+ }
22
+ return Optional(value);
23
+ }
24
+ catch (error) {
25
+ return Optional(undefined, error);
26
+ }
27
+ }
28
+ export async function TryAsync(thunk) {
29
+ try {
30
+ const value = await thunk();
31
+ if (isOptional(value)) {
32
+ return value;
33
+ }
34
+ return Optional(value);
35
+ }
36
+ catch (error) {
37
+ return Optional(undefined, error);
38
+ }
39
+ }
40
+ export function Empty(error) {
41
+ return Optional(undefined, error);
42
+ }
43
+ export class EmptyOptionalError extends Error {
44
+ static ERROR = 'EmptyOptionalError';
45
+ constructor() {
46
+ super('Optional is empty');
47
+ this.name = EmptyOptionalError.ERROR;
48
+ }
49
+ }
50
+ export function Optional(value, error) {
51
+ const getValue = (value) => {
52
+ if (isOptional(value)) {
53
+ return value.isPresent ? value.get() : undefined;
54
+ }
55
+ return value;
56
+ };
57
+ const theValue = getValue(value);
58
+ const theError = isOptional(value) && !error ? value.getError() : error;
59
+ const isEmpty = typeof theValue === 'undefined' || theValue === null;
60
+ const isPresent = !isEmpty;
61
+ return Object.freeze({
62
+ get: () => {
63
+ if (isEmpty) {
64
+ if (!theError) {
65
+ throw new EmptyOptionalError();
66
+ }
67
+ else {
68
+ throw theError;
69
+ }
70
+ }
71
+ return theValue;
72
+ },
73
+ orElse: function (elseValue) {
74
+ if (isEmpty && !theError) {
75
+ return elseValue;
76
+ }
77
+ return this.get();
78
+ },
79
+ orThrow: (error) => {
80
+ if (isEmpty) {
81
+ if (!theError) {
82
+ throw error;
83
+ }
84
+ throw theError;
85
+ }
86
+ return theValue;
87
+ },
88
+ map: (callback) => {
89
+ if (isPresent) {
90
+ return Try(() => callback(theValue));
91
+ }
92
+ return Optional(undefined, theError);
93
+ },
94
+ mapAsync: (callback) => {
95
+ if (isPresent) {
96
+ return TryAsync(() => callback(theValue));
97
+ }
98
+ return Promise.resolve(Optional(undefined, theError));
99
+ },
100
+ orMap: (callback) => {
101
+ if (isEmpty && !theError) {
102
+ return Try(() => callback());
103
+ }
104
+ return Optional(theValue, theError);
105
+ },
106
+ orMapAsync: (callback) => {
107
+ if (isEmpty && !theError) {
108
+ return TryAsync(() => callback());
109
+ }
110
+ return Promise.resolve(Optional(theValue, theError));
111
+ },
112
+ getError: () => {
113
+ return theError;
114
+ },
115
+ catch: (callback) => {
116
+ if (isEmpty && theError) {
117
+ return Try(() => callback(theError));
118
+ }
119
+ return Optional(theValue, theError);
120
+ },
121
+ catchAsync: (callback) => {
122
+ if (isEmpty && theError) {
123
+ return TryAsync(() => callback(theError));
124
+ }
125
+ return Promise.resolve(Optional(theValue, theError));
126
+ },
127
+ isEmpty: isEmpty,
128
+ isPresent: isPresent
129
+ });
130
+ }
131
+ //# sourceMappingURL=optional.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional.js","sourceRoot":"","sources":["../../src/optional.ts"],"names":[],"mappings":"AACA,MAAM,UAAU,UAAU,CAAC,QAAa;IACpC,OAAO,OAAO,CAAC,QAAQ;QACnB,OAAO,QAAQ,CAAC,GAAG,KAAK,UAAU;QAClC,OAAO,QAAQ,CAAC,MAAM,KAAK,UAAU;QACrC,OAAO,QAAQ,CAAC,OAAO,KAAK,UAAU;QACtC,OAAO,QAAQ,CAAC,GAAG,KAAK,UAAU;QAClC,OAAO,QAAQ,CAAC,QAAQ,KAAK,UAAU;QACvC,OAAO,QAAQ,CAAC,KAAK,KAAK,UAAU;QACpC,OAAO,QAAQ,CAAC,UAAU,KAAK,UAAU;QACzC,OAAO,QAAQ,CAAC,KAAK,KAAK,UAAU;QACpC,OAAO,QAAQ,CAAC,UAAU,KAAK,UAAU;QACzC,OAAO,QAAQ,CAAC,QAAQ,KAAK,UAAU;QACvC,OAAO,QAAQ,CAAC,OAAO,KAAK,SAAS;QACrC,OAAO,QAAQ,CAAC,SAAS,KAAK,SAAS,CAAC,CAAA;AAChD,CAAC;AAED,MAAM,UAAU,GAAG,CAAI,KAA4B;IAC/C,IAAI,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,EAAE,CAAA;QACrB,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACpB,OAAO,KAAoB,CAAA;QAC/B,CAAC;QACD,OAAO,QAAQ,CAAC,KAAU,CAAC,CAAA;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,QAAQ,CAAI,SAAU,EAAE,KAAc,CAAC,CAAA;IAClD,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAI,KAAqC;IACnE,IAAI,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,KAAK,EAAE,CAAA;QAC3B,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACpB,OAAO,KAAoB,CAAA;QAC/B,CAAC;QACD,OAAO,QAAQ,CAAC,KAAU,CAAC,CAAA;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,QAAQ,CAAI,SAAU,EAAE,KAAc,CAAC,CAAA;IAClD,CAAC;AACL,CAAC;AAoBD,MAAM,UAAU,KAAK,CAAI,KAAa;IAClC,OAAO,QAAQ,CAAI,SAAU,EAAE,KAAK,CAAC,CAAA;AACzC,CAAC;AAED,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IACzC,MAAM,CAAC,KAAK,GAAG,oBAAoB,CAAA;IAEnC;QACI,KAAK,CAAC,mBAAmB,CAAC,CAAA;QAE1B,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC,KAAK,CAAA;IACxC,CAAC;;AAIL,MAAM,UAAU,QAAQ,CAAC,KAAU,EAAE,KAAW;IAC5C,MAAM,QAAQ,GAAG,CAAC,KAAU,EAAE,EAAE;QAC5B,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACpB,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;QACpD,CAAC;QAED,OAAO,KAAK,CAAA;IAChB,CAAC,CAAA;IACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAChC,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CAAA;IACvE,MAAM,OAAO,GAAG,OAAO,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,IAAI,CAAA;IACpE,MAAM,SAAS,GAAG,CAAC,OAAO,CAAA;IAE1B,OAAO,MAAM,CAAC,MAAM,CAAC;QACjB,GAAG,EAAE,GAAG,EAAE;YACN,IAAI,OAAO,EAAE,CAAC;gBACV,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACZ,MAAM,IAAI,kBAAkB,EAAE,CAAA;gBAClC,CAAC;qBAAM,CAAC;oBACJ,MAAM,QAAQ,CAAA;gBAClB,CAAC;YACL,CAAC;YAED,OAAO,QAAQ,CAAA;QACnB,CAAC;QACD,MAAM,EAAE,UAAU,SAAc;YAC5B,IAAI,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACvB,OAAO,SAAS,CAAA;YACpB,CAAC;YAED,OAAO,IAAI,CAAC,GAAG,EAAE,CAAA;QACrB,CAAC;QACD,OAAO,EAAE,CAAC,KAAY,EAAE,EAAE;YACtB,IAAI,OAAO,EAAE,CAAC;gBACV,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACZ,MAAM,KAAK,CAAA;gBACf,CAAC;gBAED,MAAM,QAAQ,CAAA;YAClB,CAAC;YAED,OAAO,QAAQ,CAAA;QACnB,CAAC;QACD,GAAG,EAAE,CAAC,QAA6B,EAAE,EAAE;YACnC,IAAI,SAAS,EAAE,CAAC;gBACZ,OAAO,GAAG,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAA;YACxC,CAAC;YAED,OAAO,QAAQ,CAAC,SAAU,EAAE,QAAQ,CAAC,CAAA;QACzC,CAAC;QACD,QAAQ,EAAE,CAAC,QAA6B,EAAE,EAAE;YACxC,IAAI,SAAS,EAAE,CAAC;gBACZ,OAAO,QAAQ,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAA;YAC7C,CAAC;YAED,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAU,EAAE,QAAQ,CAAC,CAAC,CAAA;QAC1D,CAAC;QACD,KAAK,EAAE,CAAC,QAAmB,EAAE,EAAE;YAC3B,IAAI,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACvB,OAAO,GAAG,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAA;YAChC,CAAC;YAED,OAAO,QAAQ,CAAC,QAAS,EAAE,QAAQ,CAAC,CAAA;QACxC,CAAC;QACD,UAAU,EAAE,CAAC,QAAmB,EAAE,EAAE;YAChC,IAAI,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACvB,OAAO,QAAQ,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAA;YACrC,CAAC;YAED,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAS,EAAE,QAAQ,CAAC,CAAC,CAAA;QACzD,CAAC;QACD,QAAQ,EAAE,GAAG,EAAE;YACX,OAAO,QAAQ,CAAA;QACnB,CAAC;QACD,KAAK,EAAE,CAAC,QAA+B,EAAE,EAAE;YACvC,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;gBACtB,OAAO,GAAG,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAA;YACxC,CAAC;YAED,OAAO,QAAQ,CAAC,QAAS,EAAE,QAAQ,CAAC,CAAA;QACxC,CAAC;QACD,UAAU,EAAE,CAAC,QAA+B,EAAE,EAAE;YAC5C,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;gBACtB,OAAO,QAAQ,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAA;YAC7C,CAAC;YAED,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAS,EAAE,QAAQ,CAAC,CAAC,CAAA;QACzD,CAAC;QACD,OAAO,EAAE,OAAO;QAChB,SAAS,EAAE,SAAS;KACvB,CAAC,CAAA;AACN,CAAC","sourcesContent":["\nexport function isOptional(optional: any): optional is Optional<any> {\n return Boolean(optional &&\n typeof optional.get === 'function' &&\n typeof optional.orElse === 'function' &&\n typeof optional.orThrow === 'function' &&\n typeof optional.map === 'function' &&\n typeof optional.mapAsync === 'function' &&\n typeof optional.orMap === 'function' &&\n typeof optional.orMapAsync === 'function' &&\n typeof optional.catch === 'function' &&\n typeof optional.catchAsync === 'function' &&\n typeof optional.getError === 'function' &&\n typeof optional.isEmpty === 'boolean' &&\n typeof optional.isPresent === 'boolean')\n}\n\nexport function Try<T>(thunk: () => Optional<T> | T): Optional<T> {\n try {\n const value = thunk()\n if (isOptional(value)) {\n return value as Optional<T>\n }\n return Optional(value as T)\n } catch (error) {\n return Optional<T>(undefined!, error as Error)\n }\n}\n\nexport async function TryAsync<T>(thunk: () => Promise<Optional<T> | T>): Promise<Optional<T>> {\n try {\n const value = await thunk()\n if (isOptional(value)) {\n return value as Optional<T>\n }\n return Optional(value as T)\n } catch (error) {\n return Optional<T>(undefined!, error as Error)\n }\n}\n\nexport interface Maybe<T, E extends Error> {\n readonly get: () => T\n readonly orElse: (value: T) => T\n readonly orThrow: (error: E) => T\n readonly map: <A>(callback: (value: T) => Optional<A> | A) => Optional<A>\n readonly mapAsync: <A>(callback: (value: T) => Promise<Optional<A> | A>) => Promise<Optional<A>>\n readonly orMap: <A>(callback: () => Optional<A> | A) => Optional<A | T>\n readonly orMapAsync: <A>(callback: () => Promise<Optional<A> | A>) => Promise<Optional<A | T>>\n readonly getError: () => any\n readonly catch: <A>(callback: (error: E) => Optional<A> | A) => Optional<A | T>\n readonly catchAsync: <A>(callback: (error: E) => Promise<Optional<A> | A>) => Promise<Optional<A | T>>\n readonly isEmpty: boolean\n readonly isPresent: boolean\n}\n\ntype UnwrapOptional<T> = T extends Maybe<infer U, Error> ? U : T\nexport type Optional<T> = Maybe<UnwrapOptional<T>, Error>\n\nexport function Empty<T>(error?: Error): Optional<T> {\n return Optional<T>(undefined!, error)\n}\n\nexport class EmptyOptionalError extends Error {\n static ERROR = 'EmptyOptionalError'\n\n constructor() {\n super('Optional is empty')\n\n this.name = EmptyOptionalError.ERROR\n }\n}\n\nexport function Optional<T>(value: Optional<T> | T | undefined | null, error?: Error): Optional<T>\nexport function Optional(value: any, error?: any): any {\n const getValue = (value: any) => {\n if (isOptional(value)) {\n return value.isPresent ? value.get() : undefined\n }\n\n return value\n }\n const theValue = getValue(value)\n const theError = isOptional(value) && !error ? value.getError() : error\n const isEmpty = typeof theValue === 'undefined' || theValue === null\n const isPresent = !isEmpty\n\n return Object.freeze({\n get: () => {\n if (isEmpty) {\n if (!theError) {\n throw new EmptyOptionalError()\n } else {\n throw theError\n }\n }\n\n return theValue\n },\n orElse: function (elseValue: any) {\n if (isEmpty && !theError) {\n return elseValue\n }\n\n return this.get()\n },\n orThrow: (error: Error) => {\n if (isEmpty) {\n if (!theError) {\n throw error\n }\n\n throw theError\n }\n\n return theValue\n },\n map: (callback: (value: any) => any) => {\n if (isPresent) {\n return Try(() => callback(theValue))\n }\n\n return Optional(undefined!, theError)\n },\n mapAsync: (callback: (value: any) => any) => {\n if (isPresent) {\n return TryAsync(() => callback(theValue))\n }\n\n return Promise.resolve(Optional(undefined!, theError))\n },\n orMap: (callback: () => any) => {\n if (isEmpty && !theError) {\n return Try(() => callback())\n }\n\n return Optional(theValue!, theError)\n },\n orMapAsync: (callback: () => any) => {\n if (isEmpty && !theError) {\n return TryAsync(() => callback())\n }\n\n return Promise.resolve(Optional(theValue!, theError))\n },\n getError: () => {\n return theError\n },\n catch: (callback: (error: Error) => any) => {\n if (isEmpty && theError) {\n return Try(() => callback(theError))\n }\n\n return Optional(theValue!, theError)\n },\n catchAsync: (callback: (error: Error) => any) => {\n if (isEmpty && theError) {\n return TryAsync(() => callback(theError))\n }\n\n return Promise.resolve(Optional(theValue!, theError))\n },\n isEmpty: isEmpty,\n isPresent: isPresent\n })\n}\n"]}
package/package.json CHANGED
@@ -1,12 +1,28 @@
1
1
  {
2
2
  "name": "@othree.io/optional",
3
- "version": "2.3.2",
3
+ "version": "3.0.0",
4
4
  "description": "Implementation of Optional values",
5
5
  "private": false,
6
- "main": "lib/index.js",
6
+ "main": "lib/cjs/index.js",
7
+ "module": "lib/esm/index.js",
8
+ "types": "lib/cjs/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./lib/cjs/index.d.ts",
12
+ "import": "./lib/esm/index.js",
13
+ "require": "./lib/cjs/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "lib"
18
+ ],
7
19
  "scripts": {
8
- "test": "jest",
9
- "build": "tsc"
20
+ "test": "vitest run --coverage",
21
+ "build": "tsc && tsc -p tsconfig.esm.json",
22
+ "semantic-release": "semantic-release"
23
+ },
24
+ "publishConfig": {
25
+ "access": "public"
10
26
  },
11
27
  "repository": {
12
28
  "type": "git",
@@ -19,9 +35,8 @@
19
35
  },
20
36
  "homepage": "https://gitlab.com/othree.oss/optional#readme",
21
37
  "devDependencies": {
22
- "@types/jest": "^27.0.2",
23
- "jest": "^27.2.1",
24
- "ts-jest": "^27.0.5",
25
- "typescript": "^4.4.3"
38
+ "@vitest/coverage-v8": "^3.0.0",
39
+ "typescript": "^5.7.0",
40
+ "vitest": "^3.0.0"
26
41
  }
27
42
  }
package/.gitlab-ci.yml DELETED
@@ -1,29 +0,0 @@
1
- image: node:12-alpine
2
-
3
- cache:
4
- key: ${CI_PIPELINE_ID}
5
- paths:
6
- - node_modules/
7
- - lib/
8
-
9
- build:
10
- stage: build
11
- script:
12
- - npm install && npm run build
13
-
14
- test:
15
- stage: test
16
- script:
17
- - npm test
18
-
19
- deploy:
20
- image: node:18
21
- stage: deploy
22
- variables:
23
- NPM_CONFIG_USERCONFIG: '$CI_PROJECT_DIR/.npmrc'
24
- script:
25
- - cat $NPM > .npmrc
26
- - npx semantic-release
27
- only:
28
- refs:
29
- - master
package/lib/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA0B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"optional.d.ts","sourceRoot":"","sources":["../src/optional.ts"],"names":[],"mappings":"AACA,wBAAgB,UAAU,CAAC,QAAQ,EAAE,GAAG,GAAG,QAAQ,IAAI,QAAQ,CAAC,GAAG,CAAC,CAcnE;AAED,wBAAgB,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAUhE;AAED,wBAAsB,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAU7F;AAED,MAAM,WAAW,KAAK,CAAC,CAAC,EAAE,CAAC,SAAS,KAAK;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAA;IAChC,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAA;IACjC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAA;IACzE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IAChG,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACvE,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IAC9F,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,CAAA;IAC5B,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IAC/E,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IACtG,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC9B;AAED,oBAAY,QAAQ,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;AAEzC,wBAAgB,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAEnD;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IACzC,MAAM,CAAC,KAAK,SAAuB;;CAOtC;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,GAAG,IAAI,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAuFjG"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"optional.js","sourceRoot":"","sources":["../src/optional.ts"],"names":[],"mappings":"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"}
package/release.config.js DELETED
@@ -1,4 +0,0 @@
1
- module.exports = {
2
- plugins: ['@semantic-release/commit-analyzer', '@semantic-release/release-notes-generator', '@semantic-release/npm'],
3
- branches: ['master', 'main']
4
- }
File without changes
File without changes