@nice-code/error 0.2.10 → 0.2.11

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 (2) hide show
  1. package/build/index.js +952 -19
  2. package/package.json +1 -1
package/build/index.js CHANGED
@@ -1,19 +1,952 @@
1
- // src/index.ts
2
- export * from "./internal";
3
- export * from "./NiceError/NiceError";
4
- export * from "./NiceError/NiceError.types";
5
- export * from "./NiceError/NiceErrorHydrated";
6
- export * from "./NiceErrorDefined/defineNiceError";
7
- export * from "./NiceErrorDefined/err";
8
- export * from "./NiceErrorDefined/NiceErrorDefined";
9
- export * from "./NiceErrorHandler/handleWith";
10
- export * from "./NiceErrorHandler/NiceErrorHandler";
11
- export * from "./NiceErrorHandler/NiceErrorHandler.types";
12
- export * from "./utils/castAndHydrate";
13
- export * from "./utils/castNiceError";
14
- export * from "./utils/isNiceErrorObject";
15
- export * from "./utils/isRegularErrorObject";
16
- export * from "./utils/matchFirst";
17
- export * from "./utils/packError/causePack";
18
- export * from "./utils/packError/msgPack";
19
- export * from "./utils/packError/packError.enums";
1
+ // src/internal/nice_core_errors.ts
2
+ import { StatusCodes } from "http-status-codes";
3
+
4
+ // src/utils/jsErrorOrCastJsError.ts
5
+ function jsErrorOrCastJsError(error, logMessage = true) {
6
+ if (error instanceof Error) {
7
+ return Object.assign(error, {
8
+ message: error.message
9
+ });
10
+ }
11
+ const message = error?.message ?? (typeof error === "string" ? error : "No error message found");
12
+ if (logMessage) {
13
+ console.error(`An unknown and unstructured error was thrown: ${message}`, error);
14
+ }
15
+ return {
16
+ ...new Error(message),
17
+ ...error
18
+ };
19
+ }
20
+
21
+ // src/NiceError/nice_error.static.ts
22
+ var DUR_OBJ_PACK_PREFIX = "NE_DUROBJ[[";
23
+ var DUR_OBJ_PACK_SUFFIX = "]]NE_DUROBJ";
24
+
25
+ // src/utils/packError/packError.enums.ts
26
+ var EErrorPackType;
27
+ ((EErrorPackType2) => {
28
+ EErrorPackType2["no_pack"] = "no_pack";
29
+ EErrorPackType2["msg_pack"] = "msg_pack";
30
+ EErrorPackType2["cause_pack"] = "cause_pack";
31
+ })(EErrorPackType ||= {});
32
+
33
+ // src/utils/packError/causePack.ts
34
+ var causePack = (error) => {
35
+ error._packedState = { cause: error.cause, packedAs: "cause_pack" /* cause_pack */ };
36
+ error.cause = `${DUR_OBJ_PACK_PREFIX}${JSON.stringify(error.toJsonObject())}${DUR_OBJ_PACK_SUFFIX}`;
37
+ return error;
38
+ };
39
+
40
+ // src/utils/packError/msgPack.ts
41
+ var msgPack = (error) => {
42
+ error._packedState = { message: error.cleanMessage, packedAs: "msg_pack" /* msg_pack */ };
43
+ error.message = `${DUR_OBJ_PACK_PREFIX}${JSON.stringify(error.toJsonObject())}${DUR_OBJ_PACK_SUFFIX}`;
44
+ return error;
45
+ };
46
+
47
+ // src/utils/packError/packError.ts
48
+ var packError = (error, packType = "msg_pack") => {
49
+ if (packType === "no_pack") {
50
+ return error;
51
+ }
52
+ if (packType === "msg_pack") {
53
+ return msgPack(error);
54
+ }
55
+ return causePack(error);
56
+ };
57
+
58
+ // src/NiceError/NiceError.ts
59
+ class NiceError extends Error {
60
+ name = "NiceError";
61
+ def;
62
+ ids;
63
+ wasntNice;
64
+ httpStatusCode;
65
+ timeCreated;
66
+ cleanMessage;
67
+ originError;
68
+ _packedState;
69
+ _errorDataMap;
70
+ constructor(options) {
71
+ const messagePure = options.message;
72
+ const prefixedMessage = `[${options.def.domain}](${options.ids.join(",")}) ${messagePure}`;
73
+ super(prefixedMessage);
74
+ this.cleanMessage = messagePure;
75
+ this.def = options.def;
76
+ this.ids = options.ids;
77
+ this._errorDataMap = options.errorData;
78
+ this.wasntNice = options.wasntNice ?? false;
79
+ this.httpStatusCode = options.httpStatusCode ?? 500;
80
+ if (options.originError != null) {
81
+ this.originError = options.originError;
82
+ }
83
+ this.timeCreated = options.timeCreated ?? Date.now();
84
+ }
85
+ hasId(id) {
86
+ return id in this._errorDataMap;
87
+ }
88
+ hasOneOfIds(ids) {
89
+ return ids.some((id) => (id in this._errorDataMap));
90
+ }
91
+ get hasMultiple() {
92
+ return Object.keys(this._errorDataMap).length > 1;
93
+ }
94
+ getIds() {
95
+ return Object.keys(this._errorDataMap);
96
+ }
97
+ getContext(id) {
98
+ const errorData = this._errorDataMap[id];
99
+ const state = errorData?.contextState;
100
+ if (state == null) {
101
+ return;
102
+ }
103
+ if (state.kind === "unhydrated") {
104
+ throw new Error(`[NiceError.getContext] Context for id "${String(id)}" is in the "unhydrated" state. ` + `The error was reconstructed from a serialized payload but has not been deserialized yet. ` + `Call \`niceErrorDefined.hydrate(error)\` to reconstruct the typed context.`);
105
+ }
106
+ return state.value;
107
+ }
108
+ getErrorDataForId(id) {
109
+ return this._errorDataMap[id];
110
+ }
111
+ withOriginError(error) {
112
+ this.originError = jsErrorOrCastJsError(error);
113
+ if (this._packedState?.packedAs !== "cause_pack" /* cause_pack */) {
114
+ this.cause = this.originError;
115
+ }
116
+ return this;
117
+ }
118
+ matches(other) {
119
+ const myDef = this.def;
120
+ const otherDef = other.def;
121
+ if (myDef.domain !== otherDef.domain)
122
+ return false;
123
+ const myIds = this.getIds().map(String).sort();
124
+ const otherIds = other.getIds().map(String).sort();
125
+ if (myIds.length !== otherIds.length)
126
+ return false;
127
+ return myIds.every((id, i) => id === otherIds[i]);
128
+ }
129
+ toJsonObject() {
130
+ const originError = this.originError ? {
131
+ name: this.originError.name,
132
+ message: this.originError.cleanMessage ?? this.originError.message,
133
+ stack: this.originError.stack,
134
+ cause: this.originError.cause
135
+ } : undefined;
136
+ const def = {
137
+ domain: this.def.domain,
138
+ allDomains: this.def.allDomains
139
+ };
140
+ if (this.def.defaultHttpStatusCode != null) {
141
+ def["defaultHttpStatusCode"] = this.def.defaultHttpStatusCode;
142
+ }
143
+ if (this.def.defaultMessage != null) {
144
+ def["defaultMessage"] = this.def.defaultMessage;
145
+ }
146
+ const errorData = {};
147
+ for (const rawId of Object.keys(this._errorDataMap)) {
148
+ const id = rawId;
149
+ const data = this._errorDataMap[id];
150
+ if (data == null)
151
+ continue;
152
+ let contextState;
153
+ if (data.contextState.kind === "hydrated" /* hydrated */) {
154
+ contextState = {
155
+ kind: "unhydrated" /* unhydrated */,
156
+ serialized: data.contextState.serialized
157
+ };
158
+ } else {
159
+ contextState = data.contextState;
160
+ }
161
+ errorData[id] = {
162
+ contextState,
163
+ message: data.cleanMessage ?? data.message,
164
+ httpStatusCode: data.httpStatusCode,
165
+ timeAdded: data.timeAdded
166
+ };
167
+ }
168
+ return {
169
+ name: "NiceError",
170
+ def,
171
+ ids: this.ids,
172
+ errorData,
173
+ wasntNice: this.wasntNice,
174
+ message: this.cleanMessage,
175
+ httpStatusCode: this.httpStatusCode,
176
+ timeCreated: this.timeCreated,
177
+ ...this.stack != null ? { stack: this.stack } : {},
178
+ originError
179
+ };
180
+ }
181
+ toJsonString() {
182
+ return JSON.stringify(this.toJsonObject());
183
+ }
184
+ toHttpResponse() {
185
+ return new Response(this.toJsonString(), {
186
+ status: this.httpStatusCode,
187
+ headers: { "Content-Type": "application/json" }
188
+ });
189
+ }
190
+ hydrate(definedNiceError) {
191
+ return definedNiceError.hydrate(this);
192
+ }
193
+ handleWithSync(handlerInput, handlerOptions = {}) {
194
+ const handlersArray = Array.isArray(handlerInput) ? handlerInput : [handlerInput];
195
+ for (const handler of handlersArray) {
196
+ const result = handler.handleErrorWithPromiseInspection(this, handlerOptions);
197
+ if (result.matched) {
198
+ if (result.isPromise) {
199
+ console.warn(`[NiceError.handleWith] Handler ${result.target.identifier} returned a Promise but was called via \`handleWith\` (synchronous). ` + `The Promise will not be awaited. Use \`handleWithAsync\` for async handlers.`);
200
+ }
201
+ return result.isPromise ? undefined : result.handlerResponse;
202
+ }
203
+ }
204
+ if (handlerOptions.throwOnUnhandled === true)
205
+ throw this;
206
+ return;
207
+ }
208
+ async handleWithAsync(handlerInput, handlerOptions = {}) {
209
+ const handlersArray = Array.isArray(handlerInput) ? handlerInput : [handlerInput];
210
+ for (const handler of handlersArray) {
211
+ const result = handler.handleErrorWithPromiseInspection(this, handlerOptions);
212
+ if (result.matched) {
213
+ return result.isPromise ? await result.handlerPromise : result.handlerResponse;
214
+ }
215
+ }
216
+ if (handlerOptions.throwOnUnhandled === true)
217
+ throw this;
218
+ return;
219
+ }
220
+ get isPacked() {
221
+ return this._packedState != null;
222
+ }
223
+ pack(packType = "msg_pack") {
224
+ if (this.isPacked)
225
+ return this;
226
+ return packError(this, packType);
227
+ }
228
+ unpack() {
229
+ if (this._packedState == null)
230
+ return this;
231
+ if (this._packedState.packedAs === "msg_pack" /* msg_pack */) {
232
+ this.message = this._packedState.message;
233
+ }
234
+ if (this._packedState.packedAs === "cause_pack" /* cause_pack */) {
235
+ this.cause = this._packedState.cause;
236
+ }
237
+ this._packedState = undefined;
238
+ delete this._packedState;
239
+ return this;
240
+ }
241
+ }
242
+
243
+ // src/NiceError/NiceErrorHydrated.ts
244
+ class NiceErrorHydrated extends NiceError {
245
+ def;
246
+ niceErrorDefined;
247
+ constructor(options) {
248
+ super(options);
249
+ this.def = options.def;
250
+ this.niceErrorDefined = options.niceErrorDefined;
251
+ }
252
+ addContext(context) {
253
+ const newIds = Object.keys(context);
254
+ const newErrorData = {};
255
+ for (const id of newIds) {
256
+ newErrorData[id] = this.niceErrorDefined.reconcileErrorDataForId(id, context[id]);
257
+ }
258
+ const mergedErrorData = {
259
+ ...this._errorDataMap,
260
+ ...newErrorData
261
+ };
262
+ const mergedIds = Array.from(new Set([...this.getIds(), ...Object.keys(context)]));
263
+ return new NiceErrorHydrated({
264
+ def: this.def,
265
+ niceErrorDefined: this.niceErrorDefined,
266
+ ids: mergedIds,
267
+ errorData: mergedErrorData,
268
+ message: this.cleanMessage,
269
+ wasntNice: this.wasntNice,
270
+ httpStatusCode: this.httpStatusCode,
271
+ originError: this.originError
272
+ });
273
+ }
274
+ addId(...args) {
275
+ const [id, context] = args;
276
+ const reconciledData = this.niceErrorDefined.reconcileErrorDataForId(id, context);
277
+ const errorDataMap = {};
278
+ errorDataMap[id] = reconciledData;
279
+ const mergedContexts = {
280
+ ...this._errorDataMap,
281
+ ...errorDataMap
282
+ };
283
+ const mergedIds = Array.from(new Set([...this.getIds(), id]));
284
+ return new NiceErrorHydrated({
285
+ def: this.def,
286
+ niceErrorDefined: this.niceErrorDefined,
287
+ ids: mergedIds,
288
+ errorData: mergedContexts,
289
+ message: this.cleanMessage,
290
+ wasntNice: this.wasntNice,
291
+ httpStatusCode: this.httpStatusCode,
292
+ originError: this.originError
293
+ });
294
+ }
295
+ }
296
+
297
+ // src/NiceErrorDefined/NiceErrorDefined.ts
298
+ class NiceErrorDomain {
299
+ domain;
300
+ allDomains;
301
+ defaultHttpStatusCode;
302
+ defaultMessage;
303
+ _schema;
304
+ _definedChildNiceErrors = [];
305
+ _definedParentNiceError;
306
+ _setPack;
307
+ _packAsFn;
308
+ constructor(definition) {
309
+ this.domain = definition.domain;
310
+ this.allDomains = definition.allDomains;
311
+ this._schema = definition.schema;
312
+ if (definition.packAs != null) {
313
+ this._packAsFn = definition.packAs;
314
+ }
315
+ if (definition.defaultHttpStatusCode != null) {
316
+ this.defaultHttpStatusCode = definition.defaultHttpStatusCode;
317
+ }
318
+ if (definition.defaultMessage != null) {
319
+ this.defaultMessage = definition.defaultMessage;
320
+ }
321
+ }
322
+ createChildDomain(subErrorDef) {
323
+ const child = new NiceErrorDomain({
324
+ domain: subErrorDef.domain,
325
+ allDomains: [subErrorDef.domain, ...this.allDomains],
326
+ schema: subErrorDef.schema,
327
+ defaultHttpStatusCode: subErrorDef.defaultHttpStatusCode,
328
+ defaultMessage: subErrorDef.defaultMessage
329
+ });
330
+ this.addChildNiceErrorDefined(child);
331
+ child.addParentNiceErrorDefined(this);
332
+ if (subErrorDef.packAs != null) {
333
+ child._packAsFn = subErrorDef.packAs;
334
+ } else if (this._setPack) {
335
+ child.packAs(this._setPack);
336
+ } else if (this._packAsFn) {
337
+ child._packAsFn = this._packAsFn;
338
+ }
339
+ return child;
340
+ }
341
+ addParentNiceErrorDefined(parentError) {
342
+ if (this._definedParentNiceError?.domain === parentError.domain) {
343
+ return;
344
+ }
345
+ this._definedParentNiceError = {
346
+ domain: parentError.domain,
347
+ definedError: parentError
348
+ };
349
+ }
350
+ addChildNiceErrorDefined(child) {
351
+ if (this._definedChildNiceErrors.some((linked) => linked.domain === child.domain)) {
352
+ return;
353
+ }
354
+ this._definedChildNiceErrors.push({
355
+ domain: child.domain,
356
+ definedError: child
357
+ });
358
+ if (this._definedParentNiceError) {
359
+ this._definedParentNiceError.definedError.addChildNiceErrorDefined(child);
360
+ }
361
+ }
362
+ packAs(pack) {
363
+ this._setPack = pack;
364
+ return this;
365
+ }
366
+ createError(input) {
367
+ const err = new NiceErrorHydrated(input);
368
+ const packType = this._setPack ?? this._packAsFn?.();
369
+ if (packType != null && packType !== "no_pack") {
370
+ return err.pack(packType);
371
+ }
372
+ return err;
373
+ }
374
+ hydrate(error) {
375
+ const errDef = error.def;
376
+ if (errDef.domain !== this.domain) {
377
+ throw new Error(`[NiceErrorDefined.hydrate] Domain mismatch: this definition is "${this.domain}" ` + `but the error belongs to "${errDef.domain}". ` + `Call \`niceErrorDefined.is(error)\` before hydrating to ensure compatibility.`);
378
+ }
379
+ const finalError = error instanceof NiceError ? error : new NiceError(error);
380
+ const reconciledErrorData = {};
381
+ for (const id of finalError.getIds()) {
382
+ const existingData = finalError.getErrorDataForId(id);
383
+ if (existingData == null)
384
+ continue;
385
+ let contextState = existingData.contextState;
386
+ if (contextState.kind === "unhydrated") {
387
+ const entry = this._schema[id];
388
+ const deserialize = entry?.context?.serialization?.fromJsonSerializable;
389
+ if (deserialize != null) {
390
+ contextState = {
391
+ kind: "hydrated" /* hydrated */,
392
+ value: deserialize(contextState.serialized),
393
+ serialized: contextState.serialized
394
+ };
395
+ }
396
+ }
397
+ reconciledErrorData[id] = {
398
+ contextState,
399
+ message: existingData.cleanMessage ?? existingData.message,
400
+ httpStatusCode: existingData.httpStatusCode,
401
+ timeAdded: existingData.timeAdded
402
+ };
403
+ }
404
+ return new NiceErrorHydrated({
405
+ def: this._buildDef(),
406
+ niceErrorDefined: this,
407
+ ids: finalError.ids,
408
+ errorData: reconciledErrorData,
409
+ message: finalError.cleanMessage ?? finalError.message,
410
+ httpStatusCode: finalError.httpStatusCode,
411
+ wasntNice: finalError.wasntNice,
412
+ originError: finalError.originError,
413
+ timeCreated: finalError.timeCreated
414
+ });
415
+ }
416
+ fromId(...args) {
417
+ const [id, context] = args;
418
+ const reconciledData = this.reconcileErrorDataForId(id, context);
419
+ const errorData = {};
420
+ errorData[id] = reconciledData;
421
+ return this.createError({
422
+ def: this._buildDef(),
423
+ niceErrorDefined: this,
424
+ ids: [id],
425
+ errorData,
426
+ message: reconciledData.cleanMessage ?? reconciledData.message,
427
+ httpStatusCode: reconciledData.httpStatusCode
428
+ });
429
+ }
430
+ fromContext(context) {
431
+ const ids = Object.keys(context);
432
+ if (ids.length === 0) {
433
+ throw new Error("[NiceErrorDefined.fromContext] context object must contain at least one error id.");
434
+ }
435
+ const errorData = {};
436
+ for (const id of ids) {
437
+ errorData[id] = this.reconcileErrorDataForId(id, context[id]);
438
+ }
439
+ const primaryId = ids[0];
440
+ return this.createError({
441
+ def: this._buildDef(),
442
+ niceErrorDefined: this,
443
+ ids,
444
+ errorData,
445
+ message: errorData[primaryId].cleanMessage ?? errorData[primaryId].message,
446
+ httpStatusCode: errorData[primaryId].httpStatusCode
447
+ });
448
+ }
449
+ isExact(error) {
450
+ if (!(error instanceof NiceError))
451
+ return false;
452
+ const errDef = error.def;
453
+ return errDef.domain === this.domain;
454
+ }
455
+ isThisOrChild(error) {
456
+ if (!(error instanceof NiceError))
457
+ return false;
458
+ const errDef = error.def;
459
+ return errDef.domain === this.domain || this.allDomains.includes(errDef.domain);
460
+ }
461
+ isParentOf(target) {
462
+ const allDomains = target instanceof NiceError ? target.def.allDomains : target.allDomains;
463
+ return Array.isArray(allDomains) && allDomains.includes(this.domain);
464
+ }
465
+ _buildDef() {
466
+ return {
467
+ domain: this.domain,
468
+ allDomains: this.allDomains,
469
+ schema: this._schema
470
+ };
471
+ }
472
+ _resolveMessage(id, context) {
473
+ const entry = this._schema[id];
474
+ if (typeof entry?.message === "function") {
475
+ return entry.message(context);
476
+ }
477
+ if (typeof entry?.message === "string") {
478
+ return entry.message;
479
+ }
480
+ return this.defaultMessage ?? `[${this.domain}::${id}] An error occurred.`;
481
+ }
482
+ _resolveHttpStatusCode(id, context) {
483
+ const entry = this._schema[id];
484
+ let httpStatusCode;
485
+ if (typeof entry?.httpStatusCode === "function") {
486
+ httpStatusCode = entry.httpStatusCode(context);
487
+ }
488
+ if (typeof entry?.httpStatusCode === "number") {
489
+ httpStatusCode = entry.httpStatusCode;
490
+ }
491
+ return typeof httpStatusCode === "number" ? httpStatusCode : this.defaultHttpStatusCode ?? 500;
492
+ }
493
+ reconcileErrorDataForId(id, context) {
494
+ const message = this._resolveMessage(id, context);
495
+ const httpStatusCode = this._resolveHttpStatusCode(id, context);
496
+ const entry = this._schema[id];
497
+ let contextState;
498
+ if (context != null && entry?.context?.serialization != null) {
499
+ const serialized = entry.context.serialization.toJsonSerializable(context);
500
+ contextState = { kind: "hydrated" /* hydrated */, value: context, serialized };
501
+ } else {
502
+ contextState = { kind: "serde_unset" /* serde_unset */, value: context };
503
+ }
504
+ return { contextState, message, httpStatusCode, timeAdded: Date.now() };
505
+ }
506
+ }
507
+
508
+ // src/NiceErrorDefined/defineNiceError.ts
509
+ var defineNiceError = (definition) => {
510
+ return new NiceErrorDomain({
511
+ domain: definition.domain,
512
+ allDomains: [definition.domain],
513
+ schema: definition.schema,
514
+ ...definition.packAs != null ? { packAs: definition.packAs } : {}
515
+ });
516
+ };
517
+
518
+ // src/NiceErrorDefined/err.ts
519
+ function err(meta) {
520
+ return meta ?? {};
521
+ }
522
+
523
+ // src/internal/nice_core_errors.ts
524
+ var err_nice = defineNiceError({
525
+ domain: "err_nice",
526
+ schema: {}
527
+ });
528
+ var EErrId_CastNotNice;
529
+ ((EErrId_CastNotNice2) => {
530
+ EErrId_CastNotNice2["js_error"] = "native_error";
531
+ EErrId_CastNotNice2["js_error_like_object"] = "js_error_like_object";
532
+ EErrId_CastNotNice2["nullish_value"] = "nullish_value";
533
+ EErrId_CastNotNice2["js_data_type"] = "js_data_type";
534
+ EErrId_CastNotNice2["js_other"] = "js_other";
535
+ })(EErrId_CastNotNice ||= {});
536
+ var err_cast_not_nice = err_nice.createChildDomain({
537
+ domain: "err_cast_not_nice",
538
+ defaultHttpStatusCode: StatusCodes.UNPROCESSABLE_ENTITY,
539
+ schema: {
540
+ ["native_error" /* js_error */]: err({
541
+ context: {
542
+ required: true
543
+ },
544
+ message: ({ jsError }) => `A native JavaScript Error was encountered during casting: ${jsError.message}`,
545
+ httpStatusCode: StatusCodes.INTERNAL_SERVER_ERROR
546
+ }),
547
+ ["js_error_like_object" /* js_error_like_object */]: err({
548
+ context: {
549
+ required: true
550
+ },
551
+ message: ({ jsErrorObject }) => `An object resembling a JavaScript Error was encountered during casting: [${jsErrorObject.name}] ${jsErrorObject.message}`,
552
+ httpStatusCode: StatusCodes.INTERNAL_SERVER_ERROR
553
+ }),
554
+ ["nullish_value" /* nullish_value */]: err({
555
+ context: {
556
+ required: true
557
+ },
558
+ message: ({ value }) => `A nullish value [${value === null ? "null" : "undefined"}] was encountered during casting`
559
+ }),
560
+ ["js_data_type" /* js_data_type */]: err({
561
+ context: {
562
+ required: true
563
+ },
564
+ message: ({ jsDataType, jsDataValue }) => {
565
+ let inspectedValue;
566
+ try {
567
+ inspectedValue = JSON.stringify(jsDataValue);
568
+ } catch {}
569
+ return `A value of type [${jsDataType}] with value [${inspectedValue ?? "UNSERIALIZABLE"}] was encountered during casting, which is not a valid error type`;
570
+ }
571
+ }),
572
+ ["js_other" /* js_other */]: err({
573
+ context: {
574
+ required: true
575
+ },
576
+ message: ({ jsDataValue }) => {
577
+ let inspectedValue;
578
+ try {
579
+ inspectedValue = JSON.stringify(jsDataValue);
580
+ } catch {}
581
+ return `An unhandled type [${typeof jsDataValue}] with value [${inspectedValue ?? "UNSERIALIZABLE"}] was encountered during casting, which is not a valid error type`;
582
+ }
583
+ })
584
+ }
585
+ });
586
+ var err_nice_handler = err_nice.createChildDomain({
587
+ domain: "err_nice_handler",
588
+ schema: {}
589
+ });
590
+ // src/NiceErrorHandler/NiceErrorHandler.types.ts
591
+ var EErrorHandlerTargetType;
592
+ ((EErrorHandlerTargetType2) => {
593
+ EErrorHandlerTargetType2["ids"] = "ids";
594
+ EErrorHandlerTargetType2["domain"] = "domain";
595
+ EErrorHandlerTargetType2["default"] = "default";
596
+ })(EErrorHandlerTargetType ||= {});
597
+
598
+ // src/NiceErrorHandler/NiceErrorHandler.ts
599
+ class NiceErrorHandler {
600
+ handlerConfigs = [];
601
+ _defaultRequester;
602
+ handleErrorWithPromiseInspection(error, options) {
603
+ for (const handlerConfig of this.handlerConfigs) {
604
+ if (!handlerConfig._matcher(error))
605
+ continue;
606
+ const errorResult = handlerConfig._requester(error);
607
+ if (errorResult instanceof Promise) {
608
+ return {
609
+ isPromise: true,
610
+ matched: true,
611
+ target: handlerConfig.target,
612
+ handlerPromise: errorResult
613
+ };
614
+ }
615
+ return {
616
+ isPromise: false,
617
+ matched: true,
618
+ target: handlerConfig.target,
619
+ handlerResponse: errorResult
620
+ };
621
+ }
622
+ if (this._defaultRequester) {
623
+ const defaultResult = this._defaultRequester(error);
624
+ if (defaultResult instanceof Promise) {
625
+ return {
626
+ isPromise: true,
627
+ matched: true,
628
+ target: {
629
+ type: "default" /* default */,
630
+ identifier: "[matched:default]"
631
+ },
632
+ handlerPromise: defaultResult
633
+ };
634
+ }
635
+ return {
636
+ isPromise: false,
637
+ matched: true,
638
+ target: { type: "default" /* default */, identifier: "[matched:default]" },
639
+ handlerResponse: defaultResult
640
+ };
641
+ }
642
+ if (options?.throwOnUnhandled === true) {
643
+ throw error;
644
+ }
645
+ return {
646
+ matched: false,
647
+ attemptedTargets: this.handlerConfigs.map((config) => config.target)
648
+ };
649
+ }
650
+ forDomain(domain, handler) {
651
+ this.handlerConfigs.push({
652
+ target: {
653
+ type: "domain" /* domain */,
654
+ domain: domain.domain,
655
+ identifier: `[matched:domain:${domain.domain}]`
656
+ },
657
+ _matcher: (error) => domain.isExact(error),
658
+ _requester: (error) => handler(domain.hydrate(error))
659
+ });
660
+ return this;
661
+ }
662
+ forId(domain, id, handler) {
663
+ this.handlerConfigs.push({
664
+ target: {
665
+ type: "ids" /* ids */,
666
+ domain: domain.domain,
667
+ ids: [id],
668
+ identifier: `[matched:ids:${domain.domain}:${id}]`
669
+ },
670
+ _matcher: (error) => domain.isExact(error) && error.hasId(id),
671
+ _requester: (error) => handler(domain.hydrate(error))
672
+ });
673
+ return this;
674
+ }
675
+ forIds(domain, ids, handler) {
676
+ this.handlerConfigs.push({
677
+ target: {
678
+ type: "ids" /* ids */,
679
+ domain: domain.domain,
680
+ ids,
681
+ identifier: `[matched:ids:${domain.domain}:${ids.join(",")}]`
682
+ },
683
+ _matcher: (error) => domain.isExact(error) && ids.some((id) => error.hasId(id)),
684
+ _requester: (error) => handler(domain.hydrate(error))
685
+ });
686
+ return this;
687
+ }
688
+ setDefaultHandler(handler) {
689
+ this._defaultRequester = handler;
690
+ return this;
691
+ }
692
+ }
693
+
694
+ // src/NiceErrorHandler/handleWith.ts
695
+ function forDomain(domain, handler) {
696
+ return new NiceErrorHandler().forDomain(domain, handler);
697
+ }
698
+ function forId(domain, id, handler) {
699
+ return new NiceErrorHandler().forId(domain, id, handler);
700
+ }
701
+ function forIds(domain, ids, handler) {
702
+ return new NiceErrorHandler().forIds(domain, ids, handler);
703
+ }
704
+ // src/utils/isNiceErrorObject.ts
705
+ function isNiceErrorObject(obj) {
706
+ if (typeof obj !== "object" || obj == null)
707
+ return false;
708
+ const o = obj;
709
+ if (o["name"] !== "NiceError" || typeof o["message"] !== "string" || typeof o["wasntNice"] !== "boolean" || typeof o["httpStatusCode"] !== "number") {
710
+ return false;
711
+ }
712
+ const def = o["def"];
713
+ if (typeof def !== "object" || def == null)
714
+ return false;
715
+ const d = def;
716
+ if (typeof d["domain"] !== "string" || !Array.isArray(d["allDomains"]))
717
+ return false;
718
+ const errorData = o["errorData"];
719
+ if (errorData != null) {
720
+ if (typeof errorData !== "object")
721
+ return false;
722
+ for (const entry of Object.values(errorData)) {
723
+ if (entry == null)
724
+ continue;
725
+ if (typeof entry !== "object")
726
+ return false;
727
+ const e = entry;
728
+ const state = e["contextState"];
729
+ if (state == null || typeof state !== "object")
730
+ return false;
731
+ const kind = state["kind"];
732
+ if (kind !== "serde_unset" /* serde_unset */ && kind !== "unhydrated" /* unhydrated */)
733
+ return false;
734
+ }
735
+ }
736
+ return true;
737
+ }
738
+
739
+ // src/utils/isRegularErrorObject.ts
740
+ function isRegularErrorJsonObject(obj) {
741
+ if (typeof obj !== "object" || obj == null)
742
+ return false;
743
+ const o = obj;
744
+ return typeof o["name"] === "string" && typeof o["message"] === "string";
745
+ }
746
+
747
+ // src/utils/logger.ts
748
+ import { Logger } from "tslog";
749
+ var logger_NiceError = new Logger({
750
+ name: "NiceErrorLogger"
751
+ });
752
+ var logger_NiceError_testing = logger_NiceError.getSubLogger({
753
+ name: "NiceErrorTestingLogger"
754
+ });
755
+
756
+ // src/utils/inspectPotentialError/inspectPotentialError.ts
757
+ function interpretMessagePackedError(parsedError) {
758
+ let packedErrorStr;
759
+ if (typeof parsedError.message === "string" && parsedError.message.includes(DUR_OBJ_PACK_PREFIX) && parsedError.message.includes(DUR_OBJ_PACK_SUFFIX)) {
760
+ packedErrorStr = parsedError.message;
761
+ }
762
+ if (typeof parsedError.cause === "string" && parsedError.cause.includes(DUR_OBJ_PACK_PREFIX) && parsedError.cause.includes(DUR_OBJ_PACK_SUFFIX)) {
763
+ packedErrorStr = parsedError.cause;
764
+ }
765
+ if (packedErrorStr != null) {
766
+ const jsonStr = packedErrorStr.split(DUR_OBJ_PACK_PREFIX)[1].split(DUR_OBJ_PACK_SUFFIX)[0];
767
+ try {
768
+ const errorObj = JSON.parse(jsonStr);
769
+ if (isNiceErrorObject(errorObj)) {
770
+ return {
771
+ type: "niceErrorObject" /* niceErrorObject */,
772
+ niceErrorObject: errorObj
773
+ };
774
+ }
775
+ } catch {}
776
+ }
777
+ return null;
778
+ }
779
+ var inspectPotentialError = (potentialError) => {
780
+ if (potentialError == null) {
781
+ return {
782
+ type: "nullish" /* nullish */,
783
+ value: potentialError
784
+ };
785
+ }
786
+ if (typeof potentialError === "number") {
787
+ return {
788
+ type: "jsDataType" /* jsDataType */,
789
+ jsDataType: "number",
790
+ jsDataValue: potentialError
791
+ };
792
+ }
793
+ if (typeof potentialError === "boolean") {
794
+ return {
795
+ type: "jsDataType" /* jsDataType */,
796
+ jsDataType: "boolean",
797
+ jsDataValue: potentialError
798
+ };
799
+ }
800
+ let parsedError = potentialError;
801
+ if (typeof potentialError === "string") {
802
+ if (potentialError.includes("{") && potentialError.includes("name")) {
803
+ try {
804
+ parsedError = JSON.parse(potentialError);
805
+ } catch {
806
+ return {
807
+ type: "jsDataType" /* jsDataType */,
808
+ jsDataType: "string",
809
+ jsDataValue: potentialError
810
+ };
811
+ }
812
+ } else {
813
+ return {
814
+ type: "jsDataType" /* jsDataType */,
815
+ jsDataType: "string",
816
+ jsDataValue: potentialError
817
+ };
818
+ }
819
+ }
820
+ if (typeof parsedError !== "object" || parsedError == null) {
821
+ logger_NiceError.warn({
822
+ message: "Received a potential error that is a primitive data type other than string, number, or boolean. This is unexpected and may indicate an issue with error handling in the code.",
823
+ potentialError
824
+ });
825
+ return {
826
+ jsDataValue: potentialError,
827
+ type: "jsOther" /* jsOther */
828
+ };
829
+ }
830
+ if (parsedError instanceof NiceError) {
831
+ return {
832
+ type: "niceError" /* niceError */,
833
+ niceError: parsedError
834
+ };
835
+ }
836
+ if (isNiceErrorObject(parsedError)) {
837
+ return {
838
+ type: "niceErrorObject" /* niceErrorObject */,
839
+ niceErrorObject: parsedError
840
+ };
841
+ }
842
+ if (parsedError instanceof Error) {
843
+ const durObjResult = interpretMessagePackedError(parsedError);
844
+ if (durObjResult != null) {
845
+ return durObjResult;
846
+ }
847
+ return {
848
+ type: "jsError" /* jsError */,
849
+ jsError: parsedError
850
+ };
851
+ }
852
+ if (isRegularErrorJsonObject(parsedError)) {
853
+ const durObjResult = interpretMessagePackedError(parsedError);
854
+ if (durObjResult != null) {
855
+ return durObjResult;
856
+ }
857
+ return {
858
+ type: "jsErrorObject" /* jsErrorObject */,
859
+ jsErrorObject: parsedError
860
+ };
861
+ }
862
+ return {
863
+ type: "jsDataType" /* jsDataType */,
864
+ jsDataType: "object",
865
+ jsDataValue: parsedError
866
+ };
867
+ };
868
+
869
+ // src/utils/castNiceError.ts
870
+ var castNiceError = (error) => {
871
+ const inspected = inspectPotentialError(error);
872
+ switch (inspected.type) {
873
+ case "niceError" /* niceError */:
874
+ return inspected.niceError;
875
+ case "niceErrorObject" /* niceErrorObject */: {
876
+ const obj = inspected.niceErrorObject;
877
+ return new NiceError(obj);
878
+ }
879
+ case "jsError" /* jsError */: {
880
+ return err_cast_not_nice.fromContext({
881
+ ["native_error" /* js_error */]: inspected
882
+ }).withOriginError(inspected.jsError);
883
+ }
884
+ case "jsErrorObject" /* jsErrorObject */: {
885
+ const err2 = err_cast_not_nice.fromContext({
886
+ ["js_error_like_object" /* js_error_like_object */]: inspected
887
+ });
888
+ err2.cause = inspected.jsErrorObject;
889
+ return err2;
890
+ }
891
+ case "nullish" /* nullish */:
892
+ return err_cast_not_nice.fromContext({
893
+ ["nullish_value" /* nullish_value */]: inspected
894
+ });
895
+ case "jsDataType" /* jsDataType */: {
896
+ return err_cast_not_nice.fromContext({
897
+ ["js_data_type" /* js_data_type */]: inspected
898
+ });
899
+ }
900
+ default:
901
+ return err_cast_not_nice.fromContext({
902
+ ["js_other" /* js_other */]: inspected
903
+ });
904
+ }
905
+ };
906
+
907
+ // src/utils/castAndHydrate.ts
908
+ function castAndHydrate(value, niceErrorDefined) {
909
+ const casted = castNiceError(value);
910
+ if (niceErrorDefined.isExact(casted)) {
911
+ return niceErrorDefined.hydrate(casted);
912
+ }
913
+ return casted;
914
+ }
915
+ // src/utils/matchFirst.ts
916
+ function matchFirst(error, handlers) {
917
+ for (const id of error.getIds()) {
918
+ const handler = handlers[id];
919
+ if (typeof handler === "function") {
920
+ const context = error.getContext(id);
921
+ return handler(context);
922
+ }
923
+ }
924
+ if (typeof handlers._ === "function") {
925
+ return handlers._();
926
+ }
927
+ return;
928
+ }
929
+ export {
930
+ msgPack,
931
+ matchFirst,
932
+ isRegularErrorJsonObject,
933
+ isNiceErrorObject,
934
+ forIds,
935
+ forId,
936
+ forDomain,
937
+ err_nice_handler,
938
+ err_nice,
939
+ err_cast_not_nice,
940
+ err,
941
+ defineNiceError,
942
+ causePack,
943
+ castNiceError,
944
+ castAndHydrate,
945
+ NiceErrorHydrated,
946
+ NiceErrorHandler,
947
+ NiceErrorDomain,
948
+ NiceError,
949
+ EErrorPackType,
950
+ EErrorHandlerTargetType,
951
+ EErrId_CastNotNice
952
+ };
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "module": "build/index.js",
5
5
  "types": "build/types/index.d.ts",
6
6
  "type": "module",
7
- "version": "0.2.10",
7
+ "version": "0.2.11",
8
8
  "exports": {
9
9
  ".": {
10
10
  "types": "./build/types/index.d.ts",