miqro 6.2.12 → 6.3.0

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.
@@ -1,5 +1,5 @@
1
1
  import { Router, newURL, normalizePath } from "@miqro/core";
2
- import { existsSync, mkdirSync, readFile, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
2
+ import { existsSync, mkdir, readFile, readFileSync, readdirSync, statSync } from "node:fs";
3
3
  import { dirname, join, relative, resolve as pathResolve } from "node:path";
4
4
  import { CONTENT_TYPE_MAP, DEFAULT_CONTENT_TYPE } from "../common/content-type.js";
5
5
  import { importHTMLModule, importAPIRoute, inflateJSX, importJSONModule, jsx2HTML } from "../common/jsx.js";
@@ -11,11 +11,11 @@ import { getHTTPRouterPath, getStaticFilesPath } from "../common/paths.js";
11
11
  import { setupCORS } from "./setup-cors.js";
12
12
  import { setupAUTH } from "./setup-auth.js";
13
13
  import { getRoutes } from "../services/utils/get-route.js";
14
- import { describeFilePath } from "../common/fs.js";
14
+ import { describeFilePath, mkdirASync, writeFileASync } from "../common/fs.js";
15
15
  import { inflateMD2HTML } from "./md.js";
16
16
  import { setupMiddleware } from "./setup-middleware.js";
17
17
  import { setupError } from "./setup-error.js";
18
- export async function setupHTTPRouter(server, logger, hotreload, servicePath, service, routeFileMap, staticFileMap, inflateDir, inflateSea, errors) {
18
+ export async function setupHTTPRouter(server, logger, hotreload, servicePath, service, routeFileMap, staticFileMap, inflateDir, inflateSea, errors, inflateParallel) {
19
19
  const mainRouter = new Router();
20
20
  const apiRouterPath = getHTTPRouterPath(servicePath); //resolve(process.cwd(), service, "http");
21
21
  let middlewareConfig = null;
@@ -25,13 +25,13 @@ export async function setupHTTPRouter(server, logger, hotreload, servicePath, se
25
25
  middlewareConfig = await setupMiddleware(logger, servicePath, service, mainRouter, inflateDir, inflateSea, errors);
26
26
  if (apiRouterPath) {
27
27
  logger.trace("setting up http routes from [%s]", service);
28
- const { router: httpRouter } = await createRouterFromDirectory(server, hotreload, service, logger, apiRouterPath, errors, routeFileMap, staticFileMap, inflateDir, inflateSea);
28
+ const { router: httpRouter } = await createRouterFromDirectory(server, hotreload, service, logger, apiRouterPath, errors, routeFileMap, staticFileMap, inflateDir, inflateSea, inflateParallel);
29
29
  mainRouter.use(httpRouter);
30
30
  }
31
31
  const staticFilesPath = getStaticFilesPath(servicePath); //resolve(process.cwd(), service, "static");
32
32
  if (staticFilesPath) {
33
33
  logger.trace("setting up static file routes from [%s]", service);
34
- const staticRouter = createStaticRouterFromDirectory(service, logger, staticFilesPath, inflateDir, routeFileMap, staticFileMap);
34
+ const staticRouter = await createStaticRouterFromDirectory(service, logger, staticFilesPath, inflateDir, routeFileMap, staticFileMap, inflateParallel);
35
35
  mainRouter.use(staticRouter);
36
36
  }
37
37
  if (middlewareConfig && middlewareConfig.post) {
@@ -41,86 +41,114 @@ export async function setupHTTPRouter(server, logger, hotreload, servicePath, se
41
41
  }
42
42
  return mainRouter;
43
43
  }
44
- function createStaticRoute(service, logger, router, dir, file, inflateDir, routeFileMap, staticFileMap) {
45
- logger.trace("creating static route for [%s]", file.filePath);
46
- logger.trace("[%o]", {
47
- file,
48
- dir
49
- });
50
- const contentType = CONTENT_TYPE_MAP[String(file.ext).toLocaleLowerCase()];
51
- const path = join("/", relative(dir, file.filePath));
52
- routeFileMap[file.filePath] = {
53
- routes: [{
54
- method: "GET",
55
- path: normalizePath(path)
56
- }],
57
- service,
58
- filePath: file.filePath,
59
- previewMethod: "html"
60
- };
61
- if (inflateDir) {
62
- const inflatePath = join(inflateDir, service, "static", path);
63
- mkdirSync(dirname(inflatePath), {
64
- recursive: true
65
- });
66
- logger.log("writing [%s]", relative(cwd(), inflatePath));
67
- const body = readFileSync(file.filePath);
68
- writeFileSync(inflatePath, body);
69
- if (staticFileMap) {
70
- staticFileMap[file.filePath] = {
71
- contentType,
44
+ async function createStaticRoute(service, logger, router, dir, file, inflateDir, routeFileMap, staticFileMap) {
45
+ return new Promise(async (resolve, reject) => {
46
+ try {
47
+ logger.trace("creating static route for [%s]", file.filePath);
48
+ logger.trace("[%o]", {
49
+ file,
50
+ dir
51
+ });
52
+ const contentType = CONTENT_TYPE_MAP[String(file.ext).toLocaleLowerCase()];
53
+ const path = join("/", relative(dir, file.filePath));
54
+ routeFileMap[file.filePath] = {
55
+ routes: [{
56
+ method: "GET",
57
+ path: normalizePath(path)
58
+ }],
59
+ service,
72
60
  filePath: file.filePath,
73
- previewMethod: "html",
74
- method: "GET",
75
- path: normalizePath(path),
76
- body: Buffer.from(body),
77
- inflatePath: inflateDir ? join(inflateDir, service, "static", path) : undefined
61
+ previewMethod: "html"
78
62
  };
79
- }
80
- }
81
- router.use(assertGlobalTampered);
82
- router.get(path, async function (_req, res) {
83
- await new Promise((resolve, reject) => {
84
- try {
85
- readFile(file.filePath, async (err, body) => {
86
- if (err) {
87
- reject(err);
63
+ if (inflateDir) {
64
+ const inflatePath = join(inflateDir, service, "static", path);
65
+ mkdir(dirname(inflatePath), {
66
+ recursive: true
67
+ }, (err) => {
68
+ });
69
+ await mkdirASync(dirname(inflatePath), {
70
+ recursive: true
71
+ });
72
+ logger.log("writing [%s]", relative(cwd(), inflatePath));
73
+ const body = readFileSync(file.filePath);
74
+ await writeFileASync(inflatePath, body);
75
+ if (staticFileMap) {
76
+ staticFileMap[file.filePath] = {
77
+ contentType,
78
+ filePath: file.filePath,
79
+ previewMethod: "html",
80
+ method: "GET",
81
+ path: normalizePath(path),
82
+ body: Buffer.from(body),
83
+ inflatePath: inflateDir ? join(inflateDir, service, "static", path) : undefined
84
+ };
85
+ }
86
+ }
87
+ router.use(assertGlobalTampered);
88
+ router.get(path, async function (_req, res) {
89
+ await new Promise((resolve, reject) => {
90
+ try {
91
+ readFile(file.filePath, async (err, body) => {
92
+ if (err) {
93
+ reject(err);
94
+ }
95
+ else {
96
+ try {
97
+ await res.asyncEnd({
98
+ status: 200,
99
+ headers: {
100
+ ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
101
+ },
102
+ body
103
+ });
104
+ resolve();
105
+ }
106
+ catch (e) {
107
+ reject(e);
108
+ }
109
+ }
110
+ });
88
111
  }
89
- else {
90
- try {
91
- await res.asyncEnd({
92
- status: 200,
93
- headers: {
94
- ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
95
- },
96
- body
97
- });
98
- resolve();
99
- }
100
- catch (e) {
101
- reject(e);
102
- }
112
+ catch (e) {
113
+ reject(e);
103
114
  }
104
115
  });
105
- }
106
- catch (e) {
107
- reject(e);
108
- }
109
- });
116
+ });
117
+ resolve();
118
+ }
119
+ catch (e) {
120
+ reject(e);
121
+ }
110
122
  });
111
123
  }
112
- function createStaticRouterFromDirectory(service, logger, dir, inflateDir, routeFileMap, staticFileMap) {
124
+ async function createStaticRouterFromDirectory(service, logger, dir, inflateDir, routeFileMap, staticFileMap, inflateParallel) {
113
125
  const router = new Router();
114
- scanFiles(dir).forEach(file => {
115
- createStaticRoute(service, logger, router, dir, file, inflateDir, routeFileMap, staticFileMap);
116
- });
126
+ const maxParallel = inflateParallel ? inflateParallel : 1;
127
+ logger.debug("loading static directory with parallel [%s]", maxParallel);
128
+ let tR = [];
129
+ const files = scanFiles(dir);
130
+ for (const file of files) {
131
+ tR.push(await createStaticRoute(service, logger, router, dir, file, inflateDir, routeFileMap, staticFileMap));
132
+ if (tR.length >= maxParallel) {
133
+ await Promise.all(tR);
134
+ tR = [];
135
+ }
136
+ }
137
+ if (tR.length > 0) {
138
+ await Promise.all(tR);
139
+ tR = [];
140
+ }
117
141
  return router;
118
142
  }
119
- async function createRouterFromDirectory(server, hotreload, service, logger, dir, errors = [], routeFileMap = {}, staticFileMap = null, inflateDir, inflateSea) {
143
+ async function createRouterFromDirectory(server, hotreload, service, logger, dir, errors = [], routeFileMap = {}, staticFileMap = null, inflateDir, inflateSea, inflateParallel) {
120
144
  const router = new Router();
145
+ const maxParallel = inflateParallel ? inflateParallel : 1;
146
+ server.logger.debug("loading http directory with parallel [%s]", maxParallel);
147
+ let tR = [];
121
148
  router.use(assertGlobalTampered);
122
- for (const file of scanFiles(dir)) {
123
- await new Promise(async (resolve) => {
149
+ const files = scanFiles(dir);
150
+ for (const file of files) {
151
+ tR.push(new Promise(async (resolve) => {
124
152
  try {
125
153
  switch (file.ext) {
126
154
  case ".jsx":
@@ -163,11 +191,11 @@ async function createRouterFromDirectory(server, hotreload, service, logger, dir
163
191
  if (inflateDir && r.defaultInflatePath && inflateSea) {
164
192
  const rPath = r.defaultInflatePath;
165
193
  const inflatePath = join(inflateDir, service, "http", rPath + ".api.cjs");
166
- mkdirSync(dirname(inflatePath), {
194
+ await mkdirASync(dirname(inflatePath), {
167
195
  recursive: true
168
196
  });
169
197
  logger.log("writing [%s]", relative(cwd(), inflatePath));
170
- writeFileSync(inflatePath, inflatedCode);
198
+ await writeFileASync(inflatePath, inflatedCode);
171
199
  }
172
200
  router.use(assertGlobalTampered);
173
201
  router.use(module.handler, r.path, r.method, r.options);
@@ -190,7 +218,7 @@ async function createRouterFromDirectory(server, hotreload, service, logger, dir
190
218
  //if (r.method === "GET" || r.method === "get") {
191
219
  const rPath = r.inflatePath;
192
220
  const inflatePath = join(inflateDir, service, "static", rPath);
193
- mkdirSync(dirname(inflatePath), {
221
+ await mkdirASync(dirname(inflatePath), {
194
222
  recursive: true
195
223
  });
196
224
  if (existsSync(inflatePath) && statSync(inflatePath).isDirectory()) {
@@ -200,7 +228,7 @@ async function createRouterFromDirectory(server, hotreload, service, logger, dir
200
228
  const JSON_STATIC = await getJSON({ server }, null, newURL(r.path), module.apiOptions?.basePath, module.default);
201
229
  //const JSON = await getJSON({ server } as ServerRequest, null, newURL(r.path), module.apiOptions?.basePath, module.default);
202
230
  logger.log("writing [%s]", relative(cwd(), inflatePath));
203
- writeFileSync(inflatePath, JSON_STATIC);
231
+ await writeFileASync(inflatePath, JSON_STATIC);
204
232
  //}
205
233
  if (staticFileMap && inflateSea) {
206
234
  staticFileMap[file.filePath] = {
@@ -245,7 +273,7 @@ async function createRouterFromDirectory(server, hotreload, service, logger, dir
245
273
  //if (r.method === "GET" || r.method === "get") {
246
274
  const rPath = r.inflatePath;
247
275
  const inflatePath = join(inflateDir, service, "static", rPath);
248
- mkdirSync(dirname(inflatePath), {
276
+ await mkdirASync(dirname(inflatePath), {
249
277
  recursive: true
250
278
  });
251
279
  if (existsSync(inflatePath) && statSync(inflatePath).isDirectory()) {
@@ -255,7 +283,7 @@ async function createRouterFromDirectory(server, hotreload, service, logger, dir
255
283
  const toRender = typeof module.default === "function" ? module.default({ server }, null) : module.default;
256
284
  const HTML_STATIC = await getHTML(hotreload, { server }, null, newURL(r.path), module.apiOptions?.basePath, await toRender);
257
285
  logger.log("writing [%s]", relative(cwd(), inflatePath));
258
- writeFileSync(inflatePath, HTML_STATIC);
286
+ await writeFileASync(inflatePath, HTML_STATIC);
259
287
  //}
260
288
  if (staticFileMap && inflateSea) {
261
289
  staticFileMap[file.filePath + r.method + r.path] = {
@@ -309,11 +337,11 @@ async function createRouterFromDirectory(server, hotreload, service, logger, dir
309
337
  };
310
338
  if (inflateDir) {
311
339
  const inflatePath = join(inflateDir, service, "static", path);
312
- mkdirSync(dirname(inflatePath), {
340
+ await mkdirASync(dirname(inflatePath), {
313
341
  recursive: true
314
342
  });
315
343
  logger.log("writing [%s]", relative(cwd(), inflatePath));
316
- writeFileSync(inflatePath, code);
344
+ await writeFileASync(inflatePath, code);
317
345
  if (staticFileMap && inflateSea) {
318
346
  staticFileMap[file.filePath] = {
319
347
  contentType,
@@ -358,11 +386,11 @@ async function createRouterFromDirectory(server, hotreload, service, logger, dir
358
386
  };
359
387
  if (inflateDir) {
360
388
  const inflatePath = join(inflateDir, service, "static", path);
361
- mkdirSync(dirname(inflatePath), {
389
+ await mkdirASync(dirname(inflatePath), {
362
390
  recursive: true
363
391
  });
364
392
  logger.log("writing [%s]", relative(cwd(), inflatePath));
365
- writeFileSync(inflatePath, code);
393
+ await writeFileASync(inflatePath, code);
366
394
  if (staticFileMap && inflateSea) {
367
395
  staticFileMap[file.filePath] = {
368
396
  contentType,
@@ -417,11 +445,11 @@ async function createRouterFromDirectory(server, hotreload, service, logger, dir
417
445
  };
418
446
  if (inflateDir) {
419
447
  const inflatePath = join(inflateDir, service, "static", path);
420
- mkdirSync(dirname(inflatePath), {
448
+ await mkdirASync(dirname(inflatePath), {
421
449
  recursive: true
422
450
  });
423
451
  logger.log("writing [%s]", relative(cwd(), inflatePath));
424
- writeFileSync(inflatePath, code);
452
+ await writeFileASync(inflatePath, code);
425
453
  if (staticFileMap && inflateSea) {
426
454
  staticFileMap[file.filePath] = {
427
455
  contentType,
@@ -474,11 +502,11 @@ async function createRouterFromDirectory(server, hotreload, service, logger, dir
474
502
  };
475
503
  if (inflateDir) {
476
504
  const inflatePath = join(inflateDir, service, "static", path);
477
- mkdirSync(dirname(inflatePath), {
505
+ await mkdirASync(dirname(inflatePath), {
478
506
  recursive: true
479
507
  });
480
508
  logger.log("writing [%s]", relative(cwd(), inflatePath));
481
- writeFileSync(inflatePath, code);
509
+ await writeFileASync(inflatePath, code);
482
510
  if (staticFileMap && inflateSea) {
483
511
  staticFileMap[file.filePath] = {
484
512
  contentType,
@@ -505,7 +533,7 @@ async function createRouterFromDirectory(server, hotreload, service, logger, dir
505
533
  }
506
534
  }
507
535
  }
508
- createStaticRoute(service, logger, router, dir, file, inflateDir, routeFileMap, staticFileMap);
536
+ await createStaticRoute(service, logger, router, dir, file, inflateDir, routeFileMap, staticFileMap);
509
537
  return resolve();
510
538
  }
511
539
  }
@@ -520,7 +548,15 @@ async function createRouterFromDirectory(server, hotreload, service, logger, dir
520
548
  finally {
521
549
  return resolve();
522
550
  }
523
- });
551
+ }));
552
+ if (tR.length >= maxParallel) {
553
+ await Promise.all(tR);
554
+ tR = [];
555
+ }
556
+ }
557
+ if (tR.length > 0) {
558
+ await Promise.all(tR);
559
+ tR = [];
524
560
  }
525
561
  router.use(assertGlobalTampered);
526
562
  return {
@@ -22,6 +22,7 @@ async function main(args) {
22
22
  browser: args.browser,
23
23
  logFile: args.logFile,
24
24
  hotreload: args.test ? false : args.hotreload,
25
+ watch: args.test ? false : args.watch,
25
26
  https: args.test ? false : args.https,
26
27
  serverOptions: args.serverOptions,
27
28
  httpRedirect: args.test ? undefined : args.httpsRedirect
@@ -29,7 +30,9 @@ async function main(args) {
29
30
  // check arguments
30
31
  if (args.generateDoc) {
31
32
  // --generate-doc
32
- const inflated = await app.inflate();
33
+ const inflated = await app.inflate({
34
+ inflateParallel: args.inflateParallel
35
+ });
33
36
  await generateDocs(args, app.logger, inflated);
34
37
  process.exit(EXIT_CODES.NORMAL_EXIT);
35
38
  }
@@ -45,7 +48,9 @@ async function main(args) {
45
48
  }
46
49
  else if (args.test) {
47
50
  // --test
48
- await app.inflate();
51
+ await app.inflate({
52
+ inflateParallel: args.inflateParallel
53
+ });
49
54
  await app.start();
50
55
  await testMain(app);
51
56
  await app.stop();
@@ -57,7 +62,8 @@ async function main(args) {
57
62
  // --compile
58
63
  await app.inflate({
59
64
  inflateDir: args.inflateDir,
60
- inflateSea: true
65
+ inflateSea: true,
66
+ inflateParallel: args.inflateParallel
61
67
  });
62
68
  await app.dbManager.closeAll();
63
69
  await app.webSocketManager.disconnectAll();
@@ -69,7 +75,8 @@ async function main(args) {
69
75
  // loadApp with inflateDir arg to inflate inflatable files
70
76
  await app.inflate({
71
77
  inflateDir: args.inflateDir,
72
- inflateSea: args.inflateSEA
78
+ inflateSea: args.inflateSEA,
79
+ inflateParallel: args.inflateParallel
73
80
  });
74
81
  await app.dbManager.closeAll();
75
82
  await app.webSocketManager.disconnectAll();
@@ -77,7 +84,9 @@ async function main(args) {
77
84
  }
78
85
  else {
79
86
  // server
80
- await app.inflate();
87
+ await app.inflate({
88
+ inflateParallel: args.inflateParallel
89
+ });
81
90
  await app.start();
82
91
  }
83
92
  }
@@ -22,6 +22,7 @@ export interface MiqroOptions {
22
22
  browser?: string | boolean;
23
23
  logFile?: string | boolean;
24
24
  hotreload?: boolean;
25
+ watch?: boolean;
25
26
  serverOptions?: ServerOptions<any, any>;
26
27
  https?: boolean;
27
28
  httpRedirect?: number;
@@ -29,6 +30,7 @@ export interface MiqroOptions {
29
30
  export interface InflateOptions {
30
31
  inflateDir?: string;
31
32
  inflateSea?: boolean;
33
+ inflateParallel?: number;
32
34
  }
33
35
  export interface InflatedResult {
34
36
  router: Router;
@@ -127,6 +127,7 @@ export class Miqro {
127
127
  });
128
128
  await app.inflate({
129
129
  inflateDir: miqroJSON.inflateDir ? String(miqroJSON.inflateDir) : undefined,
130
+ inflateParallel: miqroJSON.inflateParallel ? miqroJSON.inflateParallel : undefined,
130
131
  ...(inflate ? inflate : {}),
131
132
  });
132
133
  return app;
@@ -290,7 +291,8 @@ export class Miqro {
290
291
  inflateDir: options?.inflateDir,
291
292
  inflateSea: options?.inflateSea ? true : false,
292
293
  //inflateTests: options?.inflateTests ? true : false,
293
- hotreload: this.options?.hotreload ? true : false
294
+ hotreload: this.options?.hotreload ? true : false,
295
+ inflateParallel: options?.inflateParallel
294
296
  });
295
297
  wsConfigList.push(...serviceWSConfigList);
296
298
  router.use(serviceRouter);
@@ -398,7 +400,7 @@ export class Miqro {
398
400
  this.logger?.debug("\t\t==listening on [%s][%s]==", this.options.https ? "https" : "http", this.options.port);
399
401
  }
400
402
  await notifiyServerConfig(this.logger, this.serverInterface, this.adminInterface, this.inflated.serverConfigMap, "start");
401
- if (this.options.hotreload && (cluster.isPrimary || process.env["CLUSTER_NODE_NUMBER"] === "0")) {
403
+ if (this.options.watch && (cluster.isPrimary || process.env["CLUSTER_NODE_NUMBER"] === "0")) {
402
404
  this.watcher = await watchAndServer(this);
403
405
  }
404
406
  this.logger?.debug("\t\t==start done==");