@milkio/astra 1.0.0-alpha.97 → 1.0.0-alpha.99

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 (2) hide show
  1. package/index.ts +149 -151
  2. package/package.json +1 -1
package/index.ts CHANGED
@@ -1,262 +1,260 @@
1
- import { join, dirname } from 'node:path'
2
- import { fileURLToPath } from 'node:url'
3
- import { existsSync } from 'node:fs'
4
- import { readFile } from 'node:fs/promises'
5
- import { cwd } from 'node:process'
6
- import { load } from 'js-toml'
7
- import { TSON } from '@southern-aurora/tson'
8
- import { format } from 'date-fns'
9
- import type { CookbookOptions } from './utils/cookbook-dto-types'
1
+ import { join, dirname } from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { existsSync } from "node:fs";
4
+ import { readFile } from "node:fs/promises";
5
+ import { cwd } from "node:process";
6
+ import { load } from "js-toml";
7
+ import { TSON } from "@southern-aurora/tson";
8
+ import { format } from "date-fns";
9
+ import type { CookbookOptions } from "./utils/cookbook-dto-types";
10
10
 
11
11
  export type AstraOptionsInit = {
12
- stargate: { $types: any, execute: any, ping: any, __cookbook: any }
13
- bootstrap: () => Promise<Record<string, any>>
14
- }
12
+ stargate: { $types: any; execute: any; ping: any; __cookbook: any };
13
+ bootstrap: () => Promise<Record<string, any>>;
14
+ };
15
15
 
16
- type GeneratorGeneric<T> = T extends AsyncGenerator<infer I> ? I : never
16
+ type GeneratorGeneric<T> = T extends AsyncGenerator<infer I> ? I : never;
17
17
 
18
- type Mixin<T, U> = U & Omit<T, keyof U>
18
+ type Mixin<T, U> = U & Omit<T, keyof U>;
19
19
 
20
20
  type ExecuteOptions = {
21
- headers?: Record<string, string>
22
- timeout?: number
23
- type?: 'action' | 'stream'
24
- }
21
+ headers?: Record<string, string>;
22
+ timeout?: number;
23
+ type?: "action" | "stream";
24
+ };
25
25
 
26
- type ExecuteResultsOption = { executeId: string }
26
+ type ExecuteResultsOption = { executeId: string };
27
27
 
28
- type Context = {
29
- logger: Logger
30
- }
28
+ type Context = {
29
+ logger: Logger;
30
+ };
31
31
 
32
32
  type Logger = {
33
- debug: (description: string, ...params: Array<unknown>) => Log
34
- info: (description: string, ...params: Array<unknown>) => Log
35
- warn: (description: string, ...params: Array<unknown>) => Log
36
- error: (description: string, ...params: Array<unknown>) => Log
37
- response: (description: string, ...params: Array<unknown>) => Log
38
- }
33
+ debug: (description: string, ...params: Array<unknown>) => Log;
34
+ info: (description: string, ...params: Array<unknown>) => Log;
35
+ warn: (description: string, ...params: Array<unknown>) => Log;
36
+ error: (description: string, ...params: Array<unknown>) => Log;
37
+ response: (description: string, ...params: Array<unknown>) => Log;
38
+ };
39
39
 
40
- type Log = [string /* executeId */, '[DEBUG]' | '[INFO]' | '[WARN]' | '[ERROR]' | '[RESPONSE]', string, string, ...Array<unknown>]
40
+ type Log = [string /* executeId */, "[DEBUG]" | "[INFO]" | "[WARN]" | "[ERROR]" | "[RESPONSE]", string, string, ...Array<unknown>];
41
41
 
42
- type Reject = (description: string, ...params: Array<unknown>) => Error
42
+ type Reject = (description: string, ...params: Array<unknown>) => Error;
43
43
 
44
- export async function createAstra<AstraOptions extends AstraOptionsInit, Generated extends AstraOptions['stargate']['$types']['generated']>(astraOptions: AstraOptions) {
45
- if (!existsSync(join(cwd(), 'cookbook.toml'))) throw new Error(`The "cookbook.toml" file does not exist in the current directory. If you are running the test with the VS Code extension, make sure it exists in the root directory of the folder you are opening with VS Code.`)
46
- const cookbookOptions = load((await readFile(join(cwd(), 'cookbook.toml'))).toString()) as CookbookOptions
44
+ export async function createAstra<AstraOptions extends AstraOptionsInit, Generated extends AstraOptions["stargate"]["$types"]["generated"]>(astraOptions: AstraOptions) {
45
+ if (!existsSync(join(cwd(), "cookbook.toml"))) throw new Error(`The "cookbook.toml" file does not exist in the current directory. If you are running the test with the VS Code extension, make sure it exists in the root directory of the folder you are opening with VS Code.`);
46
+ const cookbookOptions = load((await readFile(join(cwd(), "cookbook.toml"))).toString()) as CookbookOptions;
47
47
  // wait for all milkio projects to start and can be accessed
48
48
  // the reason why stargate's ping method is not used directly is that even if only one project is tested, it is necessary to wait for all milkio projects to start
49
49
  await Promise.all([
50
50
  ...(() => {
51
- const projectStatus = new Map<string, { promise: Promise<undefined>, resolve: (value?: undefined | PromiseLike<undefined>) => void, reject: (reason?: any) => void }>()
51
+ const projectStatus = new Map<string, { promise: Promise<undefined>; resolve: (value?: undefined | PromiseLike<undefined>) => void; reject: (reason?: any) => void }>();
52
52
  for (const projectName in cookbookOptions.projects) {
53
- const project = cookbookOptions.projects[projectName]
54
- if (project.type !== 'milkio') continue
55
- projectStatus.set(projectName, withResolvers())
56
- let counter = 65
53
+ const project = cookbookOptions.projects[projectName];
54
+ if (project.type !== "milkio") continue;
55
+ projectStatus.set(projectName, withResolvers());
56
+ let counter = 65;
57
57
  let timer: Timer | null = setInterval(async () => {
58
58
  if (--counter <= 0) {
59
- clearInterval(timer!)
60
- timer = null
61
- console.warn(`[cookbook] Your project ${projectName} (http://localhost:${project.port}/) HTTP server hasn't started for too long.`)
62
- projectStatus.get(projectName)!.resolve(undefined)
63
- return
59
+ clearInterval(timer!);
60
+ timer = null;
61
+ console.warn(`[cookbook] Your project ${projectName} (http://localhost:${project.port}/) HTTP server hasn't started for too long.`);
62
+ projectStatus.get(projectName)!.resolve(undefined);
63
+ return;
64
64
  }
65
65
  try {
66
- console.log('\n[ASTRA]', `connecting.. ${counter >= 64 ? '' : `(${counter})`}`)
67
- const response = await fetchWithTimeout(`http://localhost:${project.port}/generate_204`, { method: 'HEAD', timeout: 1024 })
66
+ console.log("\n[ASTRA]", `connecting.. ${counter >= 64 ? "" : `(${counter})`}`);
67
+ const response = await fetchWithTimeout(`http://localhost:${project.port}/generate_204`, { method: "HEAD", timeout: 1024 });
68
68
  if (response.status === 204) {
69
- if (timer) clearTimeout(timer)
70
- timer = null
71
- return projectStatus.get(projectName)!.resolve(undefined)
69
+ if (timer) clearTimeout(timer);
70
+ timer = null;
71
+ return projectStatus.get(projectName)!.resolve(undefined);
72
72
  }
73
- }
74
- catch (error) {}
75
- }, 100)
73
+ } catch (error) {}
74
+ }, 100);
76
75
  }
77
- return Array.from(projectStatus.values()).map(v => v.promise)
76
+ return Array.from(projectStatus.values()).map((v) => v.promise);
78
77
  })(),
79
- ])
78
+ ]);
80
79
 
81
- type Execute = <Path extends keyof Generated['routeSchema']>(
80
+ type Execute = <Path extends keyof Generated["routeSchema"]>(
82
81
  path: Path,
83
82
  options?: Mixin<
84
83
  ExecuteOptions,
85
84
  | {
86
- params?: Generated['routeSchema'][Path]['types']['params']
87
- }
85
+ params?: Generated["routeSchema"][Path]["types"]["params"];
86
+ }
88
87
  | {
89
- params?: Partial<Generated['routeSchema'][Path]['types']['params']>
90
- generateParams: true
91
- }
88
+ params?: Partial<Generated["routeSchema"][Path]["types"]["params"]>;
89
+ generateParams: true;
90
+ }
92
91
  >,
93
92
  ) => Promise<
94
- Generated['routeSchema'][Path]['types']['🐣'] extends boolean
93
+ Generated["routeSchema"][Path]["types"]["🐣"] extends boolean
95
94
  ? // action
96
- [Partial<Generated['rejectCode']>, null, ExecuteResultsOption] | [null, Generated['routeSchema'][Path]['types']['result'], ExecuteResultsOption]
95
+ [Partial<Generated["rejectCode"]>, null, ExecuteResultsOption] | [null, Generated["routeSchema"][Path]["types"]["result"], ExecuteResultsOption]
97
96
  : // stream
98
- [Partial<Generated['rejectCode']>, null, ExecuteResultsOption] | [null, AsyncGenerator<[Partial<Generated['rejectCode']>, null] | [null, GeneratorGeneric<Generated['routeSchema'][Path]['types']['result']>], ExecuteResultsOption>]
99
- >
97
+ [Partial<Generated["rejectCode"]>, null, ExecuteResultsOption] | [null, AsyncGenerator<[Partial<Generated["rejectCode"]>, null] | [null, GeneratorGeneric<Generated["routeSchema"][Path]["types"]["result"]>], ExecuteResultsOption>]
98
+ >;
100
99
 
101
100
  type MirrorWorld = Mixin<
102
- Awaited<ReturnType<AstraOptions['bootstrap']>>,
101
+ Awaited<ReturnType<AstraOptions["bootstrap"]>>,
103
102
  {
104
- paths: { cwd: string, milkio: string, generated: string }
105
- execute: Execute
103
+ paths: { cwd: string; milkio: string; generated: string };
104
+ execute: Execute;
106
105
  }
107
- >
106
+ >;
108
107
 
109
108
  return {
110
109
  options: astraOptions,
111
110
  async createMirrorWorld(importMetaUrl: string): Promise<[Context, Reject, MirrorWorld]> {
112
- const thisFilePath = join(fileURLToPath(importMetaUrl))
113
- const thisFileDirPath = join(dirname(thisFilePath)).replaceAll('\\', '/')
114
- const thisFileDirPathArr = thisFileDirPath.split('/')
115
- let projectName = ''
111
+ const thisFilePath = join(fileURLToPath(importMetaUrl));
112
+ const thisFileDirPath = join(dirname(thisFilePath)).replaceAll("\\", "/");
113
+ const thisFileDirPathArr = thisFileDirPath.split("/");
114
+ let projectName = "";
116
115
 
117
116
  await (async () => {
118
- let isProjectsDirectory = false
117
+ let isProjectsDirectory = false;
119
118
  for (let i = 0; i < thisFileDirPathArr.length; i++) {
120
- if (thisFileDirPathArr[i] === 'projects') {
121
- isProjectsDirectory = true
122
- continue
119
+ if (thisFileDirPathArr[i] === "projects") {
120
+ isProjectsDirectory = true;
121
+ continue;
123
122
  }
124
- if (isProjectsDirectory === false) continue
125
- projectName = thisFileDirPathArr[i]
126
- break
123
+ if (isProjectsDirectory === false) continue;
124
+ projectName = thisFileDirPathArr[i];
125
+ break;
127
126
  }
128
- if (projectName === '') throw new Error('Unable to determine the path of the current test, make sure the test is under a milkio project.')
129
- let projectNameChecked = false
127
+ if (projectName === "") throw new Error("Unable to determine the path of the current test, make sure the test is under a milkio project.");
128
+ let projectNameChecked = false;
130
129
  for (const projectNameForCookbookOptions in cookbookOptions.projects) {
131
130
  if (projectNameForCookbookOptions === projectName) {
132
- projectNameChecked = true
133
- break
131
+ projectNameChecked = true;
132
+ break;
134
133
  }
135
134
  }
136
- if (projectNameChecked === false) throw new Error(`Project name "${projectName}" not found in "cookbook.toml" in "projects.${projectName}".`)
137
- })()
135
+ if (projectNameChecked === false) throw new Error(`Project name "${projectName}" not found in "cookbook.toml" in "projects.${projectName}".`);
136
+ })();
138
137
 
139
138
  const paths = {
140
- cwd: join(cwd(), 'projects', projectName),
141
- milkio: join(cwd(), 'projects', projectName, '.milkio'),
142
- generated: join(cwd(), 'projects', projectName, '.milkio'),
143
- }
139
+ cwd: join(cwd(), "projects", projectName),
140
+ milkio: join(cwd(), "projects", projectName, ".milkio"),
141
+ generated: join(cwd(), "projects", projectName, ".milkio"),
142
+ };
144
143
 
145
- const execute = async (path: Parameters<MirrorWorld['execute']>[0], optionsInit?: Parameters<MirrorWorld['execute']>[1]) => {
146
- const options = (optionsInit as any) ?? {}
144
+ const execute = async (path: Parameters<MirrorWorld["execute"]>[0], optionsInit?: Parameters<MirrorWorld["execute"]>[1]) => {
145
+ const options = (optionsInit as any) ?? {};
147
146
  if (options?.generateParams === true) {
148
- if (!options?.params) options.params = {}
149
- options.params.$milkioGenerateParams = 'enable'
147
+ if (!options?.params) options.params = {};
148
+ options.params.$milkioGenerateParams = "enable";
150
149
  }
151
150
 
152
- const results = await this.options.stargate.__cookbook.subscribe(`http://localhost:${cookbookOptions.general.cookbookPort}`)
151
+ const results = await this.options.stargate.__cookbook.subscribe(`http://localhost:${cookbookOptions.general.cookbookPort}`);
153
152
  void (async () => {
154
153
  for await (const result of results) {
155
- if (result.type !== 'milkio@logger') continue
156
- console.log('\n[MILKIO]', ...(result.log ?? []))
154
+ if (result.type !== "milkio@logger") continue;
155
+ console.log("\n[MILKIO]", ...(result.log ?? []));
157
156
  }
158
- })()
157
+ })();
159
158
 
160
- const response = await this.options.stargate.execute(path, options)
159
+ const response = await this.options.stargate.execute(path, options);
161
160
 
162
- await new Promise(resolve => setTimeout(resolve, 40))
163
- context.logger.response(path as string, `\nerror - ${TSON.stringify(response[0])}`, `\nresult - ${typeof response[1]?.next === 'function' ? 'AsyncGenerator' : TSON.stringify(response[1])}`)
161
+ await new Promise((resolve) => setTimeout(resolve, 40));
162
+ context.logger.response(path as string, `\nerror - ${TSON.stringify(response[0])}`, `\nresult - ${typeof response[1]?.next === "function" ? "AsyncGenerator" : TSON.stringify(response[1])}`);
164
163
 
165
- return response
166
- }
164
+ return response;
165
+ };
167
166
 
168
- const getNow = () => format(new Date(), '(yyyy-MM-dd hh:mm:ss)')
167
+ const getNow = () => format(new Date(), "(yyyy-MM-dd hh:mm:ss)");
169
168
  const onLoggerInserting = (log: Log) => {
170
169
  // biome-ignore lint/style/noParameterAssign: <explanation>
171
- log = [...log]
172
- log[0] = `\n${log[0]}` as any
173
- console.log(...log)
174
- return true
175
- }
170
+ log = [...log];
171
+ log[0] = `\n${log[0]}` as any;
172
+ console.log(...log);
173
+ return true;
174
+ };
176
175
 
177
176
  const context = {
178
177
  logger: {
179
178
  debug: (description: string, ...params: Array<unknown>): Log => {
180
- const log: Log = ['[TEST]', '[DEBUG]', description, getNow(), ...params]
181
- onLoggerInserting(log)
182
- return log
179
+ const log: Log = ["[TEST]", "[DEBUG]", description, getNow(), ...params];
180
+ onLoggerInserting(log);
181
+ return log;
183
182
  },
184
183
  info: (description: string, ...params: Array<unknown>): Log => {
185
- const log: Log = ['[TEST]', '[INFO]', description, getNow(), ...params]
186
- onLoggerInserting(log)
187
- return log
184
+ const log: Log = ["[TEST]", "[INFO]", description, getNow(), ...params];
185
+ onLoggerInserting(log);
186
+ return log;
188
187
  },
189
188
  warn: (description: string, ...params: Array<unknown>): Log => {
190
- const log: Log = ['[TEST]', '[WARN]', description, getNow(), ...params]
191
- onLoggerInserting(log)
192
- return log
189
+ const log: Log = ["[TEST]", "[WARN]", description, getNow(), ...params];
190
+ onLoggerInserting(log);
191
+ return log;
193
192
  },
194
193
  error: (description: string, ...params: Array<unknown>): Log => {
195
- const log: Log = ['[TEST]', '[ERROR]', description, getNow(), ...params]
196
- onLoggerInserting(log)
197
- return log
194
+ const log: Log = ["[TEST]", "[ERROR]", description, getNow(), ...params];
195
+ onLoggerInserting(log);
196
+ return log;
198
197
  },
199
198
  response: (path: string, ...params: Array<unknown>): Log => {
200
- const log: Log = ['[TEST]', '[RESPONSE]', path, getNow(), ...params]
201
- onLoggerInserting(log)
202
- return log
199
+ const log: Log = ["[TEST]", "[RESPONSE]", path, getNow(), ...params];
200
+ onLoggerInserting(log);
201
+ return log;
203
202
  },
204
203
  },
205
- } as Context
204
+ } as Context;
206
205
 
207
206
  const world = {
208
207
  ...(await astraOptions.bootstrap()),
209
208
  paths,
210
209
  execute,
211
- } as any
210
+ } as any;
212
211
 
213
212
  const reject = (...params: Array<unknown>): Error => {
214
213
  const output: Array<any> = [
215
- '[REJECT]',
214
+ "[REJECT]",
216
215
  ...params.map((param) => {
217
216
  try {
218
- const result = TSON.stringify(param)
219
- return result
220
- }
221
- catch (error) {
222
- return error?.toString?.() ?? typeof error
217
+ const result = TSON.stringify(param);
218
+ return result;
219
+ } catch (error) {
220
+ return error?.toString?.() ?? typeof error;
223
221
  }
224
222
  }),
225
- ]
226
- console.log(...output)
223
+ ];
224
+ console.log(...output);
227
225
  for (let index = 1; index < output.length; index++) {
228
- if (typeof output[index] === 'object') {
229
- output[index] = output[index].toString()
226
+ if (typeof output[index] === "object") {
227
+ output[index] = output[index].toString();
230
228
  }
231
229
  }
232
- const message = output.join(' ')
233
- return new Error(message)
234
- }
230
+ const message = output.join(" ");
231
+ return new Error(message);
232
+ };
235
233
 
236
- return [context, reject, world]
234
+ return [context, reject, world];
237
235
  },
238
- }
236
+ };
239
237
  }
240
238
 
241
239
  export async function fetchWithTimeout(url: string, options: FetchRequestInit & { timeout?: number } = {}) {
242
- const { timeout = 8000 } = options
240
+ const { timeout = 8000 } = options;
243
241
 
244
- const controller = new AbortController()
245
- const id = setTimeout(() => controller.abort(), timeout)
242
+ const controller = new AbortController();
243
+ const id = setTimeout(() => controller.abort(), timeout);
246
244
  const response = await fetch(url, {
247
245
  ...options,
248
246
  signal: controller.signal,
249
- })
250
- clearTimeout(id)
251
- return response
247
+ });
248
+ clearTimeout(id);
249
+ return response;
252
250
  }
253
251
 
254
252
  function withResolvers<T = any>(): PromiseWithResolvers<T> {
255
- let resolve: PromiseWithResolvers<T>['resolve']
256
- let reject: PromiseWithResolvers<T>['reject']
253
+ let resolve: PromiseWithResolvers<T>["resolve"];
254
+ let reject: PromiseWithResolvers<T>["reject"];
257
255
  const promise = new Promise<T>((res, rej) => {
258
- resolve = res
259
- reject = rej
260
- })
261
- return { promise, resolve: resolve!, reject: reject! }
256
+ resolve = res;
257
+ reject = rej;
258
+ });
259
+ return { promise, resolve: resolve!, reject: reject! };
262
260
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@milkio/astra",
3
3
  "type": "module",
4
- "version": "1.0.0-alpha.97",
4
+ "version": "1.0.0-alpha.99",
5
5
  "module": "index.ts",
6
6
  "dependencies": {
7
7
  "@southern-aurora/tson": "*",