miqro 7.0.1 → 7.0.3
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/esm/editor/auth.d.ts +6 -0
- package/build/esm/editor/auth.js +41 -0
- package/build/esm/editor/common/admin-interface.d.ts +36 -0
- package/build/esm/editor/common/admin-interface.js +44 -0
- package/build/esm/editor/common/constants.d.ts +4 -0
- package/build/esm/editor/common/constants.js +20 -0
- package/build/esm/editor/common/constants.server.d.ts +2 -0
- package/build/esm/editor/common/constants.server.js +4 -0
- package/build/esm/editor/common/editor-index.d.ts +2 -0
- package/build/esm/editor/common/editor-index.js +14 -0
- package/build/esm/editor/common/html-encode.d.ts +1 -0
- package/build/esm/editor/common/html-encode.js +14 -0
- package/build/esm/editor/common/log-socket.d.ts +15 -0
- package/build/esm/editor/common/log-socket.js +71 -0
- package/build/esm/editor/common/templates.d.ts +11 -0
- package/build/esm/editor/common/templates.js +477 -0
- package/build/esm/editor/components/api-preview.d.ts +11 -0
- package/build/esm/editor/components/api-preview.js +92 -0
- package/build/esm/editor/components/editor.d.ts +16 -0
- package/build/esm/editor/components/editor.js +367 -0
- package/build/esm/editor/components/file-browser.d.ts +37 -0
- package/build/esm/editor/components/file-browser.js +127 -0
- package/build/esm/editor/components/file-editor-toolbar.d.ts +22 -0
- package/build/esm/editor/components/file-editor-toolbar.js +95 -0
- package/build/esm/editor/components/file-editor.d.ts +32 -0
- package/build/esm/editor/components/file-editor.js +61 -0
- package/build/esm/editor/components/filter-query.d.ts +1 -0
- package/build/esm/editor/components/filter-query.js +23 -0
- package/build/esm/editor/components/highlight-text-area.d.ts +11 -0
- package/build/esm/editor/components/highlight-text-area.js +127 -0
- package/build/esm/editor/components/log-viewer.d.ts +6 -0
- package/build/esm/editor/components/log-viewer.js +71 -0
- package/build/esm/editor/components/new-file.d.ts +10 -0
- package/build/esm/editor/components/new-file.js +119 -0
- package/build/esm/editor/components/scroll-query.d.ts +7 -0
- package/build/esm/editor/components/scroll-query.js +22 -0
- package/build/esm/editor/components/start-page.d.ts +13 -0
- package/build/esm/editor/components/start-page.js +32 -0
- package/build/esm/editor/http/admin/editor/api/fs/delete.api.d.ts +3 -0
- package/build/esm/editor/http/admin/editor/api/fs/delete.api.js +30 -0
- package/build/esm/editor/http/admin/editor/api/fs/read.api.d.ts +5 -0
- package/build/esm/editor/http/admin/editor/api/fs/read.api.js +50 -0
- package/build/esm/editor/http/admin/editor/api/fs/rename.api.d.ts +4 -0
- package/build/esm/editor/http/admin/editor/api/fs/rename.api.js +40 -0
- package/build/esm/editor/http/admin/editor/api/fs/scan.api.d.ts +26 -0
- package/build/esm/editor/http/admin/editor/api/fs/scan.api.js +150 -0
- package/build/esm/editor/http/admin/editor/api/fs/write.api.d.ts +3 -0
- package/build/esm/editor/http/admin/editor/api/fs/write.api.js +39 -0
- package/build/esm/editor/http/admin/editor/api/server/reload.api.d.ts +10 -0
- package/build/esm/editor/http/admin/editor/api/server/reload.api.js +46 -0
- package/build/esm/editor/http/admin/editor/api/server/restart.api.d.ts +10 -0
- package/build/esm/editor/http/admin/editor/api/server/restart.api.js +46 -0
- package/build/esm/editor/http/admin/editor/editor.d.ts +1 -0
- package/build/esm/editor/http/admin/editor/editor.js +8 -0
- package/build/esm/editor/http/admin/editor/index.api.d.ts +3 -0
- package/build/esm/editor/http/admin/editor/index.api.js +22 -0
- package/build/esm/editor/server.d.ts +3 -0
- package/build/esm/editor/server.js +49 -0
- package/build/esm/editor/ws.d.ts +3 -0
- package/build/esm/editor/ws.js +11 -0
- package/build/esm/src/inflate/inflate-sea.js +8 -1
- package/build/esm/src/services/app.js +7 -2
- package/build/lib.cjs +14 -3
- package/editor/auth.ts +51 -0
- package/editor/common/admin-interface.ts +84 -0
- package/editor/common/constants.server.ts +5 -0
- package/editor/common/constants.ts +21 -0
- package/editor/common/editor-index.tsx +17 -0
- package/editor/common/html-encode.ts +14 -0
- package/editor/common/log-socket.tsx +87 -0
- package/editor/common/templates.ts +481 -0
- package/editor/components/api-preview.tsx +118 -0
- package/editor/components/editor.tsx +496 -0
- package/editor/components/file-browser.tsx +311 -0
- package/editor/components/file-editor-toolbar.tsx +194 -0
- package/editor/components/file-editor.tsx +125 -0
- package/editor/components/filter-query.tsx +26 -0
- package/editor/components/highlight-text-area.tsx +148 -0
- package/editor/components/log-viewer.tsx +113 -0
- package/editor/components/new-file.tsx +172 -0
- package/editor/components/scroll-query.tsx +25 -0
- package/editor/components/start-page.tsx +52 -0
- package/editor/http/admin/editor/api/fs/delete.api.tsx +32 -0
- package/editor/http/admin/editor/api/fs/read.api.tsx +55 -0
- package/editor/http/admin/editor/api/fs/rename.api.tsx +41 -0
- package/editor/http/admin/editor/api/fs/scan.api.tsx +181 -0
- package/editor/http/admin/editor/api/fs/write.api.tsx +41 -0
- package/editor/http/admin/editor/api/server/reload.api.ts +53 -0
- package/editor/http/admin/editor/api/server/restart.api.tsx +52 -0
- package/editor/http/admin/editor/editor.tsx +10 -0
- package/editor/http/admin/editor/index.api.tsx +42 -0
- package/editor/server.ts +57 -0
- package/editor/ws.ts +15 -0
- package/package.json +2 -2
- package/src/bin/compile.ts +35 -0
- package/src/bin/doc-md.ts +210 -0
- package/src/bin/generate-doc.ts +64 -0
- package/src/bin/test.ts +92 -0
- package/src/bin/types.ts +34 -0
- package/src/cluster.ts +27 -0
- package/src/common/arguments.ts +762 -0
- package/src/common/assets.ts +148 -0
- package/src/common/checksum.ts +58 -0
- package/src/common/constants.ts +18 -0
- package/src/common/content-type.ts +84 -0
- package/src/common/esbuild.ts +102 -0
- package/src/common/exit.ts +91 -0
- package/src/common/fs.ts +82 -0
- package/src/common/help.ts +60 -0
- package/src/common/jsx.ts +562 -0
- package/src/common/jwt.ts +85 -0
- package/src/common/paths.ts +107 -0
- package/src/common/watch.ts +88 -0
- package/src/inflate/inflate-sea.ts +244 -0
- package/src/inflate/inflate.ts +101 -0
- package/src/inflate/md.ts +25 -0
- package/src/inflate/setup-auth.ts +41 -0
- package/src/inflate/setup-cors.ts +41 -0
- package/src/inflate/setup-db.ts +117 -0
- package/src/inflate/setup-error.ts +44 -0
- package/src/inflate/setup-http.ts +704 -0
- package/src/inflate/setup-log.ts +45 -0
- package/src/inflate/setup-middleware.ts +47 -0
- package/src/inflate/setup-server-config.ts +48 -0
- package/src/inflate/setup-test.ts +23 -0
- package/src/inflate/setup-ws.ts +50 -0
- package/src/inflate/setup.doc.ts +92 -0
- package/src/inflate/utils/sea-utils.ts +14 -0
- package/src/lib.ts +34 -0
- package/src/main.ts +101 -0
- package/src/services/app.ts +703 -0
- package/src/services/editor.tsx +101 -0
- package/src/services/globals.ts.ignore +186 -0
- package/src/services/hot-reload.ts +51 -0
- package/src/services/migrations.ts +68 -0
- package/src/services/utils/admin-interface.ts +37 -0
- package/src/services/utils/cache.ts +88 -0
- package/src/services/utils/cluster-cache.ts +230 -0
- package/src/services/utils/cluster-ws.ts +202 -0
- package/src/services/utils/db-manager.ts +92 -0
- package/src/services/utils/get-route.ts +70 -0
- package/src/services/utils/jwt.ts +25 -0
- package/src/services/utils/log-transport.ts +81 -0
- package/src/services/utils/log.ts +92 -0
- package/src/services/utils/middleware.ts +10 -0
- package/src/services/utils/server-interface.ts +122 -0
- package/src/services/utils/websocketmanager.ts +157 -0
- package/src/types.ts +307 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { APIRoute, Handler, HandlerWithOptions, Router, RouterHandlerOptions, SessionHandler } from "@miqro/core";
|
|
2
|
+
import { getAsset } from "../common/assets.js";
|
|
3
|
+
|
|
4
|
+
import { BASEEDITOR_PATH } from "../../editor/common/constants.js";
|
|
5
|
+
import EDITOR_AUTH from "../../editor/auth.js";
|
|
6
|
+
|
|
7
|
+
/*import writeAPI from "../../editor/http/admin/editor/api/fs/write.api.js";
|
|
8
|
+
import renameAPI from "../../editor/http/admin/editor/api/fs/rename.api.js";
|
|
9
|
+
import deleteAPI from "../../editor/http/admin/editor/api/fs/delete.api.js";
|
|
10
|
+
import readAPI from "../../editor/http/admin/editor/api/fs/read.api.js";
|
|
11
|
+
import scanAPI from "../../editor/http/admin/editor/api/fs/scan.api.js";
|
|
12
|
+
import restartAPI from "../../editor/http/admin/editor/api/server/restart.api.js";
|
|
13
|
+
import reloadAPI from "../../editor/http/admin/editor/api/server/reload.api.js";*/
|
|
14
|
+
|
|
15
|
+
import { AdminRequest, EditorAdminInterface } from "../../editor/common/admin-interface.js";
|
|
16
|
+
import { CONTENT_TYPE_MAP } from "../common/content-type.js";
|
|
17
|
+
|
|
18
|
+
export async function createEditorRouter(adminInterface: EditorAdminInterface): Promise<Router> {
|
|
19
|
+
const router = new Router();
|
|
20
|
+
const innerRouter = new Router();
|
|
21
|
+
|
|
22
|
+
innerRouter.use(async (req: AdminRequest, res) => {
|
|
23
|
+
res.setHeader("x-uuid", req.uuid);
|
|
24
|
+
req.editor = adminInterface;
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const editorFont = Buffer.from(getAsset("editor-assets/font.ttf"));
|
|
28
|
+
const editorJS = Buffer.from(getAsset("editor-assets/editor.bundle.js")).toString().trim();
|
|
29
|
+
const editorCSS = Buffer.from(getAsset("editor-assets/style.css")).toString().trim().split("\n").map(l => l.trim()).filter(l => l).join("");
|
|
30
|
+
|
|
31
|
+
const writeAPI = (await import("../../editor/http/admin/editor/api/fs/write.api.js")).default;
|
|
32
|
+
const renameAPI = (await import("../../editor/http/admin/editor/api/fs/rename.api.js")).default;
|
|
33
|
+
const deleteAPI = (await import("../../editor/http/admin/editor/api/fs/delete.api.js")).default;
|
|
34
|
+
const readAPI = (await import("../../editor/http/admin/editor/api/fs/read.api.js")).default;
|
|
35
|
+
const scanAPI = (await import("../../editor/http/admin/editor/api/fs/scan.api.js")).default;
|
|
36
|
+
const restartAPI = (await import("../../editor/http/admin/editor/api/server/restart.api.js")).default;
|
|
37
|
+
const reloadAPI = (await import("../../editor/http/admin/editor/api/server/reload.api.js")).default;
|
|
38
|
+
|
|
39
|
+
const authHandler = SessionHandler(EDITOR_AUTH);
|
|
40
|
+
|
|
41
|
+
const { EditorIndex } = await import("../../editor/common/editor-index.js");
|
|
42
|
+
|
|
43
|
+
innerRouter.use(authHandler);
|
|
44
|
+
|
|
45
|
+
innerRouter.post(`/api/fs/write`, getHandler(/*authHandler, */writeAPI));
|
|
46
|
+
|
|
47
|
+
innerRouter.post(`/api/fs/rename`, getHandler(/*authHandler, */renameAPI));
|
|
48
|
+
|
|
49
|
+
innerRouter.post(`/api/fs/read`, getHandler(/*authHandler, */readAPI));
|
|
50
|
+
|
|
51
|
+
innerRouter.post(`/api/fs/delete`, getHandler(/*authHandler, */deleteAPI));
|
|
52
|
+
|
|
53
|
+
innerRouter.get(`/api/fs/scan`, getHandler(/*authHandler, */scanAPI));
|
|
54
|
+
|
|
55
|
+
innerRouter.post(`/api/server/restart`, getHandler(/*authHandler, */restartAPI));
|
|
56
|
+
|
|
57
|
+
innerRouter.post(`/api/server/reload`, getHandler(/*authHandler, */reloadAPI));
|
|
58
|
+
|
|
59
|
+
innerRouter.get(`/font.ttf`, async (_req, res) => {
|
|
60
|
+
return await res.asyncEnd({
|
|
61
|
+
status: 200,
|
|
62
|
+
headers: {
|
|
63
|
+
["Content-Type"]: CONTENT_TYPE_MAP[".ttf"]
|
|
64
|
+
},
|
|
65
|
+
body: editorFont
|
|
66
|
+
})
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
innerRouter.get("/", EditorIndex(editorCSS, editorJS, false));
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
innerRouter.use(async (req: AdminRequest, res) => {
|
|
74
|
+
delete req.editor;
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
router.use(innerRouter, BASEEDITOR_PATH);
|
|
78
|
+
|
|
79
|
+
return router;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function getHandlerOptions(router: APIRoute): RouterHandlerOptions {
|
|
83
|
+
return {
|
|
84
|
+
description: router.description,
|
|
85
|
+
//handler: router,
|
|
86
|
+
middleware: router.middleware,
|
|
87
|
+
request: router.request,
|
|
88
|
+
response: router.response,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function getHandler(/*auth: Handler, */router: APIRoute): HandlerWithOptions {
|
|
93
|
+
/*const ret = new Router();
|
|
94
|
+
ret.use(auth);
|
|
95
|
+
ret.use(router.handler, undefined, undefined, getHandlerOptions(router));
|
|
96
|
+
return ret;*/
|
|
97
|
+
return {
|
|
98
|
+
...getHandlerOptions(router),
|
|
99
|
+
handler: router.handler as Handler
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
//@ts-ignore
|
|
2
|
+
import { ReadBuffer, URLEncodedParser, JSONParser, TextParser, CORS, SessionHandler } from "@miqro/core";
|
|
3
|
+
import cluster from "node:cluster";
|
|
4
|
+
import { strictEqual } from "node:assert";
|
|
5
|
+
import { HTMLEncode } from "@miqro/jsx-node";
|
|
6
|
+
import { createElement as realCreateElement, enableDebugLog, useRuntime, Link, Router, usePathname, Fragment, useEffect, useRef, useState, useQuery, useRefresh, useElement, createContext, useContext, Component, Props } from "@miqro/jsx";
|
|
7
|
+
|
|
8
|
+
import { jsx2HTML } from "../common/jsx.js";
|
|
9
|
+
import { inflateMD2HTML } from "../inflate/md.js";
|
|
10
|
+
import { EXIT_CODES } from "../common/constants.js";
|
|
11
|
+
import { ClusterCache, LocalCache, ServerGlobal } from "../lib.js";
|
|
12
|
+
import { decodeJWT, decodeProtectedHeaderJWT, decryptJWT, encryptJWT, signJWT, verifyJWT } from "../common/jwt.js";
|
|
13
|
+
import { createSecretKey } from "node:crypto";
|
|
14
|
+
import { Parser } from "@miqro/parser";
|
|
15
|
+
|
|
16
|
+
/*const globaljsx: any = Object.freeze({
|
|
17
|
+
useContext,
|
|
18
|
+
useRuntime,
|
|
19
|
+
createContext,
|
|
20
|
+
useState,
|
|
21
|
+
useEffect,
|
|
22
|
+
useQuery,
|
|
23
|
+
useRef,
|
|
24
|
+
useElement,
|
|
25
|
+
useRefresh,
|
|
26
|
+
Link,
|
|
27
|
+
Router,
|
|
28
|
+
usePathname
|
|
29
|
+
});*/
|
|
30
|
+
const globalJSX: any = Object.freeze({
|
|
31
|
+
createElement: (...args: [tag: string | Component | typeof Fragment, attributes: Props | null | undefined, ...children: Array<any>]) => {
|
|
32
|
+
const ret = realCreateElement(...args);
|
|
33
|
+
ret.toString = () => jsx2HTML(ret)
|
|
34
|
+
return ret;
|
|
35
|
+
},
|
|
36
|
+
Fragment,
|
|
37
|
+
enableDebugLog
|
|
38
|
+
});
|
|
39
|
+
const globaljsx: any = Object.freeze({
|
|
40
|
+
useContext,
|
|
41
|
+
useRuntime,
|
|
42
|
+
createContext,
|
|
43
|
+
useState,
|
|
44
|
+
useEffect,
|
|
45
|
+
useQuery,
|
|
46
|
+
useRef,
|
|
47
|
+
useElement,
|
|
48
|
+
useRefresh,
|
|
49
|
+
Link,
|
|
50
|
+
Router,
|
|
51
|
+
usePathname,
|
|
52
|
+
define: function define() {
|
|
53
|
+
/*const callSites = getCallSite();
|
|
54
|
+
const caller = callSites[2];
|
|
55
|
+
if (CLEAR_JSX_CACHE) {
|
|
56
|
+
const scriptName = basename(caller.scriptName);
|
|
57
|
+
const originalName = scriptName.substring(0, scriptName.length - ".mjs".length);
|
|
58
|
+
//server.logger.debug("browser.define not available server side!");
|
|
59
|
+
//server.logger.trace("browser.define not available server side! %s", originalName);
|
|
60
|
+
} else {
|
|
61
|
+
//server.logger.debug("browser.define not available server side!");
|
|
62
|
+
//server.logger.trace("browser.define not available server side! %s:%s:%s", caller.scriptName, caller.lineNumber, caller.column);
|
|
63
|
+
}*/
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
const globalWindow: any = Object.freeze({
|
|
67
|
+
addEventListener: function define() {
|
|
68
|
+
/*const callSites = getCallSite();
|
|
69
|
+
const caller = callSites[2];
|
|
70
|
+
if (CLEAR_JSX_CACHE) {
|
|
71
|
+
const scriptName = basename(caller.scriptName);
|
|
72
|
+
//server.logger.debug("window.addEventListener not available server side!");
|
|
73
|
+
server.logger.trace("window.addEventListener not available server side! %s", scriptName.substring(0, scriptName.length - ".mjs".length));
|
|
74
|
+
} else {
|
|
75
|
+
//server.logger.debug("window.addEventListener not available server side!");
|
|
76
|
+
server.logger.trace("window.addEventListener not available server side! %s:%s:%s", caller.scriptName, caller.lineNumber, caller.column);
|
|
77
|
+
}*/
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
const globalServer: ServerGlobal = Object.freeze<ServerGlobal>({
|
|
81
|
+
middleware: Object.freeze({
|
|
82
|
+
buffer: ReadBuffer,
|
|
83
|
+
url: URLEncodedParser,
|
|
84
|
+
json: JSONParser,
|
|
85
|
+
text: TextParser,
|
|
86
|
+
cors: CORS,
|
|
87
|
+
session: SessionHandler
|
|
88
|
+
}),
|
|
89
|
+
encodeHTML: HTMLEncode,
|
|
90
|
+
inflateMDtoHTML: inflateMD2HTML,
|
|
91
|
+
createSecretKey,
|
|
92
|
+
newParser() {
|
|
93
|
+
return new Parser();
|
|
94
|
+
},
|
|
95
|
+
newClusterCache(name, logger) {
|
|
96
|
+
return new ClusterCache(name, logger);
|
|
97
|
+
},
|
|
98
|
+
newLocalCache(name, logger) {
|
|
99
|
+
return new LocalCache(name, logger);
|
|
100
|
+
},
|
|
101
|
+
getWorkerNumber(): number {
|
|
102
|
+
return cluster.isPrimary || process.env["CLUSTER_NODE_NUMBER"] === undefined ? 0 : parseInt(process.env["CLUSTER_NODE_NUMBER"], 10);
|
|
103
|
+
},
|
|
104
|
+
getWorkerCount(): number {
|
|
105
|
+
return cluster.isPrimary || process.env["CLUSTER_NODE_NUMBER"] === undefined || process.env["CLUSTER_COUNT"] === undefined ? 1 : parseInt(process.env["CLUSTER_COUNT"], 10);
|
|
106
|
+
},
|
|
107
|
+
isPrimaryWorker(): boolean {
|
|
108
|
+
return cluster.isPrimary || process.env["CLUSTER_NODE_NUMBER"] === "0";
|
|
109
|
+
},
|
|
110
|
+
jwt: {
|
|
111
|
+
decode(jwt) {
|
|
112
|
+
return decodeJWT(jwt);
|
|
113
|
+
},
|
|
114
|
+
decodeProtectedHeader(token) {
|
|
115
|
+
return decodeProtectedHeaderJWT(token);
|
|
116
|
+
},
|
|
117
|
+
decrypt(jwt, secret, options) {
|
|
118
|
+
return decryptJWT(jwt, secret, options);
|
|
119
|
+
},
|
|
120
|
+
encrypt(payload, secret, options) {
|
|
121
|
+
return encryptJWT(payload, secret, options);
|
|
122
|
+
},
|
|
123
|
+
sign(payload, secret, options) {
|
|
124
|
+
return signJWT(payload, secret, options);
|
|
125
|
+
},
|
|
126
|
+
verify(jwt, secret, options) {
|
|
127
|
+
return verifyJWT(jwt, secret, options);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}) as ServerGlobal;
|
|
131
|
+
|
|
132
|
+
export function browserJSXGlobals(inFile: string, jsxPath: string | false = false, useExport = true): string {
|
|
133
|
+
const PRE = `import { enableDebugLog, useRuntime, Link, usePathname, createContext, useContext, useElement, useRefresh, useQuery, define, Router, useState, useEffect, useRef, createElement, Fragment } from "${jsxPath}";
|
|
134
|
+
globalThis.JSX = Object.freeze({
|
|
135
|
+
createElement,
|
|
136
|
+
Fragment,
|
|
137
|
+
enableDebugLog
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
globalThis.newParser = () => new Parser();
|
|
141
|
+
globalThis.jsx = Object.freeze({
|
|
142
|
+
define,
|
|
143
|
+
useRuntime,
|
|
144
|
+
createContext,
|
|
145
|
+
useContext,
|
|
146
|
+
useState,
|
|
147
|
+
useEffect,
|
|
148
|
+
useQuery,
|
|
149
|
+
useRef,
|
|
150
|
+
useElement,
|
|
151
|
+
useRefresh,
|
|
152
|
+
usePathname,
|
|
153
|
+
Link,
|
|
154
|
+
Router
|
|
155
|
+
});`;
|
|
156
|
+
return `${jsxPath ? PRE : ""}\n${useExport ? `export * from "${inFile}";import * as lib from "${inFile}";export default lib.default;` : `import * as lib from "${inFile}"`}`;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function initGlobals() {//webSocketManager: WebSocketManager, dbManager: DBManager) {
|
|
160
|
+
//const logger = getLogger(SERVER_IDENTIFIER);
|
|
161
|
+
globalThis.server = globalServer;
|
|
162
|
+
//globalThis.jsx = globaljsx;
|
|
163
|
+
/*for (const key of Object.keys(globaljsx)) {
|
|
164
|
+
globalThis[key] = globaljsx[key];
|
|
165
|
+
}*/
|
|
166
|
+
globalThis.JSX = globalJSX;
|
|
167
|
+
globalThis.jsx = globaljsx;
|
|
168
|
+
globalThis.window = globalWindow;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function assertGlobalTampered() {
|
|
172
|
+
try {
|
|
173
|
+
//strictEqual(globalThis.utils, globalUtils, "globalThis.utils tamperered");
|
|
174
|
+
strictEqual(globalThis.JSX, globalJSX, "globalThis.JSX tamperered");
|
|
175
|
+
//strictEqual(globalThis.jsx, globaljsx, "globalThis.jsx tamperered");
|
|
176
|
+
/*for (const key of Object.keys(globaljsx)) {
|
|
177
|
+
strictEqual(globalThis[key], globaljsx[key], "globalThis.jsx tamperered");
|
|
178
|
+
}*/
|
|
179
|
+
strictEqual(globalThis.server, globalServer, "globalThis.server tamperered");
|
|
180
|
+
strictEqual(globalThis.jsx, globaljsx, "globalThis.jsx tamperered");
|
|
181
|
+
strictEqual(globalThis.window, globalWindow, "globalThis.window tamperered");
|
|
182
|
+
} catch (e) {
|
|
183
|
+
console.error(e);
|
|
184
|
+
process.exit(EXIT_CODES.GLOBALS_ALTERED);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//import { checkEnvVariable } from "@miqro/core";
|
|
2
|
+
|
|
3
|
+
import { HOT_RELOAD_PATH } from "../common/constants.js";
|
|
4
|
+
|
|
5
|
+
export function getHotReloadScript() {
|
|
6
|
+
const HOT_RELOAD_JS_SCRIPT = `
|
|
7
|
+
// Create WebSocket connection.
|
|
8
|
+
|
|
9
|
+
function getSocket() {
|
|
10
|
+
return new WebSocket("${HOT_RELOAD_PATH}");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const socket = getSocket();
|
|
14
|
+
|
|
15
|
+
let timeout;
|
|
16
|
+
|
|
17
|
+
function tryConnection() {
|
|
18
|
+
try {
|
|
19
|
+
const newSocket = getSocket();
|
|
20
|
+
newSocket.addEventListener("open", (event) => {
|
|
21
|
+
console.log("reloading");
|
|
22
|
+
setTimeout(()=>{
|
|
23
|
+
window.location.reload();
|
|
24
|
+
}, 500);
|
|
25
|
+
|
|
26
|
+
});
|
|
27
|
+
newSocket.addEventListener("error", (err) => {
|
|
28
|
+
console.error(err);
|
|
29
|
+
timeout = setTimeout(tryConnection, 500);
|
|
30
|
+
});
|
|
31
|
+
} catch (e) {
|
|
32
|
+
console.error(e);
|
|
33
|
+
timeout = setTimeout(tryConnection, 500);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Connection closed
|
|
38
|
+
socket.addEventListener("close", (event) => {
|
|
39
|
+
clearTimeout(timeout);
|
|
40
|
+
timeout = setTimeout(tryConnection, 500);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
socket.addEventListener("error", (err) => {
|
|
44
|
+
console.error(err);
|
|
45
|
+
});`;
|
|
46
|
+
return `<script>${HOT_RELOAD_JS_SCRIPT}</script>`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/*export function isHotReloadEnabled() {
|
|
50
|
+
return checkEnvVariable("HOT_RELOAD", "0") === "1";
|
|
51
|
+
}*/
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Logger } from "@miqro/core";
|
|
2
|
+
import { Database, DatabaseLogger, migration } from "@miqro/query";
|
|
3
|
+
import { dirname, extname, relative, resolve } from "node:path";
|
|
4
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { cwd } from "node:process";
|
|
6
|
+
|
|
7
|
+
import { getMigrationsPath } from "../common/paths.js";
|
|
8
|
+
import { importJSXFile, inflateJSX } from "../common/jsx.js";
|
|
9
|
+
|
|
10
|
+
export async function runMigrations(logger: Logger | undefined, db: Database | null, servicePath: string, service: string, inflateDir: string | undefined | false, migrations: string[]) {
|
|
11
|
+
const migrationsFolderPath = getMigrationsPath(servicePath);
|
|
12
|
+
if (migrationsFolderPath) {
|
|
13
|
+
logger?.debug("running migrations from [%s]", service);
|
|
14
|
+
if (!db) {
|
|
15
|
+
throw new Error("cannot run migrations with the database disabled!");
|
|
16
|
+
}
|
|
17
|
+
const serviceMigrations = await migration.up.folder(db as any, migrationsFolderPath, logger as DatabaseLogger, (inFile: string) => importJSXFile(inFile, logger));
|
|
18
|
+
migrations.push(...serviceMigrations);
|
|
19
|
+
|
|
20
|
+
if (inflateDir) {
|
|
21
|
+
for (const migration of serviceMigrations) {
|
|
22
|
+
const inflatePath = resolve(inflateDir, service, "migration", migration.substring(0, migration.length - extname(migration).length) + ".cjs");
|
|
23
|
+
mkdirSync(dirname(inflatePath), {
|
|
24
|
+
recursive: true
|
|
25
|
+
});
|
|
26
|
+
logger?.log("writing [%s]", relative(cwd(), inflatePath));
|
|
27
|
+
writeFileSync(inflatePath, await inflateJSX(resolve(migrationsFolderPath, migration), {
|
|
28
|
+
// embemedJSX: false,
|
|
29
|
+
minify: false,
|
|
30
|
+
useExport: true,
|
|
31
|
+
platform: "node",
|
|
32
|
+
logger
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return migrations;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function runMigrationsDown(logger: Logger | Console | undefined, db: Database | null, servicePath: string, service: string, inflateDir: string | undefined, migrations: string[]) {
|
|
41
|
+
const migrationsFolderPath = getMigrationsPath(servicePath)
|
|
42
|
+
if (migrationsFolderPath) {
|
|
43
|
+
logger?.debug("running migrations from [%s]", service);
|
|
44
|
+
if (!db) {
|
|
45
|
+
throw new Error("cannot run migrations with the database disabled!");
|
|
46
|
+
}
|
|
47
|
+
const serviceMigrations = await migration.down.folder(db as any, migrationsFolderPath, logger as DatabaseLogger, (inFile: string) => importJSXFile(inFile, logger));
|
|
48
|
+
migrations.push(...serviceMigrations);
|
|
49
|
+
|
|
50
|
+
if (inflateDir) {
|
|
51
|
+
for (const migration of serviceMigrations) {
|
|
52
|
+
const inflatePath = resolve(inflateDir, service, "migration", migration.substring(0, migration.length - extname(migration).length) + ".cjs");
|
|
53
|
+
mkdirSync(dirname(inflatePath), {
|
|
54
|
+
recursive: true
|
|
55
|
+
});
|
|
56
|
+
logger?.log("writing [%s]", relative(cwd(), inflatePath));
|
|
57
|
+
writeFileSync(inflatePath, await inflateJSX(resolve(migrationsFolderPath, migration), {
|
|
58
|
+
// embemedJSX: false,
|
|
59
|
+
platform: "node",
|
|
60
|
+
minify: false,
|
|
61
|
+
useExport: true,
|
|
62
|
+
logger
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return migrations;
|
|
68
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { EditorAdminInterface } from "../../../editor/common/admin-interface.js";
|
|
2
|
+
import { MigrationModule } from "../../inflate/setup-db.js";
|
|
3
|
+
import { Miqro } from "../app.js";
|
|
4
|
+
import { getHotReloadScript } from "../hot-reload.js";
|
|
5
|
+
import { ClusterCache } from "./cluster-cache.js";
|
|
6
|
+
|
|
7
|
+
export function createAdminInterface(app: Miqro): EditorAdminInterface {
|
|
8
|
+
const adminCache = new ClusterCache("EditorCache[" + app.options.name + "]");
|
|
9
|
+
return {
|
|
10
|
+
getCache: () => adminCache,
|
|
11
|
+
stop: () => app.stop(),
|
|
12
|
+
restart: () => app.restart(),
|
|
13
|
+
reload: () => app.reload(),
|
|
14
|
+
getHotReloadHTML: getHotReloadScript,
|
|
15
|
+
getMigrations: () => {
|
|
16
|
+
if (app.inflated) {
|
|
17
|
+
const ret: MigrationModule[] = [];
|
|
18
|
+
for (const db of app.inflated.dbList) {
|
|
19
|
+
for (const m of db.migrations) {
|
|
20
|
+
ret.push(m);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return ret;
|
|
24
|
+
}
|
|
25
|
+
return [];
|
|
26
|
+
},
|
|
27
|
+
getServices: () => {
|
|
28
|
+
return app.options.services;
|
|
29
|
+
},
|
|
30
|
+
getRouteFileMap: () => {
|
|
31
|
+
return app.inflated ? app.inflated.fileMap : {};
|
|
32
|
+
},
|
|
33
|
+
getInflateErrors: () => {
|
|
34
|
+
return app.inflated ? app.inflated.errors : [];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Logger } from "@miqro/core";
|
|
2
|
+
import { CacheInterface } from "../../types.js";
|
|
3
|
+
|
|
4
|
+
export class LocalCache implements CacheInterface {
|
|
5
|
+
private localCache = new Map<string, unknown>();
|
|
6
|
+
|
|
7
|
+
constructor(public name: string, public logger?: Logger) {
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
dispose() {
|
|
11
|
+
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
get<T = any>(key: string): T | undefined {
|
|
15
|
+
this.logger?.trace("get(%s)", key);
|
|
16
|
+
return this.localCache.get(key) as T;
|
|
17
|
+
}
|
|
18
|
+
set(key: string, value: unknown): void {
|
|
19
|
+
this.localCache.set(key, value);
|
|
20
|
+
this.logger?.trace("set(%s, ...)", key);
|
|
21
|
+
}
|
|
22
|
+
unset(key: string): void {
|
|
23
|
+
this.logger?.trace("unset(%s)", key);
|
|
24
|
+
this.localCache.delete(key);
|
|
25
|
+
}
|
|
26
|
+
has(key: string): boolean {
|
|
27
|
+
this.logger?.trace("has(%s)", key);
|
|
28
|
+
return this.localCache.has(key);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
set_add(key: string, value: unknown): void {
|
|
32
|
+
this.logger?.trace("set_add(%s)", key);
|
|
33
|
+
const list = this.localCache.has(key) ? this.localCache.get(key) : new Set<string>();
|
|
34
|
+
if (!(list instanceof Set)) {
|
|
35
|
+
throw new Error("cannot apply on non Set");
|
|
36
|
+
}
|
|
37
|
+
if (!list.has(value)) {
|
|
38
|
+
list.add(value);
|
|
39
|
+
}
|
|
40
|
+
this.localCache.set(key, list);
|
|
41
|
+
}
|
|
42
|
+
set_delete(key: string, value: unknown): void {
|
|
43
|
+
this.logger?.trace("set_delete(%s)", key);
|
|
44
|
+
const list = this.localCache.has(key) ? this.localCache.get(key) : new Set<string>();
|
|
45
|
+
if (!(list instanceof Set)) {
|
|
46
|
+
throw new Error("cannot apply on non Set");
|
|
47
|
+
}
|
|
48
|
+
if (list.has(value)) {
|
|
49
|
+
list.delete(value);
|
|
50
|
+
}
|
|
51
|
+
this.localCache.set(key, list);
|
|
52
|
+
}
|
|
53
|
+
set_has(key: string, value: unknown): boolean {
|
|
54
|
+
this.logger?.trace("set_has(%s)", key);
|
|
55
|
+
const list = this.localCache.has(key) ? this.localCache.get(key) : new Set<string>();
|
|
56
|
+
if (!(list instanceof Set)) {
|
|
57
|
+
throw new Error("cannot apply on non Set");
|
|
58
|
+
}
|
|
59
|
+
const ret = list.has(value);
|
|
60
|
+
this.localCache.set(key, list);
|
|
61
|
+
return ret;
|
|
62
|
+
}
|
|
63
|
+
set_clear(key: string): void {
|
|
64
|
+
this.logger?.trace("set_clear(%s)", key);
|
|
65
|
+
const list = this.localCache.has(key) ? this.localCache.get(key) : new Set<string>();
|
|
66
|
+
if (!(list instanceof Set)) {
|
|
67
|
+
throw new Error("cannot apply on non Set");
|
|
68
|
+
}
|
|
69
|
+
list.clear();
|
|
70
|
+
this.localCache.set(key, list);
|
|
71
|
+
}
|
|
72
|
+
array_push(key: string, value: unknown): void {
|
|
73
|
+
this.logger?.trace("array_push(%s)", key);
|
|
74
|
+
const list = this.localCache.has(key) ? this.localCache.get(key) : [];
|
|
75
|
+
if (!(list instanceof Array)) {
|
|
76
|
+
throw new Error("cannot apply on non Array");
|
|
77
|
+
}
|
|
78
|
+
list.push(value);
|
|
79
|
+
this.localCache.set(key, list);
|
|
80
|
+
}
|
|
81
|
+
array_clear(key: string): void {
|
|
82
|
+
this.logger?.trace("array_clear(%s)", key);
|
|
83
|
+
if (this.localCache.has(key) && !(this.localCache.get(key) instanceof Array)) {
|
|
84
|
+
throw new Error("cannot apply on non Array");
|
|
85
|
+
}
|
|
86
|
+
this.localCache.set(key, []);
|
|
87
|
+
}
|
|
88
|
+
}
|