@devp0nt/error0 1.0.0-next.52 → 1.0.0-next.54

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.
@@ -1,12 +1,80 @@
1
- import { PluginError0, ErrorPluginPropOptions, Error0 } from '../index.js';
1
+ import { PluginError0, Error0 } from '../index.js';
2
2
 
3
3
  declare const tagsPlugin: <TTag extends string>({ isPublic, tags, strict, }?: {
4
4
  isPublic?: boolean;
5
5
  tags?: TTag[] | readonly TTag[];
6
6
  strict?: boolean;
7
- }) => PluginError0<Record<never, never> & Record<"tags", ErrorPluginPropOptions<string[], string[], Error0, string[] | undefined>>, Record<never, never> & Record<"hasTag", {
8
- (error: Error0, tag: TTag): boolean;
9
- (error: Error0, tag: TTag[], policy: "every" | "some"): boolean;
10
- }>>;
7
+ }) => PluginError0<Record<never, never> & Record<"tags", ({
8
+ resolve: (options: {
9
+ own: string[] | undefined;
10
+ flow: (string[] | undefined)[];
11
+ error: Error0;
12
+ }) => string[] | undefined;
13
+ serialize: false | ((options: {
14
+ own: string[] | undefined;
15
+ flow: (string[] | undefined)[];
16
+ resolved: string[] | undefined;
17
+ error: Error0;
18
+ isPublic: boolean;
19
+ }) => unknown);
20
+ deserialize: false | ((options: {
21
+ value: unknown;
22
+ record: Record<string, unknown>;
23
+ }) => string[] | undefined);
24
+ } & {
25
+ init: ((input: string[]) => string[]) | (() => string[]);
26
+ }) | ({
27
+ resolve: (options: {
28
+ own: string[] | undefined;
29
+ flow: (string[] | undefined)[];
30
+ error: Error0;
31
+ }) => string[] | undefined;
32
+ serialize: false | ((options: {
33
+ own: string[] | undefined;
34
+ flow: (string[] | undefined)[];
35
+ resolved: string[] | undefined;
36
+ error: Error0;
37
+ isPublic: boolean;
38
+ }) => unknown);
39
+ deserialize: false | ((options: {
40
+ value: unknown;
41
+ record: Record<string, unknown>;
42
+ }) => string[] | undefined);
43
+ } & {
44
+ init?: undefined;
45
+ })>, Record<never, never> & Record<"hasTag", (error: Error0 & {
46
+ tags: string[] | undefined;
47
+ } & {} & {
48
+ resolve: () => {
49
+ tags: string[] | undefined;
50
+ };
51
+ } & {
52
+ own?: Partial<{
53
+ tags: string[] | undefined;
54
+ }> | undefined;
55
+ flow: <TKey extends "tags">(key: TKey) => {
56
+ tags: string[] | undefined;
57
+ }[TKey][];
58
+ assign: (props: Partial<{
59
+ tags: string[] | undefined;
60
+ }>) => Error0 & {
61
+ tags: string[] | undefined;
62
+ } & {} & {
63
+ resolve: () => {
64
+ tags: string[] | undefined;
65
+ };
66
+ };
67
+ } & {
68
+ readonly __pluginsMap?: {
69
+ props: {
70
+ tags: {
71
+ init: string[] | undefined;
72
+ output: string[];
73
+ resolve: string[] | undefined;
74
+ };
75
+ };
76
+ methods: {};
77
+ } | undefined;
78
+ }, tag: TTag | TTag[], policy?: "every" | "some") => boolean>>;
11
79
 
12
80
  export { tagsPlugin };
@@ -4,19 +4,6 @@ const tagsPlugin = ({
4
4
  tags,
5
5
  strict = true
6
6
  } = {}) => {
7
- function hasTag(error, tag, policy) {
8
- const tags2 = error.tags;
9
- if (!tags2) {
10
- return false;
11
- }
12
- if (Array.isArray(tag)) {
13
- if (policy === "every") {
14
- return tag.every((item) => tags2.includes(item));
15
- }
16
- return tag.some((item) => tags2.includes(item));
17
- }
18
- return tags2.includes(tag);
19
- }
20
7
  const isTag = (value) => typeof value === "string" && (!tags || !strict || tags.includes(value));
21
8
  return Error0.plugin().prop("tags", {
22
9
  init: (input) => input,
@@ -41,7 +28,19 @@ const tagsPlugin = ({
41
28
  }
42
29
  return value.filter((item) => isTag(item));
43
30
  }
44
- }).method("hasTag", hasTag);
31
+ }).method("hasTag", (error, tag, policy = "every") => {
32
+ const tags2 = error.tags;
33
+ if (!tags2) {
34
+ return false;
35
+ }
36
+ if (Array.isArray(tag)) {
37
+ if (policy === "every") {
38
+ return tag.every((item) => tags2.includes(item));
39
+ }
40
+ return tag.some((item) => tags2.includes(item));
41
+ }
42
+ return tags2.includes(tag);
43
+ });
45
44
  };
46
45
  export {
47
46
  tagsPlugin
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/plugins/tags.ts"],"sourcesContent":["import { Error0 } from '../index.js'\n\nexport const tagsPlugin = <TTag extends string>({\n isPublic = false,\n tags,\n strict = true,\n}: { isPublic?: boolean; tags?: TTag[] | readonly TTag[]; strict?: boolean } = {}) => {\n function hasTag(error: Error0, tag: TTag): boolean\n function hasTag(error: Error0, tag: TTag[], policy: 'every' | 'some'): boolean\n function hasTag(error: Error0, tag: TTag | TTag[], policy?: 'every' | 'some'): boolean {\n const tags = (error as any).tags as string[] | undefined\n if (!tags) {\n return false\n }\n if (Array.isArray(tag)) {\n if (policy === 'every') {\n return tag.every((item) => tags.includes(item))\n }\n return tag.some((item) => tags.includes(item))\n }\n return tags.includes(tag)\n }\n const isTag = (value: unknown): value is TTag =>\n typeof value === 'string' && (!tags || !strict || tags.includes(value as TTag))\n return Error0.plugin()\n .prop('tags', {\n init: (input: string[]) => input,\n resolve: ({ flow }) => {\n const merged: string[] = []\n for (const value of flow) {\n if (Array.isArray(value)) {\n merged.push(...value)\n }\n }\n return merged.length > 0 ? Array.from(new Set(merged)) : undefined\n },\n serialize: ({ resolved, isPublic: _isPublic }) => {\n if (!isPublic && _isPublic) {\n return undefined\n }\n return resolved\n },\n deserialize: ({ value }) => {\n if (!Array.isArray(value)) {\n return undefined\n }\n return value.filter((item) => isTag(item))\n },\n })\n .method('hasTag', hasTag)\n}\n"],"mappings":"AAAA,SAAS,cAAc;AAEhB,MAAM,aAAa,CAAsB;AAAA,EAC9C,WAAW;AAAA,EACX;AAAA,EACA,SAAS;AACX,IAA+E,CAAC,MAAM;AAGpF,WAAS,OAAO,OAAe,KAAoB,QAAoC;AACrF,UAAMA,QAAQ,MAAc;AAC5B,QAAI,CAACA,OAAM;AACT,aAAO;AAAA,IACT;AACA,QAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,UAAI,WAAW,SAAS;AACtB,eAAO,IAAI,MAAM,CAAC,SAASA,MAAK,SAAS,IAAI,CAAC;AAAA,MAChD;AACA,aAAO,IAAI,KAAK,CAAC,SAASA,MAAK,SAAS,IAAI,CAAC;AAAA,IAC/C;AACA,WAAOA,MAAK,SAAS,GAAG;AAAA,EAC1B;AACA,QAAM,QAAQ,CAAC,UACb,OAAO,UAAU,aAAa,CAAC,QAAQ,CAAC,UAAU,KAAK,SAAS,KAAa;AAC/E,SAAO,OAAO,OAAO,EAClB,KAAK,QAAQ;AAAA,IACZ,MAAM,CAAC,UAAoB;AAAA,IAC3B,SAAS,CAAC,EAAE,KAAK,MAAM;AACrB,YAAM,SAAmB,CAAC;AAC1B,iBAAW,SAAS,MAAM;AACxB,YAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,iBAAO,KAAK,GAAG,KAAK;AAAA,QACtB;AAAA,MACF;AACA,aAAO,OAAO,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,IAAI;AAAA,IAC3D;AAAA,IACA,WAAW,CAAC,EAAE,UAAU,UAAU,UAAU,MAAM;AAChD,UAAI,CAAC,YAAY,WAAW;AAC1B,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA,IACA,aAAa,CAAC,EAAE,MAAM,MAAM;AAC1B,UAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,eAAO;AAAA,MACT;AACA,aAAO,MAAM,OAAO,CAAC,SAAS,MAAM,IAAI,CAAC;AAAA,IAC3C;AAAA,EACF,CAAC,EACA,OAAO,UAAU,MAAM;AAC5B;","names":["tags"]}
1
+ {"version":3,"sources":["../../../src/plugins/tags.ts"],"sourcesContent":["import { Error0 } from '../index.js'\n\nexport const tagsPlugin = <TTag extends string>({\n isPublic = false,\n tags,\n strict = true,\n}: { isPublic?: boolean; tags?: TTag[] | readonly TTag[]; strict?: boolean } = {}) => {\n // function hasTag(error: Error0, tag: TTag): boolean\n // function hasTag(error: Error0, tag: TTag[], policy: 'every' | 'some'): boolean\n // function hasTag(error: Error0, tag: TTag | TTag[], policy?: 'every' | 'some'): boolean {\n // const tags = (error as any).tags as string[] | undefined\n // if (!tags) {\n // return false\n // }\n // if (Array.isArray(tag)) {\n // if (policy === 'every') {\n // return tag.every((item) => tags.includes(item))\n // }\n // return tag.some((item) => tags.includes(item))\n // }\n // return tags.includes(tag)\n // }\n const isTag = (value: unknown): value is TTag =>\n typeof value === 'string' && (!tags || !strict || tags.includes(value as TTag))\n return Error0.plugin()\n .prop('tags', {\n init: (input: string[]) => input,\n resolve: ({ flow }) => {\n const merged: string[] = []\n for (const value of flow) {\n if (Array.isArray(value)) {\n merged.push(...value)\n }\n }\n return merged.length > 0 ? Array.from(new Set(merged)) : undefined\n },\n serialize: ({ resolved, isPublic: _isPublic }) => {\n if (!isPublic && _isPublic) {\n return undefined\n }\n return resolved\n },\n deserialize: ({ value }) => {\n if (!Array.isArray(value)) {\n return undefined\n }\n return value.filter((item) => isTag(item))\n },\n })\n .method('hasTag', (error, tag: TTag | TTag[], policy: 'every' | 'some' = 'every'): boolean => {\n const tags = error.tags\n if (!tags) {\n return false\n }\n if (Array.isArray(tag)) {\n if (policy === 'every') {\n return tag.every((item) => tags.includes(item))\n }\n return tag.some((item) => tags.includes(item))\n }\n return tags.includes(tag)\n })\n}\n"],"mappings":"AAAA,SAAS,cAAc;AAEhB,MAAM,aAAa,CAAsB;AAAA,EAC9C,WAAW;AAAA,EACX;AAAA,EACA,SAAS;AACX,IAA+E,CAAC,MAAM;AAgBpF,QAAM,QAAQ,CAAC,UACb,OAAO,UAAU,aAAa,CAAC,QAAQ,CAAC,UAAU,KAAK,SAAS,KAAa;AAC/E,SAAO,OAAO,OAAO,EAClB,KAAK,QAAQ;AAAA,IACZ,MAAM,CAAC,UAAoB;AAAA,IAC3B,SAAS,CAAC,EAAE,KAAK,MAAM;AACrB,YAAM,SAAmB,CAAC;AAC1B,iBAAW,SAAS,MAAM;AACxB,YAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,iBAAO,KAAK,GAAG,KAAK;AAAA,QACtB;AAAA,MACF;AACA,aAAO,OAAO,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,IAAI;AAAA,IAC3D;AAAA,IACA,WAAW,CAAC,EAAE,UAAU,UAAU,UAAU,MAAM;AAChD,UAAI,CAAC,YAAY,WAAW;AAC1B,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA,IACA,aAAa,CAAC,EAAE,MAAM,MAAM;AAC1B,UAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,eAAO;AAAA,MACT;AACA,aAAO,MAAM,OAAO,CAAC,SAAS,MAAM,IAAI,CAAC;AAAA,IAC3C;AAAA,EACF,CAAC,EACA,OAAO,UAAU,CAAC,OAAO,KAAoB,SAA2B,YAAqB;AAC5F,UAAMA,QAAO,MAAM;AACnB,QAAI,CAACA,OAAM;AACT,aAAO;AAAA,IACT;AACA,QAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,UAAI,WAAW,SAAS;AACtB,eAAO,IAAI,MAAM,CAAC,SAASA,MAAK,SAAS,IAAI,CAAC;AAAA,MAChD;AACA,aAAO,IAAI,KAAK,CAAC,SAASA,MAAK,SAAS,IAAI,CAAC;AAAA,IAC/C;AACA,WAAOA,MAAK,SAAS,GAAG;AAAA,EAC1B,CAAC;AACL;","names":["tags"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devp0nt/error0",
3
- "version": "1.0.0-next.52",
3
+ "version": "1.0.0-next.54",
4
4
  "license": "MIT",
5
5
  "author": {
6
6
  "name": "Sergei Dmitriev",
@@ -83,6 +83,7 @@
83
83
  "types:build": "tsc --noEmit --project tsconfig.build.json",
84
84
  "types:dev": "tsc --noEmit",
85
85
  "types": "bun run types:dev",
86
+ "typesgo": "tsgo --noEmit",
86
87
  "pack:dry": "npm pack --dry-run",
87
88
  "pack:dist": "mkdir -p dist-npm && npm pack --pack-destination dist-npm --silent && cd dist-npm && tar -xzf *.tgz && cp -r package/* . && rm -rf package && rm *.tgz",
88
89
  "pack:dist:hard": "rimraf dist-npm && bun run pack:dist",
@@ -109,6 +110,7 @@
109
110
  "eslint-config-love": "^130.0.0",
110
111
  "eslint-config-prettier": "^10.1.8",
111
112
  "eslint-plugin-no-only-tests": "^3.3.0",
113
+ "@typescript/native-preview": "^7.0.0-dev.20260219.1",
112
114
  "husky": "^9.1.7",
113
115
  "lint-staged": "^16.2.1",
114
116
  "lodash": "^4.17.21",
@@ -117,7 +119,7 @@
117
119
  "semantic-release": "^25.0.2",
118
120
  "tsc-watch": "^7.1.1",
119
121
  "tsup": "^8.0.0",
120
- "typescript": "^5.0.0"
122
+ "typescript": "^5.9.3"
121
123
  },
122
124
  "engines": {
123
125
  "node": ">=18.0.0",
package/src/index.test.ts CHANGED
@@ -186,10 +186,192 @@ describe('Error0', () => {
186
186
  })
187
187
  const error = new AppError('another error', { status: 400 })
188
188
  expect(error.status).toBe(500)
189
- expect(error.own('status')).toBe(400)
189
+ expectTypeOf<typeof error.status>().toEqualTypeOf<number>()
190
+ expect(error.own?.status).toBe(400)
190
191
  expect(error.flow('status')).toEqual([400])
191
192
  })
192
193
 
194
+ it('without resolve, getter return own value, also resolved value eq to own value', () => {
195
+ const AppError = Error0.use('prop', 'status', {
196
+ init: (input: number) => input,
197
+ serialize: ({ resolved }) => resolved,
198
+ deserialize: ({ value }) => (typeof value === 'number' ? value : undefined),
199
+ })
200
+ const error = new AppError('another error', { status: 400 })
201
+ expect(error.status).toBe(400)
202
+ expectTypeOf<typeof error.status>().toEqualTypeOf<number | undefined>()
203
+ expect(error.own?.status).toBe(400)
204
+ expect(error.flow('status')).toEqual([400])
205
+ expect(error.serialize().status).toEqual(400)
206
+ })
207
+
208
+ it('without resolve (as false), getter return own value, also resolved value eq to own value', () => {
209
+ const AppError = Error0.use('prop', 'status', {
210
+ init: (input: number) => input,
211
+ resolve: false,
212
+ serialize: ({ resolved }) => resolved,
213
+ deserialize: ({ value }) => (typeof value === 'number' ? value : undefined),
214
+ })
215
+ const error = new AppError('another error', { status: 400 })
216
+ expect(error.status).toBe(400)
217
+ expectTypeOf<typeof error.status>().toEqualTypeOf<number | undefined>()
218
+ expect(error.own?.status).toBe(400)
219
+ expect(error.flow('status')).toEqual([400])
220
+ expect(error.serialize().status).toEqual(400)
221
+ })
222
+
223
+ it('with resolve true, getter return first not undefined in flow', () => {
224
+ const AppError = Error0.use('prop', 'status', {
225
+ init: (input: number) => input,
226
+ resolve: true,
227
+ serialize: ({ resolved }) => resolved,
228
+ deserialize: ({ value }) => (typeof value === 'number' ? value : undefined),
229
+ })
230
+ const cause = new AppError('another error', { status: 400 })
231
+ const error = new AppError('test', { cause })
232
+ expect(error.status).toBe(400)
233
+ expectTypeOf<typeof error.status>().toEqualTypeOf<number | undefined>()
234
+ expect(error.own?.status).toBe(undefined)
235
+ expect(error.flow('status')).toEqual([undefined, 400])
236
+ expect(error.serialize().status).toEqual(400)
237
+ })
238
+
239
+ it('(plugin) without resolve, getter return own value, also resolved value eq to own value', () => {
240
+ const statusPlugin = Error0.plugin().prop('status', {
241
+ init: (input: number) => input,
242
+ serialize: ({ resolved }) => resolved,
243
+ deserialize: ({ value }) => (typeof value === 'number' ? value : undefined),
244
+ })
245
+ const AppError = Error0.use(statusPlugin)
246
+ const error = new AppError('another error', { status: 400 })
247
+ expect(error.status).toBe(400)
248
+ expectTypeOf<typeof error.status>().toEqualTypeOf<number | undefined>()
249
+ expect(error.own?.status).toBe(400)
250
+ expect(error.flow('status')).toEqual([400])
251
+ expect(error.serialize().status).toEqual(400)
252
+ })
253
+
254
+ it('(plugin) without resolve (as false), getter return own value, also resolved value eq to own value', () => {
255
+ const statusPlugin = Error0.plugin().prop('status', {
256
+ init: (input: number) => input,
257
+ resolve: false,
258
+ serialize: ({ resolved }) => resolved,
259
+ deserialize: ({ value }) => (typeof value === 'number' ? value : undefined),
260
+ })
261
+ const AppError = Error0.use(statusPlugin)
262
+ const error = new AppError('another error', { status: 400 })
263
+ expect(error.status).toBe(400)
264
+ expectTypeOf<typeof error.status>().toEqualTypeOf<number | undefined>()
265
+ expect(error.own?.status).toBe(400)
266
+ expect(error.flow('status')).toEqual([400])
267
+ expect(error.serialize().status).toEqual(400)
268
+ })
269
+
270
+ it('without serailize and deserialize value will not be serialized', () => {
271
+ const AppError = Error0.use('prop', 'status', {
272
+ init: (input: number) => input,
273
+ resolve: true,
274
+ })
275
+ const cause = new AppError('another error', { status: 400 })
276
+ const error = new AppError('test', { cause })
277
+ expect(error.status).toBe(400)
278
+ expectTypeOf<typeof error.status>().toEqualTypeOf<number | undefined>()
279
+ expect(error.own?.status).toBe(undefined)
280
+ expect(error.flow('status')).toEqual([undefined, 400])
281
+ expect(error.serialize().status).toEqual(undefined)
282
+ })
283
+
284
+ it('(plugin) with resolve true, getter return first not undefined in flow', () => {
285
+ const statusPlugin = Error0.plugin().prop('status', {
286
+ init: (input: number) => input,
287
+ resolve: true,
288
+ serialize: ({ resolved }) => resolved,
289
+ deserialize: ({ value }) => (typeof value === 'number' ? value : undefined),
290
+ })
291
+ const AppError = Error0.use(statusPlugin)
292
+ const cause = new AppError('another error', { status: 400 })
293
+ const error = new AppError('test', { cause })
294
+ expect(error.status).toBe(400)
295
+ expectTypeOf<typeof error.status>().toEqualTypeOf<number | undefined>()
296
+ expect(error.own?.status).toBe(undefined)
297
+ expect(error.flow('status')).toEqual([undefined, 400])
298
+ expect(error.serialize().status).toEqual(400)
299
+ })
300
+
301
+ it('assign props check types', () => {
302
+ const AppError = Error0.use(statusPlugin).use(codePlugin)
303
+ const error = new AppError('test', { status: 401 })
304
+ // @ts-expect-error - code is not match desirecd type
305
+ error.assign({ code: 'NOT_VALID_CODE' })
306
+ })
307
+
308
+ it('assign props', () => {
309
+ const AppError = Error0.use(statusPlugin).use(codePlugin)
310
+ const error = new AppError('test', { status: 401 })
311
+ const error2 = error.assign({ code: 'NOT_FOUND' })
312
+ expect(error).toBe(error2)
313
+ expect(error2.status).toBe(401)
314
+ expect(error2.code).toBe('NOT_FOUND')
315
+ })
316
+
317
+ it('static assign props check types', () => {
318
+ const AppError = Error0.use(statusPlugin).use(codePlugin)
319
+ const error = new AppError('test', { status: 401 })
320
+ AppError.assign(
321
+ error,
322
+ // @ts-expect-error - code is not match desirecd type
323
+ { code: 'NOT_VALID_CODE' },
324
+ )
325
+ })
326
+
327
+ it('static assign props', () => {
328
+ const AppError = Error0.use(statusPlugin).use(codePlugin)
329
+ const error = new AppError('test', { status: 401 })
330
+ const error2 = AppError.assign(error, { code: 'NOT_FOUND' })
331
+ expect(error).toBe(error2)
332
+ expect(error2.status).toBe(401)
333
+ expect(error2.code).toBe('NOT_FOUND')
334
+ })
335
+
336
+ // it('form, assing, round, flat, and new, return same type and instance', () => {
337
+ it('form, assing, round, and new, return same type and instance', () => {
338
+ const AppError = Error0.use(statusPlugin).use(codePlugin)
339
+ const errorNew = new AppError('test', { status: 401 })
340
+ const errorAssign = AppError.assign({}, { status: 401 })
341
+ const errorAssign1 = errorNew.assign({})
342
+ const errorFrom = AppError.from({})
343
+ const errorRound = AppError.round({})
344
+ const errorRound1 = errorNew.round()
345
+ // const errorFlat = AppError.flat({})
346
+ // const errorFlat1 = errorNew.flat()
347
+ expect(errorNew).toBeInstanceOf(AppError)
348
+ expect(errorAssign).toBeInstanceOf(AppError)
349
+ expect(errorAssign1).toBeInstanceOf(AppError)
350
+ expect(errorFrom).toBeInstanceOf(AppError)
351
+ expect(errorRound).toBeInstanceOf(AppError)
352
+ expect(errorRound1).toBeInstanceOf(AppError)
353
+ // expect(errorFlat).toBeInstanceOf(AppError)
354
+ // expect(errorFlat1).toBeInstanceOf(AppError)
355
+ expectTypeOf<typeof errorNew>().toEqualTypeOf<typeof errorAssign>()
356
+ expectTypeOf<typeof errorNew>().toEqualTypeOf<typeof errorAssign1>()
357
+ expectTypeOf<typeof errorNew>().toEqualTypeOf<typeof errorFrom>()
358
+ expectTypeOf<typeof errorNew>().toEqualTypeOf<typeof errorRound>()
359
+ expectTypeOf<typeof errorNew>().toEqualTypeOf<typeof errorRound1>()
360
+ // expectTypeOf<typeof errorNew>().toEqualTypeOf<typeof errorFlat>()
361
+ // expectTypeOf<typeof errorNew>().toEqualTypeOf<typeof errorFlat1>()
362
+ })
363
+
364
+ // it.only('flat merge all resolved values to own and remove causes', () => {
365
+ // const AppError = Error0.use(statusPlugin).use(codePlugin)
366
+ // const errorDeepDeep = new AppError('test deep deep', { status: 401 })
367
+ // const errorDeep = new AppError('test deep', { code: 'NOT_FOUND', cause: errorDeepDeep })
368
+ // const error = new AppError('test', { status: 401, cause: errorDeep })
369
+ // const flat = error.flat()
370
+ // expect(flat.own).toEqual({ status: 401, code: 'NOT_FOUND' })
371
+ // expect(flat.cause).toBeUndefined()
372
+ // console.error(flat)
373
+ // })
374
+
193
375
  it('serialize uses identity by default and skips undefined plugin values', () => {
194
376
  const AppError = Error0.use(statusPlugin).use('prop', 'code', {
195
377
  init: (input: string) => input,
@@ -412,7 +594,7 @@ describe('Error0', () => {
412
594
  expect(error.code).toBe(500)
413
595
  expect(AppError.own(error, 'code')).toBe(undefined)
414
596
  expect(AppError.own(error)).toEqual({ code: undefined })
415
- expect(error.own()).toEqual({ code: undefined })
597
+ expect(error.own).toEqual(undefined)
416
598
  expectTypeOf<typeof error.code>().toEqualTypeOf<number>()
417
599
  expectTypeOf(AppError.own(error, 'code')).toEqualTypeOf<number | 'fallback' | undefined>()
418
600
  expectTypeOf(AppError.own(error)).toEqualTypeOf<{ code: number | 'fallback' | undefined }>()
@@ -438,7 +620,7 @@ describe('Error0', () => {
438
620
  const mid = new AppError('mid', { cause: root })
439
621
  const leaf = new AppError('leaf', { status: 500, cause: mid })
440
622
 
441
- expect(leaf.own()).toEqual({ status: 500, code: undefined })
623
+ expect(leaf.own).toEqual({ status: 500, code: undefined })
442
624
  expect(AppError.own(leaf)).toEqual({ status: 500, code: undefined })
443
625
  expect(leaf.flow('status')).toEqual([500, undefined, 400])
444
626
  expect(AppError.flow(leaf, 'status')).toEqual([500, undefined, 400])
@@ -463,8 +645,8 @@ describe('Error0', () => {
463
645
 
464
646
  const error = new AppError('test', { status: 400, code: 'A' })
465
647
 
466
- expectTypeOf(error.own('status')).toEqualTypeOf<number | undefined>()
467
- expectTypeOf(error.own('code')).toEqualTypeOf<Code | undefined>()
648
+ expectTypeOf(error.own?.status).toEqualTypeOf<number | undefined>()
649
+ expectTypeOf(error.own?.code).toEqualTypeOf<Code | undefined>()
468
650
 
469
651
  expectTypeOf(AppError.own(error, 'status')).toEqualTypeOf<number | undefined>()
470
652
  expectTypeOf(AppError.own(error, 'code')).toEqualTypeOf<Code | undefined>()