miqro 6.1.2 → 6.1.4

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 (175) hide show
  1. package/build/editor.bundle.js +16 -0
  2. package/build/esm/editor/auth.d.ts +6 -0
  3. package/build/esm/editor/auth.js +41 -0
  4. package/build/esm/editor/common/admin-interface.d.ts +36 -0
  5. package/build/esm/editor/common/admin-interface.js +44 -0
  6. package/build/esm/editor/common/constants.d.ts +4 -0
  7. package/build/esm/editor/common/constants.js +20 -0
  8. package/build/esm/editor/common/constants.server.d.ts +2 -0
  9. package/build/esm/editor/common/constants.server.js +4 -0
  10. package/build/esm/editor/common/editor-index.d.ts +2 -0
  11. package/build/esm/editor/common/editor-index.js +14 -0
  12. package/build/esm/editor/common/html-encode.d.ts +1 -0
  13. package/build/esm/editor/common/html-encode.js +14 -0
  14. package/build/esm/editor/common/log-socket.d.ts +15 -0
  15. package/build/esm/editor/common/log-socket.js +70 -0
  16. package/build/esm/editor/common/templates.d.ts +11 -0
  17. package/build/esm/editor/common/templates.js +477 -0
  18. package/build/esm/editor/components/api-preview.d.ts +11 -0
  19. package/build/esm/editor/components/api-preview.js +90 -0
  20. package/build/esm/editor/components/editor.d.ts +16 -0
  21. package/build/esm/editor/components/editor.js +357 -0
  22. package/build/esm/editor/components/file-browser.d.ts +37 -0
  23. package/build/esm/editor/components/file-browser.js +126 -0
  24. package/build/esm/editor/components/file-editor-toolbar.d.ts +22 -0
  25. package/build/esm/editor/components/file-editor-toolbar.js +93 -0
  26. package/build/esm/editor/components/file-editor.d.ts +32 -0
  27. package/build/esm/editor/components/file-editor.js +59 -0
  28. package/build/esm/editor/components/filter-query.d.ts +1 -0
  29. package/build/esm/editor/components/filter-query.js +22 -0
  30. package/build/esm/editor/components/highlight-text-area.d.ts +11 -0
  31. package/build/esm/editor/components/highlight-text-area.js +124 -0
  32. package/build/esm/editor/components/log-viewer.d.ts +6 -0
  33. package/build/esm/editor/components/log-viewer.js +69 -0
  34. package/build/esm/editor/components/new-file.d.ts +10 -0
  35. package/build/esm/editor/components/new-file.js +117 -0
  36. package/build/esm/editor/components/scroll-query.d.ts +7 -0
  37. package/build/esm/editor/components/scroll-query.js +21 -0
  38. package/build/esm/editor/components/start-page.d.ts +13 -0
  39. package/build/esm/editor/components/start-page.js +30 -0
  40. package/build/esm/editor/http/admin/editor/api/fs/delete.api.d.ts +3 -0
  41. package/build/esm/editor/http/admin/editor/api/fs/delete.api.js +29 -0
  42. package/build/esm/editor/http/admin/editor/api/fs/read.api.d.ts +5 -0
  43. package/build/esm/editor/http/admin/editor/api/fs/read.api.js +49 -0
  44. package/build/esm/editor/http/admin/editor/api/fs/rename.api.d.ts +4 -0
  45. package/build/esm/editor/http/admin/editor/api/fs/rename.api.js +39 -0
  46. package/build/esm/editor/http/admin/editor/api/fs/scan.api.d.ts +26 -0
  47. package/build/esm/editor/http/admin/editor/api/fs/scan.api.js +149 -0
  48. package/build/esm/editor/http/admin/editor/api/fs/write.api.d.ts +3 -0
  49. package/build/esm/editor/http/admin/editor/api/fs/write.api.js +38 -0
  50. package/build/esm/editor/http/admin/editor/api/server/reload.api.d.ts +10 -0
  51. package/build/esm/editor/http/admin/editor/api/server/reload.api.js +46 -0
  52. package/build/esm/editor/http/admin/editor/api/server/restart.api.d.ts +10 -0
  53. package/build/esm/editor/http/admin/editor/api/server/restart.api.js +45 -0
  54. package/build/esm/editor/http/admin/editor/editor.d.ts +1 -0
  55. package/build/esm/editor/http/admin/editor/editor.js +7 -0
  56. package/build/esm/editor/http/admin/editor/index.api.d.ts +3 -0
  57. package/build/esm/editor/http/admin/editor/index.api.js +21 -0
  58. package/build/esm/editor/server.d.ts +3 -0
  59. package/build/esm/editor/server.js +49 -0
  60. package/build/esm/editor/ws.d.ts +3 -0
  61. package/build/esm/editor/ws.js +11 -0
  62. package/build/esm/src/bin/types.js +8 -0
  63. package/build/esm/src/common/arguments.d.ts +7 -1
  64. package/build/esm/src/common/arguments.js +72 -10
  65. package/build/esm/src/common/help.d.ts +1 -1
  66. package/build/esm/src/common/help.js +33 -29
  67. package/build/esm/src/inflate/setup-ws.d.ts +1 -1
  68. package/build/esm/src/inflate/setup-ws.js +2 -2
  69. package/build/esm/src/main.js +3 -1
  70. package/build/esm/src/services/app.d.ts +2 -0
  71. package/build/esm/src/services/app.js +2 -2
  72. package/build/esm/src/services/utils/log-transport.d.ts +2 -2
  73. package/build/esm/src/services/utils/log-transport.js +8 -3
  74. package/build/esm/src/services/utils/server-interface.d.ts +1 -1
  75. package/build/esm/src/services/utils/server-interface.js +19 -14
  76. package/build/lib.cjs +23 -21
  77. package/editor/auth.ts +51 -0
  78. package/editor/common/admin-interface.ts +84 -0
  79. package/editor/common/constants.server.ts +5 -0
  80. package/editor/common/constants.ts +21 -0
  81. package/editor/common/editor-index.tsx +17 -0
  82. package/editor/common/html-encode.ts +14 -0
  83. package/editor/common/log-socket.tsx +85 -0
  84. package/editor/common/templates.ts +481 -0
  85. package/editor/components/api-preview.tsx +116 -0
  86. package/editor/components/editor.tsx +486 -0
  87. package/editor/components/file-browser.tsx +308 -0
  88. package/editor/components/file-editor-toolbar.tsx +191 -0
  89. package/editor/components/file-editor.tsx +122 -0
  90. package/editor/components/filter-query.tsx +22 -0
  91. package/editor/components/highlight-text-area.tsx +144 -0
  92. package/editor/components/log-viewer.tsx +110 -0
  93. package/editor/components/new-file.tsx +169 -0
  94. package/editor/components/scroll-query.tsx +22 -0
  95. package/editor/components/start-page.tsx +49 -0
  96. package/editor/http/admin/editor/api/fs/delete.api.tsx +32 -0
  97. package/editor/http/admin/editor/api/fs/read.api.tsx +55 -0
  98. package/editor/http/admin/editor/api/fs/rename.api.tsx +41 -0
  99. package/editor/http/admin/editor/api/fs/scan.api.tsx +181 -0
  100. package/editor/http/admin/editor/api/fs/write.api.tsx +41 -0
  101. package/editor/http/admin/editor/api/server/reload.api.ts +53 -0
  102. package/editor/http/admin/editor/api/server/restart.api.tsx +52 -0
  103. package/editor/http/admin/editor/editor.tsx +8 -0
  104. package/editor/http/admin/editor/index.api.tsx +39 -0
  105. package/editor/server.ts +57 -0
  106. package/editor/ws.ts +15 -0
  107. package/package.json +1 -1
  108. package/sea/install-nodejs.sh +1 -1
  109. package/sea/node.version.tag +1 -1
  110. package/src/bin/compile.ts +35 -0
  111. package/src/bin/doc-md.ts +210 -0
  112. package/src/bin/generate-doc.ts +64 -0
  113. package/src/bin/test.ts +92 -0
  114. package/src/bin/types.ts +29 -0
  115. package/src/cluster.ts +27 -0
  116. package/src/common/arguments.ts +576 -0
  117. package/src/common/assets.ts +128 -0
  118. package/src/common/checksum.ts +58 -0
  119. package/src/common/constants.ts +18 -0
  120. package/src/common/content-type.ts +84 -0
  121. package/src/common/esbuild.ts +94 -0
  122. package/src/common/exit.ts +91 -0
  123. package/src/common/fs.ts +17 -0
  124. package/src/common/help.ts +55 -0
  125. package/src/common/jsx.ts +512 -0
  126. package/src/common/paths.ts +158 -0
  127. package/src/common/watch.ts +85 -0
  128. package/src/inflate/inflate-sea.ts +206 -0
  129. package/src/inflate/inflate.ts +99 -0
  130. package/src/inflate/md.ts +25 -0
  131. package/src/inflate/setup-auth.ts +40 -0
  132. package/src/inflate/setup-cors.ts +40 -0
  133. package/src/inflate/setup-db.ts +115 -0
  134. package/src/inflate/setup-error.ts +43 -0
  135. package/src/inflate/setup-http.ts +655 -0
  136. package/src/inflate/setup-log.ts +44 -0
  137. package/src/inflate/setup-middleware.ts +46 -0
  138. package/src/inflate/setup-server-config.ts +47 -0
  139. package/src/inflate/setup-test.ts +23 -0
  140. package/src/inflate/setup-ws.ts +49 -0
  141. package/src/inflate/setup.doc.ts +68 -0
  142. package/src/inflate/utils/sea-utils.ts +14 -0
  143. package/src/lib.ts +19 -0
  144. package/src/main.ts +89 -0
  145. package/src/services/app.ts +660 -0
  146. package/src/services/editor.tsx +101 -0
  147. package/src/services/globals.ts +143 -0
  148. package/src/services/hot-reload.ts +48 -0
  149. package/src/services/migrations.ts +66 -0
  150. package/src/services/utils/admin-interface.ts +37 -0
  151. package/src/services/utils/cache.ts +88 -0
  152. package/src/services/utils/cluster-cache.ts +230 -0
  153. package/src/services/utils/cluster-ws.ts +197 -0
  154. package/src/services/utils/db-manager.ts +92 -0
  155. package/src/services/utils/get-route.ts +70 -0
  156. package/src/services/utils/log-transport.ts +81 -0
  157. package/src/services/utils/log.ts +92 -0
  158. package/src/services/utils/server-interface.ts +179 -0
  159. package/src/services/utils/websocketmanager.ts +149 -0
  160. package/src/types/@esbuild.d.ts +1 -0
  161. package/src/types/@miqro/core.d.ts +2 -0
  162. package/src/types/@miqro/jsx.d.ts +2 -0
  163. package/src/types/@miqro/parser.d.ts +2 -0
  164. package/src/types/@miqro/query.d.ts +2 -0
  165. package/src/types/@miqro/request.d.ts +2 -0
  166. package/src/types/@miqro/test.d.ts +2 -0
  167. package/src/types/@miqro.d.ts +1 -0
  168. package/src/types/@types.d.ts +1 -0
  169. package/src/types/browser.globals.d.ts +9 -0
  170. package/src/types/globals.d.ts +2 -0
  171. package/src/types/jsx.globals.d.ts +37 -0
  172. package/src/types/miqro.d.ts +129 -0
  173. package/src/types/postject.d.ts +1 -0
  174. package/src/types/server.globals.d.ts +72 -0
  175. package/src/types.ts +222 -0
@@ -0,0 +1,357 @@
1
+ import { FileEditor } from "./file-editor.js";
2
+ import { NewFile } from "./new-file.js";
3
+ import { useScroll } from "./scroll-query.js";
4
+ import { useFilterQuery } from "./filter-query.js";
5
+ import { FileBrowser } from "./file-browser.js";
6
+ import { StartPage } from "./start-page.js";
7
+ import { BASEEDITOR_PATH } from "../common/constants.js";
8
+ import { LogViewer } from "./log-viewer.js";
9
+ import { useLogSocket } from "../common/log-socket.js";
10
+ function InflateError2Map(errors) {
11
+ const errorMap = {};
12
+ for (const e of errors) {
13
+ const filePath = e.filePath;
14
+ const error = e.error;
15
+ errorMap[filePath] = {
16
+ error
17
+ };
18
+ }
19
+ return errorMap;
20
+ }
21
+ export function Editor(props) {
22
+ //console.dir(props);
23
+ const logSocket = useLogSocket({
24
+ disableLog: props.disablelog === "true" || props.disablelog === true ? true : false
25
+ });
26
+ const [services, setservices] = jsx.useState(JSON.parse(props.services));
27
+ const [collapsed, setCollapsed] = jsx.useState((() => {
28
+ const ret = {};
29
+ services.forEach(service => {
30
+ ret[`${service}/`] = false;
31
+ });
32
+ return ret;
33
+ })());
34
+ /*const [panelVisible, setpanelVisible] = jsx.useState<{
35
+ [panel: string]: boolean | undefined;
36
+ }>({ right: false, bottom: false });*/
37
+ const [rightPanelVisible, setRightPanelVisible] = jsx.useQuery("right-panel", "0");
38
+ const [leftPanelVisible, setLeftPanelVisible] = jsx.useQuery("left-panel", "1");
39
+ const [bottomPanelVisible, setBottomPanelVisible] = jsx.useQuery("bottom-panel", "0");
40
+ const [migrations, setmigrations] = jsx.useState(JSON.parse(props.migrations));
41
+ const [files, setfiles] = jsx.useState(JSON.parse(props.files));
42
+ const [reloadString, setreloadString] = jsx.useState(props.reloadstring);
43
+ const [changed, setchanged] = jsx.useState({});
44
+ const [errors, seterrors] = jsx.useState(InflateError2Map(JSON.parse(props.errors)));
45
+ const [newFileDialogShow, setnewFileDialogShow] = jsx.useState(false);
46
+ const [filter, setfilter] = useFilterQuery();
47
+ const refresh = jsx.useRefresh();
48
+ const [opened, setopened] = jsx.useState({});
49
+ const [current, setcurrent] = jsx.useQuery("current", props.initialcurrent ? props.initialcurrent : "");
50
+ const [_, setScroll] = useScroll();
51
+ if (current instanceof Array) {
52
+ setcurrent(current[0]);
53
+ }
54
+ else if (current) {
55
+ if (!opened[current]) {
56
+ const file = files.filter(file => file.filePath === current)[0];
57
+ if (!file) {
58
+ setcurrent("");
59
+ }
60
+ else {
61
+ openFile(file.filePath);
62
+ }
63
+ }
64
+ }
65
+ /*useEffect(() => {
66
+ for (const service of services) {
67
+ if (collapsed[`${service}/`] === undefined) {
68
+ collapsed[`${service}/`] = true;
69
+ refresh();
70
+ }
71
+ }
72
+ }, services);*/
73
+ function openFile(filePath) {
74
+ console.log("open [%s]", filePath);
75
+ const isOpen = opened[filePath];
76
+ setScroll({
77
+ scrollLeft: 0,
78
+ scrollTop: 0
79
+ });
80
+ if (!isOpen) {
81
+ const file = files.filter(file => file.filePath === filePath)[0];
82
+ if (!file) {
83
+ throw new Error("cannot find reference to file [" + filePath + "]");
84
+ }
85
+ opened[file.filePath] = {
86
+ content: null,
87
+ ...file
88
+ };
89
+ changed[file.filePath] = null;
90
+ setopened(opened);
91
+ if (opened[file.filePath].content === null && (globalThis.window) !== undefined) {
92
+ if (opened[file.filePath].language !== "binary") {
93
+ fetch(BASEEDITOR_PATH + "/api/fs/read", {
94
+ method: "POST",
95
+ headers: {
96
+ ["content-type"]: "application/json"
97
+ },
98
+ body: JSON.stringify({
99
+ path: file.filePath
100
+ })
101
+ }).then(response => {
102
+ if (response.ok) {
103
+ response.json().then(json => {
104
+ const contents = json.contents;
105
+ if (opened[file.filePath]) {
106
+ opened[file.filePath].content = contents;
107
+ changed[file.filePath] = contents;
108
+ setopened(opened);
109
+ setchanged(changed);
110
+ refresh();
111
+ }
112
+ });
113
+ }
114
+ });
115
+ }
116
+ else {
117
+ opened[file.filePath].content = "";
118
+ changed[file.filePath] = "";
119
+ setopened(opened);
120
+ refresh();
121
+ }
122
+ }
123
+ }
124
+ setcurrent(filePath);
125
+ }
126
+ function closeFile(filePath) {
127
+ setScroll({
128
+ scrollTop: 0,
129
+ scrollLeft: 0
130
+ });
131
+ console.log("closing [%s]", filePath);
132
+ //console.log("current [%s]", current);
133
+ if (filePath === current) {
134
+ setcurrent("");
135
+ }
136
+ delete opened[filePath];
137
+ delete changed[filePath];
138
+ setchanged(changed);
139
+ setopened(opened);
140
+ refresh();
141
+ }
142
+ async function scanFiles() {
143
+ const r = await fetch(BASEEDITOR_PATH + "/api/fs/scan", {
144
+ method: "GET"
145
+ });
146
+ if (r.ok) {
147
+ const { files, services } = await r.json();
148
+ setfiles(files);
149
+ setservices(services);
150
+ }
151
+ }
152
+ function isDirCollapsed(dir) {
153
+ console.log("isDirCollapsed [%s]", dir);
154
+ if (dir === "" || filter !== "") {
155
+ return false;
156
+ }
157
+ return collapsed[dir] || collapsed[dir] === undefined ? true : false;
158
+ //return collapsed[dir] ? false : true;
159
+ }
160
+ function toggleCollapseDir(dir) {
161
+ console.log("toggleCollapseDir [%s]", dir);
162
+ collapsed[dir] = isDirCollapsed(dir) ? false : true;
163
+ setCollapsed(collapsed);
164
+ refresh();
165
+ }
166
+ async function deleteFile(file) {
167
+ console.log("deleteFile [%s]", file);
168
+ const r = await fetch(BASEEDITOR_PATH + "/api/fs/delete", {
169
+ method: "POST",
170
+ headers: {
171
+ ["content-type"]: "application/json"
172
+ },
173
+ body: JSON.stringify({
174
+ path: file
175
+ })
176
+ });
177
+ if (r.ok) {
178
+ await scanFiles();
179
+ if (opened[file]) {
180
+ closeFile(file);
181
+ }
182
+ }
183
+ }
184
+ async function renameFile(file, newName) {
185
+ console.log("renameFile [%s] to [%s]", file, newName);
186
+ if (opened[file]) {
187
+ const r = await fetch(BASEEDITOR_PATH + "/api/fs/rename", {
188
+ method: "POST",
189
+ headers: {
190
+ ["content-type"]: "application/json"
191
+ },
192
+ body: JSON.stringify({
193
+ path: file,
194
+ newName
195
+ })
196
+ });
197
+ if (r.ok) {
198
+ const fileO = opened[file];
199
+ const changeO = changed[file];
200
+ fileO.filePath = newName;
201
+ delete changed[file];
202
+ delete opened[file];
203
+ opened[newName] = fileO;
204
+ changed[newName] = changeO;
205
+ await scanFiles();
206
+ setopened(opened);
207
+ setchanged(changed);
208
+ if (current === file) {
209
+ setcurrent(newName);
210
+ }
211
+ refresh();
212
+ }
213
+ }
214
+ }
215
+ async function saveFile(file) {
216
+ console.log("saveFile [%s]", file);
217
+ const contents = changed[file];
218
+ if (opened[file] && contents !== undefined && contents !== null) {
219
+ const r = await fetch(BASEEDITOR_PATH + "/api/fs/write", {
220
+ method: "POST",
221
+ headers: {
222
+ ["content-type"]: "application/json"
223
+ },
224
+ body: JSON.stringify({
225
+ path: file,
226
+ contents,
227
+ override: true
228
+ })
229
+ });
230
+ if (r.ok) {
231
+ opened[file].content = contents;
232
+ setopened(opened);
233
+ setchanged(changed);
234
+ refresh();
235
+ }
236
+ }
237
+ }
238
+ async function reloadServer() {
239
+ const r = await fetch(BASEEDITOR_PATH + "/api/server/reload", {
240
+ method: "POST"
241
+ });
242
+ if (r.ok) {
243
+ const reloadResponse = await r.json();
244
+ if (reloadResponse.errors && reloadResponse.errors.length > 0) {
245
+ seterrors(InflateError2Map(reloadResponse.errors));
246
+ setreloadString(reloadResponse.reloadString);
247
+ refresh();
248
+ }
249
+ else {
250
+ setreloadString(reloadResponse.reloadString);
251
+ seterrors({});
252
+ refresh();
253
+ }
254
+ setmigrations(reloadResponse.migrations);
255
+ await scanFiles();
256
+ }
257
+ }
258
+ function setLanguage(file, newLanguage) {
259
+ if (opened[file]) {
260
+ opened[file].language = newLanguage;
261
+ setopened(opened);
262
+ refresh();
263
+ }
264
+ }
265
+ function hasFileContentChanged(filePath) {
266
+ if (!opened[filePath]) {
267
+ return false;
268
+ }
269
+ return changed[filePath] !== opened[filePath].content;
270
+ }
271
+ function isPanelVisible(panel) {
272
+ switch (panel) {
273
+ case "left":
274
+ return leftPanelVisible === "1";
275
+ case "bottom":
276
+ return bottomPanelVisible === "1";
277
+ case "right":
278
+ return rightPanelVisible === "1";
279
+ default:
280
+ return true;
281
+ }
282
+ //return panelVisible[panel] || panelVisible[panel] === undefined ? true : false;
283
+ }
284
+ function togglePanel(panel) {
285
+ console.log("togglePanel [%s]", panel);
286
+ /*panelVisible[panel] = !isPanelVisible(panel);
287
+ setpanelVisible(panelVisible);
288
+ refresh();*/
289
+ switch (panel) {
290
+ case "left":
291
+ return setLeftPanelVisible(isPanelVisible(panel) ? "0" : "1");
292
+ case "bottom":
293
+ return setBottomPanelVisible(isPanelVisible(panel) ? "0" : "1");
294
+ case "right":
295
+ return setRightPanelVisible(isPanelVisible(panel) ? "0" : "1");
296
+ default:
297
+ return;
298
+ }
299
+ }
300
+ const openedFile = opened[String(current)];
301
+ //console.log("Editor [%s]", openedFile?.filePath);
302
+ return JSX.createElement("div", { class: "editor" },
303
+ JSX.createElement("div", { class: `editor-firstrow${!isPanelVisible("bottom") ? " bottom-panel-hidden" : ""}` },
304
+ JSX.createElement(NewFile, { migrations: migrations, services: services, open: newFileDialogShow, ondone: async (path) => {
305
+ setnewFileDialogShow(false);
306
+ if (path) {
307
+ await scanFiles();
308
+ //await reloadServer();
309
+ }
310
+ } }),
311
+ JSX.createElement(FileBrowser, { disableLog: props.disablelog, disablePreview: props.disablepreview, disableReload: props.disablereload, togglePanel: togglePanel, isPanelVisible: isPanelVisible, opened: Object.keys(opened).sort().map(o => opened[o]), isDirCollapsed: isDirCollapsed, toggleCollapseDir: toggleCollapseDir, migrations: migrations, hasErrors: (file) => errors[file] ? true : false, reloadServer: reloadServer, closeAll: () => {
312
+ const openedList = Object.keys(opened);
313
+ for (const o of openedList) {
314
+ closeFile(o);
315
+ }
316
+ }, closeFile: closeFile, current: current ? String(current) : "", files: files, filter: filter, hasFileContentChanged: hasFileContentChanged, isOpen: (file) => opened[file] !== undefined, openFile: openFile, saveAll: async () => {
317
+ const openedList = Object.keys(opened);
318
+ for (const o of openedList) {
319
+ if (hasFileContentChanged(o)) {
320
+ await saveFile(o);
321
+ }
322
+ }
323
+ //await reloadServer();
324
+ }, scanFiles: scanFiles, setfilter: setfilter, showNewFile: () => {
325
+ setnewFileDialogShow(true);
326
+ } }),
327
+ JSX.createElement("div", { class: `file-editor-list${!isPanelVisible("left") ? " left-panel-hidden" : ""}${!isPanelVisible("bottom") ? " bottom-panel-hidden" : ""}` }, !openedFile ?
328
+ JSX.createElement(StartPage, { disableLog: props.disablelog, disablePreview: props.disablepreview, disableReload: props.disablereload, isPanelVisible: isPanelVisible, togglePanel: togglePanel }) :
329
+ JSX.createElement("div", { class: "file-editor-container" },
330
+ JSX.createElement(FileEditor, { disableLog: props.disablelog, disablePreview: props.disablepreview, disableReload: props.disablereload, isPanelVisible: isPanelVisible, togglePanel: togglePanel, reloadString: reloadString, error: errors[openedFile.filePath]?.error, changed: hasFileContentChanged(openedFile.filePath), setlanguage: (newLanguage) => setLanguage(openedFile.filePath, newLanguage), deleteFile: async () => {
331
+ await deleteFile(openedFile.filePath);
332
+ //await reloadServer();
333
+ }, renameFile: async (newName) => {
334
+ await renameFile(openedFile.filePath, newName);
335
+ //await reloadServer();
336
+ }, saveFile: async (reload = false) => {
337
+ await saveFile(openedFile.filePath);
338
+ if (reload) {
339
+ await reloadServer();
340
+ }
341
+ //
342
+ }, content: changed[openedFile.filePath] !== null ? changed[openedFile.filePath] : opened[openedFile.filePath].content, current: current === openedFile.filePath, revertFile: () => {
343
+ changed[openedFile.filePath] = openedFile.content;
344
+ setchanged(changed);
345
+ refresh();
346
+ }, contentchange: (content) => {
347
+ changed[openedFile.filePath] = content;
348
+ setopened(opened);
349
+ refresh();
350
+ }, closeFile: () => {
351
+ closeFile(openedFile.filePath);
352
+ }, path: openedFile.filePath, previewPath: openedFile.previewPath, apiPreview: openedFile.apiPreview, language: opened[openedFile.filePath].language })))),
353
+ JSX.createElement("div", { class: "editor-bottom-panel", style: `${!isPanelVisible("bottom") ? "display: none;" : ""}` },
354
+ JSX.createElement(LogViewer, { socket: logSocket })));
355
+ }
356
+ Editor.asFragment = true;
357
+ Editor.shadowInit = false;
@@ -0,0 +1,37 @@
1
+ interface FileBrowserFile {
2
+ filePath: string;
3
+ fileName: string;
4
+ language: string;
5
+ content?: string;
6
+ dirs: string[];
7
+ }
8
+ interface FileBrowserProps {
9
+ filter: string;
10
+ migrations: string[];
11
+ current: string;
12
+ isDirCollapsed: (dir: string) => boolean;
13
+ toggleCollapseDir: (dir: string) => void;
14
+ saveAll: () => void;
15
+ isOpen: (file: string) => boolean;
16
+ openFile: (file: string) => void;
17
+ setfilter: (newFilter: any) => void;
18
+ showNewFile: () => void;
19
+ scanFiles: () => void;
20
+ closeAll: () => void;
21
+ closeFile: (file: string) => void;
22
+ reloadServer: () => void;
23
+ hasFileContentChanged: (file: string) => boolean;
24
+ hasErrors: (file: string) => boolean;
25
+ files: FileBrowserFile[];
26
+ opened: {
27
+ fileName: string;
28
+ filePath: string;
29
+ }[];
30
+ isPanelVisible: (panel: string) => boolean;
31
+ togglePanel: (panel: string) => void;
32
+ disableLog?: boolean;
33
+ disablePreview?: boolean;
34
+ disableReload?: boolean;
35
+ }
36
+ export declare function FileBrowser(props: FileBrowserProps): JSX.Element;
37
+ export {};
@@ -0,0 +1,126 @@
1
+ export function FileBrowser(props) {
2
+ return JSX.createElement("div", { class: "file-browser", style: `${!props.isPanelVisible("left") ? "display: none;" : ""}` },
3
+ JSX.createElement("div", { class: "file-browser-toolbar" },
4
+ JSX.createElement("div", { class: "row" },
5
+ JSX.createElement("button", { class: "file-editor-button btn", style: `width: 10%;${props.disableReload ? "width: 30%;" : ""}`, onclick: ev => {
6
+ ev.preventDefault();
7
+ props.togglePanel("left");
8
+ } }, "<<"),
9
+ props.disableLog ? JSX.createElement(JSX.Fragment, null) :
10
+ JSX.createElement("button", { id: "log-btn", class: "file-editor-button btn", style: `width: 30%;${props.disableLog ? "display: none;" : ""}`, onclick: ev => {
11
+ ev.preventDefault();
12
+ props.togglePanel("bottom");
13
+ } }, "log"),
14
+ props.disableReload ? JSX.createElement(JSX.Fragment, null) :
15
+ JSX.createElement("button", { id: "scan-btn", class: "file-editor-button btn active", style: `width: 30%;${props.disableReload ? "display: none;" : ""}`, onclick: ev => {
16
+ ev.preventDefault();
17
+ props.scanFiles();
18
+ } }, "scan"),
19
+ props.disableReload ? JSX.createElement(JSX.Fragment, null) :
20
+ JSX.createElement("button", { id: "reload-btn", class: "file-editor-button btn warning", style: `width: 30%;${props.disableReload ? "display: none;" : ""}`, onclick: ev => {
21
+ ev.preventDefault();
22
+ props.reloadServer();
23
+ } }, "reload")),
24
+ JSX.createElement("div", { class: "row" },
25
+ JSX.createElement("input", { type: "text", style: "width: 100%;", value: props.filter, oninput: ev => {
26
+ ev.preventDefault();
27
+ const text = ev.target.value;
28
+ props.setfilter(text);
29
+ }, placeholder: "..filter.." })),
30
+ JSX.createElement("div", { class: "row" },
31
+ props.disablePreview ? JSX.createElement(JSX.Fragment, null) :
32
+ JSX.createElement("button", { id: "preview-btn", class: "file-editor-button btn", style: `width: 30%;${props.disablePreview ? "display: none;" : ""}`, onclick: ev => {
33
+ ev.preventDefault();
34
+ props.togglePanel("right");
35
+ } }, "preview"),
36
+ JSX.createElement("button", { id: "new-btn", class: "file-editor-button btn info", style: "width: 20%;", onclick: ev => {
37
+ ev.preventDefault();
38
+ props.showNewFile();
39
+ } }, "new"),
40
+ props.disableReload ? JSX.createElement(JSX.Fragment, null) :
41
+ JSX.createElement("button", { id: "scan-btn", class: "file-editor-button btn active", style: `width: 30%;${!props.disableReload ? "display: none;" : ""}`, onclick: ev => {
42
+ ev.preventDefault();
43
+ props.scanFiles();
44
+ } }, "scan"),
45
+ JSX.createElement("button", { id: "saveall-btn", class: "file-editor-button btn success", style: "width: 25%;", onclick: ev => {
46
+ ev.preventDefault();
47
+ props.saveAll();
48
+ } }, "save"),
49
+ JSX.createElement("button", { id: "closeall-btn", class: "file-editor-button btn danger", style: "width: 25%;", onclick: ev => {
50
+ ev.preventDefault();
51
+ props.closeAll();
52
+ } }, "close"))),
53
+ JSX.createElement("div", { class: "file-browser-files" },
54
+ props.opened.length > 0 ? JSX.createElement("div", { class: "file-browser-opened-files", style: "padding: var(--file-browser-separation);" },
55
+ JSX.createElement("ul", { style: "padding: 0; margin: 0;" }, props.opened.map(file => JSX.createElement(File, { closeFile: props.closeFile, current: props.current, fileName: file.fileName, filePath: file.filePath, hasErrors: props.hasErrors, hasFileContentChanged: props.hasFileContentChanged, isOpen: props.isOpen, openFile: props.openFile })))) : JSX.createElement(JSX.Fragment, null),
56
+ JSX.createElement(FileTree, { isDirCollapsed: props.isDirCollapsed, toggleCollapseDir: props.toggleCollapseDir, closeFile: props.closeFile, current: props.current, files: props.files, filter: props.filter, hasErrors: props.hasErrors, hasFileContentChanged: props.hasFileContentChanged, isOpen: props.isOpen, openFile: props.openFile })));
57
+ }
58
+ function FileTree(props) {
59
+ const ret = {
60
+ dirs: {},
61
+ files: [],
62
+ name: "",
63
+ fullName: ""
64
+ };
65
+ props.files.forEach((file) => {
66
+ let cDir = ret;
67
+ let fullName = "";
68
+ for (const dir of file.dirs) {
69
+ fullName += dir + "/";
70
+ if (cDir.dirs[dir] === undefined) {
71
+ const newDir = {
72
+ dirs: {},
73
+ files: [],
74
+ name: dir,
75
+ fullName: `${fullName}`
76
+ };
77
+ cDir.dirs[dir] = newDir;
78
+ cDir = newDir;
79
+ }
80
+ else {
81
+ cDir = cDir.dirs[dir];
82
+ }
83
+ }
84
+ cDir.files.push(file);
85
+ });
86
+ //console.dir(ret);
87
+ return JSX.createElement(FileTreeFolder, { ...props, tree: ret, level: 0 });
88
+ }
89
+ function FileTreeFolder(props) {
90
+ //console.dir(props.tree);
91
+ const dirs = Object.keys(props.tree.dirs).map(k => props.tree.dirs[k]);
92
+ const files = props.tree.files.filter(file => props.filter ? file.filePath.includes(props.filter) : true);
93
+ return JSX.createElement("ul", { style: `margin-left: calc(2 * var(--file-browser-separation-file));${props.level === 0 ? " padding: var(--file-browser-separation);" : ""}` },
94
+ JSX.createElement(JSX.Fragment, null,
95
+ props.tree.name !== "" ? JSX.createElement("div", { class: "file-browser-dir", style: "padding: 0;" },
96
+ JSX.createElement("p", { style: "margin: 0;" },
97
+ props.tree.name,
98
+ "/"),
99
+ JSX.createElement("button", { onclick: ev => {
100
+ ev.preventDefault();
101
+ ev.stopPropagation();
102
+ props.toggleCollapseDir(props.tree.fullName);
103
+ }, class: "btn-small", style: "margin: 0; margin-left: calc(2 * var(--file-browser-separation));" }, props.isDirCollapsed(props.tree.fullName) ? "+" : "-")) : JSX.createElement(JSX.Fragment, null),
104
+ props.isDirCollapsed(props.tree.fullName) ? JSX.createElement(JSX.Fragment, null) :
105
+ JSX.createElement(JSX.Fragment, null,
106
+ dirs.map(dir => {
107
+ return JSX.createElement(FileTreeFolder, { ...props, tree: dir, level: props.level + 1 });
108
+ }),
109
+ files.map(file => JSX.createElement(File, { closeFile: props.closeFile, current: props.current, fileName: file.fileName, filePath: file.filePath, hasErrors: props.hasErrors, hasFileContentChanged: props.hasFileContentChanged, isOpen: props.isOpen, openFile: props.openFile })))));
110
+ }
111
+ function File(props) {
112
+ const isOpen = props.isOpen(props.filePath);
113
+ return JSX.createElement("li", { class: `file-browser-file${props.hasErrors(props.filePath) ? " error" : ""}${props.hasFileContentChanged(props.filePath) ? " changed" : ""}${props.current === props.filePath ? " active" : ""}${isOpen ? " open" : ""}`, style: "display: flex; justify-content: flex-start; align-items: center; margin-left: calc(2 * var(--file-browser-separation-file));", onclick: ev => {
114
+ ev.preventDefault();
115
+ ev.stopPropagation();
116
+ props.openFile(props.filePath);
117
+ } },
118
+ JSX.createElement("p", { style: "margin: 0; padding: 0;" },
119
+ props.fileName,
120
+ props.hasFileContentChanged(props.filePath) ? "(*)" : ""),
121
+ JSX.createElement("button", { onclick: ev => {
122
+ ev.preventDefault();
123
+ ev.stopPropagation();
124
+ props.closeFile(props.filePath);
125
+ }, class: "btn-small", style: props.isOpen(props.filePath) ? "margin-left: calc(2 * var(--file-browser-separation-file));" : "display: none;", disabled: !props.isOpen(props.filePath) }, "X"));
126
+ }
@@ -0,0 +1,22 @@
1
+ interface FileEditorToolbar {
2
+ path: string;
3
+ language: string;
4
+ changed: boolean;
5
+ renameFile: (newName: string) => void;
6
+ deleteFile: () => void;
7
+ setlanguage: (newLang: string) => void;
8
+ saveFile: (reload?: boolean) => void;
9
+ revertFile: () => void;
10
+ closeFile: () => void;
11
+ togglePanel: (panel: string) => void;
12
+ isPanelVisible: (panel: string) => boolean;
13
+ disableLog?: boolean;
14
+ disablePreview?: boolean;
15
+ disableReload?: boolean;
16
+ }
17
+ export declare function FileEditorToolbar(props: FileEditorToolbar): JSX.Element;
18
+ export declare namespace FileEditorToolbar {
19
+ var asFragment: boolean;
20
+ var shadowInit: boolean;
21
+ }
22
+ export {};
@@ -0,0 +1,93 @@
1
+ import { SUPPORTED_LANGUAGES } from "../common/constants.js";
2
+ export function FileEditorToolbar(props) {
3
+ const renamingRef = jsx.useRef();
4
+ const refresh = jsx.useRefresh();
5
+ const [renaming, setrenaming] = jsx.useState(false);
6
+ jsx.useEffect(() => {
7
+ if (renamingRef.current) {
8
+ renamingRef.current.value = props.path;
9
+ renamingRef.current.focus();
10
+ refresh();
11
+ }
12
+ }, [renamingRef.current]);
13
+ jsx.useEffect(() => {
14
+ setrenaming(false);
15
+ }, [props.path]);
16
+ return JSX.createElement("div", { class: "file-editor-toolbar" },
17
+ JSX.createElement("div", { class: "file-editor-toolbar-row" },
18
+ JSX.createElement("button", { class: "file-editor-button btn", style: `${props.isPanelVisible("left") ? "display: none;" : "margin-right: var(--file-browser-separation);"}`, onclick: ev => {
19
+ ev.preventDefault();
20
+ props.togglePanel("left");
21
+ } }, ">>"),
22
+ JSX.createElement("button", { id: "save-btn", disabled: !props.changed, class: `btn success`, onclick: ev => {
23
+ ev.preventDefault();
24
+ props.saveFile();
25
+ } }, "save"),
26
+ props.disableReload ? JSX.createElement(JSX.Fragment, null) : JSX.createElement("button", { id: "savereload-btn", disabled: !props.changed, class: `btn info`, style: "margin-left: var(--file-browser-separation);", onclick: ev => {
27
+ ev.preventDefault();
28
+ props.saveFile(true);
29
+ } }, "save/reload"),
30
+ JSX.createElement("button", { id: "revert-btn", disabled: !props.changed, style: "margin-left: var(--file-browser-separation);", class: `btn warning`, onclick: ev => {
31
+ ev.preventDefault();
32
+ props.revertFile();
33
+ } }, "revert"),
34
+ JSX.createElement("button", { id: "close-btn", class: `btn danger`, style: "margin-left: var(--file-browser-separation);", onclick: ev => {
35
+ ev.preventDefault();
36
+ props.closeFile();
37
+ } }, "close"),
38
+ SUPPORTED_LANGUAGES.includes(props.language) ?
39
+ JSX.createElement("select", { value: props.language, oninput: ev => {
40
+ ev.preventDefault();
41
+ props.setlanguage(ev.target.value);
42
+ }, style: "margin: 0; padding: 0; margin-left: calc(2*var(--file-browser-separation-file));" }, SUPPORTED_LANGUAGES.map(language => JSX.createElement("option", { value: language }, language))) : JSX.createElement(JSX.Fragment, null)),
43
+ JSX.createElement("div", { class: "file-editor-toolbar-row" }, !renaming ?
44
+ JSX.createElement(JSX.Fragment, null,
45
+ JSX.createElement("p", { style: "margin-left:20px;", onclick: ev => {
46
+ ev.preventDefault();
47
+ setrenaming(true);
48
+ } }, props.path)) :
49
+ JSX.createElement(JSX.Fragment, null,
50
+ JSX.createElement("form", { style: "width: 100%; height: 100%; margin-right: calc(2 * var(--file-browser-separation));", onsubmit: ev => {
51
+ ev.preventDefault();
52
+ setrenaming(false);
53
+ if (renamingRef.current && renamingRef.current.value !== props.path) {
54
+ setrenaming(false);
55
+ props.renameFile(renamingRef.current.value);
56
+ }
57
+ } },
58
+ JSX.createElement("input", { style: "width: 100%; height: 100%;", onfocusout: ev => {
59
+ ev.preventDefault();
60
+ //setrenaming(false);
61
+ }, ref: renamingRef, onkeydown: (ev) => {
62
+ if (ev.keyCode === 27) {
63
+ // catch esc
64
+ ev.preventDefault();
65
+ setrenaming(false);
66
+ }
67
+ else {
68
+ refresh();
69
+ }
70
+ }, type: "text" })),
71
+ renamingRef.current && renamingRef.current.value !== props.path && renamingRef.current.value !== "" ?
72
+ JSX.createElement("button", { style: "margin-left: var(--file-browser-separation);", class: "btn info", onclick: ev => {
73
+ ev.preventDefault();
74
+ if (renamingRef.current) {
75
+ setrenaming(false);
76
+ props.renameFile(renamingRef.current.value);
77
+ }
78
+ } }, "rename file")
79
+ : JSX.createElement(JSX.Fragment, null),
80
+ JSX.createElement("button", { style: "margin-left: var(--file-browser-separation);", class: "btn danger", onclick: ev => {
81
+ ev.preventDefault();
82
+ if (renamingRef.current) {
83
+ setrenaming(false);
84
+ props.deleteFile();
85
+ }
86
+ } }, "delete file"),
87
+ JSX.createElement("button", { style: "margin-left: var(--file-browser-separation);", class: "btn", onclick: ev => {
88
+ ev.preventDefault();
89
+ setrenaming(false);
90
+ } }, "cancel"))));
91
+ }
92
+ FileEditorToolbar.asFragment = true;
93
+ FileEditorToolbar.shadowInit = false;
@@ -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 {};