Unverified Commit fb2366f2 authored by Hong Minhee (洪 民憙)'s avatar Hong Minhee (洪 民憙) Committed by GitHub
Browse files

Merge pull request #183 from robin-maki/integration/svelte

parents e1affcfb a6eb8599
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -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
-------------

@@ -2556,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 −0
Original line number Diff line number Diff line
@@ -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
-----------------

+3 −1
Original line number Diff line number Diff line
@@ -12,7 +12,8 @@
    "./webfinger": "./webfinger/mod.ts",
    "./x/denokv": "./x/denokv.ts",
    "./x/fresh": "./x/fresh.ts",
    "./x/hono": "./x/hono.ts"
    "./x/hono": "./x/hono.ts",
    "./x/sveltekit": "./x/sveltekit.ts"
  },
  "imports": {
    "@cfworker/json-schema": "npm:@cfworker/json-schema@^2.0.1",
@@ -28,6 +29,7 @@
    "@fedify/fedify/x/denokv": "./x/denokv.ts",
    "@fedify/fedify/x/fresh": "./x/fresh.ts",
    "@fedify/fedify/x/hono": "./x/hono.ts",
    "@fedify/fedify/x/sveltekit": "./x/sveltekit.ts",
    "@hongminhee/aitertools": "jsr:@hongminhee/aitertools@^0.6.0",
    "@hugoalh/http-header-link": "jsr:@hugoalh/http-header-link@^1.0.2",
    "@logtape/logtape": "jsr:@logtape/logtape@^0.8.0",

src/x/sveltekit.ts

0 → 100644
+87 −0
Original line number Diff line number Diff line
/**
 * Fedify with SvelteKit
 * =====================
 *
 * This module provides a [SvelteKit] hook to integrate with the Fedify.
 *
 * [SvelteKit]: https://kit.svelte.dev/
 *
 * @module
 * @since 1.3.0
 */

import type {
  Federation,
  FederationFetchOptions,
} from "../federation/federation.ts";

type RequestEvent = {
  request: Request;
};

type HookParams = {
  event: RequestEvent;
  resolve: (event: RequestEvent) => Promise<Response>;
};

/**
 * Create a SvelteKit hook handler to integrate with the {@link Federation}
 * object.
 *
 * @example hooks.server.ts
 * ``` typescript
 * import { federation } from "./federation"; // Import the `Federation` object
 *
 * export const handle = fedifyHook(federation, () => undefined);
 * ```
 *
 * @typeParam TContextData A type of the context data for the {@link Federation}
 *                         object.
 * @param federation A {@link Federation} object to integrate with SvelteKit.
 * @param createContextData A function to create a context data for the
 *                          {@link Federation} object.
 * @returns A SvelteKit hook handler.
 * @since 1.3.0
 */
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 }),
    });
  };
}

function integrateFetchOptions(
  { event, resolve }: HookParams,
): 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",
        },
      });
    },
  };
}