@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.cjs
CHANGED
|
@@ -26,36 +26,27 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
26
26
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
27
27
|
const express = require("express");
|
|
28
28
|
const path = require("path");
|
|
29
|
-
const deepmerge = require("deepmerge");
|
|
30
29
|
const fs = require("fs");
|
|
30
|
+
const deepmerge = require("deepmerge");
|
|
31
|
+
const url = require("url");
|
|
31
32
|
const Handlebars = require("handlebars");
|
|
32
33
|
const fs$1 = require("fs/promises");
|
|
33
34
|
const yaml = require("js-yaml");
|
|
34
35
|
require("clone-deep");
|
|
35
36
|
const join = require("url-join");
|
|
36
37
|
const path$1 = require("./path-sxXxpB6R.cjs");
|
|
37
|
-
const url = require("url");
|
|
38
38
|
const server = require("svelte/server");
|
|
39
39
|
const pathToRegex = require("path-to-regex");
|
|
40
|
-
const ApplicationRenderer = require("../src/components/RecursiveRender.svelte");
|
|
41
40
|
class ViteComponentLoader {
|
|
42
41
|
constructor(basePath, vite) {
|
|
43
42
|
this.basePath = basePath;
|
|
44
43
|
this.vite = vite;
|
|
45
44
|
}
|
|
46
45
|
async load(componentPath, options = { use_base_path: true }) {
|
|
47
|
-
|
|
48
|
-
const use_base_path = options.use_base_path || false;
|
|
49
|
-
if (use_base_path) {
|
|
50
|
-
absoluteComponentPath = path.join(this.basePath, componentPath);
|
|
51
|
-
} else {
|
|
52
|
-
if (path.isAbsolute(componentPath)) {
|
|
53
|
-
absoluteComponentPath = componentPath;
|
|
54
|
-
} else {
|
|
55
|
-
absoluteComponentPath = componentPath;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
46
|
+
const absoluteComponentPath = this.getComponentFullPath(componentPath, options);
|
|
58
47
|
console.log(`[ViteComponentLoader] Loading component from path: ${absoluteComponentPath}`);
|
|
48
|
+
const jsPath = absoluteComponentPath.replace(/\.svelte$/, ".js");
|
|
49
|
+
fs.existsSync(jsPath);
|
|
59
50
|
let vitePath = path.relative(process.cwd(), absoluteComponentPath);
|
|
60
51
|
vitePath = vitePath.replace(/\\/g, "/");
|
|
61
52
|
if (!vitePath.startsWith("/")) {
|
|
@@ -80,16 +71,74 @@ class ViteComponentLoader {
|
|
|
80
71
|
throw error;
|
|
81
72
|
}
|
|
82
73
|
}
|
|
74
|
+
getComponentFullPath(componentPath, options = { use_base_path: true }) {
|
|
75
|
+
const use_base_path = options.use_base_path || false;
|
|
76
|
+
if (use_base_path) {
|
|
77
|
+
return path.join(this.basePath, componentPath);
|
|
78
|
+
}
|
|
79
|
+
if (path.isAbsolute(componentPath)) {
|
|
80
|
+
return componentPath;
|
|
81
|
+
}
|
|
82
|
+
return componentPath;
|
|
83
|
+
}
|
|
83
84
|
}
|
|
84
85
|
class ProdComponentLoader {
|
|
85
86
|
constructor(base_path) {
|
|
87
|
+
__publicField(this, "componentMapPromise", null);
|
|
86
88
|
this.base_path = base_path;
|
|
87
89
|
}
|
|
88
90
|
async load(componentPath) {
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
+
const normalized = this.normalizeKey(componentPath);
|
|
92
|
+
try {
|
|
93
|
+
const map = await this.loadComponentMap();
|
|
94
|
+
const module22 = map[normalized];
|
|
95
|
+
if (module22) {
|
|
96
|
+
return module22;
|
|
97
|
+
}
|
|
98
|
+
} catch (error) {
|
|
99
|
+
console.warn(`[Forge] Failed to load component "${componentPath}" from entry manifest:`, error);
|
|
100
|
+
}
|
|
101
|
+
const component_path = this.getComponentFullPath(componentPath);
|
|
102
|
+
const fallbackPath = component_path.endsWith(".js") ? component_path : component_path.replace(/\.svelte$/, ".js");
|
|
103
|
+
const module2 = await import(url.pathToFileURL(fallbackPath).href);
|
|
91
104
|
return module2;
|
|
92
105
|
}
|
|
106
|
+
getComponentFullPath(componentPath) {
|
|
107
|
+
return path.join(this.base_path, componentPath);
|
|
108
|
+
}
|
|
109
|
+
normalizeKey(componentPath) {
|
|
110
|
+
const trimmed = componentPath.replace(/^\.\//, "");
|
|
111
|
+
if (trimmed.endsWith(".svelte")) {
|
|
112
|
+
return trimmed.replace(/\.svelte$/, ".js");
|
|
113
|
+
}
|
|
114
|
+
return trimmed;
|
|
115
|
+
}
|
|
116
|
+
async loadComponentMap() {
|
|
117
|
+
if (!this.componentMapPromise) {
|
|
118
|
+
const entryPath = path.join(this.base_path, "entry-ssr.js");
|
|
119
|
+
const entryUrl = url.pathToFileURL(entryPath).href;
|
|
120
|
+
this.componentMapPromise = import(entryUrl).then((mod) => {
|
|
121
|
+
const source = mod.components ?? mod.default ?? {};
|
|
122
|
+
const normalized = {};
|
|
123
|
+
for (const [key, value] of Object.entries(source)) {
|
|
124
|
+
const cleanKey = key.replace(/^\.\//, "");
|
|
125
|
+
normalized[cleanKey] = value;
|
|
126
|
+
if (cleanKey.startsWith("ui/")) {
|
|
127
|
+
normalized[cleanKey.slice(3)] = value;
|
|
128
|
+
}
|
|
129
|
+
if (cleanKey.endsWith(".svelte")) {
|
|
130
|
+
const jsKey = cleanKey.replace(/\.svelte$/, ".js");
|
|
131
|
+
normalized[jsKey] = value;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return normalized;
|
|
135
|
+
}).catch((error) => {
|
|
136
|
+
this.componentMapPromise = null;
|
|
137
|
+
throw error;
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
return this.componentMapPromise;
|
|
141
|
+
}
|
|
93
142
|
}
|
|
94
143
|
const default_template = `
|
|
95
144
|
<!DOCTYPE html>
|
|
@@ -280,11 +329,9 @@ async function parse_openapi_config(openapi_config_path) {
|
|
|
280
329
|
const defaultViteOptions = {
|
|
281
330
|
appType: "custom",
|
|
282
331
|
root: process.cwd(),
|
|
283
|
-
// Explicitly set root
|
|
284
332
|
server: { middlewareMode: true },
|
|
285
333
|
ssr: {
|
|
286
334
|
noExternal: ["svelte", /^svelte\/.*/]
|
|
287
|
-
// Adjust if needed, maybe add your component specifically if still failing
|
|
288
335
|
}
|
|
289
336
|
};
|
|
290
337
|
const defaultOptions = {
|
|
@@ -372,7 +419,7 @@ class ApiAdapter {
|
|
|
372
419
|
layout: layout_data,
|
|
373
420
|
view: view_data
|
|
374
421
|
};
|
|
375
|
-
return server_data;
|
|
422
|
+
return this.mergeLoaderData(route, request_data, server_data);
|
|
376
423
|
}
|
|
377
424
|
async getFallbackData(route, request_data) {
|
|
378
425
|
const view = await this.manager.getViewComponent(route);
|
|
@@ -397,7 +444,48 @@ class ApiAdapter {
|
|
|
397
444
|
layout: layout_data,
|
|
398
445
|
view: view_data
|
|
399
446
|
};
|
|
400
|
-
return server_data;
|
|
447
|
+
return this.mergeLoaderData(route, request_data, server_data);
|
|
448
|
+
}
|
|
449
|
+
async mergeLoaderData(route, request_data, server_data) {
|
|
450
|
+
if (!await this.manager.hasLoaders(route)) {
|
|
451
|
+
return server_data;
|
|
452
|
+
}
|
|
453
|
+
const loaders = await this.manager.getLoaders(route);
|
|
454
|
+
const layoutLoaderResults = await Promise.all(
|
|
455
|
+
loaders.layouts.map(async (loader) => {
|
|
456
|
+
if (!loader) {
|
|
457
|
+
return null;
|
|
458
|
+
}
|
|
459
|
+
const data = await loader(request_data);
|
|
460
|
+
return data ?? null;
|
|
461
|
+
})
|
|
462
|
+
);
|
|
463
|
+
const baseLayoutData = server_data.layout || [];
|
|
464
|
+
const maxLayouts = Math.max(baseLayoutData.length, layoutLoaderResults.length);
|
|
465
|
+
const mergedLayouts = Array.from({ length: maxLayouts }, (_, index) => {
|
|
466
|
+
const baseLayoutEntry = baseLayoutData[index];
|
|
467
|
+
const loaderResult = layoutLoaderResults[index];
|
|
468
|
+
if (!loaderResult) {
|
|
469
|
+
return baseLayoutEntry;
|
|
470
|
+
}
|
|
471
|
+
if (baseLayoutEntry && typeof baseLayoutEntry === "object") {
|
|
472
|
+
return { ...baseLayoutEntry, ...loaderResult };
|
|
473
|
+
}
|
|
474
|
+
return loaderResult;
|
|
475
|
+
});
|
|
476
|
+
const viewLoaderResult = loaders.view ? await loaders.view(request_data) : null;
|
|
477
|
+
let mergedView = server_data.view;
|
|
478
|
+
if (viewLoaderResult) {
|
|
479
|
+
if (mergedView && typeof mergedView === "object") {
|
|
480
|
+
mergedView = { ...mergedView, ...viewLoaderResult };
|
|
481
|
+
} else {
|
|
482
|
+
mergedView = viewLoaderResult;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
return {
|
|
486
|
+
layout: mergedLayouts,
|
|
487
|
+
view: mergedView
|
|
488
|
+
};
|
|
401
489
|
}
|
|
402
490
|
}
|
|
403
491
|
class ComponentManager {
|
|
@@ -430,6 +518,50 @@ class ComponentManager {
|
|
|
430
518
|
async getViewComponent(route) {
|
|
431
519
|
return await this.componentLoader.load(route.view);
|
|
432
520
|
}
|
|
521
|
+
async hasLoaders(route) {
|
|
522
|
+
const componentPaths = [...route.layout || [], route.view];
|
|
523
|
+
for (const componentPath of componentPaths) {
|
|
524
|
+
const loader = await this.resolveLoader(componentPath);
|
|
525
|
+
if (loader) {
|
|
526
|
+
return true;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return false;
|
|
530
|
+
}
|
|
531
|
+
async getLoaders(route) {
|
|
532
|
+
const layoutPaths = route.layout || [];
|
|
533
|
+
const layouts = await Promise.all(layoutPaths.map((layoutPath) => this.resolveLoader(layoutPath)));
|
|
534
|
+
const view = await this.resolveLoader(route.view);
|
|
535
|
+
return {
|
|
536
|
+
layouts,
|
|
537
|
+
view
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
getLoaderFilePath(componentPath) {
|
|
541
|
+
if (!componentPath) {
|
|
542
|
+
return null;
|
|
543
|
+
}
|
|
544
|
+
const fullPath = this.componentLoader.getComponentFullPath(componentPath);
|
|
545
|
+
const { dir, name } = path.parse(fullPath);
|
|
546
|
+
return path.join(dir, `${name}.load.ts`);
|
|
547
|
+
}
|
|
548
|
+
async resolveLoader(componentPath) {
|
|
549
|
+
const loaderFilePath = this.getLoaderFilePath(componentPath);
|
|
550
|
+
if (!loaderFilePath) {
|
|
551
|
+
return null;
|
|
552
|
+
}
|
|
553
|
+
try {
|
|
554
|
+
const module2 = await import(url.pathToFileURL(loaderFilePath).href);
|
|
555
|
+
const loader = module2 == null ? void 0 : module2.default;
|
|
556
|
+
return typeof loader === "function" ? loader : null;
|
|
557
|
+
} catch (error) {
|
|
558
|
+
if ((error == null ? void 0 : error.code) === "MODULE_NOT_FOUND" || (error == null ? void 0 : error.code) === "ERR_MODULE_NOT_FOUND") {
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
561
|
+
console.error(`[ComponentManager] Failed to load loader for ${componentPath}:`, error);
|
|
562
|
+
return null;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
433
565
|
async getView(route) {
|
|
434
566
|
const view = await this.componentLoader.load(route.view);
|
|
435
567
|
return view.default;
|
|
@@ -634,8 +766,9 @@ function initialize_route_matchers(routes) {
|
|
|
634
766
|
class ServerAdapter {
|
|
635
767
|
}
|
|
636
768
|
class ExpressServerAdapter extends ServerAdapter {
|
|
637
|
-
constructor(server2, manager, htmlRender, api_adapter, middleware_adapter, context_builder, isProd = false) {
|
|
769
|
+
constructor(server2, manager, htmlRender, api_adapter, middleware_adapter, context_builder, isProd = false, componentDir) {
|
|
638
770
|
super();
|
|
771
|
+
__publicField(this, "clientRoutes", []);
|
|
639
772
|
this.server = server2;
|
|
640
773
|
this.manager = manager;
|
|
641
774
|
this.htmlRender = htmlRender;
|
|
@@ -643,6 +776,27 @@ class ExpressServerAdapter extends ServerAdapter {
|
|
|
643
776
|
this.middleware_adapter = middleware_adapter;
|
|
644
777
|
this.context_builder = context_builder;
|
|
645
778
|
this.isProd = isProd;
|
|
779
|
+
this.componentDir = componentDir;
|
|
780
|
+
}
|
|
781
|
+
async loadApplicationRenderer(componentRoot) {
|
|
782
|
+
if (!this.isProd) {
|
|
783
|
+
const mod = await import("../src/components/RecursiveRender.svelte");
|
|
784
|
+
return mod.default ?? mod;
|
|
785
|
+
}
|
|
786
|
+
const candidates = [
|
|
787
|
+
path.join(componentRoot, "RecursiveRender.js"),
|
|
788
|
+
path.join(componentRoot, "ssr", "RecursiveRender.js")
|
|
789
|
+
];
|
|
790
|
+
let lastError;
|
|
791
|
+
for (const fp of candidates) {
|
|
792
|
+
try {
|
|
793
|
+
const mod = await import(fp);
|
|
794
|
+
return mod.default ?? mod;
|
|
795
|
+
} catch (e) {
|
|
796
|
+
lastError = e;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
throw lastError ?? new Error("Unable to locate precompiled RecursiveRender.js");
|
|
646
800
|
}
|
|
647
801
|
transformRoutesForClient(routes) {
|
|
648
802
|
var _a, _b;
|
|
@@ -660,7 +814,9 @@ class ExpressServerAdapter extends ServerAdapter {
|
|
|
660
814
|
return transformed;
|
|
661
815
|
}
|
|
662
816
|
async handleRoutes(routes, manifest) {
|
|
663
|
-
const
|
|
817
|
+
const transformedRoutes = this.transformRoutesForClient(routes);
|
|
818
|
+
this.clientRoutes = transformedRoutes;
|
|
819
|
+
const matchers = initialize_route_matchers(transformedRoutes);
|
|
664
820
|
this.server.use((req, res, next) => {
|
|
665
821
|
(async () => {
|
|
666
822
|
if (res.headersSent) {
|
|
@@ -677,13 +833,13 @@ class ExpressServerAdapter extends ServerAdapter {
|
|
|
677
833
|
await not_found();
|
|
678
834
|
return;
|
|
679
835
|
}
|
|
680
|
-
const route_options =
|
|
836
|
+
const route_options = transformedRoutes.filter((r) => r.path === matcher.pattern);
|
|
681
837
|
const route = route_options.find((r) => r.method.toLowerCase() === method);
|
|
682
838
|
if (!route) {
|
|
683
839
|
await not_found();
|
|
684
840
|
return;
|
|
685
841
|
}
|
|
686
|
-
await this.handleResponse(fullUrl, matcher, route,
|
|
842
|
+
await this.handleResponse(fullUrl, matcher, route, transformedRoutes, manifest, req, res).catch((e) => {
|
|
687
843
|
res.status(500).send(`
|
|
688
844
|
<h1>500 Internal Server Error</h1>
|
|
689
845
|
<pre>${e}</pre>
|
|
@@ -694,7 +850,7 @@ class ExpressServerAdapter extends ServerAdapter {
|
|
|
694
850
|
});
|
|
695
851
|
}
|
|
696
852
|
async handleResponse(url2, matcher, route, routes, manifest, req, res) {
|
|
697
|
-
var _a, _b;
|
|
853
|
+
var _a, _b, _c;
|
|
698
854
|
let accepts = req.headers.accept || "";
|
|
699
855
|
let server_api_call = accepts.toLowerCase().includes("application/json");
|
|
700
856
|
if (res.headersSent) {
|
|
@@ -768,7 +924,12 @@ ${e.stack}</pre>
|
|
|
768
924
|
params: request_data.params || {},
|
|
769
925
|
query: request_data.query
|
|
770
926
|
};
|
|
771
|
-
|
|
927
|
+
console.log("[SSR DEBUG] layouts:", layouts.map((l) => typeof l), "view:", typeof view);
|
|
928
|
+
const loader = ((_a = this.manager) == null ? void 0 : _a["componentLoader"]) || {};
|
|
929
|
+
const componentRoot = loader["base_path"] || loader["basePath"] || "";
|
|
930
|
+
const applicationRenderer = await this.loadApplicationRenderer(componentRoot);
|
|
931
|
+
console.log("[SSR DEBUG] applicationRenderer:", typeof applicationRenderer);
|
|
932
|
+
const { head: head_render, html: renderedHtml, css } = server.render(applicationRenderer, {
|
|
772
933
|
props: {
|
|
773
934
|
layouts,
|
|
774
935
|
view,
|
|
@@ -779,9 +940,12 @@ ${e.stack}</pre>
|
|
|
779
940
|
page
|
|
780
941
|
}
|
|
781
942
|
});
|
|
943
|
+
const body_render = renderedHtml;
|
|
944
|
+
console.log("[SSR DEBUG] render result - body length:", (body_render == null ? void 0 : body_render.length) || 0);
|
|
945
|
+
const clientComponentDir = this.isProd ? "assets" : this.componentDir;
|
|
782
946
|
const head_routing = `
|
|
783
947
|
<script type='text/javascript'>
|
|
784
|
-
window.__ROUTING__ = ${JSON.stringify(this.
|
|
948
|
+
window.__ROUTING__ = ${JSON.stringify(this.clientRoutes)}
|
|
785
949
|
<\/script>
|
|
786
950
|
|
|
787
951
|
<script type='text/javascript'>
|
|
@@ -791,16 +955,22 @@ ${e.stack}</pre>
|
|
|
791
955
|
<script type='text/javascript'>
|
|
792
956
|
window.__INITIAL_DATA__ = ${JSON.stringify(server_data || {}).trim()}
|
|
793
957
|
<\/script>
|
|
958
|
+
|
|
959
|
+
<script type='text/javascript'>
|
|
960
|
+
window.__COMPONENT_DIR__ = ${JSON.stringify(clientComponentDir)}
|
|
961
|
+
<\/script>
|
|
794
962
|
`;
|
|
963
|
+
console.log("[SSR DEBUG] About to render HTML with APP length:", (body_render == null ? void 0 : body_render.length) || 0);
|
|
795
964
|
html_render = await this.htmlRender.renderHTML({
|
|
796
965
|
HEAD: head_routing + (head_render || ""),
|
|
797
966
|
CSS: css,
|
|
798
967
|
APP: body_render
|
|
799
968
|
});
|
|
969
|
+
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">'));
|
|
800
970
|
} catch (e) {
|
|
801
971
|
response_code = 500;
|
|
802
972
|
const new_body = `<pre>Error rendering HTML:
|
|
803
|
-
${e}` + (((
|
|
973
|
+
${e}` + (((_b = route.layout) == null ? void 0 : _b.length) ? `layouts: ${(_c = route.layout) == null ? void 0 : _c.join(",\n")}` : "") + `
|
|
804
974
|
view: ${route.view}</pre>`;
|
|
805
975
|
html_render = await this.htmlRender.renderHTML({
|
|
806
976
|
APP: new_body
|
|
@@ -812,6 +982,7 @@ view: ${route.view}</pre>`;
|
|
|
812
982
|
res.end(html_render);
|
|
813
983
|
}
|
|
814
984
|
async handleFallback(req, res, server_config) {
|
|
985
|
+
var _a;
|
|
815
986
|
if (res.headersSent) {
|
|
816
987
|
console.log("Reply already sent");
|
|
817
988
|
return;
|
|
@@ -852,7 +1023,10 @@ view: ${route.view}</pre>`;
|
|
|
852
1023
|
const view = await this.manager.getView(route);
|
|
853
1024
|
console.log("Fallback view", view);
|
|
854
1025
|
console.log("Fallback layouts", layouts);
|
|
855
|
-
|
|
1026
|
+
const loader = ((_a = this.manager) == null ? void 0 : _a["componentLoader"]) || {};
|
|
1027
|
+
const componentRoot = loader["base_path"] || loader["basePath"] || "";
|
|
1028
|
+
const applicationRenderer = await this.loadApplicationRenderer(componentRoot);
|
|
1029
|
+
let { head: head_render, html, css } = server.render(applicationRenderer, {
|
|
856
1030
|
props: {
|
|
857
1031
|
layouts,
|
|
858
1032
|
view,
|
|
@@ -860,6 +1034,7 @@ view: ${route.view}</pre>`;
|
|
|
860
1034
|
params: request_data.params
|
|
861
1035
|
}
|
|
862
1036
|
});
|
|
1037
|
+
const body_render = html;
|
|
863
1038
|
const html_render = await this.htmlRender.renderHTML({
|
|
864
1039
|
HEAD: head_render,
|
|
865
1040
|
CSS: css,
|
|
@@ -868,21 +1043,53 @@ view: ${route.view}</pre>`;
|
|
|
868
1043
|
res.type("text/html").status(404).send(html_render);
|
|
869
1044
|
}
|
|
870
1045
|
}
|
|
1046
|
+
function pathExistsSync(p) {
|
|
1047
|
+
try {
|
|
1048
|
+
return fs.existsSync(p);
|
|
1049
|
+
} catch {
|
|
1050
|
+
return false;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
function resolveRuntimeRoot(candidate) {
|
|
1054
|
+
var _a;
|
|
1055
|
+
const envRoot = process.env.FORGE_ROOT;
|
|
1056
|
+
if (envRoot && path.isAbsolute(envRoot) && pathExistsSync(envRoot)) {
|
|
1057
|
+
return path.normalize(envRoot);
|
|
1058
|
+
}
|
|
1059
|
+
if (candidate && path.isAbsolute(candidate) && pathExistsSync(candidate)) {
|
|
1060
|
+
return path.normalize(candidate);
|
|
1061
|
+
}
|
|
1062
|
+
const entry = (_a = process.argv) == null ? void 0 : _a[1];
|
|
1063
|
+
if (entry) {
|
|
1064
|
+
const entryDir = path.dirname(path.resolve(entry));
|
|
1065
|
+
if (pathExistsSync(entryDir)) return entryDir;
|
|
1066
|
+
}
|
|
1067
|
+
return process.cwd();
|
|
1068
|
+
}
|
|
871
1069
|
async function createServer(app, options) {
|
|
1070
|
+
var _a;
|
|
872
1071
|
options = options || defaultOptions;
|
|
873
1072
|
const full_options = deepmerge(defaultOptions, options);
|
|
874
1073
|
full_options.open_api_path = ensureFullPath(full_options.viteOptions.root, full_options.open_api_path);
|
|
875
|
-
const
|
|
876
|
-
|
|
877
|
-
const
|
|
878
|
-
const
|
|
1074
|
+
const root = resolveRuntimeRoot((_a = full_options.viteOptions) == null ? void 0 : _a.root);
|
|
1075
|
+
const COMPONENT_DIR = !full_options.component_dir ? root : path.join(root, full_options.component_dir);
|
|
1076
|
+
const isBuiltEnvironment = process.env.FORGE_BUILT === "true";
|
|
1077
|
+
const isProd = isBuiltEnvironment || full_options.development === false;
|
|
1078
|
+
console.log(`Running in ${isProd ? "production" : "development"} mode (built environment: ${isBuiltEnvironment}, development flag: ${full_options.development}, NODE_ENV: ${process.env.NODE_ENV})`);
|
|
879
1079
|
let componentLoader;
|
|
880
1080
|
let vite;
|
|
881
1081
|
console.log(`Serving components from ${COMPONENT_DIR}`);
|
|
1082
|
+
const rendererFullPath = typeof full_options.renderer === "string" && full_options.renderer !== "default" ? ensureFullPath(root, full_options.renderer) : ensureFullPath(root, "index.html");
|
|
1083
|
+
path.dirname(rendererFullPath);
|
|
1084
|
+
const resolveAssetRoot = (entry) => {
|
|
1085
|
+
if (!entry || typeof entry !== "string") return root;
|
|
1086
|
+
const cleaned = entry.replace(/^\/+/, "");
|
|
1087
|
+
return path.resolve(root, cleaned);
|
|
1088
|
+
};
|
|
882
1089
|
if (full_options.assets) {
|
|
883
1090
|
for (const [asset_path, asset_dir] of Object.entries(full_options.assets)) {
|
|
884
1091
|
for (const asset of asset_dir) {
|
|
885
|
-
const asset_root =
|
|
1092
|
+
const asset_root = resolveAssetRoot(asset);
|
|
886
1093
|
app.use(asset_path, express.static(asset_root));
|
|
887
1094
|
console.log(`Serving assets from ${asset_root} at ${asset_path}`);
|
|
888
1095
|
}
|
|
@@ -899,8 +1106,16 @@ ${JSON.stringify(options, null, 2)}`);
|
|
|
899
1106
|
componentLoader = new ViteComponentLoader(COMPONENT_DIR, vite);
|
|
900
1107
|
} else {
|
|
901
1108
|
console.log("Starting Vite in production mode...");
|
|
902
|
-
|
|
903
|
-
|
|
1109
|
+
const staticDir = path.join(full_options.viteOptions.root, full_options.build_dir);
|
|
1110
|
+
if (pathExistsSync(staticDir)) {
|
|
1111
|
+
app.use("/", express.static(staticDir));
|
|
1112
|
+
console.log(`Serving static files from ${staticDir} at /`);
|
|
1113
|
+
} else {
|
|
1114
|
+
console.log(`Skipping static file serving (build_dir ${staticDir} not found - using asset configuration)`);
|
|
1115
|
+
}
|
|
1116
|
+
const componentPath = `/${full_options.component_dir}`;
|
|
1117
|
+
app.use(componentPath, express.static(COMPONENT_DIR));
|
|
1118
|
+
console.log(`Serving components at ${componentPath} from ${COMPONENT_DIR}`);
|
|
904
1119
|
componentLoader = new ProdComponentLoader(COMPONENT_DIR);
|
|
905
1120
|
}
|
|
906
1121
|
const manifest = await new ManifestBuilder(
|
|
@@ -925,7 +1140,8 @@ ${JSON.stringify(options, null, 2)}`);
|
|
|
925
1140
|
api_adapter,
|
|
926
1141
|
middleware_adapter,
|
|
927
1142
|
full_options.context_builder,
|
|
928
|
-
isProd
|
|
1143
|
+
isProd,
|
|
1144
|
+
full_options.component_dir
|
|
929
1145
|
);
|
|
930
1146
|
await adapter.handleRoutes(routeDefs, manifest);
|
|
931
1147
|
console.log("Routes registered");
|