@pracht/core 0.2.3 → 0.2.5
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/LICENSE +21 -0
- package/dist/index.d.mts +7 -1
- package/dist/index.mjs +31 -8
- package/package.json +2 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jovi De Croock
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.mts
CHANGED
|
@@ -157,6 +157,9 @@ type LoaderData<TLoader extends LoaderLike> = TLoader extends ((...args: any[])
|
|
|
157
157
|
interface HeadArgs<TLoader extends LoaderLike = undefined, TContext = any> extends BaseRouteArgs<TContext> {
|
|
158
158
|
data: LoaderData<TLoader>;
|
|
159
159
|
}
|
|
160
|
+
interface HeadersArgs<TLoader extends LoaderLike = undefined, TContext = any> extends BaseRouteArgs<TContext> {
|
|
161
|
+
data: LoaderData<TLoader>;
|
|
162
|
+
}
|
|
160
163
|
interface RouteComponentProps<TLoader extends LoaderLike = undefined> {
|
|
161
164
|
data: LoaderData<TLoader>;
|
|
162
165
|
params: RouteParams;
|
|
@@ -171,6 +174,7 @@ type LoaderFn<TContext = any, TData = unknown> = (args: LoaderArgs<TContext>) =>
|
|
|
171
174
|
interface RouteModule<TContext = any, TLoader extends LoaderLike = undefined> {
|
|
172
175
|
loader?: LoaderFn<TContext>;
|
|
173
176
|
head?: (args: HeadArgs<TLoader, TContext>) => MaybePromise<HeadMetadata>;
|
|
177
|
+
headers?: (args: HeadersArgs<TLoader, TContext>) => MaybePromise<HeadersInit>;
|
|
174
178
|
Component?: FunctionComponent<RouteComponentProps<TLoader>>;
|
|
175
179
|
default?: FunctionComponent<RouteComponentProps<TLoader>>;
|
|
176
180
|
ErrorBoundary?: FunctionComponent<ErrorBoundaryProps>;
|
|
@@ -180,6 +184,7 @@ interface ShellModule<TContext = any> {
|
|
|
180
184
|
Shell: FunctionComponent<ShellProps>;
|
|
181
185
|
Loading?: FunctionComponent;
|
|
182
186
|
head?: (args: BaseRouteArgs<TContext>) => MaybePromise<HeadMetadata>;
|
|
187
|
+
headers?: (args: BaseRouteArgs<TContext>) => MaybePromise<HeadersInit>;
|
|
183
188
|
}
|
|
184
189
|
type MiddlewareResult<TContext = any> = void | Response | {
|
|
185
190
|
redirect: string;
|
|
@@ -351,6 +356,7 @@ declare function applyDefaultSecurityHeaders(headers: Headers): Headers;
|
|
|
351
356
|
interface PrerenderResult {
|
|
352
357
|
path: string;
|
|
353
358
|
html: string;
|
|
359
|
+
headers?: Record<string, string>;
|
|
354
360
|
}
|
|
355
361
|
interface ISGManifestEntry {
|
|
356
362
|
revalidate: RouteRevalidate;
|
|
@@ -397,4 +403,4 @@ interface InitClientRouterOptions {
|
|
|
397
403
|
}
|
|
398
404
|
declare function initClientRouter(options: InitClientRouterOptions): Promise<void>;
|
|
399
405
|
//#endregion
|
|
400
|
-
export { type ApiConfig, type ApiRouteArgs, type ApiRouteHandler, type ApiRouteMatch, type ApiRouteModule, type BaseRouteArgs, type DataModule, type ErrorBoundaryProps, Form, type FormProps, type GroupDefinition, type GroupMeta, type HandlePrachtRequestOptions, type HeadArgs, type HeadMetadata, type HttpMethod, type ISGManifestEntry, type InitClientRouterOptions, type LoaderArgs, type LoaderData, type LoaderFn, type Location, type MiddlewareArgs, type MiddlewareFn, type MiddlewareModule, type MiddlewareResult, type ModuleImporter, type ModuleRef, type ModuleRegistry, type NavigateFn, type PrachtApp, type PrachtAppConfig, PrachtHttpError, type PrachtHydrationState, type PrachtRuntimeDiagnosticPhase, type PrachtRuntimeDiagnostics, PrachtRuntimeProvider, type PrefetchStrategy, type PrerenderAppOptions, type PrerenderAppResult, type PrerenderResult, type Register, type RenderMode, type ResolvedApiRoute, type ResolvedPrachtApp, type ResolvedRoute, type RouteComponentProps, type RouteConfig, type RouteDefinition, type RouteMatch, type RouteMeta, type RouteModule, type RouteParams, type RouteRevalidate, type RouteStateResult, type RouteTreeNode, type SerializedRouteError, type ShellModule, type ShellProps, type StartAppOptions, Suspense, type TimeRevalidatePolicy, applyDefaultSecurityHeaders, buildPathFromSegments, defineApp, forwardRef, group, handlePrachtRequest, initClientRouter, lazy, matchApiRoute, matchAppRoute, prerenderApp, readHydrationState, resolveApiRoutes, resolveApp, route, startApp, timeRevalidate, useIsHydrated, useLocation, useNavigate, useParams, useRevalidate, useRevalidateRoute, useRouteData };
|
|
406
|
+
export { type ApiConfig, type ApiRouteArgs, type ApiRouteHandler, type ApiRouteMatch, type ApiRouteModule, type BaseRouteArgs, type DataModule, type ErrorBoundaryProps, Form, type FormProps, type GroupDefinition, type GroupMeta, type HandlePrachtRequestOptions, type HeadArgs, type HeadMetadata, type HeadersArgs, type HttpMethod, type ISGManifestEntry, type InitClientRouterOptions, type LoaderArgs, type LoaderData, type LoaderFn, type Location, type MiddlewareArgs, type MiddlewareFn, type MiddlewareModule, type MiddlewareResult, type ModuleImporter, type ModuleRef, type ModuleRegistry, type NavigateFn, type PrachtApp, type PrachtAppConfig, PrachtHttpError, type PrachtHydrationState, type PrachtRuntimeDiagnosticPhase, type PrachtRuntimeDiagnostics, PrachtRuntimeProvider, type PrefetchStrategy, type PrerenderAppOptions, type PrerenderAppResult, type PrerenderResult, type Register, type RenderMode, type ResolvedApiRoute, type ResolvedPrachtApp, type ResolvedRoute, type RouteComponentProps, type RouteConfig, type RouteDefinition, type RouteMatch, type RouteMeta, type RouteModule, type RouteParams, type RouteRevalidate, type RouteStateResult, type RouteTreeNode, type SerializedRouteError, type ShellModule, type ShellProps, type StartAppOptions, Suspense, type TimeRevalidatePolicy, applyDefaultSecurityHeaders, buildPathFromSegments, defineApp, forwardRef, group, handlePrachtRequest, initClientRouter, lazy, matchApiRoute, matchAppRoute, prerenderApp, readHydrationState, resolveApiRoutes, resolveApp, route, startApp, timeRevalidate, useIsHydrated, useLocation, useNavigate, useParams, useRevalidate, useRevalidateRoute, useRouteData };
|
package/dist/index.mjs
CHANGED
|
@@ -333,6 +333,7 @@ async function handlePrachtRequest(options) {
|
|
|
333
333
|
currentPhase = "render";
|
|
334
334
|
shellModule = match.route.shellFile ? await resolveRegistryModule(registry.shellModules, match.route.shellFile) : void 0;
|
|
335
335
|
const head = await mergeHeadMetadata(shellModule, routeModule, routeArgs, data);
|
|
336
|
+
const documentHeaders = await mergeDocumentHeaders(shellModule, routeModule, routeArgs, data);
|
|
336
337
|
const cssUrls = resolvePageCssUrls(options, match.route.shellFile, match.route.file);
|
|
337
338
|
const modulePreloadUrls = resolvePageJsUrls(options, match.route.shellFile, match.route.file);
|
|
338
339
|
if (match.route.render === "spa") {
|
|
@@ -356,7 +357,7 @@ async function handlePrachtRequest(options) {
|
|
|
356
357
|
clientEntryUrl: options.clientEntryUrl,
|
|
357
358
|
cssUrls,
|
|
358
359
|
modulePreloadUrls
|
|
359
|
-
}));
|
|
360
|
+
}), 200, documentHeaders);
|
|
360
361
|
}
|
|
361
362
|
const DefaultComponent = typeof routeModule.default === "function" ? routeModule.default : void 0;
|
|
362
363
|
const Component = routeModule.Component ?? DefaultComponent;
|
|
@@ -385,7 +386,7 @@ async function handlePrachtRequest(options) {
|
|
|
385
386
|
clientEntryUrl: options.clientEntryUrl,
|
|
386
387
|
cssUrls,
|
|
387
388
|
modulePreloadUrls
|
|
388
|
-
}));
|
|
389
|
+
}), 200, documentHeaders);
|
|
389
390
|
} catch (error) {
|
|
390
391
|
return renderRouteErrorResponse({
|
|
391
392
|
error,
|
|
@@ -596,6 +597,7 @@ async function renderRouteErrorResponse(options) {
|
|
|
596
597
|
if (options.isRouteStateRequest) return jsonErrorResponse(routeErrorWithDiagnostics, { isRouteStateRequest: true });
|
|
597
598
|
const shellModule = options.shellModule ?? (options.shellFile ? await resolveRegistryModule(options.options.registry?.shellModules, options.shellFile) : void 0);
|
|
598
599
|
const head = shellModule?.head ? await shellModule.head(options.routeArgs) : {};
|
|
600
|
+
const documentHeaders = await mergeDocumentHeaders(shellModule, void 0, options.routeArgs, void 0);
|
|
599
601
|
const cssUrls = resolvePageCssUrls(options.options, options.shellFile, options.routeArgs.route.file);
|
|
600
602
|
const modulePreloadUrls = resolvePageJsUrls(options.options, options.shellFile, options.routeArgs.route.file);
|
|
601
603
|
const renderToString = await getRenderToStringAsync();
|
|
@@ -619,7 +621,7 @@ async function renderRouteErrorResponse(options) {
|
|
|
619
621
|
clientEntryUrl: options.options.clientEntryUrl,
|
|
620
622
|
cssUrls,
|
|
621
623
|
modulePreloadUrls
|
|
622
|
-
}), routeErrorWithDiagnostics.status);
|
|
624
|
+
}), routeErrorWithDiagnostics.status, documentHeaders);
|
|
623
625
|
}
|
|
624
626
|
async function runMiddlewareChain(options) {
|
|
625
627
|
let context = options.context;
|
|
@@ -681,6 +683,22 @@ async function mergeHeadMetadata(shellModule, routeModule, routeArgs, data) {
|
|
|
681
683
|
link: [...shellHead.link ?? [], ...routeHead.link ?? []]
|
|
682
684
|
};
|
|
683
685
|
}
|
|
686
|
+
async function mergeDocumentHeaders(shellModule, routeModule, routeArgs, data) {
|
|
687
|
+
const headers = new Headers();
|
|
688
|
+
const shellHeaders = shellModule?.headers ? await shellModule.headers(routeArgs) : void 0;
|
|
689
|
+
if (shellHeaders) applyHeaders(headers, shellHeaders);
|
|
690
|
+
const routeHeaders = routeModule?.headers ? await routeModule.headers({
|
|
691
|
+
...routeArgs,
|
|
692
|
+
data
|
|
693
|
+
}) : void 0;
|
|
694
|
+
if (routeHeaders) applyHeaders(headers, routeHeaders);
|
|
695
|
+
return headers;
|
|
696
|
+
}
|
|
697
|
+
function applyHeaders(headers, init) {
|
|
698
|
+
new Headers(init).forEach((value, key) => {
|
|
699
|
+
headers.set(key, value);
|
|
700
|
+
});
|
|
701
|
+
}
|
|
684
702
|
function buildHtmlDocument(options) {
|
|
685
703
|
const { head, body, hydrationState, clientEntryUrl, cssUrls = [], modulePreloadUrls = [] } = options;
|
|
686
704
|
const titleTag = head.title ? `<title>${escapeHtml(head.title)}</title>` : "";
|
|
@@ -707,8 +725,10 @@ function buildHtmlDocument(options) {
|
|
|
707
725
|
</body>
|
|
708
726
|
</html>`;
|
|
709
727
|
}
|
|
710
|
-
function htmlResponse(html, status = 200) {
|
|
711
|
-
const headers =
|
|
728
|
+
function htmlResponse(html, status = 200, initHeaders) {
|
|
729
|
+
const headers = new Headers({ "content-type": "text/html; charset=utf-8" });
|
|
730
|
+
if (initHeaders) applyHeaders(headers, initHeaders);
|
|
731
|
+
applySecurityAndRouteHeaders(headers, { isRouteStateRequest: false });
|
|
712
732
|
return new Response(html, {
|
|
713
733
|
status,
|
|
714
734
|
headers
|
|
@@ -796,16 +816,19 @@ async function prerenderApp(options) {
|
|
|
796
816
|
console.warn(` Warning: ${item.render.toUpperCase()} route "${item.pathname}" returned status ${response.status}, skipping.`);
|
|
797
817
|
return null;
|
|
798
818
|
}
|
|
819
|
+
const html = await response.text();
|
|
799
820
|
return {
|
|
800
|
-
|
|
801
|
-
html
|
|
821
|
+
headers: Object.fromEntries(response.headers),
|
|
822
|
+
html,
|
|
823
|
+
item
|
|
802
824
|
};
|
|
803
825
|
}));
|
|
804
826
|
for (const result of batchResults) {
|
|
805
827
|
if (!result) continue;
|
|
806
828
|
results.push({
|
|
807
829
|
path: result.item.pathname,
|
|
808
|
-
html: result.html
|
|
830
|
+
html: result.html,
|
|
831
|
+
headers: result.headers
|
|
809
832
|
});
|
|
810
833
|
if (result.item.render === "isg" && result.item.revalidate) isgManifest[result.item.pathname] = { revalidate: result.item.revalidate };
|
|
811
834
|
}
|
package/package.json
CHANGED