@cluesurf/kink 1.0.8 → 1.2.2

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 (55) hide show
  1. package/code/base/index.ts +223 -0
  2. package/code/index.ts +7 -0
  3. package/code/site/index.ts +92 -0
  4. package/code/site/kink.ts +97 -0
  5. package/code/site/make.ts +17 -0
  6. package/code/site/test.ts +35 -0
  7. package/code/tree/browser.ts +20 -0
  8. package/code/tree/index.ts +1 -0
  9. package/code/tree/make.ts +347 -0
  10. package/code/tree/node.ts +99 -0
  11. package/code/tree/test.ts +51 -0
  12. package/eslint.config.ts +3 -0
  13. package/host/code/base/index.js +138 -0
  14. package/host/code/base/index.js.map +1 -0
  15. package/host/code/index.d.ts +5 -0
  16. package/host/code/index.js +6 -0
  17. package/host/code/index.js.map +1 -0
  18. package/host/code/site/index.d.ts +7 -0
  19. package/host/code/site/index.js +75 -0
  20. package/host/code/site/index.js.map +1 -0
  21. package/host/code/site/kink.d.ts +31 -0
  22. package/host/code/site/kink.js +41 -0
  23. package/host/code/site/kink.js.map +1 -0
  24. package/host/code/site/make.d.ts +1 -0
  25. package/host/code/site/make.js +18 -0
  26. package/host/code/site/make.js.map +1 -0
  27. package/host/code/site/test.d.ts +7 -0
  28. package/host/code/site/test.js +23 -0
  29. package/host/code/site/test.js.map +1 -0
  30. package/host/code/tree/browser.d.ts +6 -0
  31. package/host/code/tree/browser.js +17 -0
  32. package/host/code/tree/browser.js.map +1 -0
  33. package/host/code/tree/index.d.ts +1 -0
  34. package/host/code/tree/index.js +2 -0
  35. package/host/code/tree/index.js.map +1 -0
  36. package/host/code/tree/make.d.ts +30 -0
  37. package/host/code/tree/make.js +271 -0
  38. package/host/code/tree/make.js.map +1 -0
  39. package/host/code/tree/node.d.ts +6 -0
  40. package/host/code/tree/node.js +81 -0
  41. package/host/code/tree/node.js.map +1 -0
  42. package/host/code/tree/test.d.ts +7 -0
  43. package/host/code/tree/test.js +37 -0
  44. package/host/code/tree/test.js.map +1 -0
  45. package/host/test/index.d.ts +2 -0
  46. package/host/test/index.js +11 -0
  47. package/host/test/index.js.map +1 -0
  48. package/host/test/kink.d.ts +11 -0
  49. package/host/test/kink.js +12 -0
  50. package/host/test/kink.js.map +1 -0
  51. package/package.json +22 -11
  52. package/readme.md +6 -0
  53. package/host/index.js +0 -170
  54. package/host/index.js.map +0 -1
  55. /package/host/{index.d.ts → code/base/index.d.ts} +0 -0
@@ -0,0 +1,223 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { CustomError } from 'ts-custom-error'
3
+
4
+ export type BaseHook<T extends any = any> = (
5
+ take?: T,
6
+ ) => KinkMeshBase & Link
7
+
8
+ export type FillHook<T extends any = any, U extends any = any> = (
9
+ take?: T,
10
+ load?: U,
11
+ ) => Link
12
+
13
+ export type KinkMesh = {
14
+ code: string
15
+ form: string
16
+ host: string
17
+ link?: Link
18
+ note: string
19
+ // HTTP code
20
+ siteCode?: number
21
+ take?: Link
22
+ time: string
23
+ }
24
+
25
+ export type KinkMeshBase = {
26
+ code: number
27
+ note: string
28
+ }
29
+
30
+ export type Link = Record<string, unknown>
31
+
32
+ const base: Record<string, BaseHook> = {}
33
+ const load: Record<string, LoadHook> = {}
34
+ const fill: Record<string, FillHook> = {}
35
+ const code: Record<string, (code: number) => string> = {}
36
+
37
+ let timeHook: TimeHook = (time: number) => String(time)
38
+
39
+ export type LoadHook<T extends any = any> = (take?: T) => Link
40
+
41
+ export default class Kink extends CustomError {
42
+ form: string
43
+
44
+ host: string
45
+
46
+ code: string
47
+
48
+ note: string
49
+
50
+ link: Link
51
+
52
+ siteCode?: number
53
+
54
+ take?: Link
55
+
56
+ time: string
57
+
58
+ static base = (host: string, form: string, hook: BaseHook) => {
59
+ base[`${host}:${form}`] = hook
60
+ return Kink
61
+ }
62
+
63
+ static code = (host: string, hook: (code: number) => string) => {
64
+ code[host] = hook
65
+ return Kink
66
+ }
67
+
68
+ static load = (host: string, form: string, hook: LoadHook) => {
69
+ load[`${host}:${form}`] = hook
70
+ return Kink
71
+ }
72
+
73
+ static fill = (host: string, form: string, hook: FillHook) => {
74
+ fill[`${host}:${form}`] = hook
75
+ return Kink
76
+ }
77
+
78
+ static time = (hook: TimeHook) => {
79
+ timeHook = hook
80
+ return Kink
81
+ }
82
+
83
+ static makeTime = (time: number) => {
84
+ return timeHook(time)
85
+ }
86
+
87
+ static make = (host: string, form: string, take?: any) => {
88
+ const time = Kink.makeTime(Date.now())
89
+ const hook = base[`${host}:${form}`]
90
+ if (!hook) {
91
+ throw new Error(`Missing ${host}:${form} in Kink.base`)
92
+ }
93
+ const hookLink = hook(take) as KinkMeshBase & Link
94
+ const kink = new Kink({
95
+ ...hookLink,
96
+ code: Kink.makeCode(host, hookLink.code),
97
+ form,
98
+ host,
99
+ take: take as Link,
100
+ time,
101
+ })
102
+
103
+ Kink.saveLoad(kink, take)
104
+
105
+ return kink
106
+ }
107
+
108
+ static saveLoad = (kink: Kink, take?: any) => {
109
+ const hook = load[`${kink.host}:${kink.form}`]
110
+ if (!hook) {
111
+ // throw new Error(`Missing ${kink.host}:${kink.form} in Kink.load`)
112
+ return
113
+ }
114
+ kink.link = hook(take)
115
+ }
116
+
117
+ static saveFill = (kink: Kink) => {
118
+ const hook = fill[`${kink.host}:${kink.form}`]
119
+ if (!hook) {
120
+ // throw new Error(`Missing ${kink.host}:${kink.form} in Kink.fill`)
121
+ return
122
+ }
123
+ kink.link = hook(kink.take, kink.link)
124
+ }
125
+
126
+ static makeCode = (host: string, codeLink: number) => {
127
+ const hook = code[host]
128
+ if (!hook) {
129
+ return codeLink.toString()
130
+ }
131
+ return hook(codeLink)
132
+ }
133
+
134
+ static makeBase = (
135
+ kink: Error,
136
+ {
137
+ siteCode,
138
+ list = false,
139
+ }: { list?: boolean; siteCode?: number } = {},
140
+ ) => {
141
+ const time = Kink.makeTime(Date.now())
142
+ return new Kink({
143
+ code:
144
+ 'code' in kink
145
+ ? typeof kink.code === 'string'
146
+ ? kink.code
147
+ : typeof kink.code === 'number'
148
+ ? Kink.makeCode('system', kink.code)
149
+ : '0000'
150
+ : '0000',
151
+ form: 'system_error',
152
+ host: 'system',
153
+ // list: stack ? kink.stack?.split('\n') ?? [] : [],
154
+ note: kink.message,
155
+ siteCode,
156
+ time,
157
+ })
158
+ }
159
+
160
+ constructor({
161
+ siteCode,
162
+ host,
163
+ note,
164
+ form,
165
+ take,
166
+ link = {},
167
+ code,
168
+ time,
169
+ }: KinkMesh) {
170
+ super(note)
171
+
172
+ Object.defineProperty(this, 'name', {
173
+ enumerable: false,
174
+ value: '',
175
+ writable: true,
176
+ })
177
+
178
+ Object.defineProperty(this, 'take', {
179
+ enumerable: false,
180
+ value: take,
181
+ writable: true,
182
+ })
183
+
184
+ this.time = time
185
+ this.host = host
186
+ this.form = form
187
+ this.code = code
188
+ this.note = note
189
+ this.link = link
190
+ this.take = take
191
+ this.siteCode = siteCode
192
+ }
193
+
194
+ toJSON(): KinkMesh {
195
+ return {
196
+ code: this.code,
197
+ form: this.form,
198
+ host: this.host,
199
+ link: this.link,
200
+ note: this.note,
201
+ time: this.time,
202
+ }
203
+ }
204
+ }
205
+
206
+ export type TimeHook = (time: number) => string
207
+
208
+ // eslint-disable-next-line sort-exports/sort-exports
209
+ export class KinkList extends Kink {
210
+ list: Array<Kink>
211
+
212
+ constructor(list: Array<Kink>) {
213
+ const time = Kink.makeTime(Date.now())
214
+ super({
215
+ code: Kink.makeCode('@cluesurf/kink', 0),
216
+ form: 'list',
217
+ host: '@cluesurf/kink',
218
+ note: 'A set of errors occurred.',
219
+ time,
220
+ })
221
+ this.list = list
222
+ }
223
+ }
package/code/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ import Kink from './base'
2
+
3
+ export * from './base'
4
+ export * from './site'
5
+ export * from './tree'
6
+
7
+ export default Kink
@@ -0,0 +1,92 @@
1
+ import Kink, { KinkList } from '../base'
2
+ import { z } from 'zod'
3
+ import _ from 'lodash'
4
+ import kink, { host } from './kink'
5
+ import { makeKinkText } from '../tree'
6
+
7
+ export function isZodError<I>(
8
+ input: any,
9
+ ): input is z.SafeParseError<I> {
10
+ return Boolean(
11
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
12
+ input && !input.success && 'error' in input,
13
+ )
14
+ }
15
+
16
+ export function loadKink(error: any) {
17
+ const kink = loadKinkList(error)
18
+
19
+ if (kink instanceof KinkList) {
20
+ if (kink?.list.length === 1) {
21
+ return kink.list[0]
22
+ }
23
+ }
24
+
25
+ return kink
26
+ }
27
+
28
+ export function loadKinkList(error: any) {
29
+ if (error instanceof z.ZodError) {
30
+ return loadZodErrorJSON(error)
31
+ } else {
32
+ if (error instanceof KinkList) {
33
+ error.list.forEach(error => {
34
+ Kink.saveFill(error)
35
+ })
36
+ return error
37
+ } else if (error instanceof Kink) {
38
+ Kink.saveFill(error)
39
+ return error
40
+ } else if (error instanceof Error) {
41
+ return Kink.makeBase(error, { siteCode: 500 })
42
+ } else {
43
+ return Kink.makeBase(new Error(error as string), {
44
+ siteCode: 500,
45
+ })
46
+ }
47
+ }
48
+ }
49
+
50
+ export function loadZodErrorJSON(error: z.ZodError) {
51
+ return new KinkList(
52
+ error.issues.map(error => {
53
+ // ZodInvalidTypeIssue | ZodInvalidLiteralIssue | ZodUnrecognizedKeysIssue | ZodInvalidUnionIssue | ZodInvalidUnionDiscriminatorIssue | ZodInvalidEnumValueIssue | ZodInvalidArgumentsIssue | ZodInvalidReturnTypeIssue | ZodInvalidDateIssue | ZodInvalidStringIssue | ZodTooSmallIssue | ZodTooBigIssue | ZodInvalidIntersectionTypesIssue | ZodNotMultipleOfIssue | ZodNotFiniteIssue | ZodCustomIssue;
54
+ switch (error.code) {
55
+ case z.ZodIssueCode.invalid_type:
56
+ return kink(
57
+ 'form_fail',
58
+ {
59
+ have: error.received,
60
+ link: error.path.map(String),
61
+ message: error.message,
62
+ need: error.expected,
63
+ },
64
+ 406,
65
+ )
66
+ case z.ZodIssueCode.unrecognized_keys:
67
+ return kink(
68
+ 'form_link_fail',
69
+ {
70
+ link: error.path,
71
+ list: error.keys,
72
+ message: error.message,
73
+ },
74
+ 406,
75
+ )
76
+ default: {
77
+ const kink = new Kink({
78
+ code: Kink.makeCode(host, 0),
79
+ form: 'z.ZodError',
80
+ host: host,
81
+ note: error.message,
82
+ time: Kink.makeTime(Date.now()),
83
+ })
84
+ kink.siteCode = 406
85
+ return kink
86
+ }
87
+ }
88
+ }),
89
+ )
90
+ }
91
+
92
+ export { default } from './make'
@@ -0,0 +1,97 @@
1
+ import Kink from '~/code/base'
2
+
3
+ export const host = '@cluesurf/kink'
4
+
5
+ type BaseZodError = {
6
+ link: Array<string | number>
7
+ message: string
8
+ }
9
+
10
+ type Base = {
11
+ call_fail: {
12
+ take: {}
13
+ }
14
+ call_time_meet: {
15
+ take: {
16
+ link: string
17
+ }
18
+ // base: {
19
+ // url: string
20
+ // }
21
+ // fill: {
22
+ // url: string
23
+ // }
24
+ }
25
+ form_fail: {
26
+ take: BaseZodError & {
27
+ have: string
28
+ link: Array<string>
29
+ need: string
30
+ }
31
+ }
32
+ form_link_fail: {
33
+ take: BaseZodError & {
34
+ list: Array<string>
35
+ }
36
+ }
37
+ }
38
+
39
+ type Name = keyof Base
40
+
41
+ let CODE_INDEX = 1
42
+
43
+ const CODE = {
44
+ call_fail: CODE_INDEX++,
45
+ call_time_meet: CODE_INDEX++,
46
+ form_fail: CODE_INDEX++,
47
+ form_link_fail: CODE_INDEX++,
48
+ }
49
+
50
+ Kink.code(host, (code: number) => code.toString(16).padStart(4, '0'))
51
+
52
+ Kink.base(
53
+ host,
54
+ 'call_time_meet',
55
+ (take: Base['call_time_meet']['take']) => ({
56
+ code: CODE.call_time_meet,
57
+ link: take.link,
58
+ note: 'Request timeout.',
59
+ }),
60
+ )
61
+
62
+ Kink.base(host, 'call_fail', () => ({
63
+ code: CODE.call_fail,
64
+ note: 'System unable to make request currently.',
65
+ }))
66
+
67
+ Kink.base(host, 'form_fail', (take: Base['form_fail']['take']) => ({
68
+ code: CODE.form_fail,
69
+ have: take.have,
70
+ hint: take.message,
71
+ link: take.link,
72
+ need: take.need,
73
+ note: 'Invalid link type.',
74
+ }))
75
+
76
+ // https://github.com/colinhacks/zod/blob/master/ERROR_HANDLING.md
77
+ Kink.base(
78
+ host,
79
+ 'form_link_fail',
80
+ (take: Base['form_link_fail']['take']) => ({
81
+ code: CODE.form_link_fail,
82
+ hint: take.message,
83
+ link: take.link,
84
+ list: take.list,
85
+ note: 'Unrecognized keys in object.',
86
+ }),
87
+ )
88
+
89
+ export default function makeBase<N extends Name>(
90
+ form: N,
91
+ link?: Base[N]['take'],
92
+ siteCode?: number,
93
+ ) {
94
+ const kink = Kink.make(host, form, link)
95
+ kink.siteCode = siteCode
96
+ return kink
97
+ }
@@ -0,0 +1,17 @@
1
+ import { KinkList } from '../base'
2
+ import { loadKink } from '.'
3
+ import { makeKinkText } from '../tree'
4
+
5
+ export default function makeSiteKinkText(error: any) {
6
+ const kink = loadKink(error)
7
+ const text: Array<string> = []
8
+ if (kink instanceof KinkList) {
9
+ text.push(makeKinkText(kink))
10
+ kink.list.forEach(kink => {
11
+ text.push(makeKinkText(kink))
12
+ })
13
+ } else if (kink) {
14
+ text.push(makeKinkText(kink))
15
+ }
16
+ return text.join('\n')
17
+ }
@@ -0,0 +1,35 @@
1
+ import Kink from '~/code/base'
2
+ import fs from 'fs'
3
+ import makeSiteKinkText from '.'
4
+
5
+ const host = '@cluesurf/kink'
6
+
7
+ type Base = {
8
+ syntax_error: {}
9
+ }
10
+
11
+ type Name = keyof Base
12
+
13
+ Kink.base(host, 'syntax_error', () => ({
14
+ code: 1,
15
+ note: 'Syntax error',
16
+ }))
17
+
18
+ Kink.code(host, (code: number) => code.toString(16).padStart(4, '0'))
19
+
20
+ export default function kink<N extends Name>(form: N, link?: Base[N]) {
21
+ return Kink.make(host, form, link)
22
+ }
23
+
24
+ // https://nodejs.org/api/errors.html
25
+ process.on('uncaughtException', err => {
26
+ console.log(makeSiteKinkText(err))
27
+ })
28
+
29
+ setTimeout(() => {
30
+ throw kink('syntax_error')
31
+ })
32
+
33
+ setTimeout(() => {
34
+ fs.readFileSync('.')
35
+ })
@@ -0,0 +1,20 @@
1
+ import Kink from '~/code/base'
2
+ import makeText from './make'
3
+
4
+ export * from './make'
5
+
6
+ export function makeBaseKinkText(kink: Error): string {
7
+ return makeText({ ...Kink.makeBase(kink), list: [] })
8
+ }
9
+
10
+ export function makeKinkText(kink: Kink): string {
11
+ return makeText({
12
+ code: kink.code,
13
+ host: kink.host,
14
+ list: kink.stack?.split('\n') ?? [],
15
+ note: kink.note,
16
+ time: kink.time,
17
+ })
18
+ }
19
+
20
+ export { makeText }
@@ -0,0 +1 @@
1
+ export * from './node'