milkio 1.0.0-alpha.1 → 1.0.0-alpha.100

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.
Files changed (48) hide show
  1. package/.co.toml +2 -2
  2. package/LICENSE +1 -1
  3. package/README.md +1 -1
  4. package/action/index.ts +14 -14
  5. package/bootstrap/index.ts +7 -0
  6. package/command/index.ts +41 -37
  7. package/config/index.ts +33 -0
  8. package/context/index.ts +23 -15
  9. package/event/index.ts +48 -0
  10. package/exception/index.ts +31 -28
  11. package/execute/execute-id-generator.ts +5 -5
  12. package/execute/index.ts +99 -124
  13. package/flow/index.ts +70 -0
  14. package/handler/index.ts +7 -0
  15. package/index.ts +19 -11
  16. package/listener/index.ts +205 -119
  17. package/logger/index.ts +62 -51
  18. package/meta/index.ts +2 -2
  19. package/package.json +7 -7
  20. package/step/index.ts +36 -0
  21. package/stream/index.ts +14 -14
  22. package/tsconfig.json +19 -18
  23. package/type-safety/index.ts +16 -0
  24. package/types/index.ts +46 -51
  25. package/utils/create-id.ts +10 -2
  26. package/utils/headers-to-json.ts +7 -0
  27. package/utils/send-cookbook-event.ts +27 -0
  28. package/utils/trie.ts +54 -0
  29. package/world/index.ts +81 -44
  30. package/.publish/publish.json +0 -7
  31. package/.publish/releases/0.0.0.md +0 -0
  32. package/.publish/releases/0.1.0.md +0 -13
  33. package/.publish/releases/0.2.0.md +0 -33
  34. package/.publish/releases/0.3.0.md +0 -85
  35. package/.publish/releases/0.4.0.md +0 -35
  36. package/.publish/releases/0.5.0.md +0 -19
  37. package/.publish/releases/0.6.0.md +0 -41
  38. package/.publish/releases/0.8.0.md +0 -128
  39. package/.publish/releases-github/0.0.0.md +0 -0
  40. package/.publish/releases-github/0.1.0.md +0 -13
  41. package/.publish/releases-github/0.2.0.md +0 -33
  42. package/.publish/releases-github/0.3.0.md +0 -85
  43. package/.publish/releases-github/0.4.0.md +0 -35
  44. package/.publish/releases-github/0.5.0.md +0 -19
  45. package/.publish/releases-github/0.6.0.md +0 -41
  46. package/.publish/releases-github/0.8.0.md +0 -126
  47. package/middleware/index.ts +0 -19
  48. package/test/index.ts +0 -21
package/.co.toml CHANGED
@@ -1,2 +1,2 @@
1
- ["general"]
2
- includes = ["co:bun"]
1
+ [general]
2
+ includes = [ "co:bun" ]
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 southern-aurora
3
+ Copyright (c) 2023 akirarika
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,3 +1,3 @@
1
1
  # Milkio
2
2
 
3
- Document: [milkio.fun](https://milkio.fun)
3
+ Document: [milkio.fun](https://milkio.fun)
package/action/index.ts CHANGED
@@ -1,19 +1,19 @@
1
- import { type $context, type $meta } from "..";
1
+ import type { $context, $meta } from '..'
2
2
 
3
- export const action = <ActionInitT extends ActionInit>(init: ActionInitT): Action<ActionInitT> => {
4
- const action = init as unknown as Action<ActionInitT>;
5
- action.$milkioType = "action";
6
- if (action.meta === undefined) action.meta = {};
7
- return action;
8
- };
3
+ export function action<ActionInitT extends ActionInit>(init: ActionInitT): Action<ActionInitT> {
4
+ const action = init as unknown as Action<ActionInitT>
5
+ action.$milkioType = 'action'
6
+ if (action.meta === undefined) action.meta = {}
7
+ return action
8
+ }
9
9
 
10
10
  export type ActionInit = {
11
- meta?: $meta;
12
- handler: (context: $context, params: any) => Promise<unknown>;
13
- };
11
+ meta?: $meta
12
+ handler: (context: $context, params: any) => Promise<unknown>
13
+ }
14
14
 
15
15
  export type Action<ActionInitT extends ActionInit> = {
16
- $milkioType: "action";
17
- meta: ActionInitT["meta"] extends undefined ? {} : ActionInitT["meta"];
18
- handler: ActionInitT["handler"];
19
- };
16
+ $milkioType: 'action'
17
+ meta: ActionInitT['meta'] extends undefined ? {} : ActionInitT['meta']
18
+ handler: ActionInitT['handler']
19
+ }
@@ -0,0 +1,7 @@
1
+ import type { MilkioWorld } from '..'
2
+
3
+ export function bootstrap<BootstrapInitT extends BootstrapInit>(init: BootstrapInitT): BootstrapInitT {
4
+ return init
5
+ }
6
+
7
+ export type BootstrapInit = (world: MilkioWorld) => Promise<void> | void
package/command/index.ts CHANGED
@@ -1,53 +1,57 @@
1
- import { type MilkioRuntimeInit, type MilkioInit, type GeneratedInit } from "..";
1
+ import type { GeneratedInit } from '..'
2
2
 
3
- export const command = <CommandInitT extends CommandInit>(init: CommandInitT): Command<CommandInitT> => {
4
- const command = init as unknown as Command<CommandInitT>;
5
- command.$milkioType = "command";
6
- return command;
7
- };
3
+ export function command<CommandInitT extends CommandInit>(init: CommandInitT): Command<CommandInitT> {
4
+ const command = init as unknown as Command<CommandInitT>
5
+ command.$milkioType = 'command'
6
+ return command
7
+ }
8
8
 
9
- export type CommandInit = {
10
- handler: (commands: Array<string>, options: Record<string, string>) => Promise<unknown>;
11
- };
9
+ export interface CommandInit {
10
+ handler: (commands: Array<string>, options: Record<string, string>) => Promise<unknown>
11
+ }
12
12
 
13
- export type Command<CommandInitT extends CommandInit> = {
14
- $milkioType: "command";
15
- handler: CommandInitT["handler"];
16
- };
13
+ export interface Command<CommandInitT extends CommandInit> {
14
+ $milkioType: 'command'
15
+ handler: CommandInitT['handler']
16
+ }
17
17
 
18
- export const __initCommander = <MilkioRuntime extends MilkioRuntimeInit<MilkioInit> = MilkioRuntimeInit<MilkioInit>>(generated: GeneratedInit, runtime: MilkioRuntime) => {
18
+ export function __initCommander(generated: GeneratedInit, runtime: any) {
19
19
  const commander = async (argv: Array<string>, options?: { onNotFound?: () => any }) => {
20
20
  const params = {
21
- path: "index",
21
+ path: 'index',
22
22
  commands: [] as Array<string>,
23
23
  options: {} as Record<string, string | true>,
24
- };
24
+ }
25
25
  for (const v of argv.slice(3)) {
26
- if (v.startsWith("--") && v.includes("=")) {
27
- const vSplited = v.split("=");
28
- params.options[vSplited[0].slice(2)] = vSplited.slice(1, vSplited.length).join("=");
29
- } else if (v.startsWith("--")) {
30
- params.options[v.slice(2)] = "1";
31
- } else if (v.startsWith("-") && v.includes("=")) {
32
- const vSplited = v.split("=");
33
- params.options[vSplited[0].slice(1)] = vSplited.slice(1, vSplited.length).join("=");
34
- } else if (v.startsWith("-")) {
35
- params.options[v.slice(1)] = "1";
36
- } else {
37
- params.commands.push(v);
26
+ if (v.startsWith('--') && v.includes('=')) {
27
+ const vSplited = v.split('=')
28
+ params.options[vSplited[0].slice(2)] = vSplited.slice(1, vSplited.length).join('=')
29
+ }
30
+ else if (v.startsWith('--')) {
31
+ params.options[v.slice(2)] = '1'
32
+ }
33
+ else if (v.startsWith('-') && v.includes('=')) {
34
+ const vSplited = v.split('=')
35
+ params.options[vSplited[0].slice(1)] = vSplited.slice(1, vSplited.length).join('=')
36
+ }
37
+ else if (v.startsWith('-')) {
38
+ params.options[v.slice(1)] = '1'
39
+ }
40
+ else {
41
+ params.commands.push(v)
38
42
  }
39
43
  }
40
- if (argv.length === 2) params.path = `index`;
41
- else params.path = `${argv[2] ?? "index"}`;
44
+ if (argv.length === 2) params.path = `index`
45
+ else params.path = `${argv[2] ?? 'index'}`
42
46
 
43
47
  if (!(params.path in generated.commandSchema.commands)) {
44
- if (options?.onNotFound) return await options.onNotFound();
45
- console.log(`\x1B[44m UwU \x1B[0m \x1B[2mCommand not found:\x1B[0m \x1B[32m${params.path}\x1B[0m`);
46
- return undefined;
48
+ if (options?.onNotFound) return await options.onNotFound()
49
+ console.log(`\x1B[44m UwU \x1B[0m \x1B[2mCommand not found:\x1B[0m \x1B[32m${params.path}\x1B[0m`)
50
+ return undefined
47
51
  }
48
52
 
49
- return await generated.commandSchema.commands[params.path].module.handler(params.commands, params.options);
50
- };
53
+ return await generated.commandSchema.commands[params.path].module.handler(params.commands, params.options)
54
+ }
51
55
 
52
- return commander;
53
- };
56
+ return commander
57
+ }
@@ -0,0 +1,33 @@
1
+ export function config<ConfigT extends Config>(config: ConfigT): ConfigT {
2
+ return config
3
+ }
4
+
5
+ export type Config = (mode: string) => Promise<Record<string, unknown>> | Record<string, unknown>
6
+
7
+ export interface ConfigEnvironments<T extends Config> {
8
+ [key: string]: (env: Record<string, string>) => Partial<Awaited<ReturnType<T>>> | Promise<Partial<Awaited<ReturnType<T>>>>
9
+ }
10
+
11
+ export function envToString(value: string | number | undefined, defaultValue: string) {
12
+ if (value === undefined) return defaultValue
13
+
14
+ return `${value}`
15
+ }
16
+
17
+ export function envToNumber(value: string | undefined, defaultValue: number) {
18
+ if (value === undefined) return defaultValue
19
+
20
+ return Number.parseInt(value, 10)
21
+ }
22
+
23
+ export function envToBoolean(value: string | number | undefined, defaultValue: boolean) {
24
+ if (value === 'true') return true
25
+
26
+ if (value === 'false') return false
27
+
28
+ if (value === '') return false
29
+
30
+ if (undefined === value) return defaultValue
31
+
32
+ return Boolean(value)
33
+ }
package/context/index.ts CHANGED
@@ -1,20 +1,28 @@
1
- import { type MilkioHttpRequest, type MilkioHttpResponse, type $types, type Logger } from "..";
1
+ import type { MilkioHttpRequest, MilkioHttpResponse, $types, Logger, Action, MilkioRuntimeInit, MilkioInit } from '..'
2
2
 
3
3
  export interface $context {
4
- executeId: string;
5
- path: string;
6
- logger: Logger;
7
- http?: ContextHttp<Record<any, any>>;
4
+ _: MilkioRuntimeInit<MilkioInit>
5
+ develop: boolean
6
+ executeId: string
7
+ emit: MilkioRuntimeInit<MilkioInit>['emit']
8
+ path: string
9
+ logger: Logger
10
+ http: ContextHttp<Record<any, any>>
11
+ config: Readonly<Awaited<ReturnType<$types['configSchema']['get']>>>
12
+ call: <Module extends Promise<{ default: Action<any> }>>(module: Module, params: Parameters<Awaited<Module>['default']['handler']>[1]) => Promise<ReturnType<Awaited<Module>['default']['handler']>>
13
+ onFinally: (handler: () => void | Promise<void>) => void
8
14
  }
9
15
 
10
- export type ContextHttp<ParamsParsed> = {
11
- url: URL;
12
- ip: string;
13
- path: { string: keyof $types["generated"]["routeSchema"]["$types"]; array: Array<string> };
16
+ export interface ContextHttp<ParamsParsed = any> {
17
+ url: URL
18
+ ip: string
19
+ path: { string: keyof $types['generated']['routeSchema'], array: Array<string> }
14
20
  params: {
15
- string: string;
16
- parsed: ParamsParsed;
17
- };
18
- request: MilkioHttpRequest;
19
- response: MilkioHttpResponse;
20
- };
21
+ string: string
22
+ parsed: ParamsParsed
23
+ }
24
+ request: MilkioHttpRequest
25
+ response: MilkioHttpResponse
26
+ }
27
+
28
+ export type ContextCreatedHandler = (context: $context) => Promise<void> | void
package/event/index.ts ADDED
@@ -0,0 +1,48 @@
1
+ import type { $context, ContextHttp, Results, Logger, $meta } from '..'
2
+
3
+
4
+ export interface $events {
5
+ 'milkio:httpRequest': { executeId: string, path: string, logger: Logger, http: ContextHttp<Record<string, any>> }
6
+ 'milkio:httpResponse': { executeId: string, path: string, logger: Logger, http: ContextHttp<Record<string, any>>, context: $context }
7
+ 'milkio:httpNotFound': { executeId: string, path: string, logger: Logger, http: ContextHttp<Record<string, any>> }
8
+ 'milkio:executeBefore': { executeId: string, path: string, logger: Logger, meta: $meta, context: $context }
9
+ 'milkio:executeAfter': { executeId: string, path: string, logger: Logger, meta: $meta, context: $context, results: Results<any> }
10
+ }
11
+
12
+ export function __initEventManager() {
13
+ const handlers = new Map<(event: any) => void, string>()
14
+ const indexed = new Map<string, Set<(event: any) => void>>()
15
+
16
+ const eventManager = {
17
+ on: <Key extends keyof $events, Handler extends (event: $events[Key]) => void>(key: Key, handler: Handler) => {
18
+ handlers.set(handler, key as string)
19
+ if (indexed.has(key as string) === false) {
20
+ indexed.set(key as string, new Set())
21
+ }
22
+ const set = indexed.get(key as string)!
23
+ set.add(handler)
24
+ handlers.set(handler, key as string)
25
+
26
+ return () => {
27
+ handlers.delete(handler)
28
+ set.delete(handler)
29
+ }
30
+ },
31
+ off: <Key extends keyof $events, Handler extends (event: $events[Key]) => void>(key: Key, handler: Handler) => {
32
+ const set = indexed.get(key as string)
33
+ if (!set) return
34
+ handlers.delete(handler)
35
+ set.delete(handler)
36
+ },
37
+ emit: async <Key extends keyof $events, Value extends $events[Key]>(key: Key, value: Value): Promise<void> => {
38
+ const h = indexed.get(key as string)
39
+ if (h) {
40
+ for (const handler of h) {
41
+ await handler(value)
42
+ }
43
+ }
44
+ },
45
+ }
46
+
47
+ return eventManager
48
+ }
@@ -1,45 +1,48 @@
1
- import { TSON } from "@southern-aurora/tson";
2
- import { type MilkioResponseReject, type Logger } from "..";
1
+ import { TSON } from '@southern-aurora/tson'
2
+ import type { MilkioResponseReject, Logger } from '..'
3
3
 
4
4
  export interface $rejectCode {
5
- FAIL: string;
6
- REQUEST_FAIL: any;
7
- NOT_DEVELOP_MODE: string;
8
- REQUEST_TIMEOUT: { timeout: number; message: string };
9
- NOT_FOUND: { path: string };
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
- UNACCEPTABLE: { expected: string; message: string };
13
- PARAMS_TYPE_NOT_SUPPORTED: { expected: string };
14
- INTERNAL_SERVER_ERROR: undefined;
5
+ FAIL: string
6
+ REQUEST_FAIL: any
7
+ NOT_DEVELOP_MODE: string
8
+ REQUEST_TIMEOUT: { timeout: number, message: string }
9
+ NOT_FOUND: { path: string }
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
+ UNACCEPTABLE: { expected: string, message: string }
13
+ PARAMS_TYPE_NOT_SUPPORTED: { expected: string }
14
+ RESULTS_TYPE_NOT_SUPPORTED: { expected: string }
15
+ INTERNAL_SERVER_ERROR: undefined
15
16
  }
16
17
 
17
18
  export function reject<Code extends keyof $rejectCode, RejectData extends $rejectCode[Code]>(code: Code, data: RejectData): MilkioRejectError<Code, RejectData> {
18
- const error = { $milkioReject: true, code: code, data: data } as MilkioRejectError<Code, RejectData>;
19
- Error.captureStackTrace(error);
20
- return error;
19
+ const error = { $milkioReject: true, code, data } as MilkioRejectError<Code, RejectData>
20
+ Error.captureStackTrace(error)
21
+ return error
21
22
  }
22
23
 
23
- export type MilkioRejectError<Code extends keyof $rejectCode = keyof $rejectCode, RejectData extends $rejectCode[Code] = $rejectCode[Code]> = { code: Code; data: RejectData; stack: string; $milkioReject: true };
24
+ export type MilkioRejectError<Code extends keyof $rejectCode = keyof $rejectCode, RejectData extends $rejectCode[Code] = $rejectCode[Code]> = { code: Code, data: RejectData, stack: string, $milkioReject: true }
24
25
 
25
26
  export function exceptionHandler(executeId: string, logger: Logger, error: MilkioRejectError<any, any> | any): MilkioResponseReject {
26
- const name = error?.code ?? error?.name ?? error?.constructor?.name ?? "Unnamed Exception";
27
+ const name = error?.code ?? error?.name ?? error?.constructor?.name ?? 'Unnamed Exception'
27
28
 
28
- if (error?.$milkioReject === true && error?.code === "NOT_FOUND") {
29
- logger.info(name, error?.data?.path ?? "Unknown path");
30
- } else {
29
+ if (error?.$milkioReject === true && error?.code === 'NOT_FOUND') {
30
+ logger.info(name, error?.data?.path ?? 'Unknown path')
31
+ }
32
+ else {
31
33
  try {
32
- const stack = error?.$milkioReject ? (error?.stack ?? "").split("\n").slice(2).join("\n") : error?.stack ?? "";
33
- logger.error(name, `\n${TSON.stringify(error?.data)}`, `\n${stack}\n`);
34
- } catch (_) {
35
- logger.error(name, `\n${error?.toString()}`, `\n${error?.stack}\n`);
34
+ const stack = error?.$milkioReject ? (error?.stack ?? '').split('\n').slice(2).join('\n') : error?.stack ?? ''
35
+ logger.error(name, `\n${TSON.stringify(error?.data)}`, `\n${stack}\n`)
36
+ }
37
+ catch (_) {
38
+ logger.error(name, `\n${error?.toString()}`, `\n${error?.stack}\n`)
36
39
  }
37
40
  }
38
41
 
39
- let result: MilkioResponseReject;
42
+ let result: MilkioResponseReject
40
43
 
41
- if (error?.$milkioReject === true) result = { success: false, code: error.code, reject: error.data, executeId };
42
- else result = { success: false, code: "INTERNAL_SERVER_ERROR", reject: undefined, executeId };
44
+ if (error?.$milkioReject === true) result = { success: false, code: error.code, reject: error.data, executeId }
45
+ else result = { success: false, code: 'INTERNAL_SERVER_ERROR', reject: undefined, executeId }
43
46
 
44
- return result;
47
+ return result
45
48
  }
@@ -1,7 +1,7 @@
1
- import { createId } from "../utils/create-id";
1
+ import { __createId } from '../utils/create-id'
2
2
 
3
- export type ExecuteIdGenerator = (request?: Request) => string | Promise<string>;
3
+ export type ExecuteIdGenerator = (request?: Request) => string | Promise<string>
4
4
 
5
- export const defineDefaultExecuteIdGenerator = () => {
6
- return createId;
7
- };
5
+ export function defineDefaultExecuteIdGenerator() {
6
+ return __createId
7
+ }
package/execute/index.ts CHANGED
@@ -1,160 +1,135 @@
1
- import { type IValidation } from "typia";
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 } from "..";
5
-
6
- export type MilkioHttpRequest = {
7
- request: Request;
8
- };
9
-
10
- export const __initExecuter = <MilkioRuntime extends MilkioRuntimeInit<MilkioRuntimeInit<MilkioInit>> = MilkioRuntimeInit<MilkioInit>>(generated: GeneratedInit, runtime: MilkioRuntime) => {
11
- const __call = async (
1
+ import type { IValidation } from 'typia'
2
+ import { TSON } from '@southern-aurora/tson'
3
+ import { reject } from '..'
4
+ import type { $context, $meta, Logger, Results, GeneratedInit } from '..'
5
+ import { headersToJSON } from '../utils/headers-to-json'
6
+
7
+ export function __initExecuter(generated: GeneratedInit, runtime: any) {
8
+ const __execute = async (
12
9
  routeSchema: any,
13
10
  options: {
14
- createdExecuteId: string;
15
- createdLogger: Logger;
16
- path: string;
17
- headers: Record<string, string> | Headers;
18
- mixinContext: Record<any, any> | undefined;
11
+ createdExecuteId: string
12
+ createdLogger: Logger
13
+ path: string
14
+ headers: Record<string, string> | Headers
15
+ mixinContext: Record<any, any> | undefined
19
16
  } & (
20
17
  | {
21
- params: Record<any, any>;
22
- paramsType: "raw";
23
- }
18
+ params: Record<any, any>
19
+ paramsType: 'raw'
20
+ }
24
21
  | {
25
- params: string;
26
- paramsType: "string";
27
- }
22
+ params: string
23
+ paramsType: 'string'
24
+ }
28
25
  ),
29
- ): Promise<{ executeId: string; headers: Headers; params: Record<any, unknown>; results: Results<any>; context: $context; meta: Readonly<$meta>; type: "action" | "stream" }> => {
30
- const executeId = options.createdExecuteId;
31
- let headers: Headers;
26
+ ): Promise<{ executeId: string, headers: Headers, params: Record<any, unknown>, results: Results<any>, context: $context, meta: Readonly<$meta>, type: 'action' | 'stream', emptyResult: boolean, resultsTypeSafety: boolean, finales: Array<() => void | Promise<void>> }> => {
27
+ const executeId: string = options.createdExecuteId
28
+ let headers: Headers
32
29
  if (!(options.headers instanceof Headers)) {
33
30
  // @ts-ignore
34
31
  headers = new Headers({
35
32
  ...options.headers,
36
- });
37
- } else {
38
- headers = options.headers;
33
+ })
39
34
  }
40
- let params: Record<any, unknown>;
41
- 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.");
42
- if (options.paramsType === "raw") {
43
- params = options.params;
44
- if (typeof params === "undefined") params = {};
45
- } else {
46
- if (options.params === "") params = {};
35
+ else {
36
+ headers = options.headers
37
+ }
38
+ if (!('toJSON' in headers)) (headers as any).toJSON = () => headersToJSON(headers)
39
+
40
+ const finales: Array<any> = []
41
+ const onFinally = (handler: any) => finales.unshift(handler)
42
+
43
+ let params: Record<any, unknown>
44
+ if (options.paramsType === 'raw') {
45
+ params = options.params
46
+ if (typeof params === 'undefined') params = {}
47
+ }
48
+ else {
49
+ if (options.params === '') {
50
+ params = {}
51
+ }
47
52
  else {
48
53
  try {
49
- params = TSON.parse(options.params);
50
- } catch (error) {
51
- throw reject("PARAMS_TYPE_NOT_SUPPORTED", { expected: "json" });
54
+ params = TSON.parse(options.params)
52
55
  }
53
- if (typeof params === "undefined") params = {};
56
+ catch (error) {
57
+ throw reject('PARAMS_TYPE_NOT_SUPPORTED', { expected: 'json' })
58
+ }
59
+ if (typeof params === 'undefined') params = {}
54
60
  }
55
61
  }
56
- if (typeof params !== "object" || Array.isArray(params)) throw reject("PARAMS_TYPE_NOT_SUPPORTED", { expected: "json" });
57
- if ("$milkioGenerateParams" in params && params.$milkioGenerateParams === "enable") {
58
- delete params.$milkioGenerateParams;
59
- let paramsRand = routeSchema.randomParams();
60
- if (paramsRand === undefined || paramsRand === null) paramsRand = {};
61
- params = { ...paramsRand, ...params };
62
- options.createdLogger.debug("[milkio]", "🪄 generate params:", options.path, TSON.stringify(params));
62
+ if (typeof params !== 'object' || Array.isArray(params)) throw reject('PARAMS_TYPE_NOT_SUPPORTED', { expected: 'json' })
63
+ if ('$milkioGenerateParams' in params && params.$milkioGenerateParams === 'enable') {
64
+ if (!runtime.develop) throw reject('NOT_DEVELOP_MODE', 'This feature must be in cookbook to use.')
65
+ delete params.$milkioGenerateParams
66
+ let paramsRand = routeSchema.randomParams()
67
+ if (paramsRand === undefined || paramsRand === null) paramsRand = {}
68
+ params = { ...paramsRand, ...params }
63
69
  }
64
- if (options.mixinContext?.http?.params?.string) options.mixinContext.http.params.parsed = params; // listen でパースしたパラメータを渡す
70
+ if (options.mixinContext?.http?.params?.string) options.mixinContext.http.params.parsed = params // listen でパースしたパラメータを渡す
65
71
  const context = {
66
72
  ...(options.mixinContext ? options.mixinContext : {}),
73
+ develop: runtime.develop,
67
74
  path: options.path,
68
75
  logger: options.createdLogger,
76
+ emit: runtime.emit,
69
77
  executeId: options.createdExecuteId,
70
- } as unknown as $context;
71
-
72
- const results: Results<unknown> = { value: undefined };
73
-
74
- const module = await routeSchema.module();
75
- let meta = (module.meta ? module.meta : {}) as unknown as Readonly<$meta>;
76
-
77
- if (!meta.typeSafety || meta.typeSafety.includes("params")) {
78
- const validation = routeSchema.validateParams(params) as IValidation<any>;
79
- 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.` });
78
+ config: runtime.runtime.config,
79
+ call: (module: any, options: any) => __call(context, module, options),
80
+ onFinally: onFinally,
81
+ _: runtime
82
+ } as unknown as $context
83
+ const results: Results<any> = { value: undefined }
84
+
85
+ if (runtime.develop) {
86
+ options.createdLogger.request(`headers - ${TSON.stringify(headers.toJSON())}`, `\nparams - ${TSON.stringify(params)}`)
80
87
  }
81
88
 
82
- results.value = await module.default.handler(context, params);
89
+ const module = routeSchema.module
90
+ const meta = (module.default?.meta ? module.default?.meta : {}) as unknown as Readonly<$meta>
83
91
 
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.` });
92
+ if (meta.typeSafety === undefined || meta.typeSafety === true) {
93
+ const validation = routeSchema.validateParams(params) as IValidation<any>
94
+ 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.` })
87
95
  }
88
96
 
89
- return { executeId, headers, params, results, context, meta, type: module.$milkioType };
90
- };
91
-
92
- const execute = async (path: string, options?: ExecuteOptions): Promise<any> => {
93
- if (!options) options = {};
94
- const executeId = createId();
95
- const logger = createLogger(runtime, executeId);
96
- runtime.runtime.request.set(executeId, { logger: logger });
97
+ await runtime.emit('milkio:executeBefore', { executeId: options.createdExecuteId, logger: options.createdLogger, path: options.path, meta, context })
97
98
 
98
- try {
99
- const routeSchema = generated.routeSchema.routes.get(path);
100
- if (routeSchema === undefined) throw reject("NOT_FOUND", { path: path });
99
+ results.value = await module.default.handler(context, params)
101
100
 
102
- const executed = await __call(routeSchema, {
103
- createdExecuteId: executeId,
104
- createdLogger: logger,
105
- path: path,
106
- headers: options.headers ?? {},
107
- mixinContext: {},
108
- params: options.params ?? {},
109
- paramsType: "raw",
110
- });
101
+ let resultsTypeSafety = false
102
+ if (results?.value?.$milkioType === 'type-safety') {
103
+ resultsTypeSafety = true
104
+ const validation = routeSchema.validateResults(results.value.value) as IValidation<any>
105
+ 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.` })
106
+ results.value = results.value.value
107
+ }
111
108
 
112
- if (routeSchema.type === "stream") {
113
- // stream
114
- return [
115
- undefined,
116
- (async function* () {
117
- try {
118
- for await (const result of executed.results.value) {
119
- yield [null, result];
120
- }
121
- return undefined;
122
- } catch (error) {
123
- const reject = exceptionHandler(executeId, logger, error);
124
- const result: any = {};
125
- result[reject.code] = reject.reject;
109
+ let emptyResult = false
110
+ if (results.value === undefined || results.value === null || results.value === '') {
111
+ emptyResult = true
112
+ results.value = {}
113
+ }
114
+ else if (Array.isArray(results.value)) {
115
+ throw reject('FAIL', 'The return type of the handler must be an object, which is currently an array.')
116
+ }
117
+ else if (typeof results.value !== 'object') {
118
+ throw reject('FAIL', 'The return type of the handler must be an object, which is currently a primitive type.')
119
+ }
126
120
 
127
- yield [result, null];
128
- return undefined;
129
- }
130
- })(),
131
- { executeId: executeId },
132
- ];
133
- } else {
134
- // action
135
- return [null, executed.results.value, { executeId: executeId }];
136
- }
137
- } catch (error) {
138
- const reject = exceptionHandler(executeId, logger, error);
139
- const result: any = {};
140
- result[reject.code] = reject.reject;
121
+ await runtime.emit('milkio:executeAfter', { executeId: options.createdExecuteId, logger: options.createdLogger, path: options.path, meta, context, results })
141
122
 
142
- return [result, null, { executeId: executeId }];
143
- }
144
- };
123
+ return { executeId, headers, params, results, context, meta, type: module.$milkioType, emptyResult, resultsTypeSafety, finales }
124
+ }
145
125
 
146
- const ping = async (): Promise<Ping> => [
147
- null,
148
- {
149
- connect: true,
150
- delay: 0,
151
- serverTimestamp: Date.now(),
152
- },
153
- ];
126
+ const __call = async (context: $context, module: { default: any }, params?: any): Promise<any> => {
127
+ const moduleAwaited = await module
128
+ return await moduleAwaited.default.handler(context, params)
129
+ }
154
130
 
155
131
  return {
156
132
  __call,
157
- execute,
158
- ping,
159
- };
160
- };
133
+ __execute,
134
+ }
135
+ }