milkio 1.0.0-alpha.3 → 1.0.0-alpha.31
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/.publish/releases/1.0.0-alpha.21.md +13 -0
- package/command/index.ts +1 -1
- package/config/index.ts +48 -0
- package/context/index.ts +6 -3
- package/events/index.ts +3 -3
- package/exception/index.ts +2 -0
- package/execute/index.ts +40 -80
- package/index.ts +3 -0
- package/listener/index.ts +34 -17
- package/logger/index.ts +1 -1
- package/package.json +3 -3
- package/step/index.ts +4 -4
- package/type-safety/index.ts +16 -0
- package/types/index.ts +11 -17
- package/utils/send-cookbook-event.ts +1 -1
- package/world/index.ts +13 -11
package/command/index.ts
CHANGED
|
@@ -15,7 +15,7 @@ export type Command<CommandInitT extends CommandInit> = {
|
|
|
15
15
|
handler: CommandInitT["handler"];
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
export const __initCommander =
|
|
18
|
+
export const __initCommander = (generated: GeneratedInit, runtime: any) => {
|
|
19
19
|
const commander = async (argv: Array<string>, options?: { onNotFound?: () => any }) => {
|
|
20
20
|
const params = {
|
|
21
21
|
path: "index",
|
package/config/index.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type $types, type GeneratedInit } from "../types";
|
|
2
|
+
|
|
3
|
+
export const config = <ConfigDefaultT extends ConfigDefault, ConfigEnvironmentsT extends ConfigEnvironments<ConfigDefaultT>>(def: ConfigDefaultT, envs: ConfigEnvironmentsT = {} as Record<any, any>): [ConfigDefaultT, ConfigEnvironmentsT] => {
|
|
4
|
+
return [def, envs];
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const __getConfig = async <Namespace extends keyof $types["generated"]["configSchema"]>(generated: GeneratedInit, env: Record<any, any>, envMode: string, namespace: Namespace) => {
|
|
8
|
+
if (generated.configSchema[namespace][1] && envMode in generated.configSchema[namespace][1]) {
|
|
9
|
+
return {
|
|
10
|
+
...(await generated.configSchema[namespace][0](env)),
|
|
11
|
+
...(await generated.configSchema[namespace][1][envMode](env)),
|
|
12
|
+
};
|
|
13
|
+
} else {
|
|
14
|
+
return {
|
|
15
|
+
...(await generated.configSchema[namespace][0](env)),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type ConfigDefault = (env: Record<string, string>) => Promise<Record<string, unknown>> | Record<string, unknown>;
|
|
21
|
+
|
|
22
|
+
export type ConfigEnvironments<T extends ConfigDefault> = {
|
|
23
|
+
[key: string]: (env: Record<string, string>) => Partial<Awaited<ReturnType<T>>> | Promise<Partial<Awaited<ReturnType<T>>>>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export function envToString(value: string | number | undefined, defaultValue: string) {
|
|
27
|
+
if (value === undefined) return defaultValue;
|
|
28
|
+
|
|
29
|
+
return `${value}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function envToNumber(value: string | undefined, defaultValue: number) {
|
|
33
|
+
if (value === undefined) return defaultValue;
|
|
34
|
+
|
|
35
|
+
return Number.parseInt(value, 10);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function envToBoolean(value: string | number | undefined, defaultValue: boolean) {
|
|
39
|
+
if (value === "true") return true;
|
|
40
|
+
|
|
41
|
+
if (value === "false") return false;
|
|
42
|
+
|
|
43
|
+
if (value === "") return false;
|
|
44
|
+
|
|
45
|
+
if (undefined === value) return defaultValue;
|
|
46
|
+
|
|
47
|
+
return Boolean(value);
|
|
48
|
+
}
|
package/context/index.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import { type MilkioHttpRequest, type MilkioHttpResponse, type $types, type Logger, Steps } from "..";
|
|
1
|
+
import { type MilkioHttpRequest, type MilkioHttpResponse, type $types, type Logger, type Steps, type Mixin, type ExecuteOptions, type Action } from "..";
|
|
2
2
|
|
|
3
3
|
export interface $context {
|
|
4
|
+
develop: boolean;
|
|
4
5
|
executeId: string;
|
|
6
|
+
environment: string;
|
|
5
7
|
path: string;
|
|
6
8
|
logger: Logger;
|
|
7
|
-
http
|
|
8
|
-
|
|
9
|
+
http: ContextHttp<Record<any, any>>;
|
|
10
|
+
getConfig: <Namespace extends keyof $types["generated"]["configSchema"]>(namespace: Namespace) => Promise<Readonly<Awaited<ReturnType<$types["generated"]["configSchema"][Namespace][0]>>>>;
|
|
11
|
+
call: <Module extends Promise<{ default: Action<any> }>>(module: Module, params: Parameters<Awaited<Module>["default"]["handler"]>[1]) => Promise<ReturnType<Awaited<Module>["default"]["handler"]>>;
|
|
9
12
|
}
|
|
10
13
|
|
|
11
14
|
export type ContextHttp<ParamsParsed = any> = {
|
package/events/index.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { type $context, type ContextHttp, type Results, type Logger } from "..";
|
|
1
|
+
import { type $context, type ContextHttp, type Results, type Logger, type $meta } from "..";
|
|
2
2
|
|
|
3
3
|
export interface $events {
|
|
4
4
|
"milkio:httpRequest": { executeId: string; path: string; logger: Logger; http: ContextHttp<Record<string, any>> };
|
|
5
5
|
"milkio:httpResponse": { executeId: string; path: string; logger: Logger; http: ContextHttp<Record<string, any>>; context: $context };
|
|
6
6
|
"milkio:httpNotFound": { executeId: string; path: string; logger: Logger; http: ContextHttp<Record<string, any>> };
|
|
7
|
-
"milkio:executeBefore": { executeId: string; path: string; logger: Logger; context: $context };
|
|
8
|
-
"milkio:executeAfter": { executeId: string; path: string; logger: Logger; context: $context; results: Results<any> };
|
|
7
|
+
"milkio:executeBefore": { executeId: string; path: string; logger: Logger; meta: $meta; context: $context };
|
|
8
|
+
"milkio:executeAfter": { executeId: string; path: string; logger: Logger; meta: $meta; context: $context; results: Results<any> };
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export const __initEventManager = () => {
|
package/exception/index.ts
CHANGED
|
@@ -8,8 +8,10 @@ export interface $rejectCode {
|
|
|
8
8
|
REQUEST_TIMEOUT: { timeout: number; message: string };
|
|
9
9
|
NOT_FOUND: { path: string };
|
|
10
10
|
PARAMS_TYPE_INCORRECT: { path: string; expected: string; value: any; message: string } | null;
|
|
11
|
+
RESULTS_TYPE_INCORRECT: { path: string; expected: string; value: any; message: string } | null;
|
|
11
12
|
UNACCEPTABLE: { expected: string; message: string };
|
|
12
13
|
PARAMS_TYPE_NOT_SUPPORTED: { expected: string };
|
|
14
|
+
RESULTS_TYPE_NOT_SUPPORTED: { expected: string };
|
|
13
15
|
INTERNAL_SERVER_ERROR: undefined;
|
|
14
16
|
}
|
|
15
17
|
|
package/execute/index.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { type IValidation } from "typia";
|
|
1
|
+
import typia, { type IValidation } from "typia";
|
|
2
2
|
import { TSON } from "@southern-aurora/tson";
|
|
3
|
-
import {
|
|
4
|
-
import { reject, type $context, type $meta, type ExecuteOptions, type Logger, type MilkioRuntimeInit, type Results, type GeneratedInit, type MilkioInit, createLogger, exceptionHandler, Ping, createStep } from "..";
|
|
3
|
+
import { reject, type $context, type $meta, type Logger, type Results, type GeneratedInit, __getConfig } from "..";
|
|
5
4
|
import { headersToJSON } from "../utils/headers-to-json";
|
|
6
5
|
|
|
7
|
-
export const __initExecuter =
|
|
8
|
-
const
|
|
6
|
+
export const __initExecuter = (generated: GeneratedInit, runtime: any) => {
|
|
7
|
+
const __execute = async (
|
|
8
|
+
env: Record<any, any> | undefined,
|
|
9
|
+
envMode: string | undefined,
|
|
9
10
|
routeSchema: any,
|
|
10
11
|
options: {
|
|
11
12
|
createdExecuteId: string;
|
|
@@ -23,8 +24,10 @@ export const __initExecuter = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
|
|
|
23
24
|
paramsType: "string";
|
|
24
25
|
}
|
|
25
26
|
),
|
|
26
|
-
): Promise<{ executeId: string; headers: Headers; params: Record<any, unknown>; results: Results<any>; context: $context; meta: Readonly<$meta>; type: "action" | "stream" }> => {
|
|
27
|
-
const executeId = options.createdExecuteId;
|
|
27
|
+
): Promise<{ executeId: string; headers: Headers; params: Record<any, unknown>; results: Results<any>; context: $context; meta: Readonly<$meta>; type: "action" | "stream"; emptyResult: boolean; resultsTypeSafety: boolean }> => {
|
|
28
|
+
const executeId: string = options.createdExecuteId;
|
|
29
|
+
env = env ?? {};
|
|
30
|
+
envMode = envMode ?? "production";
|
|
28
31
|
let headers: Headers;
|
|
29
32
|
if (!(options.headers instanceof Headers)) {
|
|
30
33
|
// @ts-ignore
|
|
@@ -53,7 +56,7 @@ export const __initExecuter = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
|
|
|
53
56
|
}
|
|
54
57
|
if (typeof params !== "object" || Array.isArray(params)) throw reject("PARAMS_TYPE_NOT_SUPPORTED", { expected: "json" });
|
|
55
58
|
if ("$milkioGenerateParams" in params && params.$milkioGenerateParams === "enable") {
|
|
56
|
-
if (!runtime.
|
|
59
|
+
if (!runtime.develop) throw reject("NOT_DEVELOP_MODE", "This feature must be in cookbook to use.");
|
|
57
60
|
delete params.$milkioGenerateParams;
|
|
58
61
|
let paramsRand = routeSchema.randomParams();
|
|
59
62
|
if (paramsRand === undefined || paramsRand === null) paramsRand = {};
|
|
@@ -62,102 +65,59 @@ export const __initExecuter = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
|
|
|
62
65
|
if (options.mixinContext?.http?.params?.string) options.mixinContext.http.params.parsed = params; // listen でパースしたパラメータを渡す
|
|
63
66
|
const context = {
|
|
64
67
|
...(options.mixinContext ? options.mixinContext : {}),
|
|
68
|
+
develop: runtime.develop,
|
|
69
|
+
envMode,
|
|
65
70
|
path: options.path,
|
|
66
71
|
logger: options.createdLogger,
|
|
67
72
|
executeId: options.createdExecuteId,
|
|
68
|
-
|
|
73
|
+
getConfig: (namespace: string) => __getConfig(generated, env, envMode, namespace),
|
|
74
|
+
call: (module: any, options: any) => __call(context, module, options),
|
|
69
75
|
} as unknown as $context;
|
|
70
|
-
const results: Results<
|
|
76
|
+
const results: Results<any> = { value: undefined };
|
|
71
77
|
|
|
72
|
-
if (runtime.
|
|
78
|
+
if (runtime.develop) {
|
|
73
79
|
options.createdLogger.request(`headers - ${TSON.stringify(headers.toJSON())}`, `\nparams - ${TSON.stringify(params)}`);
|
|
74
80
|
}
|
|
75
81
|
|
|
76
82
|
const module = await routeSchema.module();
|
|
77
|
-
let meta = (module.meta ? module.meta : {}) as unknown as Readonly<$meta>;
|
|
83
|
+
let meta = (module.default?.meta ? module.default?.meta : {}) as unknown as Readonly<$meta>;
|
|
78
84
|
|
|
79
|
-
if (
|
|
85
|
+
if (meta.typeSafety === undefined || meta.typeSafety === true) {
|
|
80
86
|
const validation = routeSchema.validateParams(params) as IValidation<any>;
|
|
81
87
|
if (!validation.success) throw reject("PARAMS_TYPE_INCORRECT", { ...validation.errors[0], message: `The value '${validation.errors[0].path}' is '${validation.errors[0].value}', which does not meet '${validation.errors[0].expected}' requirements.` });
|
|
82
88
|
}
|
|
83
89
|
|
|
84
|
-
await runtime.emit("milkio:executeBefore", { executeId: options.createdExecuteId, logger: options.createdLogger, path: options.path, context });
|
|
90
|
+
await runtime.emit("milkio:executeBefore", { executeId: options.createdExecuteId, logger: options.createdLogger, path: options.path, meta, context });
|
|
85
91
|
|
|
86
92
|
results.value = await module.default.handler(context, params);
|
|
87
93
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const executeId = createId();
|
|
96
|
-
const logger = createLogger(runtime, path, executeId);
|
|
97
|
-
runtime.runtime.request.set(executeId, { logger: logger });
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
const routeSchema = generated.routeSchema.routes.get(path);
|
|
101
|
-
if (routeSchema === undefined) {
|
|
102
|
-
throw reject("NOT_FOUND", { path: path });
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const executed = await __call(routeSchema, {
|
|
106
|
-
createdExecuteId: executeId,
|
|
107
|
-
createdLogger: logger,
|
|
108
|
-
path: path,
|
|
109
|
-
headers: options.headers ?? {},
|
|
110
|
-
mixinContext: {},
|
|
111
|
-
params: options.params ?? {},
|
|
112
|
-
paramsType: "raw",
|
|
113
|
-
});
|
|
94
|
+
let resultsTypeSafety = false;
|
|
95
|
+
if (results?.value?.$milkioType === "type-safety") {
|
|
96
|
+
resultsTypeSafety = true;
|
|
97
|
+
const validation = routeSchema.validateResults(results.value.value) as IValidation<any>;
|
|
98
|
+
if (!validation.success) throw reject("RESULTS_TYPE_INCORRECT", { ...validation.errors[0], message: `The value '${validation.errors[0].path}' is '${validation.errors[0].value}', which does not meet '${validation.errors[0].expected}' requirements.` });
|
|
99
|
+
results.value = results.value.value;
|
|
100
|
+
}
|
|
114
101
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
for await (const result of executed.results.value) {
|
|
122
|
-
yield [null, result];
|
|
123
|
-
}
|
|
124
|
-
return undefined;
|
|
125
|
-
} catch (error) {
|
|
126
|
-
const reject = exceptionHandler(executeId, logger, error);
|
|
127
|
-
const result: any = {};
|
|
128
|
-
result[reject.code] = reject.reject;
|
|
102
|
+
let emptyResult = false;
|
|
103
|
+
if (results.value === undefined || results.value === null || results.value === "") {
|
|
104
|
+
emptyResult = true;
|
|
105
|
+
results.value = {};
|
|
106
|
+
} else if (Array.isArray(results.value)) throw reject("FAIL", "The return type of the handler must be an object, which is currently an array.");
|
|
107
|
+
else if (typeof results.value !== "object") throw reject("FAIL", "The return type of the handler must be an object, which is currently a primitive type.");
|
|
129
108
|
|
|
130
|
-
|
|
131
|
-
return undefined;
|
|
132
|
-
}
|
|
133
|
-
})(),
|
|
134
|
-
{ executeId: executeId },
|
|
135
|
-
];
|
|
136
|
-
} else {
|
|
137
|
-
// action
|
|
138
|
-
return [null, executed.results.value, { executeId: executeId }];
|
|
139
|
-
}
|
|
140
|
-
} catch (error) {
|
|
141
|
-
const reject = exceptionHandler(executeId, logger, error);
|
|
142
|
-
const result: any = {};
|
|
143
|
-
result[reject.code] = reject.reject;
|
|
109
|
+
await runtime.emit("milkio:executeAfter", { executeId: options.createdExecuteId, logger: options.createdLogger, path: options.path, meta, context, results });
|
|
144
110
|
|
|
145
|
-
|
|
146
|
-
}
|
|
111
|
+
return { executeId, headers, params, results, context, meta, type: module.$milkioType, emptyResult, resultsTypeSafety };
|
|
147
112
|
};
|
|
148
113
|
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
delay: 0,
|
|
154
|
-
serverTimestamp: Date.now(),
|
|
155
|
-
},
|
|
156
|
-
];
|
|
114
|
+
const __call = async (context: $context, module: { default: any }, params?: any): Promise<any> => {
|
|
115
|
+
const moduleAwaited = await module;
|
|
116
|
+
return await moduleAwaited.default.handler(context, params);
|
|
117
|
+
};
|
|
157
118
|
|
|
158
119
|
return {
|
|
159
120
|
__call,
|
|
160
|
-
|
|
161
|
-
ping,
|
|
121
|
+
__execute,
|
|
162
122
|
};
|
|
163
123
|
};
|
package/index.ts
CHANGED
package/listener/index.ts
CHANGED
|
@@ -14,10 +14,14 @@ export type MilkioHttpResponse = Mixin<
|
|
|
14
14
|
}
|
|
15
15
|
>;
|
|
16
16
|
|
|
17
|
-
export const __initListener =
|
|
17
|
+
export const __initListener = (generated: GeneratedInit, runtime: any, executer: ReturnType<typeof __initExecuter>) => {
|
|
18
18
|
const port = runtime.port;
|
|
19
|
-
const fetch = async (
|
|
20
|
-
|
|
19
|
+
const fetch = async (options: {
|
|
20
|
+
request: MilkioHttpRequest;
|
|
21
|
+
envMode?: string;
|
|
22
|
+
env?: Record<any, any>;
|
|
23
|
+
}): Promise<Response> => {
|
|
24
|
+
if (options.request.method === "OPTIONS") {
|
|
21
25
|
return new Response(undefined, {
|
|
22
26
|
headers: {
|
|
23
27
|
"Access-Control-Allow-Methods": runtime.cors?.corsAllowMethods ?? "*",
|
|
@@ -27,7 +31,7 @@ export const __initListener = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
|
|
|
27
31
|
});
|
|
28
32
|
}
|
|
29
33
|
|
|
30
|
-
if (request.url.endsWith("/generate_204")) {
|
|
34
|
+
if (options.request.url.endsWith("/generate_204")) {
|
|
31
35
|
return new Response("", {
|
|
32
36
|
status: 204,
|
|
33
37
|
headers: {
|
|
@@ -40,12 +44,12 @@ export const __initListener = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
|
|
|
40
44
|
});
|
|
41
45
|
}
|
|
42
46
|
|
|
43
|
-
const url = new URL(request.url);
|
|
47
|
+
const url = new URL(options.request.url);
|
|
44
48
|
let pathArray = url.pathname.substring(1).split("/");
|
|
45
49
|
if (runtime.ignorePathLevel !== undefined && runtime.ignorePathLevel !== 0) pathArray = pathArray.slice(runtime.ignorePathLevel);
|
|
46
50
|
const pathString = `/${pathArray.join("/")}`;
|
|
47
51
|
|
|
48
|
-
const executeId = runtime?.executeId ? await runtime.executeId(request) : createId();
|
|
52
|
+
const executeId = runtime?.executeId ? await runtime.executeId(options.request) : createId();
|
|
49
53
|
const logger = createLogger(runtime, pathString, executeId);
|
|
50
54
|
runtime.runtime.request.set(executeId, { logger: logger });
|
|
51
55
|
const response: MilkioHttpResponse = {
|
|
@@ -62,9 +66,9 @@ export const __initListener = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
|
|
|
62
66
|
|
|
63
67
|
try {
|
|
64
68
|
const http = (await (async () => {
|
|
65
|
-
const ip = runtime.realIp ? runtime.realIp(request) : "::1";
|
|
69
|
+
const ip = runtime.realIp ? runtime.realIp(options.request) : "::1";
|
|
66
70
|
const params = {
|
|
67
|
-
string: await request.text(),
|
|
71
|
+
string: await options.request.text(),
|
|
68
72
|
parsed: undefined,
|
|
69
73
|
};
|
|
70
74
|
|
|
@@ -73,14 +77,19 @@ export const __initListener = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
|
|
|
73
77
|
ip,
|
|
74
78
|
path: { string: pathString as keyof $types["generated"]["routeSchema"]["$types"], array: pathArray },
|
|
75
79
|
params,
|
|
76
|
-
request,
|
|
80
|
+
request: options.request,
|
|
77
81
|
response,
|
|
78
82
|
} as ContextHttp;
|
|
79
83
|
})())!;
|
|
80
84
|
|
|
81
85
|
await runtime.emit("milkio:httpRequest", { executeId, logger, path: http.path.string as string, http });
|
|
82
86
|
|
|
83
|
-
if (!
|
|
87
|
+
if (!runtime.develop && ((http.path.string as string).includes("__") || (http.path.string as string).startsWith("/$call/"))) {
|
|
88
|
+
await runtime.emit("milkio:httpNotFound", { executeId, logger, path: http.path.string as string, http });
|
|
89
|
+
throw reject("NOT_FOUND", { path: http.path.string as string });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (!options.request.headers.get("Accept")?.startsWith("text/event-stream")) {
|
|
84
93
|
// action
|
|
85
94
|
const routeSchema = generated.routeSchema.routes.get(http.path.string);
|
|
86
95
|
if (routeSchema === undefined) {
|
|
@@ -89,17 +98,25 @@ export const __initListener = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
|
|
|
89
98
|
}
|
|
90
99
|
if (routeSchema.type !== "action") throw reject("UNACCEPTABLE", { expected: "stream", message: `Not acceptable, the Accept in the request header should be "text/event-stream". If you are using the "@milkio/stargate" package, please add \`type: "stream"\` to the execute options.` });
|
|
91
100
|
|
|
92
|
-
const executed = await executer.
|
|
101
|
+
const executed = await executer.__execute(options.env, options.envMode, routeSchema, {
|
|
93
102
|
createdExecuteId: executeId,
|
|
94
103
|
createdLogger: logger,
|
|
95
104
|
path: http.path.string as string,
|
|
96
|
-
headers: request.headers as Headers,
|
|
105
|
+
headers: options.request.headers as Headers,
|
|
97
106
|
mixinContext: { http },
|
|
98
107
|
params: http.params.string,
|
|
99
108
|
paramsType: "string",
|
|
100
109
|
});
|
|
101
110
|
|
|
102
|
-
if (
|
|
111
|
+
if (response.body === "" && executed.results.value !== undefined) {
|
|
112
|
+
if (executed.emptyResult) {
|
|
113
|
+
response.body = `{"data":{},"executeId":"${executeId}","success":true}`;
|
|
114
|
+
} else if (executed.resultsTypeSafety) {
|
|
115
|
+
response.body = `{"data":${routeSchema.resultsToJSON(executed.results.value)},"executeId":"${executeId}","success":true}`;
|
|
116
|
+
} else {
|
|
117
|
+
response.body = `{"data":${TSON.stringify(executed.results.value)},"executeId":"${executeId}","success":true}`;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
103
120
|
|
|
104
121
|
await runtime.emit("milkio:httpResponse", { executeId, logger, path: http.path.string as string, http, context: executed.context });
|
|
105
122
|
|
|
@@ -111,11 +128,11 @@ export const __initListener = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
|
|
|
111
128
|
if (routeSchema === undefined) throw reject("NOT_FOUND", { path: http.path.string as string });
|
|
112
129
|
if (routeSchema.type !== "stream") throw reject("UNACCEPTABLE", { expected: "stream", message: `Not acceptable, the Accept in the request header should be "application/json". If you are using the "@milkio/stargate" package, please remove \`type: "stream"\` to the execute options.` });
|
|
113
130
|
|
|
114
|
-
const executed = await executer.
|
|
131
|
+
const executed = await executer.__execute(options.env, options.envMode, routeSchema, {
|
|
115
132
|
createdExecuteId: executeId,
|
|
116
133
|
createdLogger: logger,
|
|
117
134
|
path: http.path.string as string,
|
|
118
|
-
headers: request.headers as Headers,
|
|
135
|
+
headers: options.request.headers as Headers,
|
|
119
136
|
mixinContext: { http },
|
|
120
137
|
params: http.params.string,
|
|
121
138
|
paramsType: "string",
|
|
@@ -132,7 +149,7 @@ export const __initListener = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
|
|
|
132
149
|
try {
|
|
133
150
|
controller.write(`data:@${JSON.stringify({ success: true, data: undefined, executeId } satisfies MilkioResponseSuccess<any>)}\n\n`);
|
|
134
151
|
for await (const value of executed.results.value) {
|
|
135
|
-
if (!request.signal.aborted) {
|
|
152
|
+
if (!options.request.signal.aborted) {
|
|
136
153
|
const result: string = JSON.stringify([null, TSON.encode(value)]);
|
|
137
154
|
controller.write(`data:${result}\n\n`);
|
|
138
155
|
} else {
|
|
@@ -161,7 +178,7 @@ export const __initListener = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
|
|
|
161
178
|
try {
|
|
162
179
|
controller.enqueue(`data:@${JSON.stringify({ success: true, data: undefined, executeId } satisfies MilkioResponseSuccess<any>)}\n\n`);
|
|
163
180
|
for await (const value of executed.results.value) {
|
|
164
|
-
if (!request.signal.aborted) {
|
|
181
|
+
if (!options.request.signal.aborted) {
|
|
165
182
|
const result: string = JSON.stringify([null, TSON.encode(value)]);
|
|
166
183
|
controller.enqueue(`data:${result}\n\n`);
|
|
167
184
|
} else {
|
package/logger/index.ts
CHANGED
|
@@ -52,7 +52,7 @@ export const createLogger = <MilkioRuntime extends MilkioRuntimeInit<MilkioRunti
|
|
|
52
52
|
if (!inserting(log)) return log;
|
|
53
53
|
|
|
54
54
|
logger._.logs.push([...log]);
|
|
55
|
-
if (runtime.
|
|
55
|
+
if (runtime.develop) {
|
|
56
56
|
void sendCookbookEvent(runtime, {
|
|
57
57
|
type: "milkio@logger",
|
|
58
58
|
log: log,
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "milkio",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"module": "index.ts",
|
|
5
|
-
"version": "1.0.0-alpha.
|
|
5
|
+
"version": "1.0.0-alpha.31",
|
|
6
6
|
"peerDependencies": {
|
|
7
7
|
"typescript": "^5.4.2"
|
|
8
8
|
},
|
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@paralleldrive/cuid2": "^2.2.2",
|
|
12
12
|
"@poech/camel-hump-under": "^1.1.0",
|
|
13
|
-
"@southern-aurora/tson": "
|
|
13
|
+
"@southern-aurora/tson": "*",
|
|
14
14
|
"chalk": "^5.3.0",
|
|
15
15
|
"date-fns": "^4.1.0",
|
|
16
|
-
"typia": "6.
|
|
16
|
+
"typia": "6.11.3"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@types/bun": "latest",
|
package/step/index.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { ToEmptyObject } from "..";
|
|
2
|
-
|
|
3
1
|
export type Steps<StageT extends Record<any, any>> = {
|
|
4
2
|
step: StepFunction<StageT>;
|
|
5
3
|
run: () => Promise<Remove_<StageT>>;
|
|
@@ -9,9 +7,11 @@ type Remove_<T> = {
|
|
|
9
7
|
[K in keyof T as K extends `_${string}` ? never : K]: T[K];
|
|
10
8
|
};
|
|
11
9
|
|
|
10
|
+
type ToEmptyObject<T> = T extends undefined | null | never ? {} : T extends object ? T : {};
|
|
11
|
+
|
|
12
12
|
export type StepFunction<StageT extends Record<any, any>> = <HandlerT extends (stage: Readonly<StageT>) => Record<any, any> | Promise<Record<any, any>>>(handler: HandlerT) => Steps<Awaited<StageT> & ToEmptyObject<Awaited<ReturnType<HandlerT>>>>;
|
|
13
13
|
|
|
14
|
-
export const createStep = (): Steps<{}>
|
|
14
|
+
export const createStep = (): Steps<{}> => {
|
|
15
15
|
const stepController = {
|
|
16
16
|
$milkioType: "step",
|
|
17
17
|
_steps: [] as Array<(stage: any) => Promise<any>>,
|
|
@@ -32,5 +32,5 @@ export const createStep = (): Steps<{}>["step"] => {
|
|
|
32
32
|
return result;
|
|
33
33
|
},
|
|
34
34
|
};
|
|
35
|
-
return stepController
|
|
35
|
+
return stepController as any as Steps<{}>;
|
|
36
36
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type TypeSafety<Value extends Record<any, any>> = (value: Value) => TypeSafetyValue;
|
|
2
|
+
|
|
3
|
+
export type TypeSafetyValue = {
|
|
4
|
+
type: <Type extends Record<any, any>>() => Type;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export type TypeSafetyType<Type extends Record<any, any>> = {
|
|
8
|
+
$milkioType: "type-safety";
|
|
9
|
+
value: Type;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function typeSafety<Value extends Record<any, any>>(value: Value): TypeSafetyValue {
|
|
13
|
+
return {
|
|
14
|
+
type: () => ({ $milkioType: "type-safety", value }),
|
|
15
|
+
} as any;
|
|
16
|
+
}
|
package/types/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type $rejectCode } from "..";
|
|
1
|
+
import { type $context, type $rejectCode } from "..";
|
|
2
2
|
|
|
3
3
|
export interface $types {
|
|
4
4
|
[key: string]: Record<any, any>;
|
|
@@ -10,7 +10,15 @@ export type Mixin<T, U> = U & Omit<T, keyof U>;
|
|
|
10
10
|
|
|
11
11
|
export type GeneratorGeneric<T> = T extends AsyncGenerator<infer I> ? I : never;
|
|
12
12
|
|
|
13
|
-
export type
|
|
13
|
+
export type DBSelect<T extends Record<any, any>, K extends keyof T> = Omit<T, K>;
|
|
14
|
+
|
|
15
|
+
export type DBCreate<T, KO extends keyof T | never = never, TO extends Omit<T, KO> = Omit<T, KO>> = {
|
|
16
|
+
[K in keyof TO]?: TO[K] extends null ? undefined : Exclude<TO[K], null>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type DBUpdate<T, KO extends keyof T | never = never, TO extends Partial<Omit<T, KO>> = Partial<Omit<T, KO>>> = {
|
|
20
|
+
[K in keyof TO]?: TO[K] extends null ? undefined : Exclude<TO[K], null>;
|
|
21
|
+
};
|
|
14
22
|
|
|
15
23
|
export type ExecuteId = string | "global";
|
|
16
24
|
|
|
@@ -20,6 +28,7 @@ export type ExecuteId = string | "global";
|
|
|
20
28
|
export type GeneratedInit = {
|
|
21
29
|
routeSchema: any;
|
|
22
30
|
commandSchema: any;
|
|
31
|
+
configSchema: any;
|
|
23
32
|
testSchema: any;
|
|
24
33
|
};
|
|
25
34
|
|
|
@@ -50,21 +59,6 @@ export type Ping =
|
|
|
50
59
|
},
|
|
51
60
|
];
|
|
52
61
|
|
|
53
|
-
export type Execute = <Path extends keyof $types["generated"]["routeSchema"]["$types"]>(
|
|
54
|
-
path: Path,
|
|
55
|
-
options?: Mixin<
|
|
56
|
-
ExecuteOptions,
|
|
57
|
-
{
|
|
58
|
-
headers?: Record<string, string>;
|
|
59
|
-
params?: $types["generated"]["routeSchema"]["$types"][Path]["params"];
|
|
60
|
-
}
|
|
61
|
-
>,
|
|
62
|
-
) => $types["generated"]["routeSchema"]["$types"][Path]["🐣"] extends boolean
|
|
63
|
-
? // action
|
|
64
|
-
Promise<[Partial<$rejectCode>, null, ExecuteResultsOption] | [null, ExecuteActionResults<Path>, ExecuteResultsOption]>
|
|
65
|
-
: // stream
|
|
66
|
-
Promise<[Partial<$rejectCode>, null, ExecuteResultsOption] | [null, AsyncGenerator<[Partial<$rejectCode>, null] | [null, ExecuteStreamResults<Path>], null>, ExecuteResultsOption]>;
|
|
67
|
-
|
|
68
62
|
export type ExecuteResultsOption = { executeId: string };
|
|
69
63
|
|
|
70
64
|
export type ExecuteActionResults<Path extends keyof Generated["routeSchema"]["$types"], Generated extends $types["generated"] = $types["generated"]> = Generated["routeSchema"]["$types"][Path]["result"];
|
|
@@ -8,7 +8,7 @@ type CookbookEvent = {
|
|
|
8
8
|
|
|
9
9
|
export const sendCookbookEvent = async (runtime: MilkioRuntimeInit<MilkioInit>, event: CookbookEvent) => {
|
|
10
10
|
try {
|
|
11
|
-
const response = await fetch(`http://localhost:${runtime.cookbook
|
|
11
|
+
const response = await fetch(`http://localhost:${runtime.cookbook.cookbookPort}/$action`, {
|
|
12
12
|
method: "POST",
|
|
13
13
|
headers: {
|
|
14
14
|
"Content-Type": "application/json",
|
package/world/index.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { __initCommander, __initListener, __initExecuter, __initEventManager, type ExecuteId, type Logger, type Mixin, type GeneratedInit, type
|
|
1
|
+
import { __initCommander, __initListener, __initExecuter, __initEventManager, type ExecuteId, type Logger, type Mixin, type GeneratedInit, type Ping, type LoggerSubmittingHandler, type LoggerInsertingHandler, type $context, $types, __getConfig } from "..";
|
|
2
2
|
import { defineDefaultExecuteIdGenerator } from "../execute/execute-id-generator";
|
|
3
3
|
|
|
4
4
|
export type MilkioInit = {
|
|
5
5
|
port: number;
|
|
6
|
-
|
|
6
|
+
develop: boolean;
|
|
7
|
+
cookbook: {
|
|
7
8
|
cookbookPort: number;
|
|
8
9
|
};
|
|
9
10
|
cors?: {
|
|
@@ -24,6 +25,7 @@ export type MilkioRuntimeInit<T extends MilkioInit> = Mixin<
|
|
|
24
25
|
executeId: (request: Request) => string | Promise<string>;
|
|
25
26
|
runtime: {
|
|
26
27
|
request: Map<ExecuteId, { logger: Logger }>;
|
|
28
|
+
app: any;
|
|
27
29
|
};
|
|
28
30
|
on: Awaited<ReturnType<typeof __initEventManager>>["on"];
|
|
29
31
|
off: Awaited<ReturnType<typeof __initEventManager>>["off"];
|
|
@@ -52,6 +54,8 @@ export const createWorld = async <MilkioOptions extends MilkioInit>(generated: G
|
|
|
52
54
|
const executer = __initExecuter(generated, _);
|
|
53
55
|
const commander = __initCommander(generated, _);
|
|
54
56
|
const listener = __initListener(generated, _, executer);
|
|
57
|
+
// functions
|
|
58
|
+
const getConfig = (namespace: keyof $types["generated"]["configSchema"], env: Record<any, any>, envMode: string) => __getConfig(generated, env, envMode, namespace);
|
|
55
59
|
|
|
56
60
|
// Initialize the app
|
|
57
61
|
const app = {
|
|
@@ -60,16 +64,16 @@ export const createWorld = async <MilkioOptions extends MilkioInit>(generated: G
|
|
|
60
64
|
on: eventManager.on,
|
|
61
65
|
off: eventManager.off,
|
|
62
66
|
emit: eventManager.emit,
|
|
63
|
-
// executer
|
|
64
|
-
_executer: executer,
|
|
65
|
-
execute: executer.execute,
|
|
66
|
-
ping: executer.ping,
|
|
67
67
|
// commander
|
|
68
68
|
commander,
|
|
69
69
|
// listener
|
|
70
70
|
listener,
|
|
71
|
+
// functions
|
|
72
|
+
getConfig,
|
|
71
73
|
};
|
|
72
74
|
|
|
75
|
+
runtime.app = app;
|
|
76
|
+
|
|
73
77
|
return app as MilkioWorld<MilkioOptions>;
|
|
74
78
|
};
|
|
75
79
|
|
|
@@ -79,12 +83,10 @@ export type MilkioWorld<MilkioOptions extends MilkioInit = MilkioInit> = {
|
|
|
79
83
|
on: Awaited<ReturnType<typeof __initEventManager>>["on"];
|
|
80
84
|
off: Awaited<ReturnType<typeof __initEventManager>>["off"];
|
|
81
85
|
emit: Awaited<ReturnType<typeof __initEventManager>>["emit"];
|
|
82
|
-
// executer
|
|
83
|
-
_executer: Awaited<ReturnType<typeof __initExecuter<MilkioRuntimeInit<MilkioOptions>>>>;
|
|
84
|
-
execute: Execute;
|
|
85
86
|
ping: (options?: { timeout?: number }) => Promise<Ping>;
|
|
86
87
|
// commander
|
|
87
|
-
commander: Awaited<ReturnType<typeof __initCommander
|
|
88
|
+
commander: Awaited<ReturnType<typeof __initCommander>>;
|
|
88
89
|
// listener
|
|
89
|
-
listener: Awaited<ReturnType<typeof __initListener
|
|
90
|
+
listener: Awaited<ReturnType<typeof __initListener>>;
|
|
91
|
+
getConfig: <Namespace extends keyof $types["generated"]["configSchema"]>(namespace: Namespace, env: Record<any, any>, envMode: string) => Promise<Readonly<Awaited<ReturnType<$types["generated"]["configSchema"][Namespace][0]>>>>;
|
|
90
92
|
};
|