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.
@@ -0,0 +1,13 @@
1
+ # 1.0.0-alpha.21 - 某章节名
2
+
3
+ > 一段编纂出来的虚构科幻小说的摘抄片段
4
+
5
+ ## ...更新内容...
6
+
7
+ ...更新内容...
8
+
9
+ ## 升级
10
+
11
+ ```
12
+ bun i milkio@1.0.0-alpha.21
13
+ ```
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 = <MilkioRuntime extends MilkioRuntimeInit<MilkioInit> = MilkioRuntimeInit<MilkioInit>>(generated: GeneratedInit, runtime: MilkioRuntime) => {
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",
@@ -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?: ContextHttp<Record<any, any>>;
8
- step: Steps<{}>["step"];
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 = () => {
@@ -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 { createId } from "../utils/create-id";
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 = <MilkioRuntime extends MilkioRuntimeInit<MilkioRuntimeInit<MilkioInit>> = MilkioRuntimeInit<MilkioInit>>(generated: GeneratedInit, runtime: MilkioRuntime) => {
8
- const __call = async (
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.cookbook) throw reject("NOT_DEVELOP_MODE", "This feature must be in cookbook to use.");
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
- step: createStep(),
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<unknown> = { value: undefined };
76
+ const results: Results<any> = { value: undefined };
71
77
 
72
- if (runtime.cookbook) {
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 (!meta.typeSafety || meta.typeSafety === true) {
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
- await runtime.emit("milkio:executeAfter", { executeId: options.createdExecuteId, logger: options.createdLogger, path: options.path, context, results });
89
-
90
- return { executeId, headers, params, results, context, meta, type: module.$milkioType };
91
- };
92
-
93
- const execute = async (path: string, options?: ExecuteOptions): Promise<any> => {
94
- if (!options) options = {};
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
- if (routeSchema.type === "stream") {
116
- // stream
117
- return [
118
- undefined,
119
- (async function* () {
120
- try {
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
- yield [result, null];
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
- return [result, null, { executeId: executeId }];
146
- }
111
+ return { executeId, headers, params, results, context, meta, type: module.$milkioType, emptyResult, resultsTypeSafety };
147
112
  };
148
113
 
149
- const ping = async (): Promise<Ping> => [
150
- null,
151
- {
152
- connect: true,
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
- execute,
161
- ping,
121
+ __execute,
162
122
  };
163
123
  };
package/index.ts CHANGED
@@ -1,4 +1,7 @@
1
+ export * from "./type-safety";
2
+ export * from "@southern-aurora/tson";
1
3
  export * from "./types";
4
+ export * from "./config";
2
5
  export * from "./execute";
3
6
  export * from "./events";
4
7
  export * from "./world";
package/listener/index.ts CHANGED
@@ -14,10 +14,14 @@ export type MilkioHttpResponse = Mixin<
14
14
  }
15
15
  >;
16
16
 
17
- export const __initListener = <MilkioRuntime extends MilkioRuntimeInit<MilkioRuntimeInit<MilkioInit>> = MilkioRuntimeInit<MilkioInit>>(generated: GeneratedInit, runtime: MilkioRuntime, executer: ReturnType<typeof __initExecuter>) => {
17
+ export const __initListener = (generated: GeneratedInit, runtime: any, executer: ReturnType<typeof __initExecuter>) => {
18
18
  const port = runtime.port;
19
- const fetch = async (request: MilkioHttpRequest): Promise<Response> => {
20
- if (request.method === "OPTIONS") {
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 (!request.headers.get("Accept")?.startsWith("text/event-stream")) {
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.__call(routeSchema, {
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 (executed.results.value !== undefined) response.body = TSON.stringify({ success: true, data: executed.results.value, executeId } satisfies MilkioResponseSuccess<any>);
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.__call(routeSchema, {
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.cookbook) {
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.3",
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": "^2.0.2",
13
+ "@southern-aurora/tson": "*",
14
14
  "chalk": "^5.3.0",
15
15
  "date-fns": "^4.1.0",
16
- "typia": "6.9.0"
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<{}>["step"] => {
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.step as any as Steps<{}>["step"];
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 ToEmptyObject<T> = T extends undefined | null | never ? {} : T extends object ? T : {};
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?.cookbookPort}/$action`, {
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 Execute, type Ping, type ContextCreatedHandler, LoggerSubmittingHandler, LoggerInsertingHandler } from "..";
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
- cookbook?: {
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<MilkioRuntimeInit<MilkioOptions>>>>;
88
+ commander: Awaited<ReturnType<typeof __initCommander>>;
88
89
  // listener
89
- listener: Awaited<ReturnType<typeof __initListener<MilkioRuntimeInit<MilkioOptions>>>>;
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
  };