miqro 7.2.7 → 7.2.9

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 (97) hide show
  1. package/build/esm/editor/auth.d.ts +6 -0
  2. package/build/esm/editor/auth.js +42 -0
  3. package/build/esm/editor/common/constants.d.ts +4 -0
  4. package/build/esm/editor/common/constants.js +20 -0
  5. package/build/esm/editor/common/constants.server.d.ts +2 -0
  6. package/build/esm/editor/common/constants.server.js +4 -0
  7. package/build/esm/editor/common/editor-index.d.ts +2 -0
  8. package/build/esm/editor/common/editor-index.js +14 -0
  9. package/build/esm/editor/common/html-encode.d.ts +1 -0
  10. package/build/esm/editor/common/html-encode.js +14 -0
  11. package/build/esm/editor/common/log-socket.d.ts +15 -0
  12. package/build/esm/editor/common/log-socket.js +71 -0
  13. package/build/esm/editor/common/templates.d.ts +11 -0
  14. package/build/esm/editor/common/templates.js +477 -0
  15. package/build/esm/editor/components/api-preview.d.ts +11 -0
  16. package/build/esm/editor/components/api-preview.js +92 -0
  17. package/build/esm/editor/components/editor.d.ts +16 -0
  18. package/build/esm/editor/components/editor.js +367 -0
  19. package/build/esm/editor/components/file-browser.d.ts +37 -0
  20. package/build/esm/editor/components/file-browser.js +127 -0
  21. package/build/esm/editor/components/file-editor-toolbar.d.ts +22 -0
  22. package/build/esm/editor/components/file-editor-toolbar.js +95 -0
  23. package/build/esm/editor/components/file-editor.d.ts +32 -0
  24. package/build/esm/editor/components/file-editor.js +61 -0
  25. package/build/esm/editor/components/filter-query.d.ts +1 -0
  26. package/build/esm/editor/components/filter-query.js +23 -0
  27. package/build/esm/editor/components/highlight-text-area.d.ts +11 -0
  28. package/build/esm/editor/components/highlight-text-area.js +127 -0
  29. package/build/esm/editor/components/log-viewer.d.ts +6 -0
  30. package/build/esm/editor/components/log-viewer.js +71 -0
  31. package/build/esm/editor/components/new-file.d.ts +10 -0
  32. package/build/esm/editor/components/new-file.js +119 -0
  33. package/build/esm/editor/components/scroll-query.d.ts +7 -0
  34. package/build/esm/editor/components/scroll-query.js +22 -0
  35. package/build/esm/editor/components/start-page.d.ts +13 -0
  36. package/build/esm/editor/components/start-page.js +32 -0
  37. package/build/esm/editor/http/admin/editor/api/fs/delete.api.d.ts +4 -0
  38. package/build/esm/editor/http/admin/editor/api/fs/delete.api.js +30 -0
  39. package/build/esm/editor/http/admin/editor/api/fs/read.api.d.ts +7 -0
  40. package/build/esm/editor/http/admin/editor/api/fs/read.api.js +50 -0
  41. package/build/esm/editor/http/admin/editor/api/fs/rename.api.d.ts +7 -0
  42. package/build/esm/editor/http/admin/editor/api/fs/rename.api.js +40 -0
  43. package/build/esm/editor/http/admin/editor/api/fs/scan.api.d.ts +26 -0
  44. package/build/esm/editor/http/admin/editor/api/fs/scan.api.js +150 -0
  45. package/build/esm/editor/http/admin/editor/api/fs/write.api.d.ts +3 -0
  46. package/build/esm/editor/http/admin/editor/api/fs/write.api.js +39 -0
  47. package/build/esm/editor/http/admin/editor/api/server/reload.api.d.ts +10 -0
  48. package/build/esm/editor/http/admin/editor/api/server/reload.api.js +46 -0
  49. package/build/esm/editor/http/admin/editor/api/server/restart.api.d.ts +10 -0
  50. package/build/esm/editor/http/admin/editor/api/server/restart.api.js +46 -0
  51. package/build/esm/editor/http/admin/editor/editor.d.ts +1 -0
  52. package/build/esm/editor/http/admin/editor/editor.js +8 -0
  53. package/build/esm/editor/http/admin/editor/index.api.d.ts +3 -0
  54. package/build/esm/editor/http/admin/editor/index.api.js +23 -0
  55. package/build/esm/editor/server.d.ts +3 -0
  56. package/build/esm/editor/server.js +49 -0
  57. package/build/esm/editor/ws.d.ts +3 -0
  58. package/build/esm/editor/ws.js +12 -0
  59. package/build/esm/src/common/admin-interface.d.ts +36 -0
  60. package/build/esm/src/common/admin-interface.js +44 -0
  61. package/build/esm/src/common/exit.js +18 -2
  62. package/build/esm/src/common/watch.js +8 -3
  63. package/build/esm/src/services/app.d.ts +1 -1
  64. package/build/esm/src/services/editor.d.ts +1 -1
  65. package/build/esm/src/services/utils/admin-interface.d.ts +1 -1
  66. package/build/esm/src/services/utils/websocketmanager.d.ts +1 -1
  67. package/build/lib.cjs +48 -20
  68. package/editor/auth.ts +52 -0
  69. package/editor/common/constants.server.ts +5 -0
  70. package/editor/common/constants.ts +21 -0
  71. package/editor/common/editor-index.tsx +17 -0
  72. package/editor/common/html-encode.ts +14 -0
  73. package/editor/common/log-socket.tsx +87 -0
  74. package/editor/common/templates.ts +481 -0
  75. package/editor/components/api-preview.tsx +118 -0
  76. package/editor/components/editor.tsx +496 -0
  77. package/editor/components/file-browser.tsx +311 -0
  78. package/editor/components/file-editor-toolbar.tsx +194 -0
  79. package/editor/components/file-editor.tsx +125 -0
  80. package/editor/components/filter-query.tsx +26 -0
  81. package/editor/components/highlight-text-area.tsx +148 -0
  82. package/editor/components/log-viewer.tsx +113 -0
  83. package/editor/components/new-file.tsx +172 -0
  84. package/editor/components/scroll-query.tsx +25 -0
  85. package/editor/components/start-page.tsx +52 -0
  86. package/editor/http/admin/editor/api/fs/delete.api.tsx +32 -0
  87. package/editor/http/admin/editor/api/fs/read.api.tsx +55 -0
  88. package/editor/http/admin/editor/api/fs/rename.api.tsx +41 -0
  89. package/editor/http/admin/editor/api/fs/scan.api.tsx +181 -0
  90. package/editor/http/admin/editor/api/fs/write.api.tsx +41 -0
  91. package/editor/http/admin/editor/api/server/reload.api.ts +53 -0
  92. package/editor/http/admin/editor/api/server/restart.api.tsx +52 -0
  93. package/editor/http/admin/editor/editor.tsx +10 -0
  94. package/editor/http/admin/editor/index.api.tsx +43 -0
  95. package/editor/server.ts +57 -0
  96. package/editor/ws.ts +17 -0
  97. package/package.json +2 -2
@@ -0,0 +1,32 @@
1
+ interface FileEditorProps {
2
+ current: boolean;
3
+ error: string;
4
+ path: string;
5
+ previewPath: string | undefined;
6
+ apiPreview: undefined | {
7
+ path: string;
8
+ method: string;
9
+ }[];
10
+ content: string | null;
11
+ contentchange: (content: string) => void;
12
+ closeFile: () => void;
13
+ saveFile: (reload?: boolean) => void;
14
+ revertFile: () => void;
15
+ deleteFile: () => void;
16
+ renameFile: (newName: any) => void;
17
+ setlanguage: (newLanguage: any) => void;
18
+ language: string;
19
+ changed: boolean;
20
+ reloadString: string;
21
+ togglePanel: (panel: string) => void;
22
+ isPanelVisible: (panel: string) => boolean;
23
+ disableLog?: boolean;
24
+ disablePreview?: boolean;
25
+ disableReload?: boolean;
26
+ }
27
+ export declare function FileEditor({ disableLog, disablePreview, disableReload, togglePanel, isPanelVisible, apiPreview, reloadString, error, revertFile, changed, setlanguage, saveFile, deleteFile, renameFile, current, path, previewPath, content, contentchange, closeFile, language }: FileEditorProps): JSX.Element;
28
+ export declare namespace FileEditor {
29
+ var asFragment: boolean;
30
+ var shadowInit: boolean;
31
+ }
32
+ export {};
@@ -0,0 +1,61 @@
1
+ import * as jsx from "@miqro/jsx";
2
+ import JSX from "@miqro/jsx";
3
+ import { APIPReview } from "./api-preview.js";
4
+ import { FileEditorToolbar } from "./file-editor-toolbar.js";
5
+ import { HighlightTextArea } from "./highlight-text-area.js";
6
+ import { useScroll } from "./scroll-query.js";
7
+ export function FileEditor({ disableLog, disablePreview, disableReload, togglePanel, isPanelVisible, apiPreview, reloadString, error, revertFile, changed, setlanguage, saveFile, deleteFile, renameFile, current, path, previewPath, content, contentchange, closeFile, language }) {
8
+ //console.log("FileEditor [%s]", path);
9
+ const iFrameRef = jsx.useRef();
10
+ const scrollRef = jsx.useRef();
11
+ const [scroll, setScroll] = useScroll();
12
+ jsx.useEffect(() => {
13
+ if (scrollRef.current) {
14
+ scrollRef.current.scrollLeft = scroll.scrollLeft;
15
+ scrollRef.current.scrollTop = scroll.scrollTop;
16
+ }
17
+ }, [scrollRef.current]);
18
+ jsx.useEffect(() => {
19
+ if (current && scrollRef.current) {
20
+ setScroll({
21
+ scrollLeft: scrollRef.current.scrollLeft,
22
+ scrollTop: scrollRef.current.scrollTop
23
+ }, true);
24
+ }
25
+ }, [current]);
26
+ jsx.useEffect(() => {
27
+ if (iFrameRef.current) {
28
+ iFrameRef.current.src = "";
29
+ iFrameRef.current.src = previewPath;
30
+ }
31
+ }, [iFrameRef.current, previewPath, reloadString]);
32
+ return JSX.createElement("div", { class: "file-editor" }, content === null ? JSX.createElement("p", null, "loading") : JSX.createElement(JSX.Fragment, null,
33
+ JSX.createElement(FileEditorToolbar, { disableLog: disableLog, disablePreview: disablePreview, disableReload: disableReload, isPanelVisible: isPanelVisible, togglePanel: togglePanel, revertFile: revertFile, closeFile: closeFile, language: language, path: path, changed: changed, saveFile: saveFile, setlanguage: setlanguage, deleteFile: deleteFile, renameFile: renameFile }),
34
+ JSX.createElement("div", {
35
+ //class={`file-editor-content${previewPath || apiPreview ? " split" : ""}`}
36
+ class: "file-editor-content" },
37
+ JSX.createElement("div", { ref: scrollRef, class: `file-editor-text-editor${previewPath || (apiPreview && apiPreview.length > 0) && isPanelVisible("right") ? " split" : ""}`,
38
+ //class={`file-editor-text-editor`}
39
+ onscroll: ev => {
40
+ setScroll({
41
+ scrollLeft: ev.target.scrollLeft,
42
+ scrollTop: ev.target.scrollTop
43
+ });
44
+ } },
45
+ error ?
46
+ JSX.createElement("p", { class: "file-editor-content-error" }, error)
47
+ : JSX.createElement(JSX.Fragment, null),
48
+ language !== "binary" ?
49
+ JSX.createElement(HighlightTextArea, { tabChar: " ", oncontentchange: (args) => {
50
+ if (contentchange) {
51
+ contentchange(args.detail);
52
+ }
53
+ }, content: content, language: language }) : JSX.createElement("p", null, "binary data not supported")),
54
+ apiPreview && apiPreview.length > 0 ? JSX.createElement(APIPReview, { isPanelVisible: isPanelVisible, apiPreview: apiPreview }) : JSX.createElement(JSX.Fragment, null),
55
+ previewPath && isPanelVisible("right") ? JSX.createElement("div", { class: `file-editor-preview`, style: `${!isPanelVisible("right") ? "display: none;" : ""}` },
56
+ JSX.createElement("div", { class: "file-editor-preview-path" },
57
+ JSX.createElement("a", { href: previewPath, target: "_blank" }, "open in new window")),
58
+ JSX.createElement("iframe", { ref: iFrameRef, src: previewPath, sandbox: "allow-scripts allow-same-origin" })) : JSX.createElement(JSX.Fragment, null))));
59
+ }
60
+ FileEditor.asFragment = true;
61
+ FileEditor.shadowInit = false;
@@ -0,0 +1 @@
1
+ export declare function useFilterQuery(): [string, (newFilter: string, inmediate?: boolean) => void];
@@ -0,0 +1,23 @@
1
+ import * as jsx from "@miqro/jsx";
2
+ let queryTimeout2 = null;
3
+ export function useFilterQuery() {
4
+ const [filterQuery, setfilterQuery] = jsx.useQuery("filter", "");
5
+ const [filter, setfilter] = jsx.useState(typeof filterQuery === "string" ? filterQuery : "");
6
+ return [
7
+ filter,
8
+ (newFilter, inmediate) => {
9
+ clearTimeout(queryTimeout2);
10
+ if (inmediate) {
11
+ setfilter(newFilter);
12
+ setfilterQuery(newFilter);
13
+ }
14
+ else {
15
+ setfilter(newFilter);
16
+ queryTimeout2 = setTimeout(() => {
17
+ setfilter(newFilter);
18
+ setfilterQuery(newFilter);
19
+ }, 1000);
20
+ }
21
+ }
22
+ ];
23
+ }
@@ -0,0 +1,11 @@
1
+ export declare function HighlightTextArea({ content, language, oncontentchange, tabChar, disabled }: {
2
+ language: string;
3
+ content: string;
4
+ disabled?: string;
5
+ tabChar?: string;
6
+ oncontentchange?: (ev: CustomEvent) => void;
7
+ }): JSX.Element;
8
+ export declare namespace HighlightTextArea {
9
+ var asFragment: boolean;
10
+ var shadowInit: boolean;
11
+ }
@@ -0,0 +1,127 @@
1
+ import * as jsx from "@miqro/jsx";
2
+ import JSX from "@miqro/jsx";
3
+ //import hljs from "../lib/highlight/core.min.js"
4
+ import hljs from 'highlight.js/lib/core';
5
+ import javascript from 'highlight.js/lib/languages/javascript';
6
+ import xml from "highlight.js/lib/languages/xml";
7
+ import css from "highlight.js/lib/languages/css";
8
+ import scss from "highlight.js/lib/languages/scss";
9
+ import markdown from "highlight.js/lib/languages/markdown";
10
+ import dockerfile from "highlight.js/lib/languages/dockerfile";
11
+ import yaml from "highlight.js/lib/languages/yaml";
12
+ import typescript from "highlight.js/lib/languages/typescript";
13
+ import c from "highlight.js/lib/languages/c";
14
+ import cpp from "highlight.js/lib/languages/cpp";
15
+ import bash from "highlight.js/lib/languages/bash";
16
+ import python from "highlight.js/lib/languages/python";
17
+ import text from "highlight.js/lib/languages/plaintext";
18
+ import json from "highlight.js/lib/languages/json";
19
+ // Then register the languages you need
20
+ hljs.registerLanguage('text', text);
21
+ hljs.registerLanguage('dockerfile', dockerfile);
22
+ hljs.registerLanguage('yaml', yaml);
23
+ hljs.registerLanguage('javascript', javascript);
24
+ hljs.registerLanguage('xml', xml);
25
+ hljs.registerLanguage('html', xml);
26
+ hljs.registerLanguage('css', css);
27
+ hljs.registerLanguage('scss', scss);
28
+ hljs.registerLanguage('markdown', markdown);
29
+ hljs.registerLanguage('typescript', typescript);
30
+ hljs.registerLanguage('c', c);
31
+ hljs.registerLanguage('cpp', cpp);
32
+ hljs.registerLanguage('bash', bash);
33
+ hljs.registerLanguage('python', python);
34
+ hljs.registerLanguage('json', json);
35
+ /*!
36
+ Theme: GitHub Dark
37
+ Description: Dark theme as seen on github.com
38
+ Author: github.com
39
+ Maintainer: @Hirse
40
+ Updated: 2021-05-15
41
+
42
+ Outdated base version: https://github.com/primer/github-syntax-dark
43
+ Current colors taken from GitHub's CSS
44
+ */
45
+ const STYLE = `pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#c9d1d9;background:#0d1117}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#ff7b72}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#d2a8ff}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#79c0ff}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#a5d6ff}.hljs-built_in,.hljs-symbol{color:#ffa657}.hljs-code,.hljs-comment,.hljs-formula{color:#8b949e}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#7ee787}.hljs-subst{color:#c9d1d9}.hljs-section{color:#1f6feb;font-weight:700}.hljs-bullet{color:#f2cc60}.hljs-emphasis{color:#c9d1d9;font-style:italic}.hljs-strong{color:#c9d1d9;font-weight:700}.hljs-addition{color:#aff5b4;background-color:#033a16}.hljs-deletion{color:#ffdcd7;background-color:#67060c}code{outline: 0px solid rgba(0, 0, 0, 0.263);caret-color: red;}.hljs-name{color: #e8910d;}.hljs-tag .hljs-attr, .hljs-tag .hljs-name{color: #e8910d;}`;
46
+ const POSTTYLE = "pre{padding:0; margin:0;} code { background-color: #000000; color: #ffffff; }";
47
+ const TAG_NAME = "HIGHLIGHT-TEXT-AREA";
48
+ function runHighlight(content, language) {
49
+ const now = Date.now();
50
+ console.log("runHighlight [%s]", language);
51
+ const value = hljs.highlight(String(content), {
52
+ language,
53
+ ignoreIllegals: true
54
+ }).value;
55
+ console.log("runHighlight [%s] took [%s]ms", language, Date.now() - now);
56
+ return value;
57
+ }
58
+ function emitEvents(elementRef, topMost, content, oncontentchange) {
59
+ if (elementRef.current && topMost.current) {
60
+ const currentContent = elementRef.current.textContent;
61
+ const webComponentElement = topMost.current.parentNode;
62
+ const event = new CustomEvent("contentchange", { detail: currentContent });
63
+ if (webComponentElement && webComponentElement instanceof HTMLElement && webComponentElement.tagName === TAG_NAME) {
64
+ try {
65
+ webComponentElement.dispatchEvent(event);
66
+ }
67
+ catch (e) {
68
+ console.error(e);
69
+ }
70
+ }
71
+ if (typeof oncontentchange === "function") {
72
+ try {
73
+ oncontentchange(event);
74
+ }
75
+ catch (e) {
76
+ console.error(e);
77
+ }
78
+ }
79
+ }
80
+ }
81
+ export function HighlightTextArea({ content, language, oncontentchange, tabChar, disabled }) {
82
+ const elementRef = jsx.useRef();
83
+ const topMost = jsx.useRef();
84
+ const [lastLanguage, setlastLanguage] = jsx.useState(language);
85
+ // effect to watch changes to language
86
+ jsx.useEffect(() => {
87
+ if (elementRef.current && (lastLanguage !== language || elementRef.current.textContent !== content)) {
88
+ setlastLanguage(language);
89
+ elementRef.current.innerHTML = runHighlight(content, language);
90
+ }
91
+ }, [lastLanguage, language, elementRef.current, content]);
92
+ return JSX.createElement("pre", { ref: topMost },
93
+ JSX.createElement("style", { innerHTML: STYLE + POSTTYLE }),
94
+ JSX.createElement("code", { autocomplete: "off", autocorrect: "off", autocapitalize: "off", spellcheck: "false", contenteditable: disabled ? "false" : "true", ref: elementRef, tabindex: "0", innerHTML: !elementRef.current ? runHighlight(content, language) : null, onfocusout: async (ev) => {
95
+ ev.preventDefault();
96
+ if (elementRef.current) {
97
+ if (content !== elementRef.current.textContent) {
98
+ //setlastContent(String(elementRef.current.textContent));
99
+ //elementRef.current.innerHTML = runHighlight(elementRef.current.textContent, language);
100
+ }
101
+ elementRef.current.innerHTML = runHighlight(elementRef.current.textContent, language);
102
+ }
103
+ }, onkeydown: ev => {
104
+ if (ev.keyCode === 9) {
105
+ ev.preventDefault();
106
+ // now insert four non-breaking spaces for the tab key
107
+ const sel = document.getSelection();
108
+ if (sel && topMost.current) {
109
+ if (topMost.current.contains(sel.anchorNode)) {
110
+ const range = sel.getRangeAt(0);
111
+ const tabNode = document.createTextNode(tabChar ? tabChar : "\t");
112
+ range.insertNode(tabNode);
113
+ range.setStartAfter(tabNode);
114
+ range.setEndAfter(tabNode);
115
+ sel.removeAllRanges();
116
+ sel.addRange(range);
117
+ }
118
+ }
119
+ emitEvents(elementRef, topMost, content, oncontentchange);
120
+ }
121
+ }, oninput: ev => {
122
+ ev.preventDefault();
123
+ emitEvents(elementRef, topMost, content, oncontentchange);
124
+ } }));
125
+ }
126
+ HighlightTextArea.asFragment = true;
127
+ HighlightTextArea.shadowInit = false;
@@ -0,0 +1,6 @@
1
+ import { LogSocket } from "../common/log-socket.js";
2
+ interface LogViewerProps {
3
+ socket: LogSocket;
4
+ }
5
+ export declare function LogViewer(props: LogViewerProps): JSX.Element;
6
+ export {};
@@ -0,0 +1,71 @@
1
+ import * as jsx from "@miqro/jsx";
2
+ import JSX from "@miqro/jsx";
3
+ function getUniqueIdentifiers(lines) {
4
+ const identifiersCache = {};
5
+ return lines.map(l => l.identifier).filter(identifier => {
6
+ const filter = !identifiersCache[identifier];
7
+ identifiersCache[identifier] = true;
8
+ return filter;
9
+ });
10
+ }
11
+ const LOG_LEVEL_MAP = {
12
+ "none": 0,
13
+ "error": 1,
14
+ "warn": 2,
15
+ "info": 3,
16
+ "debug": 4,
17
+ "trace": 5,
18
+ };
19
+ export function LogViewer(props) {
20
+ const { lines, clearLog, getMaxlogsize, setMaxLogSize } = props.socket;
21
+ const maxLogSize = getMaxlogsize();
22
+ const refresh = jsx.useRefresh();
23
+ jsx.useEffect(() => {
24
+ refresh();
25
+ }, [maxLogSize]);
26
+ const [identifier, setidentifier] = jsx.useState("");
27
+ const [level, setlevel] = jsx.useState("debug");
28
+ const [filter, setfilter] = jsx.useState("");
29
+ const identifiers = getUniqueIdentifiers(lines).sort();
30
+ //console.log(identifiers);
31
+ return JSX.createElement("div", { class: "log-viewer" },
32
+ JSX.createElement("div", { class: "log-viewer-toolbar" },
33
+ JSX.createElement("button", { class: "btn", onclick: e => {
34
+ e.preventDefault();
35
+ clearLog();
36
+ } }, "clear log"),
37
+ JSX.createElement("select", { value: maxLogSize, oninput: ev => {
38
+ ev.preventDefault();
39
+ if (ev.target.value === "unlimited") {
40
+ setMaxLogSize("unlimited");
41
+ }
42
+ else {
43
+ setMaxLogSize(parseInt(ev.target.value, 10));
44
+ }
45
+ }, style: "margin: 0; padding: 0; margin-left:auto; margin-right: 0;" },
46
+ ["10", "1000", "5000", "10000", "15000", "20000", "25000", "50000", "100000", "500000", "1000000", "1500000", "5000000"].map(l => JSX.createElement("option", { value: l }, l)),
47
+ JSX.createElement("option", { value: "unlimited" }, "unlimited")),
48
+ JSX.createElement("select", { value: level, oninput: ev => {
49
+ ev.preventDefault();
50
+ setlevel(ev.target.value);
51
+ }, style: "margin: 0; padding: 0; margin-left:var(--file-browser-separation); margin-right: 0;" },
52
+ ["error", "warn", "info", "debug", "trace"].map(l => JSX.createElement("option", { value: l }, l)),
53
+ JSX.createElement("option", { value: "" }, "all")),
54
+ JSX.createElement("select", { value: identifier, oninput: ev => {
55
+ ev.preventDefault();
56
+ setidentifier(ev.target.value);
57
+ }, style: "margin: 0; padding: 0; margin-left:var(--file-browser-separation); margin-right: 0;" },
58
+ identifiers.map(identifier => JSX.createElement("option", { value: identifier }, identifier)),
59
+ JSX.createElement("option", { value: "" })),
60
+ JSX.createElement("input", { style: "margin: 0; padding: 0; margin-left:var(--file-browser-separation); margin-right: 0;", value: filter, oninput: ev => {
61
+ ev.preventDefault();
62
+ setfilter(ev.target.value);
63
+ }, type: "text", placeholder: "..filter.." })),
64
+ JSX.createElement("div", { class: "log-viewer-log" }, lines
65
+ .filter(line => identifier === "" || line.identifier === identifier)
66
+ .filter(line => filter === "" || line.out.indexOf(filter) !== -1)
67
+ .filter(line => {
68
+ return (level === "" || LOG_LEVEL_MAP[level] >= LOG_LEVEL_MAP[line.level]);
69
+ })
70
+ .map(line => JSX.createElement("p", { style: "margin: 0; padding: 0; border-radius: 0; font-size: 12px;", class: line.level === "error" ? "info-danger" : line.level === "warn" ? "info-warn" : line.level === "trace" ? "info-success" : line.level === "debug" ? "info-info" : "" }, line.out)).reverse()));
71
+ }
@@ -0,0 +1,10 @@
1
+ export declare function NewFile(props: {
2
+ migrations: string[];
3
+ services: string[];
4
+ open: boolean;
5
+ ondone: (file?: string) => void;
6
+ }): JSX.Element;
7
+ export declare namespace NewFile {
8
+ var asFragment: boolean;
9
+ var shadowInit: boolean;
10
+ }
@@ -0,0 +1,119 @@
1
+ import * as jsx from "@miqro/jsx";
2
+ import JSX from "@miqro/jsx";
3
+ import { BASEEDITOR_PATH } from "../common/constants.js";
4
+ import { TEMPLATES } from "../common/templates.js";
5
+ import { HighlightTextArea } from "./highlight-text-area.js";
6
+ export function NewFile(props) {
7
+ const [template, settemplate] = jsx.useState("EMPTY");
8
+ const refresh = jsx.useRefresh();
9
+ const [service, setservice] = jsx.useState(props.services[0]);
10
+ const nameInput = jsx.useRef();
11
+ //const open = dialog ? dialog.open : false;
12
+ /*jsx.useEffect(() => {
13
+ if (dialog) {
14
+ //console.log((dialogRef.current as any).open);
15
+ if (open !== props.open) {
16
+ if (nameInput.current) {
17
+ nameInput.current.value = "";
18
+ nameInput.current.focus();
19
+ }
20
+ if (props.open) {
21
+ console.log("showModal");
22
+ dialog.showModal();
23
+ //(dialogRef.current as any).show();
24
+ } else {
25
+ console.log("closeModal");
26
+ //dialog.close();
27
+ }
28
+ }
29
+ }
30
+ }, [dialog, open, props.open]);*/
31
+ jsx.useEffect(() => {
32
+ if (nameInput.current) {
33
+ nameInput.current.value = "";
34
+ nameInput.current.focus();
35
+ }
36
+ }, [nameInput.current]);
37
+ function close(file) {
38
+ //console.log("closeModal");
39
+ if (props.ondone) {
40
+ props.ondone(file);
41
+ }
42
+ }
43
+ let nextMigrationNumber = 1;
44
+ if (props.migrations.length > 0) {
45
+ const lastMigration = props.migrations[props.migrations.length - 1];
46
+ const indexOfDash = lastMigration.indexOf("-");
47
+ if (indexOfDash !== -1) {
48
+ nextMigrationNumber = parseInt(lastMigration.substring(0, indexOfDash), 10) + 1;
49
+ }
50
+ }
51
+ const httpPath = (TEMPLATES[template].filename ? TEMPLATES[template].filename : nameInput.current?.value) + (TEMPLATES[template].httpSufix ? TEMPLATES[template].httpSufix : "");
52
+ const filename = (service ? service + "/" : "") + (service && TEMPLATES[template].prefix ? TEMPLATES[template].prefix + "/" : "") + (template === "MIGRATION" ? nextMigrationNumber + "-" : "") + (TEMPLATES[template].filename ? TEMPLATES[template].filename : nameInput.current?.value) + (TEMPLATES[template].sufix ? TEMPLATES[template].sufix : "");
53
+ async function createNewFile() {
54
+ if ((nameInput.current && nameInput.current.value) || TEMPLATES[template].filename) {
55
+ const t = TEMPLATES[template];
56
+ await fetch(BASEEDITOR_PATH + "/api/fs/write", {
57
+ method: "POST",
58
+ headers: {
59
+ ["content-type"]: "application/json"
60
+ },
61
+ body: JSON.stringify({
62
+ path: filename,
63
+ contents: t.template ? t.template(filename, httpPath) : ""
64
+ })
65
+ });
66
+ return filename;
67
+ }
68
+ }
69
+ return JSX.createElement(JSX.Fragment, null, props.open ? JSX.createElement("dialog", { class: "new-dialog", open: "" },
70
+ JSX.createElement("div", { class: "dialog-header" },
71
+ JSX.createElement("h1", null, "Create new File")),
72
+ JSX.createElement("div", { class: "dialog-body" },
73
+ JSX.createElement("select", { value: service, oninput: ev => {
74
+ ev.preventDefault();
75
+ ev.stopPropagation();
76
+ console.log(ev.target.value);
77
+ setservice(ev.target.value);
78
+ }, style: "margin: 0; padding: 0; margin-left:auto; margin-right: var(--file-browser-separation); width: 100%; margin-top: var(--file-browser-separation); margin-bottom: var(--file-browser-separation);" },
79
+ JSX.createElement("option", { value: "" }),
80
+ props.services.map(service => JSX.createElement("option", { value: service }, service))),
81
+ JSX.createElement("p", { style: "margin: 0; margin-bottom: var(--file-browser-separation);" }, filename),
82
+ !TEMPLATES[template].filename ? JSX.createElement("form", { style: "width: 100%;", onsubmit: async (ev) => {
83
+ ev.preventDefault();
84
+ ev.stopPropagation();
85
+ const path = await createNewFile();
86
+ close(path);
87
+ } },
88
+ JSX.createElement("input", { style: "width: 100%;", onkeydown: ev => {
89
+ if (ev.keyCode === 27) {
90
+ // catch esc
91
+ ev.stopPropagation();
92
+ ev.preventDefault();
93
+ close();
94
+ }
95
+ refresh();
96
+ }, ref: nameInput, type: "text", placeholder: "...filename..." })) : JSX.createElement(JSX.Fragment, null),
97
+ JSX.createElement("select", { value: template, oninput: ev => {
98
+ ev.preventDefault();
99
+ ev.stopPropagation();
100
+ console.log(ev.target.value);
101
+ settemplate(ev.target.value);
102
+ }, style: "margin: 0; padding: 0; margin-left:auto; margin-right: var(--file-browser-separation); width: 100%; margin-top: var(--file-browser-separation);" }, Object.keys(TEMPLATES).map(templateName => JSX.createElement("option", { value: templateName }, TEMPLATES[templateName].displayName))),
103
+ TEMPLATES[template].template ? JSX.createElement("div", { class: "new-dialog-preview" },
104
+ JSX.createElement(HighlightTextArea, { content: TEMPLATES[template].template(filename, httpPath), language: TEMPLATES[template].language, disabled: "true" })) : JSX.createElement(JSX.Fragment, null)),
105
+ JSX.createElement("div", { class: "dialog-footer" },
106
+ JSX.createElement("button", { class: "btn danger", onclick: ev => {
107
+ ev.preventDefault();
108
+ ev.stopPropagation();
109
+ close();
110
+ } }, "cancel"),
111
+ JSX.createElement("button", { style: "margin-left: auto;", class: "btn active", onclick: async (ev) => {
112
+ ev.preventDefault();
113
+ ev.stopPropagation();
114
+ const path = await createNewFile();
115
+ close(path);
116
+ } }, "create"))) : JSX.createElement(JSX.Fragment, null));
117
+ }
118
+ NewFile.asFragment = true;
119
+ NewFile.shadowInit = false;
@@ -0,0 +1,7 @@
1
+ export declare function useScroll(): [{
2
+ scrollTop: string;
3
+ scrollLeft: string;
4
+ }, (newScroll: {
5
+ scrollTop: number;
6
+ scrollLeft: number;
7
+ }, inmediate?: boolean) => void];
@@ -0,0 +1,22 @@
1
+ import * as jsx from "@miqro/jsx";
2
+ let scrollTimeout2 = null;
3
+ export function useScroll() {
4
+ const [scrollTop, setscrollTop] = jsx.useQuery("scrollTop", "0");
5
+ const [scrollLeft, setscrollLeft] = jsx.useQuery("scrollLeft", "0");
6
+ return [{
7
+ scrollTop: scrollTop,
8
+ scrollLeft: scrollLeft
9
+ }, (newScroll, inmediate) => {
10
+ clearTimeout(scrollTimeout2);
11
+ if (inmediate) {
12
+ setscrollTop(String(newScroll.scrollTop));
13
+ setscrollLeft(String(newScroll.scrollLeft));
14
+ }
15
+ else {
16
+ scrollTimeout2 = setTimeout(() => {
17
+ setscrollTop(String(newScroll.scrollTop));
18
+ setscrollLeft(String(newScroll.scrollLeft));
19
+ }, 1000);
20
+ }
21
+ }];
22
+ }
@@ -0,0 +1,13 @@
1
+ interface StartPageProps {
2
+ togglePanel: (panel: string) => void;
3
+ isPanelVisible: (panel: string) => boolean;
4
+ disableLog?: boolean;
5
+ disablePreview?: boolean;
6
+ disableReload?: boolean;
7
+ }
8
+ export declare function StartPage(props: StartPageProps): JSX.Element;
9
+ export declare namespace StartPage {
10
+ var asFragment: boolean;
11
+ var shadowInit: boolean;
12
+ }
13
+ export {};
@@ -0,0 +1,32 @@
1
+ import * as jsx from "@miqro/jsx";
2
+ import JSX from "@miqro/jsx";
3
+ export function StartPage(props) {
4
+ jsx.useEffect(() => {
5
+ if (!props.isPanelVisible("left")) {
6
+ props.togglePanel("left");
7
+ }
8
+ }, []);
9
+ return JSX.createElement("div", { class: `start-page` },
10
+ JSX.createElement("div", { class: "row center" },
11
+ JSX.createElement("h1", null, "Start Page")),
12
+ JSX.createElement("br", null),
13
+ JSX.createElement("div", { class: "row center" },
14
+ JSX.createElement("div", { class: "row" },
15
+ JSX.createElement("div", { class: `toggle-panel-button left-side-panel-button ${props.isPanelVisible("left") ? "active" : ""}`, onclick: ev => {
16
+ ev.preventDefault();
17
+ props.togglePanel("left");
18
+ } }),
19
+ JSX.createElement("br", null),
20
+ props.disableLog ? JSX.createElement(JSX.Fragment, null) : JSX.createElement("div", { class: `toggle-panel-button bottom-side-panel-button ${props.isPanelVisible("bottom") ? "active" : ""}`, onclick: ev => {
21
+ ev.preventDefault();
22
+ props.togglePanel("bottom");
23
+ } }),
24
+ JSX.createElement("br", null),
25
+ props.disablePreview ? JSX.createElement(JSX.Fragment, null) : JSX.createElement("div", { class: `toggle-panel-button right-side-panel-button ${props.isPanelVisible("right") ? "active" : ""}`, onclick: ev => {
26
+ ev.preventDefault();
27
+ props.togglePanel("right");
28
+ } }))),
29
+ JSX.createElement("br", null));
30
+ }
31
+ StartPage.asFragment = true;
32
+ StartPage.shadowInit = false;
@@ -0,0 +1,4 @@
1
+ declare const _default: import("@miqro/core").APIRoute<import("@miqro/core").Request, {
2
+ readonly path: "string";
3
+ }, undefined, undefined>;
4
+ export default _default;
@@ -0,0 +1,30 @@
1
+ import { defineRoute, JSONParser } from "@miqro/core";
2
+ import { unlinkSync } from "node:fs";
3
+ import { getPath } from "./read.api.js";
4
+ export default defineRoute({
5
+ description: "admin editor file deletion endpoint",
6
+ method: "POST",
7
+ path: "/delete",
8
+ middleware: [JSONParser()],
9
+ request: {
10
+ body: {
11
+ path: "string"
12
+ }
13
+ },
14
+ response: {
15
+ status: [200, 400],
16
+ body: {
17
+ message: "string"
18
+ }
19
+ },
20
+ handler: async (req, res) => {
21
+ const { path } = req.body;
22
+ await deleteFile(path);
23
+ return res?.json({
24
+ message: "OK"
25
+ });
26
+ }
27
+ });
28
+ function deleteFile(path) {
29
+ unlinkSync(getPath(path));
30
+ }
@@ -0,0 +1,7 @@
1
+ import { APIRoute } from "@miqro/core";
2
+ declare const _default: APIRoute<import("@miqro/core").Request, {
3
+ readonly path: "string";
4
+ }, undefined, undefined>;
5
+ export default _default;
6
+ export declare function readFile(path: string): string;
7
+ export declare function getPath(path: string): string;
@@ -0,0 +1,50 @@
1
+ import { defineRoute, JSONParser } from "@miqro/core";
2
+ import { readFileSync, realpathSync } from "node:fs";
3
+ import { SUPPORTED_LANGUAGES } from "../../../../../common/constants.js";
4
+ import { relative, resolve } from "node:path";
5
+ import { getLanguage } from "./scan.api.js";
6
+ import { BASE_PATH } from "../../../../../common/constants.server.js";
7
+ export default defineRoute({
8
+ method: "POST",
9
+ path: "/read",
10
+ description: "admin editor file read endpoint",
11
+ middleware: [JSONParser()],
12
+ request: {
13
+ body: {
14
+ path: "string"
15
+ }
16
+ },
17
+ response: {
18
+ status: [200, 400],
19
+ body: {
20
+ contents: "string",
21
+ path: "string"
22
+ }
23
+ },
24
+ handler: async (req, res) => {
25
+ const { path } = req.body;
26
+ const contents = readFile(path);
27
+ return res?.json({
28
+ contents,
29
+ path
30
+ });
31
+ }
32
+ });
33
+ export function readFile(path) {
34
+ const filePath = getPath(path);
35
+ const language = getLanguage(filePath);
36
+ if (SUPPORTED_LANGUAGES.includes(language)) {
37
+ const contents = readFileSync(filePath).toString();
38
+ return contents;
39
+ }
40
+ else {
41
+ throw new Error("unsupported file format");
42
+ }
43
+ }
44
+ export function getPath(path) {
45
+ const realPath = realpathSync(resolve(BASE_PATH, path));
46
+ if (relative(BASE_PATH, realPath).startsWith("..")) {
47
+ throw new Error("invalid path! [" + path + "]");
48
+ }
49
+ return realPath;
50
+ }