miqro 7.0.1 → 7.0.2

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 (145) hide show
  1. package/build/esm/editor/auth.d.ts +6 -0
  2. package/build/esm/editor/auth.js +41 -0
  3. package/build/esm/editor/common/admin-interface.d.ts +36 -0
  4. package/build/esm/editor/common/admin-interface.js +44 -0
  5. package/build/esm/editor/common/constants.d.ts +4 -0
  6. package/build/esm/editor/common/constants.js +20 -0
  7. package/build/esm/editor/common/constants.server.d.ts +2 -0
  8. package/build/esm/editor/common/constants.server.js +4 -0
  9. package/build/esm/editor/common/editor-index.d.ts +2 -0
  10. package/build/esm/editor/common/editor-index.js +14 -0
  11. package/build/esm/editor/common/html-encode.d.ts +1 -0
  12. package/build/esm/editor/common/html-encode.js +14 -0
  13. package/build/esm/editor/common/log-socket.d.ts +15 -0
  14. package/build/esm/editor/common/log-socket.js +71 -0
  15. package/build/esm/editor/common/templates.d.ts +11 -0
  16. package/build/esm/editor/common/templates.js +477 -0
  17. package/build/esm/editor/components/api-preview.d.ts +11 -0
  18. package/build/esm/editor/components/api-preview.js +92 -0
  19. package/build/esm/editor/components/editor.d.ts +16 -0
  20. package/build/esm/editor/components/editor.js +367 -0
  21. package/build/esm/editor/components/file-browser.d.ts +37 -0
  22. package/build/esm/editor/components/file-browser.js +127 -0
  23. package/build/esm/editor/components/file-editor-toolbar.d.ts +22 -0
  24. package/build/esm/editor/components/file-editor-toolbar.js +95 -0
  25. package/build/esm/editor/components/file-editor.d.ts +32 -0
  26. package/build/esm/editor/components/file-editor.js +61 -0
  27. package/build/esm/editor/components/filter-query.d.ts +1 -0
  28. package/build/esm/editor/components/filter-query.js +23 -0
  29. package/build/esm/editor/components/highlight-text-area.d.ts +11 -0
  30. package/build/esm/editor/components/highlight-text-area.js +127 -0
  31. package/build/esm/editor/components/log-viewer.d.ts +6 -0
  32. package/build/esm/editor/components/log-viewer.js +71 -0
  33. package/build/esm/editor/components/new-file.d.ts +10 -0
  34. package/build/esm/editor/components/new-file.js +119 -0
  35. package/build/esm/editor/components/scroll-query.d.ts +7 -0
  36. package/build/esm/editor/components/scroll-query.js +22 -0
  37. package/build/esm/editor/components/start-page.d.ts +13 -0
  38. package/build/esm/editor/components/start-page.js +32 -0
  39. package/build/esm/editor/http/admin/editor/api/fs/delete.api.d.ts +3 -0
  40. package/build/esm/editor/http/admin/editor/api/fs/delete.api.js +30 -0
  41. package/build/esm/editor/http/admin/editor/api/fs/read.api.d.ts +5 -0
  42. package/build/esm/editor/http/admin/editor/api/fs/read.api.js +50 -0
  43. package/build/esm/editor/http/admin/editor/api/fs/rename.api.d.ts +4 -0
  44. package/build/esm/editor/http/admin/editor/api/fs/rename.api.js +40 -0
  45. package/build/esm/editor/http/admin/editor/api/fs/scan.api.d.ts +26 -0
  46. package/build/esm/editor/http/admin/editor/api/fs/scan.api.js +150 -0
  47. package/build/esm/editor/http/admin/editor/api/fs/write.api.d.ts +3 -0
  48. package/build/esm/editor/http/admin/editor/api/fs/write.api.js +39 -0
  49. package/build/esm/editor/http/admin/editor/api/server/reload.api.d.ts +10 -0
  50. package/build/esm/editor/http/admin/editor/api/server/reload.api.js +46 -0
  51. package/build/esm/editor/http/admin/editor/api/server/restart.api.d.ts +10 -0
  52. package/build/esm/editor/http/admin/editor/api/server/restart.api.js +46 -0
  53. package/build/esm/editor/http/admin/editor/editor.d.ts +1 -0
  54. package/build/esm/editor/http/admin/editor/editor.js +8 -0
  55. package/build/esm/editor/http/admin/editor/index.api.d.ts +3 -0
  56. package/build/esm/editor/http/admin/editor/index.api.js +22 -0
  57. package/build/esm/editor/server.d.ts +3 -0
  58. package/build/esm/editor/server.js +49 -0
  59. package/build/esm/editor/ws.d.ts +3 -0
  60. package/build/esm/editor/ws.js +11 -0
  61. package/editor/auth.ts +51 -0
  62. package/editor/common/admin-interface.ts +84 -0
  63. package/editor/common/constants.server.ts +5 -0
  64. package/editor/common/constants.ts +21 -0
  65. package/editor/common/editor-index.tsx +17 -0
  66. package/editor/common/html-encode.ts +14 -0
  67. package/editor/common/log-socket.tsx +87 -0
  68. package/editor/common/templates.ts +481 -0
  69. package/editor/components/api-preview.tsx +118 -0
  70. package/editor/components/editor.tsx +496 -0
  71. package/editor/components/file-browser.tsx +311 -0
  72. package/editor/components/file-editor-toolbar.tsx +194 -0
  73. package/editor/components/file-editor.tsx +125 -0
  74. package/editor/components/filter-query.tsx +26 -0
  75. package/editor/components/highlight-text-area.tsx +148 -0
  76. package/editor/components/log-viewer.tsx +113 -0
  77. package/editor/components/new-file.tsx +172 -0
  78. package/editor/components/scroll-query.tsx +25 -0
  79. package/editor/components/start-page.tsx +52 -0
  80. package/editor/http/admin/editor/api/fs/delete.api.tsx +32 -0
  81. package/editor/http/admin/editor/api/fs/read.api.tsx +55 -0
  82. package/editor/http/admin/editor/api/fs/rename.api.tsx +41 -0
  83. package/editor/http/admin/editor/api/fs/scan.api.tsx +181 -0
  84. package/editor/http/admin/editor/api/fs/write.api.tsx +41 -0
  85. package/editor/http/admin/editor/api/server/reload.api.ts +53 -0
  86. package/editor/http/admin/editor/api/server/restart.api.tsx +52 -0
  87. package/editor/http/admin/editor/editor.tsx +10 -0
  88. package/editor/http/admin/editor/index.api.tsx +42 -0
  89. package/editor/server.ts +57 -0
  90. package/editor/ws.ts +15 -0
  91. package/package.json +1 -1
  92. package/src/bin/compile.ts +35 -0
  93. package/src/bin/doc-md.ts +210 -0
  94. package/src/bin/generate-doc.ts +64 -0
  95. package/src/bin/test.ts +92 -0
  96. package/src/bin/types.ts +34 -0
  97. package/src/cluster.ts +27 -0
  98. package/src/common/arguments.ts +762 -0
  99. package/src/common/assets.ts +148 -0
  100. package/src/common/checksum.ts +58 -0
  101. package/src/common/constants.ts +18 -0
  102. package/src/common/content-type.ts +84 -0
  103. package/src/common/esbuild.ts +102 -0
  104. package/src/common/exit.ts +91 -0
  105. package/src/common/fs.ts +82 -0
  106. package/src/common/help.ts +60 -0
  107. package/src/common/jsx.ts +562 -0
  108. package/src/common/jwt.ts +85 -0
  109. package/src/common/paths.ts +107 -0
  110. package/src/common/watch.ts +88 -0
  111. package/src/inflate/inflate-sea.ts +237 -0
  112. package/src/inflate/inflate.ts +101 -0
  113. package/src/inflate/md.ts +25 -0
  114. package/src/inflate/setup-auth.ts +41 -0
  115. package/src/inflate/setup-cors.ts +41 -0
  116. package/src/inflate/setup-db.ts +117 -0
  117. package/src/inflate/setup-error.ts +44 -0
  118. package/src/inflate/setup-http.ts +704 -0
  119. package/src/inflate/setup-log.ts +45 -0
  120. package/src/inflate/setup-middleware.ts +47 -0
  121. package/src/inflate/setup-server-config.ts +48 -0
  122. package/src/inflate/setup-test.ts +23 -0
  123. package/src/inflate/setup-ws.ts +50 -0
  124. package/src/inflate/setup.doc.ts +92 -0
  125. package/src/inflate/utils/sea-utils.ts +14 -0
  126. package/src/lib.ts +34 -0
  127. package/src/main.ts +101 -0
  128. package/src/services/app.ts +699 -0
  129. package/src/services/editor.tsx +101 -0
  130. package/src/services/globals.ts.ignore +186 -0
  131. package/src/services/hot-reload.ts +51 -0
  132. package/src/services/migrations.ts +68 -0
  133. package/src/services/utils/admin-interface.ts +37 -0
  134. package/src/services/utils/cache.ts +88 -0
  135. package/src/services/utils/cluster-cache.ts +230 -0
  136. package/src/services/utils/cluster-ws.ts +202 -0
  137. package/src/services/utils/db-manager.ts +92 -0
  138. package/src/services/utils/get-route.ts +70 -0
  139. package/src/services/utils/jwt.ts +25 -0
  140. package/src/services/utils/log-transport.ts +81 -0
  141. package/src/services/utils/log.ts +92 -0
  142. package/src/services/utils/middleware.ts +10 -0
  143. package/src/services/utils/server-interface.ts +122 -0
  144. package/src/services/utils/websocketmanager.ts +157 -0
  145. package/src/types.ts +307 -0
@@ -0,0 +1,92 @@
1
+ import { ConsoleTransport, getEnvVariable, Logger, LoggerTransport, MinimalLogger, newURL, normalizePath, Request, WriteArgs } from "@miqro/core";
2
+ import { format } from "node:util";
3
+
4
+ const DEFAULT_ENV_NAME = "LOG_LEVEL";
5
+
6
+ export interface LogProviderOptions {
7
+ name?: string;
8
+ transports: LoggerTransport[];
9
+ formatter: (args: WriteArgs) => string;
10
+ }
11
+
12
+ export const DEFAULT_FORMATTER = ({ identifier, level, message, optionalParams }: WriteArgs) => format(`${new Date().toISOString()} PID[${process.pid}] ` +
13
+ `${identifier ? `[${identifier}] ` : ""}` +
14
+ `${level !== "info" ? (level === "error" || level === "warn" ? `[${level.toUpperCase()}] ` : `[${level}] `) : ""}` +
15
+ `${message}`, ...optionalParams)
16
+
17
+ export class LogProvider {
18
+
19
+ public options: LogProviderOptions;
20
+ public constructor(options?: LogProviderOptions) {
21
+ this.options = {
22
+ formatter: options && options.formatter ? options.formatter : DEFAULT_FORMATTER,
23
+ transports: options && options.transports ? options.transports : [ConsoleTransport()],
24
+ name: options?.name
25
+ };
26
+ this.requestLoggerFactory = this.requestLoggerFactory.bind(this);
27
+ }
28
+
29
+ public requestLoggerFactory(uuid: string, req: Request): MinimalLogger {
30
+ let path = "";
31
+ let query = "";
32
+ let urlParsingError;
33
+ let method = "GET";
34
+ let remoteAddress: string | undefined = "";
35
+ try {
36
+ const url = newURL(req.url ? req.url : "/") as URL;
37
+ query = url.searchParams.toString();
38
+ path = normalizePath(url.pathname); // normalized path
39
+ method = req.method ? req.method.toUpperCase() as string : "GET";
40
+ remoteAddress = req.socket.remoteAddress;
41
+ } catch (e) {
42
+ urlParsingError = e;
43
+ }
44
+ const pathToEnv = path.replace(/\//ig, "_").replace(/\./ig, "_").replace(/-/ig, "_").toUpperCase();
45
+ const WORKER_IDENTIFIER = process.env["CLUSTER_NODE_NUMBER"] ? `WORKER_${process.env["CLUSTER_NODE_NUMBER"]}_` : "";
46
+ const identifier = `${pathToEnv === "_" ? "" : `${pathToEnv.substring(1)}`}${pathToEnv.charAt(pathToEnv.length - 1) !== "_" ? "_" : ""}${method.toUpperCase()}`;
47
+ const upgrade = req.headers.connection?.indexOf("Upgrade") !== -1;
48
+
49
+ const logger = this.getLogger(
50
+ `${WORKER_IDENTIFIER}${identifier}`, {
51
+ formatter: (args: WriteArgs) => {
52
+ args.message = `%s${upgrade ? " UPGRADE" : ""} %s%s [%s] (%s) ${args.message}`;
53
+ args.optionalParams = [method, path, query ? `?${query}` : "", uuid, remoteAddress].concat(args.optionalParams);
54
+ args.meta.push(req);
55
+ args.meta.push(uuid);
56
+ return this.options.formatter(args);
57
+ }
58
+ });
59
+
60
+
61
+ if (urlParsingError) {
62
+ logger.error(urlParsingError);
63
+ }
64
+
65
+ return logger;
66
+ };
67
+
68
+ public getLogger(identifier: string, options?: { level?: any; transports?: any[]; formatter?: any; }): Logger {
69
+
70
+ identifier = this.options.name ?
71
+ `${this.options.name}${identifier ?
72
+ `_${identifier}` : ""}`.toUpperCase() :
73
+ identifier ? identifier.toUpperCase() : "";
74
+
75
+ const envVarName = `LOG_LEVEL_${identifier}`;
76
+ const level = options && options.level ? options.level : getEnvVariable(envVarName) ? getEnvVariable(envVarName) : getEnvVariable(DEFAULT_ENV_NAME, "info");
77
+
78
+ const logger = new Logger(identifier, level, {
79
+ transports: [],
80
+ formatter: options && options.formatter ? options.formatter : this.options.formatter
81
+ });
82
+ for (const t of this.options.transports) {
83
+ logger.addTransport(t);
84
+ }
85
+ if (options && options.transports) {
86
+ for (const t of options.transports) {
87
+ logger.addTransport(t);
88
+ }
89
+ }
90
+ return logger;
91
+ }
92
+ }
@@ -0,0 +1,10 @@
1
+ import { CORS, JSONParser, ReadBuffer, SessionHandler, TextParser, URLEncodedParser } from "@miqro/core";
2
+
3
+ export const middleware = Object.freeze({
4
+ buffer: ReadBuffer,
5
+ url: URLEncodedParser,
6
+ json: JSONParser,
7
+ text: TextParser,
8
+ cors: CORS,
9
+ session: SessionHandler
10
+ });
@@ -0,0 +1,122 @@
1
+ import { Logger } from "@miqro/core";
2
+ import cluster from "node:cluster";
3
+ import { CacheInterface, NamedMigration, ServerInterface } from "../../types.js";
4
+ import { DBManager } from "./db-manager.js";
5
+ import { Miqro } from "../app.js";
6
+ import { WebSocketManager } from "./websocketmanager.js";
7
+ import { execSync } from "node:child_process";
8
+ import { LogProvider } from "./log.js";
9
+ import { HTMLEncode } from "../../../editor/common/html-encode.js";
10
+ import { inflateMD2HTML } from "../../inflate/md.js";
11
+
12
+ import { Parser } from "@miqro/parser";
13
+ import { ClusterCache } from "./cluster-cache.js";
14
+ import { LocalCache } from "./cache.js";
15
+ import { middleware } from "./middleware.js";
16
+ import { jwt } from "./jwt.js";
17
+
18
+ // import { initGlobals } from "../globals.js";
19
+
20
+ export interface ServerInterfaceImplOptions {
21
+ cache: CacheInterface;
22
+ localCache: CacheInterface;
23
+ dbManager: DBManager;
24
+ webSocketManager: WebSocketManager;
25
+ logger?: Logger;
26
+ app?: Miqro;
27
+ port?: string;
28
+ loggerProvider?: LogProvider;
29
+ }
30
+
31
+ export function createServerInterface(options: ServerInterfaceImplOptions): ServerInterface {
32
+ // initGlobals();
33
+ return Object.freeze<ServerInterface>({
34
+ middleware,
35
+ encodeHTML: HTMLEncode,
36
+ inflateMDtoHTML: inflateMD2HTML,
37
+ newParser() {
38
+ return new Parser();
39
+ },
40
+ newClusterCache(name, logger) {
41
+ return new ClusterCache(name, logger);
42
+ },
43
+ newLocalCache(name, logger) {
44
+ return new LocalCache(name, logger);
45
+ },
46
+ getWorkerNumber(): number {
47
+ return cluster.isPrimary || process.env["CLUSTER_NODE_NUMBER"] === undefined ? 0 : parseInt(process.env["CLUSTER_NODE_NUMBER"], 10);
48
+ },
49
+ getWorkerCount(): number {
50
+ return cluster.isPrimary || process.env["CLUSTER_NODE_NUMBER"] === undefined || process.env["CLUSTER_COUNT"] === undefined ? 1 : parseInt(process.env["CLUSTER_COUNT"], 10);
51
+ },
52
+ isPrimaryWorker(): boolean {
53
+ return cluster.isPrimary || process.env["CLUSTER_NODE_NUMBER"] === "0";
54
+ },
55
+ jwt,
56
+ cache: options.cache,
57
+ localCache: options.localCache,
58
+ logger: options.logger,
59
+ reload() {
60
+ return options?.app?.reload();
61
+ },
62
+ restart() {
63
+ return options?.app?.restart();
64
+ },
65
+ stop() {
66
+ return options?.app?.stop();
67
+ },
68
+ db: {
69
+ get(name) {
70
+ return options.dbManager.getDB(name);
71
+ },
72
+ getMigrations() {
73
+ if (options.app?.inflated) {
74
+ const ret: NamedMigration[] = [];
75
+ for (const d of options.app?.inflated.dbList) {
76
+ ret.push(...(d.migrations.map(m => {
77
+ return {
78
+ name: m.name,
79
+ service: m.service,
80
+ dbName: m.dbName
81
+ }
82
+ })));
83
+ }
84
+ return ret;
85
+ }
86
+ return [];
87
+ },
88
+ migrate(migrateOptions) {
89
+ return options?.app?.migrate(migrateOptions);
90
+ },
91
+ },
92
+ ws: {
93
+ get: (name: string) => {
94
+ return options?.webSocketManager?.getWS(name);
95
+ },
96
+ disconnectAll: (path: string) => {
97
+ return options?.webSocketManager?.disconnectAllButLOGSocket();
98
+ }
99
+ },
100
+ openBrowser(path) {
101
+ const PORT = options.port;
102
+ const URL = `http://localhost${PORT ? `:${PORT}` : ""}${path}`;
103
+ const DEFAULT_OPEN = process.platform === "win32" ? "explorer" : process.platform === "darwin" ? "open" : "xdg-open";
104
+ const OPEN = options?.app?.options.browser !== undefined && String(options?.app?.options.browser).toUpperCase() !== "TRUE" && String(options?.app?.options.browser).toUpperCase() !== "1" ?
105
+ 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 ?
106
+ options?.app.options.browser : false :
107
+ process.env["BROWSER"] ?
108
+ process.env["BROWSER"] === "none" ? false : process.env["BROWSER"] : DEFAULT_OPEN;
109
+ if (OPEN) {
110
+ const openCMD = `${OPEN} "${URL}"`;
111
+ options?.logger?.info("opening browser with [%s]", openCMD);
112
+ execSync(openCMD);
113
+ } else {
114
+ options?.logger?.warn("ignoring browser [%s]", OPEN);
115
+ }
116
+ },
117
+ getLogger(identifier, loggerOptions) {
118
+ return options?.loggerProvider?.getLogger(identifier, loggerOptions);
119
+ }
120
+ // ...server
121
+ });
122
+ }
@@ -0,0 +1,157 @@
1
+ import { Logger } from "@miqro/core";
2
+ import { LOG_SOCKET_PATH } from "../../../editor/common/constants.js";
3
+ import { ClusterWebSocketServer2 } from "./cluster-ws.js";
4
+ import { WSConfig } from "../../types.js";
5
+ import { LogProvider } from "./log.js";
6
+
7
+ export interface WebSocketManagerOptions {
8
+ logger?: Logger | Console;
9
+ loggerProvider?: LogProvider;
10
+ name?: string;
11
+ avoidLogSocket?: boolean;
12
+ }
13
+
14
+ export class WebSocketManager {
15
+ public runningGlobalWSMap = new Map<string, ClusterWebSocketServer2>();
16
+ public logger?: Logger | Console | null = null;
17
+ public name: string;
18
+ public avoidLogSocket: boolean;
19
+ public loggerProvider: LogProvider;
20
+ constructor(options?: WebSocketManagerOptions) {
21
+ this.onUpgrade = this.onUpgrade.bind(this);
22
+ this.logger = options && options.logger ? options.logger : null;
23
+ this.name = options && options.name ? options.name : "WebSocketManager";
24
+ this.loggerProvider = options && options.loggerProvider;
25
+ this.avoidLogSocket = options && options.avoidLogSocket ? options.avoidLogSocket : false;
26
+ }
27
+
28
+ public deleteWS(path: string) {
29
+ const ws = this.runningGlobalWSMap.get(path);
30
+ this.disconnectAllFrom(path);
31
+ ws.dispose();
32
+ this.runningGlobalWSMap.delete(path);
33
+ }
34
+
35
+ public deleteAllWS() {
36
+ for (const path of this.runningGlobalWSMap.keys()) {
37
+ this.deleteWS(path);
38
+ }
39
+ }
40
+
41
+ public getWS(path: string): ClusterWebSocketServer2 | undefined {
42
+ return this.runningGlobalWSMap.get(path);
43
+ }
44
+
45
+ public replaceALLWS(list: WSConfig[]) {
46
+ this.deleteAllWS();
47
+ for (const wsConfig of list) {
48
+ if (!wsConfig.disabled) {
49
+ if (this.runningGlobalWSMap.has(wsConfig.path)) {
50
+ throw new Error(`ws on path ${wsConfig.path} already setup!`);
51
+ }
52
+ this.logger?.debug("setting up websocket on [%s]", wsConfig.path);
53
+ const identifier = wsConfig.path.replaceAll("/", "_").toUpperCase();
54
+ const logger = this.loggerProvider && identifier.length >= 0 ? this.loggerProvider.getLogger(identifier.substring(identifier.charAt(0) === "_" ? 1 : 0)) : this.logger;
55
+ const server = new ClusterWebSocketServer2(this.name + wsConfig.path, wsConfig.path, logger, wsConfig);
56
+ this.runningGlobalWSMap.set(wsConfig.path, server);
57
+ }
58
+ }
59
+ }
60
+
61
+ public replaceALLWSBuLOGSocket(list: WSConfig[]) {
62
+ for (const path of this.runningGlobalWSMap.keys()) {
63
+ if (path !== LOG_SOCKET_PATH || !this.avoidLogSocket) {
64
+ this.deleteWS(path);
65
+ }
66
+ }
67
+ for (const wsConfig of list) {
68
+ if (!wsConfig.disabled) {
69
+ if (wsConfig.path !== LOG_SOCKET_PATH || !this.avoidLogSocket) {
70
+ if (this.runningGlobalWSMap.has(wsConfig.path)) {
71
+ throw new Error(`ws on path ${wsConfig.path} already setup!`);
72
+ }
73
+ this.logger?.debug("setting up websocket on [%s]", wsConfig.path);
74
+ const identifier = wsConfig.path.replaceAll("/", "_").toUpperCase();
75
+ const logger = this.loggerProvider && identifier.length >= 0 ? this.loggerProvider.getLogger(identifier.substring(identifier.charAt(0) === "_" ? 1 : 0)) : this.logger;
76
+ const server = new ClusterWebSocketServer2(this.name + wsConfig.path, wsConfig.path, logger, wsConfig);
77
+ this.runningGlobalWSMap.set(wsConfig.path, server);
78
+ }
79
+ }
80
+ }
81
+ }
82
+
83
+ /*public setupWS(path: string, server: ClusterWebSocketServer2) {
84
+ if (this.runningGlobalWSMap.has(path)) {
85
+ throw new Error(`ws on path ${path} already setup!`);
86
+ }
87
+ this.runningGlobalWSMap.set(path, server);
88
+ }*/
89
+
90
+ public disconnectAllFrom(path: string) {
91
+ try {
92
+ this.logger?.debug("disconnect all from [%s]", path);
93
+ const ws = this.getWS(path);
94
+ if (ws) {
95
+ const clients = ws.clients.values();
96
+ if (clients) {
97
+ for (const client of clients) {
98
+ try {
99
+ client.socket.destroy();
100
+ } catch (e2) {
101
+ this.logger?.error("error disconnecting web socket client");
102
+ this.logger?.error(e2);
103
+ }
104
+ }
105
+ }
106
+ //ws.dispose();
107
+ }
108
+ } catch (e) {
109
+ this.logger?.error("error disconnecting web socket clients");
110
+ this.logger?.error(e.message);
111
+ }
112
+ }
113
+
114
+ public disconnectAllButLOGSocket() {
115
+ try {
116
+ for (const wsPath of this.runningGlobalWSMap.keys()) {
117
+ if (wsPath !== LOG_SOCKET_PATH || !this.avoidLogSocket) {
118
+ this.disconnectAllFrom(wsPath);
119
+ }
120
+ }
121
+ } catch (e) {
122
+ this.logger?.error("error disconnecting web socket clients");
123
+ this.logger?.error(e.message);
124
+ }
125
+ }
126
+
127
+ public disconnectAll() {
128
+ try {
129
+ for (const wsPath of this.runningGlobalWSMap.keys()) {
130
+ this.disconnectAllFrom(wsPath);
131
+ }
132
+ } catch (e) {
133
+ this.logger?.error("error disconnecting web socket clients");
134
+ this.logger?.error(e.message);
135
+ }
136
+ }
137
+
138
+ public onUpgrade(req, socket, head) {
139
+ try {
140
+ const wsServer = this.getWS(req.path);
141
+ if (wsServer) {
142
+ return wsServer.onUpgrade(req, socket, head);
143
+ } else {
144
+ socket.destroy();
145
+ }
146
+ } catch (e) {
147
+ this.logger?.error(e);
148
+ }
149
+ }
150
+ }
151
+
152
+ /*export interface WSMapConfig {
153
+ [path: string]: {
154
+ name: string;
155
+ options: WSConfig;
156
+ } | undefined;
157
+ }*/
package/src/types.ts ADDED
@@ -0,0 +1,307 @@
1
+ import { Database } from "@miqro/query";
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
+ import { request } from "@miqro/request";
4
+ import { Parser, ParserInterface } from "@miqro/parser";
5
+ import { RuntimeHTMLElement, Runtime, RuntimeContainer, RuntimeURL, RuntimeOptions, RuntimeShadowRootInit } from "@miqro/jsx";
6
+ import {
7
+ RuntimeElementDefinitionOptions,
8
+ Component,
9
+ createElement,
10
+ Fragment,
11
+ enableDebugLog
12
+ } from "@miqro/jsx";
13
+ import * as jsxLib from "@miqro/jsx";
14
+ import { EncryptOptions, JWTDecryptOptions, JWTDecryptResult, JWTPayload, JWTVerifyOptions, JWTVerifyResult, ProtectedHeaderParameters, SignOptions } from "jose";
15
+ import { KeyObject } from "node:crypto";
16
+
17
+ export interface EncryptJWTOptions {
18
+ alg?: string;
19
+ enc?: string;
20
+ iat?: number | string | Date;
21
+ iss?: string;
22
+ aud?: string;
23
+ exp?: number | string | Date;
24
+ options?: EncryptOptions;
25
+ }
26
+
27
+ export interface JWTSignOptions {
28
+ alg?: string;
29
+ iat?: number | string | Date;
30
+ iss?: string;
31
+ aud?: string;
32
+ exp?: number | string | Date;
33
+ options?: SignOptions;
34
+ }
35
+
36
+ /*declare global {
37
+ // jsx only for the default value of tsconfig.json
38
+ //var React: {};
39
+ var JSX: {
40
+ createElement: typeof createElement;
41
+ Fragment: typeof Fragment;
42
+ enableDebugLog: typeof enableDebugLog;
43
+ }
44
+ }
45
+
46
+ declare global {
47
+ // only available browser side
48
+ var jsx: {
49
+ define: (tagName: string, component: Component, options?: RuntimeElementDefinitionOptions) => void;
50
+ useRuntime: typeof jsxLib.useRuntime;
51
+ usePathname: typeof jsxLib.usePathname;
52
+ Link: typeof jsxLib.Link;
53
+ Router: typeof jsxLib.Router;
54
+ createContext: typeof jsxLib.createContext;
55
+ useContext: typeof jsxLib.useContext;
56
+ useState: typeof jsxLib.useState;
57
+ useEffect: typeof jsxLib.useEffect;
58
+ useQuery: typeof jsxLib.useQuery;
59
+ useRef: typeof jsxLib.useRef;
60
+ useElement: typeof jsxLib.useElement;
61
+ useRefresh: typeof jsxLib.useRefresh;
62
+ }
63
+ }*/
64
+
65
+ export { APIRoute } from "@miqro/core";
66
+ export { Migration } from "@miqro/query";
67
+
68
+ export interface JWTInterface {
69
+ createSecretKey: (key: string, encoding: BufferEncoding) => KeyObject;
70
+ /**
71
+ * creates a JWT encrypted token with jose
72
+ *
73
+ * @param payload the payload to encrypt
74
+ * @param secret the secret example. const secret = createSecretKey(process.env.JWT_SECRET, 'utf-8');
75
+ * @param options options like expiratation date, issuer and audience
76
+ * @returns
77
+ */
78
+ encrypt: (payload: JWTPayload, secret: KeyObject, options?: Partial<EncryptJWTOptions>) => Promise<string>
79
+ /**
80
+ * decrypts a JWT token with jose
81
+ * @param jwt the JWT token
82
+ * @param secret the secret example. const secret = createSecretKey(process.env.JWT_SECRET, 'utf-8');
83
+ * @param options options like issuer and audience
84
+ * @returns
85
+ */
86
+ decrypt: <PayloadType = JWTPayload>(jwt: string, secret: KeyObject, options?: Partial<JWTDecryptOptions>) => Promise<JWTDecryptResult<PayloadType>>;
87
+ /**
88
+ * verify a JWT token with jose
89
+ * @param jwt the JWT token
90
+ * @param secret the secret example. const secret = createSecretKey(process.env.JWT_SECRET, 'utf-8');
91
+ * @param options options like issuer and audience
92
+ * @returns
93
+ */
94
+ verify: <PayloadType = JWTPayload>(jwt: string, secret: KeyObject, options?: Partial<JWTVerifyOptions>) => Promise<JWTVerifyResult<PayloadType>>;
95
+ /**
96
+ * creates a signed JWT with jose
97
+ *
98
+ * @param payload the payload to encrypt
99
+ * @param secret the secret example. const secret = createSecretKey(process.env.JWT_SECRET, 'utf-8');
100
+ * @param options options like expiratation date, issuer and audience
101
+ * @returns
102
+ */
103
+ sign: (payload: JWTPayload, secret: KeyObject, options?: Partial<JWTSignOptions>) => Promise<string>;
104
+ /**
105
+ * decodes a protected header with jose
106
+ * @param token
107
+ * @returns
108
+ */
109
+ decodeProtectedHeader: (token: string | object) => ProtectedHeaderParameters;
110
+ /**
111
+ * decodes a jwt token
112
+ * @param jwt
113
+ * @returns
114
+ */
115
+ decode: <PayloadType = JWTPayload>(jwt: string) => PayloadType & JWTPayload;
116
+ }
117
+
118
+ export interface ServerGlobal {
119
+ encodeHTML: (str: string) => string;
120
+ inflateMDtoHTML: (str: string) => string;
121
+ middleware: {
122
+ buffer: typeof ReadBuffer;
123
+ url: typeof URLEncodedParser;
124
+ json: typeof JSONParser;
125
+ text: typeof TextParser;
126
+ cors: typeof CORS;
127
+ session: typeof SessionHandler;
128
+ };
129
+ newParser(): Parser;
130
+ newClusterCache: (name: string, logger?: Logger) => CacheInterface;
131
+ newLocalCache: (name: string, logger?: Logger) => CacheInterface;
132
+
133
+ getWorkerCount: () => number;
134
+ getWorkerNumber: () => number;
135
+ isPrimaryWorker: () => boolean;
136
+ jwt: JWTInterface;
137
+ }
138
+
139
+ export interface CacheInterface {
140
+ get<T = any>(key: string): T | undefined;
141
+ set: (key: string, value: unknown) => void;
142
+ unset: (key: string) => void;
143
+ has: (key: string) => boolean;
144
+
145
+ set_add: (key: string, value: unknown) => void;
146
+ set_delete: (key: string, value: unknown) => void;
147
+ set_has: (key: string, value: unknown) => boolean;
148
+ set_clear: (key: string) => void;
149
+
150
+ array_push: (key: string, value: unknown) => void;
151
+ array_clear: (key: string) => void;
152
+ }
153
+
154
+ export interface NamedMigration {
155
+ name: string;
156
+ service: string;
157
+ dbName: string;
158
+ }
159
+
160
+ export interface MigrateOptions {
161
+ direction: "up" | "down";
162
+ service?: string;
163
+ dbName?: string;
164
+ name?: string;
165
+ }
166
+
167
+ export interface LogConfig {
168
+ level?: LogLevel;
169
+ replaceConsoleTransport?: boolean;
170
+ replaceFileTransport?: boolean;
171
+ write: (args: LoggerTransportWriteArgs) => Promise<void> | void;
172
+ }
173
+
174
+ export interface ServerInterface extends ServerGlobal {
175
+ // null values are if the feature has been disabled
176
+ db: {
177
+ get(name: string): Database | null;
178
+ getMigrations(): NamedMigration[];
179
+ migrate(options: MigrateOptions): Promise<void>;
180
+ },
181
+ ws: {
182
+ get(path: string): WebSocketServer | undefined;
183
+ disconnectAll(path: string): void;
184
+ };
185
+ cache: CacheInterface;
186
+ localCache: CacheInterface;
187
+ logger?: Logger;
188
+ openBrowser: (path: string) => void;
189
+ getLogger: (identifier: string, options?: { level?: any; transports?: any[]; formatter?: any; }) => Logger;
190
+ stop: () => Promise<void>;
191
+ reload: () => Promise<null | {
192
+ filePath: string;
193
+ error: Error;
194
+ }[]>;
195
+ restart: () => Promise<null | {
196
+ filePath: string;
197
+ error: Error;
198
+ }[]>;
199
+ }
200
+
201
+ export interface ServerRequest extends Request {
202
+ server?: ServerInterface;
203
+ }
204
+
205
+ export interface ServerResponse extends Response {
206
+ }
207
+
208
+ export interface TestHelperGlobal {
209
+ PORT: string;
210
+ request: typeof request,
211
+ logger: Logger,
212
+ sleep: (ms: number) => Promise<void>,
213
+ jsx: {
214
+ createRuntime: (args?: {
215
+ basePath?: string | null;
216
+ url?: RuntimeURL;
217
+ logger?: {
218
+ log: Function,
219
+ error: Function
220
+ }
221
+ }) => Runtime;
222
+ test: (cb: (container: RuntimeContainer, root: RuntimeHTMLElement, runtime: Runtime) => (Promise<void> | void), args?: {
223
+ runtimeOptions?: {
224
+ basePath?: string | null;
225
+ url?: RuntimeURL;
226
+ logger?: {
227
+ log: Function;
228
+ error: Function;
229
+ };
230
+ },
231
+ containerOptions?: {
232
+ runtimeOptions?: RuntimeOptions;
233
+ shadowInit?: boolean | RuntimeShadowRootInit;
234
+ };
235
+ }) => () => Promise<void>;
236
+ }
237
+ }
238
+
239
+ /*declare global {
240
+ // only available server side
241
+ var server: ServerGlobal;
242
+
243
+ //var utils: UtilsGlobal;
244
+
245
+ var test: TestHelperGlobal;
246
+
247
+ var it: Function;
248
+ var describe: Function;
249
+ var before: Function;
250
+ var after: Function;
251
+ }*/
252
+
253
+ export interface AuthConfig extends SessionHandlerOptions {
254
+
255
+ }
256
+
257
+ export interface MiddlewareConfig {
258
+ middleware?: Array<HandlerWithOptions | Handler>;
259
+ post?: Array<HandlerWithOptions | Handler>;
260
+ }
261
+
262
+ export interface ErrorConfig {
263
+ catch?: Array<ErrorHandler>;
264
+ }
265
+
266
+ export interface DocConfig {
267
+ publish: {
268
+ [path: string]: {
269
+ type?: "HTML" | "MD" | "JSON",
270
+ all?: boolean;
271
+ }
272
+ }
273
+ }
274
+
275
+ export interface WSConfig extends WebSocketServerOptions {
276
+ path: string;
277
+ disabled?: boolean;
278
+ }
279
+
280
+ export interface CORSConfig extends CORSOptions {
281
+
282
+ }
283
+
284
+ export interface ServerConfig {
285
+ preload?: (server: ServerInterface) => Promise<void> | void;
286
+ start?: (server: ServerInterface) => Promise<void> | void;
287
+ load?: (server: ServerInterface) => Promise<void> | void;
288
+ unload?: (server: ServerInterface) => void;
289
+ stop?: (server: ServerInterface) => void;
290
+ }
291
+
292
+ export interface DBConfig {
293
+ dialect?: string;
294
+ storage?: string;
295
+ url?: string;
296
+ disabled?: boolean;
297
+ name: string;
298
+ }
299
+
300
+ export interface APIOptions extends Partial<RouteOptions> {
301
+ basePath?: string;
302
+ path?: string | string[];
303
+ method?: string | string[];
304
+ parser?: ParserInterface;
305
+ middleware?: Handler | Handler[];
306
+ session?: SessionHandlerOptions | Handler;
307
+ }