@noego/forge 0.0.10 → 0.0.12

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 (54) hide show
  1. package/dist/client.cjs +1 -1
  2. package/dist/client.cjs.map +1 -1
  3. package/dist/client.mjs +224 -219
  4. package/dist/client.mjs.map +1 -1
  5. package/dist/options/ServerOptions.cjs +28 -0
  6. package/dist/options/ServerOptions.cjs.map +1 -0
  7. package/dist/options/ServerOptions.d.ts +19 -0
  8. package/dist/options/ServerOptions.mjs +21 -0
  9. package/dist/options/ServerOptions.mjs.map +1 -0
  10. package/dist/options/assets.cjs +42 -0
  11. package/dist/options/assets.cjs.map +1 -0
  12. package/dist/options/assets.d.ts +46 -0
  13. package/dist/options/assets.mjs +38 -0
  14. package/dist/options/assets.mjs.map +1 -0
  15. package/dist/plugins/serverOnlyStub.d.ts +6 -0
  16. package/dist/plugins-cjs/index.plugins.js +9 -0
  17. package/dist/plugins-cjs/index.plugins.js.map +1 -0
  18. package/dist/plugins-cjs/options/ServerOptions.js +28 -0
  19. package/dist/plugins-cjs/options/ServerOptions.js.map +1 -0
  20. package/dist/plugins-cjs/options/assets.js +42 -0
  21. package/dist/plugins-cjs/options/assets.js.map +1 -0
  22. package/dist/plugins-cjs/plugins/serverOnlyStub.js +226 -0
  23. package/dist/plugins-cjs/plugins/serverOnlyStub.js.map +1 -0
  24. package/dist/plugins-cjs/routing/html_render/html_render.js +62 -0
  25. package/dist/plugins-cjs/routing/html_render/html_render.js.map +1 -0
  26. package/dist/plugins-cjs/stubs/server-only.js +10 -0
  27. package/dist/plugins-cjs/stubs/server-only.js.map +1 -0
  28. package/dist/plugins-es/index.plugins.d.ts +2 -0
  29. package/dist/plugins-es/index.plugins.js +2 -0
  30. package/dist/plugins-es/index.plugins.js.map +1 -0
  31. package/dist/plugins-es/options/ServerOptions.d.ts +19 -0
  32. package/dist/plugins-es/options/ServerOptions.js +21 -0
  33. package/dist/plugins-es/options/ServerOptions.js.map +1 -0
  34. package/dist/plugins-es/options/assets.d.ts +46 -0
  35. package/dist/plugins-es/options/assets.js +38 -0
  36. package/dist/plugins-es/options/assets.js.map +1 -0
  37. package/dist/plugins-es/plugins/serverOnlyStub.d.ts +6 -0
  38. package/dist/plugins-es/plugins/serverOnlyStub.js +200 -0
  39. package/dist/plugins-es/plugins/serverOnlyStub.js.map +1 -0
  40. package/dist/plugins-es/routing/html_render/html_render.d.ts +19 -0
  41. package/dist/plugins-es/routing/html_render/html_render.js +53 -0
  42. package/dist/plugins-es/routing/html_render/html_render.js.map +1 -0
  43. package/dist/plugins-es/stubs/server-only.d.ts +3 -0
  44. package/dist/plugins-es/stubs/server-only.js +7 -0
  45. package/dist/plugins-es/stubs/server-only.js.map +1 -0
  46. package/dist/routing/html_render/html_render.d.ts +19 -0
  47. package/dist/routing/html_render/html_render.js +53 -0
  48. package/dist/routing/html_render/html_render.js.map +1 -0
  49. package/dist-ssr/server.cjs +179 -23
  50. package/dist-ssr/server.cjs.map +1 -1
  51. package/dist-ssr/server.js +179 -23
  52. package/dist-ssr/server.js.map +1 -1
  53. package/package.json +11 -4
  54. package/src/components/RecursiveRender.svelte +55 -14
@@ -26,18 +26,17 @@ 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;
@@ -56,6 +55,19 @@ class ViteComponentLoader {
56
55
  }
57
56
  }
58
57
  console.log(`[ViteComponentLoader] Loading component from path: ${absoluteComponentPath}`);
58
+ const jsPath = absoluteComponentPath.replace(/\.svelte$/, ".js");
59
+ const jsExists = fs.existsSync(jsPath);
60
+ if (jsExists) {
61
+ console.log(`[ViteComponentLoader] Found precompiled component at: ${jsPath}`);
62
+ try {
63
+ const module2 = await import(jsPath);
64
+ console.log(`[ViteComponentLoader] Loaded precompiled module successfully`);
65
+ return module2;
66
+ } catch (error) {
67
+ console.error(`[ViteComponentLoader] Error loading precompiled module from ${jsPath}`, error);
68
+ throw error;
69
+ }
70
+ }
59
71
  let vitePath = path.relative(process.cwd(), absoluteComponentPath);
60
72
  vitePath = vitePath.replace(/\\/g, "/");
61
73
  if (!vitePath.startsWith("/")) {
@@ -83,13 +95,58 @@ class ViteComponentLoader {
83
95
  }
84
96
  class ProdComponentLoader {
85
97
  constructor(base_path) {
98
+ __publicField(this, "componentMapPromise", null);
86
99
  this.base_path = base_path;
87
100
  }
88
101
  async load(componentPath) {
102
+ const normalized = this.normalizeKey(componentPath);
103
+ try {
104
+ const map = await this.loadComponentMap();
105
+ const module22 = map[normalized];
106
+ if (module22) {
107
+ return module22;
108
+ }
109
+ } catch (error) {
110
+ console.warn(`[Forge] Failed to load component "${componentPath}" from entry manifest:`, error);
111
+ }
89
112
  const component_path = path.join(this.base_path, componentPath);
90
- const module2 = await import(component_path.replace(/\.svelte$/, ".js"));
113
+ const fallbackPath = component_path.endsWith(".js") ? component_path : component_path.replace(/\.svelte$/, ".js");
114
+ const module2 = await import(url.pathToFileURL(fallbackPath).href);
91
115
  return module2;
92
116
  }
117
+ normalizeKey(componentPath) {
118
+ const trimmed = componentPath.replace(/^\.\//, "");
119
+ if (trimmed.endsWith(".svelte")) {
120
+ return trimmed.replace(/\.svelte$/, ".js");
121
+ }
122
+ return trimmed;
123
+ }
124
+ async loadComponentMap() {
125
+ if (!this.componentMapPromise) {
126
+ const entryPath = path.join(this.base_path, "entry-ssr.js");
127
+ const entryUrl = url.pathToFileURL(entryPath).href;
128
+ this.componentMapPromise = import(entryUrl).then((mod) => {
129
+ const source = mod.components ?? mod.default ?? {};
130
+ const normalized = {};
131
+ for (const [key, value] of Object.entries(source)) {
132
+ const cleanKey = key.replace(/^\.\//, "");
133
+ normalized[cleanKey] = value;
134
+ if (cleanKey.startsWith("ui/")) {
135
+ normalized[cleanKey.slice(3)] = value;
136
+ }
137
+ if (cleanKey.endsWith(".svelte")) {
138
+ const jsKey = cleanKey.replace(/\.svelte$/, ".js");
139
+ normalized[jsKey] = value;
140
+ }
141
+ }
142
+ return normalized;
143
+ }).catch((error) => {
144
+ this.componentMapPromise = null;
145
+ throw error;
146
+ });
147
+ }
148
+ return this.componentMapPromise;
149
+ }
93
150
  }
94
151
  const default_template = `
95
152
  <!DOCTYPE html>
@@ -280,11 +337,9 @@ async function parse_openapi_config(openapi_config_path) {
280
337
  const defaultViteOptions = {
281
338
  appType: "custom",
282
339
  root: process.cwd(),
283
- // Explicitly set root
284
340
  server: { middlewareMode: true },
285
341
  ssr: {
286
342
  noExternal: ["svelte", /^svelte\/.*/]
287
- // Adjust if needed, maybe add your component specifically if still failing
288
343
  }
289
344
  };
290
345
  const defaultOptions = {
@@ -634,17 +689,57 @@ function initialize_route_matchers(routes) {
634
689
  class ServerAdapter {
635
690
  }
636
691
  class ExpressServerAdapter extends ServerAdapter {
637
- constructor(server2, manager, htmlRender, api_adapter, middleware_adapter, context_builder) {
692
+ constructor(server2, manager, htmlRender, api_adapter, middleware_adapter, context_builder, isProd = false, componentDir) {
638
693
  super();
694
+ __publicField(this, "clientRoutes", []);
639
695
  this.server = server2;
640
696
  this.manager = manager;
641
697
  this.htmlRender = htmlRender;
642
698
  this.api_adapter = api_adapter;
643
699
  this.middleware_adapter = middleware_adapter;
644
700
  this.context_builder = context_builder;
701
+ this.isProd = isProd;
702
+ this.componentDir = componentDir;
703
+ }
704
+ async loadApplicationRenderer(componentRoot) {
705
+ if (!this.isProd) {
706
+ const mod = await import("../src/components/RecursiveRender.svelte");
707
+ return mod.default ?? mod;
708
+ }
709
+ const candidates = [
710
+ path.join(componentRoot, "RecursiveRender.js"),
711
+ path.join(componentRoot, "ssr", "RecursiveRender.js")
712
+ ];
713
+ let lastError;
714
+ for (const fp of candidates) {
715
+ try {
716
+ const mod = await import(fp);
717
+ return mod.default ?? mod;
718
+ } catch (e) {
719
+ lastError = e;
720
+ }
721
+ }
722
+ throw lastError ?? new Error("Unable to locate precompiled RecursiveRender.js");
723
+ }
724
+ transformRoutesForClient(routes) {
725
+ var _a, _b;
726
+ if (!this.isProd) return routes;
727
+ console.log(`[transformRoutesForClient] Transforming ${routes.length} routes for production`);
728
+ const transformed = routes.map((route) => {
729
+ var _a2, _b2;
730
+ return {
731
+ ...route,
732
+ layout: (_a2 = route.layout) == null ? void 0 : _a2.map((path2) => path2.replace(/\.svelte$/, ".js")),
733
+ view: (_b2 = route.view) == null ? void 0 : _b2.replace(/\.svelte$/, ".js")
734
+ };
735
+ });
736
+ console.log(`[transformRoutesForClient] First route view transformed: ${(_a = routes[0]) == null ? void 0 : _a.view} → ${(_b = transformed[0]) == null ? void 0 : _b.view}`);
737
+ return transformed;
645
738
  }
646
739
  async handleRoutes(routes, manifest) {
647
- const matchers = initialize_route_matchers(routes);
740
+ const transformedRoutes = this.transformRoutesForClient(routes);
741
+ this.clientRoutes = transformedRoutes;
742
+ const matchers = initialize_route_matchers(transformedRoutes);
648
743
  this.server.use((req, res, next) => {
649
744
  (async () => {
650
745
  if (res.headersSent) {
@@ -661,13 +756,13 @@ class ExpressServerAdapter extends ServerAdapter {
661
756
  await not_found();
662
757
  return;
663
758
  }
664
- const route_options = routes.filter((r) => r.path === matcher.pattern);
759
+ const route_options = transformedRoutes.filter((r) => r.path === matcher.pattern);
665
760
  const route = route_options.find((r) => r.method.toLowerCase() === method);
666
761
  if (!route) {
667
762
  await not_found();
668
763
  return;
669
764
  }
670
- await this.handleResponse(fullUrl, matcher, route, routes, manifest, req, res).catch((e) => {
765
+ await this.handleResponse(fullUrl, matcher, route, transformedRoutes, manifest, req, res).catch((e) => {
671
766
  res.status(500).send(`
672
767
  <h1>500 Internal Server Error</h1>
673
768
  <pre>${e}</pre>
@@ -678,7 +773,7 @@ class ExpressServerAdapter extends ServerAdapter {
678
773
  });
679
774
  }
680
775
  async handleResponse(url2, matcher, route, routes, manifest, req, res) {
681
- var _a, _b;
776
+ var _a, _b, _c;
682
777
  let accepts = req.headers.accept || "";
683
778
  let server_api_call = accepts.toLowerCase().includes("application/json");
684
779
  if (res.headersSent) {
@@ -752,7 +847,12 @@ ${e.stack}</pre>
752
847
  params: request_data.params || {},
753
848
  query: request_data.query
754
849
  };
755
- let { head: head_render, body: body_render, css } = server.render(ApplicationRenderer, {
850
+ console.log("[SSR DEBUG] layouts:", layouts.map((l) => typeof l), "view:", typeof view);
851
+ const loader = ((_a = this.manager) == null ? void 0 : _a["componentLoader"]) || {};
852
+ const componentRoot = loader["base_path"] || loader["basePath"] || "";
853
+ const applicationRenderer = await this.loadApplicationRenderer(componentRoot);
854
+ console.log("[SSR DEBUG] applicationRenderer:", typeof applicationRenderer);
855
+ const { head: head_render, html: renderedHtml, css } = server.render(applicationRenderer, {
756
856
  props: {
757
857
  layouts,
758
858
  view,
@@ -763,9 +863,12 @@ ${e.stack}</pre>
763
863
  page
764
864
  }
765
865
  });
866
+ const body_render = renderedHtml;
867
+ console.log("[SSR DEBUG] render result - body length:", (body_render == null ? void 0 : body_render.length) || 0);
868
+ const clientComponentDir = this.isProd ? "assets" : this.componentDir;
766
869
  const head_routing = `
767
870
  <script type='text/javascript'>
768
- window.__ROUTING__ = ${JSON.stringify(routes)}
871
+ window.__ROUTING__ = ${JSON.stringify(this.clientRoutes)}
769
872
  <\/script>
770
873
 
771
874
  <script type='text/javascript'>
@@ -775,16 +878,22 @@ ${e.stack}</pre>
775
878
  <script type='text/javascript'>
776
879
  window.__INITIAL_DATA__ = ${JSON.stringify(server_data || {}).trim()}
777
880
  <\/script>
881
+
882
+ <script type='text/javascript'>
883
+ window.__COMPONENT_DIR__ = ${JSON.stringify(clientComponentDir)}
884
+ <\/script>
778
885
  `;
886
+ console.log("[SSR DEBUG] About to render HTML with APP length:", (body_render == null ? void 0 : body_render.length) || 0);
779
887
  html_render = await this.htmlRender.renderHTML({
780
888
  HEAD: head_routing + (head_render || ""),
781
889
  CSS: css,
782
890
  APP: body_render
783
891
  });
892
+ 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">'));
784
893
  } catch (e) {
785
894
  response_code = 500;
786
895
  const new_body = `<pre>Error rendering HTML:
787
- ${e}` + (((_a = route.layout) == null ? void 0 : _a.length) ? `layouts: ${(_b = route.layout) == null ? void 0 : _b.join(",\n")}` : "") + `
896
+ ${e}` + (((_b = route.layout) == null ? void 0 : _b.length) ? `layouts: ${(_c = route.layout) == null ? void 0 : _c.join(",\n")}` : "") + `
788
897
  view: ${route.view}</pre>`;
789
898
  html_render = await this.htmlRender.renderHTML({
790
899
  APP: new_body
@@ -796,6 +905,7 @@ view: ${route.view}</pre>`;
796
905
  res.end(html_render);
797
906
  }
798
907
  async handleFallback(req, res, server_config) {
908
+ var _a;
799
909
  if (res.headersSent) {
800
910
  console.log("Reply already sent");
801
911
  return;
@@ -836,7 +946,10 @@ view: ${route.view}</pre>`;
836
946
  const view = await this.manager.getView(route);
837
947
  console.log("Fallback view", view);
838
948
  console.log("Fallback layouts", layouts);
839
- let { head: head_render, body: body_render, css } = server.render(ApplicationRenderer, {
949
+ const loader = ((_a = this.manager) == null ? void 0 : _a["componentLoader"]) || {};
950
+ const componentRoot = loader["base_path"] || loader["basePath"] || "";
951
+ const applicationRenderer = await this.loadApplicationRenderer(componentRoot);
952
+ let { head: head_render, html, css } = server.render(applicationRenderer, {
840
953
  props: {
841
954
  layouts,
842
955
  view,
@@ -844,6 +957,7 @@ view: ${route.view}</pre>`;
844
957
  params: request_data.params
845
958
  }
846
959
  });
960
+ const body_render = html;
847
961
  const html_render = await this.htmlRender.renderHTML({
848
962
  HEAD: head_render,
849
963
  CSS: css,
@@ -852,21 +966,53 @@ view: ${route.view}</pre>`;
852
966
  res.type("text/html").status(404).send(html_render);
853
967
  }
854
968
  }
969
+ function pathExistsSync(p) {
970
+ try {
971
+ return fs.existsSync(p);
972
+ } catch {
973
+ return false;
974
+ }
975
+ }
976
+ function resolveRuntimeRoot(candidate) {
977
+ var _a;
978
+ const envRoot = process.env.FORGE_ROOT;
979
+ if (envRoot && path.isAbsolute(envRoot) && pathExistsSync(envRoot)) {
980
+ return path.normalize(envRoot);
981
+ }
982
+ if (candidate && path.isAbsolute(candidate) && pathExistsSync(candidate)) {
983
+ return path.normalize(candidate);
984
+ }
985
+ const entry = (_a = process.argv) == null ? void 0 : _a[1];
986
+ if (entry) {
987
+ const entryDir = path.dirname(path.resolve(entry));
988
+ if (pathExistsSync(entryDir)) return entryDir;
989
+ }
990
+ return process.cwd();
991
+ }
855
992
  async function createServer(app, options) {
993
+ var _a;
856
994
  options = options || defaultOptions;
857
995
  const full_options = deepmerge(defaultOptions, options);
858
996
  full_options.open_api_path = ensureFullPath(full_options.viteOptions.root, full_options.open_api_path);
859
- const isProd = full_options.development === false;
860
- console.log(`Running in ${isProd ? "production" : "development"} mode`);
861
- const COMPONENT_DIR = !full_options.component_dir ? full_options.viteOptions.root : path.join(full_options.viteOptions.root, full_options.component_dir);
862
- const root = full_options.viteOptions.root;
997
+ const root = resolveRuntimeRoot((_a = full_options.viteOptions) == null ? void 0 : _a.root);
998
+ const COMPONENT_DIR = !full_options.component_dir ? root : path.join(root, full_options.component_dir);
999
+ const isBuiltEnvironment = process.env.FORGE_BUILT === "true";
1000
+ const isProd = isBuiltEnvironment || full_options.development === false;
1001
+ console.log(`Running in ${isProd ? "production" : "development"} mode (built environment: ${isBuiltEnvironment}, development flag: ${full_options.development}, NODE_ENV: ${process.env.NODE_ENV})`);
863
1002
  let componentLoader;
864
1003
  let vite;
865
1004
  console.log(`Serving components from ${COMPONENT_DIR}`);
1005
+ const rendererFullPath = typeof full_options.renderer === "string" && full_options.renderer !== "default" ? ensureFullPath(root, full_options.renderer) : ensureFullPath(root, "index.html");
1006
+ path.dirname(rendererFullPath);
1007
+ const resolveAssetRoot = (entry) => {
1008
+ if (!entry || typeof entry !== "string") return root;
1009
+ const cleaned = entry.replace(/^\/+/, "");
1010
+ return path.resolve(root, cleaned);
1011
+ };
866
1012
  if (full_options.assets) {
867
1013
  for (const [asset_path, asset_dir] of Object.entries(full_options.assets)) {
868
1014
  for (const asset of asset_dir) {
869
- const asset_root = path.join(full_options.viteOptions.root, asset);
1015
+ const asset_root = resolveAssetRoot(asset);
870
1016
  app.use(asset_path, express.static(asset_root));
871
1017
  console.log(`Serving assets from ${asset_root} at ${asset_path}`);
872
1018
  }
@@ -883,8 +1029,16 @@ ${JSON.stringify(options, null, 2)}`);
883
1029
  componentLoader = new ViteComponentLoader(COMPONENT_DIR, vite);
884
1030
  } else {
885
1031
  console.log("Starting Vite in production mode...");
886
- app.use("/", express.static(path.join(full_options.viteOptions.root, full_options.build_dir)));
887
- console.log(`Serving static files from ${path.join(full_options.viteOptions.root, full_options.build_dir)} at /`);
1032
+ const staticDir = path.join(full_options.viteOptions.root, full_options.build_dir);
1033
+ if (pathExistsSync(staticDir)) {
1034
+ app.use("/", express.static(staticDir));
1035
+ console.log(`Serving static files from ${staticDir} at /`);
1036
+ } else {
1037
+ console.log(`Skipping static file serving (build_dir ${staticDir} not found - using asset configuration)`);
1038
+ }
1039
+ const componentPath = `/${full_options.component_dir}`;
1040
+ app.use(componentPath, express.static(COMPONENT_DIR));
1041
+ console.log(`Serving components at ${componentPath} from ${COMPONENT_DIR}`);
888
1042
  componentLoader = new ProdComponentLoader(COMPONENT_DIR);
889
1043
  }
890
1044
  const manifest = await new ManifestBuilder(
@@ -908,7 +1062,9 @@ ${JSON.stringify(options, null, 2)}`);
908
1062
  htmlRenderer,
909
1063
  api_adapter,
910
1064
  middleware_adapter,
911
- full_options.context_builder
1065
+ full_options.context_builder,
1066
+ isProd,
1067
+ full_options.component_dir
912
1068
  );
913
1069
  await adapter.handleRoutes(routeDefs, manifest);
914
1070
  console.log("Routes registered");