milkio 1.0.0-alpha.2 → 1.0.0-alpha.4

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/.co.toml CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/action/index.ts CHANGED
File without changes
package/command/index.ts CHANGED
File without changes
package/context/index.ts CHANGED
@@ -1,13 +1,14 @@
1
- import { type MilkioHttpRequest, type MilkioHttpResponse, type $types, type Logger } from "..";
1
+ import { type MilkioHttpRequest, type MilkioHttpResponse, type $types, type Logger, Steps } from "..";
2
2
 
3
3
  export interface $context {
4
4
  executeId: string;
5
5
  path: string;
6
6
  logger: Logger;
7
7
  http?: ContextHttp<Record<any, any>>;
8
+ step: Steps<{}>["step"];
8
9
  }
9
10
 
10
- export type ContextHttp<ParamsParsed> = {
11
+ export type ContextHttp<ParamsParsed = any> = {
11
12
  url: URL;
12
13
  ip: string;
13
14
  path: { string: keyof $types["generated"]["routeSchema"]["$types"]; array: Array<string> };
@@ -18,3 +19,5 @@ export type ContextHttp<ParamsParsed> = {
18
19
  request: MilkioHttpRequest;
19
20
  response: MilkioHttpResponse;
20
21
  };
22
+
23
+ export type ContextCreatedHandler = (context: $context) => Promise<void> | void;
@@ -0,0 +1,47 @@
1
+ import { type $context, type ContextHttp, type Results, type Logger } from "..";
2
+
3
+ export interface $events {
4
+ "milkio:httpRequest": { executeId: string; path: string; logger: Logger; http: ContextHttp<Record<string, any>> };
5
+ "milkio:httpResponse": { executeId: string; path: string; logger: Logger; http: ContextHttp<Record<string, any>>; context: $context };
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> };
9
+ }
10
+
11
+ export const __initEventManager = () => {
12
+ const handlers = new Map<(event: any) => void, string>();
13
+ const indexed = new Map<string, Set<(event: any) => void>>();
14
+
15
+ const eventManager = {
16
+ on: <Key extends keyof $events, Handler extends (event: $events[Key]) => void>(key: Key, handler: Handler) => {
17
+ handlers.set(handler, key as string);
18
+ if (indexed.has(key as string) === false) {
19
+ indexed.set(key as string, new Set());
20
+ }
21
+ const set = indexed.get(key as string)!;
22
+ set.add(handler);
23
+ handlers.set(handler, key as string);
24
+
25
+ return () => {
26
+ handlers.delete(handler);
27
+ set.delete(handler);
28
+ };
29
+ },
30
+ off: <Key extends keyof $events, Handler extends (event: $events[Key]) => void>(key: Key, handler: Handler) => {
31
+ const set = indexed.get(key as string);
32
+ if (!set) return;
33
+ handlers.delete(handler);
34
+ set.delete(handler);
35
+ },
36
+ emit: async <Key extends keyof $events, Value extends $events[Key]>(key: Key, value: Value): Promise<void> => {
37
+ const h = indexed.get(key as string);
38
+ if (h) {
39
+ for (const handler of h) {
40
+ await handler(value);
41
+ }
42
+ }
43
+ },
44
+ };
45
+
46
+ return eventManager;
47
+ };
@@ -8,7 +8,6 @@ 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;
12
11
  UNACCEPTABLE: { expected: string; message: string };
13
12
  PARAMS_TYPE_NOT_SUPPORTED: { expected: string };
14
13
  INTERNAL_SERVER_ERROR: undefined;
File without changes
package/execute/index.ts CHANGED
@@ -1,11 +1,8 @@
1
1
  import { type IValidation } from "typia";
2
2
  import { TSON } from "@southern-aurora/tson";
3
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 } from "..";
5
-
6
- export type MilkioHttpRequest = {
7
- request: Request;
8
- };
4
+ import { reject, type $context, type $meta, type ExecuteOptions, type Logger, type MilkioRuntimeInit, type Results, type GeneratedInit, type MilkioInit, createLogger, exceptionHandler, Ping, createStep } from "..";
5
+ import { headersToJSON } from "../utils/headers-to-json";
9
6
 
10
7
  export const __initExecuter = <MilkioRuntime extends MilkioRuntimeInit<MilkioRuntimeInit<MilkioInit>> = MilkioRuntimeInit<MilkioInit>>(generated: GeneratedInit, runtime: MilkioRuntime) => {
11
8
  const __call = async (
@@ -37,6 +34,8 @@ export const __initExecuter = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
37
34
  } else {
38
35
  headers = options.headers;
39
36
  }
37
+ if (!("toJSON" in headers)) (headers as any).toJSON = () => headersToJSON(headers);
38
+
40
39
  let params: Record<any, unknown>;
41
40
  if (options.paramsType === "raw") {
42
41
  params = options.params;
@@ -54,12 +53,11 @@ export const __initExecuter = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
54
53
  }
55
54
  if (typeof params !== "object" || Array.isArray(params)) throw reject("PARAMS_TYPE_NOT_SUPPORTED", { expected: "json" });
56
55
  if ("$milkioGenerateParams" in params && params.$milkioGenerateParams === "enable") {
57
- if (runtime.port.develop === "disabled") throw reject("NOT_DEVELOP_MODE", "This feature must be in developer mode to use. Usually entering developer mode requires using a cookbook to start milkio and accessing it through localhost.");
56
+ if (!runtime.develop) throw reject("NOT_DEVELOP_MODE", "This feature must be in cookbook to use.");
58
57
  delete params.$milkioGenerateParams;
59
58
  let paramsRand = routeSchema.randomParams();
60
59
  if (paramsRand === undefined || paramsRand === null) paramsRand = {};
61
60
  params = { ...paramsRand, ...params };
62
- options.createdLogger.debug("[milkio]", "🪄 generate params:", options.path, TSON.stringify(params));
63
61
  }
64
62
  if (options.mixinContext?.http?.params?.string) options.mixinContext.http.params.parsed = params; // listen でパースしたパラメータを渡す
65
63
  const context = {
@@ -67,24 +65,27 @@ export const __initExecuter = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
67
65
  path: options.path,
68
66
  logger: options.createdLogger,
69
67
  executeId: options.createdExecuteId,
68
+ step: createStep(),
70
69
  } as unknown as $context;
71
-
72
70
  const results: Results<unknown> = { value: undefined };
73
71
 
72
+ if (runtime.develop) {
73
+ options.createdLogger.request(`headers - ${TSON.stringify(headers.toJSON())}`, `\nparams - ${TSON.stringify(params)}`);
74
+ }
75
+
74
76
  const module = await routeSchema.module();
75
77
  let meta = (module.meta ? module.meta : {}) as unknown as Readonly<$meta>;
76
78
 
77
- if (!meta.typeSafety || meta.typeSafety.includes("params")) {
79
+ if (!meta.typeSafety || meta.typeSafety === true) {
78
80
  const validation = routeSchema.validateParams(params) as IValidation<any>;
79
81
  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.` });
80
82
  }
81
83
 
84
+ await runtime.emit("milkio:executeBefore", { executeId: options.createdExecuteId, logger: options.createdLogger, path: options.path, context });
85
+
82
86
  results.value = await module.default.handler(context, params);
83
87
 
84
- if (!meta.typeSafety || meta.typeSafety.includes("results")) {
85
- const validation = routeSchema.validateResults(results.value) as IValidation<any>;
86
- 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.` });
87
- }
88
+ await runtime.emit("milkio:executeAfter", { executeId: options.createdExecuteId, logger: options.createdLogger, path: options.path, context, results });
88
89
 
89
90
  return { executeId, headers, params, results, context, meta, type: module.$milkioType };
90
91
  };
@@ -92,12 +93,14 @@ export const __initExecuter = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
92
93
  const execute = async (path: string, options?: ExecuteOptions): Promise<any> => {
93
94
  if (!options) options = {};
94
95
  const executeId = createId();
95
- const logger = createLogger(runtime, executeId);
96
+ const logger = createLogger(runtime, path, executeId);
96
97
  runtime.runtime.request.set(executeId, { logger: logger });
97
98
 
98
99
  try {
99
100
  const routeSchema = generated.routeSchema.routes.get(path);
100
- if (routeSchema === undefined) throw reject("NOT_FOUND", { path: path });
101
+ if (routeSchema === undefined) {
102
+ throw reject("NOT_FOUND", { path: path });
103
+ }
101
104
 
102
105
  const executed = await __call(routeSchema, {
103
106
  createdExecuteId: executeId,
package/index.ts CHANGED
@@ -1,11 +1,13 @@
1
1
  export * from "./types";
2
+ export * from "./execute";
3
+ export * from "./events";
2
4
  export * from "./world";
3
5
  export * from "./command";
4
6
  export * from "./action";
5
7
  export * from "./stream";
6
- export * from "./test";
7
8
  export * from "./logger";
8
9
  export * from "./context";
9
10
  export * from "./meta";
11
+ export * from "./step";
10
12
  export * from "./listener";
11
13
  export * from "./exception";
package/listener/index.ts CHANGED
@@ -15,14 +15,14 @@ export type MilkioHttpResponse = Mixin<
15
15
  >;
16
16
 
17
17
  export const __initListener = <MilkioRuntime extends MilkioRuntimeInit<MilkioRuntimeInit<MilkioInit>> = MilkioRuntimeInit<MilkioInit>>(generated: GeneratedInit, runtime: MilkioRuntime, executer: ReturnType<typeof __initExecuter>) => {
18
- const port = runtime.port.app;
18
+ const port = runtime.port;
19
19
  const fetch = async (request: MilkioHttpRequest): Promise<Response> => {
20
20
  if (request.method === "OPTIONS") {
21
21
  return new Response(undefined, {
22
22
  headers: {
23
- "Access-Control-Allow-Methods": runtime.corsAllowMethods ?? "*",
24
- "Access-Control-Allow-Origin": runtime.corsAllowOrigin ?? "*",
25
- "Access-Control-Allow-Headers": runtime.corsAllowHeaders ?? "*",
23
+ "Access-Control-Allow-Methods": runtime.cors?.corsAllowMethods ?? "*",
24
+ "Access-Control-Allow-Origin": runtime.cors?.corsAllowOrigin ?? "*",
25
+ "Access-Control-Allow-Headers": runtime.cors?.corsAllowHeaders ?? "*",
26
26
  },
27
27
  });
28
28
  }
@@ -31,25 +31,30 @@ export const __initListener = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
31
31
  return new Response("", {
32
32
  status: 204,
33
33
  headers: {
34
- "Access-Control-Allow-Methods": runtime.corsAllowMethods ?? "*",
35
- "Access-Control-Allow-Origin": runtime.corsAllowOrigin ?? "*",
36
- "Access-Control-Allow-Headers": runtime.corsAllowHeaders ?? "*",
34
+ "Access-Control-Allow-Methods": runtime.cors?.corsAllowMethods ?? "*",
35
+ "Access-Control-Allow-Origin": runtime.cors?.corsAllowOrigin ?? "*",
36
+ "Access-Control-Allow-Headers": runtime.cors?.corsAllowHeaders ?? "*",
37
37
  "Cache-Control": "no-store",
38
38
  "Content-Type": "text/plain; time=" + Date.now(),
39
39
  },
40
40
  });
41
41
  }
42
42
 
43
- const executeId = runtime?.executeIdGenerator ? await runtime.executeIdGenerator(request) : createId();
44
- const logger = createLogger(runtime, executeId);
43
+ const url = new URL(request.url);
44
+ let pathArray = url.pathname.substring(1).split("/");
45
+ if (runtime.ignorePathLevel !== undefined && runtime.ignorePathLevel !== 0) pathArray = pathArray.slice(runtime.ignorePathLevel);
46
+ const pathString = `/${pathArray.join("/")}`;
47
+
48
+ const executeId = runtime?.executeId ? await runtime.executeId(request) : createId();
49
+ const logger = createLogger(runtime, pathString, executeId);
45
50
  runtime.runtime.request.set(executeId, { logger: logger });
46
51
  const response: MilkioHttpResponse = {
47
52
  body: "",
48
53
  status: 200,
49
54
  headers: {
50
- "Access-Control-Allow-Methods": runtime.corsAllowMethods ?? "*",
51
- "Access-Control-Allow-Origin": runtime.corsAllowOrigin ?? "*",
52
- "Access-Control-Allow-Headers": runtime.corsAllowHeaders ?? "*",
55
+ "Access-Control-Allow-Methods": runtime.cors?.corsAllowMethods ?? "*",
56
+ "Access-Control-Allow-Origin": runtime.cors?.corsAllowOrigin ?? "*",
57
+ "Access-Control-Allow-Headers": runtime.cors?.corsAllowHeaders ?? "*",
53
58
  "Cache-Control": "no-store",
54
59
  "Content-Type": "application/json",
55
60
  },
@@ -57,11 +62,7 @@ export const __initListener = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
57
62
 
58
63
  try {
59
64
  const http = (await (async () => {
60
- const url = new URL(request.url);
61
- let pathArray = url.pathname.substring(1).split("/");
62
- if (runtime.ignorePathLevel !== undefined && runtime.ignorePathLevel !== 0) pathArray = pathArray.slice(runtime.ignorePathLevel);
63
- const pathString = `/${pathArray.join("/")}`;
64
- const ip = runtime.getRealIp ? runtime.getRealIp(request) : "::1";
65
+ const ip = runtime.realIp ? runtime.realIp(request) : "::1";
65
66
  const params = {
66
67
  string: await request.text(),
67
68
  parsed: undefined,
@@ -74,13 +75,18 @@ export const __initListener = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
74
75
  params,
75
76
  request,
76
77
  response,
77
- } as ContextHttp<undefined>;
78
+ } as ContextHttp;
78
79
  })())!;
79
80
 
81
+ await runtime.emit("milkio:httpRequest", { executeId, logger, path: http.path.string as string, http });
82
+
80
83
  if (!request.headers.get("Accept")?.startsWith("text/event-stream")) {
81
84
  // action
82
85
  const routeSchema = generated.routeSchema.routes.get(http.path.string);
83
- if (routeSchema === undefined) throw reject("NOT_FOUND", { path: http.path.string as string });
86
+ if (routeSchema === undefined) {
87
+ await runtime.emit("milkio:httpNotFound", { executeId, logger, path: http.path.string as string, http });
88
+ throw reject("NOT_FOUND", { path: http.path.string as string });
89
+ }
84
90
  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.` });
85
91
 
86
92
  const executed = await executer.__call(routeSchema, {
@@ -95,6 +101,8 @@ export const __initListener = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
95
101
 
96
102
  if (executed.results.value !== undefined) response.body = TSON.stringify({ success: true, data: executed.results.value, executeId } satisfies MilkioResponseSuccess<any>);
97
103
 
104
+ await runtime.emit("milkio:httpResponse", { executeId, logger, path: http.path.string as string, http, context: executed.context });
105
+
98
106
  runtime.runtime.request.delete(executeId);
99
107
  return new Response(response.body, response);
100
108
  } else {
@@ -180,6 +188,8 @@ export const __initListener = <MilkioRuntime extends MilkioRuntimeInit<MilkioRun
180
188
  response.headers["Content-Type"] = "text/event-stream";
181
189
  response.headers["Cache-Control"] = "no-cache";
182
190
 
191
+ await runtime.emit("milkio:httpResponse", { executeId, logger, path: http.path.string as string, http, context: executed.context });
192
+
183
193
  runtime.runtime.request.delete(executeId);
184
194
  return new Response(response.body, response);
185
195
  }
package/logger/index.ts CHANGED
@@ -1,13 +1,14 @@
1
- import { TSON } from "@southern-aurora/tson";
2
1
  import { format } from "date-fns";
3
- import { type MilkioInit, type MilkioRuntimeInit } from "..";
2
+ import { type $context, type MilkioInit, type MilkioRuntimeInit } from "..";
3
+ import { sendCookbookEvent } from "../utils/send-cookbook-event";
4
4
 
5
- export type Log = [string /* executeId */, "[DEBUG]" | "[INFO]" | "[WARN]" | "[ERROR]", string, string, ...Array<unknown>];
5
+ export type Log = ["[DEBUG]" | "[INFO]" | "[WARN]" | "[ERROR]" | "[REQUEST]" | "[RESPONSE]", string /* executeId */, string, string, string, ...Array<unknown>];
6
6
 
7
7
  export type Logger = {
8
8
  _: {
9
9
  logs: Array<Log>;
10
10
  tags: Map<string, unknown>;
11
+ submit: (context: $context) => Promise<void> | void;
11
12
  };
12
13
  setTag: (key: string, value: unknown) => void;
13
14
  setLog: (...log: Log) => void;
@@ -15,53 +16,63 @@ export type Logger = {
15
16
  info: (description: string, ...params: Array<unknown>) => Log;
16
17
  warn: (description: string, ...params: Array<unknown>) => Log;
17
18
  error: (description: string, ...params: Array<unknown>) => Log;
19
+ request: (description: string, ...params: Array<unknown>) => Log;
20
+ response: (description: string, ...params: Array<unknown>) => Log;
18
21
  };
19
22
 
20
- export const createLogger = <MilkioRuntime extends MilkioRuntimeInit<MilkioRuntimeInit<MilkioInit>> = MilkioRuntimeInit<MilkioInit>>(runtime: MilkioRuntime, executeId: string): Logger => {
23
+ export type LoggerInsertingHandler = (log: Log) => boolean;
24
+
25
+ export type LoggerSubmittingHandler = (context: $context, logs: Array<Log>, tags: Map<string, unknown>) => Promise<void> | void;
26
+
27
+ export const createLogger = <MilkioRuntime extends MilkioRuntimeInit<MilkioRuntimeInit<MilkioInit>> = MilkioRuntimeInit<MilkioInit>>(runtime: MilkioRuntime, path: string, executeId: string): Logger => {
21
28
  const logger = {} as Logger;
22
29
 
23
30
  logger._ = {
24
31
  logs: new Array(),
25
32
  tags: new Map(),
33
+ submit: (context: $context) => {
34
+ if (!runtime.onLoggerSubmitting) return;
35
+ return runtime.onLoggerSubmitting(context, logger._.logs, logger._.tags);
36
+ },
26
37
  };
27
38
 
28
39
  const __tagPush = (key: string, value: unknown): void => {
29
40
  logger._.tags.set(key, value);
30
41
  };
31
42
  const __logPush = (log: Log): Log => {
43
+ const inserting = runtime.onLoggerInserting
44
+ ? runtime.onLoggerInserting
45
+ : (log: Log) => {
46
+ log = [...log];
47
+ log[0] = `\n${log[0]}` as any;
48
+ console.log(...log);
49
+ return true;
50
+ };
51
+
52
+ if (!inserting(log)) return log;
53
+
32
54
  logger._.logs.push([...log]);
33
- if (runtime.port.develop !== "disabled") {
34
- void (async () => {
35
- try {
36
- const response = await fetch(`http://localhost:${runtime.port.develop}/$action`, {
37
- method: "POST",
38
- headers: {
39
- "Content-Type": "application/json",
40
- },
41
- body: TSON.stringify({
42
- type: "milkio@logger",
43
- log: log,
44
- }),
45
- });
46
- if (!response.ok) console.log("[COOKBOOK]", await response.text());
47
- } catch (error) {
48
- console.log("[COOKBOOK]", error);
49
- }
50
- })();
55
+ if (runtime.cookbook) {
56
+ void sendCookbookEvent(runtime, {
57
+ type: "milkio@logger",
58
+ log: log,
59
+ });
51
60
  }
52
- console.log(...log);
61
+
53
62
  return log;
54
63
  };
55
64
 
56
65
  logger.setTag = (key: string, value: unknown) => __tagPush(key, value);
57
66
  logger.setLog = (...log: Log) => __logPush(log);
58
67
 
59
- const getNow = () => format(new Date(), "(yyyy-MM-dd hh:mm:ss)");
68
+ const getNow = () => `${format(new Date(), "(yyyy-MM-dd hh:mm:ss)")}`;
60
69
 
61
- logger.debug = (description: string, ...params: Array<unknown>) => __logPush([executeId, "[DEBUG]", description, getNow(), ...params]);
62
- logger.info = (description: string, ...params: Array<unknown>) => __logPush([executeId, "[INFO]", description, getNow(), ...params]);
63
- logger.warn = (description: string, ...params: Array<unknown>) => __logPush([executeId, "[WARN]", description, getNow(), ...params]);
64
- logger.error = (description: string, ...params: Array<unknown>) => __logPush([executeId, "[ERROR]", description, getNow(), ...params]);
70
+ logger.debug = (description: string, ...params: Array<unknown>) => __logPush(["[DEBUG]", path, executeId, getNow(), `\n${description}`, ...params]);
71
+ logger.info = (description: string, ...params: Array<unknown>) => __logPush(["[INFO]", path, executeId, getNow(), `\n${description}`, ...params]);
72
+ logger.warn = (description: string, ...params: Array<unknown>) => __logPush(["[WARN]", path, executeId, getNow(), `\n${description}`, ...params]);
73
+ logger.error = (description: string, ...params: Array<unknown>) => __logPush(["[ERROR]", path, executeId, getNow(), `\n${description}`, ...params]);
74
+ logger.request = (description: string, ...params: Array<unknown>) => __logPush(["[REQUEST]", path, executeId, getNow(), `\n${description}`, ...params]);
75
+ logger.response = (description: string, ...params: Array<unknown>) => __logPush(["[RESPONSE]", path, executeId, getNow(), `\n${description}`, ...params]);
65
76
 
66
77
  return logger;
67
78
  };
package/meta/index.ts CHANGED
@@ -3,7 +3,7 @@ export interface $meta {
3
3
  * type safety
4
4
  * @default ["params","results"]
5
5
  */
6
- typeSafety?: Array<"params" | "results">;
6
+ typeSafety?: boolean;
7
7
  /**
8
8
  * methods
9
9
  * @default ["POST"]
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.2",
5
+ "version": "1.0.0-alpha.4",
6
6
  "peerDependencies": {
7
7
  "typescript": "^5.4.2"
8
8
  },
package/step/index.ts ADDED
@@ -0,0 +1,36 @@
1
+ import type { ToEmptyObject } from "..";
2
+
3
+ export type Steps<StageT extends Record<any, any>> = {
4
+ step: StepFunction<StageT>;
5
+ run: () => Promise<Remove_<StageT>>;
6
+ };
7
+
8
+ type Remove_<T> = {
9
+ [K in keyof T as K extends `_${string}` ? never : K]: T[K];
10
+ };
11
+
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
+
14
+ export const createStep = (): Steps<{}>["step"] => {
15
+ const stepController = {
16
+ $milkioType: "step",
17
+ _steps: [] as Array<(stage: any) => Promise<any>>,
18
+ step(handler: (stage: any) => Promise<any>) {
19
+ stepController._steps.push(handler);
20
+ return stepController;
21
+ },
22
+ async run() {
23
+ let stage = {};
24
+ for (const step of stepController._steps) {
25
+ stage = { ...stage, ...(await step(stage)) };
26
+ }
27
+ let result: Record<any, any> = {};
28
+ for (const key in stage) {
29
+ const value = (stage as any)[key];
30
+ if (!key.startsWith("_")) result[key] = value;
31
+ }
32
+ return result;
33
+ },
34
+ };
35
+ return stepController.step as any as Steps<{}>["step"];
36
+ };
package/stream/index.ts CHANGED
File without changes
package/types/index.ts CHANGED
@@ -10,6 +10,8 @@ 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 : {};
14
+
13
15
  export type ExecuteId = string | "global";
14
16
 
15
17
  // DON'T TRY TO WRITE A MORE DETAILED TYPE FOR THIS TYPE
File without changes
@@ -0,0 +1,7 @@
1
+ export function headersToJSON(headers: Headers) {
2
+ const json: Record<string, string> = {};
3
+ for (const [key, value] of (headers as Headers).entries()) {
4
+ json[key] = value;
5
+ }
6
+ return json;
7
+ }
@@ -0,0 +1,26 @@
1
+ import type { Log, MilkioInit, MilkioRuntimeInit } from "..";
2
+ import { TSON } from "@southern-aurora/tson";
3
+
4
+ type CookbookEvent = {
5
+ type: "milkio@logger";
6
+ log: Log;
7
+ };
8
+
9
+ export const sendCookbookEvent = async (runtime: MilkioRuntimeInit<MilkioInit>, event: CookbookEvent) => {
10
+ try {
11
+ const response = await fetch(`http://localhost:${runtime.cookbook.cookbookPort}/$action`, {
12
+ method: "POST",
13
+ headers: {
14
+ "Content-Type": "application/json",
15
+ },
16
+ body: TSON.stringify(event),
17
+ });
18
+ if (!response.ok) {
19
+ console.log("[COOKBOOK]", await response.text());
20
+ console.log("[COOKBOOK]", "Is Cookbook closed? There is an abnormality in the communication with Cookbook.");
21
+ }
22
+ } catch (error) {
23
+ console.log("[COOKBOOK]", error);
24
+ console.log("[COOKBOOK]", "Is Cookbook closed? There is an abnormality in the communication with Cookbook.");
25
+ }
26
+ };
package/world/index.ts CHANGED
@@ -1,41 +1,53 @@
1
- import { __initCommander, __initListener, ExecuteId, type Logger, type Mixin, type GeneratedInit, $types, Execute, Ping } from "..";
2
- import { __initExecuter } from "../execute";
1
+ import { __initCommander, __initListener, __initExecuter, __initEventManager, type ExecuteId, type Logger, type Mixin, type GeneratedInit, type Execute, type Ping, type ContextCreatedHandler, LoggerSubmittingHandler, LoggerInsertingHandler } from "..";
3
2
  import { defineDefaultExecuteIdGenerator } from "../execute/execute-id-generator";
4
3
 
5
4
  export type MilkioInit = {
6
- port: {
7
- app: number;
8
- develop: number | "disabled";
5
+ port: number;
6
+ develop: boolean;
7
+ cookbook: {
8
+ cookbookPort: number;
9
+ };
10
+ cors?: {
11
+ corsAllowMethods?: string;
12
+ corsAllowHeaders?: string;
13
+ corsAllowOrigin?: string;
9
14
  };
10
- getRealIp?: (request: Request) => string;
11
- executeIdGenerator?: (request: Request) => string | Promise<string>;
12
- corsAllowMethods?: string;
13
- corsAllowHeaders?: string;
14
- corsAllowOrigin?: string;
15
15
  ignorePathLevel?: number;
16
+ realIp?: (request: Request) => string;
17
+ executeId?: (request: Request) => string | Promise<string>;
18
+ onLoggerSubmitting?: LoggerSubmittingHandler;
19
+ onLoggerInserting?: LoggerInsertingHandler;
16
20
  };
17
21
 
18
22
  export type MilkioRuntimeInit<T extends MilkioInit> = Mixin<
19
23
  T,
20
24
  {
21
- executeIdGenerator: (request: Request) => string | Promise<string>;
25
+ executeId: (request: Request) => string | Promise<string>;
22
26
  runtime: {
23
27
  request: Map<ExecuteId, { logger: Logger }>;
24
28
  };
29
+ on: Awaited<ReturnType<typeof __initEventManager>>["on"];
30
+ off: Awaited<ReturnType<typeof __initEventManager>>["off"];
31
+ emit: Awaited<ReturnType<typeof __initEventManager>>["emit"];
25
32
  }
26
33
  >;
27
34
 
28
- export const createWorld = async <CookbookOptions extends MilkioInit>(generated: GeneratedInit, options: CookbookOptions): Promise<MilkioWorld<CookbookOptions>> => {
29
- const executeIdGenerator = options.executeIdGenerator ?? defineDefaultExecuteIdGenerator();
35
+ export const createWorld = async <MilkioOptions extends MilkioInit>(generated: GeneratedInit, options: MilkioOptions): Promise<MilkioWorld<MilkioOptions>> => {
36
+ const executeId = options.executeId ?? defineDefaultExecuteIdGenerator();
30
37
 
31
38
  const runtime = {
32
39
  request: new Map(),
33
- } as MilkioRuntimeInit<CookbookOptions>["runtime"];
40
+ } as MilkioRuntimeInit<MilkioOptions>["runtime"];
41
+
42
+ const eventManager = __initEventManager();
34
43
 
35
- const _: MilkioRuntimeInit<CookbookOptions> = {
44
+ const _: MilkioRuntimeInit<MilkioOptions> = {
36
45
  ...options,
37
- executeIdGenerator,
46
+ executeId,
38
47
  runtime,
48
+ on: eventManager.on,
49
+ off: eventManager.off,
50
+ emit: eventManager.emit,
39
51
  };
40
52
 
41
53
  const executer = __initExecuter(generated, _);
@@ -45,21 +57,35 @@ export const createWorld = async <CookbookOptions extends MilkioInit>(generated:
45
57
  // Initialize the app
46
58
  const app = {
47
59
  _: _,
60
+ // event manager
61
+ on: eventManager.on,
62
+ off: eventManager.off,
63
+ emit: eventManager.emit,
64
+ // executer
48
65
  _executer: executer,
49
66
  execute: executer.execute,
50
67
  ping: executer.ping,
68
+ // commander
51
69
  commander,
70
+ // listener
52
71
  listener,
53
72
  };
54
73
 
55
- return app as MilkioWorld<CookbookOptions>;
74
+ return app as MilkioWorld<MilkioOptions>;
56
75
  };
57
76
 
58
- export type MilkioWorld<CookbookOptions extends MilkioInit = MilkioInit> = {
59
- _: MilkioRuntimeInit<CookbookOptions>;
60
- _executer: Awaited<ReturnType<typeof __initExecuter<MilkioRuntimeInit<CookbookOptions>>>>;
61
- commander: Awaited<ReturnType<typeof __initCommander<MilkioRuntimeInit<CookbookOptions>>>>;
62
- listener: Awaited<ReturnType<typeof __initListener<MilkioRuntimeInit<CookbookOptions>>>>;
77
+ export type MilkioWorld<MilkioOptions extends MilkioInit = MilkioInit> = {
78
+ _: MilkioRuntimeInit<MilkioOptions>;
79
+ // event manager
80
+ on: Awaited<ReturnType<typeof __initEventManager>>["on"];
81
+ off: Awaited<ReturnType<typeof __initEventManager>>["off"];
82
+ emit: Awaited<ReturnType<typeof __initEventManager>>["emit"];
83
+ // executer
84
+ _executer: Awaited<ReturnType<typeof __initExecuter<MilkioRuntimeInit<MilkioOptions>>>>;
63
85
  execute: Execute;
64
86
  ping: (options?: { timeout?: number }) => Promise<Ping>;
87
+ // commander
88
+ commander: Awaited<ReturnType<typeof __initCommander<MilkioRuntimeInit<MilkioOptions>>>>;
89
+ // listener
90
+ listener: Awaited<ReturnType<typeof __initListener<MilkioRuntimeInit<MilkioOptions>>>>;
65
91
  };
@@ -1,19 +0,0 @@
1
- import { type $context, type $meta } from "..";
2
-
3
- export const middleware = <MiddlewareInitT extends MiddlewareInit>(init: MiddlewareInitT): Middleware<MiddlewareInitT> => {
4
- const middleware = init as unknown as Middleware<MiddlewareInitT>;
5
- middleware.$milkioType = "middleware";
6
- if (middleware.meta === undefined) middleware.meta = {};
7
- return middleware;
8
- };
9
-
10
- export type MiddlewareInit = {
11
- meta?: $meta;
12
- handler: (context: $context, params: any) => Promise<unknown>;
13
- };
14
-
15
- export type Middleware<MiddlewareInitT extends MiddlewareInit> = {
16
- $milkioType: "middleware";
17
- meta: MiddlewareInitT["meta"] extends undefined ? {} : MiddlewareInitT["meta"];
18
- handler: MiddlewareInitT["handler"];
19
- };
package/test/index.ts DELETED
@@ -1,21 +0,0 @@
1
- import { type context, type meta } from "..";
2
-
3
- export const test = <TestInitT extends TestInit>(init: TestInitT): Test<TestInitT> => {
4
- const test = init as unknown as Test<TestInitT>;
5
- test.$milkioType = "test";
6
- if (test.name === undefined) test.name = {};
7
- return test;
8
- };
9
-
10
- export type TestInit = {
11
- name: meta;
12
- handler: (test: TestTools) => Promise<unknown>;
13
- };
14
-
15
- export type Test<TestInitT extends TestInit> = {
16
- $milkioType: "test";
17
- name: TestInitT["name"] extends undefined ? {} : TestInitT["name"];
18
- handler: TestInitT["handler"];
19
- };
20
-
21
- export type TestTools = {};