milkio 0.2.13 → 0.2.14

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.
@@ -2,10 +2,7 @@ import type { Meta } from "../../../src/meta";
2
2
  import type { Context } from "../../../src/context";
3
3
 
4
4
  export function defineApi<ApiT extends Api>(api: ApiT): ApiT & { isApi: true } {
5
- return {
6
- ...api,
7
- isApi: true,
8
- };
5
+ return { ...api, isApi: true };
9
6
  }
10
7
 
11
8
  export type Api = {
@@ -1,6 +1,6 @@
1
- import { loggerPushTags, loggerSubmit, useLogger, runtime, MiddlewareEvent } from "..";
1
+ import { loggerPushTags, loggerSubmit, useLogger, runtime, MiddlewareEvent, reject } from "..";
2
2
  import type { ExecuteId, MilkioApp, Mixin } from "..";
3
- import { hanldeCatchError } from "../utils/handle-catch-error";
3
+ import { handleCatchError } from "../utils/handle-catch-error";
4
4
  import { routerHandler } from "../../../src/router";
5
5
  import schema from "../../../generated/api-schema";
6
6
  import { failCode } from "../../../src/fail-code";
@@ -122,13 +122,13 @@ export function defineHttpHandler(app: MilkioApp, options: ExecuteHttpServerOpti
122
122
  // execute api
123
123
  // after request middleware
124
124
  await MiddlewareEvent.handle("afterHttpRequest", [headers, detail]);
125
+ const mode = headers.get("Accept") === "text/event-stream" ? "stream" : "execute";
125
126
 
126
127
  const rawbody = await request.request.text();
127
128
  loggerPushTags(executeId, {
128
129
  body: rawbody || "no body",
129
130
  });
130
131
 
131
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
132
132
  let params: any;
133
133
  if (rawbody === "") {
134
134
  params = undefined;
@@ -146,29 +146,94 @@ export function defineHttpHandler(app: MilkioApp, options: ExecuteHttpServerOpti
146
146
  params,
147
147
  });
148
148
 
149
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
150
- // @ts-ignore
151
- const result = await app._executeCoreToJson(pathstr, params, headers, {
152
- executeId,
153
- logger,
154
- detail,
155
- });
149
+ const resultsRaw = await app._call(mode, pathstr, params, headers, { executeId, logger, detail });
156
150
 
157
- // @ts-ignore
158
- // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression, @typescript-eslint/no-explicit-any
159
- if (!detail.response.body) detail.response.body = result;
151
+ let fn: any;
152
+ try {
153
+ fn = await schema.apiValidator.validate[pathstr]();
154
+ } catch (error) {
155
+ throw reject("BUSINESS_FAIL", "This is the new API, which takes effect after restarting the server or saving any changes. It will be fixed in the future.");
156
+ }
160
157
 
161
- // before response middleware
162
- const middlewareResponse = {
163
- value: detail.response.body,
164
- };
165
- await MiddlewareEvent.handle("beforeHttpResponse", [middlewareResponse, detail]);
158
+ if (mode === "execute") {
159
+ const result: string = await fn.validateResults(TSON.encode(resultsRaw.$result));
160
+ if (!detail.response.body) detail.response.body = result;
161
+
162
+ // before response middleware
163
+ const middlewareResponse = {
164
+ value: detail.response.body,
165
+ };
166
+ await MiddlewareEvent.handle("beforeHttpResponse", [middlewareResponse, detail]);
166
167
 
167
- if (!detail.response.headers["Content-Type"]) detail.response.headers["Content-Type"] = "application/json";
168
- if (!detail.response.headers["Cache-Control"]) detail.response.headers["Cache-Control"] = "no-cache";
169
- if (!detail.response.body) detail.response.body = middlewareResponse.value;
168
+ if (!detail.response.headers["Content-Type"]) detail.response.headers["Content-Type"] = "application/json";
169
+ if (!detail.response.headers["Cache-Control"]) detail.response.headers["Cache-Control"] = "no-cache";
170
+ if (!detail.response.body) detail.response.body = middlewareResponse.value;
171
+ }
172
+
173
+ if (mode === "stream") {
174
+ const generator = (resultsRaw as any).$generator as AsyncGenerator;
175
+ let stream: ReadableStream;
176
+ let control: ReadableStreamDirectController | ReadableStreamDefaultController;
177
+ // SSE has a default timeout, which helps prevent memory leaks, especially when you are writing code with a while (true) loop
178
+
179
+ if (global?.Bun) {
180
+ // bun
181
+ stream = new ReadableStream({
182
+ type: "direct",
183
+ async pull(controller: ReadableStreamDirectController) {
184
+ control = controller;
185
+ try {
186
+ for await (const value of generator) {
187
+ if (!request.request.signal.aborted) {
188
+ const result: string = JSON.stringify(TSON.encode(value));
189
+ controller.write(`data:${result}\n\n`);
190
+ } else {
191
+ generator.return(undefined);
192
+ controller.close();
193
+ }
194
+ }
195
+ } catch (error) {
196
+ controller.close();
197
+ throw error;
198
+ }
199
+ controller.close();
200
+ },
201
+ cancel() {
202
+ control.close();
203
+ },
204
+ } as unknown as UnderlyingByteSource);
205
+ } else {
206
+ // node.js or others
207
+ stream = new ReadableStream({
208
+ async pull(controller) {
209
+ control = controller;
210
+ try {
211
+ for await (const value of generator) {
212
+ if (!request.request.signal.aborted) {
213
+ const result: string = JSON.stringify(TSON.encode(value));
214
+ controller.enqueue(`data:${result}\n\n`);
215
+ } else {
216
+ generator.return(undefined);
217
+ controller.close();
218
+ }
219
+ }
220
+ } catch (error) {
221
+ controller.close();
222
+ throw error;
223
+ }
224
+ controller.close();
225
+ },
226
+ cancel() {
227
+ control.close();
228
+ },
229
+ });
230
+ }
231
+ detail.response.headers["Content-Type"] = "text/event-stream";
232
+ detail.response.headers["Cache-Control"] = "no-cache";
233
+ detail.response.body = stream;
234
+ }
170
235
  } catch (error) {
171
- const result = hanldeCatchError(error, executeId);
236
+ const result = handleCatchError(error, executeId);
172
237
  if (!response.headers["Content-Type"]) response.headers["Content-Type"] = "application/json";
173
238
  if (!response.headers["Cache-Control"]) response.headers["Cache-Control"] = "no-cache";
174
239
  if (!response.body) response.body = TSON.stringify(result);
@@ -177,7 +242,6 @@ export function defineHttpHandler(app: MilkioApp, options: ExecuteHttpServerOpti
177
242
  loggerPushTags(executeId, {
178
243
  status: response.status,
179
244
  responseHeaders: response.headers,
180
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
181
245
  body: response.body?.toString() ?? "",
182
246
  timeout: new Date().getTime(),
183
247
  });
@@ -0,0 +1,146 @@
1
+ import type { Context } from "../../../src/context";
2
+ import { failCode } from "../../../src/fail-code";
3
+ import schema from "../../../generated/api-schema";
4
+ import { type ExecuteId, type ExecuteOptions, type ExecuteResult, createUlid, useLogger, runtime, loggerPushTags, headerToPlainObject, loggerSubmit, type ExecuteCoreOptions, TSON, MiddlewareEvent, reject, _validate } from "..";
5
+ import { handleCatchError } from "../utils/handle-catch-error";
6
+
7
+ const apis = new Map<string, any>();
8
+
9
+ /**
10
+ * call is a low-level API that is useful only when you want to execute the Milkio Api without using execute or httpServer.
11
+ * It only does the most basic thing internally, which is calling the API. The external handling of functions such as making executeId, logging, middleware, etc., are all handled externally.
12
+ * Both execute and httpServer essentially call call.
13
+ */
14
+ export async function _call(
15
+ mode: "execute" | "stream",
16
+ path: string,
17
+ params: unknown | string,
18
+ headersInit: Record<string, string> | Headers = {},
19
+ options: ExecuteCoreOptions,
20
+ ): Promise<{ $type: "result"; $result: ExecuteResult<unknown> } | { $type: "stream"; $result: ExecuteResult<unknown>; $generator: AsyncGenerator }> {
21
+ const executeId = options.executeId as ExecuteId;
22
+
23
+ params = TSON.decode(params);
24
+
25
+ if (!(path in schema.apiMethodsSchema)) {
26
+ const result = {
27
+ executeId,
28
+ success: false,
29
+ fail: {
30
+ code: "NOT_FOUND",
31
+ message: failCode.NOT_FOUND(),
32
+ data: undefined,
33
+ },
34
+ } as ExecuteResult<unknown>;
35
+
36
+ return { $type: "result", $result: result };
37
+ }
38
+
39
+ let headers: Headers;
40
+ if (!(headersInit instanceof Headers)) {
41
+ // @ts-ignore
42
+ headers = new Headers({
43
+ ...headersInit,
44
+ });
45
+ } else {
46
+ headers = headersInit;
47
+ }
48
+
49
+ if (options?.onAfterHeaders) {
50
+ await options.onAfterHeaders(headers);
51
+ }
52
+
53
+ const context: Context = {
54
+ executeId,
55
+ path: path as string,
56
+ headers,
57
+ logger: options.logger,
58
+ detail: options?.detail ?? {},
59
+ };
60
+
61
+ let result: { value: unknown };
62
+ try {
63
+ // before execute middleware
64
+ await MiddlewareEvent.handle("beforeExecute", [context]);
65
+
66
+ let fn: any;
67
+ // check type
68
+ try {
69
+ // @ts-ignore
70
+ fn = await schema.apiValidator.validate[path]();
71
+ } catch (error) {
72
+ throw reject("BUSINESS_FAIL", "This is the new API, which takes effect after restarting the server or saving any changes. It will be fixed in the future.");
73
+ }
74
+ params = _validate(await fn.validateParams(params));
75
+
76
+ // execute api
77
+ let api: any;
78
+ if (apis.has(path as string)) api = apis.get(path as string);
79
+ else {
80
+ // @ts-ignore
81
+ api = schema.apiMethodsSchema[path as string]();
82
+ apis.set(path as string, api);
83
+ }
84
+ const apiModuleAwaited = await api.module;
85
+ const apiMethod = apiModuleAwaited.api.action;
86
+ // @ts-ignore
87
+ result = { value: await apiMethod(params, context) };
88
+ // after execute middleware
89
+ await MiddlewareEvent.handle("afterExecute", [context, result]);
90
+
91
+ if (mode === "execute" && !(result.value as AsyncGenerator)[Symbol.asyncIterator]) return { $type: "result", $result: { executeId, success: true, data: result.value } };
92
+ if (mode === "stream" && (result.value as AsyncGenerator)[Symbol.asyncIterator]) return { $type: "stream", $result: { executeId, success: true, data: "$" }, $generator: result.value as AsyncGenerator };
93
+ throw reject("BUSINESS_FAIL", `It looks like you used the wrong syntax, for this API you should use "client.${mode}(...)"`);
94
+ } catch (error: any) {
95
+ const errorResult = handleCatchError(error, executeId);
96
+
97
+ return { $type: "result", $result: errorResult };
98
+ }
99
+ }
100
+
101
+ export async function _execute<Path extends keyof (typeof schema)["apiMethodsTypeSchema"], Result extends Awaited<ReturnType<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>>>(
102
+ path: Path,
103
+ params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string,
104
+ headersInit: Record<string, string> | Headers = {},
105
+ options?: ExecuteOptions,
106
+ ): Promise<ExecuteResult<Result>> {
107
+ const executeId = (options?.executeId ?? createUlid()) as ExecuteId;
108
+ const logger = useLogger(executeId);
109
+ runtime.execute.executeIds.add(executeId);
110
+
111
+ loggerPushTags(executeId, {
112
+ from: "execute",
113
+ executeId,
114
+ params,
115
+ path,
116
+ });
117
+
118
+ const result = await _call("execute", path, params, headersInit, {
119
+ ...options,
120
+ executeId,
121
+ logger,
122
+ onAfterHeaders: (headers) => {
123
+ loggerPushTags(executeId, {
124
+ headers: headerToPlainObject(headers),
125
+ });
126
+ },
127
+ });
128
+
129
+ loggerPushTags(executeId, { result: result.$result });
130
+ await loggerSubmit(executeId);
131
+ runtime.execute.executeIds.delete(executeId);
132
+
133
+ return result.$result as ExecuteResult<Result>;
134
+ }
135
+
136
+ export async function _executeToJson<Path extends keyof (typeof schema)["apiMethodsTypeSchema"]>(path: Path, params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string, headersInit: Record<string, string> | Headers = {}, options?: ExecuteOptions): Promise<string> {
137
+ const resultsRaw = await _execute(path, params, headersInit, options);
138
+ let fn: any;
139
+ try {
140
+ fn = await schema.apiValidator.validate[path]();
141
+ } catch (error) {
142
+ throw reject("BUSINESS_FAIL", "This is the new API, which takes effect after restarting the server or saving any changes. It will be fixed in the future.");
143
+ }
144
+ const results = await fn.validateResults(TSON.encode(resultsRaw));
145
+ return results;
146
+ }
package/kernel/milkio.ts CHANGED
@@ -1,13 +1,9 @@
1
1
  import { type MiddlewareOptions, _middlewares, MiddlewareEvent } from "./middleware";
2
2
  import schema from "../../../generated/api-schema";
3
- import type { Context } from "../../../src/context";
4
- import { failCode } from "../../../src/fail-code";
5
- import type { MilkioContext } from "./context";
6
- import { headerToPlainObject } from "../utils/header-to-plain-object";
7
- import { type Mixin, type ExecuteId, type Fail, type FailEnumerates, loggerPushTags, loggerSubmit, runtime, TSON, type Logger, useLogger, reject } from "..";
8
- import { hanldeCatchError } from "../utils/handle-catch-error";
3
+ import { runtime } from "..";
9
4
  import { createUlid } from "../utils/create-ulid";
10
5
  import { _validate } from "./validate";
6
+ import { _execute, _call, _executeToJson } from "./execute";
11
7
 
12
8
  export type MilkioAppOptions = {
13
9
  /**
@@ -45,11 +41,10 @@ export async function createMilkioApp(MilkioAppOptions: MilkioAppOptions = {}) {
45
41
  }
46
42
 
47
43
  const MilkioApp = {
44
+ randParams: _randParams,
48
45
  execute: _execute,
49
46
  executeToJson: _executeToJson,
50
- _executeCore,
51
- _executeCoreToJson,
52
- randParams: _randParams,
47
+ _call,
53
48
  };
54
49
 
55
50
  if (MilkioAppOptions.bootstraps) {
@@ -86,202 +81,6 @@ export async function createMilkioApp(MilkioAppOptions: MilkioAppOptions = {}) {
86
81
  return MilkioApp;
87
82
  }
88
83
 
89
- async function _execute<Path extends keyof (typeof schema)["apiMethodsTypeSchema"], Result extends Awaited<ReturnType<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>>>(
90
- path: Path,
91
- params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string,
92
- headersInit: Record<string, string> | Headers = {},
93
- options?: ExecuteOptions,
94
- ): Promise<ExecuteResult<Result>> {
95
- const executeId = (options?.executeId ?? createUlid()) as ExecuteId;
96
- const logger = useLogger(executeId);
97
- runtime.execute.executeIds.add(executeId);
98
-
99
- loggerPushTags(executeId, {
100
- from: "execute",
101
- executeId,
102
- params,
103
- path,
104
- });
105
-
106
- const result: any = await _executeCore(path, params, headersInit, {
107
- ...options,
108
- executeId,
109
- logger,
110
- onAfterHeaders: (headers) => {
111
- loggerPushTags(executeId, {
112
- headers: headerToPlainObject(headers),
113
- });
114
- },
115
- });
116
-
117
- loggerPushTags(executeId, { result });
118
- await loggerSubmit(executeId);
119
- runtime.execute.executeIds.delete(executeId);
120
-
121
- return result;
122
- }
123
-
124
- /**
125
- * executeCore is a low-level API that is useful only when you want to execute the Milkio Api without using execute or httpServer.
126
- * It only does the most basic thing internally, which is calling the API. The external handling of functions such as making executeId, logging, middleware, etc., are all handled externally.
127
- * Both execute and httpServer essentially call executeCore.
128
- */
129
- async function _executeCore<Path extends keyof (typeof schema)["apiMethodsTypeSchema"], Result extends Awaited<ReturnType<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>>>(
130
- path: Path,
131
- params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string,
132
- headersInit: Record<string, string> | Headers = {},
133
- options: ExecuteCoreOptions,
134
- ): Promise<ExecuteResult<Result>> {
135
- const executeId = options.executeId as ExecuteId;
136
-
137
- params = TSON.decode(params);
138
-
139
- if (!(path in schema.apiMethodsSchema)) {
140
- const result = {
141
- executeId,
142
- success: false,
143
- fail: {
144
- code: "NOT_FOUND",
145
- message: failCode.NOT_FOUND(),
146
- data: undefined,
147
- },
148
- } satisfies ExecuteResult<Result>;
149
-
150
- return result;
151
- }
152
-
153
- let headers: Headers;
154
- if (!(headersInit instanceof Headers)) {
155
- // @ts-ignore
156
- headers = new Headers({
157
- ...headersInit,
158
- });
159
- } else {
160
- headers = headersInit;
161
- }
162
-
163
- if (options?.onAfterHeaders) {
164
- await options.onAfterHeaders(headers);
165
- }
166
-
167
- const context: Context = {
168
- executeId,
169
- path,
170
- headers,
171
- logger: options.logger,
172
- detail: options?.detail ?? {},
173
- };
174
-
175
- let result: { value: Result };
176
- try {
177
- // before execute middleware
178
- await MiddlewareEvent.handle("beforeExecute", [context]);
179
-
180
- let fn: any;
181
- // check type
182
- // @ts-ignore
183
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
184
- try {
185
- fn = await schema.apiValidator.validate[path]();
186
- } catch (error) {
187
- throw reject("BUSINESS_FAIL", "This is the new API, which takes effect after restarting the server or saving any changes. It will be fixed in the future.");
188
- }
189
-
190
- params = _validate(await fn.validateParams(params));
191
-
192
- // execute api
193
- let api: any;
194
- if (apis.has(path)) api = apis.get(path);
195
- else {
196
- // @ts-ignore
197
- api = schema.apiMethodsSchema[path]();
198
- apis.set(path, api);
199
- }
200
- const apiModuleAwaited = await api.module;
201
-
202
- const apiMethod = apiModuleAwaited.api.action;
203
-
204
- // @ts-ignore
205
- result = { value: await apiMethod(params, context) };
206
-
207
- // after execute middleware
208
- await MiddlewareEvent.handle("afterExecute", [context, result]);
209
- } catch (error: any) {
210
- const errorResult = hanldeCatchError(error, executeId);
211
-
212
- return errorResult;
213
- }
214
-
215
- return {
216
- executeId,
217
- success: true,
218
- data: result.value,
219
- };
220
- }
221
-
222
- async function _executeToJson<Path extends keyof (typeof schema)["apiMethodsTypeSchema"]>(path: Path, params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string, headersInit: Record<string, string> | Headers = {}, options?: ExecuteOptions): Promise<string> {
223
- const resultsRaw = await _execute(path, params, headersInit, options);
224
- let fn: any;
225
- try {
226
- fn = await schema.apiValidator.validate[path]();
227
- } catch (error) {
228
- throw reject("BUSINESS_FAIL", "This is the new API, which takes effect after restarting the server or saving any changes. It will be fixed in the future.");
229
- }
230
- const results = await fn.validateResults(TSON.encode(resultsRaw));
231
- return results;
232
- }
233
-
234
- async function _executeCoreToJson<Path extends keyof (typeof schema)["apiMethodsTypeSchema"]>(path: Path, params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string, headersInit: Record<string, string> | Headers = {}, options: ExecuteCoreOptions): Promise<string> {
235
- const resultsRaw = await _executeCore(path, params, headersInit, options);
236
- let fn: any;
237
- try {
238
- fn = await schema.apiValidator.validate[path]();
239
- } catch (error) {
240
- throw reject("BUSINESS_FAIL", "This is the new API, which takes effect after restarting the server or saving any changes. It will be fixed in the future.");
241
- }
242
- const results = await fn.validateResults(TSON.encode(resultsRaw));
243
- return results;
244
- }
245
-
246
84
  export async function _randParams<Path extends keyof (typeof schema)["apiMethodsTypeSchema"]>(path: Path): Promise<Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0]> {
247
85
  return await (await schema.apiValidator.validate[path]()).randParams();
248
86
  }
249
-
250
- const apis = new Map<string, any>();
251
-
252
- export type ExecuteResult<Result> = ExecuteResultSuccess<Result> | ExecuteResultFail;
253
-
254
- export type ExecuteResultSuccess<Result> = {
255
- executeId: ExecuteId;
256
- success: true;
257
- data: Result;
258
- };
259
-
260
- export type ExecuteResultFail<FailT extends Fail<keyof FailEnumerates> = Fail<keyof FailEnumerates>> = {
261
- executeId: ExecuteId;
262
- success: false;
263
- fail: FailT;
264
- };
265
-
266
- export type ExecuteOptions = {
267
- /**
268
- * The executeId of the request
269
- * executeId may be generated by the serverless provider, if not, a random string will be generated instead
270
- */
271
- executeId?: string;
272
- /**
273
- * Additional information about the request
274
- * These are usually only fully implemented when called by an Http server
275
- * During testing or when calling between microservices, some or all of the values may be undefined
276
- */
277
- detail?: MilkioContext["detail"];
278
- };
279
-
280
- export type ExecuteCoreOptions = Mixin<
281
- ExecuteOptions,
282
- {
283
- executeId: string;
284
- logger: Logger;
285
- onAfterHeaders?: (headers: Headers) => void | Promise<void>;
286
- }
287
- >;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "milkio",
3
3
  "type": "module",
4
4
  "module": "index.ts",
5
- "version": "0.2.13",
5
+ "version": "0.2.14",
6
6
  "peerDependencies": {
7
7
  "typescript": "^5.4.2"
8
8
  },
package/types.ts CHANGED
@@ -1,6 +1,12 @@
1
- import type { createMilkioApp } from ".";
1
+ import type { Logger, MilkioContext, createMilkioApp } from ".";
2
2
  import type { failCode } from "../../src/fail-code";
3
3
 
4
+ export type Override<P, S> = Omit<P, keyof S> & S;
5
+
6
+ export type Mixin<T, U> = U & Omit<T, keyof U>;
7
+
8
+ export type GeneratorGeneric<T> = T extends AsyncGenerator<infer I> ? I : never;
9
+
4
10
  export type MilkioApp = Awaited<ReturnType<typeof createMilkioApp>>;
5
11
 
6
12
  export type ExecuteId = string | "global";
@@ -33,10 +39,6 @@ export type CookbookItem = {
33
39
  }>;
34
40
  };
35
41
 
36
- export type Override<P, S> = Omit<P, keyof S> & S;
37
-
38
- export type Mixin<T, U> = U & Omit<T, keyof U>;
39
-
40
42
  export type MilkioConfig = {
41
43
  generate?: {
42
44
  significant?: Array<string>;
@@ -47,3 +49,42 @@ export type MilkioConfig = {
47
49
  commands?: Array<{ name?: string; script?: string; icon?: string }>;
48
50
  };
49
51
  };
52
+
53
+ export type ExecuteResult<Result> = ExecuteResultSuccess<Result> | ExecuteResultFail;
54
+
55
+ export type ExecuteResultSuccess<Result> = {
56
+ executeId: ExecuteId;
57
+ success: true;
58
+ data: Result;
59
+ };
60
+
61
+ export type ExecuteResultFail<FailT extends Fail<keyof FailEnumerates> = Fail<keyof FailEnumerates>> = {
62
+ executeId: ExecuteId;
63
+ success: false;
64
+ fail: FailT;
65
+ };
66
+
67
+ export type ExecuteOptions = {
68
+ /**
69
+ * The executeId of the request
70
+ * executeId may be generated by the serverless provider, if not, a random string will be generated instead
71
+ */
72
+ executeId?: string;
73
+ /**
74
+ * Additional information about the request
75
+ * These are usually only fully implemented when called by an Http server
76
+ * During testing or when calling between microservices, some or all of the values may be undefined
77
+ */
78
+ detail?: MilkioContext["detail"];
79
+ };
80
+
81
+ export type ExecuteCoreOptions = Mixin<
82
+ ExecuteOptions,
83
+ {
84
+ executeId: string;
85
+ logger: Logger;
86
+ onAfterHeaders?: (headers: Headers) => void | Promise<void>;
87
+ }
88
+ >;
89
+
90
+ export type MilkioEvent<Result> = Awaited<GeneratorGeneric<ExecuteResultSuccess<Result>["data"] extends { $type: any } ? ExecuteResultSuccess<Result>["data"]["$type"] : never>>;
@@ -3,7 +3,7 @@ import { useLogger, type ExecuteId, type ExecuteResult } from "..";
3
3
  import { configMilkio } from "../../../src/config/milkio";
4
4
 
5
5
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
- export function hanldeCatchError(error: any, executeId: ExecuteId): ExecuteResult<any> {
6
+ export function handleCatchError(error: any, executeId: ExecuteId): ExecuteResult<any> {
7
7
  const logger = useLogger(executeId);
8
8
 
9
9
  if (configMilkio.debug === true) {