v-transform 3.1.2 → 3.2.1
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/README.md +8 -1
- package/bin/index.js +186 -649
- package/package.json +10 -6
- package/src/calibrator.js +17 -3
- package/src/dump.js +1 -16
- package/src/index.js +7 -5
- package/src/loader.js +28 -15
- package/src/prepare.js +3 -4
- package/src/transform.js +6 -9
package/package.json
CHANGED
|
@@ -4,28 +4,32 @@
|
|
|
4
4
|
"vt": "bin/index.js"
|
|
5
5
|
},
|
|
6
6
|
"type": "module",
|
|
7
|
-
"version": "3.1
|
|
7
|
+
"version": "3.2.1",
|
|
8
8
|
"main": "src/index.js",
|
|
9
9
|
"scripts": {
|
|
10
10
|
"clean": "npx rimraf test",
|
|
11
11
|
"vt": "vt",
|
|
12
12
|
"transform": "vt transform",
|
|
13
|
-
"build": "
|
|
13
|
+
"build": "bun build src/index.js --target=bun --format=esm --minify --outfile=bin/index.js"
|
|
14
14
|
},
|
|
15
15
|
"repository": {
|
|
16
16
|
"type": "git",
|
|
17
|
-
"url": "git+https://github.com/VickScarlet/
|
|
17
|
+
"url": "git+https://github.com/VickScarlet/v-transform.git"
|
|
18
18
|
},
|
|
19
19
|
"author": "Vick Scarlet <scarlet_vick@outlook.com>",
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"commander": "^15.0.0",
|
|
23
|
-
"glob": "^13.0.6",
|
|
24
23
|
"js-yaml": "^5.2.3",
|
|
25
24
|
"ts-to-zod": "^5.1.0",
|
|
26
|
-
"tsup": "^8.5.1",
|
|
27
25
|
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
|
|
28
26
|
"zod": "^4.4.3"
|
|
29
27
|
},
|
|
30
|
-
"
|
|
28
|
+
"overrides": {
|
|
29
|
+
"@oclif/core": "^4"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"bin",
|
|
33
|
+
"src"
|
|
34
|
+
]
|
|
31
35
|
}
|
package/src/calibrator.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import fs from 'node:fs'
|
|
2
1
|
import { generate } from 'ts-to-zod'
|
|
3
2
|
import { z } from 'zod'
|
|
4
3
|
globalThis.__GLOBAL_ZOD__ = z
|
|
5
4
|
|
|
6
5
|
export async function calibrateTsData(raw, name, dts) {
|
|
7
|
-
|
|
6
|
+
const targetFile = Bun.file(dts)
|
|
7
|
+
if (!dts || !(await targetFile.exists())) {
|
|
8
8
|
console.warn(`⚠️ [Calibrator] ${name}.types.ts`)
|
|
9
9
|
return { raw, type: 'any', dts: '' }
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
console.info(`🔍 [Calibrator] ${name}.types.ts`)
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
const sourceText = await targetFile.text()
|
|
15
|
+
|
|
14
16
|
const options = {
|
|
15
17
|
keepOptionalProperties: true,
|
|
16
18
|
getSchemaName: identifier => `${identifier}Schema`,
|
|
@@ -35,6 +37,14 @@ export async function calibrateTsData(raw, name, dts) {
|
|
|
35
37
|
},
|
|
36
38
|
}
|
|
37
39
|
let zodRawCode = zod.getZodSchemasFile()
|
|
40
|
+
|
|
41
|
+
globalThis.__RUNNER_CONFIG_MODULE__ = configModule
|
|
42
|
+
zodRawCode = zodRawCode.replace(
|
|
43
|
+
/import\s+\{([^}]+)\}\s+from\s+['"]undefined['"];?/g,
|
|
44
|
+
(match, enumNamesStr) =>
|
|
45
|
+
`const {${enumNamesStr}} = globalThis.__RUNNER_CONFIG_MODULE__;`,
|
|
46
|
+
)
|
|
47
|
+
|
|
38
48
|
zodRawCode = zodRawCode.replace(
|
|
39
49
|
/import\s+\{\s*z\s*\}\s+from\s+['"]zod['"];?/g,
|
|
40
50
|
'const z = globalThis.__GLOBAL_ZOD__;',
|
|
@@ -62,6 +72,7 @@ export async function calibrateTsData(raw, name, dts) {
|
|
|
62
72
|
const RowZodValidator = zodModule[targetSchemaName]
|
|
63
73
|
if (!RowZodValidator) {
|
|
64
74
|
delete globalThis.__MERGED_TRANSFORMERS__
|
|
75
|
+
delete globalThis.__RUNNER_CONFIG_MODULE__
|
|
65
76
|
throw new Error(`❌ [Calibrator] ${targetSchemaName} Missmatch`)
|
|
66
77
|
}
|
|
67
78
|
const typeName = targetSchemaName.replace(/Schema$/, '')
|
|
@@ -85,6 +96,7 @@ export async function calibrateTsData(raw, name, dts) {
|
|
|
85
96
|
const parseResult = RowZodValidator.safeParse(raw[i])
|
|
86
97
|
if (!parseResult.success) {
|
|
87
98
|
delete globalThis.__MERGED_TRANSFORMERS__
|
|
99
|
+
delete globalThis.__RUNNER_CONFIG_MODULE__
|
|
88
100
|
printZodError(name, i, parseResult.error.issues, raw[i])
|
|
89
101
|
}
|
|
90
102
|
raw[i] = parseResult.data
|
|
@@ -95,6 +107,7 @@ export async function calibrateTsData(raw, name, dts) {
|
|
|
95
107
|
const parseResult = RowZodValidator.safeParse(raw[key])
|
|
96
108
|
if (!parseResult.success) {
|
|
97
109
|
delete globalThis.__MERGED_TRANSFORMERS__
|
|
110
|
+
delete globalThis.__RUNNER_CONFIG_MODULE__
|
|
98
111
|
printZodError(name, key, parseResult.error.issues, raw[key])
|
|
99
112
|
}
|
|
100
113
|
raw[key] = parseResult.data
|
|
@@ -103,6 +116,7 @@ export async function calibrateTsData(raw, name, dts) {
|
|
|
103
116
|
}
|
|
104
117
|
|
|
105
118
|
delete globalThis.__MERGED_TRANSFORMERS__
|
|
119
|
+
delete globalThis.__RUNNER_CONFIG_MODULE__
|
|
106
120
|
return data
|
|
107
121
|
}
|
|
108
122
|
|
package/src/dump.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { dump as dumpYAML } from 'js-yaml'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import { writeFile, stat, mkdir } from 'node:fs/promises'
|
|
4
2
|
|
|
5
3
|
function j(data, space) {
|
|
6
4
|
return JSON.stringify(data, null, space)
|
|
@@ -104,22 +102,9 @@ function tsify({ name, data, space, toMap }) {
|
|
|
104
102
|
return [rows.join('\n')]
|
|
105
103
|
}
|
|
106
104
|
|
|
107
|
-
async function mkdirs(dir) {
|
|
108
|
-
try {
|
|
109
|
-
await stat(dir)
|
|
110
|
-
} catch (e) {
|
|
111
|
-
if (e.code !== 'ENOENT') {
|
|
112
|
-
throw e
|
|
113
|
-
}
|
|
114
|
-
await mkdirs(path.dirname(dir))
|
|
115
|
-
await mkdir(dir)
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
105
|
async function write(sheet, data) {
|
|
120
106
|
console.info(`📦 -> ${sheet}`)
|
|
121
|
-
await
|
|
122
|
-
await writeFile(sheet, data)
|
|
107
|
+
return await Bun.write(sheet, data)
|
|
123
108
|
}
|
|
124
109
|
|
|
125
110
|
export async function dump({ sheet, type, ext, map, types, ...args }) {
|
package/src/index.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
2
|
import { Command } from 'commander'
|
|
3
|
-
import { readFile } from 'node:fs/promises'
|
|
4
3
|
import { transform } from './transform.js'
|
|
5
4
|
|
|
6
5
|
const program = new Command()
|
|
7
6
|
|
|
8
7
|
program.name('vt')
|
|
9
|
-
|
|
8
|
+
|
|
9
|
+
const pkg = await Bun.file('package.json').json()
|
|
10
|
+
program.version(pkg.version)
|
|
11
|
+
|
|
10
12
|
program
|
|
11
13
|
.command('transform [list...]')
|
|
12
14
|
.option(
|
|
@@ -14,7 +16,7 @@ program
|
|
|
14
16
|
'type of transform, available: js, ts, esm, cjs, json',
|
|
15
17
|
'json',
|
|
16
18
|
)
|
|
17
|
-
.option('-s, --space <space>', 'format space number', 0)
|
|
19
|
+
.option('-s, --space <space>', 'format space number', Number, 0)
|
|
18
20
|
.option('-c, --config <config>', 'configure file', null)
|
|
19
21
|
.option('-w, --cwd <cwd>', 'current work dir', null)
|
|
20
22
|
.option('-o, --output <output>', 'output dir', null)
|
|
@@ -29,4 +31,4 @@ program
|
|
|
29
31
|
transform(options)
|
|
30
32
|
})
|
|
31
33
|
|
|
32
|
-
program.parse(
|
|
34
|
+
program.parse(Bun.argv)
|
package/src/loader.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import { glob } from 'glob'
|
|
2
1
|
import { load as loadYAML } from 'js-yaml'
|
|
3
|
-
import path from 'node:path'
|
|
4
|
-
import { readFile } from 'node:fs/promises'
|
|
5
2
|
|
|
6
3
|
export async function load(args) {
|
|
7
4
|
const { config, list, ...a } = args
|
|
8
5
|
const version = new Date().toISOString()
|
|
9
6
|
const type = args.type || 'json'
|
|
10
|
-
const cwd = args.cwd ||
|
|
7
|
+
const cwd = args.cwd || Bun.cwd
|
|
11
8
|
const space = Number(args.space) || 0
|
|
12
9
|
const dest = args.dest || cwd
|
|
13
10
|
const types = !args.notypes
|
|
@@ -32,17 +29,18 @@ export async function load(args) {
|
|
|
32
29
|
|
|
33
30
|
async function loadConfigData(config, def, m) {
|
|
34
31
|
const c = await loadConfig(config)
|
|
35
|
-
const dir =
|
|
32
|
+
const dir = config.substring(0, config.lastIndexOf('/')) || '.'
|
|
36
33
|
const cdef = {}
|
|
37
|
-
|
|
34
|
+
|
|
35
|
+
if (c.cwd) cdef.cwd = `${dir}/${c.cwd}`
|
|
38
36
|
if (c.type) cdef.type = c.type
|
|
39
37
|
if (typeof c.space == 'number') cdef.space = c.space
|
|
40
|
-
if (c.dest) cdef.dest =
|
|
38
|
+
if (c.dest) cdef.dest = `${dir}/${c.dest}`
|
|
41
39
|
const cfgs = []
|
|
42
40
|
|
|
43
41
|
for (const cfg of c.configurations) {
|
|
44
|
-
if (cfg.cwd) cfg.cwd =
|
|
45
|
-
if (cfg.dest) cfg.dest =
|
|
42
|
+
if (cfg.cwd) cfg.cwd = `${dir}/${cfg.cwd}`
|
|
43
|
+
if (cfg.dest) cfg.dest = `${dir}/${cfg.dest}`
|
|
46
44
|
cfgs.push(await m(def, cdef, cfg))
|
|
47
45
|
}
|
|
48
46
|
|
|
@@ -50,13 +48,15 @@ async function loadConfigData(config, def, m) {
|
|
|
50
48
|
}
|
|
51
49
|
|
|
52
50
|
async function loadConfig(config) {
|
|
53
|
-
|
|
51
|
+
const ext = config.substring(config.lastIndexOf('.'))
|
|
52
|
+
switch (ext) {
|
|
54
53
|
case '.json':
|
|
55
54
|
case '.yaml':
|
|
56
55
|
case '.yml':
|
|
57
|
-
return loadYAML(await
|
|
56
|
+
return loadYAML(await Bun.file(config).text())
|
|
58
57
|
case '.js':
|
|
59
58
|
case '.mjs':
|
|
59
|
+
case '.ts':
|
|
60
60
|
return (await import(config)).default
|
|
61
61
|
default:
|
|
62
62
|
throw new Error(`Unknown config file type: ${config}`)
|
|
@@ -66,10 +66,23 @@ async function loadConfig(config) {
|
|
|
66
66
|
async function globit(options) {
|
|
67
67
|
const { glob: gs, cwd } = options
|
|
68
68
|
const files = []
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
|
|
70
|
+
const scanGlob = async pattern => {
|
|
71
|
+
const globInstance = new Bun.Glob(pattern)
|
|
72
|
+
const matched = []
|
|
73
|
+
for await (const file of globInstance.scan({ cwd })) {
|
|
74
|
+
matched.push(file)
|
|
75
|
+
}
|
|
76
|
+
return matched
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (Array.isArray(gs)) {
|
|
80
|
+
for (const p of gs) files.push(...(await scanGlob(p)))
|
|
81
|
+
} else if (typeof gs == 'string') {
|
|
82
|
+
files.push(...(await scanGlob(gs)))
|
|
83
|
+
} else {
|
|
84
|
+
throw new Error(`Unknown glob type: ${gs}`)
|
|
85
|
+
}
|
|
73
86
|
|
|
74
87
|
return { ...options, files }
|
|
75
88
|
}
|
package/src/prepare.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
|
-
import { readFile } from 'node:fs/promises'
|
|
3
1
|
import { read, utils } from 'xlsx'
|
|
4
2
|
|
|
5
3
|
export async function prepare(xlsxPath) {
|
|
6
|
-
|
|
4
|
+
const ext = xlsxPath.substring(xlsxPath.lastIndexOf('.')).toLowerCase()
|
|
5
|
+
switch (ext) {
|
|
7
6
|
case '.xls':
|
|
8
7
|
case '.xlsx':
|
|
9
8
|
break
|
|
10
9
|
default:
|
|
11
10
|
return []
|
|
12
11
|
}
|
|
13
|
-
const xlsxFileBuffer = await
|
|
12
|
+
const xlsxFileBuffer = await Bun.file(xlsxPath).arrayBuffer()
|
|
14
13
|
const xlsx = read(xlsxFileBuffer, { type: 'buffer' })
|
|
15
14
|
const datas = []
|
|
16
15
|
for (const name in xlsx.Sheets) {
|
package/src/transform.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
1
|
import { load } from './loader.js'
|
|
3
2
|
import { prepare } from './prepare.js'
|
|
4
3
|
import { parser } from './parser.js'
|
|
@@ -17,8 +16,8 @@ async function task(options) {
|
|
|
17
16
|
const { files, dest, cwd, addition, ...opts } = options
|
|
18
17
|
const m = new Map()
|
|
19
18
|
for (const file of files) {
|
|
20
|
-
const dir =
|
|
21
|
-
await processPrepared(
|
|
19
|
+
const dir = `${dest}/${file.substring(0, file.lastIndexOf('/')) || '.'}`
|
|
20
|
+
await processPrepared(`${cwd}/${file}`, dir, m)
|
|
22
21
|
}
|
|
23
22
|
for (const [sheet, job] of m) {
|
|
24
23
|
const data = await job.result(addition)
|
|
@@ -28,7 +27,7 @@ async function task(options) {
|
|
|
28
27
|
|
|
29
28
|
async function processPrepared(src, dir, m) {
|
|
30
29
|
const prepared = await prepare(src)
|
|
31
|
-
const xlsxDir =
|
|
30
|
+
const xlsxDir = src.substring(0, src.lastIndexOf('/')) || '.'
|
|
32
31
|
for (const { name, data } of prepared) {
|
|
33
32
|
if (name.startsWith('#')) continue
|
|
34
33
|
const { sheet, keys, name: parsedName } = parseSheetAndKeys(name, dir)
|
|
@@ -43,7 +42,7 @@ function parseSheetAndKeys(name, dir) {
|
|
|
43
42
|
if (sheet.startsWith('>')) sheet = sheet.substring(1)
|
|
44
43
|
const keys = sheet.split('.')
|
|
45
44
|
let key = keys.shift()
|
|
46
|
-
sheet =
|
|
45
|
+
sheet = `${dir}/${key}`
|
|
47
46
|
return { sheet, keys, name: key }
|
|
48
47
|
}
|
|
49
48
|
|
|
@@ -80,7 +79,7 @@ class JobData {
|
|
|
80
79
|
}
|
|
81
80
|
r[last] = this.#combine(r[last], data)
|
|
82
81
|
}
|
|
83
|
-
const dts =
|
|
82
|
+
const dts = `${this.#xlsxDir}/${this.#name}.types.ts`
|
|
84
83
|
const data = await calibrateTsData(result, this.#name, dts)
|
|
85
84
|
return { ...data, pk: this.#pk, addition }
|
|
86
85
|
}
|
|
@@ -89,9 +88,7 @@ class JobData {
|
|
|
89
88
|
if (a == null) return b
|
|
90
89
|
if (b == null) return a
|
|
91
90
|
if (Array.isArray(a) && Array.isArray(b)) {
|
|
92
|
-
|
|
93
|
-
a.push(b)
|
|
94
|
-
return a
|
|
91
|
+
return a.concat(b)
|
|
95
92
|
}
|
|
96
93
|
if (Array.isArray(a)) return this.#combine(a, Object.values(b))
|
|
97
94
|
if (Array.isArray(b)) return this.#combine(Object.values(a), b)
|