miqro 6.1.4 → 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.
- package/build/editor.bundle.js +10 -2
- package/build/esm/editor/components/editor.js +8 -0
- package/build/esm/editor/components/file-editor.js +1 -1
- package/build/esm/editor/components/highlight-text-area.js +2 -1
- package/build/esm/src/common/arguments.d.ts +7 -0
- package/build/esm/src/common/arguments.js +103 -2
- package/build/esm/src/common/help.d.ts +1 -1
- package/build/esm/src/common/help.js +4 -0
- package/build/esm/src/common/jwt.d.ts +49 -0
- package/build/esm/src/common/jwt.js +76 -0
- package/build/esm/src/inflate/inflate-sea.js +9 -8
- package/build/esm/src/inflate/setup-http.d.ts +1 -0
- package/build/esm/src/inflate/setup-http.js +8 -0
- package/build/esm/src/lib.d.ts +1 -1
- package/build/esm/src/lib.js +2 -2
- package/build/esm/src/main.js +4 -1
- package/build/esm/src/services/app.d.ts +5 -0
- package/build/esm/src/services/app.js +33 -7
- package/build/esm/src/services/globals.js +45 -1
- package/build/esm/src/services/utils/cluster-ws.d.ts +4 -2
- package/build/esm/src/services/utils/cluster-ws.js +10 -1
- package/build/esm/src/services/utils/server-interface.d.ts +4 -30
- package/build/esm/src/services/utils/server-interface.js +53 -64
- package/build/esm/src/services/utils/websocketmanager.d.ts +3 -0
- package/build/esm/src/services/utils/websocketmanager.js +8 -2
- package/build/esm/src/types.d.ts +85 -5
- package/build/lib.cjs +3026 -367
- package/editor/components/editor.tsx +8 -0
- package/editor/components/file-editor.tsx +1 -1
- package/editor/components/highlight-text-area.tsx +2 -1
- package/package.json +5 -4
- package/sea/install-nodejs.sh +1 -1
- package/sea/node.version.tag +1 -1
- package/sea/types.json +1 -1
- package/src/common/arguments.ts +118 -2
- package/src/common/help.ts +4 -0
- package/src/common/jwt.ts +85 -0
- package/src/inflate/inflate-sea.ts +9 -8
- package/src/inflate/setup-http.ts +9 -0
- package/src/lib.ts +2 -2
- package/src/main.ts +4 -1
- package/src/services/app.ts +38 -7
- package/src/services/globals.ts +45 -2
- package/src/services/utils/cluster-ws.ts +6 -1
- package/src/services/utils/server-interface.ts +53 -140
- package/src/services/utils/websocketmanager.ts +10 -2
- package/src/types/browser.globals.d.ts +0 -8
- package/src/types/cookie.d.ts +2 -0
- package/src/types/jose.d.ts +2 -0
- package/src/types/jsx.globals.d.ts +1 -0
- package/src/types/miqro.d.ts +101 -2
- package/src/types/server.globals.d.ts +4 -29
- package/src/types.ts +87 -5
|
@@ -19,7 +19,7 @@ import { initAssets } from "../common/assets.js";
|
|
|
19
19
|
import { setupExitHandlers } from "../common/exit.js";
|
|
20
20
|
import { inflateDBConfig, inflateDBMigrations } from "../inflate/setup-db.js";
|
|
21
21
|
import { getServicePath } from "../common/paths.js";
|
|
22
|
-
import {
|
|
22
|
+
import { createServerInterface } from "./utils/server-interface.js";
|
|
23
23
|
import { getPORT, importMiqroJSON } from "../common/arguments.js";
|
|
24
24
|
import { createLogProviderOptions } from "./utils/log-transport.js";
|
|
25
25
|
import { createAdminInterface } from "./utils/admin-interface.js";
|
|
@@ -30,6 +30,7 @@ export class Miqro {
|
|
|
30
30
|
status = "stopped";
|
|
31
31
|
options;
|
|
32
32
|
server = null;
|
|
33
|
+
httpsRedirectServer = null;
|
|
33
34
|
cache;
|
|
34
35
|
localCache;
|
|
35
36
|
webSocketManager;
|
|
@@ -90,6 +91,7 @@ export class Miqro {
|
|
|
90
91
|
this.localCache = new LocalCache(`MiqroApplicationLocalCache[${this.options.name}]`, this.logger);
|
|
91
92
|
this.webSocketManager = new WebSocketManager({
|
|
92
93
|
logger: this.logger,
|
|
94
|
+
loggerProvider: this.loggerProvider,
|
|
93
95
|
name: `MiqroApplicationWebsocketManager[${this.options.name}]`,
|
|
94
96
|
avoidLogSocket: this.options.editor
|
|
95
97
|
});
|
|
@@ -100,11 +102,11 @@ export class Miqro {
|
|
|
100
102
|
loggerProvider: this.loggerProvider,
|
|
101
103
|
logger: this.logger
|
|
102
104
|
});
|
|
103
|
-
this.serverInterface =
|
|
105
|
+
this.serverInterface = createServerInterface({
|
|
104
106
|
cache: this.cache,
|
|
105
|
-
localCache: this.localCache,
|
|
106
107
|
dbManager: this.dbManager,
|
|
107
|
-
|
|
108
|
+
localCache: this.localCache,
|
|
109
|
+
webSocketManager: this.webSocketManager,
|
|
108
110
|
app: this,
|
|
109
111
|
logger: this.logger,
|
|
110
112
|
loggerProvider: this.loggerProvider,
|
|
@@ -342,6 +344,7 @@ export class Miqro {
|
|
|
342
344
|
//this.disconnect();
|
|
343
345
|
this.status = "starting";
|
|
344
346
|
this.server = undefined;
|
|
347
|
+
this.httpsRedirectServer = undefined;
|
|
345
348
|
this.connect();
|
|
346
349
|
await this.dbManager.connectAll();
|
|
347
350
|
this.server = new App({
|
|
@@ -349,8 +352,17 @@ export class Miqro {
|
|
|
349
352
|
req.server = this.serverInterface;
|
|
350
353
|
return this.webSocketManager.onUpgrade(req, socket, head);
|
|
351
354
|
},
|
|
352
|
-
loggerFactory: this.loggerProvider.requestLoggerFactory
|
|
355
|
+
loggerFactory: this.loggerProvider.requestLoggerFactory,
|
|
356
|
+
serverOptions: this.options?.serverOptions,
|
|
357
|
+
https: this.options?.https
|
|
353
358
|
});
|
|
359
|
+
if (this.options?.httpRedirect) {
|
|
360
|
+
this.httpsRedirectServer = new App();
|
|
361
|
+
this.httpsRedirectServer.use(async (req, res) => {
|
|
362
|
+
const hostname = req.headers.host.split(":").length > 1 ? req.headers.host.split(":")[0] : req.headers.host;
|
|
363
|
+
return await res.redirect('https://' + hostname + ":" + this.options.port + req.url);
|
|
364
|
+
});
|
|
365
|
+
}
|
|
354
366
|
this.webSocketManager.replaceALLWS(this.inflated.wsConfigList);
|
|
355
367
|
reloadInflatedRouter(this);
|
|
356
368
|
await notifiyServerConfig(this.logger, this.serverInterface, this.adminInterface, this.inflated.serverConfigMap, "load");
|
|
@@ -367,11 +379,20 @@ export class Miqro {
|
|
|
367
379
|
}
|
|
368
380
|
this.logger?.trace("calling listen on [%s]", this.options.port);
|
|
369
381
|
await this.server.listen(this.options.port);
|
|
382
|
+
if (this.options?.httpRedirect) {
|
|
383
|
+
await this.httpsRedirectServer.listen(this.options.httpRedirect);
|
|
384
|
+
}
|
|
385
|
+
if (this.options?.httpRedirect && this.logger && (cluster.isPrimary || process.env["CLUSTER_NODE_NUMBER"] === "0")) {
|
|
386
|
+
this.logger?.log("\t\t==listening on [http][%s] for [https][%s] redirection==", this.options?.httpRedirect, this.options.port);
|
|
387
|
+
}
|
|
388
|
+
else if (this.options?.httpRedirect) {
|
|
389
|
+
this.logger?.debug("\t\t==listening on [http][%s] for [https][%s] redirection==", this.options?.httpRedirect, this.options.port);
|
|
390
|
+
}
|
|
370
391
|
if (this.logger && (cluster.isPrimary || process.env["CLUSTER_NODE_NUMBER"] === "0")) {
|
|
371
|
-
this.logger?.log("\t\t==listening on [%s]==", this.options.port);
|
|
392
|
+
this.logger?.log("\t\t==listening on [%s][%s]==", this.options.https ? "https" : "http", this.options.port);
|
|
372
393
|
}
|
|
373
394
|
else {
|
|
374
|
-
this.logger?.debug("\t\t==listening on [%s]==", this.options.port);
|
|
395
|
+
this.logger?.debug("\t\t==listening on [%s][%s]==", this.options.https ? "https" : "http", this.options.port);
|
|
375
396
|
}
|
|
376
397
|
await notifiyServerConfig(this.logger, this.serverInterface, this.adminInterface, this.inflated.serverConfigMap, "start");
|
|
377
398
|
if (this.options.hotreload && (cluster.isPrimary || process.env["CLUSTER_NODE_NUMBER"] === "0")) {
|
|
@@ -391,7 +412,9 @@ export class Miqro {
|
|
|
391
412
|
this.watcher = null;
|
|
392
413
|
}
|
|
393
414
|
const server = this.server;
|
|
415
|
+
const httpsRedirectServer = this.httpsRedirectServer;
|
|
394
416
|
this.server = null;
|
|
417
|
+
this.httpsRedirectServer = null;
|
|
395
418
|
this.disconnect();
|
|
396
419
|
this.logger?.debug("\t\t==stop==");
|
|
397
420
|
this.logger?.debug("clear running server routes");
|
|
@@ -402,6 +425,9 @@ export class Miqro {
|
|
|
402
425
|
notifiyServerConfigSync(this, "unload");
|
|
403
426
|
//server.ws.disconnectAll();
|
|
404
427
|
this.logger?.debug("stopping");
|
|
428
|
+
if (httpsRedirectServer) {
|
|
429
|
+
await httpsRedirectServer.close();
|
|
430
|
+
}
|
|
405
431
|
const p = server.close();
|
|
406
432
|
await p;
|
|
407
433
|
await pD;
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
//@ts-ignore
|
|
2
2
|
import { ReadBuffer, URLEncodedParser, JSONParser, TextParser, CORS, SessionHandler } from "@miqro/core";
|
|
3
|
+
import cluster from "node:cluster";
|
|
3
4
|
import { strictEqual } from "node:assert";
|
|
4
5
|
import { HTMLEncode } from "@miqro/jsx-node";
|
|
5
6
|
import { createElement as realCreateElement, enableDebugLog, useRuntime, Link, Router, usePathname, Fragment, useEffect, useRef, useState, useQuery, useRefresh, useElement, createContext, useContext } from "@miqro/jsx";
|
|
6
7
|
import { jsx2HTML } from "../common/jsx.js";
|
|
7
8
|
import { inflateMD2HTML } from "../inflate/md.js";
|
|
8
9
|
import { EXIT_CODES } from "../common/constants.js";
|
|
10
|
+
import { ClusterCache, LocalCache } from "../lib.js";
|
|
11
|
+
import { decodeJWT, decodeProtectedHeaderJWT, decryptJWT, encryptJWT, signJWT, verifyJWT } from "../common/jwt.js";
|
|
12
|
+
import { createSecretKey } from "node:crypto";
|
|
13
|
+
import { Parser } from "@miqro/parser";
|
|
9
14
|
/*const globaljsx: any = Object.freeze({
|
|
10
15
|
useContext,
|
|
11
16
|
useRuntime,
|
|
@@ -80,7 +85,46 @@ const globalServer = Object.freeze({
|
|
|
80
85
|
session: SessionHandler
|
|
81
86
|
}),
|
|
82
87
|
encodeHTML: HTMLEncode,
|
|
83
|
-
inflateMDtoHTML: inflateMD2HTML
|
|
88
|
+
inflateMDtoHTML: inflateMD2HTML,
|
|
89
|
+
createSecretKey,
|
|
90
|
+
newParser() {
|
|
91
|
+
return new Parser();
|
|
92
|
+
},
|
|
93
|
+
newClusterCache(name, logger) {
|
|
94
|
+
return new ClusterCache(name, logger);
|
|
95
|
+
},
|
|
96
|
+
newLocalCache(name, logger) {
|
|
97
|
+
return new LocalCache(name, logger);
|
|
98
|
+
},
|
|
99
|
+
getWorkerNumber() {
|
|
100
|
+
return cluster.isPrimary || process.env["CLUSTER_NODE_NUMBER"] === undefined ? 0 : parseInt(process.env["CLUSTER_NODE_NUMBER"], 10);
|
|
101
|
+
},
|
|
102
|
+
getWorkerCount() {
|
|
103
|
+
return cluster.isPrimary || process.env["CLUSTER_NODE_NUMBER"] === undefined || process.env["CLUSTER_COUNT"] === undefined ? 1 : parseInt(process.env["CLUSTER_COUNT"], 10);
|
|
104
|
+
},
|
|
105
|
+
isPrimaryWorker() {
|
|
106
|
+
return cluster.isPrimary || process.env["CLUSTER_NODE_NUMBER"] === "0";
|
|
107
|
+
},
|
|
108
|
+
jwt: {
|
|
109
|
+
decode(jwt) {
|
|
110
|
+
return decodeJWT(jwt);
|
|
111
|
+
},
|
|
112
|
+
decodeProtectedHeader(token) {
|
|
113
|
+
return decodeProtectedHeaderJWT(token);
|
|
114
|
+
},
|
|
115
|
+
decrypt(jwt, secret, options) {
|
|
116
|
+
return decryptJWT(jwt, secret, options);
|
|
117
|
+
},
|
|
118
|
+
encrypt(payload, secret, options) {
|
|
119
|
+
return encryptJWT(payload, secret, options);
|
|
120
|
+
},
|
|
121
|
+
sign(payload, secret, options) {
|
|
122
|
+
return signJWT(payload, secret, options);
|
|
123
|
+
},
|
|
124
|
+
verify(jwt, secret, options) {
|
|
125
|
+
return verifyJWT(jwt, secret, options);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
84
128
|
});
|
|
85
129
|
export function browserJSXGlobals(inFile, jsxPath = false, useExport = true) {
|
|
86
130
|
const PRE = `import { enableDebugLog, useRuntime, Link, usePathname, createContext, useContext, useElement, useRefresh, useQuery, define, Router, useState, useEffect, useRef, createElement, Fragment } from "${jsxPath}";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WebSocketServer, WebSocketServerOptions } from "@miqro/core";
|
|
1
|
+
import { Logger, WebSocketServer, WebSocketServerOptions } from "@miqro/core";
|
|
2
2
|
import { Serializable } from "node:child_process";
|
|
3
3
|
declare const ClusterWebSocketServer2MessageType = "$$$$ClusterWebSocketServer2Message$$$$$";
|
|
4
4
|
export interface ClusterWebSocketServer2Message {
|
|
@@ -13,9 +13,11 @@ export interface ClusterWebSocketServer2Message {
|
|
|
13
13
|
}
|
|
14
14
|
export declare class ClusterWebSocketServer2 extends WebSocketServer {
|
|
15
15
|
protected name: string;
|
|
16
|
+
path: string;
|
|
17
|
+
logger: Logger | Console;
|
|
16
18
|
remoteClients: Set<string>;
|
|
17
19
|
listener: (data: any) => Promise<void>;
|
|
18
|
-
constructor(name: string, options: WebSocketServerOptions);
|
|
20
|
+
constructor(name: string, path: string, logger: Logger | Console, options: WebSocketServerOptions);
|
|
19
21
|
connect(): void;
|
|
20
22
|
dispose(): void;
|
|
21
23
|
broadcast(payload: string, fromUUID?: string): Promise<void>;
|
|
@@ -2,14 +2,17 @@ import { WebSocketServer } from "@miqro/core";
|
|
|
2
2
|
const ClusterWebSocketServer2MessageType = "$$$$ClusterWebSocketServer2Message$$$$$";
|
|
3
3
|
export class ClusterWebSocketServer2 extends WebSocketServer {
|
|
4
4
|
name;
|
|
5
|
+
path;
|
|
6
|
+
logger;
|
|
5
7
|
remoteClients = new Set();
|
|
6
8
|
listener;
|
|
7
|
-
constructor(name, options) {
|
|
9
|
+
constructor(name, path, logger, options) {
|
|
8
10
|
super({
|
|
9
11
|
...options,
|
|
10
12
|
validate: (req) => {
|
|
11
13
|
if (this.options.maxConnections !== undefined &&
|
|
12
14
|
this.clients.size + this.remoteClients.size >= this.options.maxConnections) {
|
|
15
|
+
this.logger?.warn("[%s] max web socket connection reached! connection refused from [%s]", req.uuid, req.socket.remoteAddress);
|
|
13
16
|
return false;
|
|
14
17
|
}
|
|
15
18
|
else {
|
|
@@ -27,6 +30,8 @@ export class ClusterWebSocketServer2 extends WebSocketServer {
|
|
|
27
30
|
errorMessage: error.message
|
|
28
31
|
});
|
|
29
32
|
}
|
|
33
|
+
this.logger?.error("[%s] error from (%s) error [%s]", req.uuid, req.req.socket.remoteAddress, error);
|
|
34
|
+
this.logger?.error(error);
|
|
30
35
|
if (options.onError) {
|
|
31
36
|
options.onError(req, error);
|
|
32
37
|
}
|
|
@@ -41,6 +46,7 @@ export class ClusterWebSocketServer2 extends WebSocketServer {
|
|
|
41
46
|
clientUUID: req.uuid
|
|
42
47
|
});
|
|
43
48
|
}
|
|
49
|
+
this.logger?.log("[%s] new web socket connection from (%s)", req.uuid, req.req.socket.remoteAddress);
|
|
44
50
|
if (options.onConnection) {
|
|
45
51
|
options.onConnection(req);
|
|
46
52
|
}
|
|
@@ -55,12 +61,15 @@ export class ClusterWebSocketServer2 extends WebSocketServer {
|
|
|
55
61
|
clientUUID: req.uuid
|
|
56
62
|
});
|
|
57
63
|
}
|
|
64
|
+
this.logger?.log("[%s] [%s] web socket disconnection from (%s)", req.uuid, this.path, req.req.socket.remoteAddress);
|
|
58
65
|
if (options.onDisconnect) {
|
|
59
66
|
options.onDisconnect(req);
|
|
60
67
|
}
|
|
61
68
|
}
|
|
62
69
|
});
|
|
63
70
|
this.name = name;
|
|
71
|
+
this.path = path;
|
|
72
|
+
this.logger = logger;
|
|
64
73
|
this.listener = async (data) => {
|
|
65
74
|
try {
|
|
66
75
|
const msg = data;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { CacheInterface, MigrateOptions, NamedMigration, ServerInterface } from "../../types.js";
|
|
1
|
+
import { Logger } from "@miqro/core";
|
|
2
|
+
import { CacheInterface, ServerInterface } from "../../types.js";
|
|
4
3
|
import { DBManager } from "./db-manager.js";
|
|
5
4
|
import { Miqro } from "../app.js";
|
|
6
5
|
import { WebSocketManager } from "./websocketmanager.js";
|
|
@@ -9,35 +8,10 @@ export interface ServerInterfaceImplOptions {
|
|
|
9
8
|
cache: CacheInterface;
|
|
10
9
|
localCache: CacheInterface;
|
|
11
10
|
dbManager: DBManager;
|
|
12
|
-
|
|
11
|
+
webSocketManager: WebSocketManager;
|
|
13
12
|
logger?: Logger;
|
|
14
13
|
app?: Miqro;
|
|
15
14
|
port?: string;
|
|
16
15
|
loggerProvider?: LogProvider;
|
|
17
16
|
}
|
|
18
|
-
export declare
|
|
19
|
-
cache: CacheInterface;
|
|
20
|
-
localCache: CacheInterface;
|
|
21
|
-
logger?: Logger;
|
|
22
|
-
port?: string;
|
|
23
|
-
db: {
|
|
24
|
-
get(name: string): Database | null;
|
|
25
|
-
getMigrations(): NamedMigration[];
|
|
26
|
-
migrate(options: MigrateOptions): Promise<void>;
|
|
27
|
-
};
|
|
28
|
-
ws: {
|
|
29
|
-
get(path: string): WebSocketServer | undefined;
|
|
30
|
-
disconnectAll(path: string): void;
|
|
31
|
-
};
|
|
32
|
-
loggerProvider?: LogProvider;
|
|
33
|
-
openBrowser: (path: string) => void;
|
|
34
|
-
constructor(options: ServerInterfaceImplOptions);
|
|
35
|
-
getWorkerNumber(): number;
|
|
36
|
-
getWorkerCount(): number;
|
|
37
|
-
isPrimaryWorker(): boolean;
|
|
38
|
-
getLogger(identifier: string, options?: {
|
|
39
|
-
level?: any;
|
|
40
|
-
transports?: any[];
|
|
41
|
-
formatter?: any;
|
|
42
|
-
}): Logger;
|
|
43
|
-
}
|
|
17
|
+
export declare function createServerInterface(options: ServerInterfaceImplOptions): ServerInterface;
|
|
@@ -1,49 +1,28 @@
|
|
|
1
|
-
import cluster from "node:cluster";
|
|
2
1
|
import { execSync } from "node:child_process";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const PORT = this.port;
|
|
23
|
-
const URL = `http://localhost${PORT ? `:${PORT}` : ""}${path}`;
|
|
24
|
-
const DEFAULT_OPEN = process.platform === "win32" ? "explorer" : process.platform === "darwin" ? "open" : "xdg-open";
|
|
25
|
-
const OPEN = app.options.browser !== undefined && String(app.options.browser).toUpperCase() !== "TRUE" && String(app.options.browser).toUpperCase() !== "1" ?
|
|
26
|
-
String(app.options.browser).toUpperCase() !== "0" && String(app.options.browser).toUpperCase() !== "FALSE" && String(app.options.browser).toUpperCase() !== "NONE" && app.options.browser ?
|
|
27
|
-
app.options.browser : false :
|
|
28
|
-
process.env["BROWSER"] ?
|
|
29
|
-
process.env["BROWSER"] === "none" ? false : process.env["BROWSER"] : DEFAULT_OPEN;
|
|
30
|
-
if (OPEN) {
|
|
31
|
-
const openCMD = `${OPEN} "${URL}"`;
|
|
32
|
-
this.logger?.info("opening browser with [%s]", openCMD);
|
|
33
|
-
execSync(openCMD);
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
this.logger?.warn("ignoring browser [%s]", OPEN);
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
this.db = Object.freeze({
|
|
40
|
-
get: (name) => {
|
|
41
|
-
return dbManager.getDB(name);
|
|
2
|
+
import { initGlobals } from "../globals.js";
|
|
3
|
+
export function createServerInterface(options) {
|
|
4
|
+
initGlobals();
|
|
5
|
+
return Object.freeze({
|
|
6
|
+
cache: options.cache,
|
|
7
|
+
localCache: options.localCache,
|
|
8
|
+
logger: options.logger,
|
|
9
|
+
reload() {
|
|
10
|
+
return options?.app?.reload();
|
|
11
|
+
},
|
|
12
|
+
restart() {
|
|
13
|
+
return options?.app?.restart();
|
|
14
|
+
},
|
|
15
|
+
stop() {
|
|
16
|
+
return options?.app?.stop();
|
|
17
|
+
},
|
|
18
|
+
db: {
|
|
19
|
+
get(name) {
|
|
20
|
+
return options.dbManager.getDB(name);
|
|
42
21
|
},
|
|
43
|
-
getMigrations
|
|
44
|
-
if (app?.inflated) {
|
|
22
|
+
getMigrations() {
|
|
23
|
+
if (options.app?.inflated) {
|
|
45
24
|
const ret = [];
|
|
46
|
-
for (const d of app?.inflated.dbList) {
|
|
25
|
+
for (const d of options.app?.inflated.dbList) {
|
|
47
26
|
ret.push(...(d.migrations.map(m => {
|
|
48
27
|
return {
|
|
49
28
|
name: m.name,
|
|
@@ -56,29 +35,39 @@ export class ServerInterfaceImpl {
|
|
|
56
35
|
}
|
|
57
36
|
return [];
|
|
58
37
|
},
|
|
59
|
-
migrate
|
|
60
|
-
return app?.migrate(
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
38
|
+
migrate(migrateOptions) {
|
|
39
|
+
return options?.app?.migrate(migrateOptions);
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
ws: {
|
|
64
43
|
get: (name) => {
|
|
65
|
-
return
|
|
44
|
+
return options?.webSocketManager?.getWS(name);
|
|
66
45
|
},
|
|
67
46
|
disconnectAll: (path) => {
|
|
68
|
-
return
|
|
47
|
+
return options?.webSocketManager?.disconnectAllButLOGSocket();
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
openBrowser(path) {
|
|
51
|
+
const PORT = options.port;
|
|
52
|
+
const URL = `http://localhost${PORT ? `:${PORT}` : ""}${path}`;
|
|
53
|
+
const DEFAULT_OPEN = process.platform === "win32" ? "explorer" : process.platform === "darwin" ? "open" : "xdg-open";
|
|
54
|
+
const OPEN = options?.app?.options.browser !== undefined && String(options?.app?.options.browser).toUpperCase() !== "TRUE" && String(options?.app?.options.browser).toUpperCase() !== "1" ?
|
|
55
|
+
String(options?.app.options.browser).toUpperCase() !== "0" && String(options?.app?.options.browser).toUpperCase() !== "FALSE" && String(options?.app?.options.browser).toUpperCase() !== "NONE" && options?.app?.options.browser ?
|
|
56
|
+
options?.app.options.browser : false :
|
|
57
|
+
process.env["BROWSER"] ?
|
|
58
|
+
process.env["BROWSER"] === "none" ? false : process.env["BROWSER"] : DEFAULT_OPEN;
|
|
59
|
+
if (OPEN) {
|
|
60
|
+
const openCMD = `${OPEN} "${URL}"`;
|
|
61
|
+
options?.logger?.info("opening browser with [%s]", openCMD);
|
|
62
|
+
execSync(openCMD);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
options?.logger?.warn("ignoring browser [%s]", OPEN);
|
|
69
66
|
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return cluster.isPrimary || process.env["CLUSTER_NODE_NUMBER"] === undefined || process.env["CLUSTER_COUNT"] === undefined ? 1 : parseInt(process.env["CLUSTER_COUNT"], 10);
|
|
77
|
-
}
|
|
78
|
-
isPrimaryWorker() {
|
|
79
|
-
return cluster.isPrimary || process.env["CLUSTER_NODE_NUMBER"] === "0";
|
|
80
|
-
}
|
|
81
|
-
getLogger(identifier, options) {
|
|
82
|
-
return this.loggerProvider?.getLogger(identifier, options);
|
|
83
|
-
}
|
|
67
|
+
},
|
|
68
|
+
getLogger(identifier, loggerOptions) {
|
|
69
|
+
return options?.loggerProvider?.getLogger(identifier, loggerOptions);
|
|
70
|
+
},
|
|
71
|
+
...server
|
|
72
|
+
});
|
|
84
73
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Logger } from "@miqro/core";
|
|
2
2
|
import { ClusterWebSocketServer2 } from "./cluster-ws.js";
|
|
3
3
|
import { WSConfig } from "../../types.js";
|
|
4
|
+
import { LogProvider } from "./log.js";
|
|
4
5
|
export interface WebSocketManagerOptions {
|
|
5
6
|
logger?: Logger | Console;
|
|
7
|
+
loggerProvider?: LogProvider;
|
|
6
8
|
name?: string;
|
|
7
9
|
avoidLogSocket?: boolean;
|
|
8
10
|
}
|
|
@@ -11,6 +13,7 @@ export declare class WebSocketManager {
|
|
|
11
13
|
logger?: Logger | Console | null;
|
|
12
14
|
name: string;
|
|
13
15
|
avoidLogSocket: boolean;
|
|
16
|
+
loggerProvider: LogProvider;
|
|
14
17
|
constructor(options?: WebSocketManagerOptions);
|
|
15
18
|
deleteWS(path: string): void;
|
|
16
19
|
deleteAllWS(): void;
|
|
@@ -5,10 +5,12 @@ export class WebSocketManager {
|
|
|
5
5
|
logger = null;
|
|
6
6
|
name;
|
|
7
7
|
avoidLogSocket;
|
|
8
|
+
loggerProvider;
|
|
8
9
|
constructor(options) {
|
|
9
10
|
this.onUpgrade = this.onUpgrade.bind(this);
|
|
10
11
|
this.logger = options && options.logger ? options.logger : null;
|
|
11
12
|
this.name = options && options.name ? options.name : "WebSocketManager";
|
|
13
|
+
this.loggerProvider = options.loggerProvider;
|
|
12
14
|
this.avoidLogSocket = options && options.avoidLogSocket ? options.avoidLogSocket : false;
|
|
13
15
|
}
|
|
14
16
|
deleteWS(path) {
|
|
@@ -33,7 +35,9 @@ export class WebSocketManager {
|
|
|
33
35
|
throw new Error(`ws on path ${wsConfig.path} already setup!`);
|
|
34
36
|
}
|
|
35
37
|
this.logger?.debug("setting up websocket on [%s]", wsConfig.path);
|
|
36
|
-
const
|
|
38
|
+
const identifier = wsConfig.path.replaceAll("/", "_").toUpperCase();
|
|
39
|
+
const logger = this.loggerProvider && identifier.length >= 0 ? this.loggerProvider.getLogger(identifier.substring(identifier.charAt(0) === "_" ? 1 : 0)) : this.logger;
|
|
40
|
+
const server = new ClusterWebSocketServer2(this.name + wsConfig.path, wsConfig.path, logger, wsConfig);
|
|
37
41
|
this.runningGlobalWSMap.set(wsConfig.path, server);
|
|
38
42
|
}
|
|
39
43
|
}
|
|
@@ -51,7 +55,9 @@ export class WebSocketManager {
|
|
|
51
55
|
throw new Error(`ws on path ${wsConfig.path} already setup!`);
|
|
52
56
|
}
|
|
53
57
|
this.logger?.debug("setting up websocket on [%s]", wsConfig.path);
|
|
54
|
-
const
|
|
58
|
+
const identifier = wsConfig.path.replaceAll("/", "_").toUpperCase();
|
|
59
|
+
const logger = this.loggerProvider && identifier.length >= 0 ? this.loggerProvider.getLogger(identifier.substring(identifier.charAt(0) === "_" ? 1 : 0)) : this.logger;
|
|
60
|
+
const server = new ClusterWebSocketServer2(this.name + wsConfig.path, wsConfig.path, logger, wsConfig);
|
|
55
61
|
this.runningGlobalWSMap.set(wsConfig.path, server);
|
|
56
62
|
}
|
|
57
63
|
}
|
package/build/esm/src/types.d.ts
CHANGED
|
@@ -1,10 +1,29 @@
|
|
|
1
1
|
import { Database } from "@miqro/query";
|
|
2
2
|
import { WebSocketServerOptions, SessionHandlerOptions, Logger, WebSocketServer, ReadBuffer, URLEncodedParser, JSONParser, TextParser, CORS, SessionHandler, RouteOptions, Handler, Request, Response, LogLevel, LoggerTransportWriteArgs, CORSOptions, HandlerWithOptions, ErrorHandler } from "@miqro/core";
|
|
3
3
|
import { request } from "@miqro/request";
|
|
4
|
-
import { ParserInterface } from "@miqro/parser";
|
|
4
|
+
import { Parser, ParserInterface } from "@miqro/parser";
|
|
5
5
|
import { RuntimeHTMLElement, Runtime, RuntimeContainer, RuntimeURL, RuntimeOptions, RuntimeShadowRootInit } from "@miqro/jsx";
|
|
6
6
|
import { RuntimeElementDefinitionOptions, Component, createElement, Fragment, enableDebugLog } from "@miqro/jsx";
|
|
7
7
|
import * as jsxLib from "@miqro/jsx";
|
|
8
|
+
import { EncryptOptions, JWTDecryptOptions, JWTDecryptResult, JWTPayload, JWTVerifyOptions, JWTVerifyResult, ProtectedHeaderParameters, SignOptions } from "jose";
|
|
9
|
+
import { KeyObject } from "node:crypto";
|
|
10
|
+
export interface EncryptJWTOptions {
|
|
11
|
+
alg?: string;
|
|
12
|
+
enc?: string;
|
|
13
|
+
iat?: number | string | Date;
|
|
14
|
+
iss?: string;
|
|
15
|
+
aud?: string;
|
|
16
|
+
exp?: number | string | Date;
|
|
17
|
+
options?: EncryptOptions;
|
|
18
|
+
}
|
|
19
|
+
export interface JWTSignOptions {
|
|
20
|
+
alg?: string;
|
|
21
|
+
iat?: number | string | Date;
|
|
22
|
+
iss?: string;
|
|
23
|
+
aud?: string;
|
|
24
|
+
exp?: number | string | Date;
|
|
25
|
+
options?: SignOptions;
|
|
26
|
+
}
|
|
8
27
|
declare global {
|
|
9
28
|
var JSX: {
|
|
10
29
|
createElement: typeof createElement;
|
|
@@ -42,6 +61,61 @@ export interface ServerGlobal {
|
|
|
42
61
|
cors: typeof CORS;
|
|
43
62
|
session: typeof SessionHandler;
|
|
44
63
|
};
|
|
64
|
+
newParser(): Parser;
|
|
65
|
+
newClusterCache: (name: string, logger?: Logger) => CacheInterface;
|
|
66
|
+
newLocalCache: (name: string, logger?: Logger) => CacheInterface;
|
|
67
|
+
createSecretKey: (key: string, encoding: BufferEncoding) => KeyObject;
|
|
68
|
+
getWorkerCount: () => number;
|
|
69
|
+
getWorkerNumber: () => number;
|
|
70
|
+
isPrimaryWorker: () => boolean;
|
|
71
|
+
jwt: {
|
|
72
|
+
/**
|
|
73
|
+
* creates a JWT encrypted token with jose
|
|
74
|
+
*
|
|
75
|
+
* @param payload the payload to encrypt
|
|
76
|
+
* @param secret the secret example. const secret = createSecretKey(process.env.JWT_SECRET, 'utf-8');
|
|
77
|
+
* @param options options like expiratation date, issuer and audience
|
|
78
|
+
* @returns
|
|
79
|
+
*/
|
|
80
|
+
encrypt: (payload: JWTPayload, secret: KeyObject, options?: Partial<EncryptJWTOptions>) => Promise<string>;
|
|
81
|
+
/**
|
|
82
|
+
* decrypts a JWT token with jose
|
|
83
|
+
* @param jwt the JWT token
|
|
84
|
+
* @param secret the secret example. const secret = createSecretKey(process.env.JWT_SECRET, 'utf-8');
|
|
85
|
+
* @param options options like issuer and audience
|
|
86
|
+
* @returns
|
|
87
|
+
*/
|
|
88
|
+
decrypt: <PayloadType = JWTPayload>(jwt: string, secret: KeyObject, options?: Partial<JWTDecryptOptions>) => Promise<JWTDecryptResult<PayloadType>>;
|
|
89
|
+
/**
|
|
90
|
+
* verify a JWT token with jose
|
|
91
|
+
* @param jwt the JWT token
|
|
92
|
+
* @param secret the secret example. const secret = createSecretKey(process.env.JWT_SECRET, 'utf-8');
|
|
93
|
+
* @param options options like issuer and audience
|
|
94
|
+
* @returns
|
|
95
|
+
*/
|
|
96
|
+
verify: <PayloadType = JWTPayload>(jwt: string, secret: KeyObject, options?: Partial<JWTVerifyOptions>) => Promise<JWTVerifyResult<PayloadType>>;
|
|
97
|
+
/**
|
|
98
|
+
* creates a signed JWT with jose
|
|
99
|
+
*
|
|
100
|
+
* @param payload the payload to encrypt
|
|
101
|
+
* @param secret the secret example. const secret = createSecretKey(process.env.JWT_SECRET, 'utf-8');
|
|
102
|
+
* @param options options like expiratation date, issuer and audience
|
|
103
|
+
* @returns
|
|
104
|
+
*/
|
|
105
|
+
sign: (payload: JWTPayload, secret: KeyObject, options?: Partial<JWTSignOptions>) => Promise<string>;
|
|
106
|
+
/**
|
|
107
|
+
* decodes a protected header with jose
|
|
108
|
+
* @param token
|
|
109
|
+
* @returns
|
|
110
|
+
*/
|
|
111
|
+
decodeProtectedHeader: (token: string | object) => ProtectedHeaderParameters;
|
|
112
|
+
/**
|
|
113
|
+
* decodes a jwt token
|
|
114
|
+
* @param jwt
|
|
115
|
+
* @returns
|
|
116
|
+
*/
|
|
117
|
+
decode: <PayloadType = JWTPayload>(jwt: string) => PayloadType & JWTPayload;
|
|
118
|
+
};
|
|
45
119
|
}
|
|
46
120
|
export interface CacheInterface {
|
|
47
121
|
get<T = any>(key: string): T | undefined;
|
|
@@ -72,7 +146,7 @@ export interface LogConfig {
|
|
|
72
146
|
replaceFileTransport?: boolean;
|
|
73
147
|
write: (args: LoggerTransportWriteArgs) => Promise<void> | void;
|
|
74
148
|
}
|
|
75
|
-
export interface ServerInterface {
|
|
149
|
+
export interface ServerInterface extends ServerGlobal {
|
|
76
150
|
db: {
|
|
77
151
|
get(name: string): Database | null;
|
|
78
152
|
getMigrations(): NamedMigration[];
|
|
@@ -85,15 +159,21 @@ export interface ServerInterface {
|
|
|
85
159
|
cache: CacheInterface;
|
|
86
160
|
localCache: CacheInterface;
|
|
87
161
|
logger?: Logger;
|
|
88
|
-
isPrimaryWorker: () => boolean;
|
|
89
|
-
getWorkerNumber: () => number;
|
|
90
|
-
getWorkerCount: () => number;
|
|
91
162
|
openBrowser: (path: string) => void;
|
|
92
163
|
getLogger: (identifier: string, options?: {
|
|
93
164
|
level?: any;
|
|
94
165
|
transports?: any[];
|
|
95
166
|
formatter?: any;
|
|
96
167
|
}) => Logger;
|
|
168
|
+
stop: () => Promise<void>;
|
|
169
|
+
reload: () => Promise<null | {
|
|
170
|
+
filePath: string;
|
|
171
|
+
error: Error;
|
|
172
|
+
}[]>;
|
|
173
|
+
restart: () => Promise<null | {
|
|
174
|
+
filePath: string;
|
|
175
|
+
error: Error;
|
|
176
|
+
}[]>;
|
|
97
177
|
}
|
|
98
178
|
export interface ServerRequest extends Request {
|
|
99
179
|
server?: ServerInterface;
|