@taujs/server 0.1.4 → 0.1.6

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/README.md CHANGED
@@ -14,6 +14,14 @@ Supports rendering modes:
14
14
  - Server-side rendering (SSR)
15
15
  - Streaming SSR
16
16
 
17
+ Supported application structure and composition:
18
+
19
+ - Single-page Application (SPA)
20
+ - Multi-page Application (MPA)
21
+ - Build-time Micro-Frontends, server orchestration and delivery
22
+
23
+ Assemble independently built frontends at build time incorporating flexible per-route SPA-MPA hybrid with CSR, SSR, and Streaming SSR, rendering options.
24
+
17
25
  Fastify Plugin for integration with taujs [ τjs ] template https://github.com/aoede3/taujs
18
26
 
19
27
  - Production: Fastify, React
package/dist/index.d.ts CHANGED
@@ -5,8 +5,46 @@ declare const RENDERTYPE: {
5
5
  ssr: string;
6
6
  streaming: string;
7
7
  };
8
+ declare const TEMPLATE: {
9
+ defaultEntryClient: string;
10
+ defaultEntryServer: string;
11
+ defaultHtmlTemplate: string;
12
+ };
8
13
 
14
+ declare const createMaps: () => {
15
+ bootstrapModules: Map<string, string>;
16
+ cssLinks: Map<string, string>;
17
+ manifests: Map<string, Manifest>;
18
+ preloadLinks: Map<string, string>;
19
+ renderModules: Map<string, RenderModule>;
20
+ ssrManifests: Map<string, SSRManifest>;
21
+ templates: Map<string, string>;
22
+ };
23
+ declare const processConfigs: (configs: Config[], baseClientRoot: string, templateDefaults: typeof TEMPLATE) => ProcessedConfig[];
9
24
  declare const SSRServer: FastifyPluginAsync<SSRServerOptions>;
25
+ type Config = {
26
+ appId: string;
27
+ entryPoint: string;
28
+ entryClient?: string;
29
+ entryServer?: string;
30
+ htmlTemplate?: string;
31
+ };
32
+ type ProcessedConfig = {
33
+ appId: string;
34
+ clientRoot: string;
35
+ entryClient: string;
36
+ entryPoint: string;
37
+ entryServer: string;
38
+ htmlTemplate: string;
39
+ };
40
+ type SSRServerOptions = {
41
+ alias?: Record<string, string>;
42
+ clientRoot: string;
43
+ configs: Config[];
44
+ routes: Route<RouteParams>[];
45
+ serviceRegistry: ServiceRegistry;
46
+ isDebug?: boolean;
47
+ };
10
48
  type ServiceRegistry = {
11
49
  [serviceName: string]: {
12
50
  [methodName: string]: (params: Record<string, unknown>) => Promise<Record<string, unknown>>;
@@ -25,25 +63,19 @@ type FetchConfig = {
25
63
  serviceName?: string;
26
64
  serviceMethod?: string;
27
65
  };
28
- type SSRServerOptions = {
29
- alias?: Record<string, string>;
30
- clientRoot: string;
31
- clientHtmlTemplate: string;
32
- clientEntryClient: string;
33
- clientEntryServer: string;
34
- routes: Route<RouteParams>[];
35
- serviceRegistry: ServiceRegistry;
36
- isDebug?: boolean;
66
+ type SSRManifest = {
67
+ [key: string]: string[];
68
+ };
69
+ type ManifestEntry = {
70
+ file: string;
71
+ src?: string;
72
+ isDynamicEntry?: boolean;
73
+ imports?: string[];
74
+ css?: string[];
75
+ assets?: string[];
37
76
  };
38
77
  type Manifest = {
39
- [key: string]: {
40
- file: string;
41
- src?: string;
42
- isDynamicEntry?: boolean;
43
- imports?: string[];
44
- css?: string[];
45
- assets?: string[];
46
- };
78
+ [key: string]: ManifestEntry;
47
79
  };
48
80
  type RenderSSR = (initialDataResolved: Record<string, unknown>, location: string, meta?: Record<string, unknown>) => Promise<{
49
81
  headContent: string;
@@ -58,20 +90,18 @@ type RenderModule = {
58
90
  type RouteAttributes<Params = {}> = {
59
91
  fetch?: (params?: Params, options?: RequestInit & {
60
92
  params?: Record<string, unknown>;
61
- }) => Promise<{
62
- options: RequestInit & {
63
- params?: Record<string, unknown>;
64
- };
65
- serviceName?: string;
66
- serviceMethod?: string;
67
- url?: string;
68
- }>;
93
+ }) => Promise<FetchConfig>;
94
+ } & ({
95
+ render?: typeof RENDERTYPE.ssr;
69
96
  meta?: Record<string, unknown>;
70
- render?: typeof RENDERTYPE.ssr | typeof RENDERTYPE.streaming;
71
- };
97
+ } | {
98
+ render: typeof RENDERTYPE.streaming;
99
+ meta: Record<string, unknown>;
100
+ });
72
101
  type Route<Params = {}> = {
73
102
  attr?: RouteAttributes<Params>;
74
103
  path: string;
104
+ appId?: string;
75
105
  };
76
106
  interface InitialRouteParams extends Record<string, unknown> {
77
107
  serviceName?: string;
@@ -80,4 +110,4 @@ interface InitialRouteParams extends Record<string, unknown> {
80
110
  type RouteParams = InitialRouteParams & Record<string, unknown>;
81
111
  type RoutePathsAndAttributes<Params = {}> = Omit<Route<Params>, 'element'>;
82
112
 
83
- export { type FetchConfig, type InitialRouteParams, type Manifest, type RenderCallbacks, type RenderModule, type RenderSSR, type RenderStream, type Route, type RouteAttributes, type RouteParams, type RoutePathsAndAttributes, SSRServer, type SSRServerOptions, type ServiceRegistry };
113
+ export { type Config, type FetchConfig, type InitialRouteParams, type Manifest, type ManifestEntry, type ProcessedConfig, type RenderCallbacks, type RenderModule, type RenderSSR, type RenderStream, type Route, type RouteAttributes, type RouteParams, type RoutePathsAndAttributes, type SSRManifest, SSRServer, type SSRServerOptions, type ServiceRegistry, TEMPLATE, createMaps, processConfigs };
package/dist/index.js CHANGED
@@ -57,10 +57,9 @@ var require_toCamelCase = __commonJS({
57
57
  if (name[0] === "@") {
58
58
  name = name.slice(1).replace("/", "-");
59
59
  }
60
- const newName = name.replace(/-(.)/g, function(match2, g1) {
60
+ return name.replace(/-(.)/g, function(match2, g1) {
61
61
  return g1.toUpperCase();
62
62
  });
63
- return newName;
64
63
  };
65
64
  }
66
65
  });
@@ -74,7 +73,7 @@ var require_plugin = __commonJS({
74
73
  var count = 0;
75
74
  function plugin(fn, options = {}) {
76
75
  let autoName = false;
77
- if (typeof fn.default !== "undefined") {
76
+ if (fn.default !== void 0) {
78
77
  fn = fn.default;
79
78
  }
80
79
  if (typeof fn !== "function") {
@@ -118,7 +117,7 @@ var require_plugin = __commonJS({
118
117
  // src/SSRServer.ts
119
118
  var import_fastify_plugin = __toESM(require_plugin(), 1);
120
119
  import { readFile } from "node:fs/promises";
121
- import path from "node:path";
120
+ import path2 from "node:path";
122
121
  import { createViteRuntime } from "vite";
123
122
 
124
123
  // src/constants.ts
@@ -130,10 +129,16 @@ var SSRTAG = {
130
129
  ssrHead: "<!--ssr-head-->",
131
130
  ssrHtml: "<!--ssr-html-->"
132
131
  };
132
+ var TEMPLATE = {
133
+ defaultEntryClient: "entry-client",
134
+ defaultEntryServer: "entry-server",
135
+ defaultHtmlTemplate: "index.html"
136
+ };
133
137
 
134
138
  // src/utils/Utils.ts
135
- import { fileURLToPath } from "node:url";
136
139
  import { dirname, join } from "node:path";
140
+ import "node:path";
141
+ import { fileURLToPath } from "node:url";
137
142
  import { match } from "path-to-regexp";
138
143
  var isDevelopment = process.env.NODE_ENV === "development";
139
144
  var __filename = fileURLToPath(import.meta.url);
@@ -163,20 +168,20 @@ async function collectStyleUrls(server, entries) {
163
168
  await Promise.all(entries.map((url) => traverse(url)));
164
169
  return [...visited].filter((url) => url.match(CSS_LANGS_RE));
165
170
  }
166
- function renderPreloadLinks(modules, manifest) {
171
+ function renderPreloadLinks(ssrManifest, basePath = "") {
167
172
  const seen = /* @__PURE__ */ new Set();
168
173
  let links = "";
169
- modules.forEach((id) => {
170
- const files = manifest[id];
174
+ for (const moduleId in ssrManifest) {
175
+ const files = ssrManifest[moduleId];
171
176
  if (files) {
172
177
  files.forEach((file) => {
173
178
  if (!seen.has(file)) {
174
179
  seen.add(file);
175
- links += renderPreloadLink(file);
180
+ links += renderPreloadLink(basePath ? `${basePath}/${file}` : `${file}`);
176
181
  }
177
182
  });
178
183
  }
179
- });
184
+ }
180
185
  return links;
181
186
  }
182
187
  function renderPreloadLink(file) {
@@ -248,17 +253,22 @@ var matchRoute = (url, renderRoutes) => {
248
253
  }
249
254
  return null;
250
255
  };
251
- var getCssLinks = (manifest) => {
252
- const links = [];
253
- for (const value of Object.values(manifest)) {
254
- if (value.css && value.css.length > 0) {
255
- value.css.forEach((cssFile) => {
256
- links.push(`<link rel="preload stylesheet" as="style" type="text/css" href="/${cssFile}">`);
257
- });
256
+ function getCssLinks(manifest, basePath = "") {
257
+ const seen = /* @__PURE__ */ new Set();
258
+ const styles = [];
259
+ for (const key in manifest) {
260
+ const entry = manifest[key];
261
+ if (entry && entry.css) {
262
+ for (const cssFile of entry.css) {
263
+ if (!seen.has(cssFile)) {
264
+ seen.add(cssFile);
265
+ styles.push(`<link rel="preload stylesheet" as="style" type="text/css" href="${basePath}/${cssFile}">`);
266
+ }
267
+ }
258
268
  }
259
269
  }
260
- return links.join("");
261
- };
270
+ return styles.join("\n");
271
+ }
262
272
  var overrideCSSHMRConsoleError = () => {
263
273
  const originalConsoleError = console.error;
264
274
  console.error = function(message, ...optionalParams) {
@@ -266,29 +276,76 @@ var overrideCSSHMRConsoleError = () => {
266
276
  originalConsoleError.apply(console, [message, ...optionalParams]);
267
277
  };
268
278
  };
279
+ var ensureNonNull = (value, errorMessage) => {
280
+ if (value === void 0 || value === null) throw new Error(errorMessage);
281
+ return value;
282
+ };
269
283
 
270
284
  // src/SSRServer.ts
285
+ var createMaps = () => {
286
+ return {
287
+ bootstrapModules: /* @__PURE__ */ new Map(),
288
+ cssLinks: /* @__PURE__ */ new Map(),
289
+ manifests: /* @__PURE__ */ new Map(),
290
+ preloadLinks: /* @__PURE__ */ new Map(),
291
+ renderModules: /* @__PURE__ */ new Map(),
292
+ ssrManifests: /* @__PURE__ */ new Map(),
293
+ templates: /* @__PURE__ */ new Map()
294
+ };
295
+ };
296
+ var processConfigs = (configs, baseClientRoot, templateDefaults) => {
297
+ return configs.map((config) => {
298
+ const clientRoot = path2.resolve(baseClientRoot, config.entryPoint);
299
+ return {
300
+ clientRoot,
301
+ entryPoint: config.entryPoint,
302
+ entryClient: config.entryClient || templateDefaults.defaultEntryClient,
303
+ entryServer: config.entryServer || templateDefaults.defaultEntryServer,
304
+ htmlTemplate: config.htmlTemplate || templateDefaults.defaultHtmlTemplate,
305
+ appId: config.appId
306
+ };
307
+ });
308
+ };
271
309
  var SSRServer = (0, import_fastify_plugin.default)(
272
310
  async (app, opts) => {
273
- const { alias, clientRoot, clientHtmlTemplate, clientEntryClient, clientEntryServer, routes, serviceRegistry, isDebug } = opts;
274
- const templateHtmlPath = path.join(clientRoot, clientHtmlTemplate);
275
- const templateHtml = !isDevelopment ? await readFile(templateHtmlPath, "utf-8") : await readFile(path.join(clientRoot, clientHtmlTemplate), "utf-8");
276
- const ssrManifestPath = path.join(clientRoot, ".vite/ssr-manifest.json");
277
- const ssrManifest = !isDevelopment ? JSON.parse(await readFile(ssrManifestPath, "utf-8")) : void 0;
278
- const manifestPath = path.join(clientRoot, ".vite/manifest.json");
279
- const manifest = !isDevelopment ? JSON.parse(await readFile(manifestPath, "utf-8")) : void 0;
280
- const bootstrapModules = isDevelopment ? `/${clientEntryClient}.tsx` : `/${manifest[`${clientEntryClient}.tsx`]?.file}`;
281
- const preloadLinks = !isDevelopment ? renderPreloadLinks(Object.keys(ssrManifest), ssrManifest) : void 0;
282
- const cssLinks = !isDevelopment ? getCssLinks(manifest) : void 0;
283
- let renderModule;
284
- let styles;
285
- let template = templateHtml;
311
+ const { alias, configs, routes, serviceRegistry, isDebug, clientRoot: baseClientRoot } = opts;
312
+ const { bootstrapModules, cssLinks, manifests, preloadLinks, renderModules, ssrManifests, templates } = createMaps();
313
+ const processedConfigs = processConfigs(configs, baseClientRoot, TEMPLATE);
314
+ for (const config of processedConfigs) {
315
+ const { clientRoot, entryClient, htmlTemplate } = config;
316
+ const templateHtmlPath = path2.join(clientRoot, htmlTemplate);
317
+ const templateHtml = await readFile(templateHtmlPath, "utf-8");
318
+ templates.set(clientRoot, templateHtml);
319
+ const relativeBasePath = path2.relative(baseClientRoot, clientRoot).replace(/\\/g, "/");
320
+ const adjustedRelativePath = relativeBasePath ? `/${relativeBasePath}` : "";
321
+ if (!isDevelopment) {
322
+ const manifestPath = path2.join(clientRoot, ".vite/manifest.json");
323
+ const manifestContent = await readFile(manifestPath, "utf-8");
324
+ const manifest = JSON.parse(manifestContent);
325
+ manifests.set(clientRoot, manifest);
326
+ const ssrManifestPath = path2.join(clientRoot, ".vite/ssr-manifest.json");
327
+ const ssrManifestContent = await readFile(ssrManifestPath, "utf-8");
328
+ const ssrManifest = JSON.parse(ssrManifestContent);
329
+ ssrManifests.set(clientRoot, ssrManifest);
330
+ const entryClientFile = manifest[`${entryClient}.tsx`]?.file;
331
+ if (!entryClientFile) throw new Error(`Entry client file not found in manifest for ${entryClient}.tsx`);
332
+ const bootstrapModule = `/${adjustedRelativePath}/${entryClientFile}`.replace(/\/{2,}/g, "/");
333
+ bootstrapModules.set(clientRoot, bootstrapModule);
334
+ const preloadLink = renderPreloadLinks(ssrManifest, adjustedRelativePath);
335
+ preloadLinks.set(clientRoot, preloadLink);
336
+ const cssLink = getCssLinks(manifest, adjustedRelativePath);
337
+ cssLinks.set(clientRoot, cssLink);
338
+ } else {
339
+ const bootstrapModule = `/${adjustedRelativePath}/${entryClient}`.replace(/\/{2,}/g, "/");
340
+ bootstrapModules.set(clientRoot, bootstrapModule);
341
+ }
342
+ }
286
343
  let viteDevServer;
287
344
  let viteRuntime;
288
- void await app.register(import("@fastify/static"), {
345
+ await app.register(import("@fastify/static"), {
289
346
  index: false,
290
347
  prefix: "/",
291
- root: clientRoot,
348
+ root: baseClientRoot,
292
349
  wildcard: false
293
350
  });
294
351
  if (isDevelopment) {
@@ -306,31 +363,27 @@ var SSRServer = (0, import_fastify_plugin.default)(
306
363
  plugins: [
307
364
  ...isDebug ? [
308
365
  {
366
+ name: "taujs-development-server-debug-logging",
309
367
  configureServer(server) {
310
- console.log("\u03C4js debug ssr server started.");
368
+ console.log("\u03C4js development server debug started.");
311
369
  server.middlewares.use((req, res, next) => {
312
370
  console.log(`rx: ${req.url}`);
313
- res.on("finish", () => {
314
- console.log(`tx: ${req.url}`);
315
- });
371
+ res.on("finish", () => console.log(`tx: ${req.url}`));
316
372
  next();
317
373
  });
318
- },
319
- name: "taujs-ssr-server-debug-logging"
374
+ }
320
375
  }
321
376
  ] : []
322
377
  ],
323
378
  resolve: {
324
379
  alias: {
325
- ...{
326
- "@client": path.resolve(clientRoot),
327
- "@server": path.resolve(__dirname),
328
- "@shared": path.resolve(__dirname, "../shared")
329
- },
380
+ "@client": path2.resolve(baseClientRoot),
381
+ "@server": path2.resolve(__dirname),
382
+ "@shared": path2.resolve(__dirname, "../shared"),
330
383
  ...alias
331
384
  }
332
385
  },
333
- root: clientRoot,
386
+ root: baseClientRoot,
334
387
  server: {
335
388
  middlewareMode: true,
336
389
  hmr: {
@@ -340,17 +393,15 @@ var SSRServer = (0, import_fastify_plugin.default)(
340
393
  });
341
394
  viteRuntime = await createViteRuntime(viteDevServer);
342
395
  overrideCSSHMRConsoleError();
343
- void app.addHook("onRequest", async (request, reply) => {
396
+ app.addHook("onRequest", async (request, reply) => {
344
397
  await new Promise((resolve) => {
345
398
  viteDevServer.middlewares(request.raw, reply.raw, () => {
346
399
  if (!reply.sent) resolve();
347
400
  });
348
401
  });
349
402
  });
350
- } else {
351
- renderModule = await import(path.join(clientRoot, `${clientEntryServer}.js`));
352
403
  }
353
- void app.get("/*", async (req, reply) => {
404
+ app.get("/*", async (req, reply) => {
354
405
  try {
355
406
  if (/\.\w+$/.test(req.raw.url ?? "")) return reply.callNotFound();
356
407
  const url = req.url ? new URL(req.url, `http://${req.headers.host}`).pathname : "/";
@@ -359,19 +410,39 @@ var SSRServer = (0, import_fastify_plugin.default)(
359
410
  reply.callNotFound();
360
411
  return;
361
412
  }
413
+ const { route, params } = matchedRoute;
414
+ const { attr, appId } = route;
415
+ const config = processedConfigs.find((config2) => config2.appId === appId) || processedConfigs[0];
416
+ if (!config) throw new Error("No configuration found for the request.");
417
+ const { clientRoot, entryServer } = config;
418
+ let template = ensureNonNull(templates.get(clientRoot), `Template not found for clientRoot: ${clientRoot}`);
419
+ const bootstrapModule = bootstrapModules.get(clientRoot);
420
+ const cssLink = cssLinks.get(clientRoot);
421
+ const manifest = manifests.get(clientRoot);
422
+ const preloadLink = preloadLinks.get(clientRoot);
423
+ const ssrManifest = ssrManifests.get(clientRoot);
424
+ let renderModule;
362
425
  if (isDevelopment) {
363
426
  template = template.replace(/<script type="module" src="\/@vite\/client"><\/script>/g, "");
364
427
  template = template.replace(/<style type="text\/css">[\s\S]*?<\/style>/g, "");
365
- renderModule = await viteRuntime.executeEntrypoint(path.join(clientRoot, `${clientEntryServer}.tsx`));
366
- styles = await collectStyle(viteDevServer, [`${clientRoot}/${clientEntryServer}.tsx`]);
367
- template = template.replace("</head>", `<style type="text/css">${styles}</style></head>`);
428
+ const entryServerPath = path2.join(clientRoot, `${entryServer}.tsx`);
429
+ const executedModule = await viteRuntime.executeEntrypoint(entryServerPath);
430
+ renderModule = executedModule;
431
+ const styles = await collectStyle(viteDevServer, [entryServerPath]);
432
+ template = template?.replace("</head>", `<style type="text/css">${styles}</style></head>`);
368
433
  template = await viteDevServer.transformIndexHtml(url, template);
434
+ } else {
435
+ renderModule = renderModules.get(clientRoot);
436
+ if (!renderModule) {
437
+ const renderModulePath = path2.join(clientRoot, `${entryServer}.js`);
438
+ const importedModule = await import(renderModulePath);
439
+ renderModule = importedModule;
440
+ renderModules.set(clientRoot, renderModule);
441
+ }
369
442
  }
370
- const { route, params } = matchedRoute;
371
- const { attr } = route;
372
- const renderType = attr?.render || RENDERTYPE.streaming;
373
- const [beforeBody = "", afterBody] = template.split(SSRTAG.ssrHtml);
374
- const [beforeHead, afterHead] = beforeBody.split(SSRTAG.ssrHead);
443
+ const renderType = attr?.render || RENDERTYPE.ssr;
444
+ const [beforeBody = "", afterBody = ""] = template.split(SSRTAG.ssrHtml);
445
+ const [beforeHead = "", afterHead = ""] = beforeBody.split(SSRTAG.ssrHead);
375
446
  const initialDataPromise = fetchInitialData(attr, params, serviceRegistry);
376
447
  if (renderType === RENDERTYPE.ssr) {
377
448
  const { renderSSR } = renderModule;
@@ -379,9 +450,9 @@ var SSRServer = (0, import_fastify_plugin.default)(
379
450
  const initialDataScript = `<script>window.__INITIAL_DATA__ = ${JSON.stringify(initialDataResolved).replace(/</g, "\\u003c")}</script>`;
380
451
  const { headContent, appHtml } = await renderSSR(initialDataResolved, req.url, attr?.meta);
381
452
  let aggregateHeadContent = headContent;
382
- if (ssrManifest) aggregateHeadContent += preloadLinks;
383
- if (manifest) aggregateHeadContent += cssLinks;
384
- const fullHtml = template.replace(SSRTAG.ssrHead, aggregateHeadContent).replace(SSRTAG.ssrHtml, `${appHtml}${initialDataScript}<script type="module" src="${bootstrapModules}" async=""></script>`);
453
+ if (ssrManifest && preloadLink) aggregateHeadContent += preloadLink;
454
+ if (manifest && cssLink) aggregateHeadContent += cssLink;
455
+ const fullHtml = template.replace(SSRTAG.ssrHead, aggregateHeadContent).replace(SSRTAG.ssrHtml, `${appHtml}${initialDataScript}<script type="module" src="${bootstrapModule}" async=""></script>`);
385
456
  return reply.status(200).header("Content-Type", "text/html").send(fullHtml);
386
457
  } else {
387
458
  const { renderStream } = renderModule;
@@ -391,8 +462,8 @@ var SSRServer = (0, import_fastify_plugin.default)(
391
462
  {
392
463
  onHead: (headContent) => {
393
464
  let aggregateHeadContent = headContent;
394
- if (ssrManifest) aggregateHeadContent += preloadLinks;
395
- if (manifest) aggregateHeadContent += cssLinks;
465
+ if (ssrManifest && preloadLink) aggregateHeadContent += preloadLink;
466
+ if (manifest && cssLink) aggregateHeadContent += cssLink;
396
467
  reply.raw.write(`${beforeHead}${aggregateHeadContent}${afterHead}`);
397
468
  },
398
469
  onFinish: async (initialDataResolved) => {
@@ -407,7 +478,7 @@ var SSRServer = (0, import_fastify_plugin.default)(
407
478
  },
408
479
  initialDataPromise,
409
480
  req.url,
410
- bootstrapModules,
481
+ bootstrapModule,
411
482
  attr?.meta
412
483
  );
413
484
  }
@@ -417,14 +488,19 @@ var SSRServer = (0, import_fastify_plugin.default)(
417
488
  reply.raw.end("Internal Server Error");
418
489
  }
419
490
  });
420
- void app.setNotFoundHandler(async (req, reply) => {
491
+ app.setNotFoundHandler(async (req, reply) => {
421
492
  if (/\.\w+$/.test(req.raw.url ?? "")) return reply.callNotFound();
422
493
  try {
423
- let template2 = templateHtml;
424
- template2 = template2.replace(SSRTAG.ssrHead, "").replace(SSRTAG.ssrHtml, "");
425
- if (!isDevelopment) template2 = template2.replace("</head>", `${getCssLinks(manifest)}</head>`);
426
- template2 = template2.replace("</body>", `<script type="module" src="${bootstrapModules}" async=""></script></body>`);
427
- reply.status(200).type("text/html").send(template2);
494
+ const defaultConfig = processedConfigs[0];
495
+ if (!defaultConfig) throw new Error("No default configuration found.");
496
+ const { clientRoot } = defaultConfig;
497
+ let template = ensureNonNull(templates.get(clientRoot), `Template not found for clientRoot: ${clientRoot}`);
498
+ const cssLink = cssLinks.get(clientRoot);
499
+ const bootstrapModule = bootstrapModules.get(clientRoot);
500
+ template = template.replace(SSRTAG.ssrHead, "").replace(SSRTAG.ssrHtml, "");
501
+ if (!isDevelopment && cssLink) template = template.replace("</head>", `${cssLink}</head>`);
502
+ if (bootstrapModule) template = template.replace("</body>", `<script type="module" src="${bootstrapModule}" async=""></script></body>`);
503
+ reply.status(200).type("text/html").send(template);
428
504
  } catch (error) {
429
505
  console.error("Failed to serve clientHtmlTemplate:", error);
430
506
  reply.status(500).send("Internal Server Error");
@@ -434,5 +510,8 @@ var SSRServer = (0, import_fastify_plugin.default)(
434
510
  { name: "taujs-ssr-server" }
435
511
  );
436
512
  export {
437
- SSRServer
513
+ SSRServer,
514
+ TEMPLATE,
515
+ createMaps,
516
+ processConfigs
438
517
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taujs/server",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "taujs | τjs",
5
5
  "author": "Aoede <taujs@aoede.uk.net> (https://www.aoede.uk.net)",
6
6
  "license": "MIT",
@@ -39,7 +39,7 @@
39
39
  "dist"
40
40
  ],
41
41
  "dependencies": {
42
- "@fastify/static": "^7.0.4",
42
+ "@fastify/static": "^8.0.3",
43
43
  "path-to-regexp": "^8.1.0"
44
44
  },
45
45
  "devDependencies": {
@@ -52,7 +52,7 @@
52
52
  "@types/react": "^18.3.3",
53
53
  "@types/react-dom": "^18.3.0",
54
54
  "@vitest/coverage-v8": "^2.1.0",
55
- "fastify": "^4.28.1",
55
+ "fastify": "^5.2.0",
56
56
  "jsdom": "^25.0.0",
57
57
  "prettier": "^3.3.3",
58
58
  "react-dom": "^18.3.1",
@@ -62,7 +62,7 @@
62
62
  "vitest": "^2.0.5"
63
63
  },
64
64
  "peerDependencies": {
65
- "fastify": "^4.28.1",
65
+ "fastify": "^5.2.0",
66
66
  "react": "^18.3.1",
67
67
  "react-dom": "^18.3.1",
68
68
  "typescript": "^5.5.4",