@noego/forge 0.0.11 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.cjs +1 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.mjs +113 -117
- package/dist/client.mjs.map +1 -1
- package/dist/options/ServerOptions.cjs +28 -0
- package/dist/options/ServerOptions.cjs.map +1 -0
- package/dist/options/ServerOptions.d.ts +19 -0
- package/dist/options/ServerOptions.mjs +21 -0
- package/dist/options/ServerOptions.mjs.map +1 -0
- package/dist/options/assets.cjs +42 -0
- package/dist/options/assets.cjs.map +1 -0
- package/dist/options/assets.d.ts +46 -0
- package/dist/options/assets.mjs +38 -0
- package/dist/options/assets.mjs.map +1 -0
- package/dist/plugins/serverOnlyStub.d.ts +6 -0
- package/dist/plugins-cjs/index.plugins.js +9 -0
- package/dist/plugins-cjs/index.plugins.js.map +1 -0
- package/dist/plugins-cjs/options/ServerOptions.js +28 -0
- package/dist/plugins-cjs/options/ServerOptions.js.map +1 -0
- package/dist/plugins-cjs/options/assets.js +42 -0
- package/dist/plugins-cjs/options/assets.js.map +1 -0
- package/dist/plugins-cjs/plugins/serverOnlyStub.js +226 -0
- package/dist/plugins-cjs/plugins/serverOnlyStub.js.map +1 -0
- package/dist/plugins-cjs/routing/html_render/html_render.js +62 -0
- package/dist/plugins-cjs/routing/html_render/html_render.js.map +1 -0
- package/dist/plugins-cjs/stubs/server-only.js +10 -0
- package/dist/plugins-cjs/stubs/server-only.js.map +1 -0
- package/dist/plugins-es/index.plugins.d.ts +2 -0
- package/dist/plugins-es/index.plugins.js +2 -0
- package/dist/plugins-es/index.plugins.js.map +1 -0
- package/dist/plugins-es/options/ServerOptions.d.ts +19 -0
- package/dist/plugins-es/options/ServerOptions.js +21 -0
- package/dist/plugins-es/options/ServerOptions.js.map +1 -0
- package/dist/plugins-es/options/assets.d.ts +46 -0
- package/dist/plugins-es/options/assets.js +38 -0
- package/dist/plugins-es/options/assets.js.map +1 -0
- package/dist/plugins-es/plugins/serverOnlyStub.d.ts +6 -0
- package/dist/plugins-es/plugins/serverOnlyStub.js +200 -0
- package/dist/plugins-es/plugins/serverOnlyStub.js.map +1 -0
- package/dist/plugins-es/routing/html_render/html_render.d.ts +19 -0
- package/dist/plugins-es/routing/html_render/html_render.js +53 -0
- package/dist/plugins-es/routing/html_render/html_render.js.map +1 -0
- package/dist/plugins-es/stubs/server-only.d.ts +3 -0
- package/dist/plugins-es/stubs/server-only.js +7 -0
- package/dist/plugins-es/stubs/server-only.js.map +1 -0
- package/dist/routing/html_render/html_render.d.ts +19 -0
- package/dist/routing/html_render/html_render.js +53 -0
- package/dist/routing/html_render/html_render.js.map +1 -0
- package/dist-ssr/server.cjs +253 -37
- package/dist-ssr/server.cjs.map +1 -1
- package/dist-ssr/server.js +253 -37
- package/dist-ssr/server.js.map +1 -1
- package/package.json +11 -4
package/dist-ssr/server.js
CHANGED
|
@@ -3,36 +3,27 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
import express from "express";
|
|
5
5
|
import path from "path";
|
|
6
|
-
import deepmerge from "deepmerge";
|
|
7
6
|
import fs from "fs";
|
|
7
|
+
import deepmerge from "deepmerge";
|
|
8
|
+
import { pathToFileURL } from "url";
|
|
8
9
|
import Handlebars from "handlebars";
|
|
9
10
|
import fs$1 from "fs/promises";
|
|
10
11
|
import yaml from "js-yaml";
|
|
11
12
|
import "clone-deep";
|
|
12
13
|
import join from "url-join";
|
|
13
14
|
import { p as parsePathConfig } from "./path-BqcF5dbs.js";
|
|
14
|
-
import { pathToFileURL } from "url";
|
|
15
15
|
import { render } from "svelte/server";
|
|
16
16
|
import pathToRegex from "path-to-regex";
|
|
17
|
-
import ApplicationRenderer from "../src/components/RecursiveRender.svelte";
|
|
18
17
|
class ViteComponentLoader {
|
|
19
18
|
constructor(basePath, vite) {
|
|
20
19
|
this.basePath = basePath;
|
|
21
20
|
this.vite = vite;
|
|
22
21
|
}
|
|
23
22
|
async load(componentPath, options = { use_base_path: true }) {
|
|
24
|
-
|
|
25
|
-
const use_base_path = options.use_base_path || false;
|
|
26
|
-
if (use_base_path) {
|
|
27
|
-
absoluteComponentPath = path.join(this.basePath, componentPath);
|
|
28
|
-
} else {
|
|
29
|
-
if (path.isAbsolute(componentPath)) {
|
|
30
|
-
absoluteComponentPath = componentPath;
|
|
31
|
-
} else {
|
|
32
|
-
absoluteComponentPath = componentPath;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
23
|
+
const absoluteComponentPath = this.getComponentFullPath(componentPath, options);
|
|
35
24
|
console.log(`[ViteComponentLoader] Loading component from path: ${absoluteComponentPath}`);
|
|
25
|
+
const jsPath = absoluteComponentPath.replace(/\.svelte$/, ".js");
|
|
26
|
+
fs.existsSync(jsPath);
|
|
36
27
|
let vitePath = path.relative(process.cwd(), absoluteComponentPath);
|
|
37
28
|
vitePath = vitePath.replace(/\\/g, "/");
|
|
38
29
|
if (!vitePath.startsWith("/")) {
|
|
@@ -57,16 +48,74 @@ class ViteComponentLoader {
|
|
|
57
48
|
throw error;
|
|
58
49
|
}
|
|
59
50
|
}
|
|
51
|
+
getComponentFullPath(componentPath, options = { use_base_path: true }) {
|
|
52
|
+
const use_base_path = options.use_base_path || false;
|
|
53
|
+
if (use_base_path) {
|
|
54
|
+
return path.join(this.basePath, componentPath);
|
|
55
|
+
}
|
|
56
|
+
if (path.isAbsolute(componentPath)) {
|
|
57
|
+
return componentPath;
|
|
58
|
+
}
|
|
59
|
+
return componentPath;
|
|
60
|
+
}
|
|
60
61
|
}
|
|
61
62
|
class ProdComponentLoader {
|
|
62
63
|
constructor(base_path) {
|
|
64
|
+
__publicField(this, "componentMapPromise", null);
|
|
63
65
|
this.base_path = base_path;
|
|
64
66
|
}
|
|
65
67
|
async load(componentPath) {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
+
const normalized = this.normalizeKey(componentPath);
|
|
69
|
+
try {
|
|
70
|
+
const map = await this.loadComponentMap();
|
|
71
|
+
const module2 = map[normalized];
|
|
72
|
+
if (module2) {
|
|
73
|
+
return module2;
|
|
74
|
+
}
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.warn(`[Forge] Failed to load component "${componentPath}" from entry manifest:`, error);
|
|
77
|
+
}
|
|
78
|
+
const component_path = this.getComponentFullPath(componentPath);
|
|
79
|
+
const fallbackPath = component_path.endsWith(".js") ? component_path : component_path.replace(/\.svelte$/, ".js");
|
|
80
|
+
const module = await import(pathToFileURL(fallbackPath).href);
|
|
68
81
|
return module;
|
|
69
82
|
}
|
|
83
|
+
getComponentFullPath(componentPath) {
|
|
84
|
+
return path.join(this.base_path, componentPath);
|
|
85
|
+
}
|
|
86
|
+
normalizeKey(componentPath) {
|
|
87
|
+
const trimmed = componentPath.replace(/^\.\//, "");
|
|
88
|
+
if (trimmed.endsWith(".svelte")) {
|
|
89
|
+
return trimmed.replace(/\.svelte$/, ".js");
|
|
90
|
+
}
|
|
91
|
+
return trimmed;
|
|
92
|
+
}
|
|
93
|
+
async loadComponentMap() {
|
|
94
|
+
if (!this.componentMapPromise) {
|
|
95
|
+
const entryPath = path.join(this.base_path, "entry-ssr.js");
|
|
96
|
+
const entryUrl = pathToFileURL(entryPath).href;
|
|
97
|
+
this.componentMapPromise = import(entryUrl).then((mod) => {
|
|
98
|
+
const source = mod.components ?? mod.default ?? {};
|
|
99
|
+
const normalized = {};
|
|
100
|
+
for (const [key, value] of Object.entries(source)) {
|
|
101
|
+
const cleanKey = key.replace(/^\.\//, "");
|
|
102
|
+
normalized[cleanKey] = value;
|
|
103
|
+
if (cleanKey.startsWith("ui/")) {
|
|
104
|
+
normalized[cleanKey.slice(3)] = value;
|
|
105
|
+
}
|
|
106
|
+
if (cleanKey.endsWith(".svelte")) {
|
|
107
|
+
const jsKey = cleanKey.replace(/\.svelte$/, ".js");
|
|
108
|
+
normalized[jsKey] = value;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return normalized;
|
|
112
|
+
}).catch((error) => {
|
|
113
|
+
this.componentMapPromise = null;
|
|
114
|
+
throw error;
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return this.componentMapPromise;
|
|
118
|
+
}
|
|
70
119
|
}
|
|
71
120
|
const default_template = `
|
|
72
121
|
<!DOCTYPE html>
|
|
@@ -257,11 +306,9 @@ async function parse_openapi_config(openapi_config_path) {
|
|
|
257
306
|
const defaultViteOptions = {
|
|
258
307
|
appType: "custom",
|
|
259
308
|
root: process.cwd(),
|
|
260
|
-
// Explicitly set root
|
|
261
309
|
server: { middlewareMode: true },
|
|
262
310
|
ssr: {
|
|
263
311
|
noExternal: ["svelte", /^svelte\/.*/]
|
|
264
|
-
// Adjust if needed, maybe add your component specifically if still failing
|
|
265
312
|
}
|
|
266
313
|
};
|
|
267
314
|
const defaultOptions = {
|
|
@@ -349,7 +396,7 @@ class ApiAdapter {
|
|
|
349
396
|
layout: layout_data,
|
|
350
397
|
view: view_data
|
|
351
398
|
};
|
|
352
|
-
return server_data;
|
|
399
|
+
return this.mergeLoaderData(route, request_data, server_data);
|
|
353
400
|
}
|
|
354
401
|
async getFallbackData(route, request_data) {
|
|
355
402
|
const view = await this.manager.getViewComponent(route);
|
|
@@ -374,7 +421,48 @@ class ApiAdapter {
|
|
|
374
421
|
layout: layout_data,
|
|
375
422
|
view: view_data
|
|
376
423
|
};
|
|
377
|
-
return server_data;
|
|
424
|
+
return this.mergeLoaderData(route, request_data, server_data);
|
|
425
|
+
}
|
|
426
|
+
async mergeLoaderData(route, request_data, server_data) {
|
|
427
|
+
if (!await this.manager.hasLoaders(route)) {
|
|
428
|
+
return server_data;
|
|
429
|
+
}
|
|
430
|
+
const loaders = await this.manager.getLoaders(route);
|
|
431
|
+
const layoutLoaderResults = await Promise.all(
|
|
432
|
+
loaders.layouts.map(async (loader) => {
|
|
433
|
+
if (!loader) {
|
|
434
|
+
return null;
|
|
435
|
+
}
|
|
436
|
+
const data = await loader(request_data);
|
|
437
|
+
return data ?? null;
|
|
438
|
+
})
|
|
439
|
+
);
|
|
440
|
+
const baseLayoutData = server_data.layout || [];
|
|
441
|
+
const maxLayouts = Math.max(baseLayoutData.length, layoutLoaderResults.length);
|
|
442
|
+
const mergedLayouts = Array.from({ length: maxLayouts }, (_, index) => {
|
|
443
|
+
const baseLayoutEntry = baseLayoutData[index];
|
|
444
|
+
const loaderResult = layoutLoaderResults[index];
|
|
445
|
+
if (!loaderResult) {
|
|
446
|
+
return baseLayoutEntry;
|
|
447
|
+
}
|
|
448
|
+
if (baseLayoutEntry && typeof baseLayoutEntry === "object") {
|
|
449
|
+
return { ...baseLayoutEntry, ...loaderResult };
|
|
450
|
+
}
|
|
451
|
+
return loaderResult;
|
|
452
|
+
});
|
|
453
|
+
const viewLoaderResult = loaders.view ? await loaders.view(request_data) : null;
|
|
454
|
+
let mergedView = server_data.view;
|
|
455
|
+
if (viewLoaderResult) {
|
|
456
|
+
if (mergedView && typeof mergedView === "object") {
|
|
457
|
+
mergedView = { ...mergedView, ...viewLoaderResult };
|
|
458
|
+
} else {
|
|
459
|
+
mergedView = viewLoaderResult;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return {
|
|
463
|
+
layout: mergedLayouts,
|
|
464
|
+
view: mergedView
|
|
465
|
+
};
|
|
378
466
|
}
|
|
379
467
|
}
|
|
380
468
|
class ComponentManager {
|
|
@@ -407,6 +495,50 @@ class ComponentManager {
|
|
|
407
495
|
async getViewComponent(route) {
|
|
408
496
|
return await this.componentLoader.load(route.view);
|
|
409
497
|
}
|
|
498
|
+
async hasLoaders(route) {
|
|
499
|
+
const componentPaths = [...route.layout || [], route.view];
|
|
500
|
+
for (const componentPath of componentPaths) {
|
|
501
|
+
const loader = await this.resolveLoader(componentPath);
|
|
502
|
+
if (loader) {
|
|
503
|
+
return true;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
return false;
|
|
507
|
+
}
|
|
508
|
+
async getLoaders(route) {
|
|
509
|
+
const layoutPaths = route.layout || [];
|
|
510
|
+
const layouts = await Promise.all(layoutPaths.map((layoutPath) => this.resolveLoader(layoutPath)));
|
|
511
|
+
const view = await this.resolveLoader(route.view);
|
|
512
|
+
return {
|
|
513
|
+
layouts,
|
|
514
|
+
view
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
getLoaderFilePath(componentPath) {
|
|
518
|
+
if (!componentPath) {
|
|
519
|
+
return null;
|
|
520
|
+
}
|
|
521
|
+
const fullPath = this.componentLoader.getComponentFullPath(componentPath);
|
|
522
|
+
const { dir, name } = path.parse(fullPath);
|
|
523
|
+
return path.join(dir, `${name}.load.ts`);
|
|
524
|
+
}
|
|
525
|
+
async resolveLoader(componentPath) {
|
|
526
|
+
const loaderFilePath = this.getLoaderFilePath(componentPath);
|
|
527
|
+
if (!loaderFilePath) {
|
|
528
|
+
return null;
|
|
529
|
+
}
|
|
530
|
+
try {
|
|
531
|
+
const module = await import(pathToFileURL(loaderFilePath).href);
|
|
532
|
+
const loader = module == null ? void 0 : module.default;
|
|
533
|
+
return typeof loader === "function" ? loader : null;
|
|
534
|
+
} catch (error) {
|
|
535
|
+
if ((error == null ? void 0 : error.code) === "MODULE_NOT_FOUND" || (error == null ? void 0 : error.code) === "ERR_MODULE_NOT_FOUND") {
|
|
536
|
+
return null;
|
|
537
|
+
}
|
|
538
|
+
console.error(`[ComponentManager] Failed to load loader for ${componentPath}:`, error);
|
|
539
|
+
return null;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
410
542
|
async getView(route) {
|
|
411
543
|
const view = await this.componentLoader.load(route.view);
|
|
412
544
|
return view.default;
|
|
@@ -611,8 +743,9 @@ function initialize_route_matchers(routes) {
|
|
|
611
743
|
class ServerAdapter {
|
|
612
744
|
}
|
|
613
745
|
class ExpressServerAdapter extends ServerAdapter {
|
|
614
|
-
constructor(server, manager, htmlRender, api_adapter, middleware_adapter, context_builder, isProd = false) {
|
|
746
|
+
constructor(server, manager, htmlRender, api_adapter, middleware_adapter, context_builder, isProd = false, componentDir) {
|
|
615
747
|
super();
|
|
748
|
+
__publicField(this, "clientRoutes", []);
|
|
616
749
|
this.server = server;
|
|
617
750
|
this.manager = manager;
|
|
618
751
|
this.htmlRender = htmlRender;
|
|
@@ -620,6 +753,27 @@ class ExpressServerAdapter extends ServerAdapter {
|
|
|
620
753
|
this.middleware_adapter = middleware_adapter;
|
|
621
754
|
this.context_builder = context_builder;
|
|
622
755
|
this.isProd = isProd;
|
|
756
|
+
this.componentDir = componentDir;
|
|
757
|
+
}
|
|
758
|
+
async loadApplicationRenderer(componentRoot) {
|
|
759
|
+
if (!this.isProd) {
|
|
760
|
+
const mod = await import("../src/components/RecursiveRender.svelte");
|
|
761
|
+
return mod.default ?? mod;
|
|
762
|
+
}
|
|
763
|
+
const candidates = [
|
|
764
|
+
path.join(componentRoot, "RecursiveRender.js"),
|
|
765
|
+
path.join(componentRoot, "ssr", "RecursiveRender.js")
|
|
766
|
+
];
|
|
767
|
+
let lastError;
|
|
768
|
+
for (const fp of candidates) {
|
|
769
|
+
try {
|
|
770
|
+
const mod = await import(fp);
|
|
771
|
+
return mod.default ?? mod;
|
|
772
|
+
} catch (e) {
|
|
773
|
+
lastError = e;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
throw lastError ?? new Error("Unable to locate precompiled RecursiveRender.js");
|
|
623
777
|
}
|
|
624
778
|
transformRoutesForClient(routes) {
|
|
625
779
|
var _a, _b;
|
|
@@ -637,7 +791,9 @@ class ExpressServerAdapter extends ServerAdapter {
|
|
|
637
791
|
return transformed;
|
|
638
792
|
}
|
|
639
793
|
async handleRoutes(routes, manifest) {
|
|
640
|
-
const
|
|
794
|
+
const transformedRoutes = this.transformRoutesForClient(routes);
|
|
795
|
+
this.clientRoutes = transformedRoutes;
|
|
796
|
+
const matchers = initialize_route_matchers(transformedRoutes);
|
|
641
797
|
this.server.use((req, res, next) => {
|
|
642
798
|
(async () => {
|
|
643
799
|
if (res.headersSent) {
|
|
@@ -654,13 +810,13 @@ class ExpressServerAdapter extends ServerAdapter {
|
|
|
654
810
|
await not_found();
|
|
655
811
|
return;
|
|
656
812
|
}
|
|
657
|
-
const route_options =
|
|
813
|
+
const route_options = transformedRoutes.filter((r) => r.path === matcher.pattern);
|
|
658
814
|
const route = route_options.find((r) => r.method.toLowerCase() === method);
|
|
659
815
|
if (!route) {
|
|
660
816
|
await not_found();
|
|
661
817
|
return;
|
|
662
818
|
}
|
|
663
|
-
await this.handleResponse(fullUrl, matcher, route,
|
|
819
|
+
await this.handleResponse(fullUrl, matcher, route, transformedRoutes, manifest, req, res).catch((e) => {
|
|
664
820
|
res.status(500).send(`
|
|
665
821
|
<h1>500 Internal Server Error</h1>
|
|
666
822
|
<pre>${e}</pre>
|
|
@@ -671,7 +827,7 @@ class ExpressServerAdapter extends ServerAdapter {
|
|
|
671
827
|
});
|
|
672
828
|
}
|
|
673
829
|
async handleResponse(url, matcher, route, routes, manifest, req, res) {
|
|
674
|
-
var _a, _b;
|
|
830
|
+
var _a, _b, _c;
|
|
675
831
|
let accepts = req.headers.accept || "";
|
|
676
832
|
let server_api_call = accepts.toLowerCase().includes("application/json");
|
|
677
833
|
if (res.headersSent) {
|
|
@@ -745,7 +901,12 @@ ${e.stack}</pre>
|
|
|
745
901
|
params: request_data.params || {},
|
|
746
902
|
query: request_data.query
|
|
747
903
|
};
|
|
748
|
-
|
|
904
|
+
console.log("[SSR DEBUG] layouts:", layouts.map((l) => typeof l), "view:", typeof view);
|
|
905
|
+
const loader = ((_a = this.manager) == null ? void 0 : _a["componentLoader"]) || {};
|
|
906
|
+
const componentRoot = loader["base_path"] || loader["basePath"] || "";
|
|
907
|
+
const applicationRenderer = await this.loadApplicationRenderer(componentRoot);
|
|
908
|
+
console.log("[SSR DEBUG] applicationRenderer:", typeof applicationRenderer);
|
|
909
|
+
const { head: head_render, html: renderedHtml, css } = render(applicationRenderer, {
|
|
749
910
|
props: {
|
|
750
911
|
layouts,
|
|
751
912
|
view,
|
|
@@ -756,9 +917,12 @@ ${e.stack}</pre>
|
|
|
756
917
|
page
|
|
757
918
|
}
|
|
758
919
|
});
|
|
920
|
+
const body_render = renderedHtml;
|
|
921
|
+
console.log("[SSR DEBUG] render result - body length:", (body_render == null ? void 0 : body_render.length) || 0);
|
|
922
|
+
const clientComponentDir = this.isProd ? "assets" : this.componentDir;
|
|
759
923
|
const head_routing = `
|
|
760
924
|
<script type='text/javascript'>
|
|
761
|
-
window.__ROUTING__ = ${JSON.stringify(this.
|
|
925
|
+
window.__ROUTING__ = ${JSON.stringify(this.clientRoutes)}
|
|
762
926
|
<\/script>
|
|
763
927
|
|
|
764
928
|
<script type='text/javascript'>
|
|
@@ -768,16 +932,22 @@ ${e.stack}</pre>
|
|
|
768
932
|
<script type='text/javascript'>
|
|
769
933
|
window.__INITIAL_DATA__ = ${JSON.stringify(server_data || {}).trim()}
|
|
770
934
|
<\/script>
|
|
935
|
+
|
|
936
|
+
<script type='text/javascript'>
|
|
937
|
+
window.__COMPONENT_DIR__ = ${JSON.stringify(clientComponentDir)}
|
|
938
|
+
<\/script>
|
|
771
939
|
`;
|
|
940
|
+
console.log("[SSR DEBUG] About to render HTML with APP length:", (body_render == null ? void 0 : body_render.length) || 0);
|
|
772
941
|
html_render = await this.htmlRender.renderHTML({
|
|
773
942
|
HEAD: head_routing + (head_render || ""),
|
|
774
943
|
CSS: css,
|
|
775
944
|
APP: body_render
|
|
776
945
|
});
|
|
946
|
+
console.log("[SSR DEBUG] Final HTML length:", (html_render == null ? void 0 : html_render.length) || 0, "contains APP div:", html_render == null ? void 0 : html_render.includes('<div id="app">'));
|
|
777
947
|
} catch (e) {
|
|
778
948
|
response_code = 500;
|
|
779
949
|
const new_body = `<pre>Error rendering HTML:
|
|
780
|
-
${e}` + (((
|
|
950
|
+
${e}` + (((_b = route.layout) == null ? void 0 : _b.length) ? `layouts: ${(_c = route.layout) == null ? void 0 : _c.join(",\n")}` : "") + `
|
|
781
951
|
view: ${route.view}</pre>`;
|
|
782
952
|
html_render = await this.htmlRender.renderHTML({
|
|
783
953
|
APP: new_body
|
|
@@ -789,6 +959,7 @@ view: ${route.view}</pre>`;
|
|
|
789
959
|
res.end(html_render);
|
|
790
960
|
}
|
|
791
961
|
async handleFallback(req, res, server_config) {
|
|
962
|
+
var _a;
|
|
792
963
|
if (res.headersSent) {
|
|
793
964
|
console.log("Reply already sent");
|
|
794
965
|
return;
|
|
@@ -829,7 +1000,10 @@ view: ${route.view}</pre>`;
|
|
|
829
1000
|
const view = await this.manager.getView(route);
|
|
830
1001
|
console.log("Fallback view", view);
|
|
831
1002
|
console.log("Fallback layouts", layouts);
|
|
832
|
-
|
|
1003
|
+
const loader = ((_a = this.manager) == null ? void 0 : _a["componentLoader"]) || {};
|
|
1004
|
+
const componentRoot = loader["base_path"] || loader["basePath"] || "";
|
|
1005
|
+
const applicationRenderer = await this.loadApplicationRenderer(componentRoot);
|
|
1006
|
+
let { head: head_render, html, css } = render(applicationRenderer, {
|
|
833
1007
|
props: {
|
|
834
1008
|
layouts,
|
|
835
1009
|
view,
|
|
@@ -837,6 +1011,7 @@ view: ${route.view}</pre>`;
|
|
|
837
1011
|
params: request_data.params
|
|
838
1012
|
}
|
|
839
1013
|
});
|
|
1014
|
+
const body_render = html;
|
|
840
1015
|
const html_render = await this.htmlRender.renderHTML({
|
|
841
1016
|
HEAD: head_render,
|
|
842
1017
|
CSS: css,
|
|
@@ -845,21 +1020,53 @@ view: ${route.view}</pre>`;
|
|
|
845
1020
|
res.type("text/html").status(404).send(html_render);
|
|
846
1021
|
}
|
|
847
1022
|
}
|
|
1023
|
+
function pathExistsSync(p) {
|
|
1024
|
+
try {
|
|
1025
|
+
return fs.existsSync(p);
|
|
1026
|
+
} catch {
|
|
1027
|
+
return false;
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
function resolveRuntimeRoot(candidate) {
|
|
1031
|
+
var _a;
|
|
1032
|
+
const envRoot = process.env.FORGE_ROOT;
|
|
1033
|
+
if (envRoot && path.isAbsolute(envRoot) && pathExistsSync(envRoot)) {
|
|
1034
|
+
return path.normalize(envRoot);
|
|
1035
|
+
}
|
|
1036
|
+
if (candidate && path.isAbsolute(candidate) && pathExistsSync(candidate)) {
|
|
1037
|
+
return path.normalize(candidate);
|
|
1038
|
+
}
|
|
1039
|
+
const entry = (_a = process.argv) == null ? void 0 : _a[1];
|
|
1040
|
+
if (entry) {
|
|
1041
|
+
const entryDir = path.dirname(path.resolve(entry));
|
|
1042
|
+
if (pathExistsSync(entryDir)) return entryDir;
|
|
1043
|
+
}
|
|
1044
|
+
return process.cwd();
|
|
1045
|
+
}
|
|
848
1046
|
async function createServer(app, options) {
|
|
1047
|
+
var _a;
|
|
849
1048
|
options = options || defaultOptions;
|
|
850
1049
|
const full_options = deepmerge(defaultOptions, options);
|
|
851
1050
|
full_options.open_api_path = ensureFullPath(full_options.viteOptions.root, full_options.open_api_path);
|
|
852
|
-
const
|
|
853
|
-
|
|
854
|
-
const
|
|
855
|
-
const
|
|
1051
|
+
const root = resolveRuntimeRoot((_a = full_options.viteOptions) == null ? void 0 : _a.root);
|
|
1052
|
+
const COMPONENT_DIR = !full_options.component_dir ? root : path.join(root, full_options.component_dir);
|
|
1053
|
+
const isBuiltEnvironment = process.env.FORGE_BUILT === "true";
|
|
1054
|
+
const isProd = isBuiltEnvironment || full_options.development === false;
|
|
1055
|
+
console.log(`Running in ${isProd ? "production" : "development"} mode (built environment: ${isBuiltEnvironment}, development flag: ${full_options.development}, NODE_ENV: ${process.env.NODE_ENV})`);
|
|
856
1056
|
let componentLoader;
|
|
857
1057
|
let vite;
|
|
858
1058
|
console.log(`Serving components from ${COMPONENT_DIR}`);
|
|
1059
|
+
const rendererFullPath = typeof full_options.renderer === "string" && full_options.renderer !== "default" ? ensureFullPath(root, full_options.renderer) : ensureFullPath(root, "index.html");
|
|
1060
|
+
path.dirname(rendererFullPath);
|
|
1061
|
+
const resolveAssetRoot = (entry) => {
|
|
1062
|
+
if (!entry || typeof entry !== "string") return root;
|
|
1063
|
+
const cleaned = entry.replace(/^\/+/, "");
|
|
1064
|
+
return path.resolve(root, cleaned);
|
|
1065
|
+
};
|
|
859
1066
|
if (full_options.assets) {
|
|
860
1067
|
for (const [asset_path, asset_dir] of Object.entries(full_options.assets)) {
|
|
861
1068
|
for (const asset of asset_dir) {
|
|
862
|
-
const asset_root =
|
|
1069
|
+
const asset_root = resolveAssetRoot(asset);
|
|
863
1070
|
app.use(asset_path, express.static(asset_root));
|
|
864
1071
|
console.log(`Serving assets from ${asset_root} at ${asset_path}`);
|
|
865
1072
|
}
|
|
@@ -876,8 +1083,16 @@ ${JSON.stringify(options, null, 2)}`);
|
|
|
876
1083
|
componentLoader = new ViteComponentLoader(COMPONENT_DIR, vite);
|
|
877
1084
|
} else {
|
|
878
1085
|
console.log("Starting Vite in production mode...");
|
|
879
|
-
|
|
880
|
-
|
|
1086
|
+
const staticDir = path.join(full_options.viteOptions.root, full_options.build_dir);
|
|
1087
|
+
if (pathExistsSync(staticDir)) {
|
|
1088
|
+
app.use("/", express.static(staticDir));
|
|
1089
|
+
console.log(`Serving static files from ${staticDir} at /`);
|
|
1090
|
+
} else {
|
|
1091
|
+
console.log(`Skipping static file serving (build_dir ${staticDir} not found - using asset configuration)`);
|
|
1092
|
+
}
|
|
1093
|
+
const componentPath = `/${full_options.component_dir}`;
|
|
1094
|
+
app.use(componentPath, express.static(COMPONENT_DIR));
|
|
1095
|
+
console.log(`Serving components at ${componentPath} from ${COMPONENT_DIR}`);
|
|
881
1096
|
componentLoader = new ProdComponentLoader(COMPONENT_DIR);
|
|
882
1097
|
}
|
|
883
1098
|
const manifest = await new ManifestBuilder(
|
|
@@ -902,7 +1117,8 @@ ${JSON.stringify(options, null, 2)}`);
|
|
|
902
1117
|
api_adapter,
|
|
903
1118
|
middleware_adapter,
|
|
904
1119
|
full_options.context_builder,
|
|
905
|
-
isProd
|
|
1120
|
+
isProd,
|
|
1121
|
+
full_options.component_dir
|
|
906
1122
|
);
|
|
907
1123
|
await adapter.handleRoutes(routeDefs, manifest);
|
|
908
1124
|
console.log("Routes registered");
|