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,40 @@
|
|
|
1
|
+
import { JSONParser } from "@miqro/core";
|
|
2
|
+
import { existsSync, mkdirSync, renameSync } from "node:fs";
|
|
3
|
+
import { getPath } from "./read.api.js";
|
|
4
|
+
import { dirname } from "node:path";
|
|
5
|
+
export default {
|
|
6
|
+
middleware: [JSONParser()],
|
|
7
|
+
method: "POST",
|
|
8
|
+
description: "admin editor file rename endpoint",
|
|
9
|
+
path: "/rename",
|
|
10
|
+
request: {
|
|
11
|
+
body: {
|
|
12
|
+
path: "string",
|
|
13
|
+
newName: "string"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
response: {
|
|
17
|
+
status: [200, 400],
|
|
18
|
+
body: {
|
|
19
|
+
message: "string"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
handler: async (req, res) => {
|
|
23
|
+
const { path, newName } = req.body;
|
|
24
|
+
await rename(path, newName);
|
|
25
|
+
return res?.json({
|
|
26
|
+
message: "OK"
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
export async function rename(path, newName) {
|
|
31
|
+
if (existsSync(path) && !existsSync(newName)) {
|
|
32
|
+
mkdirSync(dirname(getPath(newName)), {
|
|
33
|
+
recursive: true
|
|
34
|
+
});
|
|
35
|
+
renameSync(getPath(path), getPath(newName));
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
throw new Error("invalid paths");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { APIRoute } from "@miqro/core";
|
|
2
|
+
import { AdminRequest } from "../../../../../common/admin-interface.js";
|
|
3
|
+
export interface ScannedFile {
|
|
4
|
+
filePath: string;
|
|
5
|
+
ext: string;
|
|
6
|
+
fileName: string;
|
|
7
|
+
name: string;
|
|
8
|
+
subExt: string;
|
|
9
|
+
subName: string;
|
|
10
|
+
language: string;
|
|
11
|
+
previewPath?: string;
|
|
12
|
+
dirs: string[];
|
|
13
|
+
apiPreview?: {
|
|
14
|
+
path: string;
|
|
15
|
+
method: string;
|
|
16
|
+
}[];
|
|
17
|
+
}
|
|
18
|
+
declare const _default: APIRoute;
|
|
19
|
+
export default _default;
|
|
20
|
+
export declare function scanDir(req: AdminRequest, basePath?: string, ret?: ScannedFile[]): ScannedFile[];
|
|
21
|
+
export declare function getLanguage(filePath: string): string;
|
|
22
|
+
export declare function getPreview(req: AdminRequest, filePath: string): undefined | string;
|
|
23
|
+
export declare function getAPIPreview(req: any, filePath: string): undefined | {
|
|
24
|
+
path: string;
|
|
25
|
+
method: string;
|
|
26
|
+
}[];
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { JSONParser } from "@miqro/core";
|
|
2
|
+
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
3
|
+
import { basename, dirname, extname, relative, resolve, sep } from "node:path";
|
|
4
|
+
import { BASE_PATH } from "../../../../../common/constants.server.js";
|
|
5
|
+
export default {
|
|
6
|
+
method: "GET",
|
|
7
|
+
path: "/scan",
|
|
8
|
+
description: "admin editor file scan endpoint",
|
|
9
|
+
middleware: [JSONParser()],
|
|
10
|
+
request: {
|
|
11
|
+
body: false
|
|
12
|
+
},
|
|
13
|
+
response: {
|
|
14
|
+
status: [200, 400]
|
|
15
|
+
},
|
|
16
|
+
handler: async (req, res) => {
|
|
17
|
+
const admin = req.editor;
|
|
18
|
+
const services = admin ? admin.getServices() : ["."];
|
|
19
|
+
return res.json({
|
|
20
|
+
files: scanDir(req),
|
|
21
|
+
services
|
|
22
|
+
});
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
export function scanDir(req, basePath = BASE_PATH, ret = []) {
|
|
26
|
+
const admin = req.editor;
|
|
27
|
+
const services = admin ? admin.getServices() : ["."];
|
|
28
|
+
services.forEach(service => {
|
|
29
|
+
scanDirInternal(req, resolve(basePath, service), ret);
|
|
30
|
+
});
|
|
31
|
+
return ret;
|
|
32
|
+
}
|
|
33
|
+
function scanDirInternal(req, path = BASE_PATH, ret = []) {
|
|
34
|
+
if (!existsSync(path)) {
|
|
35
|
+
return ret;
|
|
36
|
+
}
|
|
37
|
+
const files = readdirSync(path);
|
|
38
|
+
for (const file of files) {
|
|
39
|
+
if (shouldIgnoreFile(file)) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const filePath = resolve(path, file);
|
|
43
|
+
if (statSync(filePath).isDirectory()) {
|
|
44
|
+
scanDirInternal(req, filePath, ret);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
const ext = extname(filePath);
|
|
49
|
+
const fileName = basename(filePath);
|
|
50
|
+
const name = fileName.substring(0, fileName.length - ext.length);
|
|
51
|
+
const subExt = extname(name);
|
|
52
|
+
const subName = name.substring(0, name.length - subExt.length);
|
|
53
|
+
ret.push({
|
|
54
|
+
dirs: getFileDirs(relative(BASE_PATH, filePath)),
|
|
55
|
+
language: getLanguage(filePath),
|
|
56
|
+
filePath: relative(BASE_PATH, filePath),
|
|
57
|
+
ext,
|
|
58
|
+
fileName,
|
|
59
|
+
name,
|
|
60
|
+
subExt,
|
|
61
|
+
subName,
|
|
62
|
+
previewPath: getPreview(req, filePath),
|
|
63
|
+
apiPreview: getAPIPreview(req, filePath)
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return ret;
|
|
68
|
+
}
|
|
69
|
+
function shouldIgnoreFile(file) {
|
|
70
|
+
return file === ".git" || file === ".types" || file === ".DS_Store" || file === "node_modules";
|
|
71
|
+
}
|
|
72
|
+
function getFileDirs(filePath) {
|
|
73
|
+
const dirs = [];
|
|
74
|
+
let dir = dirname(filePath);
|
|
75
|
+
while (dir !== sep && dir !== "" && dir !== "." && dir !== BASE_PATH) {
|
|
76
|
+
dirs.push(dir);
|
|
77
|
+
dir = dirname(dir);
|
|
78
|
+
}
|
|
79
|
+
return dirs.reverse().map(d => basename(d));
|
|
80
|
+
}
|
|
81
|
+
export function getLanguage(filePath) {
|
|
82
|
+
const ext = extname(filePath);
|
|
83
|
+
const fileName = basename(filePath);
|
|
84
|
+
switch (ext.toLocaleLowerCase()) {
|
|
85
|
+
case ".py":
|
|
86
|
+
return "python";
|
|
87
|
+
case ".sh":
|
|
88
|
+
return "bash";
|
|
89
|
+
case ".webmanifest":
|
|
90
|
+
case ".json":
|
|
91
|
+
return "json";
|
|
92
|
+
case ".xml":
|
|
93
|
+
return "xml";
|
|
94
|
+
case ".jsx":
|
|
95
|
+
case ".js":
|
|
96
|
+
return "javascript";
|
|
97
|
+
case ".tsx":
|
|
98
|
+
case ".ts":
|
|
99
|
+
case "d.ts":
|
|
100
|
+
return "typescript";
|
|
101
|
+
case ".htm":
|
|
102
|
+
case ".html":
|
|
103
|
+
return "html";
|
|
104
|
+
case ".scss":
|
|
105
|
+
case ".css":
|
|
106
|
+
return "css";
|
|
107
|
+
case ".md":
|
|
108
|
+
return "markdown";
|
|
109
|
+
case ".c":
|
|
110
|
+
return "c";
|
|
111
|
+
case ".h":
|
|
112
|
+
case ".cpp":
|
|
113
|
+
return "cpp";
|
|
114
|
+
case ".yml":
|
|
115
|
+
case ".yaml":
|
|
116
|
+
return "yaml";
|
|
117
|
+
case ".txt":
|
|
118
|
+
case ".log":
|
|
119
|
+
return "text";
|
|
120
|
+
default:
|
|
121
|
+
switch (fileName) {
|
|
122
|
+
case "dockerfile":
|
|
123
|
+
return "dockerfile";
|
|
124
|
+
case ".gitignore":
|
|
125
|
+
return "text";
|
|
126
|
+
}
|
|
127
|
+
return "text";
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
export function getPreview(req, filePath) {
|
|
131
|
+
const admin = req.editor;
|
|
132
|
+
const inflateData = admin ? admin.getRouteFileMap()[filePath] : undefined;
|
|
133
|
+
if (inflateData) {
|
|
134
|
+
return inflateData.previewMethod === "html" ? inflateData.routes[0].path : undefined;
|
|
135
|
+
}
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
export function getAPIPreview(req, filePath) {
|
|
139
|
+
const admin = req.editor;
|
|
140
|
+
const inflateData = admin ? admin.getRouteFileMap()[filePath] : undefined;
|
|
141
|
+
if (inflateData) {
|
|
142
|
+
return inflateData.previewMethod === "api" ? inflateData.routes.map(r => {
|
|
143
|
+
return {
|
|
144
|
+
path: r.path,
|
|
145
|
+
method: r.method ? r.method : "GET"
|
|
146
|
+
};
|
|
147
|
+
}) : undefined;
|
|
148
|
+
}
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { JSONParser } from "@miqro/core";
|
|
2
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { getPath } from "./read.api.js";
|
|
4
|
+
import { dirname } from "node:path";
|
|
5
|
+
export default {
|
|
6
|
+
middleware: [JSONParser()],
|
|
7
|
+
method: "POST",
|
|
8
|
+
path: "/write",
|
|
9
|
+
description: "admin editor file write endpoint",
|
|
10
|
+
request: {
|
|
11
|
+
body: {
|
|
12
|
+
path: "string",
|
|
13
|
+
contents: "string",
|
|
14
|
+
override: "boolean?"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
response: {
|
|
18
|
+
status: [200, 400],
|
|
19
|
+
body: {
|
|
20
|
+
message: "string"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
handler: async (req, res) => {
|
|
24
|
+
const { path, contents, override } = req.body;
|
|
25
|
+
await writeFile(path, contents, override);
|
|
26
|
+
return res.json({
|
|
27
|
+
message: "OK"
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
async function writeFile(path, contents, override) {
|
|
32
|
+
if (existsSync(getPath(path)) && !override) {
|
|
33
|
+
throw new Error("file already exists!");
|
|
34
|
+
}
|
|
35
|
+
mkdirSync(dirname(getPath(path)), {
|
|
36
|
+
recursive: true
|
|
37
|
+
});
|
|
38
|
+
writeFileSync(getPath(path), contents);
|
|
39
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { relative } from "node:path";
|
|
2
|
+
import { BASE_PATH } from "../../../../../common/constants.server.js";
|
|
3
|
+
export default {
|
|
4
|
+
method: "POST",
|
|
5
|
+
path: "/reload",
|
|
6
|
+
description: "admin editor server reload endpoint. reloads the server without closing the port",
|
|
7
|
+
middleware: [],
|
|
8
|
+
request: {
|
|
9
|
+
body: false
|
|
10
|
+
},
|
|
11
|
+
response: {
|
|
12
|
+
status: [200, 400],
|
|
13
|
+
body: {
|
|
14
|
+
message: "string",
|
|
15
|
+
reloadString: "string",
|
|
16
|
+
migrations: "string[]",
|
|
17
|
+
errors: {
|
|
18
|
+
allowNull: true,
|
|
19
|
+
type: "array",
|
|
20
|
+
arrayType: "object",
|
|
21
|
+
properties: {
|
|
22
|
+
filePath: "string",
|
|
23
|
+
error: "string"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
handler: async (req, res) => {
|
|
29
|
+
const errors = await req?.editor?.reload();
|
|
30
|
+
const parsedErrors = parseInflateErrors(errors);
|
|
31
|
+
return res.json({
|
|
32
|
+
message: "OK",
|
|
33
|
+
reloadString: req.uuid,
|
|
34
|
+
migrations: req?.editor?.getMigrations().map(m => m.name),
|
|
35
|
+
errors: parsedErrors ? parsedErrors : []
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
export function parseInflateErrors(errors) {
|
|
40
|
+
return errors?.map(error => {
|
|
41
|
+
return {
|
|
42
|
+
filePath: relative(BASE_PATH, error.filePath),
|
|
43
|
+
error: error.error.message
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { JSONParser } from "@miqro/core";
|
|
2
|
+
import { relative } from "node:path";
|
|
3
|
+
import { BASE_PATH } from "../../../../../common/constants.server.js";
|
|
4
|
+
export default {
|
|
5
|
+
method: "POST",
|
|
6
|
+
path: "/restart",
|
|
7
|
+
description: "admin editor server restart endpoint",
|
|
8
|
+
middleware: [JSONParser()],
|
|
9
|
+
request: {
|
|
10
|
+
body: false
|
|
11
|
+
},
|
|
12
|
+
response: {
|
|
13
|
+
status: [200, 400],
|
|
14
|
+
body: {
|
|
15
|
+
message: "string",
|
|
16
|
+
reloadString: "string",
|
|
17
|
+
migrations: "string[]",
|
|
18
|
+
errors: {
|
|
19
|
+
allowNull: true,
|
|
20
|
+
type: "array",
|
|
21
|
+
arrayType: "object",
|
|
22
|
+
properties: {
|
|
23
|
+
filePath: "string",
|
|
24
|
+
error: "string"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
handler: async (req, res) => {
|
|
30
|
+
const errors = await req?.editor?.restart();
|
|
31
|
+
return res.json({
|
|
32
|
+
message: "OK",
|
|
33
|
+
reloadString: req.uuid,
|
|
34
|
+
migrations: req?.editor?.getMigrations().map(m => m.name),
|
|
35
|
+
errors: parseInflateErrors(errors)
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
export function parseInflateErrors(errors) {
|
|
40
|
+
return errors?.map(error => {
|
|
41
|
+
return {
|
|
42
|
+
filePath: relative(BASE_PATH, error.filePath),
|
|
43
|
+
error: error.error.message
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { define } from "@miqro/jsx-dom";
|
|
2
|
+
//import "../../../../.types/browser.globals";
|
|
3
|
+
import { Editor } from "../../../components/editor.js";
|
|
4
|
+
window.addEventListener("load", async (event) => {
|
|
5
|
+
define("editor-component", Editor, {
|
|
6
|
+
shadowInit: false
|
|
7
|
+
});
|
|
8
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import JSX from "@miqro/jsx";
|
|
2
|
+
import { scanDir } from "./api/fs/scan.api.js";
|
|
3
|
+
import { HTMLEncode } from "../../../common/html-encode.js";
|
|
4
|
+
export default {
|
|
5
|
+
description: "ADMIN EDITOR GUI",
|
|
6
|
+
path: "/",
|
|
7
|
+
method: "GET",
|
|
8
|
+
handler: async (req, res) => {
|
|
9
|
+
const admin = req.editor;
|
|
10
|
+
const errors = admin ? admin.getInflateErrors() : [];
|
|
11
|
+
const files = scanDir(req);
|
|
12
|
+
const migrations = admin ? admin.getMigrations().map(m => m.name) : [];
|
|
13
|
+
const services = admin ? admin.getServices() : ["."];
|
|
14
|
+
return res.html("<!DOCTYPE html>" + String(JSX.createElement("html", null,
|
|
15
|
+
JSX.createElement("head", null,
|
|
16
|
+
JSX.createElement("link", { rel: "stylesheet", href: "/admin/editor/style.css" })),
|
|
17
|
+
JSX.createElement("body", null,
|
|
18
|
+
JSX.createElement("script", { type: "module", src: "/admin/editor/editor.js" }),
|
|
19
|
+
JSX.createElement("editor-component", { disablelog: "true", disablepreview: "true", disablereload: "true", class: "main-container", reloadstring: `${req?.uuid}`, migrations: `${HTMLEncode(JSON.stringify(migrations))}`, services: `${HTMLEncode(JSON.stringify(services))}`, errors: `${HTMLEncode(JSON.stringify(errors))}`, files: `${HTMLEncode(JSON.stringify(files))}` },
|
|
20
|
+
JSX.createElement("noscript", null, "Enable JavaScript"))))));
|
|
21
|
+
}
|
|
22
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { BASEEDITOR_PATH } from "./common/constants.js";
|
|
3
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
import { relative, resolve } from "node:path";
|
|
5
|
+
import { ADMIN_EDITOR_AUTH_KEY, ADMIN_EDITOR_AUTH_QUERY } from "./auth.js";
|
|
6
|
+
//import { getEditorAdmin } from "./common/admin-interface.js";
|
|
7
|
+
const ADMIN_EDITOR_BROWSER_OPEN_KEY = "ADMIN_EDITOR_BROWSER_OPEN_KEY$$";
|
|
8
|
+
export default {
|
|
9
|
+
preload: (serverInterface, adminInterface) => {
|
|
10
|
+
//console.dir(server);
|
|
11
|
+
if (serverInterface?.isPrimaryWorker()) {
|
|
12
|
+
const cache = (adminInterface ? adminInterface.getCache() : serverInterface.cache);
|
|
13
|
+
if (!cache.has(ADMIN_EDITOR_AUTH_KEY)) {
|
|
14
|
+
const adminKEYPath = resolve(".admin_key");
|
|
15
|
+
if (existsSync(adminKEYPath)) {
|
|
16
|
+
serverInterface.logger.warn("loading static ADMIN_KEY from [%s]", relative(process.cwd(), adminKEYPath));
|
|
17
|
+
cache.set(ADMIN_EDITOR_AUTH_KEY, readFileSync(adminKEYPath).toString().trim());
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
cache.set(ADMIN_EDITOR_AUTH_KEY, randomUUID());
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
start: (serverInterface, adminInterface) => {
|
|
26
|
+
//console.dir(server);
|
|
27
|
+
const cache = (adminInterface ? adminInterface.getCache() : serverInterface.cache);
|
|
28
|
+
if (!cache.has(ADMIN_EDITOR_BROWSER_OPEN_KEY)) {
|
|
29
|
+
const KEY = cache.get(ADMIN_EDITOR_AUTH_KEY);
|
|
30
|
+
const adminPath = `${BASEEDITOR_PATH}?${ADMIN_EDITOR_AUTH_QUERY}=${KEY}`;
|
|
31
|
+
if (serverInterface?.isPrimaryWorker()) {
|
|
32
|
+
serverInterface.logger.log("\n\n\tADMIN_EDITOR\n\n\t%s\n\n", adminPath);
|
|
33
|
+
}
|
|
34
|
+
//const DEFAULT_OPEN = process.platform === "win32" ? "explorer" : process.platform === "darwin" ? "open" : "xdg-open";
|
|
35
|
+
//const OPEN = process.env["BROWSER"] ? process.env["BROWSER"] === "none" ? false : process.env["BROWSER"] : DEFAULT_OPEN;
|
|
36
|
+
if (serverInterface.isPrimaryWorker()) {
|
|
37
|
+
cache.set(ADMIN_EDITOR_BROWSER_OPEN_KEY, true);
|
|
38
|
+
try {
|
|
39
|
+
serverInterface.openBrowser(`${BASEEDITOR_PATH}?${ADMIN_EDITOR_AUTH_QUERY}=${KEY}`);
|
|
40
|
+
//serverInterface.logger.log(`${OPEN} "${adminPath}"`);
|
|
41
|
+
//execSync(`${OPEN} "${adminPath}"`);
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
serverInterface.logger.error(e.message);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { LOG_SOCKET_PATH } from "./common/constants.js";
|
|
2
|
+
export default {
|
|
3
|
+
path: LOG_SOCKET_PATH,
|
|
4
|
+
validate(req) {
|
|
5
|
+
const admin = req.editor;
|
|
6
|
+
const cache = (admin ? admin.getCache() : req.server.cache);
|
|
7
|
+
const KEY = cache.get("AUTH_KEY");
|
|
8
|
+
const cookieToken = req.cookies["auth"];
|
|
9
|
+
return cookieToken === KEY ? true : false;
|
|
10
|
+
},
|
|
11
|
+
};
|
|
@@ -79,7 +79,14 @@ async function main() {
|
|
|
79
79
|
|
|
80
80
|
${!WSLIST ? "" : `\n webSocketManager.replaceALLWS(await Promise.all([${WSLIST}]))`}
|
|
81
81
|
const app = new App({
|
|
82
|
-
onUpgrade:
|
|
82
|
+
onUpgrade: (req, socket, head) => {
|
|
83
|
+
try {
|
|
84
|
+
req.server = serverInterface;
|
|
85
|
+
return webSocketManager.onUpgrade(req, socket, head);
|
|
86
|
+
} catch(e) {
|
|
87
|
+
console.error(e);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
83
90
|
});
|
|
84
91
|
${SERVERCONFIGLIST ? `\n await Promise.all([${SERVERCONFIGLIST}].filter(config=>config.preload).map(config=>config.preload(serverInterface)));\n` : ""}
|
|
85
92
|
app.use(ServerRequestHandler(serverInterface));
|
|
@@ -351,8 +351,13 @@ export class Miqro {
|
|
|
351
351
|
await this.dbManager.connectAll();
|
|
352
352
|
this.server = new App({
|
|
353
353
|
onUpgrade: (req, socket, head) => {
|
|
354
|
-
|
|
355
|
-
|
|
354
|
+
try {
|
|
355
|
+
req.server = this.serverInterface;
|
|
356
|
+
return this.webSocketManager.onUpgrade(req, socket, head);
|
|
357
|
+
}
|
|
358
|
+
catch (e) {
|
|
359
|
+
this.logger?.error(e);
|
|
360
|
+
}
|
|
356
361
|
},
|
|
357
362
|
loggerFactory: this.loggerProvider.requestLoggerFactory,
|
|
358
363
|
serverOptions: this.options?.serverOptions,
|
package/build/lib.cjs
CHANGED
|
@@ -13095,7 +13095,14 @@ async function main() {
|
|
|
13095
13095
|
${!WSLIST ? "" : `
|
|
13096
13096
|
webSocketManager.replaceALLWS(await Promise.all([${WSLIST}]))`}
|
|
13097
13097
|
const app = new App({
|
|
13098
|
-
onUpgrade:
|
|
13098
|
+
onUpgrade: (req, socket, head) => {
|
|
13099
|
+
try {
|
|
13100
|
+
req.server = serverInterface;
|
|
13101
|
+
return webSocketManager.onUpgrade(req, socket, head);
|
|
13102
|
+
} catch(e) {
|
|
13103
|
+
console.error(e);
|
|
13104
|
+
}
|
|
13105
|
+
}
|
|
13099
13106
|
});
|
|
13100
13107
|
${SERVERCONFIGLIST ? `
|
|
13101
13108
|
await Promise.all([${SERVERCONFIGLIST}].filter(config=>config.preload).map(config=>config.preload(serverInterface)));
|
|
@@ -17237,8 +17244,12 @@ var Miqro = class _Miqro {
|
|
|
17237
17244
|
await this.dbManager.connectAll();
|
|
17238
17245
|
this.server = new App({
|
|
17239
17246
|
onUpgrade: (req, socket, head) => {
|
|
17240
|
-
|
|
17241
|
-
|
|
17247
|
+
try {
|
|
17248
|
+
req.server = this.serverInterface;
|
|
17249
|
+
return this.webSocketManager.onUpgrade(req, socket, head);
|
|
17250
|
+
} catch (e) {
|
|
17251
|
+
this.logger?.error(e);
|
|
17252
|
+
}
|
|
17242
17253
|
},
|
|
17243
17254
|
loggerFactory: this.loggerProvider.requestLoggerFactory,
|
|
17244
17255
|
serverOptions: this.options?.serverOptions,
|
package/editor/auth.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { AuthConfig, ServerRequest } from "../src/types.js";
|
|
2
|
+
import { AdminRequest } from "./common/admin-interface.js";
|
|
3
|
+
|
|
4
|
+
export const ADMIN_EDITOR_AUTH_KEY = "$$ADMIN_EDITOR_AUTH_KEY$$";
|
|
5
|
+
|
|
6
|
+
export const ADMIN_EDITOR_AUTH_QUERY = "key";
|
|
7
|
+
export const ADMIN_EDITOR_AUTH_COOKIE = ADMIN_EDITOR_AUTH_KEY;
|
|
8
|
+
|
|
9
|
+
export default {
|
|
10
|
+
authService: {
|
|
11
|
+
verify: async (args) => {
|
|
12
|
+
|
|
13
|
+
const adminInterface = (args.req as AdminRequest).editor;
|
|
14
|
+
const serverInterface = (args.req as any as ServerRequest).server;
|
|
15
|
+
const KEY = (adminInterface ? adminInterface.getCache() : serverInterface.cache).get<string>(ADMIN_EDITOR_AUTH_KEY);
|
|
16
|
+
|
|
17
|
+
const validSesson = {
|
|
18
|
+
username: "username",
|
|
19
|
+
account: "account",
|
|
20
|
+
groups: [],
|
|
21
|
+
token: args.token
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const queryToken = args.req.query[ADMIN_EDITOR_AUTH_QUERY];
|
|
25
|
+
const cookieToken = args.req.cookies[ADMIN_EDITOR_AUTH_COOKIE];
|
|
26
|
+
|
|
27
|
+
//console.log("\n\nqueryToken[%s] cookieToken[%s] KEY[%s]\n\n", queryToken, cookieToken, KEY);
|
|
28
|
+
|
|
29
|
+
if (queryToken) {
|
|
30
|
+
if (queryToken === KEY) {
|
|
31
|
+
args.res.setCookie(ADMIN_EDITOR_AUTH_COOKIE, KEY, {
|
|
32
|
+
expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 31 * 12 * 500),
|
|
33
|
+
httpOnly: true,
|
|
34
|
+
|
|
35
|
+
//secure: true,
|
|
36
|
+
path: "/",
|
|
37
|
+
//sameSite: "strict"
|
|
38
|
+
});
|
|
39
|
+
args.req.searchParams.delete(ADMIN_EDITOR_AUTH_QUERY);
|
|
40
|
+
const queryString = args.req.searchParams.toString();
|
|
41
|
+
const redirect = args.req.path + (queryString ? "?" + queryString : "");
|
|
42
|
+
await args.res.redirect(redirect);
|
|
43
|
+
return validSesson;
|
|
44
|
+
}
|
|
45
|
+
} else if (cookieToken) {
|
|
46
|
+
return cookieToken === KEY ? validSesson : null;
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
} as AuthConfig;
|