@demiurgejs/core 0.2.0-beta.3 → 0.2.0-beta.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/README.md +36 -11
- package/bin/demiurge.mjs +47 -13
- package/dist/adapter/index.d.ts +1 -1
- package/dist/adapter/index.d.ts.map +1 -1
- package/dist/browser/file-router.d.ts +388 -5
- package/dist/browser/file-router.d.ts.map +1 -1
- package/dist/browser/focus.d.ts +20 -0
- package/dist/browser/focus.d.ts.map +1 -0
- package/dist/browser/index.d.ts +7 -1
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/mutation-action.d.ts +81 -0
- package/dist/browser/mutation-action.d.ts.map +1 -0
- package/dist/chunks/document-shell-9GPwtcTt.js +36 -0
- package/dist/chunks/document-shell-9GPwtcTt.js.map +1 -0
- package/dist/chunks/{image-codec-Di53WpcH.js → image-codec-Dh1POFhE.js} +2 -2
- package/dist/chunks/{image-codec-Di53WpcH.js.map → image-codec-Dh1POFhE.js.map} +1 -1
- package/dist/chunks/{images-Edar3eU1.js → images-CG7ZzayG.js} +99 -91
- package/dist/chunks/images-CG7ZzayG.js.map +1 -0
- package/dist/chunks/index-0MNiR_wo.js +833 -0
- package/dist/chunks/index-0MNiR_wo.js.map +1 -0
- package/dist/chunks/manifest-vO6c0G0W.js +19 -0
- package/dist/chunks/manifest-vO6c0G0W.js.map +1 -0
- package/dist/chunks/plugin-BZauDxRY.js +2310 -0
- package/dist/chunks/plugin-BZauDxRY.js.map +1 -0
- package/dist/chunks/session-store-ChModVcq.js +92 -0
- package/dist/chunks/session-store-ChModVcq.js.map +1 -0
- package/dist/chunks/static-files-ehaD1kE7.js +51 -0
- package/dist/chunks/static-files-ehaD1kE7.js.map +1 -0
- package/dist/chunks/streaming-GYIsVTQH.js +560 -0
- package/dist/chunks/streaming-GYIsVTQH.js.map +1 -0
- package/dist/chunks/testing-CUwGj2ie.js +4751 -0
- package/dist/chunks/testing-CUwGj2ie.js.map +1 -0
- package/dist/chunks/vite-QoqrGl6f.js +259 -0
- package/dist/chunks/vite-QoqrGl6f.js.map +1 -0
- package/dist/cli.d.ts +19 -25
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +289 -128
- package/dist/cli.js.map +1 -1
- package/dist/config/define.d.ts +3 -0
- package/dist/config/define.d.ts.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +78 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/load.d.ts +12 -0
- package/dist/config/load.d.ts.map +1 -0
- package/dist/config/types.d.ts +74 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/validate.d.ts +9 -0
- package/dist/config/validate.d.ts.map +1 -0
- package/dist/config/vite.d.ts +12 -0
- package/dist/config/vite.d.ts.map +1 -0
- package/dist/data/cache.d.ts +2 -0
- package/dist/data/cache.d.ts.map +1 -1
- package/dist/data/idempotency.d.ts.map +1 -1
- package/dist/deployment/testing.d.ts +25 -0
- package/dist/deployment/testing.d.ts.map +1 -0
- package/dist/deployment/testing.js +171 -0
- package/dist/deployment/testing.js.map +1 -0
- package/dist/document/hydration.d.ts +9 -0
- package/dist/document/hydration.d.ts.map +1 -1
- package/dist/document/index.d.ts +4 -2
- package/dist/document/index.d.ts.map +1 -1
- package/dist/document/metadata.d.ts +8 -0
- package/dist/document/metadata.d.ts.map +1 -1
- package/dist/document/navigation.d.ts +28 -0
- package/dist/document/navigation.d.ts.map +1 -0
- package/dist/document/render.d.ts +3 -1
- package/dist/document/render.d.ts.map +1 -1
- package/dist/document/seo.d.ts.map +1 -1
- package/dist/edge/assets.d.ts.map +1 -1
- package/dist/edge/index.js +55 -73
- package/dist/edge/index.js.map +1 -1
- package/dist/index.d.ts +12 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1883 -692
- package/dist/index.js.map +1 -1
- package/dist/inspect/command.d.ts +28 -0
- package/dist/inspect/command.d.ts.map +1 -0
- package/dist/inspect/index.d.ts +9 -0
- package/dist/inspect/index.d.ts.map +1 -0
- package/dist/inspect/redact.d.ts +35 -0
- package/dist/inspect/redact.d.ts.map +1 -0
- package/dist/inspect/report.d.ts +24 -0
- package/dist/inspect/report.d.ts.map +1 -0
- package/dist/inspect/types.d.ts +102 -0
- package/dist/inspect/types.d.ts.map +1 -0
- package/dist/internal/testing.js +5 -5
- package/dist/kv/index.d.ts +2 -0
- package/dist/kv/index.d.ts.map +1 -1
- package/dist/kv/index.js +170 -73
- package/dist/kv/index.js.map +1 -1
- package/dist/kv/session-store.d.ts +20 -0
- package/dist/kv/session-store.d.ts.map +1 -0
- package/dist/manifest.d.ts +10 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/node/http.d.ts +5 -0
- package/dist/node/http.d.ts.map +1 -1
- package/dist/node/image.d.ts.map +1 -1
- package/dist/node/index.d.ts +4 -1
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +257 -182
- package/dist/node/index.js.map +1 -1
- package/dist/node/serve.d.ts +47 -0
- package/dist/node/serve.d.ts.map +1 -0
- package/dist/node/static.d.ts.map +1 -1
- package/dist/platform/fonts.d.ts.map +1 -1
- package/dist/platform/image-url.d.ts.map +1 -1
- package/dist/platform/url.d.ts +19 -0
- package/dist/platform/url.d.ts.map +1 -0
- package/dist/platform/web-vitals.d.ts.map +1 -1
- package/dist/redis/index.d.ts +2 -0
- package/dist/redis/index.d.ts.map +1 -1
- package/dist/redis/index.js +186 -69
- package/dist/redis/index.js.map +1 -1
- package/dist/redis/session-store.d.ts +9 -0
- package/dist/redis/session-store.d.ts.map +1 -0
- package/dist/route/index.d.ts +3 -2
- package/dist/route/index.d.ts.map +1 -1
- package/dist/route/mutation.d.ts +97 -0
- package/dist/route/mutation.d.ts.map +1 -0
- package/dist/route/serialization.d.ts +24 -0
- package/dist/route/serialization.d.ts.map +1 -0
- package/dist/route/types.d.ts +6 -1
- package/dist/route/types.d.ts.map +1 -1
- package/dist/route/webhook.d.ts +6 -1
- package/dist/route/webhook.d.ts.map +1 -1
- package/dist/router/manifest.d.ts +8 -0
- package/dist/router/manifest.d.ts.map +1 -1
- package/dist/router/navigation-data.d.ts +9 -1
- package/dist/router/navigation-data.d.ts.map +1 -1
- package/dist/routing/generate.d.ts +3 -0
- package/dist/routing/generate.d.ts.map +1 -1
- package/dist/routing/index.d.ts +3 -1
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/locale.d.ts +43 -0
- package/dist/routing/locale.d.ts.map +1 -0
- package/dist/routing/types.d.ts +12 -0
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/security/audit.d.ts +2 -1
- package/dist/security/audit.d.ts.map +1 -1
- package/dist/security/authorization.d.ts +36 -0
- package/dist/security/authorization.d.ts.map +1 -0
- package/dist/security/cookie-session.d.ts +43 -0
- package/dist/security/cookie-session.d.ts.map +1 -0
- package/dist/security/csrf.d.ts +1 -1
- package/dist/security/csrf.d.ts.map +1 -1
- package/dist/security/env-startup.d.ts +13 -0
- package/dist/security/env-startup.d.ts.map +1 -0
- package/dist/security/env.d.ts +49 -11
- package/dist/security/env.d.ts.map +1 -1
- package/dist/security/exceptions.d.ts +29 -0
- package/dist/security/exceptions.d.ts.map +1 -0
- package/dist/security/finding-codes.d.ts +56 -0
- package/dist/security/finding-codes.d.ts.map +1 -0
- package/dist/security/index.d.ts +14 -3
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/policy.d.ts +2 -5
- package/dist/security/policy.d.ts.map +1 -1
- package/dist/security/report.d.ts +2 -1
- package/dist/security/report.d.ts.map +1 -1
- package/dist/security/request.d.ts +1 -0
- package/dist/security/request.d.ts.map +1 -1
- package/dist/security/session-manager.d.ts +32 -0
- package/dist/security/session-manager.d.ts.map +1 -0
- package/dist/security/session-store.d.ts +51 -0
- package/dist/security/session-store.d.ts.map +1 -0
- package/dist/security/testing.d.ts +10 -0
- package/dist/security/testing.d.ts.map +1 -0
- package/dist/security/testing.js +145 -0
- package/dist/security/testing.js.map +1 -0
- package/dist/security/types.d.ts +139 -5
- package/dist/security/types.d.ts.map +1 -1
- package/dist/security/upload.d.ts +3 -3
- package/dist/security/upload.d.ts.map +1 -1
- package/dist/security/verification.d.ts.map +1 -1
- package/dist/server/document-shell.d.ts.map +1 -1
- package/dist/server/errors.d.ts +1 -0
- package/dist/server/errors.d.ts.map +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/not-found.d.ts +1 -0
- package/dist/server/not-found.d.ts.map +1 -1
- package/dist/server/render-tree.d.ts.map +1 -1
- package/dist/server/request-handler.d.ts +7 -2
- package/dist/server/request-handler.d.ts.map +1 -1
- package/dist/server/request-metadata.d.ts +1 -0
- package/dist/server/request-metadata.d.ts.map +1 -1
- package/dist/server/ssr.d.ts +2 -0
- package/dist/server/ssr.d.ts.map +1 -1
- package/dist/server-only/browser.d.ts +2 -0
- package/dist/server-only/browser.d.ts.map +1 -0
- package/dist/server-only/browser.js +4 -0
- package/dist/server-only/browser.js.map +1 -0
- package/dist/server-only/index.d.ts +2 -0
- package/dist/server-only/index.d.ts.map +1 -0
- package/dist/server-only/index.js +2 -0
- package/dist/server-only/index.js.map +1 -0
- package/dist/static/index.d.ts +2 -0
- package/dist/static/index.d.ts.map +1 -1
- package/dist/static/index.js +380 -363
- package/dist/static/index.js.map +1 -1
- package/dist/static/preview.d.ts.map +1 -1
- package/dist/static/vercel.d.ts +11 -2
- package/dist/static/vercel.d.ts.map +1 -1
- package/dist/static-files.d.ts +12 -0
- package/dist/static-files.d.ts.map +1 -1
- package/dist/type-guards.d.ts +19 -0
- package/dist/type-guards.d.ts.map +1 -0
- package/dist/vite/env-boundary.d.ts +14 -0
- package/dist/vite/env-boundary.d.ts.map +1 -0
- package/dist/vite/index.d.ts +13 -6
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +29 -1560
- package/dist/vite/index.js.map +1 -1
- package/dist/vite/plugin.d.ts +24 -3
- package/dist/vite/plugin.d.ts.map +1 -1
- package/dist/vite/policy-verification.d.ts +33 -2
- package/dist/vite/policy-verification.d.ts.map +1 -1
- package/dist/vite/route-audit.d.ts +14 -2
- package/dist/vite/route-audit.d.ts.map +1 -1
- package/dist/vite/server-only-boundary.d.ts +8 -0
- package/dist/vite/server-only-boundary.d.ts.map +1 -0
- package/package.json +24 -6
- package/dist/chunks/document-shell-WoM8yZlR.js +0 -35
- package/dist/chunks/document-shell-WoM8yZlR.js.map +0 -1
- package/dist/chunks/images-Edar3eU1.js.map +0 -1
- package/dist/chunks/request-metadata-DaIYq4Ea.js +0 -677
- package/dist/chunks/request-metadata-DaIYq4Ea.js.map +0 -1
- package/dist/chunks/static-files-DUjHw-4H.js +0 -11
- package/dist/chunks/static-files-DUjHw-4H.js.map +0 -1
- package/dist/chunks/streaming-D0fGAuiO.js +0 -469
- package/dist/chunks/streaming-D0fGAuiO.js.map +0 -1
- package/dist/chunks/testing-CRflAw4X.js +0 -3475
- package/dist/chunks/testing-CRflAw4X.js.map +0 -1
- package/dist/route/action.d.ts +0 -33
- package/dist/route/action.d.ts.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focus.d.ts","sourceRoot":"","sources":["../../src/browser/focus.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,qBAAqB,EAC1B,KAAK,WAAW,EAEhB,KAAK,WAAW,EAChB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,MAAM,MAAM,yBAAyB,GAAG,OAAO,GAAG;IAChD,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,YAAY,KAAK,IAAI,CAAC;CAC1C,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,OAAO,EAAE,yBAAyB,GAAG,MAAM,IAAI,CAAC;IACzD,KAAK,IAAI,OAAO,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,iBAAiB,iDAG5B,CAAC;AAEH,MAAM,MAAM,uBAAuB,CACjC,GAAG,SAAS,WAAW,GAAG,KAAK,IAC7B;IACF,EAAE,CAAC,EAAE,GAAG,CAAC;CACV,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,UAAU,CAAC,CAAC;AAExD,wBAAgB,qBAAqB,CACnC,QAAQ,SAAS,yBAAyB,GAAG,yBAAyB;;;EAiBvE;AAED,wBAAgB,kBAAkB,CAChC,GAAG,SAAS,WAAW,GAAG,KAAK,EAC/B,KAAK,EAAE,uBAAuB,CAAC,GAAG,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,0FAqB/D"}
|
package/dist/browser/index.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
export { createFileRouter, hydrateFileRouter, Link } from "./file-router";
|
|
1
|
+
export { createFileRouter, Form, hydrateFileRouter, Link, MutationSubmit, useNavigation, useFormNavigation, } from "./file-router";
|
|
2
|
+
export { createMutationAction, useMutationAction } from "./mutation-action";
|
|
3
|
+
export { RouteFocusBoundary, useRouteFocusBoundary, } from "./focus";
|
|
4
|
+
export type { FileRouterOptions, MutationNavigationState, FormProps, LinkProps, MutationSubmitProps, NavigationAccessibility, NavigationCommit, NavigationScrollContext, NavigationScrollOption, } from "./file-router";
|
|
5
|
+
export type { MutationAction, MutationActionOptions, MutationFormAction, MutationResult, } from "./mutation-action";
|
|
6
|
+
export type { MutationValidation } from "../route";
|
|
7
|
+
export type { RouteFocusBoundaryElement, RouteFocusBoundaryProps, } from "./focus";
|
|
2
8
|
export type { HydrateFileRouterOptions } from "./file-router";
|
|
3
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,IAAI,EACJ,iBAAiB,EACjB,IAAI,EACJ,cAAc,EACd,aAAa,EACb,iBAAiB,GAClB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EACL,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,SAAS,CAAC;AACjB,YAAY,EACV,iBAAiB,EACjB,uBAAuB,EACvB,SAAS,EACT,SAAS,EACT,mBAAmB,EACnB,uBAAuB,EACvB,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAClB,cAAc,GACf,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACnD,YAAY,EACV,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { type MutationValidation } from "../route";
|
|
2
|
+
import { type MutationDataFor, type MutationFieldsFor, type MutationMethodFor, type MutationRoute, type PathValue, type PathVarsFor, type RoutePathVars } from "../routing";
|
|
3
|
+
declare const mutationFormActionMetadata: unique symbol;
|
|
4
|
+
declare const mutationFormActionResult: unique symbol;
|
|
5
|
+
export type MutationResult<TData = unknown, TField extends string = string> = {
|
|
6
|
+
version: 1;
|
|
7
|
+
status: "success";
|
|
8
|
+
data?: TData;
|
|
9
|
+
revalidate?: boolean;
|
|
10
|
+
} | {
|
|
11
|
+
version: 1;
|
|
12
|
+
status: "invalid";
|
|
13
|
+
validation: MutationValidation<TField>;
|
|
14
|
+
} | {
|
|
15
|
+
version: 1;
|
|
16
|
+
status: "redirect";
|
|
17
|
+
location: string;
|
|
18
|
+
history: "push" | "replace";
|
|
19
|
+
} | {
|
|
20
|
+
version: 1;
|
|
21
|
+
status: "failed";
|
|
22
|
+
message?: string;
|
|
23
|
+
};
|
|
24
|
+
export type MutationAction<TData = unknown, TField extends string = string> = (previousState: MutationResult<TData, TField> | undefined, formData: FormData) => Promise<MutationResult<TData, TField>>;
|
|
25
|
+
export type MutationFormAction<TData = unknown, TField extends string = string> = ((formData: FormData) => void) & {
|
|
26
|
+
readonly [mutationFormActionMetadata]: {
|
|
27
|
+
method: "POST";
|
|
28
|
+
url: string;
|
|
29
|
+
};
|
|
30
|
+
readonly [mutationFormActionResult]?: MutationResult<TData, TField>;
|
|
31
|
+
};
|
|
32
|
+
type MutationActionPath<TRoute extends MutationRoute> = TRoute extends keyof RoutePathVars & string ? keyof PathVarsFor<TRoute> extends never ? {
|
|
33
|
+
path?: never;
|
|
34
|
+
} : {
|
|
35
|
+
path: PathVarsFor<TRoute>;
|
|
36
|
+
} : {
|
|
37
|
+
path?: Record<string, PathValue>;
|
|
38
|
+
};
|
|
39
|
+
export type MutationActionOptions<TRoute extends MutationRoute, TMethod extends MutationMethodFor<TRoute> = MutationMethodFor<TRoute>> = {
|
|
40
|
+
method: TMethod;
|
|
41
|
+
route: TRoute;
|
|
42
|
+
} & MutationActionPath<TRoute>;
|
|
43
|
+
type MutationRouter = {
|
|
44
|
+
redirect(location: string, history: "push" | "replace", controller: AbortController): void;
|
|
45
|
+
refresh(): Promise<void>;
|
|
46
|
+
};
|
|
47
|
+
export declare function registerMutationRouter(router: MutationRouter): () => void;
|
|
48
|
+
export declare function abortMutationActions(except?: AbortController): void;
|
|
49
|
+
export declare function createMutationAction<TData = never, const TRoute extends MutationRoute = MutationRoute, const TMethod extends MutationMethodFor<TRoute> = MutationMethodFor<TRoute>>(options: MutationActionOptions<TRoute, TMethod>): MutationAction<[
|
|
50
|
+
TData
|
|
51
|
+
] extends [never] ? MutationDataFor<TRoute, TMethod> : TData, MutationFieldsFor<TRoute, TMethod>>;
|
|
52
|
+
export declare function useMutationAction<TData = never, const TRoute extends MutationRoute = MutationRoute, const TMethod extends MutationMethodFor<TRoute> = MutationMethodFor<TRoute>>(options: MutationActionOptions<TRoute, TMethod> & {
|
|
53
|
+
method: TMethod & "POST";
|
|
54
|
+
}, initialState?: MutationResult<[
|
|
55
|
+
TData
|
|
56
|
+
] extends [never] ? MutationDataFor<TRoute, TMethod> : TData, MutationFieldsFor<TRoute, TMethod>>): readonly [MutationResult<[TData] extends [never] ? MutationDataFor<TRoute, TMethod> : TData, MutationFieldsFor<TRoute, TMethod>> | undefined, MutationFormAction<[TData] extends [never] ? MutationDataFor<TRoute, TMethod> : TData, MutationFieldsFor<TRoute, TMethod>>, boolean];
|
|
57
|
+
export declare function mutationFormActionDetails(action: MutationFormAction): {
|
|
58
|
+
method: "POST";
|
|
59
|
+
url: string;
|
|
60
|
+
};
|
|
61
|
+
export declare function submitMutation<TData = unknown, TField extends string = string>(options: {
|
|
62
|
+
body: BodyInit;
|
|
63
|
+
contentType?: string;
|
|
64
|
+
method: string;
|
|
65
|
+
signal: AbortSignal;
|
|
66
|
+
url: string;
|
|
67
|
+
}): Promise<MutationResult<TData, TField>>;
|
|
68
|
+
export declare function performMutationRequest<TData = unknown, TField extends string = string>(options: {
|
|
69
|
+
body: BodyInit;
|
|
70
|
+
contentType?: string;
|
|
71
|
+
method: string;
|
|
72
|
+
signal: AbortSignal;
|
|
73
|
+
url: string;
|
|
74
|
+
}): Promise<{
|
|
75
|
+
response: Response;
|
|
76
|
+
result: MutationResult<TData, TField> | undefined;
|
|
77
|
+
}>;
|
|
78
|
+
export declare function readMutationResult<TData = unknown, TField extends string = string>(response: Response): Promise<MutationResult<TData, TField> | undefined>;
|
|
79
|
+
export declare function validateMutationRedirect(location: string): string | undefined;
|
|
80
|
+
export {};
|
|
81
|
+
//# sourceMappingURL=mutation-action.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutation-action.d.ts","sourceRoot":"","sources":["../../src/browser/mutation-action.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { r as c } from "./index-0MNiR_wo.js";
|
|
2
|
+
const r = '<template data-demiurge-stream-root=""></template>';
|
|
3
|
+
async function i(t, e) {
|
|
4
|
+
const l = c({
|
|
5
|
+
body: { data: t.data, locale: e.locale, navigation: e.navigation },
|
|
6
|
+
dir: e.dir,
|
|
7
|
+
entrySrc: e.clientEntry,
|
|
8
|
+
lang: e.lang,
|
|
9
|
+
links: t.links,
|
|
10
|
+
metadata: t.metadata,
|
|
11
|
+
nonce: e.nonce,
|
|
12
|
+
scripts: e.scripts ?? t.scripts,
|
|
13
|
+
styles: e.styles,
|
|
14
|
+
title: e.title
|
|
15
|
+
});
|
|
16
|
+
if (!e.transformDocument)
|
|
17
|
+
return l;
|
|
18
|
+
const a = await e.transformDocument(
|
|
19
|
+
`${l.prefix}${r}${l.suffix}`
|
|
20
|
+
), n = a.indexOf(r);
|
|
21
|
+
if (n === -1 || a.indexOf(
|
|
22
|
+
r,
|
|
23
|
+
n + r.length
|
|
24
|
+
) !== -1)
|
|
25
|
+
throw new Error(
|
|
26
|
+
"Demiurge streaming document transform must preserve the root marker exactly once."
|
|
27
|
+
);
|
|
28
|
+
return {
|
|
29
|
+
prefix: a.slice(0, n),
|
|
30
|
+
suffix: a.slice(n + r.length)
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
i as c
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=document-shell-9GPwtcTt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-shell-9GPwtcTt.js","sources":["../../src/server/document-shell.ts"],"sourcesContent":["import { renderDocumentShell } from \"../document/render\";\nimport type { ScriptTag } from \"../document/scripts\";\nimport type { LoadedRouteMatch } from \"../router\";\nimport type { SsrRenderOptions } from \"./ssr\";\n\n// A streaming render sends the document head before the body exists. A\n// transform that rewrites the document therefore needs a placeholder where the\n// streamed body will go, and it has to leave that placeholder in place.\nexport const STREAM_ROOT_MARKER =\n '<template data-demiurge-stream-root=\"\"></template>';\n\nexport type DocumentShell = {\n prefix: string;\n suffix: string;\n};\n\nexport async function createDocumentShell(\n match: LoadedRouteMatch,\n options: SsrRenderOptions & { scripts?: ScriptTag[] },\n): Promise<DocumentShell> {\n const shell = renderDocumentShell({\n body: { data: match.data, locale: options.locale, navigation: options.navigation },\n dir: options.dir,\n entrySrc: options.clientEntry,\n lang: options.lang,\n links: match.links,\n metadata: match.metadata,\n nonce: options.nonce,\n scripts: options.scripts ?? match.scripts,\n styles: options.styles,\n title: options.title,\n });\n\n if (!options.transformDocument) {\n return shell;\n }\n\n const transformed = await options.transformDocument(\n `${shell.prefix}${STREAM_ROOT_MARKER}${shell.suffix}`,\n );\n const markerIndex = transformed.indexOf(STREAM_ROOT_MARKER);\n\n if (\n markerIndex === -1 ||\n transformed.indexOf(\n STREAM_ROOT_MARKER,\n markerIndex + STREAM_ROOT_MARKER.length,\n ) !== -1\n ) {\n throw new Error(\n \"Demiurge streaming document transform must preserve the root marker exactly once.\",\n );\n }\n\n return {\n prefix: transformed.slice(0, markerIndex),\n suffix: transformed.slice(markerIndex + STREAM_ROOT_MARKER.length),\n };\n}\n"],"names":["STREAM_ROOT_MARKER","createDocumentShell","match","options","shell","renderDocumentShell","transformed","markerIndex"],"mappings":";AAQO,MAAMA,IACX;AAOF,eAAsBC,EACpBC,GACAC,GACwB;AACxB,QAAMC,IAAQC,EAAoB;AAAA,IAChC,MAAM,EAAE,MAAMH,EAAM,MAAM,QAAQC,EAAQ,QAAQ,YAAYA,EAAQ,WAAA;AAAA,IACtE,KAAKA,EAAQ;AAAA,IACb,UAAUA,EAAQ;AAAA,IAClB,MAAMA,EAAQ;AAAA,IACd,OAAOD,EAAM;AAAA,IACb,UAAUA,EAAM;AAAA,IAChB,OAAOC,EAAQ;AAAA,IACf,SAASA,EAAQ,WAAWD,EAAM;AAAA,IAClC,QAAQC,EAAQ;AAAA,IAChB,OAAOA,EAAQ;AAAA,EAAA,CAChB;AAED,MAAI,CAACA,EAAQ;AACX,WAAOC;AAGT,QAAME,IAAc,MAAMH,EAAQ;AAAA,IAChC,GAAGC,EAAM,MAAM,GAAGJ,CAAkB,GAAGI,EAAM,MAAM;AAAA,EAAA,GAE/CG,IAAcD,EAAY,QAAQN,CAAkB;AAE1D,MACEO,MAAgB,MAChBD,EAAY;AAAA,IACVN;AAAA,IACAO,IAAcP,EAAmB;AAAA,EAAA,MAC7B;AAEN,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAIJ,SAAO;AAAA,IACL,QAAQM,EAAY,MAAM,GAAGC,CAAW;AAAA,IACxC,QAAQD,EAAY,MAAMC,IAAcP,EAAmB,MAAM;AAAA,EAAA;AAErE;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash as d } from "node:crypto";
|
|
2
2
|
import { readFile as h, mkdir as p, writeFile as F } from "node:fs/promises";
|
|
3
3
|
import { resolve as u, join as w, relative as b, sep as $ } from "node:path";
|
|
4
|
-
import { d as v, f as S, a as N, r as E, b as J, c as O, i as j } from "./images-
|
|
4
|
+
import { d as v, f as S, a as N, r as E, b as J, c as O, i as j } from "./images-CG7ZzayG.js";
|
|
5
5
|
const y = 5 * 1024 * 1024;
|
|
6
6
|
async function H(e) {
|
|
7
7
|
const t = e.fonts ?? [];
|
|
@@ -138,4 +138,4 @@ export {
|
|
|
138
138
|
H as r,
|
|
139
139
|
q as t
|
|
140
140
|
};
|
|
141
|
-
//# sourceMappingURL=image-codec-
|
|
141
|
+
//# sourceMappingURL=image-codec-Dh1POFhE.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-codec-Di53WpcH.js","sources":["../../src/platform/font-assets.ts","../../src/platform/image-codec.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join, relative, resolve, sep } from \"node:path\";\nimport {\n defaultFontPath,\n fontAssetFileName,\n fontFormat,\n fontMediaType,\n fontStylesheetUrl,\n renderFontFaceCss,\n type FontContribution,\n type FontDefinition,\n} from \"./fonts\";\n\nexport type FontAssetFetch = (\n input: string,\n init?: { signal?: AbortSignal },\n) => Promise<Response>;\n\nexport type FontAssetOptions = {\n basePath?: string;\n // Where a downloaded font file stays between builds. A build that already\n // downloaded a font reads it back and makes no network request.\n cacheDir?: string;\n fetch?: FontAssetFetch;\n fonts?: FontContribution;\n // The project directory that every local font source resolves against.\n root: string;\n};\n\nexport type FontAsset = {\n body: Uint8Array;\n contentType: string;\n // The output path, relative to the directory that the build publishes.\n file: string;\n url: string;\n};\n\nconst maximumFontBytes = 5 * 1024 * 1024;\n\n// One font declaration becomes one published file plus one stylesheet. The\n// build writes these files, and the Node handler serves the same set from\n// memory. Both derive every URL from the declaration, so they cannot drift.\nexport async function resolveFontAssets(\n options: FontAssetOptions,\n): Promise<FontAsset[]> {\n const fonts = options.fonts ?? [];\n\n if (fonts.length === 0) {\n return [];\n }\n\n const basePath = options.basePath ?? defaultFontPath;\n const root = resolve(options.root);\n const cacheDir = resolve(\n options.cacheDir ?? join(root, \"node_modules\", \".demiurge\", \"fonts\"),\n );\n const load = options.fetch ?? ((input, init) => fetch(input, init));\n const published = new Map<string, string>();\n const assets: FontAsset[] = [];\n\n for (const definition of fonts) {\n if (!definition.selfHost) {\n continue;\n }\n\n const name = fontAssetFileName(definition);\n const claimed = published.get(name);\n\n if (claimed !== undefined) {\n if (claimed !== definition.src) {\n throw new Error(\n `Font family ${JSON.stringify(definition.family)} declares two sources that publish the same file ${JSON.stringify(name)}. Give one of them a different weight or style.`,\n );\n }\n\n continue;\n }\n\n published.set(name, definition.src);\n assets.push({\n body: await readFontBody(definition, { cacheDir, load, root }),\n contentType: fontMediaType(definition.src),\n file: outputFile(basePath, name),\n url: `${basePath}/${name}`,\n });\n }\n\n const stylesheet = `${renderFontFaceCss(fonts, basePath)}\\n`;\n\n assets.push({\n body: new TextEncoder().encode(stylesheet),\n contentType: \"text/css; charset=utf-8\",\n file: outputFile(basePath, \"fonts.css\"),\n url: fontStylesheetUrl(basePath),\n });\n\n return assets;\n}\n\nasync function readFontBody(\n definition: FontDefinition,\n context: { cacheDir: string; load: FontAssetFetch; root: string },\n) {\n const body = definition.source === \"google\"\n ? await downloadFontFile(definition, context)\n : await readLocalFontFile(definition, context.root);\n\n if (body.byteLength === 0) {\n throw new Error(\n `Font family ${JSON.stringify(definition.family)} resolved to an empty file.`,\n );\n }\n\n if (body.byteLength > maximumFontBytes) {\n throw new Error(\n `Font family ${JSON.stringify(definition.family)} is larger than the ${maximumFontBytes} byte limit.`,\n );\n }\n\n return body;\n}\n\nasync function readLocalFontFile(definition: FontDefinition, root: string) {\n const file = resolve(root, definition.src.replace(/^\\/+/, \"\"));\n\n if (relative(root, file).split(sep).includes(\"..\")) {\n throw new Error(\n `Font source escaped the project directory: ${JSON.stringify(definition.src)}.`,\n );\n }\n\n try {\n return new Uint8Array(await readFile(file));\n } catch (error) {\n throw new Error(\n `Demiurge could not read the font file ${JSON.stringify(definition.src)} for family ${JSON.stringify(definition.family)}.`,\n { cause: error },\n );\n }\n}\n\n// A downloaded font stays in the cache directory. The first build reaches the\n// font host once, and every later build reads the file from disk. A build that\n// runs without network access therefore keeps working.\nasync function downloadFontFile(\n definition: FontDefinition,\n context: { cacheDir: string; load: FontAssetFetch; root: string },\n) {\n const digest = createHash(\"sha256\").update(definition.src).digest(\"hex\");\n const cacheFile = join(\n context.cacheDir,\n `${digest.slice(0, 32)}.${fontFormat(definition.src)}`,\n );\n\n try {\n return new Uint8Array(await readFile(cacheFile));\n } catch {\n // The cache holds no copy yet, so the font host answers this once.\n }\n\n let response: Response;\n\n try {\n response = await context.load(definition.src);\n } catch (error) {\n throw new Error(\n `Demiurge could not download the font for family ${JSON.stringify(definition.family)} from ${JSON.stringify(definition.src)}.`,\n { cause: error },\n );\n }\n\n if (!response.ok) {\n throw new Error(\n `The font host answered ${response.status} for family ${JSON.stringify(definition.family)} at ${JSON.stringify(definition.src)}.`,\n );\n }\n\n const body = new Uint8Array(await response.arrayBuffer());\n\n await mkdir(context.cacheDir, { recursive: true });\n await writeFile(cacheFile, body);\n\n return body;\n}\n\nfunction outputFile(basePath: string, name: string) {\n return `${basePath.replace(/^\\/+/, \"\")}/${name}`;\n}\n","import type { ImageFormat } from \"./images\";\nimport { imageSourceExtension, type ImageVariantDescriptor } from \"./image-url\";\n\nexport type EncodedImage = {\n body: Uint8Array;\n contentType: string;\n};\n\ntype SharpModule = {\n default: (input: Uint8Array) => SharpPipeline;\n};\n\ntype SharpPipeline = {\n avif: (options: { quality: number }) => SharpPipeline;\n jpeg: (options: { quality: number }) => SharpPipeline;\n png: () => SharpPipeline;\n resize: (options: {\n width: number;\n withoutEnlargement: boolean;\n }) => SharpPipeline;\n toBuffer: () => Promise<Buffer>;\n webp: (options: { quality: number }) => SharpPipeline;\n};\n\nconst contentTypes: Record<Exclude<ImageFormat, \"auto\">, string> = {\n avif: \"image/avif\",\n jpeg: \"image/jpeg\",\n png: \"image/png\",\n webp: \"image/webp\",\n};\n\nconst defaultQuality = 75;\n\nexport function imageContentType(format: Exclude<ImageFormat, \"auto\">) {\n return contentTypes[format];\n}\n\n// `auto` lets the browser take the smallest format that it accepts. A client\n// that sends no usable `accept` header keeps the source format.\nexport function negotiateImageFormat(\n descriptor: ImageVariantDescriptor,\n accept: string | null,\n): Exclude<ImageFormat, \"auto\"> {\n if (descriptor.format !== \"auto\") {\n return descriptor.format;\n }\n\n const accepted = (accept ?? \"\").toLowerCase();\n\n if (accepted.includes(\"image/avif\")) {\n return \"avif\";\n }\n\n if (accepted.includes(\"image/webp\")) {\n return \"webp\";\n }\n\n return sourceFormat(descriptor.src);\n}\n\nexport function sourceFormat(src: string): Exclude<ImageFormat, \"auto\"> {\n const extension = imageSourceExtension(src);\n\n if (extension === \"avif\") {\n return \"avif\";\n }\n\n if (extension === \"webp\") {\n return \"webp\";\n }\n\n if (extension === \"png\") {\n return \"png\";\n }\n\n return \"jpeg\";\n}\n\nexport async function transformImage(\n source: Uint8Array,\n options: {\n format: Exclude<ImageFormat, \"auto\">;\n quality?: number;\n width: number;\n },\n): Promise<EncodedImage> {\n const sharp = await loadImageCodec();\n const quality = options.quality ?? defaultQuality;\n const resized = sharp(source).resize({\n width: options.width,\n withoutEnlargement: true,\n });\n\n return {\n body: new Uint8Array(await encode(resized, options.format, quality)),\n contentType: contentTypes[options.format],\n };\n}\n\nfunction encode(\n pipeline: SharpPipeline,\n format: Exclude<ImageFormat, \"auto\">,\n quality: number,\n) {\n if (format === \"png\") {\n return pipeline.png().toBuffer();\n }\n\n if (format === \"jpeg\") {\n return pipeline.jpeg({ quality }).toBuffer();\n }\n\n if (format === \"avif\") {\n return pipeline.avif({ quality }).toBuffer();\n }\n\n return pipeline.webp({ quality }).toBuffer();\n}\n\n// `sharp` is an optional peer dependency. Only an application that optimizes\n// an image installs it, the same rule that ADR 0006 states for a host\n// adapter dependency.\nasync function loadImageCodec() {\n let module: SharpModule;\n\n try {\n // TYPE-EVIDENCE: sharp ships no types. The local type describes the methods the codec calls.\n module = (await import(\"sharp\")) as SharpModule;\n } catch (error) {\n throw new Error(\n \"Demiurge image optimization requires the optional peer dependency sharp. Install sharp in the application.\",\n { cause: error },\n );\n }\n\n return module.default;\n}\n"],"names":["maximumFontBytes","resolveFontAssets","options","fonts","basePath","defaultFontPath","root","resolve","cacheDir","join","load","input","init","published","assets","definition","name","fontAssetFileName","claimed","readFontBody","fontMediaType","outputFile","stylesheet","renderFontFaceCss","fontStylesheetUrl","context","body","downloadFontFile","readLocalFontFile","file","relative","sep","readFile","error","digest","createHash","cacheFile","fontFormat","response","mkdir","writeFile","contentTypes","defaultQuality","negotiateImageFormat","descriptor","accept","accepted","sourceFormat","src","extension","imageSourceExtension","transformImage","source","sharp","loadImageCodec","quality","resized","encode","pipeline","format","module"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"image-codec-Dh1POFhE.js","sources":["../../src/platform/font-assets.ts","../../src/platform/image-codec.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join, relative, resolve, sep } from \"node:path\";\nimport {\n defaultFontPath,\n fontAssetFileName,\n fontFormat,\n fontMediaType,\n fontStylesheetUrl,\n renderFontFaceCss,\n type FontContribution,\n type FontDefinition,\n} from \"./fonts\";\n\nexport type FontAssetFetch = (\n input: string,\n init?: { signal?: AbortSignal },\n) => Promise<Response>;\n\nexport type FontAssetOptions = {\n basePath?: string;\n // Where a downloaded font file stays between builds. A build that already\n // downloaded a font reads it back and makes no network request.\n cacheDir?: string;\n fetch?: FontAssetFetch;\n fonts?: FontContribution;\n // The project directory that every local font source resolves against.\n root: string;\n};\n\nexport type FontAsset = {\n body: Uint8Array;\n contentType: string;\n // The output path, relative to the directory that the build publishes.\n file: string;\n url: string;\n};\n\nconst maximumFontBytes = 5 * 1024 * 1024;\n\n// One font declaration becomes one published file plus one stylesheet. The\n// build writes these files, and the Node handler serves the same set from\n// memory. Both derive every URL from the declaration, so they cannot drift.\nexport async function resolveFontAssets(\n options: FontAssetOptions,\n): Promise<FontAsset[]> {\n const fonts = options.fonts ?? [];\n\n if (fonts.length === 0) {\n return [];\n }\n\n const basePath = options.basePath ?? defaultFontPath;\n const root = resolve(options.root);\n const cacheDir = resolve(\n options.cacheDir ?? join(root, \"node_modules\", \".demiurge\", \"fonts\"),\n );\n const load = options.fetch ?? ((input, init) => fetch(input, init));\n const published = new Map<string, string>();\n const assets: FontAsset[] = [];\n\n for (const definition of fonts) {\n if (!definition.selfHost) {\n continue;\n }\n\n const name = fontAssetFileName(definition);\n const claimed = published.get(name);\n\n if (claimed !== undefined) {\n if (claimed !== definition.src) {\n throw new Error(\n `Font family ${JSON.stringify(definition.family)} declares two sources that publish the same file ${JSON.stringify(name)}. Give one of them a different weight or style.`,\n );\n }\n\n continue;\n }\n\n published.set(name, definition.src);\n assets.push({\n body: await readFontBody(definition, { cacheDir, load, root }),\n contentType: fontMediaType(definition.src),\n file: outputFile(basePath, name),\n url: `${basePath}/${name}`,\n });\n }\n\n const stylesheet = `${renderFontFaceCss(fonts, basePath)}\\n`;\n\n assets.push({\n body: new TextEncoder().encode(stylesheet),\n contentType: \"text/css; charset=utf-8\",\n file: outputFile(basePath, \"fonts.css\"),\n url: fontStylesheetUrl(basePath),\n });\n\n return assets;\n}\n\nasync function readFontBody(\n definition: FontDefinition,\n context: { cacheDir: string; load: FontAssetFetch; root: string },\n) {\n const body = definition.source === \"google\"\n ? await downloadFontFile(definition, context)\n : await readLocalFontFile(definition, context.root);\n\n if (body.byteLength === 0) {\n throw new Error(\n `Font family ${JSON.stringify(definition.family)} resolved to an empty file.`,\n );\n }\n\n if (body.byteLength > maximumFontBytes) {\n throw new Error(\n `Font family ${JSON.stringify(definition.family)} is larger than the ${maximumFontBytes} byte limit.`,\n );\n }\n\n return body;\n}\n\nasync function readLocalFontFile(definition: FontDefinition, root: string) {\n const file = resolve(root, definition.src.replace(/^\\/+/, \"\"));\n\n if (relative(root, file).split(sep).includes(\"..\")) {\n throw new Error(\n `Font source escaped the project directory: ${JSON.stringify(definition.src)}.`,\n );\n }\n\n try {\n return new Uint8Array(await readFile(file));\n } catch (error) {\n throw new Error(\n `Demiurge could not read the font file ${JSON.stringify(definition.src)} for family ${JSON.stringify(definition.family)}.`,\n { cause: error },\n );\n }\n}\n\n// A downloaded font stays in the cache directory. The first build reaches the\n// font host once, and every later build reads the file from disk. A build that\n// runs without network access therefore keeps working.\nasync function downloadFontFile(\n definition: FontDefinition,\n context: { cacheDir: string; load: FontAssetFetch; root: string },\n) {\n const digest = createHash(\"sha256\").update(definition.src).digest(\"hex\");\n const cacheFile = join(\n context.cacheDir,\n `${digest.slice(0, 32)}.${fontFormat(definition.src)}`,\n );\n\n try {\n return new Uint8Array(await readFile(cacheFile));\n } catch {\n // The cache holds no copy yet, so the font host answers this once.\n }\n\n let response: Response;\n\n try {\n response = await context.load(definition.src);\n } catch (error) {\n throw new Error(\n `Demiurge could not download the font for family ${JSON.stringify(definition.family)} from ${JSON.stringify(definition.src)}.`,\n { cause: error },\n );\n }\n\n if (!response.ok) {\n throw new Error(\n `The font host answered ${response.status} for family ${JSON.stringify(definition.family)} at ${JSON.stringify(definition.src)}.`,\n );\n }\n\n const body = new Uint8Array(await response.arrayBuffer());\n\n await mkdir(context.cacheDir, { recursive: true });\n await writeFile(cacheFile, body);\n\n return body;\n}\n\nfunction outputFile(basePath: string, name: string) {\n return `${basePath.replace(/^\\/+/, \"\")}/${name}`;\n}\n","import type { ImageFormat } from \"./images\";\nimport { imageSourceExtension, type ImageVariantDescriptor } from \"./image-url\";\n\nexport type EncodedImage = {\n body: Uint8Array;\n contentType: string;\n};\n\ntype SharpModule = {\n default: (input: Uint8Array) => SharpPipeline;\n};\n\ntype SharpPipeline = {\n avif: (options: { quality: number }) => SharpPipeline;\n jpeg: (options: { quality: number }) => SharpPipeline;\n png: () => SharpPipeline;\n resize: (options: {\n width: number;\n withoutEnlargement: boolean;\n }) => SharpPipeline;\n toBuffer: () => Promise<Buffer>;\n webp: (options: { quality: number }) => SharpPipeline;\n};\n\nconst contentTypes: Record<Exclude<ImageFormat, \"auto\">, string> = {\n avif: \"image/avif\",\n jpeg: \"image/jpeg\",\n png: \"image/png\",\n webp: \"image/webp\",\n};\n\nconst defaultQuality = 75;\n\nexport function imageContentType(format: Exclude<ImageFormat, \"auto\">) {\n return contentTypes[format];\n}\n\n// `auto` lets the browser take the smallest format that it accepts. A client\n// that sends no usable `accept` header keeps the source format.\nexport function negotiateImageFormat(\n descriptor: ImageVariantDescriptor,\n accept: string | null,\n): Exclude<ImageFormat, \"auto\"> {\n if (descriptor.format !== \"auto\") {\n return descriptor.format;\n }\n\n const accepted = (accept ?? \"\").toLowerCase();\n\n if (accepted.includes(\"image/avif\")) {\n return \"avif\";\n }\n\n if (accepted.includes(\"image/webp\")) {\n return \"webp\";\n }\n\n return sourceFormat(descriptor.src);\n}\n\nexport function sourceFormat(src: string): Exclude<ImageFormat, \"auto\"> {\n const extension = imageSourceExtension(src);\n\n if (extension === \"avif\") {\n return \"avif\";\n }\n\n if (extension === \"webp\") {\n return \"webp\";\n }\n\n if (extension === \"png\") {\n return \"png\";\n }\n\n return \"jpeg\";\n}\n\nexport async function transformImage(\n source: Uint8Array,\n options: {\n format: Exclude<ImageFormat, \"auto\">;\n quality?: number;\n width: number;\n },\n): Promise<EncodedImage> {\n const sharp = await loadImageCodec();\n const quality = options.quality ?? defaultQuality;\n const resized = sharp(source).resize({\n width: options.width,\n withoutEnlargement: true,\n });\n\n return {\n body: new Uint8Array(await encode(resized, options.format, quality)),\n contentType: contentTypes[options.format],\n };\n}\n\nfunction encode(\n pipeline: SharpPipeline,\n format: Exclude<ImageFormat, \"auto\">,\n quality: number,\n) {\n if (format === \"png\") {\n return pipeline.png().toBuffer();\n }\n\n if (format === \"jpeg\") {\n return pipeline.jpeg({ quality }).toBuffer();\n }\n\n if (format === \"avif\") {\n return pipeline.avif({ quality }).toBuffer();\n }\n\n return pipeline.webp({ quality }).toBuffer();\n}\n\n// `sharp` is an optional peer dependency. Only an application that optimizes\n// an image installs it, the same rule that ADR 0006 states for a host\n// adapter dependency.\nasync function loadImageCodec() {\n let module: SharpModule;\n\n try {\n // TYPE-EVIDENCE: sharp ships no types. The local type describes the methods the codec calls.\n module = (await import(\"sharp\")) as SharpModule;\n } catch (error) {\n throw new Error(\n \"Demiurge image optimization requires the optional peer dependency sharp. Install sharp in the application.\",\n { cause: error },\n );\n }\n\n return module.default;\n}\n"],"names":["maximumFontBytes","resolveFontAssets","options","fonts","basePath","defaultFontPath","root","resolve","cacheDir","join","load","input","init","published","assets","definition","name","fontAssetFileName","claimed","readFontBody","fontMediaType","outputFile","stylesheet","renderFontFaceCss","fontStylesheetUrl","context","body","downloadFontFile","readLocalFontFile","file","relative","sep","readFile","error","digest","createHash","cacheFile","fontFormat","response","mkdir","writeFile","contentTypes","defaultQuality","negotiateImageFormat","descriptor","accept","accepted","sourceFormat","src","extension","imageSourceExtension","transformImage","source","sharp","loadImageCodec","quality","resized","encode","pipeline","format","module"],"mappings":"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"}
|
|
@@ -1,20 +1,27 @@
|
|
|
1
|
-
import { p as
|
|
2
|
-
|
|
1
|
+
import { p as P } from "./index-0MNiR_wo.js";
|
|
2
|
+
function j(t) {
|
|
3
|
+
return t.split("?")[0].split("#")[0];
|
|
4
|
+
}
|
|
5
|
+
function v(t) {
|
|
6
|
+
const e = j(t).split("/").at(-1);
|
|
7
|
+
return e.includes(".") ? e.split(".").at(-1).toLowerCase() : "";
|
|
8
|
+
}
|
|
9
|
+
const u = "/_demiurge/font", k = {
|
|
3
10
|
otf: "otf",
|
|
4
11
|
ttf: "ttf",
|
|
5
12
|
woff: "woff",
|
|
6
13
|
woff2: "woff2"
|
|
7
|
-
},
|
|
14
|
+
}, x = {
|
|
8
15
|
otf: "opentype",
|
|
9
16
|
ttf: "truetype",
|
|
10
17
|
woff: "woff",
|
|
11
18
|
woff2: "woff2"
|
|
12
|
-
},
|
|
19
|
+
}, E = {
|
|
13
20
|
otf: "font/otf",
|
|
14
21
|
ttf: "font/ttf",
|
|
15
22
|
woff: "font/woff",
|
|
16
23
|
woff2: "font/woff2"
|
|
17
|
-
},
|
|
24
|
+
}, G = {
|
|
18
25
|
// A Google font needs the file URL that the Google stylesheet points at.
|
|
19
26
|
// The framework reads no third-party stylesheet, because that request is
|
|
20
27
|
// the privacy cost self-hosting removes.
|
|
@@ -57,58 +64,58 @@ const u = "/_demiurge/font", j = {
|
|
|
57
64
|
};
|
|
58
65
|
}
|
|
59
66
|
};
|
|
60
|
-
function
|
|
67
|
+
function B(t) {
|
|
61
68
|
return [...t];
|
|
62
69
|
}
|
|
63
|
-
function
|
|
70
|
+
function N(t) {
|
|
64
71
|
const e = p(t.family), r = p(String(t.weight));
|
|
65
72
|
return `${e}-${r}-${t.style}.${m(t.src)}`;
|
|
66
73
|
}
|
|
67
|
-
function
|
|
68
|
-
return t.selfHost ? `${e}/${
|
|
74
|
+
function I(t, e = u) {
|
|
75
|
+
return t.selfHost ? `${e}/${N(t)}` : t.src;
|
|
69
76
|
}
|
|
70
|
-
function
|
|
77
|
+
function F(t = u) {
|
|
71
78
|
return `${t}/fonts.css`;
|
|
72
79
|
}
|
|
73
|
-
function
|
|
74
|
-
return
|
|
80
|
+
function R(t) {
|
|
81
|
+
return E[m(t)];
|
|
75
82
|
}
|
|
76
83
|
function m(t) {
|
|
77
|
-
const e =
|
|
78
|
-
if (!
|
|
84
|
+
const e = k[v(t)];
|
|
85
|
+
if (!e)
|
|
79
86
|
throw new Error(
|
|
80
87
|
`Font source ${JSON.stringify(t)} has no known font extension.`
|
|
81
88
|
);
|
|
82
|
-
return
|
|
89
|
+
return e;
|
|
83
90
|
}
|
|
84
|
-
function
|
|
91
|
+
function X(t, e = u) {
|
|
85
92
|
return t.length === 0 ? [] : [
|
|
86
93
|
{
|
|
87
|
-
href:
|
|
94
|
+
href: F(e),
|
|
88
95
|
kind: "link",
|
|
89
96
|
rel: "stylesheet"
|
|
90
97
|
},
|
|
91
|
-
...
|
|
98
|
+
...L(t, e)
|
|
92
99
|
];
|
|
93
100
|
}
|
|
94
|
-
function
|
|
101
|
+
function L(t, e = u) {
|
|
95
102
|
return t.map(
|
|
96
|
-
(r) =>
|
|
103
|
+
(r) => P(I(r, e), {
|
|
97
104
|
as: "font",
|
|
98
105
|
// A font request runs in CORS mode even on the same origin. A preload
|
|
99
106
|
// without this attribute fetches the file twice.
|
|
100
107
|
crossOrigin: "anonymous",
|
|
101
|
-
type:
|
|
108
|
+
type: R(r.src)
|
|
102
109
|
})
|
|
103
110
|
);
|
|
104
111
|
}
|
|
105
|
-
function
|
|
112
|
+
function Y(t, e = u) {
|
|
106
113
|
return t.map((r) => {
|
|
107
|
-
const n =
|
|
114
|
+
const n = I(r, e);
|
|
108
115
|
return [
|
|
109
116
|
"@font-face {",
|
|
110
117
|
` font-family: "${$(r.family)}";`,
|
|
111
|
-
` src: url("${$(n)}") format("${
|
|
118
|
+
` src: url("${$(n)}") format("${x[m(r.src)]}");`,
|
|
112
119
|
` font-style: ${r.style};`,
|
|
113
120
|
` font-weight: ${r.weight};`,
|
|
114
121
|
` font-display: ${r.display};`,
|
|
@@ -118,7 +125,7 @@ function B(t, e = u) {
|
|
|
118
125
|
}).join(`
|
|
119
126
|
`);
|
|
120
127
|
}
|
|
121
|
-
function
|
|
128
|
+
function Z(t) {
|
|
122
129
|
const e = /* @__PURE__ */ new Set();
|
|
123
130
|
for (const r of t)
|
|
124
131
|
r.selfHost || e.add(new URL(r.src).origin);
|
|
@@ -136,80 +143,80 @@ function p(t) {
|
|
|
136
143
|
function $(t) {
|
|
137
144
|
return t.replace(/[\\"]/g, "\\$&");
|
|
138
145
|
}
|
|
139
|
-
const
|
|
146
|
+
const z = "/_demiurge/image", O = {
|
|
140
147
|
avif: "avif",
|
|
141
148
|
jpeg: "jpg",
|
|
142
149
|
png: "png",
|
|
143
150
|
webp: "webp"
|
|
144
|
-
},
|
|
151
|
+
}, S = {
|
|
145
152
|
avif: "avif",
|
|
146
153
|
jpeg: "jpeg",
|
|
147
154
|
jpg: "jpeg",
|
|
148
155
|
png: "png",
|
|
149
156
|
webp: "webp"
|
|
150
|
-
},
|
|
151
|
-
function
|
|
157
|
+
}, U = /^(.+)\.w(\d{1,5})(?:\.q(\d{1,3}))?\.([a-z0-9]+)$/;
|
|
158
|
+
function T(t, e) {
|
|
152
159
|
const r = new URLSearchParams({
|
|
153
160
|
src: t.src,
|
|
154
161
|
w: String(t.width)
|
|
155
162
|
});
|
|
156
163
|
return t.quality !== void 0 && r.set("q", String(t.quality)), t.format !== "auto" && r.set("f", t.format), `${e}?${r.toString()}`;
|
|
157
164
|
}
|
|
158
|
-
function
|
|
165
|
+
function W(t, e) {
|
|
159
166
|
if (t.sourceKind === "remote")
|
|
160
167
|
throw new Error(
|
|
161
168
|
`Image source ${JSON.stringify(t.src)} is remote. A static image loader can only emit a local image.`
|
|
162
169
|
);
|
|
163
170
|
const r = t.quality === void 0 ? "" : `.q${t.quality}`;
|
|
164
|
-
return `${e}${t.src}.w${t.width}${r}.${
|
|
171
|
+
return `${e}${t.src}.w${t.width}${r}.${V(t)}`;
|
|
165
172
|
}
|
|
166
|
-
function
|
|
173
|
+
function tt(t, e) {
|
|
167
174
|
if (!t.startsWith(`${e}/`))
|
|
168
175
|
return;
|
|
169
|
-
const r =
|
|
176
|
+
const r = U.exec(t.slice(e.length));
|
|
170
177
|
if (!r)
|
|
171
178
|
return;
|
|
172
|
-
const [, n, a, s,
|
|
173
|
-
if (!(!i || !
|
|
179
|
+
const [, n, a, s, f] = r, i = S[f], l = Number(a), o = s === void 0 ? void 0 : Number(s);
|
|
180
|
+
if (!(!i || !b(n) || l <= 0 || o !== void 0 && (o < 1 || o > 100)))
|
|
174
181
|
return { format: i, quality: o, sourceKind: "local", src: n, width: l };
|
|
175
182
|
}
|
|
176
|
-
function
|
|
183
|
+
function V(t) {
|
|
177
184
|
if (t.format !== "auto")
|
|
178
|
-
return
|
|
179
|
-
const e =
|
|
185
|
+
return O[t.format];
|
|
186
|
+
const e = b(t.src);
|
|
180
187
|
if (!e)
|
|
181
188
|
throw new Error(
|
|
182
189
|
`Image source ${JSON.stringify(t.src)} has no known image extension. Declare an explicit format.`
|
|
183
190
|
);
|
|
184
191
|
return e === "jpeg" ? "jpg" : e;
|
|
185
192
|
}
|
|
186
|
-
function
|
|
187
|
-
const e = t
|
|
188
|
-
return
|
|
193
|
+
function b(t) {
|
|
194
|
+
const e = v(t);
|
|
195
|
+
return e in S ? e : void 0;
|
|
189
196
|
}
|
|
190
|
-
function
|
|
197
|
+
function et(t, e) {
|
|
191
198
|
const r = new RegExp(
|
|
192
|
-
`${
|
|
199
|
+
`${A(e)}/[^"'\\s,)<>]+`,
|
|
193
200
|
"g"
|
|
194
201
|
);
|
|
195
202
|
return [...new Set(t.match(r) ?? [])];
|
|
196
203
|
}
|
|
197
|
-
function
|
|
204
|
+
function A(t) {
|
|
198
205
|
return t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
199
206
|
}
|
|
200
|
-
function
|
|
207
|
+
function rt(t) {
|
|
201
208
|
return t;
|
|
202
209
|
}
|
|
203
|
-
function
|
|
210
|
+
function nt(t, e = {}) {
|
|
204
211
|
return h(t, e) !== null;
|
|
205
212
|
}
|
|
206
|
-
function
|
|
213
|
+
function at(t, e = {}) {
|
|
207
214
|
const r = h(t.src, e);
|
|
208
215
|
if (!r)
|
|
209
216
|
throw new Error(`Image source "${t.src}" is not allowed by the image policy.`);
|
|
210
|
-
g("width", t.width), g("height", t.height),
|
|
211
|
-
const n = t.format ?? "auto", a = e.loader ?? "optimizer", s = e.optimizerPath ??
|
|
212
|
-
const
|
|
217
|
+
g("width", t.width), g("height", t.height), M(t.quality);
|
|
218
|
+
const n = t.format ?? "auto", a = e.loader ?? "optimizer", s = e.optimizerPath ?? z, i = Q(t.width, t.widths).map((o) => {
|
|
219
|
+
const q = Math.round(t.height / t.width * o), w = {
|
|
213
220
|
format: n,
|
|
214
221
|
quality: t.quality,
|
|
215
222
|
sourceKind: r.kind,
|
|
@@ -218,8 +225,8 @@ function rt(t, e = {}) {
|
|
|
218
225
|
};
|
|
219
226
|
return {
|
|
220
227
|
format: n,
|
|
221
|
-
height:
|
|
222
|
-
src: a === "static" ?
|
|
228
|
+
height: q,
|
|
229
|
+
src: a === "static" ? W(w, s) : T(w, s),
|
|
223
230
|
width: o
|
|
224
231
|
};
|
|
225
232
|
}), l = i[0];
|
|
@@ -246,64 +253,64 @@ function h(t, e) {
|
|
|
246
253
|
} catch {
|
|
247
254
|
return null;
|
|
248
255
|
}
|
|
249
|
-
return r.protocol !== "https:" && r.protocol !== "http:" ? null :
|
|
256
|
+
return r.protocol !== "https:" && r.protocol !== "http:" ? null : H(r, e.remote ?? []) ? { kind: "remote", src: r.toString() } : null;
|
|
250
257
|
}
|
|
251
|
-
function
|
|
258
|
+
function H(t, e) {
|
|
252
259
|
return e.some(
|
|
253
|
-
(r) => typeof r == "string" ?
|
|
260
|
+
(r) => typeof r == "string" ? J(t, r) : K(t, r)
|
|
254
261
|
);
|
|
255
262
|
}
|
|
256
|
-
function
|
|
263
|
+
function J(t, e) {
|
|
257
264
|
try {
|
|
258
265
|
return t.origin === new URL(e).origin;
|
|
259
266
|
} catch {
|
|
260
267
|
return !1;
|
|
261
268
|
}
|
|
262
269
|
}
|
|
263
|
-
function
|
|
264
|
-
return e.protocol && t.protocol !== e.protocol || t.hostname !== e.hostname || e.port !== void 0 && t.port !== e.port ? !1 : e.pathname ?
|
|
270
|
+
function K(t, e) {
|
|
271
|
+
return e.protocol && t.protocol !== e.protocol || t.hostname !== e.hostname || e.port !== void 0 && t.port !== e.port ? !1 : e.pathname ? C(t.pathname, e.pathname) : !0;
|
|
265
272
|
}
|
|
266
|
-
function
|
|
273
|
+
function C(t, e) {
|
|
267
274
|
return e.endsWith("*") ? t.startsWith(e.slice(0, -1)) : t === e;
|
|
268
275
|
}
|
|
269
276
|
function g(t, e) {
|
|
270
277
|
if (!Number.isInteger(e) || e <= 0)
|
|
271
278
|
throw new Error(`Image ${t} must be a positive integer.`);
|
|
272
279
|
}
|
|
273
|
-
function
|
|
280
|
+
function M(t) {
|
|
274
281
|
if (t !== void 0 && (!Number.isInteger(t) || t < 1 || t > 100))
|
|
275
282
|
throw new Error("Image quality must be an integer between 1 and 100.");
|
|
276
283
|
}
|
|
277
|
-
function
|
|
284
|
+
function Q(t, e) {
|
|
278
285
|
const r = e ?? [t, t * 2], n = [...new Set(r)];
|
|
279
286
|
for (const a of n)
|
|
280
287
|
g("width", a);
|
|
281
288
|
return n.sort((a, s) => a - s);
|
|
282
289
|
}
|
|
283
|
-
const
|
|
290
|
+
const D = /* @__PURE__ */ new Set([
|
|
284
291
|
"avif",
|
|
285
292
|
"jpeg",
|
|
286
293
|
"png",
|
|
287
294
|
"webp"
|
|
288
295
|
]);
|
|
289
|
-
function
|
|
296
|
+
function ot(t, e = {}) {
|
|
290
297
|
const r = t.searchParams.get("src");
|
|
291
298
|
if (!r)
|
|
292
|
-
return
|
|
299
|
+
return c(400, "The image request must declare a src parameter.");
|
|
293
300
|
const n = h(r, e);
|
|
294
301
|
if (!n)
|
|
295
|
-
return
|
|
302
|
+
return c(403, "The image policy does not allow this image source.");
|
|
296
303
|
const a = Number(t.searchParams.get("w"));
|
|
297
304
|
if (!Number.isInteger(a) || a <= 0)
|
|
298
|
-
return
|
|
299
|
-
const s = t.searchParams.get("q"),
|
|
300
|
-
if (
|
|
301
|
-
return
|
|
305
|
+
return c(400, "The image width must be a positive integer.");
|
|
306
|
+
const s = t.searchParams.get("q"), f = s === null ? void 0 : Number(s);
|
|
307
|
+
if (f !== void 0 && (!Number.isInteger(f) || f < 1 || f > 100))
|
|
308
|
+
return c(400, "The image quality must be an integer from 1 through 100.");
|
|
302
309
|
const i = t.searchParams.get("f");
|
|
303
|
-
return i !== null && !
|
|
310
|
+
return i !== null && !D.has(i) ? c(400, "The image format is not supported.") : {
|
|
304
311
|
descriptor: {
|
|
305
312
|
format: i ?? "auto",
|
|
306
|
-
quality:
|
|
313
|
+
quality: f,
|
|
307
314
|
sourceKind: n.kind,
|
|
308
315
|
src: n.src,
|
|
309
316
|
width: a
|
|
@@ -311,29 +318,30 @@ function nt(t, e = {}) {
|
|
|
311
318
|
ok: !0
|
|
312
319
|
};
|
|
313
320
|
}
|
|
314
|
-
function
|
|
321
|
+
function c(t, e) {
|
|
315
322
|
return { ok: !1, rejection: { reason: e, status: t } };
|
|
316
323
|
}
|
|
317
324
|
export {
|
|
318
|
-
|
|
319
|
-
|
|
325
|
+
R as a,
|
|
326
|
+
F as b,
|
|
320
327
|
m as c,
|
|
321
328
|
u as d,
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
329
|
+
z as e,
|
|
330
|
+
N as f,
|
|
331
|
+
et as g,
|
|
332
|
+
nt as h,
|
|
333
|
+
b as i,
|
|
334
|
+
ot as j,
|
|
335
|
+
at as k,
|
|
336
|
+
B as l,
|
|
337
|
+
rt as m,
|
|
338
|
+
G as n,
|
|
339
|
+
I as o,
|
|
340
|
+
tt as p,
|
|
341
|
+
X as q,
|
|
342
|
+
Y as r,
|
|
343
|
+
L as s,
|
|
344
|
+
Z as t,
|
|
345
|
+
j as u
|
|
338
346
|
};
|
|
339
|
-
//# sourceMappingURL=images-
|
|
347
|
+
//# sourceMappingURL=images-CG7ZzayG.js.map
|