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,655 @@
1
+ import { Router, newURL, Response, Request, RouterHandlerOptions, Logger, APIRoute, normalizePath, HandlerWithOptions, Handler } from "@miqro/core";
2
+ import { existsSync, mkdirSync, readFile, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
3
+ import { dirname, join, relative, resolve as pathResolve } from "node:path";
4
+
5
+ import { CONTENT_TYPE_MAP, DEFAULT_CONTENT_TYPE } from "../common/content-type.js";
6
+ import { InflateError, importHTMLModule, importAPIRoute, inflateJSX, importJSONModule, JSONModuleValue, jsx2HTML } from "../common/jsx.js";
7
+ import { createNodeRuntime } from "@miqro/jsx-node";
8
+ import { getHotReloadScript } from "../services/hot-reload.js";
9
+ import { RuntimeURL } from "@miqro/jsx";
10
+ import { cwd } from "node:process";
11
+ import { assertGlobalTampered } from "../services/globals.js";
12
+ import { getHTTPRouterPath, getStaticFilesPath } from "../common/paths.js";
13
+ import { setupCORS } from "./setup-cors.js";
14
+ import { setupAUTH } from "./setup-auth.js";
15
+ import { getRoutes } from "../services/utils/get-route.js";
16
+ import { describeFilePath } from "../common/fs.js";
17
+ import { inflateMD2HTML } from "./md.js";
18
+ import { MiddlewareConfig, ServerInterface, ServerRequest } from "../types.js";
19
+ import { setupMiddleware } from "./setup-middleware.js";
20
+ import { setupError } from "./setup-error.js";
21
+
22
+ export interface RouteFileMap {
23
+ [filePath: string]: {
24
+ routes: {
25
+ path?: string;
26
+ method?: string;
27
+ options?: RouterHandlerOptions;
28
+ inflatePath?: string;
29
+ }[];
30
+ service: string;
31
+ previewMethod: "api" | "html" | null;
32
+ }
33
+ }
34
+
35
+ export interface StaticFileMap {
36
+ [filePathKey: string]: {
37
+ path: string;
38
+ filePath: string;
39
+ method: string | null;
40
+ inflatePath?: string;
41
+ contentType: string;
42
+ previewMethod: "html" | null;
43
+ body: Buffer;
44
+ }
45
+ }
46
+
47
+ export async function setupHTTPRouter(server: ServerInterface, logger: Logger, hotreload: boolean, servicePath: string, service: string, routeFileMap: RouteFileMap, staticFileMap: StaticFileMap | null, inflateDir: string | undefined | false, inflateSea: boolean, errors: InflateError[]) {
48
+ const mainRouter = new Router();
49
+ const apiRouterPath = getHTTPRouterPath(servicePath); //resolve(process.cwd(), service, "http");
50
+ let middlewareConfig: MiddlewareConfig | null = null;
51
+
52
+ await setupError(logger, servicePath, service, mainRouter, inflateDir, inflateSea, errors);
53
+
54
+ await setupCORS(logger, servicePath, service, mainRouter, inflateDir, inflateSea, errors);
55
+ await setupAUTH(logger, servicePath, service, mainRouter, inflateDir, inflateSea, errors);
56
+ middlewareConfig = await setupMiddleware(logger, servicePath, service, mainRouter, inflateDir, inflateSea, errors);
57
+
58
+ if (apiRouterPath) {
59
+ logger.trace("setting up http routes from [%s]", service);
60
+ const { router: httpRouter } = await createRouterFromDirectory(server, hotreload, service, logger, apiRouterPath, errors, routeFileMap, staticFileMap, inflateDir, inflateSea);
61
+ mainRouter.use(httpRouter);
62
+ }
63
+
64
+ const staticFilesPath = getStaticFilesPath(servicePath); //resolve(process.cwd(), service, "static");
65
+ if (staticFilesPath) {
66
+ logger.trace("setting up static file routes from [%s]", service);
67
+ const staticRouter = createStaticRouterFromDirectory(service, logger, staticFilesPath, inflateDir, routeFileMap, staticFileMap);
68
+ mainRouter.use(staticRouter);
69
+ }
70
+
71
+ if (middlewareConfig && middlewareConfig.post) {
72
+ for (const m of middlewareConfig.post) {
73
+ mainRouter.use(m);
74
+ }
75
+ }
76
+
77
+ return mainRouter;
78
+ }
79
+
80
+ function createStaticRoute(service: string, logger: Logger, router: Router, dir: string, file: ScannedFile, inflateDir?: string | undefined | false, routeFileMap?: RouteFileMap, staticFileMap?: StaticFileMap) {
81
+ logger.trace("creating static route for [%s]", file.filePath);
82
+ logger.trace("[%o]", {
83
+ file,
84
+ dir
85
+ });
86
+ const contentType = CONTENT_TYPE_MAP[String(file.ext).toLocaleLowerCase()];
87
+ const path = join("/", relative(dir, file.filePath));
88
+
89
+
90
+ routeFileMap[file.filePath] = {
91
+ routes: [{
92
+ method: "GET",
93
+ path: normalizePath(path)
94
+ }],
95
+ service,
96
+ previewMethod: "html"
97
+ };
98
+
99
+ if (inflateDir) {
100
+ const inflatePath = join(inflateDir, service, "static", path);
101
+ mkdirSync(dirname(inflatePath), {
102
+ recursive: true
103
+ });
104
+ logger.log("writing [%s]", relative(cwd(), inflatePath));
105
+ const body = readFileSync(file.filePath);
106
+ writeFileSync(inflatePath, body);
107
+ if (staticFileMap) {
108
+ staticFileMap[file.filePath] = {
109
+ contentType,
110
+ filePath: file.filePath,
111
+ previewMethod: "html",
112
+ method: "GET",
113
+ path: normalizePath(path),
114
+ body: Buffer.from(body),
115
+ inflatePath: inflateDir ? join(inflateDir, service, "static", path) : undefined
116
+ }
117
+ }
118
+ }
119
+
120
+
121
+
122
+ router.use(assertGlobalTampered);
123
+ router.get(path, async function (_req, res) {
124
+ await new Promise<void>((resolve, reject) => {
125
+ try {
126
+ readFile(file.filePath, async (err, body) => {
127
+ if (err) {
128
+ reject(err);
129
+ } else {
130
+ try {
131
+ await res.asyncEnd({
132
+ status: 200,
133
+ headers: {
134
+ ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
135
+ },
136
+ body
137
+ });
138
+ resolve();
139
+ } catch (e) {
140
+ reject(e);
141
+ }
142
+ }
143
+ })
144
+ } catch (e) {
145
+ reject(e);
146
+ }
147
+ });
148
+ });
149
+ }
150
+
151
+ function createStaticRouterFromDirectory(service: string, logger: Logger, dir: string, inflateDir: string | false | undefined, routeFileMap: RouteFileMap | undefined, staticFileMap: StaticFileMap | null): Router {
152
+ const router = new Router();
153
+ scanFiles(dir).forEach(file => {
154
+ createStaticRoute(service, logger, router, dir, file, inflateDir, routeFileMap, staticFileMap);
155
+ });
156
+ return router;
157
+ }
158
+
159
+ async function createRouterFromDirectory(server: ServerInterface, hotreload: boolean, service: string, logger: Logger, dir: string, errors: InflateError[] = [], routeFileMap: RouteFileMap = {}, staticFileMap: StaticFileMap | null = null, inflateDir: string | undefined | false, inflateSea: boolean): Promise<{
160
+ router: Router;
161
+ errors: InflateError[];
162
+ routeFileMap: RouteFileMap;
163
+ }> {
164
+ const router = new Router();
165
+ router.use(assertGlobalTampered);
166
+ await Promise.all(scanFiles(dir).map(file => new Promise<void>(async (resolve) => {
167
+ try {
168
+ switch (file.ext) {
169
+ case ".jsx":
170
+ case ".js":
171
+ case ".ts":
172
+ case ".tsx": {
173
+ switch (file.subExt) {
174
+ case ".test":
175
+ return resolve();
176
+ case ".ignore":
177
+ logger.warn("ignoring [%s]", file.filePath);
178
+ return resolve();
179
+ case ".api": {
180
+
181
+ const module = await importAPIRoute(file.filePath, logger);
182
+
183
+ const routes = getRoutes(join("/", dirname(relative(dir, file.filePath))), file.subName, module);
184
+
185
+ routeFileMap[file.filePath] = {
186
+ routes,
187
+ service,
188
+ previewMethod: "api"
189
+ };
190
+
191
+ const inflatedCode = inflateDir ? await inflateJSX(file.filePath, {
192
+ embemedJSX: false,
193
+ minify: false,
194
+ useExport: true,
195
+ logger
196
+ }) : "";
197
+
198
+ for (const r of routes) {
199
+
200
+ /*if (inflateDir && r.inflatePath) {
201
+ const rPath = r.inflatePath;
202
+ const inflatePath = join(inflateDir, service, "http", rPath + ".api.js");
203
+ mkdirSync(dirname(inflatePath), {
204
+ recursive: true
205
+ });
206
+ logger.log("writing [%s]", relative(cwd(), inflatePath));
207
+ writeFileSync(inflatePath, inflatedCode);
208
+ }*/
209
+
210
+ if (inflateDir && r.defaultInflatePath && inflateSea) {
211
+ const rPath = r.defaultInflatePath;
212
+ const inflatePath = join(inflateDir, service, "http", rPath + ".api.js");
213
+ mkdirSync(dirname(inflatePath), {
214
+ recursive: true
215
+ });
216
+ logger.log("writing [%s]", relative(cwd(), inflatePath));
217
+ writeFileSync(inflatePath, inflatedCode);
218
+ }
219
+
220
+
221
+ router.use(assertGlobalTampered);
222
+ router.use(module.handler, r.path, r.method as any, r.options);
223
+ }
224
+ return resolve();
225
+ }
226
+ case ".json": {
227
+ const module = await importJSONModule(file.filePath, logger);
228
+ const routes = getRoutes(join("/", dirname(relative(dir, file.filePath))), file.subName + ".json", module.apiOptions as Partial<APIRoute>);
229
+
230
+ routeFileMap[file.filePath] = {
231
+ routes,
232
+ service,
233
+ previewMethod: "html"
234
+ };
235
+
236
+ for (const r of routes) {
237
+
238
+ const contentType = CONTENT_TYPE_MAP[".json"] ? CONTENT_TYPE_MAP[".json"] : DEFAULT_CONTENT_TYPE;
239
+
240
+
241
+
242
+ if (inflateDir) {
243
+
244
+ if (r.inflatePath) {
245
+ //if (r.method === "GET" || r.method === "get") {
246
+ const rPath = r.inflatePath;
247
+ const inflatePath = join(inflateDir, service, "static", rPath);
248
+ mkdirSync(dirname(inflatePath), {
249
+ recursive: true
250
+ });
251
+ if (existsSync(inflatePath) && statSync(inflatePath).isDirectory()) {
252
+ logger.trace("ignoring writing over directory [%s] for file [%s]", relative(cwd(), inflatePath), file.filePath);
253
+ continue;
254
+ }
255
+ const JSON_STATIC = await getJSON({ server } as ServerRequest, null, newURL(r.path), module.apiOptions?.basePath, module.default);
256
+ //const JSON = await getJSON({ server } as ServerRequest, null, newURL(r.path), module.apiOptions?.basePath, module.default);
257
+ logger.log("writing [%s]", relative(cwd(), inflatePath));
258
+ writeFileSync(inflatePath, JSON_STATIC);
259
+ //}
260
+
261
+ if (staticFileMap && inflateSea) {
262
+ staticFileMap[file.filePath] = {
263
+ contentType,
264
+ filePath: file.filePath,
265
+ method: r.method,
266
+ previewMethod: "html",
267
+ path: r.path,
268
+ body: Buffer.from(JSON_STATIC),
269
+ inflatePath: inflateDir ? join(inflateDir, service, "static", r.inflatePath) : undefined
270
+ }
271
+ }
272
+ }
273
+ }
274
+
275
+ router.use(assertGlobalTampered);
276
+ router.use(async function (req: Request, res: Response) {
277
+
278
+ const JSON = await getJSON(req, res, newURL(req.path), module.apiOptions?.basePath, module.default);
279
+
280
+ return res.asyncEnd({
281
+ status: 200,
282
+ headers: {
283
+ ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
284
+ },
285
+ body: JSON
286
+ });
287
+ }, r.path, r.method as any, r.options)
288
+ }
289
+
290
+ return resolve();
291
+ }
292
+ case ".html": {
293
+
294
+ const module = await importHTMLModule(file.filePath, logger);
295
+
296
+ const routes = getRoutes(join("/", dirname(relative(dir, file.filePath))), file.subName + ".html", module.apiOptions as Partial<APIRoute>);
297
+
298
+ routeFileMap[file.filePath] = {
299
+ routes,
300
+ service,
301
+ previewMethod: "html"
302
+ };
303
+
304
+ for (const r of routes) {
305
+
306
+ const contentType = CONTENT_TYPE_MAP[".html"] ? CONTENT_TYPE_MAP[".html"] : DEFAULT_CONTENT_TYPE;
307
+
308
+ if (inflateDir) {
309
+
310
+ if (r.inflatePath) {
311
+ //if (r.method === "GET" || r.method === "get") {
312
+ const rPath = r.inflatePath;
313
+ const inflatePath = join(inflateDir, service, "static", rPath);
314
+ mkdirSync(dirname(inflatePath), {
315
+ recursive: true
316
+ });
317
+ if (existsSync(inflatePath) && statSync(inflatePath).isDirectory()) {
318
+ logger.trace("ignoring writing over directory [%s] for file [%s]", relative(cwd(), inflatePath), file.filePath);
319
+ continue;
320
+ }
321
+ const toRender = typeof module.default === "function" ? module.default({ server } as ServerRequest, null) : module.default;
322
+ const HTML_STATIC = await getHTML(hotreload, { server } as ServerRequest, null, newURL(r.path), module.apiOptions?.basePath, await toRender);
323
+
324
+ logger.log("writing [%s]", relative(cwd(), inflatePath));
325
+ writeFileSync(inflatePath, HTML_STATIC);
326
+ //}
327
+
328
+
329
+ if (staticFileMap && inflateSea) {
330
+ staticFileMap[file.filePath + r.method + r.path] = {
331
+ filePath: file.filePath,
332
+ contentType,
333
+ method: r.method,
334
+ previewMethod: "html",
335
+ path: r.path,
336
+ body: Buffer.from(HTML_STATIC),
337
+ inflatePath: inflateDir ? join(inflateDir, service, "static", r.inflatePath) : undefined
338
+ }
339
+ }
340
+ }
341
+ }
342
+
343
+ router.use(assertGlobalTampered);
344
+ router.use(async function (req: Request, res: Response) {
345
+ const toRender = typeof module.default === "function" ? module.default(req, res) : module.default;
346
+ const HTML = await getHTML(hotreload, req, res, newURL(req.path), module.apiOptions?.basePath, await toRender);
347
+
348
+ return res.asyncEnd({
349
+ status: 200,
350
+ headers: {
351
+ ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
352
+ },
353
+ body: HTML
354
+ });
355
+ }, r.path, r.method as any, r.options)
356
+ }
357
+ return resolve();
358
+ }
359
+ case ".min":
360
+ case ".js":
361
+ default: {
362
+ // allow fall-through when extension is .js and .ts because is a static route without embemedJSX
363
+ if (file.ext !== ".js" && file.ext !== ".ts") {
364
+ const code = await inflateJSX(file.filePath, {
365
+ embemedJSX: true,
366
+ minify: file.subExt === ".min" ? true : false,
367
+ useExport: false,
368
+ logger
369
+ });
370
+ const contentType = CONTENT_TYPE_MAP[".js"];
371
+ const path = join("/", dirname(relative(dir, file.filePath)), file.name + ".js");
372
+
373
+ routeFileMap[file.filePath] = {
374
+ routes: [{
375
+ method: "GET",
376
+ path
377
+ }],
378
+ service,
379
+ previewMethod: "html"
380
+ };
381
+
382
+ if (inflateDir) {
383
+ const inflatePath = join(inflateDir, service, "static", path);
384
+ mkdirSync(dirname(inflatePath), {
385
+ recursive: true
386
+ });
387
+ logger.log("writing [%s]", relative(cwd(), inflatePath));
388
+ writeFileSync(inflatePath, code);
389
+
390
+
391
+ if (staticFileMap && inflateSea) {
392
+ staticFileMap[file.filePath] = {
393
+ contentType,
394
+ filePath: file.filePath,
395
+ method: "GET",
396
+ previewMethod: "html",
397
+ path,
398
+ body: Buffer.from(code),
399
+ inflatePath: inflateDir ? join(inflateDir, service, "static", path) : undefined
400
+ }
401
+ }
402
+ }
403
+
404
+ router.use(assertGlobalTampered);
405
+ router.get(path, async function (req, res) {
406
+ return res.asyncEnd({
407
+ status: 200,
408
+ headers: {
409
+ ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
410
+ },
411
+ body: code
412
+ });
413
+ });
414
+ return resolve();
415
+ }
416
+ }
417
+ }
418
+ }
419
+ case ".md": {
420
+ switch (file.subExt) {
421
+ case ".html": {
422
+ const code = await inflateMD2HTML(file.filePath, logger);
423
+ const contentType = CONTENT_TYPE_MAP[".html"];
424
+ const path = join("/", dirname(relative(dir, file.filePath)), file.name);
425
+ routeFileMap[file.filePath] = {
426
+ routes: [{
427
+ method: "GET",
428
+ path
429
+ }],
430
+ service,
431
+ previewMethod: "html"
432
+ };
433
+
434
+ if (inflateDir) {
435
+ const inflatePath = join(inflateDir, service, "static", path);
436
+ mkdirSync(dirname(inflatePath), {
437
+ recursive: true
438
+ });
439
+ logger.log("writing [%s]", relative(cwd(), inflatePath));
440
+ writeFileSync(inflatePath, code);
441
+ if (staticFileMap && inflateSea) {
442
+ staticFileMap[file.filePath] = {
443
+ contentType,
444
+ method: "GET",
445
+ filePath: file.filePath,
446
+ previewMethod: "html",
447
+ path,
448
+ body: Buffer.from(code),
449
+ inflatePath: inflateDir ? join(inflateDir, service, "static", path) : undefined
450
+ }
451
+ }
452
+ }
453
+
454
+ router.use(assertGlobalTampered);
455
+ router.get(path, async function (_req, res) {
456
+ res.asyncEnd({
457
+ status: 200,
458
+ headers: {
459
+ ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
460
+ },
461
+ body: code
462
+ });
463
+ });
464
+ return resolve();
465
+ }
466
+ }
467
+ }
468
+ default:
469
+ if (file.ext === ".js" || file.ext === ".ts") {
470
+ switch (file.subExt) {
471
+ case ".ignore": {
472
+ logger.warn("ignoring [%s]", file.filePath);
473
+ return resolve();
474
+ }
475
+ case ".bundle":
476
+ case ".min": {
477
+ const code = await inflateJSX(file.filePath, {
478
+ embemedJSX: false,
479
+ minify: file.subExt === ".min" ? true : false,
480
+ useExport: false,
481
+ logger
482
+ });
483
+ const contentType = CONTENT_TYPE_MAP[".js"];
484
+ const path = join("/", dirname(relative(dir, file.filePath)), file.name + ".js");
485
+ routeFileMap[file.filePath] = {
486
+ routes: [{
487
+ method: "GET",
488
+ path
489
+ }],
490
+ service,
491
+ previewMethod: "html"
492
+ };
493
+
494
+ if (inflateDir) {
495
+ const inflatePath = join(inflateDir, service, "static", path);
496
+ mkdirSync(dirname(inflatePath), {
497
+ recursive: true
498
+ });
499
+ logger.log("writing [%s]", relative(cwd(), inflatePath));
500
+ writeFileSync(inflatePath, code);
501
+ if (staticFileMap && inflateSea) {
502
+ staticFileMap[file.filePath] = {
503
+ contentType,
504
+ method: "GET",
505
+ filePath: file.filePath,
506
+ previewMethod: "html",
507
+ path,
508
+ body: Buffer.from(code),
509
+ inflatePath: inflateDir ? join(inflateDir, service, "static", path) : undefined
510
+ }
511
+ }
512
+ }
513
+
514
+ router.use(assertGlobalTampered);
515
+ router.get(path, async function (_req, res) {
516
+ res.asyncEnd({
517
+ status: 200,
518
+ headers: {
519
+ ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
520
+ },
521
+ body: code
522
+ });
523
+ });
524
+ return resolve();
525
+ }
526
+ }
527
+ } else if (file.ext === ".bundle") {
528
+ switch (file.subExt) {
529
+ case ".ignore": {
530
+ logger.warn("ignoring [%s]", file.filePath);
531
+ return resolve();
532
+ }
533
+ case ".css": {
534
+ const code = readFileSync(file.filePath).toString()
535
+ .split("\n")
536
+ .filter(c => c)
537
+ .filter(c => c.charAt(0) !== "#")
538
+ .map(cssPath => readFileSync(pathResolve(dirname(file.filePath), cssPath)).toString())
539
+ .join("\n");
540
+ const contentType = CONTENT_TYPE_MAP[".css"];
541
+ const path = join("/", dirname(relative(dir, file.filePath)), file.name);
542
+ routeFileMap[file.filePath] = {
543
+ routes: [{
544
+ method: "GET",
545
+ path
546
+ }],
547
+ service,
548
+ previewMethod: "html"
549
+ };
550
+
551
+ if (inflateDir) {
552
+ const inflatePath = join(inflateDir, service, "static", path);
553
+ mkdirSync(dirname(inflatePath), {
554
+ recursive: true
555
+ });
556
+ logger.log("writing [%s]", relative(cwd(), inflatePath));
557
+ writeFileSync(inflatePath, code);
558
+ if (staticFileMap && inflateSea) {
559
+ staticFileMap[file.filePath] = {
560
+ contentType,
561
+ method: "GET",
562
+ filePath: file.filePath,
563
+ previewMethod: "html",
564
+ path,
565
+ body: Buffer.from(code),
566
+ inflatePath: inflateDir ? join(inflateDir, service, "static", path) : undefined
567
+ }
568
+ }
569
+ }
570
+
571
+ router.use(assertGlobalTampered);
572
+ router.get(path, async function (_req, res) {
573
+ res.asyncEnd({
574
+ status: 200,
575
+ headers: {
576
+ ["Content-Type"]: contentType ? contentType : DEFAULT_CONTENT_TYPE
577
+ },
578
+ body: code
579
+ });
580
+ });
581
+ return resolve();
582
+ }
583
+ }
584
+ }
585
+ createStaticRoute(service, logger, router, dir, file, inflateDir, routeFileMap, staticFileMap);
586
+ return resolve();
587
+
588
+ }
589
+ } catch (e) {
590
+ logger.error("error with " + file.filePath);
591
+ logger.error(e);
592
+ errors.push({
593
+ filePath: file.filePath,
594
+ error: e
595
+ });
596
+ } finally {
597
+ return resolve();
598
+ }
599
+ })));
600
+ router.use(assertGlobalTampered);
601
+ return {
602
+ routeFileMap,
603
+ router,
604
+ errors
605
+ };
606
+ }
607
+
608
+ interface ScannedFile {
609
+ filePath: string;
610
+ ext: string;
611
+ fileName: string;
612
+ name: string;
613
+ subExt: string;
614
+ subName: string;
615
+ }
616
+
617
+ export function scanFiles(path: string, ret: ScannedFile[] = []): ScannedFile[] {
618
+ const files = readdirSync(path).sort();
619
+ for (const file of files) {
620
+ const filePath = pathResolve(path, file);
621
+ if (statSync(filePath).isDirectory()) {
622
+ scanFiles(filePath, ret);
623
+ continue;
624
+ } else {
625
+ const description = describeFilePath(filePath);
626
+ if (description.fileName === ".DS_Store") {
627
+ continue;
628
+ }
629
+ ret.push(description);
630
+ }
631
+ }
632
+ return ret;
633
+ }
634
+
635
+
636
+
637
+ function getHTML(hotreload: boolean, req: ServerRequest, res: Response | null, url: RuntimeURL, basePath: string | undefined, out: JSX.Element): string {
638
+ let HTML = `<!DOCTYPE html>\n${jsx2HTML(out, createNodeRuntime({
639
+ url,
640
+ basePath
641
+ }))}`;
642
+
643
+ //console.log("GET_HTML[%s] [%o]", HTML, out);
644
+
645
+ if (hotreload) {
646
+ HTML += getHotReloadScript()
647
+ }
648
+ return HTML;
649
+ }
650
+
651
+ async function getJSON(req: ServerRequest, res: Response | null, url: RuntimeURL, basePath: string | undefined, out: JSONModuleValue | Promise<JSONModuleValue> | ((req: Request | null, res: Response | null) => JSONModuleValue | Promise<JSONModuleValue>)) {
652
+
653
+ const toRender = await (typeof out === "function" ? out(req, res) : out);
654
+ return JSON.stringify(toRender, undefined, 2);
655
+ }
@@ -0,0 +1,44 @@
1
+ import { Logger } from "@miqro/core";
2
+ import { importLogConfigModule, InflateError, inflateJSX } from "../common/jsx.js";
3
+ import { getLogConfigPath } from "../common/paths.js";
4
+ import { dirname, relative, resolve } from "node:path";
5
+ import { mkdirSync, writeFileSync } from "node:fs";
6
+ import { cwd } from "node:process";
7
+ import { LogConfig } from "../types.js";
8
+
9
+ export interface LogConfigMap {
10
+ [service: string]: LogConfig | undefined;
11
+ }
12
+
13
+ export async function setupLogConfig(logger: Logger, servicePath: string, service: string, logConfigMap: LogConfigMap, inflateDir: string | undefined | false, errors: InflateError[]) {
14
+ const logPath = getLogConfigPath(servicePath); // resolve(process.cwd(), service, "server.ts");
15
+ if (logPath) {
16
+ try {
17
+ //logger.debug("setting up server config from [%s]", join(service, basename(serverPath)));
18
+
19
+ const logConfig = await importLogConfigModule(logPath, logger);
20
+ logConfigMap[service] = logConfig;
21
+
22
+ if (inflateDir) {
23
+ const inflatePath = resolve(inflateDir, service, "log.js");
24
+ mkdirSync(dirname(inflatePath), {
25
+ recursive: true
26
+ });
27
+ logger.log("writing [%s]", relative(cwd(), inflatePath));
28
+ writeFileSync(inflatePath, await inflateJSX(logPath, {
29
+ embemedJSX: false,
30
+ minify: false,
31
+ useExport: true,
32
+ logger
33
+ }));
34
+ }
35
+ } catch (e) {
36
+ errors.push({
37
+ filePath: logPath,
38
+ error: e
39
+ });
40
+ logger.error("error with " + logPath);
41
+ logger.error(e);
42
+ }
43
+ }
44
+ }