milkio 0.1.2 → 0.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.
@@ -1,264 +1,262 @@
1
- /* eslint-disable no-console, @typescript-eslint/no-dynamic-delete */
1
+ import { $ } from "bun";
2
+ import { join } from "node:path";
3
+ import { cwd } from "node:process";
4
+ import { existsSync } from "node:fs";
5
+ import { writeFile, readFile, copyFile } from "node:fs/promises";
6
+ import { type MilkioConfig, TSON, type Cookbook } from "..";
2
7
 
3
- import { $ } from "bun"
4
- import { join } from "node:path"
5
- import { cwd } from "node:process"
6
- import { existsSync } from "node:fs"
7
- import { writeFile, readFile, copyFile } from "node:fs/promises"
8
- import { MilkioConfig, TSON, type Cookbook } from ".."
8
+ export default async () => {
9
+ const schema = await import("../../../generated/api-schema");
10
+ const paths = Object.keys(schema.default.apiMethodsSchema);
9
11
 
10
- export default async () => {
11
- const schema = await import("../../../generated/api-schema")
12
- const paths = Object.keys(schema.default.apiMethodsSchema)
12
+ console.log("");
13
+ console.time(`Cookbook Stage`);
13
14
 
14
- console.log('')
15
- console.time(`Cookbook Stage`)
15
+ const cookbook: Cookbook = {};
16
+ for (const path of paths) {
17
+ // const module = await import(/* @vite-ignore */ join(`../../../src/apps/${path}`));
18
+ const code = (await readFile(join(cwd(), `./src/apps/${path}.ts`))).toString();
19
+ const codeLines = code.split("\n");
20
+ let title;
21
+ let desc;
22
+ const descRaw = /\n\/\*\*\n[\s\S]+?\*\//.exec(code)?.[0] ?? "";
16
23
 
17
- const cookbook: Cookbook = {}
18
- for (const path of paths) {
19
- // const module = await import(/* @vite-ignore */ join(`../../../src/apps/${path}`));
20
- const code = (await readFile(join(cwd(), `./src/apps/${path}.ts`))).toString()
21
- const codeLines = code.split("\n")
22
- let title
23
- let desc
24
- const descRaw = /\n\/\*\*\n[\s\S]+?\*\//.exec(code)?.[0] ?? ""
24
+ if (descRaw) {
25
+ const descRawLines = descRaw.split("\n");
26
+ if (descRawLines.at(0)?.trim() === "") descRawLines.shift();
27
+ if (descRawLines.at(-1)?.trim() === "") descRawLines.pop();
28
+ let first = true;
29
+ for (let index = 0; index < descRawLines.length; index++) {
30
+ const descRawLine = descRawLines[index].replace(/^[/ ]+?[*]*/, "").replace(/[*]*\/$/, "");
25
31
 
26
- if (descRaw) {
27
- const descRawLines = descRaw.split("\n")
28
- if (descRawLines.at(0)?.trim() === "") descRawLines.shift()
29
- if (descRawLines.at(-1)?.trim() === "") descRawLines.pop()
30
- let first = true
31
- for (let index = 0; index < descRawLines.length; index++) {
32
- const descRawLine = descRawLines[index].replace(/^[/ ]+?[*]*/, "").replace(/[*]*\/$/, "")
32
+ if (!descRawLine) continue;
33
+ if (first) {
34
+ title = descRawLine.replace(/#/g, "").trim();
35
+ // Originally the title was in the first line, desc is the rest of it, now desc contains complete markdown content.
36
+ // continue;
37
+ }
38
+ first = false;
39
+ desc = `${desc ?? ""}\n${descRawLine.trim()}`;
40
+ }
41
+ }
33
42
 
34
- if (!descRawLine) continue
35
- if (first) {
36
- title = descRawLine.replace(/#/g, "").trim()
37
- // Originally the title was in the first line, desc is the rest of it, now desc contains complete markdown content.
38
- // continue;
39
- }
40
- first = false
41
- desc = (desc ?? "") + "\n" + descRawLine.trim()
42
- }
43
- }
43
+ let apiParams = /action\([\s\S]+?\)/.exec(code)?.[0] ?? ""; // The intention of the following code is to extract the parameter part of the action.
44
+ apiParams = /\([\s\S]*,/.exec(apiParams)?.[0] ?? "";
45
+ apiParams = apiParams.slice(0, -1);
46
+ apiParams = apiParams.slice(/[\s\S]+?:/.exec(apiParams)?.[0].length);
47
+ const apiParamsLines = apiParams.split("\n"); // The intention of the following code is to remove extra spaces, which will make the code look more beautiful.
48
+ if (apiParamsLines.at(-1)?.trim() === "") apiParamsLines.pop();
49
+ if (apiParamsLines.at(-1)?.trim() === "") apiParamsLines.pop();
50
+ let spaceNumber = 0;
51
+ for (const char of apiParamsLines.at(-1) ?? "") {
52
+ if (char === " ") spaceNumber++;
53
+ else break;
54
+ }
55
+ for (let index = 0; index < apiParamsLines.length; index++) {
56
+ const line = apiParamsLines[index];
57
+ let spaceNumberForThisLine = 0;
58
+ for (const char of line) {
59
+ if (char === " ") spaceNumberForThisLine++;
60
+ else break;
61
+ }
62
+ if (spaceNumberForThisLine >= spaceNumber) {
63
+ apiParamsLines[index] = line.slice(spaceNumber);
64
+ } else {
65
+ apiParamsLines[index] = line.slice(spaceNumberForThisLine);
66
+ }
67
+ }
68
+ apiParams = apiParamsLines.join("\n");
44
69
 
45
- let apiParams = /action\([\s\S]+?\)/.exec(code)?.[0] ?? "" // The intention of the following code is to extract the parameter part of the action.
46
- apiParams = /\([\s\S]*,/.exec(apiParams)?.[0] ?? ""
47
- apiParams = apiParams.slice(0, -1)
48
- apiParams = apiParams.slice(/[\s\S]+?:/.exec(apiParams)?.[0].length)
49
- const apiParamsLines = apiParams.split("\n") // The intention of the following code is to remove extra spaces, which will make the code look more beautiful.
50
- if (apiParamsLines.at(-1)?.trim() === "") apiParamsLines.pop()
51
- if (apiParamsLines.at(-1)?.trim() === "") apiParamsLines.pop()
52
- let spaceNumber = 0
53
- for (const char of apiParamsLines.at(-1) ?? "") {
54
- if (char === " ") spaceNumber++
55
- else break
56
- }
57
- for (let index = 0; index < apiParamsLines.length; index++) {
58
- const line = apiParamsLines[index]
59
- let spaceNumberForThisLine = 0
60
- for (const char of line) {
61
- if (char === " ") spaceNumberForThisLine++
62
- else break
63
- }
64
- if (spaceNumberForThisLine >= spaceNumber) {
65
- apiParamsLines[index] = line.slice(spaceNumber)
66
- } else {
67
- apiParamsLines[index] = line.slice(spaceNumberForThisLine)
68
- }
69
- }
70
- apiParams = apiParamsLines.join("\n")
70
+ // Find the code for the API testing section.
71
+ const apiTestsCodeChars = [];
72
+ let apiTestsStartIndex = undefined as undefined | number;
73
+ let semicolonMatch = 0;
74
+ let semicolonMax = 0;
75
+ for (let index = 0; index < codeLines.length; index++) {
76
+ const codeLine = codeLines[index];
77
+ if (apiTestsStartIndex === undefined && !codeLine.includes("defineApiTest(")) continue;
78
+ if (apiTestsStartIndex === undefined) apiTestsStartIndex = index;
79
+ const codeChars = codeLine.split("");
80
+ for (const codeChar of codeChars) {
81
+ if (codeChar === "[") {
82
+ semicolonMatch++;
83
+ semicolonMax++;
84
+ }
85
+ if (semicolonMatch !== 0) apiTestsCodeChars.push(codeChar);
86
+ if (codeChar === "]") semicolonMatch--;
87
+ }
88
+ if (semicolonMatch === 0 && semicolonMax >= 1) {
89
+ break;
90
+ }
91
+ apiTestsCodeChars.push("\n");
92
+ }
71
93
 
72
- // Find the code for the API testing section.
73
- const apiTestsCodeChars = []
74
- let apiTestsStartIndex = undefined as undefined | number
75
- let semicolonMatch = 0
76
- let semicolonMax = 0
77
- for (let index = 0; index < codeLines.length; index++) {
78
- const codeLine = codeLines[index]
79
- if (apiTestsStartIndex === undefined && !codeLine.includes("defineApiTest(")) continue
80
- if (apiTestsStartIndex === undefined) apiTestsStartIndex = index
81
- const codeChars = codeLine.split("")
82
- for (const codeChar of codeChars) {
83
- if (codeChar === "[") {
84
- semicolonMatch++
85
- semicolonMax++
86
- }
87
- if (semicolonMatch !== 0) apiTestsCodeChars.push(codeChar)
88
- if (codeChar === "]") semicolonMatch--
89
- }
90
- if (semicolonMatch === 0 && semicolonMax >= 1) {
91
- break
92
- }
93
- apiTestsCodeChars.push("\n")
94
- }
94
+ // Find the code for each API test case.
95
+ const apiCaseCodes: Array<string> = [];
96
+ let currentApiCaseCode = undefined as undefined | Array<string>;
97
+ let apiTestCaseStartIndex = undefined as undefined | number;
98
+ let apiTestCaseMatch = 0;
99
+ for (let index = 0; index < apiTestsCodeChars.length; index++) {
100
+ const apiTestsCodeChar = apiTestsCodeChars[index];
101
+ if (apiTestCaseStartIndex === undefined && apiTestsCodeChar === "{") {
102
+ currentApiCaseCode = [];
103
+ apiTestCaseStartIndex = index;
104
+ }
105
+ if (apiTestsCodeChar === "{") {
106
+ apiTestCaseMatch++;
107
+ }
95
108
 
96
- // Find the code for each API test case.
97
- const apiCaseCodes: Array<string> = []
98
- let currentApiCaseCode = undefined as undefined | Array<string>
99
- let apiTestCaseStartIndex = undefined as undefined | number
100
- let apiTestCaseMatch = 0
101
- for (let index = 0; index < apiTestsCodeChars.length; index++) {
102
- const apiTestsCodeChar = apiTestsCodeChars[index]
103
- if (apiTestCaseStartIndex === undefined && apiTestsCodeChar === "{") {
104
- currentApiCaseCode = []
105
- apiTestCaseStartIndex = index
106
- }
107
- if (apiTestsCodeChar === "{") {
108
- apiTestCaseMatch++
109
- }
109
+ if (apiTestCaseMatch !== 0) currentApiCaseCode!.push(apiTestsCodeChar);
110
110
 
111
- if (apiTestCaseMatch !== 0) currentApiCaseCode!.push(apiTestsCodeChar)
111
+ if (apiTestsCodeChar === "}") {
112
+ apiTestCaseMatch--;
113
+ if (apiTestCaseMatch === 0) {
114
+ apiCaseCodes.push(currentApiCaseCode!.join(""));
115
+ currentApiCaseCode = undefined;
116
+ apiTestCaseStartIndex = undefined;
117
+ }
118
+ }
119
+ }
112
120
 
113
- if (apiTestsCodeChar === "}") {
114
- apiTestCaseMatch--
115
- if (apiTestCaseMatch === 0) {
116
- apiCaseCodes.push(currentApiCaseCode!.join(""))
117
- currentApiCaseCode = undefined
118
- apiTestCaseStartIndex = undefined
119
- }
120
- }
121
- }
121
+ const apiCases: Array<{
122
+ name: string;
123
+ handler: string;
124
+ }> = [];
122
125
 
123
- const apiCases: Array<{
124
- name: string;
125
- handler: string;
126
- }> = []
126
+ for (let index = 0; index < apiCaseCodes.length; index++) {
127
+ const code = apiCaseCodes[index];
128
+ const name = /name:[\s\S]+?,/.exec(code)?.[0]?.slice(5, -1)?.trim().slice(1, -1) ?? "";
129
+ const handlerChars = /handler:[\s\S]*/.exec(code)?.[0]?.split("") ?? [];
130
+ let handler = ""; // Find the main code of the handler.
131
+ let handlerStartIndex = undefined as undefined | number;
132
+ let handlerMatch = 0;
133
+ for (let index = 0; index < handlerChars.length; index++) {
134
+ const handlerChar = handlerChars[index];
135
+ if (handlerStartIndex !== undefined && handlerChar === "{") handlerStartIndex = index;
136
+ if (handlerChar === "{") handlerMatch++;
137
+ if (handlerMatch !== 0) handler = handler + handlerChar;
138
+ if (handlerChar === "}") handlerMatch--;
139
+ if (handlerStartIndex !== undefined && handlerMatch === 0) break;
140
+ }
141
+ handler = handler.slice(1, -1);
127
142
 
128
- for (let index = 0; index < apiCaseCodes.length; index++) {
129
- const code = apiCaseCodes[index]
130
- const name = /name:[\s\S]+?,/.exec(code)?.[0]?.slice(5, -1)?.trim().slice(1, -1) ?? ""
131
- const handlerChars = /handler:[\s\S]*/.exec(code)?.[0]?.split("") ?? []
132
- let handler = "" // Find the main code of the handler.
133
- let handlerStartIndex = undefined as undefined | number
134
- let handlerMatch = 0
135
- for (let index = 0; index < handlerChars.length; index++) {
136
- const handlerChar = handlerChars[index]
137
- if (handlerStartIndex !== undefined && handlerChar === "{") handlerStartIndex = index
138
- if (handlerChar === "{") handlerMatch++
139
- if (handlerMatch !== 0) handler = handler + handlerChar
140
- if (handlerChar === "}") handlerMatch--
141
- if (handlerStartIndex !== undefined && handlerMatch === 0) break
142
- }
143
- handler = handler.slice(1, -1)
143
+ const handlerLines = handler.split("\n"); // The intention of the following code is to remove extra spaces, which will make the code look more beautiful.
144
+ if (handlerLines.at(-1)?.trim() === "") handlerLines.pop();
145
+ if (handlerLines.at(-1)?.trim() === "") handlerLines.pop();
146
+ if (handlerLines.at(0)?.trim() === "") handlerLines.shift();
147
+ if (handlerLines.at(0)?.trim() === "") handlerLines.shift();
148
+ let spaceNumber = 0;
149
+ for (const char of handlerLines.at(-1) ?? "") {
150
+ if (char === " ") spaceNumber++;
151
+ else break;
152
+ }
153
+ for (let index = 0; index < handlerLines.length; index++) {
154
+ const line = handlerLines[index];
155
+ let spaceNumberForThisLine = 0;
156
+ for (const char of line) {
157
+ if (char === " ") spaceNumberForThisLine++;
158
+ else break;
159
+ }
160
+ if (spaceNumberForThisLine >= spaceNumber) {
161
+ handlerLines[index] = line.slice(spaceNumber);
162
+ } else {
163
+ handlerLines[index] = line.slice(spaceNumberForThisLine);
164
+ }
165
+ }
166
+ handler = handlerLines.join("\n");
144
167
 
145
- const handlerLines = handler.split("\n") // The intention of the following code is to remove extra spaces, which will make the code look more beautiful.
146
- if (handlerLines.at(-1)?.trim() === "") handlerLines.pop()
147
- if (handlerLines.at(-1)?.trim() === "") handlerLines.pop()
148
- if (handlerLines.at(0)?.trim() === "") handlerLines.shift()
149
- if (handlerLines.at(0)?.trim() === "") handlerLines.shift()
150
- let spaceNumber = 0
151
- for (const char of handlerLines.at(-1) ?? "") {
152
- if (char === " ") spaceNumber++
153
- else break
154
- }
155
- for (let index = 0; index < handlerLines.length; index++) {
156
- const line = handlerLines[index]
157
- let spaceNumberForThisLine = 0
158
- for (const char of line) {
159
- if (char === " ") spaceNumberForThisLine++
160
- else break
161
- }
162
- if (spaceNumberForThisLine >= spaceNumber) {
163
- handlerLines[index] = line.slice(spaceNumber)
164
- } else {
165
- handlerLines[index] = line.slice(spaceNumberForThisLine)
166
- }
167
- }
168
- handler = handlerLines.join("\n")
168
+ apiCases.push({
169
+ name,
170
+ handler,
171
+ });
172
+ }
169
173
 
170
- apiCases.push({
171
- name,
172
- handler
173
- })
174
- }
174
+ // This value has been deprecated because TypeScript types can already replace it well
175
+ // let paramsSchema;
176
+ // try {
177
+ // const moduleGenerated = await import(/* @vite-ignore */ `../../../generated/products/apps/${path}`);
178
+ // paramsSchema = moduleGenerated.paramsSchema.schemas[0]?.properties?.data;
179
+ // } catch (error) {}
175
180
 
176
- // This value has been deprecated because TypeScript types can already replace it well
177
- // let paramsSchema;
178
- // try {
179
- // const moduleGenerated = await import(/* @vite-ignore */ `../../../generated/products/apps/${path}`);
180
- // paramsSchema = moduleGenerated.paramsSchema.schemas[0]?.properties?.data;
181
- // } catch (error) {}
181
+ cookbook[path] = {
182
+ title,
183
+ desc,
184
+ params: apiParams,
185
+ cases: apiCases,
186
+ };
187
+ }
182
188
 
183
- cookbook[path] = {
184
- title,
185
- desc,
186
- params: apiParams,
187
- cases: apiCases
188
- }
189
- }
189
+ /**
190
+ * -- indexes
191
+ */
190
192
 
191
- /**
192
- * -- indexes
193
- */
193
+ const indexes: Record<string, Array<string>> = {};
194
+ const folderIndexes: Record<string, Array<string>> = {};
195
+ indexes["(root)"] = [];
196
+ folderIndexes["(root)"] = [];
197
+ for (const path in cookbook) {
198
+ if (!path.includes("/")) indexes["(root)"].push(path);
199
+ }
200
+ for (const path in cookbook) {
201
+ const dirnames = path.split("/");
202
+ for (let index = 0; index < dirnames.length - 1; index++) {
203
+ const dirpath = dirnames.slice(0, index + 1).join("/");
204
+ if (!indexes[dirpath]) indexes[dirpath] = [];
205
+ if (!folderIndexes[dirpath]) folderIndexes[dirpath] = [];
206
+ if (index + 1 === dirnames.length - 1) {
207
+ indexes[dirpath].push(path);
208
+ } else {
209
+ const childDirpath = dirnames.slice(0, index + 2).join("/");
210
+ if (folderIndexes[dirpath].includes(childDirpath)) continue;
211
+ folderIndexes[dirpath].push(childDirpath);
212
+ }
213
+ }
214
+ }
215
+ for (const path in folderIndexes) {
216
+ if (path.includes("/") || path === "(root)") continue;
217
+ folderIndexes["(root)"].push(path);
218
+ }
194
219
 
195
- const indexes: Record<string, Array<string>> = {}
196
- const folderIndexes: Record<string, Array<string>> = {}
197
- indexes["(root)"] = []
198
- folderIndexes["(root)"] = []
199
- for (const path in cookbook) {
200
- if (!path.includes("/")) indexes["(root)"].push(path)
201
- }
202
- for (const path in cookbook) {
203
- const dirnames = path.split("/")
204
- for (let index = 0; index < dirnames.length - 1; index++) {
205
- const dirpath = dirnames.slice(0, index + 1).join("/")
206
- if (!indexes[dirpath]) indexes[dirpath] = []
207
- if (!folderIndexes[dirpath]) folderIndexes[dirpath] = []
208
- if (index + 1 === dirnames.length - 1) {
209
- indexes[dirpath].push(path)
210
- } else {
211
- const childDirpath = dirnames.slice(0, index + 2).join("/")
212
- if (folderIndexes[dirpath].includes(childDirpath)) continue
213
- folderIndexes[dirpath].push(childDirpath)
214
- }
215
- }
216
- }
217
- for (const path in folderIndexes) {
218
- if (path.includes("/") || path === "(root)") continue
219
- folderIndexes["(root)"].push(path)
220
- }
220
+ const readme = (await readFile(join(cwd(), "src", "apps", "README.md"))).toString();
221
+ Object.keys(indexes).forEach((key) => indexes[key].length === 0 && delete indexes[key]);
222
+ const generatedAt = new Date();
221
223
 
222
- const readme = (await readFile(join(cwd(), "src", "apps", "README.md"))).toString()
223
- Object.keys(indexes).forEach((key) => indexes[key].length === 0 && delete indexes[key])
224
- const generatedAt = new Date()
224
+ await writeFile(
225
+ join(cwd(), `./generated/cookbook.json`),
226
+ TSON.stringify({
227
+ cookbook,
228
+ readme,
229
+ indexes,
230
+ folderIndexes,
231
+ generatedAt,
232
+ }),
233
+ );
225
234
 
226
- await writeFile(
227
- join(cwd(), `./generated/cookbook.json`),
228
- TSON.stringify({
229
- cookbook,
230
- readme,
231
- indexes,
232
- folderIndexes,
233
- generatedAt
234
- })
235
- )
235
+ console.timeEnd(`Cookbook Stage`);
236
+ console.log(``);
236
237
 
237
- console.timeEnd(`Cookbook Stage`)
238
- console.log(``)
238
+ console.time(`Client Stage`);
239
+ try {
240
+ await $`bun run ./node_modules/typescript/bin/tsc --outDir "./packages/client/project"`.quiet();
241
+ } catch (error) {}
242
+ await Bun.build({
243
+ entrypoints: ["./packages/client/index.ts"],
244
+ outdir: "./packages/client/dist",
245
+ target: "browser",
246
+ minify: true,
247
+ });
248
+ await copyFile(join(cwd(), "src", "fail-code.ts"), join(cwd(), "packages", "client", "project", "src", "fail-code.ts"));
249
+ console.timeEnd(`Client Stage`);
250
+ console.log(``);
239
251
 
240
- console.time(`Client Stage`)
241
- try {
242
- await $`bun run ./node_modules/typescript/bin/tsc --outDir "./packages/client/project"`.quiet()
243
- } catch (error) {}
244
- await Bun.build({
245
- entrypoints: ["./packages/client/index.ts"],
246
- outdir: "./packages/client/dist",
247
- target: 'browser',
248
- minify: true
249
- })
250
- await copyFile(join(cwd(), 'src', 'fail-code.ts'), join(cwd(), 'packages', 'client', 'project', 'src', 'fail-code.ts'))
251
- console.timeEnd(`Client Stage`)
252
- console.log(``)
253
-
254
- if (!existsSync(join(cwd(), "milkio.toml"))) return
255
- const milkioConfig = (await import(join(cwd(), "milkio.toml"))).default as MilkioConfig
256
- if (!milkioConfig?.generate?.significant) return
257
- let i = 0
258
- for (const command of milkioConfig.generate.significant) {
259
- ++i
260
- console.time(`Insignificant Stage (LINE ${i})`)
261
- await $`${{ raw: command }}`
262
- console.timeEnd(`Insignificant Stage (LINE ${i})`)
263
- }
264
- }
252
+ if (!existsSync(join(cwd(), "milkio.toml"))) return;
253
+ const milkioConfig = (await import(join(cwd(), "milkio.toml"))).default as MilkioConfig;
254
+ if (!milkioConfig?.generate?.significant) return;
255
+ let i = 0;
256
+ for (const command of milkioConfig.generate.significant) {
257
+ ++i;
258
+ console.time(`Insignificant Stage (LINE ${i})`);
259
+ await $`${{ raw: command }}`;
260
+ console.timeEnd(`Insignificant Stage (LINE ${i})`);
261
+ }
262
+ };