miqro 6.2.0 → 6.2.1

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.
@@ -12,6 +12,7 @@ import { isSea } from "node:sea";
12
12
  import cluster from "node:cluster";
13
13
  import { __package_dirname, getVersion } from "./assets.js";
14
14
  import { Parser, Schema } from "@miqro/parser";
15
+ import { ServerOptions } from "node:https";
15
16
 
16
17
  const parser = new Parser();
17
18
 
@@ -23,6 +24,9 @@ interface MiqroJSON {
23
24
  browser?: string | boolean;
24
25
  logFile?: string | boolean;
25
26
  editor?: boolean;
27
+ https?: boolean;
28
+ serverOptions?: ServerOptions;
29
+ httpsRedirect?: number;
26
30
  }
27
31
 
28
32
  const MiqroJSONSchema: Schema<MiqroJSON> = {
@@ -34,7 +38,10 @@ const MiqroJSONSchema: Schema<MiqroJSON> = {
34
38
  inflateDir: "string?",
35
39
  browser: "boolean?|string?",
36
40
  logFile: "boolean?|string?",
37
- editor: "boolean?"
41
+ editor: "boolean?",
42
+ https: "boolean?",
43
+ serverOptions: "any?",
44
+ httpsRedirect: "number?"
38
45
  }
39
46
  }
40
47
 
@@ -76,6 +83,9 @@ export interface Arguments {
76
83
  services: string[];
77
84
  editor: boolean;
78
85
  hotreload: boolean;
86
+ https: boolean;
87
+ serverOptions: ServerOptions;
88
+ httpsRedirect?: number;
79
89
  }
80
90
 
81
91
  /**
@@ -87,6 +97,9 @@ export function parseArguments(): Arguments {
87
97
 
88
98
  const args = cluster.isPrimary ? process.argv.slice(2, process.argv.length) : process.argv.slice(3, process.argv.length);
89
99
  const flags: {
100
+ httpsRedirect: number | null;
101
+ https: boolean | null;
102
+ serverOptions: ServerOptions;
90
103
  logFile: string | boolean | null;
91
104
  browser: string | boolean | null;
92
105
  name: string | null;
@@ -110,6 +123,9 @@ export function parseArguments(): Arguments {
110
123
  inflateDir?: string | null;
111
124
  hotreload?: boolean | null;
112
125
  } = {
126
+ httpsRedirect: null,
127
+ https: null,
128
+ serverOptions: {},
113
129
  name: null,
114
130
  browser: null,
115
131
  logFile: null,
@@ -196,6 +212,59 @@ export function parseArguments(): Arguments {
196
212
  }
197
213
  flags.hotreload = true;
198
214
  continue;
215
+ case "--https":
216
+ if (flags.https !== null) {
217
+ console.error("bad arguments.");
218
+ console.error(usage);
219
+ process.exit(EXIT_CODES.BAD_ARGUMENTS);
220
+ }
221
+ flags.https = true;
222
+ continue;
223
+ case "--https-redirect":
224
+ if (flags.httpsRedirect !== null) {
225
+ console.error("bad arguments.");
226
+ console.error(usage);
227
+ process.exit(EXIT_CODES.BAD_ARGUMENTS);
228
+ }
229
+ const httpsRedirectPort = parseInt(String(args[i + 1]) as any, 10);
230
+ if (isNaN(httpsRedirectPort)) {
231
+ console.error("bad arguments. --https-redirect must be a number.");
232
+ console.error(usage);
233
+ process.exit(EXIT_CODES.BAD_ARGUMENTS);
234
+ }
235
+ flags.httpsRedirect = httpsRedirectPort;
236
+ i++;
237
+ continue;
238
+ case "--https-cert":
239
+ if (flags.serverOptions.cert) {
240
+ console.error("bad arguments.");
241
+ console.error(usage);
242
+ process.exit(EXIT_CODES.BAD_ARGUMENTS);
243
+ }
244
+ const httpsCertPath = args[i + 1] as any;
245
+ if (typeof httpsCertPath !== "string") {
246
+ console.error("bad arguments. --https-cert must be a string.");
247
+ console.error(usage);
248
+ process.exit(EXIT_CODES.BAD_ARGUMENTS);
249
+ }
250
+ flags.serverOptions.cert = readFileSync(httpsCertPath);
251
+ i++;
252
+ continue;
253
+ case "--https-key":
254
+ if (flags.serverOptions.key) {
255
+ console.error("bad arguments.");
256
+ console.error(usage);
257
+ process.exit(EXIT_CODES.BAD_ARGUMENTS);
258
+ }
259
+ const httpsKeyPath = args[i + 1] as any;
260
+ if (typeof httpsKeyPath !== "string") {
261
+ console.error("bad arguments. --https-key must be a string.");
262
+ console.error(usage);
263
+ process.exit(EXIT_CODES.BAD_ARGUMENTS);
264
+ }
265
+ flags.serverOptions.key = readFileSync(httpsKeyPath);
266
+ i++;
267
+ continue;
199
268
  case "--port":
200
269
  if (flags.port !== null) {
201
270
  console.error("bad arguments.");
@@ -426,6 +495,8 @@ export function parseArguments(): Arguments {
426
495
  const miqroJSONPath = !flags.disableMiqroJSON ? flags.miqroJSONPath ? resolve(flags.miqroJSONPath) : getMiqroJSONPath() : false;
427
496
  const miqroRC = miqroJSONPath ? importMiqroJSON(miqroJSONPath) : {};
428
497
 
498
+ //console.dir(miqroRC.serverOptions);
499
+
429
500
  // try to load .miqrorc
430
501
  if (!flags.disableMiqroJSON && miqroJSONPath) {
431
502
  if (services.length === 0) {
@@ -435,6 +506,33 @@ export function parseArguments(): Arguments {
435
506
  }
436
507
  }
437
508
  }
509
+ if (flags.https === null) {
510
+ if (miqroRC.https) {
511
+ flags.https = miqroRC.https;
512
+ }
513
+ }
514
+ if (flags.httpsRedirect === null) {
515
+ if (miqroRC.httpsRedirect && flags.https) {
516
+ /*console.log("reading key from " + String(miqroRC.serverOptions?.key));
517
+ flags.serverOptions.key = readFileSync(String(miqroRC.serverOptions?.key));*/
518
+ flags.httpsRedirect = miqroRC.httpsRedirect;
519
+ }
520
+ }
521
+ if (!flags.serverOptions.key) {
522
+ if (miqroRC.serverOptions?.key) {
523
+ /*console.log("reading key from " + String(miqroRC.serverOptions?.key));
524
+ flags.serverOptions.key = readFileSync(String(miqroRC.serverOptions?.key));*/
525
+ flags.serverOptions.key = miqroRC.serverOptions?.key;
526
+ }
527
+ }
528
+
529
+ if (!flags.serverOptions.cert) {
530
+ if (miqroRC.serverOptions?.cert) {
531
+ /*console.log("reading cert from " + String(miqroRC.serverOptions?.cert));
532
+ flags.serverOptions.cert = readFileSync(String(miqroRC.serverOptions?.cert));*/
533
+ flags.serverOptions.cert = miqroRC.serverOptions?.cert;
534
+ }
535
+ }
438
536
  if (flags.port === null) {
439
537
  if (miqroRC.port) {
440
538
  flags.port = String(miqroRC.port);
@@ -548,6 +646,21 @@ export function parseArguments(): Arguments {
548
646
 
549
647
  const generateDocType = flags.generateDocType ? flags.generateDocType as any : "MD";
550
648
 
649
+ if (flags.https && (!flags.serverOptions.key)) {
650
+ console.error("bad arguments. cannot use --https without --https-key. or set values in miqro.json file.");
651
+ process.exit(EXIT_CODES.BAD_ARGUMENTS);
652
+ }
653
+
654
+ if (flags.https && (!flags.serverOptions.cert)) {
655
+ console.error("bad arguments. cannot use --https without --https-cert. or set values in miqro.json file.");
656
+ process.exit(EXIT_CODES.BAD_ARGUMENTS);
657
+ }
658
+
659
+ if (flags.httpsRedirect && !flags.https) {
660
+ console.error("bad arguments. cannot use --https-redirect without --https. or set values in miqro.json file.");
661
+ process.exit(EXIT_CODES.BAD_ARGUMENTS);
662
+ }
663
+
551
664
  return {
552
665
  name: flags.name ? flags.name : undefined,
553
666
  browser: flags.browser !== null ? flags.browser : undefined,
@@ -571,6 +684,9 @@ export function parseArguments(): Arguments {
571
684
  generateDocOut: flags.generateDocOut ? resolve(process.cwd(), flags.generateDocOut) : generateDocType === "MD" ? resolve(process.cwd(), "API.md") : resolve(process.cwd(), "API.json"),
572
685
  generateDocType,
573
686
  services,
574
- editor: flags.editor ? true : false
687
+ editor: flags.editor ? true : false,
688
+ https: flags.https ? true : false,
689
+ httpsRedirect: flags.httpsRedirect ? flags.httpsRedirect : undefined,
690
+ serverOptions: flags.serverOptions
575
691
  }
576
692
  }
@@ -40,6 +40,10 @@ export const help = `
40
40
  --config\n\toverrides the default miqro.json path.
41
41
  --port\n\toverrides the default port from PORT.
42
42
  --name\n\toverrides the default name of the server.
43
+ --https\n\tserves the server in https instead of http
44
+ --https-key\n\tpoint to a server.key file for https.
45
+ --https-cert\n\tpoint to a server.cert file for https.
46
+ --https-redirect\n\tserves an aditional http server that redirects to https. it needs a port number.
43
47
 
44
48
  ==environment variables==
45
49
 
package/src/main.ts CHANGED
@@ -22,7 +22,10 @@ async function main(args: Arguments) {
22
22
  services: args.services,
23
23
  browser: args.browser,
24
24
  logFile: args.logFile,
25
- hotreload: args.test ? false : args.hotreload
25
+ hotreload: args.test ? false : args.hotreload,
26
+ https: args.test ? false : args.https,
27
+ serverOptions: args.serverOptions,
28
+ httpRedirect: args.test ? undefined : args.httpsRedirect
26
29
  });
27
30
  // check arguments
28
31
  if (args.generateDoc) {
@@ -31,6 +31,7 @@ import { createLogProviderOptions } from "./utils/log-transport.js";
31
31
  import { createAdminInterface } from "./utils/admin-interface.js";
32
32
  import { dirname, join, relative, resolve } from "node:path";
33
33
  import { cwd } from "node:process";
34
+ import { ServerOptions } from "node:https";
34
35
 
35
36
  export interface MiqroOptions {
36
37
  name: string;
@@ -42,6 +43,9 @@ export interface MiqroOptions {
42
43
  browser?: string | boolean;
43
44
  logFile?: string | boolean;
44
45
  hotreload?: boolean;
46
+ serverOptions?: ServerOptions<any, any>;
47
+ https?: boolean;
48
+ httpRedirect?: number;
45
49
  }
46
50
 
47
51
  export interface InflateOptions {
@@ -76,6 +80,7 @@ export class Miqro {
76
80
  public status: "stopped" | "starting" | "stopping" | "reloading" | "started" = "stopped";
77
81
  public options: MiqroOptions;
78
82
  public server?: App | null = null;
83
+ public httpsRedirectServer?: App | null = null;
79
84
  public cache: ClusterCache;
80
85
  public localCache: LocalCache;
81
86
  public webSocketManager: WebSocketManager;
@@ -424,6 +429,7 @@ export class Miqro {
424
429
  //this.disconnect();
425
430
  this.status = "starting";
426
431
  this.server = undefined;
432
+ this.httpsRedirectServer = undefined;
427
433
  this.connect();
428
434
  await this.dbManager.connectAll();
429
435
  this.server = new App({
@@ -431,8 +437,17 @@ export class Miqro {
431
437
  req.server = this.serverInterface;
432
438
  return this.webSocketManager.onUpgrade(req, socket, head);
433
439
  },
434
- loggerFactory: this.loggerProvider.requestLoggerFactory
440
+ loggerFactory: this.loggerProvider.requestLoggerFactory,
441
+ serverOptions: this.options?.serverOptions,
442
+ https: this.options?.https
435
443
  });
444
+ if (this.options?.httpRedirect) {
445
+ this.httpsRedirectServer = new App();
446
+ this.httpsRedirectServer.use(async (req: ServerRequest, res) => {
447
+ const hostname = req.headers.host.split(":").length > 1 ? req.headers.host.split(":")[0] : req.headers.host;
448
+ return await res.redirect('https://' + hostname + ":" + this.options.port + req.url);
449
+ });
450
+ }
436
451
 
437
452
  this.webSocketManager.replaceALLWS(this.inflated.wsConfigList);
438
453
 
@@ -455,11 +470,20 @@ export class Miqro {
455
470
  this.logger?.trace("calling listen on [%s]", this.options.port);
456
471
 
457
472
  await this.server.listen(this.options.port);
473
+ if (this.options?.httpRedirect) {
474
+ await this.httpsRedirectServer.listen(this.options.httpRedirect);
475
+ }
476
+
477
+ if (this.options?.httpRedirect && this.logger && (cluster.isPrimary || process.env["CLUSTER_NODE_NUMBER"] === "0")) {
478
+ this.logger?.log("\t\t==listening on [http][%s] for [https][%s] redirection==", this.options?.httpRedirect, this.options.port);
479
+ } else if (this.options?.httpRedirect) {
480
+ this.logger?.debug("\t\t==listening on [http][%s] for [https][%s] redirection==", this.options?.httpRedirect, this.options.port);
481
+ }
458
482
 
459
483
  if (this.logger && (cluster.isPrimary || process.env["CLUSTER_NODE_NUMBER"] === "0")) {
460
- this.logger?.log("\t\t==listening on [%s]==", this.options.port);
484
+ this.logger?.log("\t\t==listening on [%s][%s]==", this.options.https ? "https" : "http", this.options.port);
461
485
  } else {
462
- this.logger?.debug("\t\t==listening on [%s]==", this.options.port);
486
+ this.logger?.debug("\t\t==listening on [%s][%s]==", this.options.https ? "https" : "http", this.options.port);
463
487
  }
464
488
 
465
489
  await notifiyServerConfig(this.logger, this.serverInterface, this.adminInterface, this.inflated.serverConfigMap, "start");
@@ -484,7 +508,9 @@ export class Miqro {
484
508
  this.watcher = null;
485
509
  }
486
510
  const server = this.server;
511
+ const httpsRedirectServer = this.httpsRedirectServer;
487
512
  this.server = null;
513
+ this.httpsRedirectServer = null;
488
514
  this.disconnect();
489
515
  this.logger?.debug("\t\t==stop==");
490
516
  this.logger?.debug("clear running server routes");
@@ -495,6 +521,9 @@ export class Miqro {
495
521
  notifiyServerConfigSync(this, "unload");
496
522
  //server.ws.disconnectAll();
497
523
  this.logger?.debug("stopping");
524
+ if (httpsRedirectServer) {
525
+ await httpsRedirectServer.close();
526
+ }
498
527
  const p = server.close();
499
528
  await p;
500
529
  await pD;
@@ -26,6 +26,15 @@ export function createServerInterface(options: ServerInterfaceImplOptions): Serv
26
26
  cache: options.cache,
27
27
  localCache: options.localCache,
28
28
  logger: options.logger,
29
+ reload() {
30
+ return options?.app?.reload();
31
+ },
32
+ restart() {
33
+ return options?.app?.restart();
34
+ },
35
+ stop() {
36
+ return options?.app?.stop();
37
+ },
29
38
  db: {
30
39
  get(name) {
31
40
  return options.dbManager.getDB(name);
@@ -1,9 +1 @@
1
1
  import "./jsx.globals.js";
2
- import { RuntimeElementDefinitionOptions, Component } from "@miqro/jsx/esm/lib.js";
3
-
4
- declare global {
5
- // only available browser side
6
- var jsx: {
7
- define: (tagName: string, component: Component, options?: RuntimeElementDefinitionOptions) => void;
8
- }
9
- }
@@ -4,6 +4,7 @@ declare global {
4
4
  // jsx only for the default value of tsconfig.json
5
5
  var React: {};
6
6
  var jsx: {
7
+ define: (tagName: string, component: jsxLib.Component, options?: jsxLib.RuntimeElementDefinitionOptions) => void;
7
8
  useRuntime: typeof jsxLib.useRuntime;
8
9
  usePathname: typeof jsxLib.usePathname;
9
10
  Link: typeof jsxLib.Link;
@@ -206,6 +206,15 @@ export interface ServerInterface extends ServerGlobal{
206
206
  getWorkerCount: () => number;
207
207
  openBrowser: (path: string) => void;
208
208
  getLogger: (identifier: string, options?: { level?: any; transports?: any[]; formatter?: any; }) => Logger;
209
+ stop: () => Promise<void>;
210
+ reload: () => Promise<null | {
211
+ filePath: string;
212
+ error: Error;
213
+ }[]>;
214
+ restart: () => Promise<null | {
215
+ filePath: string;
216
+ error: Error;
217
+ }[]>;
209
218
  }
210
219
 
211
220
  export interface ServerRequest extends Request {
package/src/types.ts CHANGED
@@ -184,6 +184,15 @@ export interface ServerInterface extends ServerGlobal {
184
184
  logger?: Logger;
185
185
  openBrowser: (path: string) => void;
186
186
  getLogger: (identifier: string, options?: { level?: any; transports?: any[]; formatter?: any; }) => Logger;
187
+ stop: () => Promise<void>;
188
+ reload: () => Promise<null | {
189
+ filePath: string;
190
+ error: Error;
191
+ }[]>;
192
+ restart: () => Promise<null | {
193
+ filePath: string;
194
+ error: Error;
195
+ }[]>;
187
196
  }
188
197
 
189
198
  export interface ServerRequest extends Request {