@devp0nt/error0 1.0.0-next.47 → 1.0.0-next.49

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 (57) hide show
  1. package/dist/cjs/index.cjs +165 -85
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/cjs/index.d.cts +47 -16
  4. package/dist/cjs/plugins/cause-serialize.cjs +4 -1
  5. package/dist/cjs/plugins/cause-serialize.cjs.map +1 -1
  6. package/dist/cjs/plugins/cause-serialize.d.cts +3 -1
  7. package/dist/cjs/plugins/expected.cjs +7 -2
  8. package/dist/cjs/plugins/expected.cjs.map +1 -1
  9. package/dist/cjs/plugins/expected.d.cts +3 -1
  10. package/dist/cjs/plugins/message-merge.cjs +5 -2
  11. package/dist/cjs/plugins/message-merge.cjs.map +1 -1
  12. package/dist/cjs/plugins/message-merge.d.cts +4 -1
  13. package/dist/cjs/plugins/meta.cjs +7 -2
  14. package/dist/cjs/plugins/meta.cjs.map +1 -1
  15. package/dist/cjs/plugins/meta.d.cts +3 -1
  16. package/dist/cjs/plugins/stack-merge.cjs +6 -3
  17. package/dist/cjs/plugins/stack-merge.cjs.map +1 -1
  18. package/dist/cjs/plugins/stack-merge.d.cts +4 -1
  19. package/dist/cjs/plugins/tags.cjs +7 -2
  20. package/dist/cjs/plugins/tags.cjs.map +1 -1
  21. package/dist/cjs/plugins/tags.d.cts +3 -1
  22. package/dist/esm/index.d.ts +47 -16
  23. package/dist/esm/index.js +165 -85
  24. package/dist/esm/index.js.map +1 -1
  25. package/dist/esm/plugins/cause-serialize.d.ts +3 -1
  26. package/dist/esm/plugins/cause-serialize.js +4 -1
  27. package/dist/esm/plugins/cause-serialize.js.map +1 -1
  28. package/dist/esm/plugins/expected.d.ts +3 -1
  29. package/dist/esm/plugins/expected.js +7 -2
  30. package/dist/esm/plugins/expected.js.map +1 -1
  31. package/dist/esm/plugins/message-merge.d.ts +4 -1
  32. package/dist/esm/plugins/message-merge.js +5 -2
  33. package/dist/esm/plugins/message-merge.js.map +1 -1
  34. package/dist/esm/plugins/meta.d.ts +3 -1
  35. package/dist/esm/plugins/meta.js +7 -2
  36. package/dist/esm/plugins/meta.js.map +1 -1
  37. package/dist/esm/plugins/stack-merge.d.ts +4 -1
  38. package/dist/esm/plugins/stack-merge.js +6 -3
  39. package/dist/esm/plugins/stack-merge.js.map +1 -1
  40. package/dist/esm/plugins/tags.d.ts +3 -1
  41. package/dist/esm/plugins/tags.js +7 -2
  42. package/dist/esm/plugins/tags.js.map +1 -1
  43. package/package.json +1 -1
  44. package/src/index.test.ts +96 -23
  45. package/src/index.ts +229 -101
  46. package/src/plugins/cause-serialize.test.ts +6 -4
  47. package/src/plugins/cause-serialize.ts +13 -9
  48. package/src/plugins/expected.test.ts +4 -4
  49. package/src/plugins/expected.ts +16 -10
  50. package/src/plugins/message-merge.test.ts +3 -3
  51. package/src/plugins/message-merge.ts +17 -13
  52. package/src/plugins/meta.test.ts +2 -2
  53. package/src/plugins/meta.ts +28 -22
  54. package/src/plugins/stack-merge.test.ts +4 -4
  55. package/src/plugins/stack-merge.ts +18 -14
  56. package/src/plugins/tags.test.ts +2 -2
  57. package/src/plugins/tags.ts +24 -18
@@ -99,45 +99,87 @@ class PluginError0 {
99
99
  });
100
100
  }
101
101
  }
102
+ const OWN_SYMBOL = Symbol("Error0.own");
102
103
  class Error0 extends Error {
103
104
  static __pluginsMap;
104
105
  __pluginsMap;
106
+ static MAX_CAUSES_DEPTH = 99;
105
107
  static _plugins = [];
108
+ static _resolvedPlugin;
106
109
  static _emptyPlugin = {
107
110
  props: {},
108
111
  methods: {},
109
112
  adapt: [],
110
113
  stack: void 0,
111
114
  cause: void 0,
112
- message: void 0
115
+ message: void 0,
116
+ propKeys: [],
117
+ propEntries: [],
118
+ methodEntries: []
113
119
  };
120
+ static _indexResolvedPlugin(resolved) {
121
+ return {
122
+ ...resolved,
123
+ propKeys: Object.keys(resolved.props),
124
+ propEntries: Object.entries(resolved.props),
125
+ methodEntries: Object.entries(resolved.methods)
126
+ };
127
+ }
128
+ static _applyPlugin(resolved, plugin) {
129
+ if (plugin.props && "stack" in plugin.props) {
130
+ throw new Error(RESERVED_STACK_PROP_ERROR);
131
+ }
132
+ if (plugin.props && "message" in plugin.props) {
133
+ throw new Error(RESERVED_MESSAGE_PROP_ERROR);
134
+ }
135
+ Object.assign(resolved.props, plugin.props ?? this._emptyPlugin.props);
136
+ Object.assign(resolved.methods, plugin.methods ?? this._emptyPlugin.methods);
137
+ resolved.adapt.push(...plugin.adapt ?? this._emptyPlugin.adapt);
138
+ if (typeof plugin.stack !== "undefined") {
139
+ resolved.stack = plugin.stack;
140
+ }
141
+ if (typeof plugin.cause !== "undefined") {
142
+ resolved.cause = plugin.cause;
143
+ }
144
+ if (typeof plugin.message !== "undefined") {
145
+ resolved.message = plugin.message;
146
+ }
147
+ }
148
+ static _mergeResolvedPlugin(base, plugin) {
149
+ const merged = {
150
+ props: { ...base.props },
151
+ methods: { ...base.methods },
152
+ adapt: [...base.adapt],
153
+ stack: base.stack,
154
+ cause: base.cause,
155
+ message: base.message
156
+ };
157
+ this._applyPlugin(merged, plugin);
158
+ return this._indexResolvedPlugin(merged);
159
+ }
114
160
  static _getResolvedPlugin() {
161
+ if (Object.prototype.hasOwnProperty.call(this, "_resolvedPlugin") && this._resolvedPlugin) {
162
+ return this._resolvedPlugin;
163
+ }
115
164
  const resolved = {
116
165
  props: {},
117
166
  methods: {},
118
- adapt: []
167
+ adapt: [],
168
+ propKeys: [],
169
+ propEntries: [],
170
+ methodEntries: []
119
171
  };
120
172
  for (const plugin of this._plugins) {
121
- if (plugin.props && "stack" in plugin.props) {
122
- throw new Error(RESERVED_STACK_PROP_ERROR);
123
- }
124
- if (plugin.props && "message" in plugin.props) {
125
- throw new Error(RESERVED_MESSAGE_PROP_ERROR);
126
- }
127
- Object.assign(resolved.props, plugin.props ?? this._emptyPlugin.props);
128
- Object.assign(resolved.methods, plugin.methods ?? this._emptyPlugin.methods);
129
- resolved.adapt.push(...plugin.adapt ?? this._emptyPlugin.adapt);
130
- if (typeof plugin.stack !== "undefined") {
131
- resolved.stack = plugin.stack;
132
- }
133
- if (typeof plugin.cause !== "undefined") {
134
- resolved.cause = plugin.cause;
135
- }
136
- if (typeof plugin.message !== "undefined") {
137
- resolved.message = plugin.message;
138
- }
173
+ this._applyPlugin(resolved, plugin);
139
174
  }
140
- return resolved;
175
+ const indexed = this._indexResolvedPlugin(resolved);
176
+ Object.defineProperty(this, "_resolvedPlugin", {
177
+ value: indexed,
178
+ writable: true,
179
+ enumerable: false,
180
+ configurable: true
181
+ });
182
+ return indexed;
141
183
  }
142
184
  constructor(...args) {
143
185
  const [first, second] = args;
@@ -146,37 +188,43 @@ class Error0 extends Error {
146
188
  this.name = "Error0";
147
189
  const ctor = this.constructor;
148
190
  const plugin = ctor._getResolvedPlugin();
149
- for (const [key, prop] of Object.entries(plugin.props)) {
191
+ const ownStore = /* @__PURE__ */ Object.create(null);
192
+ Object.defineProperty(this, OWN_SYMBOL, { value: ownStore, writable: true, enumerable: false, configurable: true });
193
+ for (const [key, prop] of plugin.propEntries) {
150
194
  if (key === "stack") {
151
195
  continue;
152
196
  }
197
+ Object.defineProperty(this, key, {
198
+ get: () => prop.resolve({
199
+ own: ownStore[key],
200
+ flow: this.flow(key),
201
+ error: this
202
+ }),
203
+ set: (value) => {
204
+ ownStore[key] = value;
205
+ },
206
+ enumerable: true,
207
+ configurable: true
208
+ });
153
209
  if (key in input) {
154
210
  const ownValue = input[key];
155
- if (typeof prop.init === "function") {
156
- ;
157
- this[key] = prop.init(ownValue);
158
- } else {
159
- ;
160
- this[key] = ownValue;
161
- }
162
- } else {
163
- Object.defineProperty(this, key, {
164
- get: () => prop.resolve({ own: void 0, flow: this.flow(key), error: this }),
165
- set: (value) => {
166
- Object.defineProperty(this, key, {
167
- value,
168
- writable: true,
169
- enumerable: true,
170
- configurable: true
171
- });
172
- },
173
- enumerable: true,
174
- configurable: true
175
- });
211
+ ownStore[key] = typeof prop.init === "function" ? prop.init(ownValue) : ownValue;
176
212
  }
177
213
  }
178
214
  }
179
- static isSelfProperty = (object, key) => {
215
+ static _getOwnStore(object) {
216
+ const record = object;
217
+ const existing = record[OWN_SYMBOL];
218
+ if (existing && typeof existing === "object") {
219
+ return existing;
220
+ }
221
+ return void 0;
222
+ }
223
+ static isOwnProperty = (object, key) => {
224
+ const ownStore = this._getOwnStore(object);
225
+ if (ownStore && Object.prototype.hasOwnProperty.call(ownStore, key)) {
226
+ return true;
227
+ }
180
228
  const d = Object.getOwnPropertyDescriptor(object, key);
181
229
  if (!d) return false;
182
230
  if (typeof d.get === "function" || typeof d.set === "function") {
@@ -189,22 +237,29 @@ class Error0 extends Error {
189
237
  return true;
190
238
  };
191
239
  static _ownByKey(error, key) {
192
- if (this.isSelfProperty(error, key)) {
240
+ const ownStore = this._getOwnStore(error);
241
+ if (ownStore && Object.prototype.hasOwnProperty.call(ownStore, key)) {
242
+ return ownStore[key];
243
+ }
244
+ if (this.isOwnProperty(error, key)) {
193
245
  return error[key];
194
246
  }
195
247
  return void 0;
196
248
  }
197
249
  static _flowByKey(error, key) {
198
- return this.causes(error, true).map((cause) => {
199
- return this._ownByKey(cause, key);
200
- });
250
+ const causes = this.causes(error, true);
251
+ const values = new Array(causes.length);
252
+ for (let i = 0; i < causes.length; i += 1) {
253
+ values[i] = this._ownByKey(causes[i], key);
254
+ }
255
+ return values;
201
256
  }
202
257
  static own(error, key) {
203
258
  const error0 = this.from(error);
204
259
  if (key === void 0) {
205
260
  const ownValues = {};
206
261
  const plugin = this._getResolvedPlugin();
207
- for (const ownKey of Object.keys(plugin.props)) {
262
+ for (const ownKey of plugin.propKeys) {
208
263
  ownValues[ownKey] = this._ownByKey(error0, ownKey);
209
264
  }
210
265
  return ownValues;
@@ -226,29 +281,34 @@ class Error0 extends Error {
226
281
  const ctor = this.constructor;
227
282
  return ctor._flowByKey(this, key);
228
283
  }
284
+ static _resolveByKey(error, key, plugin) {
285
+ try {
286
+ const options = {
287
+ get own() {
288
+ return error.own(key);
289
+ },
290
+ get flow() {
291
+ return error.flow(key);
292
+ },
293
+ error
294
+ };
295
+ const prop = plugin.props[key];
296
+ const resolver = prop.resolve;
297
+ if (!resolver) {
298
+ return error[key];
299
+ }
300
+ return resolver(options);
301
+ } catch {
302
+ console.error(`Error0: failed to resolve property ${key}`, error);
303
+ return void 0;
304
+ }
305
+ }
229
306
  static resolve(error) {
230
307
  const error0 = this.from(error);
231
308
  const resolved = {};
232
309
  const plugin = this._getResolvedPlugin();
233
- for (const [key, prop] of Object.entries(plugin.props)) {
234
- try {
235
- const options = Object.defineProperties(
236
- {
237
- error: error0
238
- },
239
- {
240
- own: {
241
- get: () => error0.own(key)
242
- },
243
- flow: {
244
- get: () => error0.flow(key)
245
- }
246
- }
247
- );
248
- resolved[key] = prop.resolve(options);
249
- } catch {
250
- console.error(`Error0: failed to resolve property ${key}`, error0);
251
- }
310
+ for (const key of plugin.propKeys) {
311
+ resolved[key] = this._resolveByKey(error0, key, plugin);
252
312
  }
253
313
  return resolved;
254
314
  }
@@ -259,9 +319,9 @@ class Error0 extends Error {
259
319
  static causes(error, instancesOnly) {
260
320
  const causes = [];
261
321
  let current = error;
262
- const maxDepth = 99;
263
322
  const seen = /* @__PURE__ */ new Set();
264
- for (let depth = 0; depth < maxDepth; depth += 1) {
323
+ let depth = 0;
324
+ while (depth < this.MAX_CAUSES_DEPTH) {
265
325
  if (seen.has(current)) {
266
326
  break;
267
327
  }
@@ -273,6 +333,7 @@ class Error0 extends Error {
273
333
  break;
274
334
  }
275
335
  current = current.cause;
336
+ depth += 1;
276
337
  }
277
338
  return causes;
278
339
  }
@@ -298,6 +359,9 @@ class Error0 extends Error {
298
359
  }
299
360
  return this._fromNonError0(error);
300
361
  }
362
+ static round(error, isPublic = false) {
363
+ return this.from(this.serialize(error, isPublic));
364
+ }
301
365
  static _applyAdapt(error) {
302
366
  const plugin = this._getResolvedPlugin();
303
367
  for (const adapt of plugin.adapt) {
@@ -316,8 +380,7 @@ class Error0 extends Error {
316
380
  const errorRecord = error;
317
381
  const recreated = new this(message);
318
382
  const plugin = this._getResolvedPlugin();
319
- const propsEntries = Object.entries(plugin.props);
320
- for (const [key, prop] of propsEntries) {
383
+ for (const [key, prop] of plugin.propEntries) {
321
384
  if (prop.deserialize === false) {
322
385
  continue;
323
386
  }
@@ -325,7 +388,7 @@ class Error0 extends Error {
325
388
  continue;
326
389
  }
327
390
  try {
328
- const value = prop.deserialize({ value: errorRecord[key], serialized: errorRecord });
391
+ const value = prop.deserialize({ value: errorRecord[key], record: errorRecord });
329
392
  recreated[key] = value;
330
393
  } catch {
331
394
  console.error(`Error0: failed to deserialize property ${key}`, errorRecord);
@@ -368,8 +431,9 @@ class Error0 extends Error {
368
431
  const Error0Extended = class Error0 extends Base {
369
432
  };
370
433
  Error0Extended._plugins = [...Base._plugins, plugin];
371
- const resolved = Error0Extended._getResolvedPlugin();
372
- for (const [key, method] of Object.entries(resolved.methods)) {
434
+ const resolved = this._mergeResolvedPlugin(Base._getResolvedPlugin(), plugin);
435
+ Error0Extended._resolvedPlugin = resolved;
436
+ for (const [key, method] of resolved.methodEntries) {
373
437
  Object.defineProperty(Error0Extended.prototype, key, {
374
438
  value: function(...args) {
375
439
  return method(this, ...args);
@@ -468,9 +532,8 @@ class Error0 extends Error {
468
532
  }
469
533
  static serialize(error, isPublic = true) {
470
534
  const error0 = this.from(error);
471
- const resolvedProps = this.resolve(error0);
472
- const resolvedRecord = resolvedProps;
473
535
  const plugin = this._getResolvedPlugin();
536
+ const resolveByKey = (targetError, key, targetPlugin) => this._resolveByKey(targetError, key, targetPlugin);
474
537
  const messagePlugin = plugin.message;
475
538
  let serializedMessage = error0.message;
476
539
  try {
@@ -482,24 +545,37 @@ class Error0 extends Error {
482
545
  serializedMessage = error0.message;
483
546
  }
484
547
  const json = {
485
- name: error0.name,
486
- message: serializedMessage
548
+ name: error0.name
487
549
  // we do not serialize causes, it is enough that we have floated props and adapt helper
488
550
  // cause: error0.cause,
489
551
  };
490
- const propsEntries = Object.entries(plugin.props);
491
- for (const [key, prop] of propsEntries) {
552
+ if (serializedMessage !== void 0) {
553
+ json.message = serializedMessage;
554
+ }
555
+ for (const [key, prop] of plugin.propEntries) {
492
556
  if (prop.serialize === false) {
493
557
  continue;
494
558
  }
495
559
  try {
496
- const value = resolvedRecord[key];
497
- const jsonValue = prop.serialize({ value, error: error0, isPublic });
560
+ const options = {
561
+ get own() {
562
+ return error0.own(key);
563
+ },
564
+ get flow() {
565
+ return error0.flow(key);
566
+ },
567
+ get resolved() {
568
+ return resolveByKey(error0, key, plugin);
569
+ },
570
+ error: error0,
571
+ isPublic
572
+ };
573
+ const jsonValue = prop.serialize(options);
498
574
  if (jsonValue !== void 0) {
499
575
  json[key] = jsonValue;
500
576
  }
501
577
  } catch {
502
- console.error(`Error0: failed to serialize property ${key}`, resolvedRecord);
578
+ console.error(`Error0: failed to serialize property ${key}`, error0);
503
579
  }
504
580
  }
505
581
  const stackPlugin = plugin.stack;
@@ -531,12 +607,16 @@ class Error0 extends Error {
531
607
  console.error("Error0: failed to serialize cause", error0);
532
608
  }
533
609
  }
534
- return Object.fromEntries(Object.entries(json).filter(([, value]) => value !== void 0));
610
+ return json;
535
611
  }
536
612
  serialize(isPublic = true) {
537
613
  const ctor = this.constructor;
538
614
  return ctor.serialize(this, isPublic);
539
615
  }
616
+ round(isPublic = true) {
617
+ const ctor = this.constructor;
618
+ return ctor.round(this, isPublic);
619
+ }
540
620
  }
541
621
  // Annotate the CommonJS export names for ESM import in node:
542
622
  0 && (module.exports = {