@tyndall/runtime 0.0.1 → 0.0.3
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 +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +558 -10
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -10,6 +10,9 @@ Runtime HTTP serving package for static routes, SSR execution, and route payload
|
|
|
10
10
|
- Stream SSR responses when server entries provide `renderToStream`
|
|
11
11
|
- Resolve client/server chunk files using manifest asset metadata (`assets.assetsDir`)
|
|
12
12
|
- Emit module or classic script tags based on manifest `assets.scriptType`
|
|
13
|
+
- Run `init.server` and `getRouteData` hooks to populate route data payloads for SSR and navigation
|
|
14
|
+
- Serve special routes (`_404`, `_error`) and custom document shells from `_document` when provided
|
|
15
|
+
- Emit redirect navigation payloads when route data hooks request redirects
|
|
13
16
|
- Emit build version markers and append `?v=` to script URLs when manifest versioning is configured
|
|
14
17
|
|
|
15
18
|
## Public API Highlights
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAcL,KAAK,sBAAsB,EAE3B,KAAK,QAAQ,EASb,KAAK,sBAAsB,EAG3B,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EAGvB,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACxC,eAAe,CAAC,EAAE,iBAAiB,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACxC,OAAO,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;CACzB;AAED,MAAM,WAAW,oBAAqB,SAAQ,qBAAqB;IACjE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AA20BD,eAAO,MAAM,YAAY,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,QAAQ,CAyBpE,CAAC;AA43BF,eAAO,MAAM,YAAY,GACvB,UAAS,oBAAyB,KACjC,OAAO,CAAC,aAAa,CAkCvB,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,UAAS,qBAA0B,MAGpE,SAAS;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAA;CAAE,EACnG,UAAU;IACR,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,KAAK,IAAI,CAAC;IAC1C,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,KAAK,IAAI,CAAC;IAC7C,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK,IAAI,CAAC;IACrE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK,IAAI,CAAC;IACvE,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK,IAAI,CAAC;IACjF,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B,EACD,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,SAYnC,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,UAAS,qBAA0B,MAEvD,SAAS;IAAE,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAA;CAAE,kBAa9G,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createRequire } from "node:module";
|
|
|
3
3
|
import { readFile, stat } from "node:fs/promises";
|
|
4
4
|
import { extname, join, resolve } from "node:path";
|
|
5
5
|
import { pathToFileURL } from "node:url";
|
|
6
|
-
import { handleDynamicPageApiRequest, HyperError, resolveRouteWithPolicyFallback, resolveUIAdapter, runGetServerProps, serializeProps, validateManifest, } from "@tyndall/core";
|
|
6
|
+
import { handleDynamicPageApiRequest, HyperError, resolveRouteWithPolicyFallback, resolveUIAdapter, runGetRouteData, runGetServerProps, runInitServer, ROUTE_DATA_ERROR_KEY, ROUTE_DATA_INIT_KEY, ROUTE_DATA_SCRIPT_ID, SPECIAL_ROUTE_IDS, serializeProps, validateManifest, } from "@tyndall/core";
|
|
7
7
|
const CONTENT_TYPES = {
|
|
8
8
|
".html": "text/html; charset=utf-8",
|
|
9
9
|
".js": "text/javascript; charset=utf-8",
|
|
@@ -119,6 +119,165 @@ const resolveRuntimePropsSerializer = (options) => {
|
|
|
119
119
|
const adapter = resolveUIAdapter(options.uiAdapter, options.uiOptions ?? {}, options.adapterRegistry ?? {});
|
|
120
120
|
return adapter.serializeProps ?? serializeProps;
|
|
121
121
|
};
|
|
122
|
+
const normalizeRedirect = (redirect) => {
|
|
123
|
+
if (!redirect) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
if (typeof redirect === "string") {
|
|
127
|
+
return { destination: redirect, status: 302 };
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
destination: redirect.destination,
|
|
131
|
+
status: redirect.status ?? 302,
|
|
132
|
+
replace: redirect.replace,
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
const normalizeError = (error) => {
|
|
136
|
+
if (!error) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
if (typeof error === "string") {
|
|
140
|
+
return { message: error };
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
status: error.status,
|
|
144
|
+
message: error.message,
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
const resolveRouteDataEntries = (serverModule, routeId) => {
|
|
148
|
+
if (serverModule && typeof serverModule === "object") {
|
|
149
|
+
const record = serverModule;
|
|
150
|
+
const entries = record.routeDataEntries;
|
|
151
|
+
if (Array.isArray(entries)) {
|
|
152
|
+
return entries
|
|
153
|
+
.map((entry) => {
|
|
154
|
+
if (!entry || typeof entry !== "object") {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
const item = entry;
|
|
158
|
+
if (typeof item.key !== "string" || typeof item.routeId !== "string") {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
key: item.key,
|
|
163
|
+
routeId: item.routeId,
|
|
164
|
+
hook: typeof item.hook === "function"
|
|
165
|
+
? item.hook
|
|
166
|
+
: undefined,
|
|
167
|
+
};
|
|
168
|
+
})
|
|
169
|
+
.filter((entry) => Boolean(entry));
|
|
170
|
+
}
|
|
171
|
+
if (typeof record.getRouteData === "function") {
|
|
172
|
+
return [
|
|
173
|
+
{
|
|
174
|
+
key: `page:${routeId}`,
|
|
175
|
+
routeId,
|
|
176
|
+
hook: record.getRouteData,
|
|
177
|
+
},
|
|
178
|
+
];
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return [];
|
|
182
|
+
};
|
|
183
|
+
const collectRouteDataFromServerModule = async (input) => {
|
|
184
|
+
const dataMap = {};
|
|
185
|
+
const headers = {};
|
|
186
|
+
let status;
|
|
187
|
+
let initData;
|
|
188
|
+
let parentData;
|
|
189
|
+
const initServer = input.serverModule && typeof input.serverModule.initServer === "function"
|
|
190
|
+
? (input.serverModule.initServer)
|
|
191
|
+
: undefined;
|
|
192
|
+
if (initServer) {
|
|
193
|
+
const initResult = await runInitServer(initServer, {
|
|
194
|
+
routeId: input.routeId,
|
|
195
|
+
params: input.params,
|
|
196
|
+
request: input.request,
|
|
197
|
+
response: input.response,
|
|
198
|
+
});
|
|
199
|
+
if (initResult.data !== undefined) {
|
|
200
|
+
initData = initResult.data;
|
|
201
|
+
dataMap[ROUTE_DATA_INIT_KEY] = initResult.data;
|
|
202
|
+
}
|
|
203
|
+
if (initResult.headers) {
|
|
204
|
+
Object.assign(headers, initResult.headers);
|
|
205
|
+
}
|
|
206
|
+
if (initResult.status !== undefined) {
|
|
207
|
+
status = initResult.status;
|
|
208
|
+
}
|
|
209
|
+
if (initResult.redirect) {
|
|
210
|
+
return {
|
|
211
|
+
data: dataMap,
|
|
212
|
+
initData,
|
|
213
|
+
headers,
|
|
214
|
+
status,
|
|
215
|
+
redirect: normalizeRedirect(initResult.redirect) ?? undefined,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
if (initResult.error) {
|
|
219
|
+
const normalizedError = normalizeError(initResult.error);
|
|
220
|
+
if (normalizedError) {
|
|
221
|
+
dataMap[ROUTE_DATA_ERROR_KEY] = normalizedError;
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
data: dataMap,
|
|
225
|
+
initData,
|
|
226
|
+
headers,
|
|
227
|
+
status,
|
|
228
|
+
error: normalizedError ?? undefined,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
const entries = resolveRouteDataEntries(input.serverModule, input.routeId);
|
|
233
|
+
for (const entry of entries) {
|
|
234
|
+
if (typeof entry.hook !== "function") {
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
const result = await runGetRouteData(entry.hook, {
|
|
238
|
+
routeId: entry.routeId,
|
|
239
|
+
params: input.params,
|
|
240
|
+
request: input.request,
|
|
241
|
+
response: input.response,
|
|
242
|
+
init: initData,
|
|
243
|
+
routeData: dataMap,
|
|
244
|
+
parentData,
|
|
245
|
+
});
|
|
246
|
+
if (result.data !== undefined) {
|
|
247
|
+
dataMap[entry.key] = result.data;
|
|
248
|
+
parentData = result.data;
|
|
249
|
+
}
|
|
250
|
+
if (result.headers) {
|
|
251
|
+
Object.assign(headers, result.headers);
|
|
252
|
+
}
|
|
253
|
+
if (result.status !== undefined) {
|
|
254
|
+
status = result.status;
|
|
255
|
+
}
|
|
256
|
+
if (result.redirect) {
|
|
257
|
+
return {
|
|
258
|
+
data: dataMap,
|
|
259
|
+
initData,
|
|
260
|
+
headers,
|
|
261
|
+
status,
|
|
262
|
+
redirect: normalizeRedirect(result.redirect) ?? undefined,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
if (result.error) {
|
|
266
|
+
const normalizedError = normalizeError(result.error);
|
|
267
|
+
if (normalizedError) {
|
|
268
|
+
dataMap[ROUTE_DATA_ERROR_KEY] = normalizedError;
|
|
269
|
+
}
|
|
270
|
+
return {
|
|
271
|
+
data: dataMap,
|
|
272
|
+
initData,
|
|
273
|
+
headers,
|
|
274
|
+
status,
|
|
275
|
+
error: normalizedError ?? undefined,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return { data: dataMap, initData, headers, status };
|
|
280
|
+
};
|
|
122
281
|
const parseAttributeMap = (value) => {
|
|
123
282
|
const attributes = {};
|
|
124
283
|
const attributePattern = /([a-zA-Z0-9:_-]+)\s*=\s*["']([^"']*)["']/g;
|
|
@@ -167,6 +326,10 @@ const extractScriptPayload = (html) => {
|
|
|
167
326
|
const match = html.match(/<script[^>]*id=["']__HYPER_PROPS__["'][^>]*>([\s\S]*?)<\/script>/i);
|
|
168
327
|
return match?.[1] ?? "{}";
|
|
169
328
|
};
|
|
329
|
+
const extractRouteDataPayload = (html) => {
|
|
330
|
+
const match = html.match(new RegExp(`<script[^>]*id=[\"']${ROUTE_DATA_SCRIPT_ID}[\"'][^>]*>([\\s\\S]*?)<\\/script>`, "i"));
|
|
331
|
+
return match?.[1] ?? "{}";
|
|
332
|
+
};
|
|
170
333
|
const extractHeadFromHtml = (html) => {
|
|
171
334
|
const head = {};
|
|
172
335
|
const headMatch = html.match(/<head[^>]*>([\s\S]*?)<\/head>/i);
|
|
@@ -216,6 +379,7 @@ const extractNavigationPayloadFromHtml = (html, fallbackRouteId) => {
|
|
|
216
379
|
routeId: attrs["data-hyper-route"] ?? fallbackRouteId,
|
|
217
380
|
appHtml: app.appHtml,
|
|
218
381
|
propsPayload: extractScriptPayload(html),
|
|
382
|
+
routeDataPayload: extractRouteDataPayload(html),
|
|
219
383
|
head: extractHeadFromHtml(html),
|
|
220
384
|
hydration: attrs["data-hyper-hydration"] === "islands" ? "islands" : "full",
|
|
221
385
|
};
|
|
@@ -277,9 +441,34 @@ const renderScriptTags = (scripts, scriptType) => scripts
|
|
|
277
441
|
? `<script src=\"${src}\"></script>`
|
|
278
442
|
: `<script type=\"module\" src=\"${src}\"></script>`)
|
|
279
443
|
.join("");
|
|
280
|
-
const
|
|
444
|
+
const renderStyleLinks = (styles) => styles.map((href) => `<link rel=\"stylesheet\" href=\"${href}\">`).join("");
|
|
445
|
+
const renderSsrHtmlFragments = (routeId, head, propsPayload, routeDataPayload, scripts, styles, hydration, scriptType, buildVersion, renderDocumentFragments) => {
|
|
446
|
+
if (renderDocumentFragments) {
|
|
447
|
+
try {
|
|
448
|
+
const custom = renderDocumentFragments({
|
|
449
|
+
html: "",
|
|
450
|
+
head,
|
|
451
|
+
propsPayload,
|
|
452
|
+
routeDataPayload,
|
|
453
|
+
routeId,
|
|
454
|
+
hydration,
|
|
455
|
+
scripts,
|
|
456
|
+
legacyScripts: [],
|
|
457
|
+
styles,
|
|
458
|
+
scriptType,
|
|
459
|
+
buildVersion,
|
|
460
|
+
});
|
|
461
|
+
if (custom && typeof custom.prefix === "string" && typeof custom.suffix === "string") {
|
|
462
|
+
return custom;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
catch {
|
|
466
|
+
// Fallback to default document fragments if custom renderer fails.
|
|
467
|
+
}
|
|
468
|
+
}
|
|
281
469
|
const headHtml = renderHeadDescriptor(head);
|
|
282
470
|
const scriptsHtml = renderScriptTags(scripts, scriptType);
|
|
471
|
+
const stylesHtml = renderStyleLinks(styles);
|
|
283
472
|
const islandAttr = hydration === "islands" ? " data-hyper-island-root=\"router\"" : "";
|
|
284
473
|
const buildVersionMeta = buildVersion
|
|
285
474
|
? `<meta name=\"hyper-build-version\" content=\"${escapeHtml(buildVersion)}\">`
|
|
@@ -293,6 +482,7 @@ const renderSsrHtmlFragments = (routeId, head, propsPayload, scripts, hydration,
|
|
|
293
482
|
"<head>",
|
|
294
483
|
headHtml,
|
|
295
484
|
buildVersionMeta,
|
|
485
|
+
stylesHtml,
|
|
296
486
|
"</head>",
|
|
297
487
|
"<body>",
|
|
298
488
|
`<div id=\"app\" data-hyper-route=\"${routeId}\" data-hyper-hydration=\"${hydration}\"${islandAttr}>`,
|
|
@@ -300,6 +490,7 @@ const renderSsrHtmlFragments = (routeId, head, propsPayload, scripts, hydration,
|
|
|
300
490
|
const suffix = [
|
|
301
491
|
"</div>",
|
|
302
492
|
`<script id=\"__HYPER_PROPS__\" type=\"application/json\">${propsPayload}</script>`,
|
|
493
|
+
`<script id=\"${ROUTE_DATA_SCRIPT_ID}\" type=\"application/json\">${routeDataPayload}</script>`,
|
|
303
494
|
`<script>window.__HYPER_ROUTE_ID__ = ${JSON.stringify(routeId)};</script>`,
|
|
304
495
|
scriptsHtml,
|
|
305
496
|
"</body>",
|
|
@@ -307,8 +498,31 @@ const renderSsrHtmlFragments = (routeId, head, propsPayload, scripts, hydration,
|
|
|
307
498
|
].join("");
|
|
308
499
|
return { prefix, suffix };
|
|
309
500
|
};
|
|
310
|
-
const renderSsrHtml = (routeId, html, head, propsPayload, scripts, hydration, scriptType, buildVersion) => {
|
|
311
|
-
|
|
501
|
+
const renderSsrHtml = (routeId, html, head, propsPayload, routeDataPayload, scripts, styles, hydration, scriptType, buildVersion, renderDocument) => {
|
|
502
|
+
if (renderDocument) {
|
|
503
|
+
try {
|
|
504
|
+
const custom = renderDocument({
|
|
505
|
+
html,
|
|
506
|
+
head,
|
|
507
|
+
propsPayload,
|
|
508
|
+
routeDataPayload,
|
|
509
|
+
routeId,
|
|
510
|
+
hydration,
|
|
511
|
+
scripts,
|
|
512
|
+
legacyScripts: [],
|
|
513
|
+
styles,
|
|
514
|
+
scriptType,
|
|
515
|
+
buildVersion,
|
|
516
|
+
});
|
|
517
|
+
if (typeof custom === "string") {
|
|
518
|
+
return custom;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
catch {
|
|
522
|
+
// Fall back to default template if custom document rendering fails.
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
const { prefix, suffix } = renderSsrHtmlFragments(routeId, head, propsPayload, routeDataPayload, scripts, styles, hydration, scriptType, buildVersion);
|
|
312
526
|
return `${prefix}${html}${suffix}`;
|
|
313
527
|
};
|
|
314
528
|
const resolveScriptUrl = (basePath, file) => {
|
|
@@ -345,6 +559,19 @@ const resolveChunkScripts = (manifest, entryKey, basePath, assetsDir, buildVersi
|
|
|
345
559
|
walk(entryKey);
|
|
346
560
|
return scripts;
|
|
347
561
|
};
|
|
562
|
+
const resolveEntryStyles = (entry, basePath, assetsDir, buildVersion) => {
|
|
563
|
+
const styles = entry.styles ?? [];
|
|
564
|
+
const urls = [];
|
|
565
|
+
for (const style of styles) {
|
|
566
|
+
if (typeof style !== "string" || style.length === 0) {
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
const normalized = style.replace(/^\/+/, "");
|
|
570
|
+
const filePath = normalized.includes("/") ? normalized : `${assetsDir}/${normalized}`;
|
|
571
|
+
urls.push(appendBuildVersion(resolveScriptUrl(basePath, filePath), buildVersion));
|
|
572
|
+
}
|
|
573
|
+
return urls;
|
|
574
|
+
};
|
|
348
575
|
const resolveScriptType = (manifest) => manifest.assets?.scriptType === "classic" ? "classic" : "module";
|
|
349
576
|
const isExternalUrl = (value) => value.startsWith("http://") || value.startsWith("https://") || value.startsWith("//");
|
|
350
577
|
const appendBuildVersion = (value, buildVersion) => {
|
|
@@ -394,6 +621,24 @@ const createRuntimeContext = async (options) => {
|
|
|
394
621
|
const assetsDir = typeof manifest.assets?.assetsDir === "string" && manifest.assets.assetsDir.length > 0
|
|
395
622
|
? normalizeAssetsDir(manifest.assets.assetsDir)
|
|
396
623
|
: "assets";
|
|
624
|
+
const serverAssetPaths = new Set();
|
|
625
|
+
const registerServerAsset = (entryKey) => {
|
|
626
|
+
if (!entryKey) {
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
const chunk = manifest.chunks[entryKey];
|
|
630
|
+
if (!chunk || typeof chunk.file !== "string") {
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
const normalized = chunk.file.replace(/^\/+/, "");
|
|
634
|
+
const filePath = normalized.includes("/") ? normalized : `${assetsDir}/${normalized}`;
|
|
635
|
+
serverAssetPaths.add(`/${filePath}`);
|
|
636
|
+
};
|
|
637
|
+
for (const entry of Object.values(manifest.routes)) {
|
|
638
|
+
registerServerAsset(entry.serverEntry);
|
|
639
|
+
}
|
|
640
|
+
registerServerAsset(manifest.special?.notFound?.serverEntry);
|
|
641
|
+
registerServerAsset(manifest.special?.error?.serverEntry);
|
|
397
642
|
const serializeRouteProps = resolveRuntimePropsSerializer(options);
|
|
398
643
|
const resolveServerEntryModule = async (entry) => {
|
|
399
644
|
if (!entry.serverEntry) {
|
|
@@ -424,6 +669,30 @@ const createRuntimeContext = async (options) => {
|
|
|
424
669
|
}
|
|
425
670
|
const getServerProps = serverModule?.getServerProps ??
|
|
426
671
|
serverModule?.getServerSideProps;
|
|
672
|
+
const routeDataResult = await collectRouteDataFromServerModule({
|
|
673
|
+
serverModule,
|
|
674
|
+
routeId,
|
|
675
|
+
params,
|
|
676
|
+
request,
|
|
677
|
+
response,
|
|
678
|
+
});
|
|
679
|
+
if (routeDataResult.redirect) {
|
|
680
|
+
return {
|
|
681
|
+
status: routeDataResult.redirect.status ?? 302,
|
|
682
|
+
headers: {
|
|
683
|
+
...routeDataResult.headers,
|
|
684
|
+
location: routeDataResult.redirect.destination,
|
|
685
|
+
},
|
|
686
|
+
redirect: routeDataResult.redirect,
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
if (routeDataResult.error) {
|
|
690
|
+
return {
|
|
691
|
+
status: routeDataResult.error.status ?? routeDataResult.status ?? 500,
|
|
692
|
+
headers: routeDataResult.headers,
|
|
693
|
+
error: routeDataResult.error,
|
|
694
|
+
};
|
|
695
|
+
}
|
|
427
696
|
// Important: resolve server props before render so SSR output matches data contracts.
|
|
428
697
|
const serverProps = getServerProps
|
|
429
698
|
? await runGetServerProps(getServerProps, {
|
|
@@ -431,30 +700,47 @@ const createRuntimeContext = async (options) => {
|
|
|
431
700
|
params,
|
|
432
701
|
request,
|
|
433
702
|
response,
|
|
703
|
+
init: routeDataResult.initData,
|
|
704
|
+
routeData: routeDataResult.data,
|
|
434
705
|
})
|
|
435
706
|
: null;
|
|
436
707
|
const props = serverProps?.props ?? {};
|
|
437
|
-
const renderResult = await renderToHtml({
|
|
708
|
+
const renderResult = await renderToHtml({
|
|
709
|
+
routeId,
|
|
710
|
+
params,
|
|
711
|
+
props,
|
|
712
|
+
routeData: routeDataResult.data,
|
|
713
|
+
});
|
|
438
714
|
const scripts = resolveChunkScripts(manifest, entry.clientEntry, basePath, assetsDir, manifest.version);
|
|
715
|
+
const styles = resolveEntryStyles(entry, basePath, assetsDir, manifest.version);
|
|
439
716
|
const scriptType = resolveScriptType(manifest);
|
|
440
717
|
const propsPayload = serializeRouteProps(props);
|
|
718
|
+
const routeDataPayload = serializeRouteProps(routeDataResult.data);
|
|
441
719
|
const hydration = serverModule?.hydration === "full" || serverModule?.hydration === "islands"
|
|
442
720
|
? serverModule.hydration
|
|
443
721
|
: "islands";
|
|
722
|
+
const renderDocument = serverModule && typeof serverModule.renderDocument === "function"
|
|
723
|
+
? serverModule.renderDocument
|
|
724
|
+
: undefined;
|
|
444
725
|
const payload = {
|
|
445
726
|
kind: "hyper-route-payload",
|
|
446
727
|
routeId,
|
|
447
728
|
appHtml: renderResult.html,
|
|
448
729
|
propsPayload,
|
|
730
|
+
routeDataPayload,
|
|
449
731
|
head: renderResult.head ?? {},
|
|
450
732
|
hydration,
|
|
451
733
|
};
|
|
452
|
-
const finalHtml = renderSsrHtml(routeId, payload.appHtml, payload.head, payload.propsPayload, scripts, hydration, scriptType, manifest.version);
|
|
734
|
+
const finalHtml = renderSsrHtml(routeId, payload.appHtml, payload.head, payload.propsPayload, payload.routeDataPayload, scripts, styles, hydration, scriptType, manifest.version, renderDocument);
|
|
453
735
|
return {
|
|
454
736
|
payload,
|
|
455
737
|
html: finalHtml,
|
|
456
|
-
status: renderResult.status ??
|
|
738
|
+
status: renderResult.status ??
|
|
739
|
+
serverProps?.status ??
|
|
740
|
+
routeDataResult.status ??
|
|
741
|
+
200,
|
|
457
742
|
headers: {
|
|
743
|
+
...routeDataResult.headers,
|
|
458
744
|
...(serverProps?.headers ?? {}),
|
|
459
745
|
...(renderResult.headers ?? {}),
|
|
460
746
|
},
|
|
@@ -468,38 +754,143 @@ const createRuntimeContext = async (options) => {
|
|
|
468
754
|
}
|
|
469
755
|
const getServerProps = serverModule?.getServerProps ??
|
|
470
756
|
serverModule?.getServerSideProps;
|
|
757
|
+
const routeDataResult = await collectRouteDataFromServerModule({
|
|
758
|
+
serverModule,
|
|
759
|
+
routeId,
|
|
760
|
+
params,
|
|
761
|
+
request,
|
|
762
|
+
response,
|
|
763
|
+
});
|
|
764
|
+
if (routeDataResult.redirect || routeDataResult.error) {
|
|
765
|
+
return null;
|
|
766
|
+
}
|
|
471
767
|
const serverProps = getServerProps
|
|
472
768
|
? await runGetServerProps(getServerProps, {
|
|
473
769
|
routeId,
|
|
474
770
|
params,
|
|
475
771
|
request,
|
|
476
772
|
response,
|
|
773
|
+
init: routeDataResult.initData,
|
|
774
|
+
routeData: routeDataResult.data,
|
|
477
775
|
})
|
|
478
776
|
: null;
|
|
479
777
|
const props = serverProps?.props ?? {};
|
|
480
|
-
const renderResult = await renderToStream({
|
|
778
|
+
const renderResult = await renderToStream({
|
|
779
|
+
routeId,
|
|
780
|
+
params,
|
|
781
|
+
props,
|
|
782
|
+
routeData: routeDataResult.data,
|
|
783
|
+
});
|
|
481
784
|
if (!renderResult || !renderResult.stream || typeof renderResult.stream.pipe !== "function") {
|
|
482
785
|
return null;
|
|
483
786
|
}
|
|
484
787
|
const scripts = resolveChunkScripts(manifest, entry.clientEntry, basePath, assetsDir, manifest.version);
|
|
788
|
+
const styles = resolveEntryStyles(entry, basePath, assetsDir, manifest.version);
|
|
485
789
|
const scriptType = resolveScriptType(manifest);
|
|
486
790
|
const propsPayload = serializeRouteProps(props);
|
|
791
|
+
const routeDataPayload = serializeRouteProps(routeDataResult.data);
|
|
487
792
|
const hydration = serverModule?.hydration === "full" || serverModule?.hydration === "islands"
|
|
488
793
|
? serverModule.hydration
|
|
489
794
|
: "islands";
|
|
795
|
+
const renderDocumentFragments = serverModule &&
|
|
796
|
+
typeof serverModule.renderDocumentFragments === "function"
|
|
797
|
+
? serverModule.renderDocumentFragments
|
|
798
|
+
: undefined;
|
|
490
799
|
return {
|
|
491
800
|
stream: renderResult.stream,
|
|
492
801
|
head: renderResult.head ?? {},
|
|
493
802
|
propsPayload,
|
|
803
|
+
routeDataPayload,
|
|
494
804
|
scripts,
|
|
805
|
+
styles,
|
|
495
806
|
hydration,
|
|
496
807
|
scriptType,
|
|
497
|
-
status: renderResult.status ??
|
|
808
|
+
status: renderResult.status ??
|
|
809
|
+
serverProps?.status ??
|
|
810
|
+
routeDataResult.status ??
|
|
811
|
+
200,
|
|
498
812
|
headers: {
|
|
813
|
+
...routeDataResult.headers,
|
|
499
814
|
...(serverProps?.headers ?? {}),
|
|
500
815
|
...(renderResult.headers ?? {}),
|
|
501
816
|
},
|
|
502
817
|
abort: renderResult.abort,
|
|
818
|
+
renderDocumentFragments,
|
|
819
|
+
};
|
|
820
|
+
};
|
|
821
|
+
const renderSpecialPage = async (input) => {
|
|
822
|
+
const serverModule = await resolveServerEntryModule(input.entry);
|
|
823
|
+
const renderToHtml = serverModule?.renderToHtml;
|
|
824
|
+
if (typeof renderToHtml !== "function") {
|
|
825
|
+
throw new HyperError("MANIFEST_INVALID", "Server entry missing renderToHtml export.", {
|
|
826
|
+
entry: input.entry.serverEntry,
|
|
827
|
+
});
|
|
828
|
+
}
|
|
829
|
+
const routeDataResult = await collectRouteDataFromServerModule({
|
|
830
|
+
serverModule,
|
|
831
|
+
routeId: input.routeId,
|
|
832
|
+
params: undefined,
|
|
833
|
+
request: input.request,
|
|
834
|
+
response: input.response,
|
|
835
|
+
});
|
|
836
|
+
const mergedRouteData = {
|
|
837
|
+
...routeDataResult.data,
|
|
838
|
+
...(input.extraRouteData ?? {}),
|
|
839
|
+
};
|
|
840
|
+
const getServerProps = serverModule?.getServerProps ??
|
|
841
|
+
serverModule?.getServerSideProps;
|
|
842
|
+
const serverProps = getServerProps
|
|
843
|
+
? await runGetServerProps(getServerProps, {
|
|
844
|
+
routeId: input.routeId,
|
|
845
|
+
request: input.request,
|
|
846
|
+
response: input.response,
|
|
847
|
+
init: routeDataResult.initData,
|
|
848
|
+
routeData: mergedRouteData,
|
|
849
|
+
})
|
|
850
|
+
: null;
|
|
851
|
+
const props = {
|
|
852
|
+
...(serverProps?.props ?? {}),
|
|
853
|
+
...(input.extraProps ?? {}),
|
|
854
|
+
};
|
|
855
|
+
const renderResult = await renderToHtml({
|
|
856
|
+
routeId: input.routeId,
|
|
857
|
+
props,
|
|
858
|
+
routeData: mergedRouteData,
|
|
859
|
+
});
|
|
860
|
+
const scripts = resolveChunkScripts(manifest, input.entry.clientEntry, basePath, assetsDir, manifest.version);
|
|
861
|
+
const styles = resolveEntryStyles(input.entry, basePath, assetsDir, manifest.version);
|
|
862
|
+
const scriptType = resolveScriptType(manifest);
|
|
863
|
+
const propsPayload = serializeRouteProps(props);
|
|
864
|
+
const routeDataPayload = serializeRouteProps(mergedRouteData);
|
|
865
|
+
const hydration = serverModule?.hydration === "full" || serverModule?.hydration === "islands"
|
|
866
|
+
? serverModule.hydration
|
|
867
|
+
: "islands";
|
|
868
|
+
const renderDocument = serverModule && typeof serverModule.renderDocument === "function"
|
|
869
|
+
? serverModule.renderDocument
|
|
870
|
+
: undefined;
|
|
871
|
+
const payload = {
|
|
872
|
+
kind: "hyper-route-payload",
|
|
873
|
+
routeId: input.routeId,
|
|
874
|
+
appHtml: renderResult.html,
|
|
875
|
+
propsPayload,
|
|
876
|
+
routeDataPayload,
|
|
877
|
+
head: renderResult.head ?? {},
|
|
878
|
+
hydration,
|
|
879
|
+
};
|
|
880
|
+
const finalHtml = renderSsrHtml(input.routeId, payload.appHtml, payload.head, payload.propsPayload, payload.routeDataPayload, scripts, styles, hydration, scriptType, manifest.version, renderDocument);
|
|
881
|
+
return {
|
|
882
|
+
payload,
|
|
883
|
+
html: finalHtml,
|
|
884
|
+
status: input.statusOverride ??
|
|
885
|
+
renderResult.status ??
|
|
886
|
+
serverProps?.status ??
|
|
887
|
+
routeDataResult.status ??
|
|
888
|
+
200,
|
|
889
|
+
headers: {
|
|
890
|
+
...routeDataResult.headers,
|
|
891
|
+
...(serverProps?.headers ?? {}),
|
|
892
|
+
...(renderResult.headers ?? {}),
|
|
893
|
+
},
|
|
503
894
|
};
|
|
504
895
|
};
|
|
505
896
|
return {
|
|
@@ -508,11 +899,14 @@ const createRuntimeContext = async (options) => {
|
|
|
508
899
|
routeGraph,
|
|
509
900
|
basePath,
|
|
510
901
|
assetsDir,
|
|
902
|
+
serverAssetPaths,
|
|
903
|
+
special: manifest.special,
|
|
511
904
|
fallbackPolicy: options.fallbackPolicy,
|
|
512
905
|
appMode: options.appMode ?? "ssg",
|
|
513
906
|
dynamicPageApi: options.dynamicPageApi,
|
|
514
907
|
renderSsrRoute,
|
|
515
908
|
renderSsrStream,
|
|
909
|
+
renderSpecialPage,
|
|
516
910
|
};
|
|
517
911
|
};
|
|
518
912
|
const handleRuntimeRequest = async (context, request, response) => {
|
|
@@ -537,6 +931,12 @@ const handleRuntimeRequest = async (context, request, response) => {
|
|
|
537
931
|
}
|
|
538
932
|
const assetPath = resolveAssetPath(context.distDir, urlPath, context.assetsDir);
|
|
539
933
|
if (assetPath) {
|
|
934
|
+
// Guard: server entry bundles must never be publicly downloadable.
|
|
935
|
+
if (context.serverAssetPaths.has(urlPath)) {
|
|
936
|
+
response.statusCode = 404;
|
|
937
|
+
response.end();
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
540
940
|
try {
|
|
541
941
|
const assetStat = await stat(assetPath);
|
|
542
942
|
if (assetStat.isFile()) {
|
|
@@ -630,7 +1030,7 @@ const handleRuntimeRequest = async (context, request, response) => {
|
|
|
630
1030
|
response.setHeader(key, value);
|
|
631
1031
|
}
|
|
632
1032
|
response.setHeader("content-type", "text/html; charset=utf-8");
|
|
633
|
-
const { prefix, suffix } = renderSsrHtmlFragments(match.route.id, streamResult.head, streamResult.propsPayload, streamResult.scripts, streamResult.hydration, streamResult.scriptType, context.manifest.version);
|
|
1033
|
+
const { prefix, suffix } = renderSsrHtmlFragments(match.route.id, streamResult.head, streamResult.propsPayload, streamResult.routeDataPayload, streamResult.scripts, streamResult.styles, streamResult.hydration, streamResult.scriptType, context.manifest.version, streamResult.renderDocumentFragments);
|
|
634
1034
|
response.write(prefix);
|
|
635
1035
|
response.flushHeaders?.();
|
|
636
1036
|
const stream = streamResult.stream;
|
|
@@ -668,6 +1068,64 @@ const handleRuntimeRequest = async (context, request, response) => {
|
|
|
668
1068
|
}
|
|
669
1069
|
}
|
|
670
1070
|
const ssrResult = await context.renderSsrRoute(entry, match.route.id, match.params, request, response);
|
|
1071
|
+
if (ssrResult.redirect) {
|
|
1072
|
+
if (navigationRequest) {
|
|
1073
|
+
response.statusCode = 200;
|
|
1074
|
+
response.setHeader("content-type", "application/json; charset=utf-8");
|
|
1075
|
+
response.setHeader("x-hyper-navigation", NAVIGATION_MODE);
|
|
1076
|
+
response.end(JSON.stringify({
|
|
1077
|
+
kind: "hyper-route-redirect",
|
|
1078
|
+
destination: ssrResult.redirect.destination,
|
|
1079
|
+
status: ssrResult.redirect.status ?? 302,
|
|
1080
|
+
replace: ssrResult.redirect.replace ?? false,
|
|
1081
|
+
}));
|
|
1082
|
+
return;
|
|
1083
|
+
}
|
|
1084
|
+
response.statusCode = ssrResult.redirect.status ?? 302;
|
|
1085
|
+
response.setHeader("location", ssrResult.redirect.destination);
|
|
1086
|
+
response.end();
|
|
1087
|
+
return;
|
|
1088
|
+
}
|
|
1089
|
+
if (ssrResult.error) {
|
|
1090
|
+
const errorEntry = context.special?.error;
|
|
1091
|
+
if (errorEntry?.serverEntry) {
|
|
1092
|
+
const errorResult = await context.renderSpecialPage({
|
|
1093
|
+
entry: errorEntry,
|
|
1094
|
+
routeId: SPECIAL_ROUTE_IDS.error,
|
|
1095
|
+
request,
|
|
1096
|
+
response,
|
|
1097
|
+
statusOverride: ssrResult.error.status ?? ssrResult.status ?? 500,
|
|
1098
|
+
extraRouteData: {
|
|
1099
|
+
[ROUTE_DATA_ERROR_KEY]: ssrResult.error,
|
|
1100
|
+
},
|
|
1101
|
+
extraProps: {
|
|
1102
|
+
error: ssrResult.error,
|
|
1103
|
+
routeId: match.route.id,
|
|
1104
|
+
},
|
|
1105
|
+
});
|
|
1106
|
+
if (navigationRequest && errorResult.payload) {
|
|
1107
|
+
response.statusCode = errorResult.status;
|
|
1108
|
+
for (const [key, value] of Object.entries(errorResult.headers ?? {})) {
|
|
1109
|
+
response.setHeader(key, value);
|
|
1110
|
+
}
|
|
1111
|
+
response.setHeader("content-type", "application/json; charset=utf-8");
|
|
1112
|
+
response.setHeader("x-hyper-navigation", NAVIGATION_MODE);
|
|
1113
|
+
response.end(JSON.stringify(errorResult.payload));
|
|
1114
|
+
return;
|
|
1115
|
+
}
|
|
1116
|
+
response.statusCode = errorResult.status;
|
|
1117
|
+
for (const [key, value] of Object.entries(errorResult.headers ?? {})) {
|
|
1118
|
+
response.setHeader(key, value);
|
|
1119
|
+
}
|
|
1120
|
+
response.setHeader("content-type", "text/html; charset=utf-8");
|
|
1121
|
+
response.end(errorResult.html ?? "");
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
1124
|
+
response.statusCode = ssrResult.error.status ?? ssrResult.status ?? 500;
|
|
1125
|
+
response.setHeader("content-type", "text/plain; charset=utf-8");
|
|
1126
|
+
response.end(ssrResult.error.message ?? "SSR route error");
|
|
1127
|
+
return;
|
|
1128
|
+
}
|
|
671
1129
|
if (navigationRequest) {
|
|
672
1130
|
response.statusCode = ssrResult.status ?? 200;
|
|
673
1131
|
for (const [key, value] of Object.entries(ssrResult.headers ?? {})) {
|
|
@@ -687,6 +1145,35 @@ const handleRuntimeRequest = async (context, request, response) => {
|
|
|
687
1145
|
return;
|
|
688
1146
|
}
|
|
689
1147
|
catch {
|
|
1148
|
+
const errorEntry = context.special?.error;
|
|
1149
|
+
if (errorEntry?.serverEntry) {
|
|
1150
|
+
try {
|
|
1151
|
+
const errorResult = await context.renderSpecialPage({
|
|
1152
|
+
entry: errorEntry,
|
|
1153
|
+
routeId: SPECIAL_ROUTE_IDS.error,
|
|
1154
|
+
request,
|
|
1155
|
+
response,
|
|
1156
|
+
statusOverride: 500,
|
|
1157
|
+
extraRouteData: {
|
|
1158
|
+
[ROUTE_DATA_ERROR_KEY]: { status: 500, message: "SSR render failed" },
|
|
1159
|
+
},
|
|
1160
|
+
extraProps: {
|
|
1161
|
+
error: { status: 500, message: "SSR render failed" },
|
|
1162
|
+
routeId: match.route.id,
|
|
1163
|
+
},
|
|
1164
|
+
});
|
|
1165
|
+
response.statusCode = errorResult.status;
|
|
1166
|
+
for (const [key, value] of Object.entries(errorResult.headers ?? {})) {
|
|
1167
|
+
response.setHeader(key, value);
|
|
1168
|
+
}
|
|
1169
|
+
response.setHeader("content-type", "text/html; charset=utf-8");
|
|
1170
|
+
response.end(errorResult.html ?? "");
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
catch {
|
|
1174
|
+
// Fall through to plain error response.
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
690
1177
|
response.statusCode = 500;
|
|
691
1178
|
response.setHeader("content-type", "text/plain; charset=utf-8");
|
|
692
1179
|
response.end("SSR render failed");
|
|
@@ -735,6 +1222,67 @@ const handleRuntimeRequest = async (context, request, response) => {
|
|
|
735
1222
|
response.end(renderRuntimePlaceholder(match.route.id));
|
|
736
1223
|
return;
|
|
737
1224
|
}
|
|
1225
|
+
const notFoundEntry = context.special?.notFound;
|
|
1226
|
+
if (notFoundEntry?.serverEntry) {
|
|
1227
|
+
try {
|
|
1228
|
+
const notFoundResult = await context.renderSpecialPage({
|
|
1229
|
+
entry: notFoundEntry,
|
|
1230
|
+
routeId: SPECIAL_ROUTE_IDS.notFound,
|
|
1231
|
+
request,
|
|
1232
|
+
response,
|
|
1233
|
+
statusOverride: 404,
|
|
1234
|
+
extraProps: {
|
|
1235
|
+
routeId: urlPath,
|
|
1236
|
+
},
|
|
1237
|
+
});
|
|
1238
|
+
if (navigationRequest && notFoundResult.payload) {
|
|
1239
|
+
response.statusCode = 404;
|
|
1240
|
+
for (const [key, value] of Object.entries(notFoundResult.headers ?? {})) {
|
|
1241
|
+
response.setHeader(key, value);
|
|
1242
|
+
}
|
|
1243
|
+
response.setHeader("content-type", "application/json; charset=utf-8");
|
|
1244
|
+
response.setHeader("x-hyper-navigation", NAVIGATION_MODE);
|
|
1245
|
+
response.end(JSON.stringify(notFoundResult.payload));
|
|
1246
|
+
return;
|
|
1247
|
+
}
|
|
1248
|
+
response.statusCode = 404;
|
|
1249
|
+
for (const [key, value] of Object.entries(notFoundResult.headers ?? {})) {
|
|
1250
|
+
response.setHeader(key, value);
|
|
1251
|
+
}
|
|
1252
|
+
response.setHeader("content-type", "text/html; charset=utf-8");
|
|
1253
|
+
response.end(notFoundResult.html ?? "");
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
catch {
|
|
1257
|
+
// Fall through to static or plain 404 response.
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
if (notFoundEntry?.html) {
|
|
1261
|
+
const htmlPath = resolveManifestFile(context.distDir, notFoundEntry.html);
|
|
1262
|
+
if (htmlPath) {
|
|
1263
|
+
try {
|
|
1264
|
+
const file = await readStaticFile(htmlPath);
|
|
1265
|
+
if (navigationRequest) {
|
|
1266
|
+
const text = file.body.toString("utf-8");
|
|
1267
|
+
const payload = extractNavigationPayloadFromHtml(text, SPECIAL_ROUTE_IDS.notFound);
|
|
1268
|
+
if (payload) {
|
|
1269
|
+
response.statusCode = 404;
|
|
1270
|
+
response.setHeader("content-type", "application/json; charset=utf-8");
|
|
1271
|
+
response.setHeader("x-hyper-navigation", NAVIGATION_MODE);
|
|
1272
|
+
response.end(JSON.stringify(payload));
|
|
1273
|
+
return;
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
response.statusCode = 404;
|
|
1277
|
+
response.setHeader("content-type", file.contentType);
|
|
1278
|
+
response.end(file.body);
|
|
1279
|
+
return;
|
|
1280
|
+
}
|
|
1281
|
+
catch {
|
|
1282
|
+
// Fall through to plain response.
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
738
1286
|
response.statusCode = 404;
|
|
739
1287
|
response.setHeader("content-type", "text/plain; charset=utf-8");
|
|
740
1288
|
response.end("Not Found");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tyndall/runtime",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
12
|
"types": "./dist/index.d.ts",
|
|
13
|
-
"bun": "./
|
|
13
|
+
"bun": "./dist/index.js",
|
|
14
14
|
"default": "./dist/index.js"
|
|
15
15
|
}
|
|
16
16
|
},
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"build": "tsc -p tsconfig.json"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@tyndall/core": "
|
|
25
|
-
"@tyndall/shared": "
|
|
24
|
+
"@tyndall/core": "^0.0.3",
|
|
25
|
+
"@tyndall/shared": "^0.0.3"
|
|
26
26
|
}
|
|
27
27
|
}
|