@clipboard-health/util-ts 2.8.8 → 2.9.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 (112) hide show
  1. package/README.md +219 -2
  2. package/package.json +13 -5
  3. package/src/index.d.ts +13 -15
  4. package/src/index.js +14 -14
  5. package/src/index.js.map +1 -1
  6. package/src/lib/{head.d.ts → arrays/head.d.ts} +6 -2
  7. package/src/lib/{head.js → arrays/head.js} +4 -1
  8. package/src/lib/arrays/head.js.map +1 -0
  9. package/src/lib/{non-empty-array.d.ts → arrays/nonEmptyArray.d.ts} +0 -1
  10. package/src/lib/{non-empty-array.js → arrays/nonEmptyArray.js} +1 -1
  11. package/src/lib/arrays/nonEmptyArray.js.map +1 -0
  12. package/src/lib/deepFreeze.d.ts +9 -0
  13. package/src/lib/deepFreeze.js +27 -0
  14. package/src/lib/deepFreeze.js.map +1 -0
  15. package/src/lib/errors/cbhError.d.ts +33 -0
  16. package/src/lib/{cbh-error.js → errors/cbhError.js} +10 -3
  17. package/src/lib/errors/cbhError.js.map +1 -0
  18. package/src/lib/errors/isError.d.ts +7 -0
  19. package/src/lib/errors/isError.js +13 -0
  20. package/src/lib/errors/isError.js.map +1 -0
  21. package/src/lib/errors/serviceError.d.ts +86 -0
  22. package/src/lib/errors/serviceError.js +180 -0
  23. package/src/lib/errors/serviceError.js.map +1 -0
  24. package/src/lib/errors/toError.d.ts +8 -0
  25. package/src/lib/errors/toError.js +35 -0
  26. package/src/lib/errors/toError.js.map +1 -0
  27. package/src/lib/errors/toErrorMessage.d.ts +7 -0
  28. package/src/lib/errors/toErrorMessage.js +14 -0
  29. package/src/lib/errors/toErrorMessage.js.map +1 -0
  30. package/src/lib/{force-cast.d.ts → forceCast.d.ts} +2 -1
  31. package/src/lib/{force-cast.js → forceCast.js} +3 -1
  32. package/src/lib/forceCast.js.map +1 -0
  33. package/src/lib/functional/cbhResponse.d.ts +23 -0
  34. package/src/lib/{cbh-response.js → functional/cbhResponse.js} +9 -3
  35. package/src/lib/functional/cbhResponse.js.map +1 -0
  36. package/src/lib/functional/either.d.ts +86 -0
  37. package/src/lib/functional/either.js +97 -0
  38. package/src/lib/functional/either.js.map +1 -0
  39. package/src/lib/functional/option.d.ts +71 -0
  40. package/src/lib/functional/option.js +82 -0
  41. package/src/lib/functional/option.js.map +1 -0
  42. package/src/lib/functional/pipe.d.ts +21 -0
  43. package/src/lib/functional/pipe.js +7 -0
  44. package/src/lib/functional/pipe.js.map +1 -0
  45. package/src/lib/functional/serviceResult.d.ts +23 -0
  46. package/src/lib/functional/serviceResult.js +27 -0
  47. package/src/lib/functional/serviceResult.js.map +1 -0
  48. package/src/lib/nullish/isDefined.d.ts +9 -0
  49. package/src/lib/nullish/isDefined.js +15 -0
  50. package/src/lib/nullish/isDefined.js.map +1 -0
  51. package/src/lib/nullish/isNil.d.ts +12 -0
  52. package/src/lib/nullish/isNil.js +20 -0
  53. package/src/lib/nullish/isNil.js.map +1 -0
  54. package/src/lib/{null-to-undefined.d.ts → nullish/nullToUndefined.d.ts} +0 -1
  55. package/src/lib/{null-to-undefined.js → nullish/nullToUndefined.js} +1 -1
  56. package/src/lib/nullish/nullToUndefined.js.map +1 -0
  57. package/src/lib/strings/isString.d.ts +7 -0
  58. package/src/lib/strings/isString.js +13 -0
  59. package/src/lib/strings/isString.js.map +1 -0
  60. package/src/lib/strings/stringify.d.ts +8 -0
  61. package/src/lib/strings/stringify.js +14 -0
  62. package/src/lib/strings/stringify.js.map +1 -0
  63. package/src/lib/types.d.ts +1 -0
  64. package/src/lib/types.js +3 -0
  65. package/src/lib/types.js.map +1 -0
  66. package/src/index.d.ts.map +0 -1
  67. package/src/lib/cbh-error.d.ts +0 -22
  68. package/src/lib/cbh-error.d.ts.map +0 -1
  69. package/src/lib/cbh-error.js.map +0 -1
  70. package/src/lib/cbh-response.d.ts +0 -18
  71. package/src/lib/cbh-response.d.ts.map +0 -1
  72. package/src/lib/cbh-response.js.map +0 -1
  73. package/src/lib/defined-utils.d.ts +0 -11
  74. package/src/lib/defined-utils.d.ts.map +0 -1
  75. package/src/lib/defined-utils.js +0 -17
  76. package/src/lib/defined-utils.js.map +0 -1
  77. package/src/lib/delay.d.ts +0 -5
  78. package/src/lib/delay.d.ts.map +0 -1
  79. package/src/lib/delay.js +0 -12
  80. package/src/lib/delay.js.map +0 -1
  81. package/src/lib/either.d.ts +0 -32
  82. package/src/lib/either.d.ts.map +0 -1
  83. package/src/lib/either.js +0 -31
  84. package/src/lib/either.js.map +0 -1
  85. package/src/lib/force-cast.d.ts.map +0 -1
  86. package/src/lib/force-cast.js.map +0 -1
  87. package/src/lib/head.d.ts.map +0 -1
  88. package/src/lib/head.js.map +0 -1
  89. package/src/lib/identity.d.ts +0 -7
  90. package/src/lib/identity.d.ts.map +0 -1
  91. package/src/lib/identity.js +0 -12
  92. package/src/lib/identity.js.map +0 -1
  93. package/src/lib/is-string.d.ts +0 -2
  94. package/src/lib/is-string.d.ts.map +0 -1
  95. package/src/lib/is-string.js +0 -7
  96. package/src/lib/is-string.js.map +0 -1
  97. package/src/lib/non-empty-array.d.ts.map +0 -1
  98. package/src/lib/non-empty-array.js.map +0 -1
  99. package/src/lib/null-to-undefined.d.ts.map +0 -1
  100. package/src/lib/null-to-undefined.js.map +0 -1
  101. package/src/lib/option.d.ts +0 -28
  102. package/src/lib/option.d.ts.map +0 -1
  103. package/src/lib/option.js +0 -29
  104. package/src/lib/option.js.map +0 -1
  105. package/src/lib/stringify.d.ts +0 -5
  106. package/src/lib/stringify.d.ts.map +0 -1
  107. package/src/lib/stringify.js +0 -10
  108. package/src/lib/stringify.js.map +0 -1
  109. package/src/lib/to-error.d.ts +0 -13
  110. package/src/lib/to-error.d.ts.map +0 -1
  111. package/src/lib/to-error.js +0 -34
  112. package/src/lib/to-error.js.map +0 -1
package/README.md CHANGED
@@ -1,11 +1,17 @@
1
- # @clipboard-health/util-ts
1
+ # @clipboard-health/util-ts <!-- omit from toc -->
2
2
 
3
3
  TypeScript utilities.
4
4
 
5
- ## Table of Contents
5
+ ## Table of contents <!-- omit from toc -->
6
6
 
7
7
  - [Install](#install)
8
8
  - [Usage](#usage)
9
+ - [ServiceError](#serviceerror)
10
+ - [ServiceResult](#serviceresult)
11
+ - [Functional](#functional)
12
+ - [`pipe`](#pipe)
13
+ - [`option`](#option)
14
+ - [`either`](#either)
9
15
  - [Local development commands](#local-development-commands)
10
16
 
11
17
  ## Install
@@ -16,6 +22,217 @@ npm install @clipboard-health/util-ts
16
22
 
17
23
  ## Usage
18
24
 
25
+ See `./src/lib` for each utility.
26
+
27
+ ### ServiceError
28
+
29
+ <!-- prettier-ignore -->
30
+ ```ts
31
+ // ./examples/serviceError.ts
32
+
33
+ import { deepEqual, equal } from "node:assert/strict";
34
+
35
+ import { ERROR_CODES, ServiceError } from "@clipboard-health/util-ts";
36
+
37
+ {
38
+ const error = new ServiceError("boom");
39
+ equal(error.toString(), `ServiceError[${error.id}]: [internal]: boom`);
40
+ }
41
+
42
+ {
43
+ const error = new Error("boom");
44
+ const serviceError = ServiceError.fromError(error);
45
+ equal(
46
+ serviceError.toString(),
47
+ `ServiceError[${serviceError.id}]: [internal]: boom; [cause]: Error: boom`,
48
+ );
49
+ }
50
+
51
+ {
52
+ const errorWithCause = new ServiceError({
53
+ issues: [{ message: "boom" }],
54
+ cause: new Error("Original error"),
55
+ });
56
+ equal(
57
+ errorWithCause.toString(),
58
+ `ServiceError[${errorWithCause.id}]: [internal]: boom; [cause]: Error: Original error`,
59
+ );
60
+ }
61
+
62
+ {
63
+ const multipleIssues = new ServiceError({
64
+ issues: [
65
+ {
66
+ code: ERROR_CODES.badRequest,
67
+ message: "Invalid email format",
68
+ path: ["data", "attributes", "email"],
69
+ },
70
+ {
71
+ code: ERROR_CODES.unprocessableEntity,
72
+ message: "Phone number too short",
73
+ path: ["data", "attributes", "phoneNumber"],
74
+ },
75
+ ],
76
+ cause: new Error("Original error"),
77
+ });
78
+
79
+ equal(
80
+ multipleIssues.toString(),
81
+ `ServiceError[${multipleIssues.id}]: [badRequest]: Invalid email format; [unprocessableEntity]: Phone number too short; [cause]: Error: Original error`,
82
+ );
83
+
84
+ deepEqual(multipleIssues.toJsonApi(), {
85
+ errors: [
86
+ {
87
+ id: multipleIssues.id,
88
+ status: "400",
89
+ code: "badRequest",
90
+ title: "Invalid or malformed request",
91
+ detail: "Invalid email format",
92
+ source: {
93
+ pointer: "/data/attributes/email",
94
+ },
95
+ },
96
+ {
97
+ id: multipleIssues.id,
98
+ status: "422",
99
+ code: "unprocessableEntity",
100
+ title: "Request failed validation",
101
+ detail: "Phone number too short",
102
+ source: {
103
+ pointer: "/data/attributes/phoneNumber",
104
+ },
105
+ },
106
+ ],
107
+ });
108
+ }
109
+
110
+ ```
111
+
112
+ ### ServiceResult
113
+
114
+ <!-- prettier-ignore -->
115
+ ```ts
116
+ // ./examples/serviceResult.ts
117
+
118
+ import { ok } from "node:assert/strict";
119
+
120
+ import {
121
+ either as E,
122
+ ERROR_CODES,
123
+ failure,
124
+ type ServiceResult,
125
+ success,
126
+ } from "@clipboard-health/util-ts";
127
+
128
+ function validateUser(params: { email: string; phone: string }): ServiceResult<{ id: string }> {
129
+ const { email, phone } = params;
130
+ const code = ERROR_CODES.unprocessableEntity;
131
+
132
+ if (!email.includes("@")) {
133
+ return failure({ issues: [{ code, message: "Invalid email format" }] });
134
+ }
135
+
136
+ if (phone.length !== 12) {
137
+ return failure({ issues: [{ code, message: "Invalid phone number" }] });
138
+ }
139
+
140
+ return success({ id: "user-123" });
141
+ }
142
+
143
+ ok(E.isLeft(validateUser({ email: "invalidEmail", phone: "invalidPhoneNumber" })));
144
+ ok(E.isRight(validateUser({ email: "user@example.com", phone: "555-555-5555" })));
145
+
146
+ ```
147
+
148
+ ### Functional
149
+
150
+ #### `pipe`
151
+
152
+ <!-- prettier-ignore -->
153
+ ```ts
154
+ // ./examples/pipe.ts
155
+
156
+ import { equal } from "node:assert/strict";
157
+
158
+ import { pipe } from "@clipboard-health/util-ts";
159
+
160
+ const result = pipe(
161
+ " hello world ",
162
+ (s) => s.trim(),
163
+ (s) => s.split(" "),
164
+ (array) => array.map((word) => word.charAt(0).toUpperCase() + word.slice(1)),
165
+ (array) => array.join(" "),
166
+ );
167
+
168
+ equal(result, "Hello World");
169
+
170
+ ```
171
+
172
+ #### `option`
173
+
174
+ <!-- prettier-ignore -->
175
+ ```ts
176
+ // ./examples/option.ts
177
+
178
+ import { equal } from "node:assert/strict";
179
+
180
+ import { option as O, pipe } from "@clipboard-health/util-ts";
181
+
182
+ function double(n: number) {
183
+ return n * 2;
184
+ }
185
+
186
+ function inverse(n: number): O.Option<number> {
187
+ return n === 0 ? O.none : O.some(1 / n);
188
+ }
189
+
190
+ const result = pipe(
191
+ O.some(5),
192
+ O.map(double),
193
+ O.flatMap(inverse),
194
+ O.match(
195
+ () => "No result",
196
+ (n) => `Result is ${n}`,
197
+ ),
198
+ );
199
+
200
+ equal(result, "Result is 0.1");
201
+
202
+ ```
203
+
204
+ #### `either`
205
+
206
+ <!-- prettier-ignore -->
207
+ ```ts
208
+ // ./examples/either.ts
209
+
210
+ import { equal } from "node:assert/strict";
211
+
212
+ import { either as E, pipe } from "@clipboard-health/util-ts";
213
+
214
+ function double(n: number): number {
215
+ return n * 2;
216
+ }
217
+
218
+ function inverse(n: number): E.Either<string, number> {
219
+ return n === 0 ? E.left("Division by zero") : E.right(1 / n);
220
+ }
221
+
222
+ const result = pipe(
223
+ E.right(5),
224
+ E.map(double),
225
+ E.flatMap(inverse),
226
+ E.match(
227
+ (error) => `Error: ${error}`,
228
+ (result) => `Result is ${result}`,
229
+ ),
230
+ );
231
+
232
+ equal(result, "Result is 0.1");
233
+
234
+ ```
235
+
19
236
  ## Local development commands
20
237
 
21
238
  See [`package.json`](./package.json) `scripts` for a list of commands.
package/package.json CHANGED
@@ -1,15 +1,23 @@
1
1
  {
2
2
  "name": "@clipboard-health/util-ts",
3
- "version": "2.8.8",
3
+ "description": "TypeScript utilities.",
4
+ "version": "2.9.0",
5
+ "dependencies": {
6
+ "tslib": "2.8.0"
7
+ },
8
+ "devDependencies": {
9
+ "type-fest": "4.26.1"
10
+ },
11
+ "keywords": [],
12
+ "license": "MIT",
4
13
  "main": "./src/index.js",
5
14
  "publishConfig": {
6
- "access": "restricted"
15
+ "access": "public"
7
16
  },
8
17
  "scripts": {
9
- "build": "nx build util-ts",
10
- "lint": "nx lint util-ts",
11
- "test": "nx test util-ts"
18
+ "embed": "embedme README.md"
12
19
  },
13
20
  "type": "commonjs",
21
+ "typings": "./src/index.d.ts",
14
22
  "types": "./src/index.d.ts"
15
23
  }
package/src/index.d.ts CHANGED
@@ -1,15 +1,13 @@
1
- export * from "./lib/cbh-error";
2
- export * from "./lib/cbh-response";
3
- export * from "./lib/defined-utils";
4
- export * from "./lib/delay";
5
- export * from "./lib/either";
6
- export * from "./lib/force-cast";
7
- export * from "./lib/head";
8
- export * from "./lib/identity";
9
- export * from "./lib/is-string";
10
- export * from "./lib/non-empty-array";
11
- export * from "./lib/null-to-undefined";
12
- export * from "./lib/option";
13
- export * from "./lib/stringify";
14
- export * from "./lib/to-error";
15
- //# sourceMappingURL=index.d.ts.map
1
+ export * from "./lib/deepFreeze";
2
+ export * from "./lib/errors/isError";
3
+ export * from "./lib/errors/serviceError";
4
+ export * from "./lib/errors/toError";
5
+ export * as either from "./lib/functional/either";
6
+ export * as option from "./lib/functional/option";
7
+ export * from "./lib/functional/pipe";
8
+ export * from "./lib/functional/serviceResult";
9
+ export * from "./lib/nullish/isDefined";
10
+ export * from "./lib/nullish/isNil";
11
+ export * from "./lib/strings/isString";
12
+ export * from "./lib/strings/stringify";
13
+ export * from "./lib/types";
package/src/index.js CHANGED
@@ -1,18 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.option = exports.either = void 0;
3
4
  const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./lib/cbh-error"), exports);
5
- tslib_1.__exportStar(require("./lib/cbh-response"), exports);
6
- tslib_1.__exportStar(require("./lib/defined-utils"), exports);
7
- tslib_1.__exportStar(require("./lib/delay"), exports);
8
- tslib_1.__exportStar(require("./lib/either"), exports);
9
- tslib_1.__exportStar(require("./lib/force-cast"), exports);
10
- tslib_1.__exportStar(require("./lib/head"), exports);
11
- tslib_1.__exportStar(require("./lib/identity"), exports);
12
- tslib_1.__exportStar(require("./lib/is-string"), exports);
13
- tslib_1.__exportStar(require("./lib/non-empty-array"), exports);
14
- tslib_1.__exportStar(require("./lib/null-to-undefined"), exports);
15
- tslib_1.__exportStar(require("./lib/option"), exports);
16
- tslib_1.__exportStar(require("./lib/stringify"), exports);
17
- tslib_1.__exportStar(require("./lib/to-error"), exports);
5
+ tslib_1.__exportStar(require("./lib/deepFreeze"), exports);
6
+ tslib_1.__exportStar(require("./lib/errors/isError"), exports);
7
+ tslib_1.__exportStar(require("./lib/errors/serviceError"), exports);
8
+ tslib_1.__exportStar(require("./lib/errors/toError"), exports);
9
+ exports.either = tslib_1.__importStar(require("./lib/functional/either"));
10
+ exports.option = tslib_1.__importStar(require("./lib/functional/option"));
11
+ tslib_1.__exportStar(require("./lib/functional/pipe"), exports);
12
+ tslib_1.__exportStar(require("./lib/functional/serviceResult"), exports);
13
+ tslib_1.__exportStar(require("./lib/nullish/isDefined"), exports);
14
+ tslib_1.__exportStar(require("./lib/nullish/isNil"), exports);
15
+ tslib_1.__exportStar(require("./lib/strings/isString"), exports);
16
+ tslib_1.__exportStar(require("./lib/strings/stringify"), exports);
17
+ tslib_1.__exportStar(require("./lib/types"), exports);
18
18
  //# sourceMappingURL=index.js.map
package/src/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/util-ts/src/index.ts"],"names":[],"mappings":";;;AAAA,0DAAgC;AAChC,6DAAmC;AACnC,8DAAoC;AACpC,sDAA4B;AAC5B,uDAA6B;AAC7B,2DAAiC;AACjC,qDAA2B;AAC3B,yDAA+B;AAC/B,0DAAgC;AAChC,gEAAsC;AACtC,kEAAwC;AACxC,uDAA6B;AAC7B,0DAAgC;AAChC,yDAA+B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/util-ts/src/index.ts"],"names":[],"mappings":";;;;AAAA,2DAAiC;AACjC,+DAAqC;AACrC,oEAA0C;AAC1C,+DAAqC;AACrC,0EAAkD;AAClD,0EAAkD;AAClD,gEAAsC;AACtC,yEAA+C;AAC/C,kEAAwC;AACxC,8DAAoC;AACpC,iEAAuC;AACvC,kEAAwC;AACxC,sDAA4B"}
@@ -1,9 +1,13 @@
1
1
  /**
2
2
  * Either a single value or an array of values.
3
+ *
4
+ * @deprecated Use `Arrayable` from "type-fest" instead.
3
5
  */
4
6
  export type OneOrArray<T> = T | T[];
5
7
  /**
6
- * If the provided value is an array, returns the first element. Otherwise, returns the value itself.
8
+ * If the provided value is an array, returns the first element. Otherwise, returns the value
9
+ * itself.
10
+ *
11
+ * @deprecated Use `const [first] = [1, 2, 3]` instead.
7
12
  */
8
13
  export declare function head<T>(value?: OneOrArray<T>): T | undefined;
9
- //# sourceMappingURL=head.d.ts.map
@@ -2,7 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.head = head;
4
4
  /**
5
- * If the provided value is an array, returns the first element. Otherwise, returns the value itself.
5
+ * If the provided value is an array, returns the first element. Otherwise, returns the value
6
+ * itself.
7
+ *
8
+ * @deprecated Use `const [first] = [1, 2, 3]` instead.
6
9
  */
7
10
  function head(value) {
8
11
  return Array.isArray(value) ? value[0] : (value ?? undefined);
@@ -0,0 +1 @@
1
+ {"version":3,"file":"head.js","sourceRoot":"","sources":["../../../../../../packages/util-ts/src/lib/arrays/head.ts"],"names":[],"mappings":";;AAaA,oBAEC;AARD;;;;;GAKG;AACH,SAAgB,IAAI,CAAI,KAAqB;IAC3C,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,SAAS,CAAC,CAAC;AAChE,CAAC"}
@@ -10,4 +10,3 @@ export type OneOrNonEmptyArray<T> = T | NonEmptyArray<T>;
10
10
  * @deprecated Use standard Array<T> instead.
11
11
  */
12
12
  export declare function toNonEmptyArray<T>(value: OneOrNonEmptyArray<T>): NonEmptyArray<T>;
13
- //# sourceMappingURL=non-empty-array.d.ts.map
@@ -7,4 +7,4 @@ exports.toNonEmptyArray = toNonEmptyArray;
7
7
  function toNonEmptyArray(value) {
8
8
  return Array.isArray(value) ? value : [value];
9
9
  }
10
- //# sourceMappingURL=non-empty-array.js.map
10
+ //# sourceMappingURL=nonEmptyArray.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nonEmptyArray.js","sourceRoot":"","sources":["../../../../../../packages/util-ts/src/lib/arrays/nonEmptyArray.ts"],"names":[],"mappings":";;AAaA,0CAEC;AALD;;GAEG;AACH,SAAgB,eAAe,CAAI,KAA4B;IAC7D,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Recursively freezes an object and all its nested properties.
3
+ *
4
+ * @template T - Type of the object to freeze
5
+ * @param value - The object to freeze
6
+ * @param seen - Internal parameter to track circular references
7
+ * @returns A deeply frozen version of the input object.
8
+ */
9
+ export declare function deepFreeze<T extends object>(value: T, seen?: WeakSet<WeakKey>): Readonly<T>;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deepFreeze = deepFreeze;
4
+ /**
5
+ * Recursively freezes an object and all its nested properties.
6
+ *
7
+ * @template T - Type of the object to freeze
8
+ * @param value - The object to freeze
9
+ * @param seen - Internal parameter to track circular references
10
+ * @returns A deeply frozen version of the input object.
11
+ */
12
+ // eslint-disable-next-line @typescript-eslint/ban-types
13
+ function deepFreeze(value, seen = new WeakSet()) {
14
+ if (!value || typeof value !== "object" || seen.has(value)) {
15
+ return value;
16
+ }
17
+ seen.add(value);
18
+ Reflect.ownKeys(value).forEach((key) => {
19
+ const property = value[key];
20
+ if (property && typeof property === "object" && !Object.isFrozen(property)) {
21
+ // eslint-disable-next-line @typescript-eslint/ban-types
22
+ deepFreeze(property, seen);
23
+ }
24
+ });
25
+ return Object.freeze(value);
26
+ }
27
+ //# sourceMappingURL=deepFreeze.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deepFreeze.js","sourceRoot":"","sources":["../../../../../packages/util-ts/src/lib/deepFreeze.ts"],"names":[],"mappings":";;AASA,gCAeC;AAxBD;;;;;;;GAOG;AACH,wDAAwD;AACxD,SAAgB,UAAU,CAAmB,KAAQ,EAAE,IAAI,GAAG,IAAI,OAAO,EAAE;IACzE,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACf,OAAO,CAAC,OAAO,CAAC,KAAK,CAAoB,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QACzD,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3E,wDAAwD;YACxD,UAAU,CAA2B,QAAQ,EAAE,IAAI,CAAC,CAAC;QACvD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { type Arrayable } from "type-fest";
2
+ import * as E from "../functional/either";
3
+ /**
4
+ * Error status codes in our service APIs.
5
+ *
6
+ * @see {@link https://www.notion.so/BP-REST-API-f769b7fe745c4cf38f6eca2e9ad8a843?pvs=4#e0b4e9ea30f041409ce39505650098ea}
7
+ */
8
+ declare const ERROR_STATUS_CODES: readonly [400, 401, 403, 404, 409, 422, 429, 500];
9
+ /**
10
+ * @deprecated Use {@link ErrorCode} instead.
11
+ */
12
+ export type ErrorStatusCode = (typeof ERROR_STATUS_CODES)[number];
13
+ /**
14
+ * @deprecated Use {@link ServiceIssue} instead.
15
+ */
16
+ export interface CbhIssue {
17
+ cause?: Error;
18
+ id?: string;
19
+ message: string;
20
+ statusCode?: ErrorStatusCode;
21
+ }
22
+ /**
23
+ * @deprecated Use {@link ServiceError} instead.
24
+ */
25
+ export declare class CbhError extends Error {
26
+ readonly issues: readonly CbhIssue[];
27
+ constructor(messageOrIssues: Arrayable<CbhIssue> | string);
28
+ }
29
+ /**
30
+ * @deprecated Use {@link failure} instead.
31
+ */
32
+ export declare function toLeft<A = never>(issues: Arrayable<CbhIssue> | string): E.Either<CbhError, A>;
33
+ export {};
@@ -2,13 +2,17 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CbhError = void 0;
4
4
  exports.toLeft = toLeft;
5
- const either_1 = require("./either");
5
+ const tslib_1 = require("tslib");
6
+ const E = tslib_1.__importStar(require("../functional/either"));
6
7
  /**
7
8
  * Error status codes in our service APIs.
8
9
  *
9
10
  * @see {@link https://www.notion.so/BP-REST-API-f769b7fe745c4cf38f6eca2e9ad8a843?pvs=4#e0b4e9ea30f041409ce39505650098ea}
10
11
  */
11
12
  const ERROR_STATUS_CODES = [400, 401, 403, 404, 409, 422, 429, 500];
13
+ /**
14
+ * @deprecated Use {@link ServiceError} instead.
15
+ */
12
16
  class CbhError extends Error {
13
17
  issues;
14
18
  constructor(messageOrIssues) {
@@ -26,7 +30,10 @@ class CbhError extends Error {
26
30
  }
27
31
  }
28
32
  exports.CbhError = CbhError;
33
+ /**
34
+ * @deprecated Use {@link failure} instead.
35
+ */
29
36
  function toLeft(issues) {
30
- return (0, either_1.left)(new CbhError(issues));
37
+ return E.left(new CbhError(issues));
31
38
  }
32
- //# sourceMappingURL=cbh-error.js.map
39
+ //# sourceMappingURL=cbhError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cbhError.js","sourceRoot":"","sources":["../../../../../../packages/util-ts/src/lib/errors/cbhError.ts"],"names":[],"mappings":";;;AAqDA,wBAEC;;AArDD,gEAA0C;AAE1C;;;;GAIG;AACH,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAU,CAAC;AAiB7E;;GAEG;AACH,MAAa,QAAS,SAAQ,KAAK;IACjB,MAAM,CAAsB;IAE5C,YAAY,eAA6C;QACvD,MAAM,EAAE,GACN,OAAO,eAAe,KAAK,QAAQ;YACjC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;YAChC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC;gBAC9B,CAAC,CAAC,eAAe;gBACjB,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;QAE1B,MAAM,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;QACpD,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;QAC7E,6FAA6F;QAC7F,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAElD,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAnBD,4BAmBC;AAED;;GAEG;AACH,SAAgB,MAAM,CAAY,MAAoC;IACpE,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AACtC,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Type guard that checks if a value is an instance of Error.
3
+ *
4
+ * @param value - The value to check
5
+ * @returns True if the value is an Error instance, false otherwise
6
+ */
7
+ export declare function isError(value: unknown): value is Error;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isError = isError;
4
+ /**
5
+ * Type guard that checks if a value is an instance of Error.
6
+ *
7
+ * @param value - The value to check
8
+ * @returns True if the value is an Error instance, false otherwise
9
+ */
10
+ function isError(value) {
11
+ return value instanceof Error;
12
+ }
13
+ //# sourceMappingURL=isError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isError.js","sourceRoot":"","sources":["../../../../../../packages/util-ts/src/lib/errors/isError.ts"],"names":[],"mappings":";;AAMA,0BAEC;AARD;;;;;GAKG;AACH,SAAgB,OAAO,CAAC,KAAc;IACpC,OAAO,KAAK,YAAY,KAAK,CAAC;AAChC,CAAC"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Standard error codes used across microservices.
3
+ */
4
+ export declare const ERROR_CODES: {
5
+ readonly badRequest: "badRequest";
6
+ readonly unauthorized: "unauthorized";
7
+ readonly forbidden: "forbidden";
8
+ readonly notFound: "notFound";
9
+ readonly conflict: "conflict";
10
+ readonly unprocessableEntity: "unprocessableEntity";
11
+ readonly tooManyRequests: "tooManyRequests";
12
+ readonly internal: "internal";
13
+ };
14
+ export type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES];
15
+ export interface ServiceIssue {
16
+ /** Standardized {@link ERROR_CODES} */
17
+ code?: ErrorCode;
18
+ /** Details about what caused the issue */
19
+ message?: string | undefined;
20
+ /** Path to issue location */
21
+ path?: Array<string | number>;
22
+ }
23
+ export type ServiceErrorParams = string | {
24
+ cause?: Readonly<unknown>;
25
+ issues: readonly ServiceIssue[];
26
+ };
27
+ export interface ZodLike {
28
+ issues: ReadonlyArray<{
29
+ message?: string | undefined;
30
+ path: Array<string | number>;
31
+ }>;
32
+ }
33
+ interface Issue extends ServiceIssue {
34
+ code: Required<ServiceIssue>["code"];
35
+ title: string;
36
+ }
37
+ /**
38
+ * Error class for service-level errors, convertible to JSON:API errors.
39
+ */
40
+ export declare class ServiceError extends Error {
41
+ /**
42
+ * Converts an error to a `ServiceError`.
43
+ *
44
+ * @param value - The value to convert, which can be any type
45
+ * @returns If the value is already a `ServiceError`, returns it unchanged. Otherwise, convert it
46
+ * to a `ServiceError`.
47
+ */
48
+ static fromError(value: unknown): ServiceError;
49
+ /**
50
+ * Converts a Zod-like error to a `ServiceError`.
51
+ *
52
+ * @param value - An object with a Zod-like error structure containing issues
53
+ * @returns The converted `ServiceError`
54
+ * @throws {ServiceError} If the provided value does not match the expected Zod-like structure
55
+ */
56
+ static fromZodLike(value: ZodLike): ServiceError;
57
+ readonly id: string;
58
+ readonly issues: readonly Issue[];
59
+ /**
60
+ * Creates a new `ServiceError`
61
+ * @param parameters - Issues contributing to the error or a message string
62
+ */
63
+ constructor(parameters: ServiceErrorParams);
64
+ /**
65
+ * Return string representation of the error for logging.
66
+ */
67
+ toString(): string;
68
+ /**
69
+ * Converts the error to JSON:API format
70
+ * @see {@link https://jsonapi.org/format/#error-objects}
71
+ * @returns Object conforming to JSON:API error format
72
+ */
73
+ toJsonApi(): {
74
+ errors: {
75
+ source?: {
76
+ pointer: string;
77
+ };
78
+ detail?: string;
79
+ id: string;
80
+ status: string;
81
+ code: ErrorCode;
82
+ title: string;
83
+ }[];
84
+ };
85
+ }
86
+ export {};