@cluesurf/kink 1.0.8 → 1.2.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.
- package/code/base/index.ts +223 -0
- package/code/index.ts +7 -0
- package/code/site/index.ts +92 -0
- package/code/site/kink.ts +97 -0
- package/code/site/make.ts +17 -0
- package/code/site/test.ts +35 -0
- package/code/tree/browser.ts +20 -0
- package/code/tree/index.ts +1 -0
- package/code/tree/make.ts +347 -0
- package/code/tree/node.ts +99 -0
- package/code/tree/test.ts +51 -0
- package/eslint.config.ts +3 -0
- package/host/code/base/index.js +138 -0
- package/host/code/base/index.js.map +1 -0
- package/host/code/index.d.ts +5 -0
- package/host/code/index.js +6 -0
- package/host/code/index.js.map +1 -0
- package/host/code/site/index.d.ts +7 -0
- package/host/code/site/index.js +75 -0
- package/host/code/site/index.js.map +1 -0
- package/host/code/site/kink.d.ts +31 -0
- package/host/code/site/kink.js +41 -0
- package/host/code/site/kink.js.map +1 -0
- package/host/code/site/make.d.ts +1 -0
- package/host/code/site/make.js +18 -0
- package/host/code/site/make.js.map +1 -0
- package/host/code/site/test.d.ts +7 -0
- package/host/code/site/test.js +23 -0
- package/host/code/site/test.js.map +1 -0
- package/host/code/tree/browser.d.ts +6 -0
- package/host/code/tree/browser.js +17 -0
- package/host/code/tree/browser.js.map +1 -0
- package/host/code/tree/index.d.ts +1 -0
- package/host/code/tree/index.js +2 -0
- package/host/code/tree/index.js.map +1 -0
- package/host/code/tree/make.d.ts +30 -0
- package/host/code/tree/make.js +271 -0
- package/host/code/tree/make.js.map +1 -0
- package/host/code/tree/node.d.ts +6 -0
- package/host/code/tree/node.js +81 -0
- package/host/code/tree/node.js.map +1 -0
- package/host/code/tree/test.d.ts +7 -0
- package/host/code/tree/test.js +37 -0
- package/host/code/tree/test.js.map +1 -0
- package/host/test/index.d.ts +2 -0
- package/host/test/index.js +11 -0
- package/host/test/index.js.map +1 -0
- package/host/test/kink.d.ts +11 -0
- package/host/test/kink.js +12 -0
- package/host/test/kink.js.map +1 -0
- package/package.json +21 -10
- package/readme.md +6 -0
- package/host/index.js +0 -170
- package/host/index.js.map +0 -1
- /package/host/{index.d.ts → code/base/index.d.ts} +0 -0
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
import { text as tint } from '@cluesurf/show'
|
|
3
|
+
|
|
4
|
+
export type HostLinkHook = (
|
|
5
|
+
file: string,
|
|
6
|
+
line: number,
|
|
7
|
+
rise: number,
|
|
8
|
+
) => [string, number | undefined, number | undefined]
|
|
9
|
+
|
|
10
|
+
export type LineListLink = {
|
|
11
|
+
code?: number
|
|
12
|
+
file: string
|
|
13
|
+
line?: number
|
|
14
|
+
task?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type MakeText = {
|
|
18
|
+
code: string
|
|
19
|
+
hook?: HostLinkHook
|
|
20
|
+
host: string
|
|
21
|
+
link?: Record<string, unknown>
|
|
22
|
+
// stack trace
|
|
23
|
+
list: Array<string>
|
|
24
|
+
note: string
|
|
25
|
+
time: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const TIME_FORM = 'yyyy/MM/dd @ hh:mm:ss.SSSaaa'
|
|
29
|
+
|
|
30
|
+
export function makeLinkList(list: Array<string>, hook?: HostLinkHook) {
|
|
31
|
+
const noteLine: Array<string> = []
|
|
32
|
+
const linkList: Array<LineListLink> = []
|
|
33
|
+
|
|
34
|
+
let find = false
|
|
35
|
+
let i = list.length - 1
|
|
36
|
+
while (i >= 0) {
|
|
37
|
+
const line = list[i--]
|
|
38
|
+
if (!find && line?.startsWith(' at ')) {
|
|
39
|
+
const link = readListLine(line.slice(' at '.length), hook)
|
|
40
|
+
if (link) {
|
|
41
|
+
linkList.push(link)
|
|
42
|
+
}
|
|
43
|
+
} else if (line) {
|
|
44
|
+
find = true
|
|
45
|
+
noteLine.push(line)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return { linkList: linkList.reverse(), note: noteLine }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* This you pass it a stack trace and it will render the error text.
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
const makeText = ({
|
|
57
|
+
host,
|
|
58
|
+
code,
|
|
59
|
+
note,
|
|
60
|
+
link = {},
|
|
61
|
+
list,
|
|
62
|
+
time,
|
|
63
|
+
hook,
|
|
64
|
+
}: MakeText): string => {
|
|
65
|
+
const textList: Array<string> = []
|
|
66
|
+
|
|
67
|
+
const W = { tone: 'white' }
|
|
68
|
+
const WB = { tone: 'whiteBright' }
|
|
69
|
+
const B = { tone: 'blue' }
|
|
70
|
+
const M = { tone: 'magenta' }
|
|
71
|
+
const MB = { bold: true, tone: 'cyan' }
|
|
72
|
+
const G = { tone: 'green' }
|
|
73
|
+
const H = { tone: 'blackBright' }
|
|
74
|
+
|
|
75
|
+
textList.push(...makeTextHead(note, code, host, time))
|
|
76
|
+
|
|
77
|
+
textList.push(...makeLinkHash(link, 1))
|
|
78
|
+
|
|
79
|
+
const { linkList } = makeLinkList(list, hook)
|
|
80
|
+
|
|
81
|
+
linkList.forEach(link => {
|
|
82
|
+
let head: (string | number)[] = []
|
|
83
|
+
if (link.line) {
|
|
84
|
+
head.push(link.line)
|
|
85
|
+
}
|
|
86
|
+
if (link.code) {
|
|
87
|
+
head.push(link.code)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const headText = head.length ? ':' + head.join(':') : ''
|
|
91
|
+
const siteText = tint('site <', H)
|
|
92
|
+
const fileText = tint(`${link.file}${headText}`, WB)
|
|
93
|
+
textList.push(` ${siteText}${fileText}${tint('>', H)}`)
|
|
94
|
+
|
|
95
|
+
if (link.task) {
|
|
96
|
+
const callText = ' ' + tint(`call <`, H)
|
|
97
|
+
const taskText = tint(link.task, W)
|
|
98
|
+
textList.push(`${callText}${taskText}${tint('>', H)}`)
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
return textList.join('\n')
|
|
103
|
+
|
|
104
|
+
function makeLinkHash(link: Record<string, unknown>, move: number) {
|
|
105
|
+
const textList: Array<string> = []
|
|
106
|
+
const moveText = makeTextMove(move)
|
|
107
|
+
|
|
108
|
+
for (const name in link) {
|
|
109
|
+
const bond = link[name]
|
|
110
|
+
if (bond === undefined) {
|
|
111
|
+
textList.push(...makeLinkVoid(name, move))
|
|
112
|
+
} else if (bond === null) {
|
|
113
|
+
textList.push(...makeLinkNull(name, move))
|
|
114
|
+
} else if (typeof bond === 'boolean') {
|
|
115
|
+
textList.push(...makeLinkWave(name, bond, move))
|
|
116
|
+
} else if (typeof bond === 'string') {
|
|
117
|
+
textList.push(...makeLinkText(name, bond, move))
|
|
118
|
+
} else if (typeof bond === 'number') {
|
|
119
|
+
textList.push(...makeLinkSize(name, bond, move))
|
|
120
|
+
} else if (Array.isArray(bond)) {
|
|
121
|
+
bond.forEach(bond => {
|
|
122
|
+
textList.push(...makeLinkBond(name, bond, move))
|
|
123
|
+
})
|
|
124
|
+
} else if (typeof bond === 'object') {
|
|
125
|
+
let base = true
|
|
126
|
+
for (const bondName in bond) {
|
|
127
|
+
const bind = (bond as Record<string, unknown>)[bondName]
|
|
128
|
+
if (base) {
|
|
129
|
+
base = false
|
|
130
|
+
if (bind === undefined) {
|
|
131
|
+
textList.push(...makeLinkVoid(name, move))
|
|
132
|
+
} else if (bind === null) {
|
|
133
|
+
textList.push(...makeLinkNull(name, move))
|
|
134
|
+
} else if (typeof bind === 'boolean') {
|
|
135
|
+
textList.push(...makeLinkWave(name, bind, move))
|
|
136
|
+
} else if (typeof bind === 'string') {
|
|
137
|
+
textList.push(...makeLinkText(name, bind, move))
|
|
138
|
+
} else if (typeof bind === 'number') {
|
|
139
|
+
textList.push(...makeLinkSize(name, bind, move))
|
|
140
|
+
} else if (Array.isArray(bind)) {
|
|
141
|
+
textList.push(`${moveText}${tint(`bind ${name}`, H)}`)
|
|
142
|
+
bind.forEach(bind => {
|
|
143
|
+
textList.push(...makeLinkBond(bondName, bind, move + 1))
|
|
144
|
+
})
|
|
145
|
+
} else if (typeof bind === 'object') {
|
|
146
|
+
textList.push(`${moveText}${tint(`bind ${name}`, H)}`)
|
|
147
|
+
textList.push(...makeLinkBond(bondName, bind, move + 1))
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
if (bind === undefined) {
|
|
151
|
+
textList.push(...makeLinkVoid(bondName, move + 1))
|
|
152
|
+
} else if (bind === null) {
|
|
153
|
+
textList.push(...makeLinkNull(bondName, move + 1))
|
|
154
|
+
} else if (typeof bind === 'boolean') {
|
|
155
|
+
textList.push(...makeLinkWave(bondName, bind, move + 1))
|
|
156
|
+
} else if (typeof bind === 'string') {
|
|
157
|
+
textList.push(...makeLinkText(bondName, bind, move + 1))
|
|
158
|
+
} else if (typeof bind === 'number') {
|
|
159
|
+
textList.push(...makeLinkSize(bondName, bind, move + 1))
|
|
160
|
+
} else if (Array.isArray(bind)) {
|
|
161
|
+
bind.forEach(bind => {
|
|
162
|
+
textList.push(...makeLinkBond(bondName, bind, move + 1))
|
|
163
|
+
})
|
|
164
|
+
} else if (typeof bind === 'object') {
|
|
165
|
+
textList.push(...makeLinkBond(bondName, bind, move + 1))
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return textList
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function makeLinkBond(name: string, bond: unknown, move: number) {
|
|
176
|
+
const textList: Array<string> = []
|
|
177
|
+
if (bond === undefined) {
|
|
178
|
+
textList.push(...makeLinkVoid(name, move))
|
|
179
|
+
} else if (bond === null) {
|
|
180
|
+
textList.push(...makeLinkNull(name, move))
|
|
181
|
+
} else if (typeof bond === 'boolean') {
|
|
182
|
+
textList.push(...makeLinkWave(name, bond, move))
|
|
183
|
+
} else if (typeof bond === 'string') {
|
|
184
|
+
textList.push(...makeLinkText(name, bond, move))
|
|
185
|
+
} else if (typeof bond === 'number') {
|
|
186
|
+
textList.push(...makeLinkSize(name, bond, move))
|
|
187
|
+
} else if (typeof bond === 'object') {
|
|
188
|
+
const moveText = makeTextMove(move)
|
|
189
|
+
textList.push(`${moveText}${tint(`bind ${name}`, H)}`)
|
|
190
|
+
textList.push(
|
|
191
|
+
...makeLinkHash(bond as Record<string, unknown>, move + 1),
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
return textList
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function makeLinkVoid(name: string, move: number) {
|
|
198
|
+
const textList: Array<string> = []
|
|
199
|
+
// const moveText = makeTextMove(move)
|
|
200
|
+
// textList.push(
|
|
201
|
+
// `${moveText}${tint(`${name} <`, H)}${tint('void', B)}${tint(
|
|
202
|
+
// `>`,
|
|
203
|
+
// H,
|
|
204
|
+
// )}`,
|
|
205
|
+
// )
|
|
206
|
+
return textList
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function makeLinkNull(name: string, move: number) {
|
|
210
|
+
const textList: Array<string> = []
|
|
211
|
+
const moveText = makeTextMove(move)
|
|
212
|
+
textList.push(
|
|
213
|
+
`${moveText}${tint(`bind`, H)} ${tint(name, W)}${tint(
|
|
214
|
+
`,`,
|
|
215
|
+
H,
|
|
216
|
+
)} ${tint('null', MB)}`,
|
|
217
|
+
)
|
|
218
|
+
return textList
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function makeLinkSize(name: string, bond: number, move: number) {
|
|
222
|
+
const textList: Array<string> = []
|
|
223
|
+
const moveText = makeTextMove(move)
|
|
224
|
+
textList.push(
|
|
225
|
+
`${moveText}${tint(`bind`, H)} ${tint(name, W)}${tint(
|
|
226
|
+
`,`,
|
|
227
|
+
H,
|
|
228
|
+
)} ${tint(String(bond), G)}`,
|
|
229
|
+
)
|
|
230
|
+
return textList
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function makeLinkWave(name: string, bond: boolean, move: number) {
|
|
234
|
+
const textList: Array<string> = []
|
|
235
|
+
const moveText = makeTextMove(move)
|
|
236
|
+
textList.push(
|
|
237
|
+
`${moveText}${tint(`bind`, H)} ${tint(name, W)}${tint(
|
|
238
|
+
`,`,
|
|
239
|
+
H,
|
|
240
|
+
)} ${tint(String(bond), B)}`,
|
|
241
|
+
)
|
|
242
|
+
return textList
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function makeLinkText(name: string, bond: string, move: number) {
|
|
246
|
+
const textList: Array<string> = []
|
|
247
|
+
const moveText = makeTextMove(move)
|
|
248
|
+
if (bond.match(/\n/)) {
|
|
249
|
+
textList.push(
|
|
250
|
+
`${moveText}${tint(`bind`, H)} ${tint(name, W)}${tint(
|
|
251
|
+
`, <`,
|
|
252
|
+
H,
|
|
253
|
+
)}`,
|
|
254
|
+
)
|
|
255
|
+
bond.split(/\n/).forEach(line => {
|
|
256
|
+
const moveNest = move + 1
|
|
257
|
+
const moveNestText = makeTextMove(moveNest)
|
|
258
|
+
textList.push(`${moveNestText}${tint(line, M)}`)
|
|
259
|
+
})
|
|
260
|
+
textList.push(`${moveText}${tint(`>`, H)}`)
|
|
261
|
+
} else {
|
|
262
|
+
textList.push(
|
|
263
|
+
`${moveText}${tint(`bind`, H)} ${tint(name, W)}${tint(
|
|
264
|
+
`, <`,
|
|
265
|
+
H,
|
|
266
|
+
)}${tint(bond, M)}${tint(`>`, H)}`,
|
|
267
|
+
)
|
|
268
|
+
}
|
|
269
|
+
return textList
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export default makeText
|
|
274
|
+
// Export node implementation by default for now
|
|
275
|
+
// Dynamic resolution will be handled by package.json exports field when using @cluesurf/kink/system
|
|
276
|
+
export { makeKinkText, makeBaseKinkText } from './node'
|
|
277
|
+
|
|
278
|
+
export const makeTextHead = (
|
|
279
|
+
note: string,
|
|
280
|
+
code: string,
|
|
281
|
+
host: string,
|
|
282
|
+
time: string,
|
|
283
|
+
) => {
|
|
284
|
+
const list: Array<string> = []
|
|
285
|
+
|
|
286
|
+
const R = { tone: 'red' }
|
|
287
|
+
const RB = { bold: true, tone: 'red' }
|
|
288
|
+
const W = { tone: 'white' }
|
|
289
|
+
const H = { tone: 'blackBright' }
|
|
290
|
+
const C = { tone: 'cyan' }
|
|
291
|
+
|
|
292
|
+
list.push(
|
|
293
|
+
tint(`kink`, R) +
|
|
294
|
+
' ' +
|
|
295
|
+
tint('<', H) +
|
|
296
|
+
tint(`${note}`, RB) +
|
|
297
|
+
tint('>', H),
|
|
298
|
+
)
|
|
299
|
+
list.push(
|
|
300
|
+
' ' + tint(`time <`, H) + tint(`${time}`, W) + tint('>,', H),
|
|
301
|
+
)
|
|
302
|
+
list.push(
|
|
303
|
+
' ' + tint(`code <`, H) + tint(`${code}`, C) + tint(`>`, H),
|
|
304
|
+
)
|
|
305
|
+
list.push(' ' + tint(`host `, H) + tint(`${host}`, H))
|
|
306
|
+
return list
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export function readListLine(text: string, hook?: HostLinkHook) {
|
|
310
|
+
const [a, b] = text.trim().split(/\s+/)
|
|
311
|
+
if (a && !b) {
|
|
312
|
+
return readListLineFile(a, hook)
|
|
313
|
+
} else if (a && b) {
|
|
314
|
+
return {
|
|
315
|
+
...readListLineFile(b, hook),
|
|
316
|
+
task: a,
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export function readListLineFile(
|
|
322
|
+
text: string,
|
|
323
|
+
hook?: HostLinkHook,
|
|
324
|
+
): LineListLink {
|
|
325
|
+
const list = text.replace(/[\(\)]/g, '').split(':')
|
|
326
|
+
const code = list.pop()
|
|
327
|
+
let codeMark = code ? parseInt(code, 10) : undefined
|
|
328
|
+
const line = list.pop()
|
|
329
|
+
let lineMark = line ? parseInt(line, 10) : undefined
|
|
330
|
+
let file = list.join(':')
|
|
331
|
+
if (
|
|
332
|
+
hook &&
|
|
333
|
+
typeof lineMark === 'number' &&
|
|
334
|
+
typeof codeMark === 'number'
|
|
335
|
+
) {
|
|
336
|
+
;[file, lineMark, codeMark] = hook(file, lineMark, codeMark)
|
|
337
|
+
}
|
|
338
|
+
return {
|
|
339
|
+
code: codeMark,
|
|
340
|
+
file,
|
|
341
|
+
line: lineMark,
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function makeTextMove(move: number) {
|
|
346
|
+
return new Array(move + 1).join(' ')
|
|
347
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import smc from '@cspotcode/source-map'
|
|
2
|
+
import Kink from '~/code/base'
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import pathResolve from 'path'
|
|
5
|
+
import makeText from './make'
|
|
6
|
+
|
|
7
|
+
export * from './make'
|
|
8
|
+
|
|
9
|
+
const HOST_LINK_MESH: Record<string, smc.SourceMapConsumer> = {}
|
|
10
|
+
|
|
11
|
+
function loadHostLink(line: string): smc.SourceMapConsumer | void {
|
|
12
|
+
const link = HOST_LINK_MESH[`${line}`]
|
|
13
|
+
if (link) {
|
|
14
|
+
return link
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const fileLink = line.replace(/^file:\/\//, '')
|
|
18
|
+
|
|
19
|
+
if (fs.existsSync(`${fileLink}.map`)) {
|
|
20
|
+
const mapContent = fs.readFileSync(`${fileLink}.map`, 'utf-8')
|
|
21
|
+
const json = JSON.parse(mapContent) as smc.RawSourceMap
|
|
22
|
+
const sm = new smc.SourceMapConsumer(json)
|
|
23
|
+
HOST_LINK_MESH[`${line}`] = sm
|
|
24
|
+
return sm
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function readLinkBase(path: string): string {
|
|
29
|
+
const relative = pathResolve.relative(process.cwd(), path)
|
|
30
|
+
// get pnpm symlink path so it's nicer to see.
|
|
31
|
+
if (relative.match(/^(node_modules\/\.pnpm\/.+\/node_modules)/)) {
|
|
32
|
+
return `node_modules/${relative.slice(RegExp.$1.length)}`
|
|
33
|
+
}
|
|
34
|
+
return relative
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function readLink(path: string, context: string): string {
|
|
38
|
+
return readLinkBase(pathResolve.resolve(context, path))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function readHostLinkFile(
|
|
42
|
+
file: string,
|
|
43
|
+
line: number,
|
|
44
|
+
rise: number,
|
|
45
|
+
): [string, number | undefined, number | undefined] {
|
|
46
|
+
const link = loadHostLink(file)
|
|
47
|
+
|
|
48
|
+
const trace = {
|
|
49
|
+
column: rise,
|
|
50
|
+
filename: file,
|
|
51
|
+
line: line,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (link) {
|
|
55
|
+
const token = link.originalPositionFor(trace)
|
|
56
|
+
if (token.source) {
|
|
57
|
+
return [
|
|
58
|
+
readLink(
|
|
59
|
+
token.source,
|
|
60
|
+
pathResolve.dirname(file.replace(/^file:\/\//, '')),
|
|
61
|
+
),
|
|
62
|
+
token.line == null ? undefined : token.line,
|
|
63
|
+
token.column == null ? undefined : token.column,
|
|
64
|
+
]
|
|
65
|
+
} else {
|
|
66
|
+
return [file, line, rise]
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
return [readLinkBase(file), line, rise]
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function makeBaseKinkText(kink: Error) {
|
|
74
|
+
return makeText({
|
|
75
|
+
code:
|
|
76
|
+
'code' in kink && typeof kink.code === 'string'
|
|
77
|
+
? kink.code
|
|
78
|
+
: '0000',
|
|
79
|
+
hook: readHostLinkFile,
|
|
80
|
+
host: 'node',
|
|
81
|
+
list: kink.stack?.split('\n') ?? [],
|
|
82
|
+
note: kink.message,
|
|
83
|
+
time: Kink.makeTime(Date.now()),
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function makeKinkText(kink: Kink): string {
|
|
88
|
+
return makeText({
|
|
89
|
+
code: kink.code,
|
|
90
|
+
hook: readHostLinkFile,
|
|
91
|
+
host: kink.host,
|
|
92
|
+
link: kink.link,
|
|
93
|
+
list: kink.stack?.split('\n') ?? [],
|
|
94
|
+
note: kink.note,
|
|
95
|
+
time: kink.time,
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export { makeText }
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import Kink from '~/code/base'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import { format } from 'date-fns'
|
|
4
|
+
import { makeKinkText, makeBaseKinkText, TIME_FORM } from './make'
|
|
5
|
+
|
|
6
|
+
const host = '@cluesurf/kink'
|
|
7
|
+
|
|
8
|
+
type Base = {
|
|
9
|
+
syntax_error: {}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
type Name = keyof Base
|
|
13
|
+
|
|
14
|
+
Kink.base(host, 'syntax_error', () => ({
|
|
15
|
+
code: 1,
|
|
16
|
+
note: 'Syntax error',
|
|
17
|
+
}))
|
|
18
|
+
|
|
19
|
+
Kink.code(host, (code: number) => code.toString(16).padStart(4, '0'))
|
|
20
|
+
|
|
21
|
+
Kink.time(time => format(time, TIME_FORM))
|
|
22
|
+
|
|
23
|
+
export default function kink<N extends Name>(form: N, link?: Base[N]) {
|
|
24
|
+
return Kink.make(host, form, link)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
console.log('')
|
|
28
|
+
console.log('')
|
|
29
|
+
console.log('')
|
|
30
|
+
|
|
31
|
+
// https://nodejs.org/api/errors.html
|
|
32
|
+
process.on('uncaughtException', err => {
|
|
33
|
+
if (err instanceof Kink) {
|
|
34
|
+
// Kink.saveFill(err, err.link)
|
|
35
|
+
console.log(makeKinkText(err))
|
|
36
|
+
} else {
|
|
37
|
+
console.log(makeBaseKinkText(err))
|
|
38
|
+
|
|
39
|
+
console.log('')
|
|
40
|
+
console.log('')
|
|
41
|
+
console.log('')
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
setTimeout(() => {
|
|
46
|
+
throw kink('syntax_error')
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
setTimeout(() => {
|
|
50
|
+
fs.readFileSync('.')
|
|
51
|
+
})
|
package/eslint.config.ts
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { CustomError } from 'ts-custom-error';
|
|
3
|
+
const base = {};
|
|
4
|
+
const load = {};
|
|
5
|
+
const fill = {};
|
|
6
|
+
const code = {};
|
|
7
|
+
let timeHook = (time) => String(time);
|
|
8
|
+
class Kink extends CustomError {
|
|
9
|
+
constructor({ siteCode, host, note, form, take, link = {}, code, time, }) {
|
|
10
|
+
super(note);
|
|
11
|
+
Object.defineProperty(this, 'name', {
|
|
12
|
+
enumerable: false,
|
|
13
|
+
value: '',
|
|
14
|
+
writable: true,
|
|
15
|
+
});
|
|
16
|
+
Object.defineProperty(this, 'take', {
|
|
17
|
+
enumerable: false,
|
|
18
|
+
value: take,
|
|
19
|
+
writable: true,
|
|
20
|
+
});
|
|
21
|
+
this.time = time;
|
|
22
|
+
this.host = host;
|
|
23
|
+
this.form = form;
|
|
24
|
+
this.code = code;
|
|
25
|
+
this.note = note;
|
|
26
|
+
this.link = link;
|
|
27
|
+
this.take = take;
|
|
28
|
+
this.siteCode = siteCode;
|
|
29
|
+
}
|
|
30
|
+
toJSON() {
|
|
31
|
+
return {
|
|
32
|
+
code: this.code,
|
|
33
|
+
form: this.form,
|
|
34
|
+
host: this.host,
|
|
35
|
+
link: this.link,
|
|
36
|
+
note: this.note,
|
|
37
|
+
time: this.time,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
Kink.base = (host, form, hook) => {
|
|
42
|
+
base[`${host}:${form}`] = hook;
|
|
43
|
+
return Kink;
|
|
44
|
+
};
|
|
45
|
+
Kink.code = (host, hook) => {
|
|
46
|
+
code[host] = hook;
|
|
47
|
+
return Kink;
|
|
48
|
+
};
|
|
49
|
+
Kink.load = (host, form, hook) => {
|
|
50
|
+
load[`${host}:${form}`] = hook;
|
|
51
|
+
return Kink;
|
|
52
|
+
};
|
|
53
|
+
Kink.fill = (host, form, hook) => {
|
|
54
|
+
fill[`${host}:${form}`] = hook;
|
|
55
|
+
return Kink;
|
|
56
|
+
};
|
|
57
|
+
Kink.time = (hook) => {
|
|
58
|
+
timeHook = hook;
|
|
59
|
+
return Kink;
|
|
60
|
+
};
|
|
61
|
+
Kink.makeTime = (time) => {
|
|
62
|
+
return timeHook(time);
|
|
63
|
+
};
|
|
64
|
+
Kink.make = (host, form, take) => {
|
|
65
|
+
const time = Kink.makeTime(Date.now());
|
|
66
|
+
const hook = base[`${host}:${form}`];
|
|
67
|
+
if (!hook) {
|
|
68
|
+
throw new Error(`Missing ${host}:${form} in Kink.base`);
|
|
69
|
+
}
|
|
70
|
+
const hookLink = hook(take);
|
|
71
|
+
const kink = new Kink({
|
|
72
|
+
...hookLink,
|
|
73
|
+
code: Kink.makeCode(host, hookLink.code),
|
|
74
|
+
form,
|
|
75
|
+
host,
|
|
76
|
+
take: take,
|
|
77
|
+
time,
|
|
78
|
+
});
|
|
79
|
+
Kink.saveLoad(kink, take);
|
|
80
|
+
return kink;
|
|
81
|
+
};
|
|
82
|
+
Kink.saveLoad = (kink, take) => {
|
|
83
|
+
const hook = load[`${kink.host}:${kink.form}`];
|
|
84
|
+
if (!hook) {
|
|
85
|
+
// throw new Error(`Missing ${kink.host}:${kink.form} in Kink.load`)
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
kink.link = hook(take);
|
|
89
|
+
};
|
|
90
|
+
Kink.saveFill = (kink) => {
|
|
91
|
+
const hook = fill[`${kink.host}:${kink.form}`];
|
|
92
|
+
if (!hook) {
|
|
93
|
+
// throw new Error(`Missing ${kink.host}:${kink.form} in Kink.fill`)
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
kink.link = hook(kink.take, kink.link);
|
|
97
|
+
};
|
|
98
|
+
Kink.makeCode = (host, codeLink) => {
|
|
99
|
+
const hook = code[host];
|
|
100
|
+
if (!hook) {
|
|
101
|
+
return codeLink.toString();
|
|
102
|
+
}
|
|
103
|
+
return hook(codeLink);
|
|
104
|
+
};
|
|
105
|
+
Kink.makeBase = (kink, { siteCode, list = false, } = {}) => {
|
|
106
|
+
const time = Kink.makeTime(Date.now());
|
|
107
|
+
return new Kink({
|
|
108
|
+
code: 'code' in kink
|
|
109
|
+
? typeof kink.code === 'string'
|
|
110
|
+
? kink.code
|
|
111
|
+
: typeof kink.code === 'number'
|
|
112
|
+
? Kink.makeCode('system', kink.code)
|
|
113
|
+
: '0000'
|
|
114
|
+
: '0000',
|
|
115
|
+
form: 'system_error',
|
|
116
|
+
host: 'system',
|
|
117
|
+
// list: stack ? kink.stack?.split('\n') ?? [] : [],
|
|
118
|
+
note: kink.message,
|
|
119
|
+
siteCode,
|
|
120
|
+
time,
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
export default Kink;
|
|
124
|
+
// eslint-disable-next-line sort-exports/sort-exports
|
|
125
|
+
export class KinkList extends Kink {
|
|
126
|
+
constructor(list) {
|
|
127
|
+
const time = Kink.makeTime(Date.now());
|
|
128
|
+
super({
|
|
129
|
+
code: Kink.makeCode('@cluesurf/kink', 0),
|
|
130
|
+
form: 'list',
|
|
131
|
+
host: '@cluesurf/kink',
|
|
132
|
+
note: 'A set of errors occurred.',
|
|
133
|
+
time,
|
|
134
|
+
});
|
|
135
|
+
this.list = list;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../code/base/index.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AA8B7C,MAAM,IAAI,GAA6B,EAAE,CAAA;AACzC,MAAM,IAAI,GAA6B,EAAE,CAAA;AACzC,MAAM,IAAI,GAA6B,EAAE,CAAA;AACzC,MAAM,IAAI,GAA6C,EAAE,CAAA;AAEzD,IAAI,QAAQ,GAAa,CAAC,IAAY,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;AAIvD,MAAqB,IAAK,SAAQ,WAAW;IAuH3C,YAAY,EACV,QAAQ,EACR,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,IAAI,GAAG,EAAE,EACT,IAAI,EACJ,IAAI,GACK;QACT,KAAK,CAAC,IAAI,CAAC,CAAA;QAEX,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE;YAClC,UAAU,EAAE,KAAK;YACjB,KAAK,EAAE,EAAE;YACT,QAAQ,EAAE,IAAI;SACf,CAAC,CAAA;QAEF,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE;YAClC,UAAU,EAAE,KAAK;YACjB,KAAK,EAAE,IAAI;YACX,QAAQ,EAAE,IAAI;SACf,CAAC,CAAA;QAEF,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAC1B,CAAC;IAED,MAAM;QACJ,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAA;IACH,CAAC;;AAjJM,SAAI,GAAG,CAAC,IAAY,EAAE,IAAY,EAAE,IAAc,EAAE,EAAE;IAC3D,IAAI,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,GAAG,IAAI,CAAA;IAC9B,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AAEM,SAAI,GAAG,CAAC,IAAY,EAAE,IAA8B,EAAE,EAAE;IAC7D,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACjB,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AAEM,SAAI,GAAG,CAAC,IAAY,EAAE,IAAY,EAAE,IAAc,EAAE,EAAE;IAC3D,IAAI,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,GAAG,IAAI,CAAA;IAC9B,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AAEM,SAAI,GAAG,CAAC,IAAY,EAAE,IAAY,EAAE,IAAc,EAAE,EAAE;IAC3D,IAAI,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,GAAG,IAAI,CAAA;IAC9B,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AAEM,SAAI,GAAG,CAAC,IAAc,EAAE,EAAE;IAC/B,QAAQ,GAAG,IAAI,CAAA;IACf,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AAEM,aAAQ,GAAG,CAAC,IAAY,EAAE,EAAE;IACjC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAA;AACvB,CAAC,CAAA;AAEM,SAAI,GAAG,CAAC,IAAY,EAAE,IAAY,EAAE,IAAU,EAAE,EAAE;IACvD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;IACtC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,CAAA;IACpC,IAAI,CAAC,IAAI,EAAE;QACT,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,IAAI,IAAI,eAAe,CAAC,CAAA;KACxD;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAwB,CAAA;IAClD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC;QACpB,GAAG,QAAQ;QACX,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC;QACxC,IAAI;QACJ,IAAI;QACJ,IAAI,EAAE,IAAY;QAClB,IAAI;KACL,CAAC,CAAA;IAEF,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAEzB,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AAEM,aAAQ,GAAG,CAAC,IAAU,EAAE,IAAU,EAAE,EAAE;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;IAC9C,IAAI,CAAC,IAAI,EAAE;QACT,oEAAoE;QACpE,OAAM;KACP;IACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAA;AACxB,CAAC,CAAA;AAEM,aAAQ,GAAG,CAAC,IAAU,EAAE,EAAE;IAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;IAC9C,IAAI,CAAC,IAAI,EAAE;QACT,oEAAoE;QACpE,OAAM;KACP;IACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;AACxC,CAAC,CAAA;AAEM,aAAQ,GAAG,CAAC,IAAY,EAAE,QAAgB,EAAE,EAAE;IACnD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAA;IACvB,IAAI,CAAC,IAAI,EAAE;QACT,OAAO,QAAQ,CAAC,QAAQ,EAAE,CAAA;KAC3B;IACD,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAA;AACvB,CAAC,CAAA;AAEM,aAAQ,GAAG,CAChB,IAAW,EACX,EACE,QAAQ,EACR,IAAI,GAAG,KAAK,MAC6B,EAAE,EAC7C,EAAE;IACF,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;IACtC,OAAO,IAAI,IAAI,CAAC;QACd,IAAI,EACF,MAAM,IAAI,IAAI;YACZ,CAAC,CAAC,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;gBAC7B,CAAC,CAAC,IAAI,CAAC,IAAI;gBACX,CAAC,CAAC,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;oBAC/B,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC;oBACpC,CAAC,CAAC,MAAM;YACV,CAAC,CAAC,MAAM;QACZ,IAAI,EAAE,cAAc;QACpB,IAAI,EAAE,QAAQ;QACd,oDAAoD;QACpD,IAAI,EAAE,IAAI,CAAC,OAAO;QAClB,QAAQ;QACR,IAAI;KACL,CAAC,CAAA;AACJ,CAAC,CAAA;eArHkB,IAAI;AAuKzB,qDAAqD;AACrD,MAAM,OAAO,QAAS,SAAQ,IAAI;IAGhC,YAAY,IAAiB;QAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;QACtC,KAAK,CAAC;YACJ,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC,CAAC;YACxC,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,gBAAgB;YACtB,IAAI,EAAE,2BAA2B;YACjC,IAAI;SACL,CAAC,CAAA;QACF,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../code/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,QAAQ,CAAA;AAEzB,cAAc,QAAQ,CAAA;AACtB,cAAc,QAAQ,CAAA;AACtB,cAAc,QAAQ,CAAA;AAEtB,eAAe,IAAI,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import Kink, { KinkList } from '../base';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
export declare function isZodError<I>(input: any): input is z.SafeParseError<I>;
|
|
4
|
+
export declare function loadKink(error: any): Kink | undefined;
|
|
5
|
+
export declare function loadKinkList(error: any): Kink;
|
|
6
|
+
export declare function loadZodErrorJSON(error: z.ZodError): KinkList;
|
|
7
|
+
export { default } from './make';
|