milkio 0.0.12 β 0.0.13
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/c.ts +0 -8
- package/package.json +1 -1
- package/scripts/gen-insignificant.ts +5 -5
- package/scripts-del/build-cookbook.ts +0 -233
- package/scripts-del/build-dto.ts +0 -65
- package/scripts-del/generate/generate-app-partial.ts +0 -74
- package/scripts-del/generate/generate-app.ts +0 -152
- package/scripts-del/generate/generate-database.ts +0 -22
- package/scripts-del/generate-partial.ts +0 -15
- package/scripts-del/generate.ts +0 -23
package/c.ts
CHANGED
|
@@ -26,14 +26,6 @@ const commands = {
|
|
|
26
26
|
await (await import('./scripts/gen-insignificant')).default()
|
|
27
27
|
console.log("\nβ
Milkio Insignificant Generated!")
|
|
28
28
|
},
|
|
29
|
-
// async "build:cookbook"() {
|
|
30
|
-
// await exec(rootPath, ["bun", "./node_modules/milkio/scripts/build-cookbook.ts"])
|
|
31
|
-
// },
|
|
32
|
-
// async "build:dto"() {
|
|
33
|
-
// await exec(join(rootPath, "packages", "dto"), ["bun", "i"])
|
|
34
|
-
// await exec(rootPath, ["bun", "./node_modules/milkio/scripts/generate.ts"])
|
|
35
|
-
// await exec(rootPath, ["bun", "./node_modules/milkio/scripts/build-dto.ts"])
|
|
36
|
-
// },
|
|
37
29
|
async EAR(commandBase64ed: string) {
|
|
38
30
|
try { await $`clear` } catch (e) {}
|
|
39
31
|
const command = Buffer.from(commandBase64ed, 'base64').toString('utf-8')
|
package/package.json
CHANGED
|
@@ -237,15 +237,15 @@ export default async () => {
|
|
|
237
237
|
console.timeEnd(`π§ Cookbook Stage`)
|
|
238
238
|
console.log(``)
|
|
239
239
|
|
|
240
|
-
console.time(`π§
|
|
241
|
-
await $`bun run ./node_modules/typescript/bin/tsc --outDir "./packages/
|
|
240
|
+
console.time(`π§ Client Stage`)
|
|
241
|
+
await $`bun run ./node_modules/typescript/bin/tsc --outDir "./packages/client/project"`.quiet()
|
|
242
242
|
await Bun.build({
|
|
243
|
-
entrypoints: ["./packages/
|
|
244
|
-
outdir: "./packages/
|
|
243
|
+
entrypoints: ["./packages/client/index.ts"],
|
|
244
|
+
outdir: "./packages/client/dist",
|
|
245
245
|
target: 'browser',
|
|
246
246
|
minify: true
|
|
247
247
|
})
|
|
248
|
-
console.timeEnd(`π§
|
|
248
|
+
console.timeEnd(`π§ Client Stage`)
|
|
249
249
|
console.log(``)
|
|
250
250
|
|
|
251
251
|
if (!existsSync(join(cwd(), "milkio.toml"))) return
|
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console, @typescript-eslint/no-dynamic-delete */
|
|
2
|
-
|
|
3
|
-
import { TSON, type Cookbook } from ".."
|
|
4
|
-
import { join } from "node:path"
|
|
5
|
-
import { cwd } from "node:process"
|
|
6
|
-
import { writeFile, readFile } from "node:fs/promises"
|
|
7
|
-
|
|
8
|
-
export async function buildCookbook() {
|
|
9
|
-
const schema = await import("../../../generated/api-schema")
|
|
10
|
-
const paths = Object.keys(schema.default.apiMethodsSchema)
|
|
11
|
-
|
|
12
|
-
const cookbook: Cookbook = {}
|
|
13
|
-
for (const path of paths) {
|
|
14
|
-
// const module = await import(/* @vite-ignore */ join(`../../../src/apps/${path}`));
|
|
15
|
-
const code = (await readFile(join(cwd(), `./src/apps/${path}.ts`))).toString()
|
|
16
|
-
const codeLines = code.split("\n")
|
|
17
|
-
let title
|
|
18
|
-
let desc
|
|
19
|
-
const descRaw = /\n\/\*\*\n[\s\S]+?\*\//.exec(code)?.[0] ?? ""
|
|
20
|
-
|
|
21
|
-
if (descRaw) {
|
|
22
|
-
const descRawLines = descRaw.split("\n")
|
|
23
|
-
if (descRawLines.at(0)?.trim() === "") descRawLines.shift()
|
|
24
|
-
if (descRawLines.at(-1)?.trim() === "") descRawLines.pop()
|
|
25
|
-
let first = true
|
|
26
|
-
for (let index = 0; index < descRawLines.length; index++) {
|
|
27
|
-
const descRawLine = descRawLines[index].replace(/^[/ ]+?[*]*/, "").replace(/[*]*\/$/, "")
|
|
28
|
-
|
|
29
|
-
if (!descRawLine) continue
|
|
30
|
-
if (first) {
|
|
31
|
-
title = descRawLine.replace(/#/g, "").trim()
|
|
32
|
-
// Originally the title was in the first line, desc is the rest of it, now desc contains complete markdown content.
|
|
33
|
-
// continue;
|
|
34
|
-
}
|
|
35
|
-
first = false
|
|
36
|
-
desc = (desc ?? "") + "\n" + descRawLine.trim()
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
let apiParams = /action\([\s\S]+?\)/.exec(code)?.[0] ?? "" // The intention of the following code is to extract the parameter part of the action.
|
|
41
|
-
apiParams = /\([\s\S]*,/.exec(apiParams)?.[0] ?? ""
|
|
42
|
-
apiParams = apiParams.slice(0, -1)
|
|
43
|
-
apiParams = apiParams.slice(/[\s\S]+?:/.exec(apiParams)?.[0].length)
|
|
44
|
-
const apiParamsLines = apiParams.split("\n") // The intention of the following code is to remove extra spaces, which will make the code look more beautiful.
|
|
45
|
-
if (apiParamsLines.at(-1)?.trim() === "") apiParamsLines.pop()
|
|
46
|
-
if (apiParamsLines.at(-1)?.trim() === "") apiParamsLines.pop()
|
|
47
|
-
let spaceNumber = 0
|
|
48
|
-
for (const char of apiParamsLines.at(-1) ?? "") {
|
|
49
|
-
if (char === " ") spaceNumber++
|
|
50
|
-
else break
|
|
51
|
-
}
|
|
52
|
-
for (let index = 0; index < apiParamsLines.length; index++) {
|
|
53
|
-
const line = apiParamsLines[index]
|
|
54
|
-
let spaceNumberForThisLine = 0
|
|
55
|
-
for (const char of line) {
|
|
56
|
-
if (char === " ") spaceNumberForThisLine++
|
|
57
|
-
else break
|
|
58
|
-
}
|
|
59
|
-
if (spaceNumberForThisLine >= spaceNumber) {
|
|
60
|
-
apiParamsLines[index] = line.slice(spaceNumber)
|
|
61
|
-
} else {
|
|
62
|
-
apiParamsLines[index] = line.slice(spaceNumberForThisLine)
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
apiParams = apiParamsLines.join("\n")
|
|
66
|
-
|
|
67
|
-
// Find the code for the API testing section.
|
|
68
|
-
const apiTestsCodeChars = []
|
|
69
|
-
let apiTestsStartIndex = undefined as undefined | number
|
|
70
|
-
let semicolonMatch = 0
|
|
71
|
-
let semicolonMax = 0
|
|
72
|
-
for (let index = 0; index < codeLines.length; index++) {
|
|
73
|
-
const codeLine = codeLines[index]
|
|
74
|
-
if (apiTestsStartIndex === undefined && !codeLine.includes("defineApiTest(")) continue
|
|
75
|
-
if (apiTestsStartIndex === undefined) apiTestsStartIndex = index
|
|
76
|
-
const codeChars = codeLine.split("")
|
|
77
|
-
for (const codeChar of codeChars) {
|
|
78
|
-
if (codeChar === "[") {
|
|
79
|
-
semicolonMatch++
|
|
80
|
-
semicolonMax++
|
|
81
|
-
}
|
|
82
|
-
if (semicolonMatch !== 0) apiTestsCodeChars.push(codeChar)
|
|
83
|
-
if (codeChar === "]") semicolonMatch--
|
|
84
|
-
}
|
|
85
|
-
if (semicolonMatch === 0 && semicolonMax >= 1) {
|
|
86
|
-
break
|
|
87
|
-
}
|
|
88
|
-
apiTestsCodeChars.push("\n")
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Find the code for each API test case.
|
|
92
|
-
const apiCaseCodes: Array<string> = []
|
|
93
|
-
let currentApiCaseCode = undefined as undefined | Array<string>
|
|
94
|
-
let apiTestCaseStartIndex = undefined as undefined | number
|
|
95
|
-
let apiTestCaseMatch = 0
|
|
96
|
-
for (let index = 0; index < apiTestsCodeChars.length; index++) {
|
|
97
|
-
const apiTestsCodeChar = apiTestsCodeChars[index]
|
|
98
|
-
if (apiTestCaseStartIndex === undefined && apiTestsCodeChar === "{") {
|
|
99
|
-
currentApiCaseCode = []
|
|
100
|
-
apiTestCaseStartIndex = index
|
|
101
|
-
}
|
|
102
|
-
if (apiTestsCodeChar === "{") {
|
|
103
|
-
apiTestCaseMatch++
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (apiTestCaseMatch !== 0) currentApiCaseCode!.push(apiTestsCodeChar)
|
|
107
|
-
|
|
108
|
-
if (apiTestsCodeChar === "}") {
|
|
109
|
-
apiTestCaseMatch--
|
|
110
|
-
if (apiTestCaseMatch === 0) {
|
|
111
|
-
apiCaseCodes.push(currentApiCaseCode!.join(""))
|
|
112
|
-
currentApiCaseCode = undefined
|
|
113
|
-
apiTestCaseStartIndex = undefined
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const apiCases: Array<{
|
|
119
|
-
name: string;
|
|
120
|
-
handler: string;
|
|
121
|
-
}> = []
|
|
122
|
-
|
|
123
|
-
for (let index = 0; index < apiCaseCodes.length; index++) {
|
|
124
|
-
const code = apiCaseCodes[index]
|
|
125
|
-
const name = /name:[\s\S]+?,/.exec(code)?.[0]?.slice(5, -1)?.trim().slice(1, -1) ?? ""
|
|
126
|
-
const handlerChars = /handler:[\s\S]*/.exec(code)?.[0]?.split("") ?? []
|
|
127
|
-
let handler = "" // Find the main code of the handler.
|
|
128
|
-
let handlerStartIndex = undefined as undefined | number
|
|
129
|
-
let handlerMatch = 0
|
|
130
|
-
for (let index = 0; index < handlerChars.length; index++) {
|
|
131
|
-
const handlerChar = handlerChars[index]
|
|
132
|
-
if (handlerStartIndex !== undefined && handlerChar === "{") handlerStartIndex = index
|
|
133
|
-
if (handlerChar === "{") handlerMatch++
|
|
134
|
-
if (handlerMatch !== 0) handler = handler + handlerChar
|
|
135
|
-
if (handlerChar === "}") handlerMatch--
|
|
136
|
-
if (handlerStartIndex !== undefined && handlerMatch === 0) break
|
|
137
|
-
}
|
|
138
|
-
handler = handler.slice(1, -1)
|
|
139
|
-
|
|
140
|
-
const handlerLines = handler.split("\n") // The intention of the following code is to remove extra spaces, which will make the code look more beautiful.
|
|
141
|
-
if (handlerLines.at(-1)?.trim() === "") handlerLines.pop()
|
|
142
|
-
if (handlerLines.at(-1)?.trim() === "") handlerLines.pop()
|
|
143
|
-
if (handlerLines.at(0)?.trim() === "") handlerLines.shift()
|
|
144
|
-
if (handlerLines.at(0)?.trim() === "") handlerLines.shift()
|
|
145
|
-
let spaceNumber = 0
|
|
146
|
-
for (const char of handlerLines.at(-1) ?? "") {
|
|
147
|
-
if (char === " ") spaceNumber++
|
|
148
|
-
else break
|
|
149
|
-
}
|
|
150
|
-
for (let index = 0; index < handlerLines.length; index++) {
|
|
151
|
-
const line = handlerLines[index]
|
|
152
|
-
let spaceNumberForThisLine = 0
|
|
153
|
-
for (const char of line) {
|
|
154
|
-
if (char === " ") spaceNumberForThisLine++
|
|
155
|
-
else break
|
|
156
|
-
}
|
|
157
|
-
if (spaceNumberForThisLine >= spaceNumber) {
|
|
158
|
-
handlerLines[index] = line.slice(spaceNumber)
|
|
159
|
-
} else {
|
|
160
|
-
handlerLines[index] = line.slice(spaceNumberForThisLine)
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
handler = handlerLines.join("\n")
|
|
164
|
-
|
|
165
|
-
apiCases.push({
|
|
166
|
-
name,
|
|
167
|
-
handler
|
|
168
|
-
})
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// This value has been deprecated because TypeScript types can already replace it well
|
|
172
|
-
// let paramsSchema;
|
|
173
|
-
// try {
|
|
174
|
-
// const moduleGenerated = await import(/* @vite-ignore */ `../../../generated/products/apps/${path}`);
|
|
175
|
-
// paramsSchema = moduleGenerated.paramsSchema.schemas[0]?.properties?.data;
|
|
176
|
-
// } catch (error) {}
|
|
177
|
-
|
|
178
|
-
cookbook[path] = {
|
|
179
|
-
title,
|
|
180
|
-
desc,
|
|
181
|
-
params: apiParams,
|
|
182
|
-
cases: apiCases
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* -- indexes
|
|
188
|
-
*/
|
|
189
|
-
|
|
190
|
-
const indexes: Record<string, Array<string>> = {}
|
|
191
|
-
const folderIndexes: Record<string, Array<string>> = {}
|
|
192
|
-
indexes["(root)"] = []
|
|
193
|
-
folderIndexes["(root)"] = []
|
|
194
|
-
for (const path in cookbook) {
|
|
195
|
-
if (!path.includes("/")) indexes["(root)"].push(path)
|
|
196
|
-
}
|
|
197
|
-
for (const path in cookbook) {
|
|
198
|
-
const dirnames = path.split("/")
|
|
199
|
-
for (let index = 0; index < dirnames.length - 1; index++) {
|
|
200
|
-
const dirpath = dirnames.slice(0, index + 1).join("/")
|
|
201
|
-
if (!indexes[dirpath]) indexes[dirpath] = []
|
|
202
|
-
if (!folderIndexes[dirpath]) folderIndexes[dirpath] = []
|
|
203
|
-
if (index + 1 === dirnames.length - 1) {
|
|
204
|
-
indexes[dirpath].push(path)
|
|
205
|
-
} else {
|
|
206
|
-
const childDirpath = dirnames.slice(0, index + 2).join("/")
|
|
207
|
-
if (folderIndexes[dirpath].includes(childDirpath)) continue
|
|
208
|
-
folderIndexes[dirpath].push(childDirpath)
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
for (const path in folderIndexes) {
|
|
213
|
-
if (path.includes("/") || path === "(root)") continue
|
|
214
|
-
folderIndexes["(root)"].push(path)
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const readme = (await readFile(join(cwd(), "src", "apps", "README.md"))).toString()
|
|
218
|
-
Object.keys(indexes).forEach((key) => indexes[key].length === 0 && delete indexes[key])
|
|
219
|
-
const generatedAt = new Date()
|
|
220
|
-
|
|
221
|
-
await writeFile(
|
|
222
|
-
join(cwd(), `./generated/cookbook.json`),
|
|
223
|
-
TSON.stringify({
|
|
224
|
-
cookbook,
|
|
225
|
-
readme,
|
|
226
|
-
indexes,
|
|
227
|
-
folderIndexes,
|
|
228
|
-
generatedAt
|
|
229
|
-
})
|
|
230
|
-
)
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
void buildCookbook()
|
package/scripts-del/build-dto.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
import { cwd, platform } from "node:process"
|
|
3
|
-
import { exec as nodeExec } from "node:child_process"
|
|
4
|
-
import { removeDir } from "../utils/remove-dir"
|
|
5
|
-
import { join } from "node:path"
|
|
6
|
-
import { copyFile, mkdir } from "node:fs/promises"
|
|
7
|
-
|
|
8
|
-
export async function buildDTO() {
|
|
9
|
-
console.log("π₯ Milkio DTO Building..")
|
|
10
|
-
|
|
11
|
-
removeDir(join(cwd(), "packages", "dto", "dist"))
|
|
12
|
-
removeDir(join(cwd(), "packages", "dto", "generated"))
|
|
13
|
-
await mkdir(join(cwd(), "packages", "dto", "dist"))
|
|
14
|
-
await mkdir(join(cwd(), "packages", "dto", "generated"))
|
|
15
|
-
|
|
16
|
-
// Generate the corresponding types for the files in the project and output them to the /packages/dto/generate directory.
|
|
17
|
-
await new Promise((resolve) =>
|
|
18
|
-
nodeExec("bun ./node_modules/typescript/bin/tsc --project tsconfig.build-dto.json", (e, stdout) => {
|
|
19
|
-
resolve(e)
|
|
20
|
-
})
|
|
21
|
-
)
|
|
22
|
-
await copyFile(join(cwd(), "src", "fail-code.ts"), join(cwd(), "packages", "dto", "generated", "src", "fail-code.ts"))
|
|
23
|
-
|
|
24
|
-
// Packaging type for the dto
|
|
25
|
-
await new Promise((resolve) =>
|
|
26
|
-
nodeExec("cd ./packages/dto && bunx tsc", (e) => {
|
|
27
|
-
resolve(e)
|
|
28
|
-
})
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
// build /src/dto/index.ts to js
|
|
32
|
-
await Bun.build({
|
|
33
|
-
entrypoints: ["./packages/dto/index.ts"],
|
|
34
|
-
outdir: "./packages/dto"
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
const root = join(cwd(), "packages", "dto")
|
|
38
|
-
|
|
39
|
-
console.log("π₯ Milkio DTO Build Finished")
|
|
40
|
-
console.log("\x1B[2m")
|
|
41
|
-
console.log("Now, your latest code (including changes to your interface) is built to the latest version and waiting for your release!")
|
|
42
|
-
console.log("")
|
|
43
|
-
console.log("If you want to publish it to NPM, you can use a command similar to the following.")
|
|
44
|
-
console.log(`(But before that, you may need to modify the package name (${join(cwd(), "packages", "dto", "package.json")}) and login to your NPM account or private NPM repository)`)
|
|
45
|
-
|
|
46
|
-
if (platform !== "win32") {
|
|
47
|
-
console.log("You can publish it to npm by running this commands:\n")
|
|
48
|
-
console.log("\u001B[0m---")
|
|
49
|
-
console.log(`cd ${join(root)} \\`)
|
|
50
|
-
console.log(" && npm version major \\")
|
|
51
|
-
console.log(" && npm publish --access public \\")
|
|
52
|
-
console.log(` && cd ${join(cwd())}`)
|
|
53
|
-
} else {
|
|
54
|
-
console.log("You can publish it to npm by running this commands (use \x1B[42mPowerShell\x1B[0m):")
|
|
55
|
-
console.log("\u001B[0m---")
|
|
56
|
-
console.log('$ErrorActionPreference = "Stop";')
|
|
57
|
-
console.log(`Set-Location ${join(root)};`)
|
|
58
|
-
console.log("npm version major;")
|
|
59
|
-
console.log("npm publish --access public;")
|
|
60
|
-
console.log(`Set-Location ${join(cwd())};`)
|
|
61
|
-
}
|
|
62
|
-
console.log("---")
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
await buildDTO()
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
|
|
3
|
-
import ejs from "ejs"
|
|
4
|
-
import { join } from "node:path"
|
|
5
|
-
import { existsSync, mkdirSync } from "node:fs"
|
|
6
|
-
import { cwd, env, exit } from "node:process"
|
|
7
|
-
import { writeFile, readFile } from "node:fs/promises"
|
|
8
|
-
import { exec as nodeExec } from "node:child_process"
|
|
9
|
-
import { camel, hump, hyphen } from "@poech/camel-hump-under"
|
|
10
|
-
|
|
11
|
-
const utils = {
|
|
12
|
-
camel: (str: string) => camel(str).replaceAll("-", "").replaceAll("_", ""),
|
|
13
|
-
hump: (str: string) => hump(str).replaceAll("-", "").replaceAll("_", ""),
|
|
14
|
-
hyphen: (str: string) => hyphen(str).replaceAll("_", "")
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export async function generateAppPartial(path?: string) {
|
|
18
|
-
const partialPath = path ?? env.GENERATE_PARTIAL_PATH!
|
|
19
|
-
const partialDir = partialPath.split("/").slice(0, -1).join("/")
|
|
20
|
-
// Generate api-schema.ts file through templates
|
|
21
|
-
const templateVars = {
|
|
22
|
-
utils
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (!partialPath.endsWith(".ts")) return
|
|
26
|
-
const module = await import(/* @vite-ignore */ `../../../../src/apps/${partialPath}`)
|
|
27
|
-
if (module?.api?.isApi === true) {
|
|
28
|
-
// Exclude disallowed characters
|
|
29
|
-
if (partialPath.includes("_")) {
|
|
30
|
-
console.error(`\n\nPath: ` + partialPath)
|
|
31
|
-
console.error(`Do not use "_" in the path. If you want to add a separator between words, please use "-".\n`)
|
|
32
|
-
exit(1)
|
|
33
|
-
}
|
|
34
|
-
if (/^[a-z0-9/-]+$/.test(partialPath)) {
|
|
35
|
-
console.error(`\n\nPath: ` + partialPath)
|
|
36
|
-
console.error(`The path can only contain lowercase letters, numbers, and "-".\n`)
|
|
37
|
-
exit(1)
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// typia
|
|
42
|
-
const filePathTmp = join(cwd(), "generated", "raw-tmp", "apps", partialPath)
|
|
43
|
-
const dirPathTmp = join(cwd(), "generated", "raw-tmp", "apps", partialPath).split("/").slice(0, -1).join("/")
|
|
44
|
-
const filePath = join(cwd(), "generated", "raw", "apps", partialPath)
|
|
45
|
-
if (!existsSync(dirPathTmp)) {
|
|
46
|
-
mkdirSync(dirPathTmp, { recursive: true })
|
|
47
|
-
}
|
|
48
|
-
let importPath = "../../../"
|
|
49
|
-
|
|
50
|
-
for (let i = 0; i < partialPath.split("/").length - 1; i++) {
|
|
51
|
-
importPath = importPath + "../"
|
|
52
|
-
}
|
|
53
|
-
importPath = importPath + "src/apps"
|
|
54
|
-
const template = `
|
|
55
|
-
import typia from "typia";
|
|
56
|
-
import { _validate, type ExecuteResultSuccess } from "milkio";
|
|
57
|
-
import { type TSONEncode } from "@southern-aurora/tson";
|
|
58
|
-
import type * as <%= utils.camel(path.slice(0, -3).replaceAll('/', '$')) %> from '${importPath}/<%= path.slice(0, -3) %>';
|
|
59
|
-
|
|
60
|
-
type ParamsT = Parameters<typeof <%= utils.camel(path.replaceAll('/', '$').slice(0, -${3})) %>['api']['action']>[0];
|
|
61
|
-
export const params = async (params: any) => typia.misc.validatePrune<ParamsT>(params);
|
|
62
|
-
type ResultsT = Awaited<ReturnType<typeof <%= utils.camel(path.replaceAll('/', '$').slice(0, -${3})) %>['api']['action']>>;
|
|
63
|
-
export const results = async (results: any) => { _validate(typia.validate<TSONEncode<ExecuteResultSuccess<ResultsT>>>(results)); return typia.json.stringify<TSONEncode<ExecuteResultSuccess<ResultsT>>>(results); };
|
|
64
|
-
`.trim()
|
|
65
|
-
|
|
66
|
-
await writeFile(filePathTmp, ejs.render(template, { ...templateVars, path: partialPath }))
|
|
67
|
-
|
|
68
|
-
await new Promise((resolve) =>
|
|
69
|
-
nodeExec(`bun run ./node_modules/typia/lib/executable/typia.js generate --input generate/raw-tmp/apps/${partialDir} --output generate/products-tmp/apps/${partialDir} --project tsconfig.json`, (e) => {
|
|
70
|
-
resolve(e)
|
|
71
|
-
})
|
|
72
|
-
)
|
|
73
|
-
await Promise.all([writeFile(filePath, ejs.render(template, { ...templateVars, path: partialPath })), writeFile(join(cwd(), "generated", "products", "apps", partialPath), (await readFile(join(cwd(), "generated", "products-tmp", "apps", partialPath))).toString())])
|
|
74
|
-
}
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
|
|
3
|
-
import ejs from "ejs"
|
|
4
|
-
import { join } from "node:path"
|
|
5
|
-
import { existsSync, mkdirSync } from "node:fs"
|
|
6
|
-
import { cwd, exit } from "node:process"
|
|
7
|
-
import { unlink, writeFile } from "node:fs/promises"
|
|
8
|
-
import { exec as nodeExec } from "node:child_process"
|
|
9
|
-
import { camel, hyphen } from "@poech/camel-hump-under"
|
|
10
|
-
import { Glob } from "bun"
|
|
11
|
-
|
|
12
|
-
const utils = {
|
|
13
|
-
camel: (str: string) => camel(str).replaceAll("-", "").replaceAll("_", ""),
|
|
14
|
-
hyphen: (str: string) => hyphen(str).replaceAll("_", "")
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export async function generateApp() {
|
|
18
|
-
// Delete the files generated in the past and regenerate them
|
|
19
|
-
try {
|
|
20
|
-
await unlink(join(cwd(), "generated", "api-schema.ts"))
|
|
21
|
-
} catch (error) {} // Maybe the file does not exist
|
|
22
|
-
|
|
23
|
-
if (!existsSync(join("generated", "README.md"))) {
|
|
24
|
-
await writeFile(join("generated", "README.md"), "β οΈ All files in this directory are generated by milkio. Please do not modify the content, otherwise your modifications will be overwritten in the next generation.")
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Write a basic framework to ensure that there are no errors when reading later
|
|
28
|
-
const apiSchemaSkeleton = `
|
|
29
|
-
export default {
|
|
30
|
-
apiValidator: {},
|
|
31
|
-
apiMethodsSchema: {},
|
|
32
|
-
apiMethodsTypeSchema: {},
|
|
33
|
-
}
|
|
34
|
-
`
|
|
35
|
-
await writeFile(join(cwd(), "generated", "api-schema.ts"), ejs.render(apiSchemaSkeleton, { utils }))
|
|
36
|
-
|
|
37
|
-
// Generate api-schema.ts file through templates
|
|
38
|
-
const templateVars = {
|
|
39
|
-
utils,
|
|
40
|
-
apiPaths: [] as Array<string>,
|
|
41
|
-
apiTestPaths: [] as Array<string>
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const glob = new Glob("**/*.ts")
|
|
45
|
-
const appFiles = await Array.fromAsync(glob.scan({ cwd: join(cwd(), "src", "apps") }))
|
|
46
|
-
|
|
47
|
-
for (const path of appFiles) {
|
|
48
|
-
if (!path.endsWith(".ts")) continue
|
|
49
|
-
const module = await import(/* @vite-ignore */ `../../../../src/apps/${path}`)
|
|
50
|
-
if (module?.api?.isApi === true) {
|
|
51
|
-
// Exclude disallowed characters
|
|
52
|
-
if (path.includes("_")) {
|
|
53
|
-
console.error(`\n\nPath: ` + `"${path}"`)
|
|
54
|
-
console.error(`Do not use "_" in the path. If you want to add a separator between words, please use "-".\n`)
|
|
55
|
-
exit(1)
|
|
56
|
-
}
|
|
57
|
-
if (!/^[a-z0-9/-]+$/.test(path.slice(0, -3))) {
|
|
58
|
-
console.error(`\n\nPath: ` + `"${path}"`)
|
|
59
|
-
console.error(`The path can only contain lowercase letters, numbers, and "-".\n`)
|
|
60
|
-
exit(1)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
templateVars.apiPaths.push(path)
|
|
64
|
-
|
|
65
|
-
if (module?.test?.isApiTest === true) {
|
|
66
|
-
templateVars.apiTestPaths.push(path)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// typia
|
|
70
|
-
const filePath = join(cwd(), "generated", "raw", "apps", path)
|
|
71
|
-
const dirPath = join(cwd(), "generated", "raw", "apps", path).split("/").slice(0, -1).join("/")
|
|
72
|
-
if (!existsSync(dirPath)) {
|
|
73
|
-
mkdirSync(dirPath, { recursive: true })
|
|
74
|
-
}
|
|
75
|
-
let importPath = "../../../"
|
|
76
|
-
|
|
77
|
-
for (let i = 0; i < path.split("/").length - 1; i++) {
|
|
78
|
-
importPath = importPath + "../"
|
|
79
|
-
}
|
|
80
|
-
importPath = importPath + "src/apps"
|
|
81
|
-
const template = `
|
|
82
|
-
import typia from "typia";
|
|
83
|
-
import { _validate, type ExecuteResultSuccess } from "milkio";
|
|
84
|
-
import { type TSONEncode } from "@southern-aurora/tson";
|
|
85
|
-
import type * as <%= utils.camel(path.slice(0, -3).replaceAll('/', '$')) %> from '${importPath}/<%= path.slice(0, -3) %>';
|
|
86
|
-
|
|
87
|
-
type ParamsT = Parameters<typeof <%= utils.camel(path.replaceAll('/', '$').slice(0, -${3})) %>['api']['action']>[0];
|
|
88
|
-
export const params = async (params: any) => typia.misc.validatePrune<ParamsT>(params);
|
|
89
|
-
type ResultsT = Awaited<ReturnType<typeof <%= utils.camel(path.replaceAll('/', '$').slice(0, -${3})) %>['api']['action']>>;
|
|
90
|
-
export const results = async (results: any) => { _validate(typia.validate<TSONEncode<ExecuteResultSuccess<ResultsT>>>(results)); return typia.json.stringify<TSONEncode<ExecuteResultSuccess<ResultsT>>>(results); };
|
|
91
|
-
|
|
92
|
-
`.trim()
|
|
93
|
-
// export const paramsSchema = typia.json.application<[{ data: ParamsT }], "swagger">();
|
|
94
|
-
|
|
95
|
-
await writeFile(filePath, ejs.render(template, { ...templateVars, path }))
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
await writeFile(
|
|
100
|
-
join(cwd(), "generated", "api-schema.ts"),
|
|
101
|
-
ejs.render(
|
|
102
|
-
`
|
|
103
|
-
/**
|
|
104
|
-
* β οΈ This file is generated and modifications will be overwritten
|
|
105
|
-
*/
|
|
106
|
-
|
|
107
|
-
// api
|
|
108
|
-
<% for (const path of ${"apiPaths"}) { %>import type * as <%= utils.camel(path.slice(0, -3).replaceAll('/', '$')) %> from '${"../src/apps"}/<%= path.slice(0, -3) %>'
|
|
109
|
-
<% } %>
|
|
110
|
-
import _apiValidator from './products/api-validator.ts'
|
|
111
|
-
|
|
112
|
-
export default {
|
|
113
|
-
apiValidator: _apiValidator,
|
|
114
|
-
${"apiMethodsSchema"}: {
|
|
115
|
-
<% for (const path of apiPaths) { %>'<%= utils.hyphen(path.slice(0, -${3})) %>': () => ({ module: import('../src/apps/<%= path.slice(0, -${3}) %>') }),
|
|
116
|
-
<% } %>
|
|
117
|
-
},
|
|
118
|
-
${"apiMethodsTypeSchema"}: {
|
|
119
|
-
<% for (const path of apiPaths) { %>'<%= utils.hyphen(path.slice(0, -${3})) %>': undefined as unknown as typeof <%= utils.camel(path.slice(0, -${3}).replaceAll('/', '$')) %>,
|
|
120
|
-
<% } %>
|
|
121
|
-
},
|
|
122
|
-
${"apiTestsSchema"}: {
|
|
123
|
-
<% for (const path of apiTestPaths) { %>'<%= utils.hyphen(path.slice(0, -${3})) %>': () => ({ module: import('../src/apps/<%= path.slice(0, -${3}) %>') }),
|
|
124
|
-
<% } %>
|
|
125
|
-
},
|
|
126
|
-
}
|
|
127
|
-
`.trim(),
|
|
128
|
-
templateVars
|
|
129
|
-
)
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
// api
|
|
133
|
-
const apiValidatorTemplate = `/**
|
|
134
|
-
* β οΈThis file is generated and modifications will be overwritten
|
|
135
|
-
*/
|
|
136
|
-
|
|
137
|
-
export default {
|
|
138
|
-
generatedAt: ${new Date().getTime()},
|
|
139
|
-
${"validate"}: {
|
|
140
|
-
<% for (const path of apiPaths) { %>'<%= utils.hyphen(path.slice(0, -${3})) %>': () => import('./apps/<%= utils.hyphen(path) %>'),
|
|
141
|
-
<% } %>
|
|
142
|
-
},
|
|
143
|
-
}
|
|
144
|
-
`.trim()
|
|
145
|
-
await writeFile(join(cwd(), "generated", "raw", "api-validator.ts"), ejs.render(apiValidatorTemplate, templateVars))
|
|
146
|
-
|
|
147
|
-
await new Promise((resolve) =>
|
|
148
|
-
nodeExec("bun run ./node_modules/typia/lib/executable/typia.js generate --input generate/raw --output generate/products --project tsconfig.json", (e) => {
|
|
149
|
-
resolve(e)
|
|
150
|
-
})
|
|
151
|
-
)
|
|
152
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
|
|
3
|
-
import ejs from "ejs"
|
|
4
|
-
import { join } from "node:path"
|
|
5
|
-
import { existsSync } from "node:fs"
|
|
6
|
-
import { cwd } from "node:process"
|
|
7
|
-
import { writeFile } from "node:fs/promises"
|
|
8
|
-
import { Glob } from "bun"
|
|
9
|
-
|
|
10
|
-
export async function generateDatabase() {
|
|
11
|
-
if (existsSync(join(cwd(), "src", "databases"))) {
|
|
12
|
-
if (!existsSync(join("generated", "database-schema.ts"))) {
|
|
13
|
-
await writeFile(join("generated", "database-schema.ts"), ``)
|
|
14
|
-
}
|
|
15
|
-
const filePath = join(cwd(), "generated", "database-schema.ts")
|
|
16
|
-
const glob = new Glob("**/*.ts")
|
|
17
|
-
const databaseFiles = await Array.fromAsync(glob.scan({ cwd: join(cwd(), "src", "databases") }))
|
|
18
|
-
const template = `<% for (const path of ${"databaseFiles"}) { %>export * from '${"../src/databases"}/<%= path.slice(0, -3) %>'
|
|
19
|
-
<% } %>`
|
|
20
|
-
await writeFile(filePath, ejs.render(template, { databaseFiles }))
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument */
|
|
2
|
-
|
|
3
|
-
import { exit } from "node:process"
|
|
4
|
-
import { generateApp } from "./generated/generate-app"
|
|
5
|
-
console.log("Milkio Quick Generating..")
|
|
6
|
-
|
|
7
|
-
export async function generatePartial() {
|
|
8
|
-
await generateApp()
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
await generatePartial()
|
|
12
|
-
|
|
13
|
-
console.log("\nβ
Milkio Generated!")
|
|
14
|
-
|
|
15
|
-
exit(0)
|
package/scripts-del/generate.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
|
|
3
|
-
import { join } from "node:path"
|
|
4
|
-
import { existsSync, mkdirSync } from "node:fs"
|
|
5
|
-
import { exit } from "node:process"
|
|
6
|
-
import { generateApp } from "./generated/generate-app"
|
|
7
|
-
|
|
8
|
-
export async function generate() {
|
|
9
|
-
// Make sure that the existing directories are all present
|
|
10
|
-
existsSync(join("generated")) || mkdirSync(join("generated"))
|
|
11
|
-
existsSync(join("generated", "raw")) || mkdirSync(join("generated", "raw"))
|
|
12
|
-
existsSync(join("generated", "raw", "apps")) || mkdirSync(join("generated", "raw", "apps"))
|
|
13
|
-
|
|
14
|
-
await generateApp()
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
console.log("Milkio Generating..")
|
|
18
|
-
|
|
19
|
-
await generate()
|
|
20
|
-
|
|
21
|
-
console.log("\nβ
Milkio Generated!")
|
|
22
|
-
|
|
23
|
-
exit(0)
|