-
-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Close #25
- Loading branch information
Showing
12 changed files
with
276 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,6 +46,7 @@ | |
"Guppe", | ||
"halfyear", | ||
"hongminhee", | ||
"hono", | ||
"httpsig", | ||
"jsonld", | ||
"keypair", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"recommendations": [ | ||
"denoland.vscode-deno" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
{ | ||
"deno.enable": true, | ||
"deno.lint": true, | ||
"files.eol": "\n", | ||
"files.insertFinalNewline": true, | ||
"files.trimFinalNewlines": true, | ||
"git.openRepositoryInParentFolders": "never", | ||
"[javascript]": { | ||
"editor.defaultFormatter": "denoland.vscode-deno", | ||
"editor.formatOnSave": true | ||
}, | ||
"[javascriptreact]": { | ||
"editor.defaultFormatter": "denoland.vscode-deno", | ||
"editor.formatOnSave": true | ||
}, | ||
"[json]": { | ||
"editor.defaultFormatter": "vscode.json-language-features", | ||
"editor.formatOnSave": true | ||
}, | ||
"[jsonc]": { | ||
"editor.defaultFormatter": "vscode.json-language-features", | ||
"editor.formatOnSave": true | ||
}, | ||
"[typescript]": { | ||
"editor.defaultFormatter": "denoland.vscode-deno", | ||
"editor.formatOnSave": true, | ||
"editor.codeActionsOnSave": { | ||
"source.sortImports": "always" | ||
} | ||
}, | ||
"[typescriptreact]": { | ||
"editor.defaultFormatter": "denoland.vscode-deno", | ||
"editor.formatOnSave": true | ||
}, | ||
"cSpell.words": [ | ||
"deno", | ||
"fedi", | ||
"fedify", | ||
"hono" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
Hono integration sample | ||
======================= | ||
|
||
This project is a sample application that demonstrates how to integrate Fedify | ||
with [Hono], a web server framework in TypeScript. | ||
|
||
To run the sample: | ||
|
||
~~~~ command | ||
deno task start | ||
~~~~ | ||
|
||
The sample application will be available at <http://localhost:8000/>. | ||
|
||
[Hono]: https://hono.dev/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"importMap": "./import_map.g.json", | ||
"tasks": { | ||
"generate-import-map": "deno run --allow-read --allow-write generate_import_map.ts", | ||
"codegen": "deno task generate-import-map", | ||
"start": "deno task codegen && deno run -A main.ts" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
const fedifyImportMap = JSON.parse( | ||
await Deno.readTextFile(`${import.meta.dirname}/../../deno.json`), | ||
).imports; | ||
|
||
const blogImportMap = JSON.parse( | ||
await Deno.readTextFile(`${import.meta.dirname}/import_map.json`), | ||
).imports; | ||
|
||
const importMap = { ...fedifyImportMap, ...blogImportMap }; | ||
|
||
await Deno.writeTextFile( | ||
`${import.meta.dirname}/import_map.g.json`, | ||
JSON.stringify({ imports: importMap }, null, 2) + "\n", | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
{ | ||
"imports": { | ||
"@cfworker/json-schema": "npm:@cfworker/json-schema@^1.12.8", | ||
"@david/which-runtime": "jsr:@david/which-runtime@^0.2.0", | ||
"@deno/dnt": "jsr:@deno/dnt@^0.41.1", | ||
"@fedify/fedify": "../../mod.ts", | ||
"@fedify/fedify/federation": "../../federation/mod.ts", | ||
"@fedify/fedify/httpsig": "../../httpsig/mod.ts", | ||
"@fedify/fedify/nodeinfo": "./nodeinfo/mod.ts", | ||
"@fedify/fedify/runtime": "../../runtime/mod.ts", | ||
"@fedify/fedify/vocab": "../../vocab/mod.ts", | ||
"@fedify/fedify/webfinger": "../../webfinger/mod.ts", | ||
"@fedify/fedify/x/fresh": "./x/fresh.ts", | ||
"@hongminhee/aitertools": "jsr:@hongminhee/aitertools@^0.6.0", | ||
"@js-temporal/polyfill": "npm:@js-temporal/polyfill@^0.4.4", | ||
"@phensley/language-tag": "npm:@phensley/language-tag@^1.8.0", | ||
"@std/assert": "jsr:@std/assert@^0.220.1", | ||
"@std/async/delay": "jsr:@std/async@^0.220.1/delay", | ||
"@std/bytes": "jsr:@std/bytes@^0.220.1", | ||
"@std/collections": "jsr:@std/collections@^0.220.1", | ||
"@std/encoding": "jsr:@std/encoding@^0.220.1", | ||
"@std/encoding/base64": "jsr:@std/encoding@^0.220.1/base64", | ||
"@std/fs": "jsr:@std/fs@^0.220.1", | ||
"@std/http/negotiation": "jsr:@std/http@^0.220.1/negotiation", | ||
"@std/json/common": "jsr:@std/json@^0.220.1/common", | ||
"@std/path": "jsr:@std/path@^0.220.1", | ||
"@std/semver": "jsr:@std/semver@^0.220.1", | ||
"@std/testing": "jsr:@std/testing@^0.220.1", | ||
"@std/text": "jsr:@std/text@^0.220.1", | ||
"@std/url": "jsr:@std/url@^0.220.1", | ||
"@std/yaml": "jsr:@std/yaml@^0.220.1", | ||
"fast-check": "npm:fast-check@^3.17.0", | ||
"jsonld": "npm:jsonld@^8.3.2", | ||
"mock_fetch": "https://deno.land/x/[email protected]/mod.ts", | ||
"uri-template-router": "npm:uri-template-router@^0.0.16", | ||
"url-template": "npm:url-template@^3.1.1", | ||
"@fedify/fedify/x/denokv": "../../x/denokv.ts", | ||
"@fedify/fedify/x/hono": "../../x/hono.ts", | ||
"hono": "https://deno.land/x/[email protected]/mod.ts" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"imports": { | ||
"@fedify/fedify": "../../mod.ts", | ||
"@fedify/fedify/federation": "../../federation/mod.ts", | ||
"@fedify/fedify/httpsig": "../../httpsig/mod.ts", | ||
"@fedify/fedify/runtime": "../../runtime/mod.ts", | ||
"@fedify/fedify/vocab": "../../vocab/mod.ts", | ||
"@fedify/fedify/webfinger": "../../webfinger/mod.ts", | ||
"@fedify/fedify/x/denokv": "../../x/denokv.ts", | ||
"@fedify/fedify/x/hono": "../../x/hono.ts", | ||
"hono": "https://deno.land/x/[email protected]/mod.ts" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { Federation, MemoryKvStore } from "@fedify/fedify/federation"; | ||
import { Person } from "@fedify/fedify/vocab"; | ||
import { federation } from "@fedify/fedify/x/hono"; | ||
import { Hono } from "hono"; | ||
|
||
const fedi = new Federation<void>({ | ||
kv: new MemoryKvStore(), | ||
}); | ||
|
||
fedi.setActorDispatcher("/{handle}", (ctx, handle, _key) => { | ||
if (handle !== "sample") return null; | ||
return new Person({ | ||
id: ctx.getActorUri(handle), | ||
name: "Sample", | ||
preferredUsername: handle, | ||
}); | ||
}); | ||
|
||
const app = new Hono(); | ||
app.use(federation(fedi, () => undefined)); | ||
app.get("/", (c) => c.redirect("/sample")); | ||
app.get("/sample", (c) => c.text("Hi, I am Sample!\n")); | ||
|
||
if (import.meta.main) Deno.serve(app.fetch.bind(app)); | ||
|
||
export default app; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
/** | ||
* Fedify with Hono | ||
* ================ | ||
* | ||
* This module provides a [Hono] middleware to integrate with the Fedify. | ||
* | ||
* [Hono]: https://hono.dev/ | ||
* | ||
* @module | ||
* @since 0.6.0 | ||
*/ | ||
import type { | ||
Federation, | ||
FederationFetchOptions, | ||
} from "../federation/middleware.ts"; | ||
|
||
interface HonoRequest { | ||
raw: Request; | ||
} | ||
|
||
interface HonoContext { | ||
req: HonoRequest; | ||
res: Response; | ||
} | ||
|
||
type HonoMiddleware<THonoContext extends HonoContext> = ( | ||
ctx: THonoContext, | ||
next: () => Promise<void>, | ||
) => Promise<Response | void>; | ||
|
||
/** | ||
* A factory function to create a context data for the {@link Federation} | ||
* object. | ||
* | ||
* @typeParam TContextData A type of the context data for the {@link Federation} | ||
* object. | ||
* @typeParam THonoContext A type of the Hono context. | ||
* @param context A Hono context object. | ||
* @returns A context data for the {@link Federation} object. | ||
*/ | ||
export type ContextDataFactory<TContextData, THonoContext> = ( | ||
context: THonoContext, | ||
) => TContextData | Promise<TContextData>; | ||
|
||
/** | ||
* Create a Hono middleware to integrate with the {@link Federation} object. | ||
* | ||
* @typeParam TContextData A type of the context data for the {@link Federation} | ||
* object. | ||
* @typeParam THonoContext A type of the Hono context. | ||
* @param federation A {@link Federation} object to integrate with Hono. | ||
* @param contextDataFactory A function to create a context data for the | ||
* {@link Federation} object. | ||
* @returns A Hono middleware. | ||
*/ | ||
export function federation<TContextData, THonoContext extends HonoContext>( | ||
federation: Federation<TContextData>, | ||
contextDataFactory: ContextDataFactory<TContextData, THonoContext>, | ||
): HonoMiddleware<THonoContext> { | ||
return async (ctx, next) => { | ||
let contextData = contextDataFactory(ctx); | ||
if (contextData instanceof Promise) contextData = await contextData; | ||
return await federation.fetch(ctx.req.raw, { | ||
contextData, | ||
...integrateFetchOptions(ctx, next), | ||
}); | ||
}; | ||
} | ||
|
||
function integrateFetchOptions<THonoContext extends HonoContext>( | ||
ctx: THonoContext, | ||
next: () => Promise<void>, | ||
): Omit<FederationFetchOptions<void>, "contextData"> { | ||
return { | ||
// If the `federation` object finds a request not responsible for it | ||
// (i.e., not a federation-related request), it will call the `next` | ||
// provided by the Hono framework to continue the request handling | ||
// by the Hono: | ||
async onNotFound(_req: Request): Promise<Response> { | ||
await next(); | ||
return ctx.res; | ||
}, | ||
|
||
// 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 `next` | ||
// provided by the Hono 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 Hono to share the same routes | ||
// and they do content negotiation depending on `Accept` header: | ||
async onNotAcceptable(_req: Request): Promise<Response> { | ||
await next(); | ||
if (ctx.res.status !== 404) return ctx.res; | ||
return new Response("Not acceptable", { | ||
status: 406, | ||
headers: { | ||
"Content-Type": "text/plain", | ||
Vary: "Accept", | ||
}, | ||
}); | ||
}, | ||
}; | ||
} |