Skip to content

Commit

Permalink
Adjust style and changelog, and add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
dahlia committed Nov 23, 2024
1 parent 5cb637f commit a6eb859
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 38 deletions.
12 changes: 10 additions & 2 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,26 @@ 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.

- Let the `fedify lookup` command take multiple arguments.
[[#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
-------------

Expand All @@ -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
-------------
Expand Down Expand Up @@ -2557,4 +2565,4 @@ Version 0.1.0

Initial release. Released on March 8, 2024.

<!-- cSpell: ignore Dogeon Fabien Wressell Emelia Hana Heesun Kyunghee -->
<!-- cSpell: ignore Dogeon Fabien Wressell Emelia Hana Heesun Kyunghee Jiyu -->
26 changes: 26 additions & 0 deletions docs/manual/integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>({
// 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
-----------------

Expand Down
73 changes: 37 additions & 36 deletions src/x/sveltekit.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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);
* ```
Expand All @@ -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 = <TContextData>(
export function fedifyHook<TContextData>(
federation: Federation<TContextData>,
createContextData: (
event: RequestEvent,
) => TContextData | Promise<TContextData>,
) => {
): (params: HookParams) => Promise<Response> {
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<FederationFetchOptions<void>, "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<Response> {
return await resolve(event);
},
): Omit<FederationFetchOptions<void>, "contextData"> {
return {
async onNotFound(): Promise<Response> {
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<Response> {
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<Response> {
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",
},
});
},
};
}

0 comments on commit a6eb859

Please sign in to comment.