milkio 1.0.0-alpha.64 → 1.0.0-alpha.69

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/context/index.ts CHANGED
@@ -10,6 +10,7 @@ export interface $context {
10
10
  http: ContextHttp<Record<any, any>>
11
11
  config: Readonly<Awaited<ReturnType<$types['configSchema']['get']>>>
12
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
13
14
  }
14
15
 
15
16
  export interface ContextHttp<ParamsParsed = any> {
@@ -24,4 +25,4 @@ export interface ContextHttp<ParamsParsed = any> {
24
25
  response: MilkioHttpResponse
25
26
  }
26
27
 
27
- export type ContextCreatedHandler = (context: $context) => Promise<void> | void
28
+ export type ContextCreatedHandler = (context: $context) => Promise<void> | void
package/execute/index.ts CHANGED
@@ -23,7 +23,7 @@ export function __initExecuter(generated: GeneratedInit, runtime: any) {
23
23
  paramsType: 'string'
24
24
  }
25
25
  ),
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 }> => {
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
27
  const executeId: string = options.createdExecuteId
28
28
  let headers: Headers
29
29
  if (!(options.headers instanceof Headers)) {
@@ -37,6 +37,9 @@ export function __initExecuter(generated: GeneratedInit, runtime: any) {
37
37
  }
38
38
  if (!('toJSON' in headers)) (headers as any).toJSON = () => headersToJSON(headers)
39
39
 
40
+ const finales: Array<any> = []
41
+ const onFinally = (handler: any) => finales.unshift(handler)
42
+
40
43
  let params: Record<any, unknown>
41
44
  if (options.paramsType === 'raw') {
42
45
  params = options.params
@@ -74,6 +77,7 @@ export function __initExecuter(generated: GeneratedInit, runtime: any) {
74
77
  executeId: options.createdExecuteId,
75
78
  config: runtime.runtime.config,
76
79
  call: (module: any, options: any) => __call(context, module, options),
80
+ onFinally: onFinally,
77
81
  _: runtime
78
82
  } as unknown as $context
79
83
  const results: Results<any> = { value: undefined }
@@ -116,7 +120,7 @@ export function __initExecuter(generated: GeneratedInit, runtime: any) {
116
120
 
117
121
  await runtime.emit('milkio:executeAfter', { executeId: options.createdExecuteId, logger: options.createdLogger, path: options.path, meta, context, results })
118
122
 
119
- return { executeId, headers, params, results, context, meta, type: module.$milkioType, emptyResult, resultsTypeSafety }
123
+ return { executeId, headers, params, results, context, meta, type: module.$milkioType, emptyResult, resultsTypeSafety, finales }
120
124
  }
121
125
 
122
126
  const __call = async (context: $context, module: { default: any }, params?: any): Promise<any> => {
package/flow/index.ts ADDED
@@ -0,0 +1,35 @@
1
+ export type MilkioFlow<T> = {
2
+ emit: (flow: T) => void;
3
+ next: () => Promise<T>;
4
+ }
5
+
6
+ export function createFlow<T extends unknown>(): MilkioFlow<T> {
7
+ const flows: Array<{
8
+ blank: boolean;
9
+ promise: Promise<T>;
10
+ resolve: (value?: T | PromiseLike<T>) => void;
11
+ reject: (reason?: any) => void;
12
+ }> = [];
13
+
14
+ return {
15
+ emit: (flow: T) => {
16
+ if (flows.at(-1)?.blank === true) {
17
+ flows.at(-1)!.resolve(flow);
18
+ return;
19
+ }
20
+ const resolvers = Promise.withResolvers<T>();
21
+ resolvers.resolve(flow);
22
+ flows.push({ ...resolvers, blank: false });
23
+ },
24
+ next: async () => {
25
+ if (flows.length === 0) {
26
+ const resolvers = Promise.withResolvers<T>();
27
+ flows.push({ ...resolvers, blank: true });
28
+ }
29
+ const flow = flows.at(0)!;
30
+ const result = await flow.promise;
31
+ flows.shift();
32
+ return result;
33
+ },
34
+ }
35
+ }
package/index.ts CHANGED
@@ -5,6 +5,7 @@ export * from './config'
5
5
  export * from './execute'
6
6
  export * from './bootstrap'
7
7
  export * from './event'
8
+ export * from './flow'
8
9
  export * from './handler'
9
10
  export * from './world'
10
11
  export * from './command'
@@ -15,4 +16,4 @@ export * from './context'
15
16
  export * from './meta'
16
17
  export * from './step'
17
18
  export * from './listener'
18
- export * from './exception'
19
+ export * from './exception'
package/listener/index.ts CHANGED
@@ -66,6 +66,8 @@ export function __initListener(generated: GeneratedInit, runtime: any, executer:
66
66
  'Content-Type': 'application/json',
67
67
  },
68
68
  }
69
+
70
+ let finales: Array<() => void | Promise<void>> = []
69
71
 
70
72
  try {
71
73
  const http = (await (async () => {
@@ -110,6 +112,7 @@ export function __initListener(generated: GeneratedInit, runtime: any, executer:
110
112
  params: http.params.string,
111
113
  paramsType: 'string',
112
114
  })
115
+ finales = executed.finales;
113
116
 
114
117
  if (response.body === '' && executed.results.value !== undefined) {
115
118
  if (executed.emptyResult) {
@@ -124,6 +127,14 @@ export function __initListener(generated: GeneratedInit, runtime: any, executer:
124
127
  }
125
128
 
126
129
  await runtime.emit('milkio:httpResponse', { executeId, logger, path: http.path.string as string, http, context: executed.context })
130
+
131
+ for (const handler of finales) {
132
+ try {
133
+ await handler()
134
+ } catch (error) {
135
+ logger.error('An error occurred inside onFinally.', error)
136
+ }
137
+ }
127
138
 
128
139
  runtime.runtime.request.delete(executeId)
129
140
  return new Response(response.body, response)
@@ -134,6 +145,18 @@ export function __initListener(generated: GeneratedInit, runtime: any, executer:
134
145
  if (routeSchema === undefined) throw reject('NOT_FOUND', { path: http.path.string as string })
135
146
  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.` })
136
147
 
148
+
149
+ const handleClose = async () => {
150
+ runtime.runtime.request.delete(executeId)
151
+ for (const handler of finales) {
152
+ try {
153
+ await handler()
154
+ } catch (error) {
155
+ logger.error('An error occurred inside onFinally.', error)
156
+ }
157
+ }
158
+ }
159
+
137
160
  const executed = await executer.__execute(routeSchema, {
138
161
  createdExecuteId: executeId,
139
162
  createdLogger: logger,
@@ -143,6 +166,7 @@ export function __initListener(generated: GeneratedInit, runtime: any, executer:
143
166
  params: http.params.string,
144
167
  paramsType: 'string',
145
168
  })
169
+ finales = executed.finales;
146
170
  let stream: ReadableStream
147
171
  let control: ReadableStreamDirectController | ReadableStreamDefaultController
148
172
 
@@ -161,6 +185,7 @@ export function __initListener(generated: GeneratedInit, runtime: any, executer:
161
185
  }
162
186
  else {
163
187
  executed.results.value.return(undefined)
188
+ await handleClose()
164
189
  controller.close()
165
190
  }
166
191
  }
@@ -172,9 +197,11 @@ export function __initListener(generated: GeneratedInit, runtime: any, executer:
172
197
  controller.write(`data:${JSON.stringify([TSON.encode(result), null])}\n\n`)
173
198
  }
174
199
  await new Promise(resolve => setTimeout(resolve, 0))
200
+ await handleClose()
175
201
  controller.close()
176
202
  },
177
- cancel() {
203
+ async cancel() {
204
+ await handleClose()
178
205
  control.close()
179
206
  },
180
207
  })
@@ -193,6 +220,7 @@ export function __initListener(generated: GeneratedInit, runtime: any, executer:
193
220
  }
194
221
  else {
195
222
  executed.results.value.return(undefined)
223
+ await handleClose()
196
224
  controller.close()
197
225
  }
198
226
  }
@@ -203,10 +231,12 @@ export function __initListener(generated: GeneratedInit, runtime: any, executer:
203
231
  result[exception.code] = exception.reject
204
232
  controller.enqueue(`data:${JSON.stringify([TSON.encode(result), null])}\n\n`)
205
233
  }
234
+ await handleClose()
206
235
  await new Promise(resolve => setTimeout(resolve, 0))
207
236
  controller.close()
208
237
  },
209
- cancel() {
238
+ async cancel() {
239
+ await handleClose()
210
240
  control.close()
211
241
  },
212
242
  })
@@ -218,7 +248,6 @@ export function __initListener(generated: GeneratedInit, runtime: any, executer:
218
248
 
219
249
  await runtime.emit('milkio:httpResponse', { executeId, logger, path: http.path.string as string, http, context: executed.context })
220
250
 
221
- runtime.runtime.request.delete(executeId)
222
251
  return new Response(response.body, response)
223
252
  }
224
253
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "milkio",
3
3
  "type": "module",
4
- "version": "1.0.0-alpha.64",
4
+ "version": "1.0.0-alpha.69",
5
5
  "module": "index.ts",
6
6
  "scripts": {},
7
7
  "peerDependencies": {
package/tsconfig.json CHANGED
@@ -3,6 +3,7 @@
3
3
  "composite": true,
4
4
  "target": "esnext",
5
5
  "jsx": "react-jsx",
6
+ "erasableSyntaxOnly":true,
6
7
  "lib": [
7
8
  "ESNext"
8
9
  ],