@kubb/core 2.0.0-alpha.3 → 2.0.0-alpha.5
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/dist/index.cjs +70 -75
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +198 -215
- package/dist/index.d.ts +198 -215
- package/dist/index.js +70 -73
- package/dist/index.js.map +1 -1
- package/dist/utils.cjs +19 -8
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +6 -2
- package/dist/utils.d.ts +6 -2
- package/dist/utils.js +19 -8
- package/dist/utils.js.map +1 -1
- package/package.json +7 -5
- package/src/BarrelManager.ts +123 -0
- package/src/FileManager.ts +483 -0
- package/src/Generator.ts +34 -0
- package/src/PackageManager.ts +163 -0
- package/src/PluginManager.ts +644 -0
- package/src/PromiseManager.ts +47 -0
- package/src/SchemaGenerator.ts +8 -0
- package/src/build.ts +207 -0
- package/src/config.ts +22 -0
- package/src/errors.ts +12 -0
- package/src/index.ts +28 -0
- package/src/plugin.ts +80 -0
- package/src/types.ts +346 -0
- package/src/utils/EventEmitter.ts +24 -0
- package/src/utils/FunctionParams.ts +85 -0
- package/src/utils/Queue.ts +110 -0
- package/src/utils/TreeNode.ts +122 -0
- package/src/utils/URLPath.ts +128 -0
- package/src/utils/cache.ts +35 -0
- package/src/utils/clean.ts +5 -0
- package/src/utils/executeStrategies.ts +71 -0
- package/src/utils/index.ts +19 -0
- package/src/utils/logger.ts +76 -0
- package/src/utils/promise.ts +13 -0
- package/src/utils/randomColour.ts +39 -0
- package/src/utils/read.ts +68 -0
- package/src/utils/renderTemplate.ts +31 -0
- package/src/utils/throttle.ts +30 -0
- package/src/utils/timeout.ts +7 -0
- package/src/utils/transformers/combineCodes.ts +3 -0
- package/src/utils/transformers/createJSDocBlockText.ts +15 -0
- package/src/utils/transformers/escape.ts +31 -0
- package/src/utils/transformers/indent.ts +3 -0
- package/src/utils/transformers/index.ts +22 -0
- package/src/utils/transformers/nameSorter.ts +9 -0
- package/src/utils/transformers/searchAndReplace.ts +25 -0
- package/src/utils/transformers/transformReservedWord.ts +97 -0
- package/src/utils/transformers/trim.ts +3 -0
- package/src/utils/uniqueName.ts +20 -0
- package/src/utils/write.ts +63 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import pc from 'picocolors'
|
|
2
|
+
import seedrandom from 'seedrandom'
|
|
3
|
+
|
|
4
|
+
import type { Formatter } from 'picocolors/types.ts'
|
|
5
|
+
|
|
6
|
+
const defaultColours = ['black', 'blue', 'darkBlue', 'cyan', 'gray', 'green', 'darkGreen', 'magenta', 'red', 'darkRed', 'yellow', 'darkYellow'] as const
|
|
7
|
+
|
|
8
|
+
export function randomColour(text?: string, colours = defaultColours): string {
|
|
9
|
+
if (!text) {
|
|
10
|
+
return 'white'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const random = seedrandom(text)
|
|
14
|
+
const colour = colours.at(Math.floor(random() * colours.length)) || 'white'
|
|
15
|
+
|
|
16
|
+
return colour
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function randomPicoColour(text?: string, colors = defaultColours): string {
|
|
20
|
+
const colours = pc.createColors(true)
|
|
21
|
+
|
|
22
|
+
if (!text) {
|
|
23
|
+
return colours.white(text)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const colour = randomColour(text, colors)
|
|
27
|
+
const isDark = colour.includes('dark')
|
|
28
|
+
const key = colour.replace('dark', '').toLowerCase() as keyof typeof colours
|
|
29
|
+
const formatter: Formatter = colours[key] as Formatter
|
|
30
|
+
|
|
31
|
+
if (isDark) {
|
|
32
|
+
return pc.bold(formatter(text))
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (typeof formatter !== 'function') {
|
|
36
|
+
throw new Error('Formatter for picoColor is not of type function/Formatter')
|
|
37
|
+
}
|
|
38
|
+
return formatter(text)
|
|
39
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { basename, extname, relative } from 'node:path'
|
|
2
|
+
|
|
3
|
+
import fs from 'fs-extra'
|
|
4
|
+
import { switcher } from 'js-runtime'
|
|
5
|
+
|
|
6
|
+
function slash(path: string, platform: 'windows' | 'mac' | 'linux' = 'linux') {
|
|
7
|
+
const isWindowsPath = /^\\\\\?\\/.test(path)
|
|
8
|
+
|
|
9
|
+
if (['linux', 'mac'].includes(platform) && !isWindowsPath) {
|
|
10
|
+
// linux and mac
|
|
11
|
+
return path.replaceAll(/\\/g, '/').replace('../', '').trimEnd()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// windows
|
|
15
|
+
return path.replaceAll(/\\/g, '/').replace('../', '').trimEnd()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function getRelativePath(rootDir?: string | null, filePath?: string | null, platform: 'windows' | 'mac' | 'linux' = 'linux'): string {
|
|
19
|
+
if (!rootDir || !filePath) {
|
|
20
|
+
throw new Error(`Root and file should be filled in when retrieving the relativePath, ${rootDir || ''} ${filePath || ''}`)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const relativePath = relative(rootDir, filePath)
|
|
24
|
+
|
|
25
|
+
// On Windows, paths are separated with a "\"
|
|
26
|
+
// However, web browsers use "/" no matter the platform
|
|
27
|
+
const slashedPath = slash(relativePath, platform)
|
|
28
|
+
|
|
29
|
+
if (slashedPath.startsWith('../')) {
|
|
30
|
+
return slashedPath.replace(basename(slashedPath), basename(slashedPath, extname(filePath)))
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return `./${slashedPath.replace(basename(slashedPath), basename(slashedPath, extname(filePath)))}`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const reader = switcher(
|
|
37
|
+
{
|
|
38
|
+
node: async (path: string) => {
|
|
39
|
+
return fs.readFile(path, { encoding: 'utf8' })
|
|
40
|
+
},
|
|
41
|
+
bun: async (path: string) => {
|
|
42
|
+
const file = Bun.file(path)
|
|
43
|
+
|
|
44
|
+
return file.text()
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
'node',
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
const syncReader = switcher(
|
|
51
|
+
{
|
|
52
|
+
node: (path: string) => {
|
|
53
|
+
return fs.readFileSync(path, { encoding: 'utf8' })
|
|
54
|
+
},
|
|
55
|
+
bun: () => {
|
|
56
|
+
throw new Error('Bun cannot read sync')
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
'node',
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
export async function read(path: string): Promise<string> {
|
|
63
|
+
return reader(path)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function readSync(path: string): string {
|
|
67
|
+
return syncReader(path)
|
|
68
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function renderTemplate<TData extends Record<string, unknown> = Record<string, unknown>>(template: string, data: TData | undefined = undefined): string {
|
|
2
|
+
if (!data || !Object.keys(data).length) {
|
|
3
|
+
return template.replace(/{{(.*?)}}/g, '')
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const matches = template.match(/{{(.*?)}}/g)
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
matches?.reduce((prev, curr) => {
|
|
10
|
+
const index = curr.split(/{{|}}/).filter(Boolean)[0]?.trim()
|
|
11
|
+
if (index === undefined) {
|
|
12
|
+
return prev
|
|
13
|
+
}
|
|
14
|
+
const value = data[index]
|
|
15
|
+
|
|
16
|
+
if (value === undefined) {
|
|
17
|
+
return prev
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return prev
|
|
21
|
+
.replace(curr, () => {
|
|
22
|
+
if (typeof value === 'boolean') {
|
|
23
|
+
return `${value.toString()}` || 'false'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return (value as string) || ''
|
|
27
|
+
})
|
|
28
|
+
.trim()
|
|
29
|
+
}, template) || ''
|
|
30
|
+
)
|
|
31
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const throttle = <R, A extends any[]>(fn: (...args: A) => R, delay: number): [(...args: A) => R | undefined, () => void] => {
|
|
2
|
+
let wait = false
|
|
3
|
+
let timeout: NodeJS.Timeout
|
|
4
|
+
let cancelled = false
|
|
5
|
+
|
|
6
|
+
return [
|
|
7
|
+
(...args: A) => {
|
|
8
|
+
if (cancelled) {
|
|
9
|
+
return undefined
|
|
10
|
+
}
|
|
11
|
+
if (wait) {
|
|
12
|
+
return undefined
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const val = fn(...args)
|
|
16
|
+
|
|
17
|
+
wait = true
|
|
18
|
+
|
|
19
|
+
timeout = setTimeout(() => {
|
|
20
|
+
wait = false
|
|
21
|
+
}, delay)
|
|
22
|
+
|
|
23
|
+
return val
|
|
24
|
+
},
|
|
25
|
+
() => {
|
|
26
|
+
cancelled = true
|
|
27
|
+
clearTimeout(timeout)
|
|
28
|
+
},
|
|
29
|
+
]
|
|
30
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function createJSDocBlockText({ comments, newLine }: { comments: Array<string>; newLine?: boolean }): string {
|
|
2
|
+
const filteredComments = comments.filter(Boolean)
|
|
3
|
+
|
|
4
|
+
if (!filteredComments.length) {
|
|
5
|
+
return ''
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const source = `/**\n * ${filteredComments.join('\n * ')}\n */`
|
|
9
|
+
|
|
10
|
+
if (newLine) {
|
|
11
|
+
return `${source}\n`
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return source
|
|
15
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function escape(text?: string): string {
|
|
2
|
+
return text ? text.replaceAll('`', '\\`') : ''
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Escape all characters not included in SingleStringCharacters and DoubleStringCharacters on
|
|
7
|
+
* @link http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4
|
|
8
|
+
* @link https://github.com/joliss/js-string-escape/blob/master/index.js
|
|
9
|
+
*/
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
11
|
+
export function jsStringEscape(input: any): string {
|
|
12
|
+
return `${input}`.replace(/["'\\\n\r\u2028\u2029]/g, (character) => {
|
|
13
|
+
switch (character) {
|
|
14
|
+
case '"':
|
|
15
|
+
case "'":
|
|
16
|
+
case '\\':
|
|
17
|
+
return '\\' + character
|
|
18
|
+
// Four possible LineTerminator characters need to be escaped:
|
|
19
|
+
case '\n':
|
|
20
|
+
return '\\n'
|
|
21
|
+
case '\r':
|
|
22
|
+
return '\\r'
|
|
23
|
+
case '\u2028':
|
|
24
|
+
return '\\u2028'
|
|
25
|
+
case '\u2029':
|
|
26
|
+
return '\\u2029'
|
|
27
|
+
default:
|
|
28
|
+
return ''
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { combineCodes } from './combineCodes.ts'
|
|
2
|
+
import { createJSDocBlockText } from './createJSDocBlockText.ts'
|
|
3
|
+
import { escape, jsStringEscape } from './escape.ts'
|
|
4
|
+
import { createIndent } from './indent.ts'
|
|
5
|
+
import { nameSorter } from './nameSorter.ts'
|
|
6
|
+
import { searchAndReplace } from './searchAndReplace.ts'
|
|
7
|
+
import { transformReservedWord } from './transformReservedWord.ts'
|
|
8
|
+
import { trim } from './trim.ts'
|
|
9
|
+
|
|
10
|
+
export const transformers = {
|
|
11
|
+
combineCodes,
|
|
12
|
+
escape,
|
|
13
|
+
jsStringEscape,
|
|
14
|
+
createIndent,
|
|
15
|
+
transformReservedWord,
|
|
16
|
+
nameSorter,
|
|
17
|
+
searchAndReplace,
|
|
18
|
+
trim,
|
|
19
|
+
JSDoc: {
|
|
20
|
+
createJSDocBlockText,
|
|
21
|
+
},
|
|
22
|
+
} as const
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
type Options = {
|
|
2
|
+
text: string
|
|
3
|
+
replaceBy: string
|
|
4
|
+
prefix?: string
|
|
5
|
+
key: string
|
|
6
|
+
searchValues?: (prefix: string, key: string) => Array<RegExp | string>
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function searchAndReplace(options: Options): string {
|
|
10
|
+
const { text, replaceBy, prefix = '', key } = options
|
|
11
|
+
|
|
12
|
+
const searchValues = options.searchValues?.(prefix, key) || [
|
|
13
|
+
`${prefix}["${key}"]`,
|
|
14
|
+
`${prefix}['${key}']`,
|
|
15
|
+
`${prefix}[\`${key}\`]`,
|
|
16
|
+
`${prefix}"${key}"`,
|
|
17
|
+
`${prefix}'${key}'`,
|
|
18
|
+
`${prefix}\`${key}\``,
|
|
19
|
+
new RegExp(`${prefix}${key}`, 'g'),
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
return searchValues.reduce((prev, searchValue) => {
|
|
23
|
+
return prev.toString().replaceAll(searchValue, replaceBy)
|
|
24
|
+
}, text) as string
|
|
25
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @link https://github.com/jonschlinkert/reserved/blob/master/index.js
|
|
3
|
+
*/
|
|
4
|
+
const reservedWords = [
|
|
5
|
+
'abstract',
|
|
6
|
+
'arguments',
|
|
7
|
+
'boolean',
|
|
8
|
+
'break',
|
|
9
|
+
'byte',
|
|
10
|
+
'case',
|
|
11
|
+
'catch',
|
|
12
|
+
'char',
|
|
13
|
+
'class',
|
|
14
|
+
'const',
|
|
15
|
+
'continue',
|
|
16
|
+
'debugger',
|
|
17
|
+
'default',
|
|
18
|
+
'delete',
|
|
19
|
+
'do',
|
|
20
|
+
'double',
|
|
21
|
+
'else',
|
|
22
|
+
'enum',
|
|
23
|
+
'eval',
|
|
24
|
+
'export',
|
|
25
|
+
'extends',
|
|
26
|
+
'false',
|
|
27
|
+
'final',
|
|
28
|
+
'finally',
|
|
29
|
+
'float',
|
|
30
|
+
'for',
|
|
31
|
+
'function',
|
|
32
|
+
'goto',
|
|
33
|
+
'if',
|
|
34
|
+
'implements',
|
|
35
|
+
'import',
|
|
36
|
+
'in',
|
|
37
|
+
'instanceof',
|
|
38
|
+
'int',
|
|
39
|
+
'interface',
|
|
40
|
+
'let',
|
|
41
|
+
'long',
|
|
42
|
+
'native',
|
|
43
|
+
'new',
|
|
44
|
+
'null',
|
|
45
|
+
'package',
|
|
46
|
+
'private',
|
|
47
|
+
'protected',
|
|
48
|
+
'public',
|
|
49
|
+
'return',
|
|
50
|
+
'short',
|
|
51
|
+
'static',
|
|
52
|
+
'super',
|
|
53
|
+
'switch',
|
|
54
|
+
'synchronized',
|
|
55
|
+
'this',
|
|
56
|
+
'throw',
|
|
57
|
+
'throws',
|
|
58
|
+
'transient',
|
|
59
|
+
'true',
|
|
60
|
+
'try',
|
|
61
|
+
'typeof',
|
|
62
|
+
'var',
|
|
63
|
+
'void',
|
|
64
|
+
'volatile',
|
|
65
|
+
'while',
|
|
66
|
+
'with',
|
|
67
|
+
'yield',
|
|
68
|
+
|
|
69
|
+
'Array',
|
|
70
|
+
'Date',
|
|
71
|
+
'eval',
|
|
72
|
+
'function',
|
|
73
|
+
'hasOwnProperty',
|
|
74
|
+
'Infinity',
|
|
75
|
+
'isFinite',
|
|
76
|
+
'isNaN',
|
|
77
|
+
'isPrototypeOf',
|
|
78
|
+
'length',
|
|
79
|
+
'Math',
|
|
80
|
+
'name',
|
|
81
|
+
'NaN',
|
|
82
|
+
'Number',
|
|
83
|
+
'Object',
|
|
84
|
+
'prototype',
|
|
85
|
+
'String',
|
|
86
|
+
'toString',
|
|
87
|
+
'undefined',
|
|
88
|
+
'valueOf',
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
export function transformReservedWord(word: string): string {
|
|
92
|
+
if ((word && reservedWords.includes(word)) || word?.match(/^\d/)) {
|
|
93
|
+
return `_${word}`
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return word
|
|
97
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function getUniqueName(originalName: string, data: Record<string, number>): string {
|
|
2
|
+
let used = data[originalName] || 0
|
|
3
|
+
if (used) {
|
|
4
|
+
data[originalName] = ++used
|
|
5
|
+
originalName += used
|
|
6
|
+
}
|
|
7
|
+
data[originalName] = 1
|
|
8
|
+
return originalName
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function setUniqueName(originalName: string, data: Record<string, number>): string {
|
|
12
|
+
let used = data[originalName] || 0
|
|
13
|
+
if (used) {
|
|
14
|
+
data[originalName] = ++used
|
|
15
|
+
|
|
16
|
+
return originalName
|
|
17
|
+
}
|
|
18
|
+
data[originalName] = 1
|
|
19
|
+
return originalName
|
|
20
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { dirname, resolve } from 'node:path'
|
|
2
|
+
|
|
3
|
+
import fs from 'fs-extra'
|
|
4
|
+
import { switcher } from 'js-runtime'
|
|
5
|
+
|
|
6
|
+
async function saveCreateDirectory(path: string): Promise<void> {
|
|
7
|
+
// resolve the full path and get just the directory, ignoring the file and extension
|
|
8
|
+
const passedPath = dirname(resolve(path))
|
|
9
|
+
// make the directory, recursively. Theoretically, if every directory in the path exists, this won't do anything.
|
|
10
|
+
await fs.mkdir(passedPath, { recursive: true })
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const writer = switcher(
|
|
14
|
+
{
|
|
15
|
+
node: async (path: string, data: string) => {
|
|
16
|
+
try {
|
|
17
|
+
await fs.stat(resolve(path))
|
|
18
|
+
const oldContent = await fs.readFile(resolve(path), { encoding: 'utf-8' })
|
|
19
|
+
if (oldContent?.toString() === data?.toString()) {
|
|
20
|
+
return
|
|
21
|
+
}
|
|
22
|
+
} catch (_err) {
|
|
23
|
+
/* empty */
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
await saveCreateDirectory(path)
|
|
27
|
+
await fs.writeFile(resolve(path), data, { encoding: 'utf-8' })
|
|
28
|
+
|
|
29
|
+
const savedData = await fs.readFile(resolve(path), { encoding: 'utf-8' })
|
|
30
|
+
|
|
31
|
+
if (savedData?.toString() !== data?.toString()) {
|
|
32
|
+
throw new Error(`Sanity check failed for ${path}\n\nData[${data.length}]:\n${data}\n\nSaved[${savedData.length}]:\n${savedData}\n`)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return savedData
|
|
36
|
+
},
|
|
37
|
+
bun: async (path: string, data: string) => {
|
|
38
|
+
try {
|
|
39
|
+
await saveCreateDirectory(path)
|
|
40
|
+
await Bun.write(resolve(path), data)
|
|
41
|
+
|
|
42
|
+
const file = Bun.file(resolve(path))
|
|
43
|
+
const savedData = await file.text()
|
|
44
|
+
|
|
45
|
+
if (savedData?.toString() !== data?.toString()) {
|
|
46
|
+
throw new Error(`Sanity check failed for ${path}\n\nData[${data.length}]:\n${data}\n\nSaved[${savedData.length}]:\n${savedData}\n`)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return savedData
|
|
50
|
+
} catch (e) {
|
|
51
|
+
console.log(e, resolve(path))
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
'node',
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
export async function write(data: string, path: string): Promise<string | undefined> {
|
|
59
|
+
if (data.trim() === '') {
|
|
60
|
+
return undefined
|
|
61
|
+
}
|
|
62
|
+
return writer(path, data.trim())
|
|
63
|
+
}
|