@taujs/server 0.5.4 → 0.5.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/dist/index.js +77 -103
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -304,7 +304,7 @@ var SSRTAG = {
|
|
|
304
304
|
ssrHtml: "<!--ssr-html-->"
|
|
305
305
|
};
|
|
306
306
|
var TEMPLATE = {
|
|
307
|
-
defaultEntryClient: "entry-client",
|
|
307
|
+
defaultEntryClient: "entry-client.tsx",
|
|
308
308
|
defaultEntryServer: "entry-server",
|
|
309
309
|
defaultHtmlTemplate: "index.html"
|
|
310
310
|
};
|
|
@@ -1352,6 +1352,14 @@ function processTemplate(template) {
|
|
|
1352
1352
|
var rebuildTemplate = (parts, headContent, bodyContent) => {
|
|
1353
1353
|
return `${parts.beforeHead}${headContent}${parts.afterHead}${parts.beforeBody}${bodyContent}${parts.afterBody}`;
|
|
1354
1354
|
};
|
|
1355
|
+
var addNonceToInlineScripts = (html, nonce) => {
|
|
1356
|
+
if (!nonce) return html;
|
|
1357
|
+
return html.replace(/<script(?![^>]*\bnonce=)([^>]*)>/g, `<script nonce="${nonce}"$1>`);
|
|
1358
|
+
};
|
|
1359
|
+
function extractHeadInner(html) {
|
|
1360
|
+
const m = html.match(/<head[^>]*>([\s\S]*?)<\/head>/i);
|
|
1361
|
+
return (m?.[1] ?? "").trim();
|
|
1362
|
+
}
|
|
1355
1363
|
|
|
1356
1364
|
// src/utils/AssetManager.ts
|
|
1357
1365
|
var createMaps = () => ({
|
|
@@ -1833,6 +1841,57 @@ function createRequestContext(req, reply, baseLogger) {
|
|
|
1833
1841
|
return { traceId, logger, headers };
|
|
1834
1842
|
}
|
|
1835
1843
|
|
|
1844
|
+
// src/utils/HandleNotFound.ts
|
|
1845
|
+
var handleNotFound = async (req, reply, processedConfigs, maps, opts = {}) => {
|
|
1846
|
+
const { viteDevServer } = opts;
|
|
1847
|
+
const logger = opts.logger ?? createLogger({
|
|
1848
|
+
debug: opts.debug,
|
|
1849
|
+
context: { component: "handle-not-found", url: req.url, method: req.method, traceId: req.id }
|
|
1850
|
+
});
|
|
1851
|
+
try {
|
|
1852
|
+
if (/\.\w+$/.test(req.raw.url ?? "")) {
|
|
1853
|
+
logger.debug?.("ssr", { url: req.raw.url }, "Delegating asset-like request to Fastify notFound handler");
|
|
1854
|
+
return reply.callNotFound();
|
|
1855
|
+
}
|
|
1856
|
+
const defaultConfig = processedConfigs[0];
|
|
1857
|
+
if (!defaultConfig) {
|
|
1858
|
+
logger.error?.({ configCount: processedConfigs.length, url: req.raw.url }, "No default configuration found");
|
|
1859
|
+
throw AppError.internal("No default configuration found", {
|
|
1860
|
+
details: { configCount: processedConfigs.length, url: req.raw.url }
|
|
1861
|
+
});
|
|
1862
|
+
}
|
|
1863
|
+
const { clientRoot } = defaultConfig;
|
|
1864
|
+
const cspNonce = req.cspNonce ?? void 0;
|
|
1865
|
+
const template = ensureNonNull(maps.templates.get(clientRoot), `Template not found for clientRoot: ${clientRoot}`);
|
|
1866
|
+
const cssLink = maps.cssLinks.get(clientRoot);
|
|
1867
|
+
const bootstrapModule = maps.bootstrapModules.get(clientRoot);
|
|
1868
|
+
let processedTemplate = template.replace(SSRTAG.ssrHead, "").replace(SSRTAG.ssrHtml, "");
|
|
1869
|
+
if (isDevelopment && viteDevServer) {
|
|
1870
|
+
processedTemplate = processedTemplate.replace(/<script type="module" src="\/@vite\/client"><\/script>/g, "");
|
|
1871
|
+
processedTemplate = processedTemplate.replace(/<style type="text\/css">[\s\S]*?<\/style>/g, "");
|
|
1872
|
+
const url = req.url ? new URL(req.url, `http://${req.headers.host}`).pathname : "/";
|
|
1873
|
+
processedTemplate = await viteDevServer.transformIndexHtml(url, processedTemplate);
|
|
1874
|
+
if (cspNonce) processedTemplate = processedTemplate.replace(/<script(?![^>]*\bnonce=)([^>]*)>/g, `<script nonce="${cspNonce}"$1>`);
|
|
1875
|
+
} else if (!isDevelopment && cssLink) {
|
|
1876
|
+
processedTemplate = processedTemplate.replace("</head>", `${cssLink}</head>`);
|
|
1877
|
+
}
|
|
1878
|
+
if (bootstrapModule) {
|
|
1879
|
+
const nonceAttr = cspNonce ? ` nonce="${cspNonce}"` : "";
|
|
1880
|
+
processedTemplate = processedTemplate.replace("</body>", `<script${nonceAttr} type="module" src="${bootstrapModule}" defer></script></body>`);
|
|
1881
|
+
}
|
|
1882
|
+
logger.debug?.("ssr", { status: 200 }, "Sending not-found fallback HTML");
|
|
1883
|
+
const result = reply.status(200).type("text/html").send(processedTemplate);
|
|
1884
|
+
return result;
|
|
1885
|
+
} catch (err) {
|
|
1886
|
+
logger.error?.({ error: err, url: req.url, clientRoot: processedConfigs[0]?.clientRoot }, "handleNotFound failed");
|
|
1887
|
+
throw AppError.internal("handleNotFound failed", err, {
|
|
1888
|
+
stage: "handleNotFound",
|
|
1889
|
+
url: req.url,
|
|
1890
|
+
clientRoot: processedConfigs[0]?.clientRoot
|
|
1891
|
+
});
|
|
1892
|
+
}
|
|
1893
|
+
};
|
|
1894
|
+
|
|
1836
1895
|
// src/utils/HandleRender.ts
|
|
1837
1896
|
var handleRender = async (req, reply, routeMatchers, processedConfigs, serviceRegistry, maps, opts = {}) => {
|
|
1838
1897
|
const { viteDevServer } = opts;
|
|
@@ -1849,8 +1908,7 @@ var handleRender = async (req, reply, routeMatchers, processedConfigs, serviceRe
|
|
|
1849
1908
|
const rawNonce = req.cspNonce;
|
|
1850
1909
|
const cspNonce = rawNonce && rawNonce.length > 0 ? rawNonce : void 0;
|
|
1851
1910
|
if (!matchedRoute) {
|
|
1852
|
-
reply.callNotFound();
|
|
1853
|
-
return;
|
|
1911
|
+
return reply.callNotFound();
|
|
1854
1912
|
}
|
|
1855
1913
|
const { route, params } = matchedRoute;
|
|
1856
1914
|
const { attr, appId } = route;
|
|
@@ -1877,6 +1935,7 @@ var handleRender = async (req, reply, routeMatchers, processedConfigs, serviceRe
|
|
|
1877
1935
|
const manifest = maps.manifests.get(clientRoot);
|
|
1878
1936
|
const preloadLink = maps.preloadLinks.get(clientRoot);
|
|
1879
1937
|
const ssrManifest = maps.ssrManifests.get(clientRoot);
|
|
1938
|
+
let devHead = "";
|
|
1880
1939
|
let renderModule;
|
|
1881
1940
|
if (isDevelopment && viteDevServer) {
|
|
1882
1941
|
try {
|
|
@@ -1889,7 +1948,16 @@ var handleRender = async (req, reply, routeMatchers, processedConfigs, serviceRe
|
|
|
1889
1948
|
const styles = await collectStyle(viteDevServer, [entryServerPath]);
|
|
1890
1949
|
const styleNonce = cspNonce ? ` nonce="${cspNonce}"` : "";
|
|
1891
1950
|
template = template?.replace("</head>", `<style type="text/css"${styleNonce}>${styles}</style></head>`);
|
|
1892
|
-
|
|
1951
|
+
const isStreaming = attr?.render === RENDERTYPE.streaming;
|
|
1952
|
+
if (isStreaming) {
|
|
1953
|
+
const stub = "<!doctype html><html><head></head><body></body></html>";
|
|
1954
|
+
const transformed = await viteDevServer.transformIndexHtml(url, stub);
|
|
1955
|
+
devHead = extractHeadInner(transformed);
|
|
1956
|
+
if (cspNonce) devHead = devHead.replace(/<script(?![^>]*\bnonce=)([^>]*)>/g, `<script nonce="${cspNonce}"$1>`);
|
|
1957
|
+
} else {
|
|
1958
|
+
template = await viteDevServer.transformIndexHtml(url, template);
|
|
1959
|
+
if (cspNonce) template = addNonceToInlineScripts(template, cspNonce);
|
|
1960
|
+
}
|
|
1893
1961
|
} catch (error) {
|
|
1894
1962
|
throw AppError.internal("Failed to load dev assets", { cause: error, details: { clientRoot, entryServer, url } });
|
|
1895
1963
|
}
|
|
@@ -2031,7 +2099,9 @@ var handleRender = async (req, reply, routeMatchers, processedConfigs, serviceRe
|
|
|
2031
2099
|
writable,
|
|
2032
2100
|
{
|
|
2033
2101
|
onHead: (headContent) => {
|
|
2034
|
-
let aggregateHeadContent =
|
|
2102
|
+
let aggregateHeadContent = "";
|
|
2103
|
+
if (devHead) aggregateHeadContent += devHead;
|
|
2104
|
+
aggregateHeadContent += headContent;
|
|
2035
2105
|
if (ssrManifest && preloadLink) aggregateHeadContent += preloadLink;
|
|
2036
2106
|
if (manifest && cssLink) aggregateHeadContent += cssLink;
|
|
2037
2107
|
reply.raw.write(`${templateParts.beforeHead}${aggregateHeadContent}${templateParts.afterHead}${templateParts.beforeBody}`);
|
|
@@ -2106,86 +2176,6 @@ var handleRender = async (req, reply, routeMatchers, processedConfigs, serviceRe
|
|
|
2106
2176
|
}
|
|
2107
2177
|
};
|
|
2108
2178
|
|
|
2109
|
-
// src/utils/HandleNotFound.ts
|
|
2110
|
-
var handleNotFound = async (req, reply, processedConfigs, maps, opts = {}) => {
|
|
2111
|
-
const logger = opts.logger ?? createLogger({
|
|
2112
|
-
debug: opts.debug,
|
|
2113
|
-
context: { component: "handle-not-found", url: req.url, method: req.method, traceId: req.id }
|
|
2114
|
-
});
|
|
2115
|
-
try {
|
|
2116
|
-
if (/\.\w+$/.test(req.raw.url ?? "")) {
|
|
2117
|
-
logger.debug?.("ssr", { url: req.raw.url }, "Delegating asset-like request to Fastify notFound handler");
|
|
2118
|
-
return reply.callNotFound();
|
|
2119
|
-
}
|
|
2120
|
-
const defaultConfig = processedConfigs[0];
|
|
2121
|
-
if (!defaultConfig) {
|
|
2122
|
-
logger.error?.({ configCount: processedConfigs.length, url: req.raw.url }, "No default configuration found");
|
|
2123
|
-
throw AppError.internal("No default configuration found", {
|
|
2124
|
-
details: { configCount: processedConfigs.length, url: req.raw.url }
|
|
2125
|
-
});
|
|
2126
|
-
}
|
|
2127
|
-
const { clientRoot } = defaultConfig;
|
|
2128
|
-
const cspNonce = req.cspNonce ?? void 0;
|
|
2129
|
-
const template = ensureNonNull(maps.templates.get(clientRoot), `Template not found for clientRoot: ${clientRoot}`);
|
|
2130
|
-
const cssLink = maps.cssLinks.get(clientRoot);
|
|
2131
|
-
const bootstrapModule = maps.bootstrapModules.get(clientRoot);
|
|
2132
|
-
logger.debug?.(
|
|
2133
|
-
"ssr",
|
|
2134
|
-
{
|
|
2135
|
-
clientRoot,
|
|
2136
|
-
hasCssLink: !!cssLink,
|
|
2137
|
-
hasBootstrapModule: !!bootstrapModule,
|
|
2138
|
-
isDevelopment,
|
|
2139
|
-
hasCspNonce: !!cspNonce
|
|
2140
|
-
},
|
|
2141
|
-
"Preparing not-found fallback HTML"
|
|
2142
|
-
);
|
|
2143
|
-
let processedTemplate = template.replace(SSRTAG.ssrHead, "").replace(SSRTAG.ssrHtml, "");
|
|
2144
|
-
if (!isDevelopment && cssLink) {
|
|
2145
|
-
processedTemplate = processedTemplate.replace("</head>", `${cssLink}</head>`);
|
|
2146
|
-
}
|
|
2147
|
-
if (bootstrapModule) {
|
|
2148
|
-
const nonceAttr = cspNonce ? ` nonce="${cspNonce}"` : "";
|
|
2149
|
-
processedTemplate = processedTemplate.replace("</body>", `<script${nonceAttr} type="module" src="${bootstrapModule}" defer></script></body>`);
|
|
2150
|
-
}
|
|
2151
|
-
logger.debug?.("ssr", { status: 200 }, "Sending not-found fallback HTML");
|
|
2152
|
-
return reply.status(200).type("text/html").send(processedTemplate);
|
|
2153
|
-
} catch (err) {
|
|
2154
|
-
logger.error?.({ error: err, url: req.url, clientRoot: processedConfigs[0]?.clientRoot }, "handleNotFound failed");
|
|
2155
|
-
throw AppError.internal("handleNotFound failed", err, {
|
|
2156
|
-
stage: "handleNotFound",
|
|
2157
|
-
url: req.url,
|
|
2158
|
-
clientRoot: processedConfigs[0]?.clientRoot
|
|
2159
|
-
});
|
|
2160
|
-
}
|
|
2161
|
-
};
|
|
2162
|
-
|
|
2163
|
-
// src/core/routes/ResolveRouteData.ts
|
|
2164
|
-
async function resolveRouteDataCore(url, opts) {
|
|
2165
|
-
const match2 = matchRoute(url, opts.routeMatchers);
|
|
2166
|
-
if (!match2) {
|
|
2167
|
-
throw AppError.notFound("route_not_found", { details: { url } });
|
|
2168
|
-
}
|
|
2169
|
-
const { route, params } = match2;
|
|
2170
|
-
if (!route.attr?.data) {
|
|
2171
|
-
throw AppError.notFound("no_data_handler", {
|
|
2172
|
-
details: { url, path: route.path, appId: route.appId }
|
|
2173
|
-
});
|
|
2174
|
-
}
|
|
2175
|
-
const ctx = opts.getCtx();
|
|
2176
|
-
return fetchInitialData(route.attr, params, opts.serviceRegistry, ctx);
|
|
2177
|
-
}
|
|
2178
|
-
|
|
2179
|
-
// src/utils/ResolveRouteData.ts
|
|
2180
|
-
async function resolveRouteData(url, opts) {
|
|
2181
|
-
const { req, reply, routeMatchers, serviceRegistry, logger } = opts;
|
|
2182
|
-
return resolveRouteDataCore(url, {
|
|
2183
|
-
routeMatchers,
|
|
2184
|
-
serviceRegistry,
|
|
2185
|
-
getCtx: () => createRequestContext(req, reply, logger)
|
|
2186
|
-
});
|
|
2187
|
-
}
|
|
2188
|
-
|
|
2189
2179
|
// src/utils/StaticAssets.ts
|
|
2190
2180
|
function normaliseStaticAssets(reg) {
|
|
2191
2181
|
if (!reg) return [];
|
|
@@ -2295,23 +2285,6 @@ var SSRServer = fp3(
|
|
|
2295
2285
|
viteDevServer = await setupDevServer(app, clientRoot, alias, opts.debug, opts.devNet, plugins);
|
|
2296
2286
|
}
|
|
2297
2287
|
app.addHook("onRequest", createAuthHook(routeMatchers, logger));
|
|
2298
|
-
app.get("/__taujs/route", async (req, reply) => {
|
|
2299
|
-
const query = req.query;
|
|
2300
|
-
const url = typeof query.url === "string" ? query.url : "";
|
|
2301
|
-
if (!url) {
|
|
2302
|
-
throw AppError.badRequest("url query param required", {
|
|
2303
|
-
details: { query }
|
|
2304
|
-
});
|
|
2305
|
-
}
|
|
2306
|
-
const data = await resolveRouteData(url, {
|
|
2307
|
-
req,
|
|
2308
|
-
reply,
|
|
2309
|
-
routeMatchers,
|
|
2310
|
-
serviceRegistry,
|
|
2311
|
-
logger
|
|
2312
|
-
});
|
|
2313
|
-
return reply.status(200).send({ data });
|
|
2314
|
-
});
|
|
2315
2288
|
app.get("/*", async (req, reply) => {
|
|
2316
2289
|
await handleRender(req, reply, routeMatchers, processedConfigs, serviceRegistry, maps, {
|
|
2317
2290
|
debug: opts.debug,
|
|
@@ -2331,7 +2304,8 @@ var SSRServer = fp3(
|
|
|
2331
2304
|
},
|
|
2332
2305
|
{
|
|
2333
2306
|
debug: opts.debug,
|
|
2334
|
-
logger
|
|
2307
|
+
logger,
|
|
2308
|
+
viteDevServer
|
|
2335
2309
|
}
|
|
2336
2310
|
);
|
|
2337
2311
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taujs/server",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.6",
|
|
4
4
|
"description": "τjs [ taujs ]",
|
|
5
5
|
"author": "John Smith | Aoede <taujs@aoede.uk.net> (https://www.aoede.uk.net)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"fastify": "^5.6.1",
|
|
49
49
|
"fastify-plugin": "^5.1.0",
|
|
50
50
|
"path-to-regexp": "^8.1.0",
|
|
51
|
-
"vite": "^7.1
|
|
51
|
+
"vite": "^7.3.1"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@arethetypeswrong/cli": "^0.15.4",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"peerDependencies": {
|
|
67
67
|
"fastify": "^5.6.1",
|
|
68
68
|
"typescript": "^5.5.4",
|
|
69
|
-
"vite": "^7.1
|
|
69
|
+
"vite": "^7.3.1"
|
|
70
70
|
},
|
|
71
71
|
"scripts": {
|
|
72
72
|
"build": "tsup",
|