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.
- package/api-test/index.ts +65 -67
- package/c.ts +37 -37
- package/defines/define-api-test.ts +24 -17
- package/defines/define-api.ts +9 -9
- package/defines/define-command-handler.ts +41 -42
- package/defines/define-http-handler.ts +188 -184
- package/defines/define-middleware.ts +6 -6
- package/defines/define-use.ts +10 -10
- package/index.ts +22 -22
- package/kernel/context.ts +18 -18
- package/kernel/fail.ts +13 -13
- package/kernel/logger.ts +96 -98
- package/kernel/meta.ts +6 -6
- package/kernel/middleware.ts +37 -36
- package/kernel/milkio.ts +250 -225
- package/kernel/runtime.ts +9 -9
- package/kernel/validate.ts +9 -11
- package/package.json +1 -1
- package/scripts/gen-insignificant.ts +239 -241
- package/scripts/gen-significant.ts +118 -122
- package/types.ts +32 -34
- package/utils/create-ulid.ts +3 -3
- package/utils/env-to-boolean.ts +5 -5
- package/utils/env-to-number.ts +2 -2
- package/utils/env-to-string.ts +2 -2
- package/utils/exec.ts +18 -18
- package/utils/handle-catch-error.ts +37 -37
- package/utils/header-to-plain-object.ts +7 -7
- package/utils/remove-dir.ts +19 -19
- package/utils/tson.ts +2 -2
- package/.co.toml +0 -2
package/api-test/index.ts
CHANGED
|
@@ -1,71 +1,69 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import schema from "../../../generated/api-schema"
|
|
4
|
-
import { useLogger, type MilkioApp } from ".."
|
|
1
|
+
import schema from "../../../generated/api-schema";
|
|
2
|
+
import { useLogger, type MilkioApp } from "..";
|
|
5
3
|
|
|
6
4
|
export const executeApiTests = async <Path extends Array<keyof (typeof schema)["apiTestsSchema"]>>(app: MilkioApp, path: Path | string | true | 1 | undefined) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
5
|
+
console.log(`🥛 Milkio Api Testing..\n`);
|
|
6
|
+
|
|
7
|
+
let pathArr = [] as Array<string>;
|
|
8
|
+
if (!path || path === "1" || path === 1 || path === true) {
|
|
9
|
+
pathArr = Object.keys(schema.apiTestsSchema) as unknown as Path;
|
|
10
|
+
} else if (typeof path === "string") {
|
|
11
|
+
pathArr = [path] as Path;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const tests = [];
|
|
15
|
+
const startedAt = new Date().getTime();
|
|
16
|
+
|
|
17
|
+
const apiTestHooks = await import("../../../src/api-test.ts");
|
|
18
|
+
await apiTestHooks.default.onBootstrap();
|
|
19
|
+
|
|
20
|
+
for (let path of pathArr) {
|
|
21
|
+
if (path.startsWith("/")) path = path.slice(1) as Path[number];
|
|
22
|
+
|
|
23
|
+
tests.push(
|
|
24
|
+
// @ts-ignore
|
|
25
|
+
(async () => {
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
const module = await schema.apiTestsSchema[path]().module;
|
|
28
|
+
const cases = module.test.getCases();
|
|
29
|
+
let i = 0;
|
|
30
|
+
for (const cs of cases) {
|
|
31
|
+
++i;
|
|
32
|
+
const csStartedAt = new Date().getTime();
|
|
33
|
+
const clear = setTimeout(() => {
|
|
34
|
+
console.error(`------`);
|
|
35
|
+
console.error(`❌ TIMEOUT -- More than ${cs.timeout ?? 8192}ms`);
|
|
36
|
+
console.error(` ${cs.name} | Path: src/apps/${path as string}.ts | Case: ${i}`);
|
|
37
|
+
console.error(`------`);
|
|
38
|
+
throw new Error("");
|
|
39
|
+
}, cs.timeout ?? 8192);
|
|
40
|
+
await cs.handler({
|
|
41
|
+
...((await apiTestHooks.default.onBefore()) ?? {}),
|
|
42
|
+
log: (...args: Array<unknown>) => console.log(...args),
|
|
43
|
+
// @ts-ignore
|
|
44
|
+
execute: async (params: any, headers?: any, options?: any) => app.execute(path, params, headers ?? {}, options),
|
|
45
|
+
executeOther: async (path: any, params: any, headers?: any, options?: any) => app.execute(path, params, headers ?? {}, options),
|
|
46
|
+
randParams: () => app.randParams(path as any),
|
|
47
|
+
randOtherParams: (path: any) => app.randParams(path),
|
|
48
|
+
reject: (message?: string) => {
|
|
49
|
+
console.error(`------`);
|
|
50
|
+
console.error(`❌ REJECT -- ${message ?? "Test not satisfied"}`);
|
|
51
|
+
console.error(` ${cs.name} | Path: src/apps/${path as string}.ts | Case: ${i} | Time: ${new Date().getTime() - csStartedAt}ms`);
|
|
52
|
+
console.error(`------`);
|
|
53
|
+
throw new Error("");
|
|
54
|
+
},
|
|
55
|
+
} as any);
|
|
56
|
+
clearTimeout(clear);
|
|
57
|
+
console.log(`✅ DIRECT -- ${cs.name} | Path: src/apps/${path as string}.ts | Case: ${i} | Time: ${new Date().getTime() - csStartedAt}ms`);
|
|
58
|
+
}
|
|
59
|
+
})(),
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
await Promise.all(tests);
|
|
18
64
|
|
|
19
|
-
|
|
20
|
-
await apiTestHooks.default.onBootstrap()
|
|
21
|
-
|
|
22
|
-
for (let path of pathArr) {
|
|
23
|
-
if (path.startsWith("/")) path = path.slice(1) as Path[number]
|
|
65
|
+
const endedAt = new Date().getTime();
|
|
24
66
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
// @ts-ignore
|
|
29
|
-
const module = await schema.apiTestsSchema[path]().module
|
|
30
|
-
const cases = module.test.getCases()
|
|
31
|
-
let i = 0
|
|
32
|
-
for (const cs of cases) {
|
|
33
|
-
++i
|
|
34
|
-
const csStartedAt = new Date().getTime()
|
|
35
|
-
const clear = setTimeout(() => {
|
|
36
|
-
console.error(`------`)
|
|
37
|
-
console.error(`❌ TIMEOUT -- More than ${cs.timeout ?? 8192}ms`)
|
|
38
|
-
console.error(` ${cs.name} | Path: src/apps/${path as string}.ts | Case: ${i}`)
|
|
39
|
-
console.error(`------`)
|
|
40
|
-
throw new Error("")
|
|
41
|
-
}, cs.timeout ?? 8192)
|
|
42
|
-
await cs.handler({
|
|
43
|
-
...(await apiTestHooks.default.onBefore()) ?? {},
|
|
44
|
-
log: (...args: Array<unknown>) => console.log(...args),
|
|
45
|
-
// @ts-ignore
|
|
46
|
-
execute: async (params: any, headers?: any, options?: any) => app.execute(path, params, headers ?? {}, options),
|
|
47
|
-
executeOther: async (path: any, params: any, headers?: any, options?: any) => app.execute(path, params, headers ?? {}, options),
|
|
48
|
-
randParams: () => app.randParams(path as any),
|
|
49
|
-
randOtherParams: (path: any) => app.randParams(path),
|
|
50
|
-
reject: (message?: string) => {
|
|
51
|
-
console.error(`------`)
|
|
52
|
-
console.error(`❌ REJECT -- ${message ?? "Test not satisfied"}`)
|
|
53
|
-
console.error(` ${cs.name} | Path: src/apps/${path as string}.ts | Case: ${i} | Time: ${new Date().getTime() - csStartedAt}ms`)
|
|
54
|
-
console.error(`------`)
|
|
55
|
-
throw new Error("")
|
|
56
|
-
}
|
|
57
|
-
} as any)
|
|
58
|
-
clearTimeout(clear)
|
|
59
|
-
console.log(`✅ DIRECT -- ${cs.name} | Path: src/apps/${path as string}.ts | Case: ${i} | Time: ${new Date().getTime() - csStartedAt}ms`)
|
|
60
|
-
}
|
|
61
|
-
})()
|
|
62
|
-
)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
await Promise.all(tests)
|
|
66
|
-
|
|
67
|
-
const endedAt = new Date().getTime()
|
|
68
|
-
|
|
69
|
-
console.log(`\n✅ All tests passed.`)
|
|
70
|
-
console.log(`🥛 Milkio Api Testing took ${((endedAt - startedAt) / 1000).toFixed(2)}s\n`)
|
|
71
|
-
}
|
|
67
|
+
console.log(`\n✅ All tests passed.`);
|
|
68
|
+
console.log(`🥛 Milkio Api Testing took ${((endedAt - startedAt) / 1000).toFixed(2)}s\n`);
|
|
69
|
+
};
|
package/c.ts
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { argv, exit } from "node:process";
|
|
4
|
+
import { $ } from "bun";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const method = argv[2] as keyof typeof commands
|
|
9
|
-
const params = argv.slice(3) as Parameters<(typeof commands)[keyof typeof commands]>
|
|
6
|
+
const method = argv[2] as keyof typeof commands;
|
|
7
|
+
const params = argv.slice(3) as Parameters<(typeof commands)[keyof typeof commands]>;
|
|
10
8
|
|
|
11
9
|
const commands = {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
10
|
+
async gen() {
|
|
11
|
+
console.log("🥛 Milkio Generating..\n");
|
|
12
|
+
await (await import("./scripts/gen-significant")).default();
|
|
13
|
+
await (await import("./scripts/gen-insignificant")).default();
|
|
14
|
+
console.log("\n✅ Milkio Generated!");
|
|
15
|
+
},
|
|
16
|
+
async "gen:significant"() {
|
|
17
|
+
console.log("🥛 Milkio Significant Generating..\n");
|
|
18
|
+
await (await import("./scripts/gen-significant")).default();
|
|
19
|
+
console.log("\n✅ Milkio Significant Generated!");
|
|
20
|
+
},
|
|
21
|
+
async "gen:insignificant"() {
|
|
22
|
+
console.log("🥛 Milkio Insignificant Generating..\n");
|
|
23
|
+
await (await import("./scripts/gen-insignificant")).default();
|
|
24
|
+
console.log("\n✅ Milkio Insignificant Generated!");
|
|
25
|
+
},
|
|
26
|
+
async EAR(commandBase64ed: string) {
|
|
27
|
+
try {
|
|
28
|
+
await $`clear`;
|
|
29
|
+
} catch (e) {}
|
|
30
|
+
const command = Buffer.from(commandBase64ed, "base64").toString("utf-8");
|
|
31
|
+
console.log("\x1B[2m%s\x1B[0m", `$ ${command}`);
|
|
32
|
+
console.log(``);
|
|
33
|
+
await $`${{ raw: command }}`;
|
|
34
|
+
process.on("SIGINT", () => {}); // prevent users from exiting by pressing ctrl + c
|
|
35
|
+
while (true) await new Promise((resolve) => process.stdin.on("keypress", resolve));
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
38
|
|
|
39
39
|
if (method === undefined || !(method in commands)) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
console.log("Command does not exist, Supported commands are:");
|
|
41
|
+
console.log(` ${Object.keys(commands).join(", ")}`);
|
|
42
|
+
exit(1);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
// @ts-ignore
|
|
46
|
-
await commands[method](...params)
|
|
46
|
+
await commands[method](...params);
|
|
47
47
|
|
|
48
|
-
exit(0)
|
|
48
|
+
exit(0);
|
|
@@ -1,23 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type schema from "../../../generated/api-schema"
|
|
3
|
-
import type apiTestHooks from "../../../src/api-test.ts"
|
|
1
|
+
import type { Api, ExecuteResult, ExecuteOptions } from "..";
|
|
2
|
+
import type schema from "../../../generated/api-schema";
|
|
3
|
+
import type apiTestHooks from "../../../src/api-test.ts";
|
|
4
4
|
|
|
5
5
|
export function defineApiTest<ApiT extends Api>(_api: ApiT, cases: Array<ApiTestCases<ApiT>>) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
return {
|
|
7
|
+
getCases: () => cases,
|
|
8
|
+
isApiTest: true,
|
|
9
|
+
};
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export type ApiTestCases<ApiT extends Api> = {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
handler: (
|
|
14
|
+
test: {
|
|
15
|
+
log: (...params: Array<unknown>) => void;
|
|
16
|
+
execute: (params: Parameters<ApiT["action"]>[0], headers?: Record<string, string>, options?: ExecuteOptions) => Promise<ExecuteResult<Awaited<ReturnType<ApiT["action"]>>>>;
|
|
17
|
+
executeOther: <Path extends keyof (typeof schema)["apiMethodsTypeSchema"], Result extends Awaited<ReturnType<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>>>(
|
|
18
|
+
path: Path,
|
|
19
|
+
params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string,
|
|
20
|
+
headers?: Record<string, string>,
|
|
21
|
+
options?: ExecuteOptions,
|
|
22
|
+
) => Promise<ExecuteResult<Result>>;
|
|
23
|
+
randParams: () => Promise<Parameters<ApiT["action"]>[0]>;
|
|
24
|
+
randOtherParams: <Path extends keyof (typeof schema)["apiMethodsTypeSchema"]>(path: Path) => Promise<Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0]>;
|
|
25
|
+
reject: (message?: string) => void;
|
|
26
|
+
} & Awaited<ReturnType<(typeof apiTestHooks)["onBefore"]>>,
|
|
27
|
+
) => Promise<void> | void;
|
|
28
|
+
name: string;
|
|
29
|
+
timeout?: number;
|
|
23
30
|
};
|
package/defines/define-api.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import type { Meta } from "../../../src/meta"
|
|
2
|
-
import type { Context } from "../../../src/context"
|
|
1
|
+
import type { Meta } from "../../../src/meta";
|
|
2
|
+
import type { Context } from "../../../src/context";
|
|
3
3
|
|
|
4
4
|
export function defineApi<ApiT extends Api>(api: ApiT): ApiT & { isApi: true } {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
return {
|
|
6
|
+
...api,
|
|
7
|
+
isApi: true,
|
|
8
|
+
};
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export type Api = {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
meta: Meta;
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
|
+
action: (params: any, context: Context) => Promise<unknown> | unknown;
|
|
15
15
|
};
|
|
@@ -1,48 +1,47 @@
|
|
|
1
|
-
|
|
2
|
-
import type { MilkioApp } from ".."
|
|
1
|
+
import type { MilkioApp } from "..";
|
|
3
2
|
|
|
4
3
|
export type CommandOptions = {
|
|
5
|
-
|
|
6
|
-
}
|
|
4
|
+
notFoundHandler?: (event: { name: string; path: string; commands: Array<string>; options: Record<string, string | true> }) => void | Promise<void>;
|
|
5
|
+
};
|
|
7
6
|
|
|
8
7
|
export function defineCommandHandler(app: MilkioApp, options: CommandOptions = {}) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
8
|
+
const call = async (argv: Array<string>) => {
|
|
9
|
+
const params = {
|
|
10
|
+
path: "default",
|
|
11
|
+
commands: [] as Array<string>,
|
|
12
|
+
options: {} as Record<string, string | true>,
|
|
13
|
+
};
|
|
14
|
+
for (const v of argv.slice(3)) {
|
|
15
|
+
if (v.startsWith("--") && v.includes("=")) {
|
|
16
|
+
const vSplited = v.split("=");
|
|
17
|
+
params.options[vSplited[0].slice(2)] = vSplited.slice(1, vSplited.length).join("=");
|
|
18
|
+
} else if (v.startsWith("--")) {
|
|
19
|
+
params.options[v.slice(2)] = true;
|
|
20
|
+
} else if (v.startsWith("-") && v.includes("=")) {
|
|
21
|
+
const vSplited = v.split("=");
|
|
22
|
+
params.options[vSplited[0].slice(1)] = vSplited.slice(1, vSplited.length).join("=");
|
|
23
|
+
} else if (v.startsWith("-")) {
|
|
24
|
+
params.options[v.slice(1)] = true;
|
|
25
|
+
} else {
|
|
26
|
+
params.commands.push(v);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (argv.length === 2) params.path = `$/default`;
|
|
30
|
+
else params.path = `$/${argv[2]}`;
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
32
|
+
// @ts-ignore
|
|
33
|
+
const result = await app.execute(params.path as any, params);
|
|
34
|
+
if (!result.success) {
|
|
35
|
+
if (result.fail.code === "NOT_FOUND") {
|
|
36
|
+
if (options.notFoundHandler) await options.notFoundHandler({ ...params, name: argv.length === 2 ? "default" : argv[2] });
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (result.fail.code !== "INTERNAL_SERVER_ERROR") {
|
|
40
|
+
console.log(result.fail.message);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
}
|
|
46
|
+
return call;
|
|
47
|
+
}
|