diff --git a/CHANGES.md b/CHANGES.md index 9f6d927..4996da4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -61,6 +61,11 @@ To be released. - Added `CreateFederationOptions.tracerProvider` option. + - Added `@fedify/fedify/x/sveltekit` module for integrating with [SvelteKit] + hook. [[#171], [#183] by Jiyu Park] + + - Added `fedifyHook()` function. + - The scaffold project generated by `fedify init` command now enables tracing data into log messages. @@ -68,10 +73,14 @@ To be released. [[#173], [#186] by PGD] +[SvelteKit]: https://kit.svelte.dev/ [#162]: https://github.com/dahlia/fedify/issues/162 +[#171]: https://github.com/dahlia/fedify/issues/171 [#173]: https://github.com/dahlia/fedify/issues/173 +[#183]: https://github.com/dahlia/fedify/pull/183 [#186]: https://github.com/dahlia/fedify/pull/186 + Version 1.2.8 ------------- @@ -87,7 +96,6 @@ Released on November 23, 2024. [#177]: https://github.com/dahlia/fedify/issues/177 [#181]: https://github.com/dahlia/fedify/pull/181 - - Support SvelteKit integrations. [[#183]] Version 1.2.7 ------------- @@ -2557,4 +2565,4 @@ Version 0.1.0 Initial release. Released on March 8, 2024. - + diff --git a/docs/manual/integration.md b/docs/manual/integration.md index 48c7622..896f0ff 100644 --- a/docs/manual/integration.md +++ b/docs/manual/integration.md @@ -191,6 +191,32 @@ export const handler = integrateHandler( [Fresh]: https://fresh.deno.dev/ +SvelteKit +--------- + +*This API is available since Fedify 1.3.0.* + +[SvelteKit] is a framework for building web applications with [Svelte]. Fedify +has the `@fedify/fedify/x/sveltekit` module that provides a hook handler to +integrate Fedify with SvelteKit. Put the following code in your +*hooks.server.ts* file: + +~~~~ typescript +import { createFederation } from "@fedify/fedify"; +import { fedifyHook } from "@fedify/fedify/x/sveltekit"; + +const federation = createFederation({ + // Omitted for brevity; see the related section for details. +}); + +// This is the entry point to the Fedify hook from the SvelteKit framework: +export const handle = fedifyHook(federation, (req) => "context data"); +~~~~ + +[SvelteKit]: https://kit.svelte.dev/ +[Svelte]: https://svelte.dev/ + + Custom middleware ----------------- diff --git a/src/x/sveltekit.ts b/src/x/sveltekit.ts index 59fc14e..3e658d8 100644 --- a/src/x/sveltekit.ts +++ b/src/x/sveltekit.ts @@ -1,12 +1,13 @@ /** * Fedify with SvelteKit - * ================ + * ===================== * - * This module provides a [SvelteKit] middleware to integrate with the Fedify. + * This module provides a [SvelteKit] hook to integrate with the Fedify. * - * [SvelteKit]: https://svelte.dev/ + * [SvelteKit]: https://kit.svelte.dev/ * * @module + * @since 1.3.0 */ import type { @@ -24,11 +25,12 @@ type HookParams = { }; /** - * Create a SvelteKit hook handler to integrate with the {@link Federation} object. + * Create a SvelteKit hook handler to integrate with the {@link Federation} + * object. * * @example hooks.server.ts * ``` typescript - * import { federation } from "federation.ts"; // Import the `Federation` object + * import { federation } from "./federation"; // Import the `Federation` object * * export const handle = fedifyHook(federation, () => undefined); * ``` @@ -39,48 +41,47 @@ type HookParams = { * @param createContextData A function to create a context data for the * {@link Federation} object. * @returns A SvelteKit hook handler. + * @since 1.3.0 */ -export const fedifyHook = ( +export function fedifyHook( federation: Federation, createContextData: ( event: RequestEvent, ) => TContextData | Promise, -) => { +): (params: HookParams) => Promise { return async ({ event, resolve }: HookParams) => { return await federation.fetch(event.request, { contextData: await createContextData(event), ...integrateFetchOptions({ event, resolve }), }); }; -}; +} -const integrateFetchOptions = ( +function integrateFetchOptions( { event, resolve }: HookParams, -): Omit, "contextData"> => ({ - // If the `federation` object finds a request not responsible for it - // (i.e., not a federation-related request), it will call the `resolve` - // provided by the SvelteKit framework to continue the request handling - // by the SvelteKit: - async onNotFound(): Promise { - return await resolve(event); - }, +): Omit, "contextData"> { + return { + async onNotFound(): Promise { + return await resolve(event); + }, - // Similar to `onNotFound`, but slightly more tricky one. - // When the `federation` object finds a request not acceptable type-wise - // (i.e., a user-agent doesn't want JSON-LD), it will call the `resolve` - // provided by the SvelteKit framework so that it renders HTML if there's some - // page. Otherwise, it will simply return a 406 Not Acceptable response. - // This kind of trick enables the Fedify and SvelteKit to share the same routes - // and they do content negotiation depending on `Accept` header: - async onNotAcceptable(): Promise { - const res = await resolve(event); - if (res.status !== 404) return res; - return new Response("Not acceptable", { - status: 406, - headers: { - "Content-Type": "text/plain", - Vary: "Accept", - }, - }); - }, -}); + // Similar to `onNotFound`, but slightly more tricky one. + // When the `federation` object finds a request not acceptable type-wise + // (i.e., a user-agent doesn't want JSON-LD), it will call the `resolve` + // provided by the SvelteKit framework so that it renders HTML if there's some + // page. Otherwise, it will simply return a 406 Not Acceptable response. + // This kind of trick enables the Fedify and SvelteKit to share the same routes + // and they do content negotiation depending on `Accept` header: + async onNotAcceptable(): Promise { + const res = await resolve(event); + if (res.status !== 404) return res; + return new Response("Not acceptable", { + status: 406, + headers: { + "Content-Type": "text/plain", + Vary: "Accept", + }, + }); + }, + }; +}