Loading docs/manual/federation.md +23 −6 Original line number Diff line number Diff line Loading @@ -45,9 +45,15 @@ that the `Federation` object uses to store several kinds of cache data and to maintain the queue of outgoing activities. `KvStore` is an abstract interface that represents a key-value store. Currently, there is only one implementation of `KvStore`, which is the `MemoryKvStore` class, but you can define your own `KvStore` implementation if you want to use a different key-value store. Currently, there are two implementations of `KvStore`, which are the `MemoryKvStore` and `DenoKvStore` classes. The `MemoryKvStore` class is for testing and development purposes, and the `DenoKvStore` class is Deno KV-backed implementation for production use (as you can guess from the name, it is only available in Deno runtime). However, you can define your own `KvStore` implementation if you want to use a different key-value store.[^1] [^1]: We are welcome to contributions of `KvStore` implementations for other key-value stores. ### `kvPrefixes` Loading @@ -71,9 +77,20 @@ If you don't provide this option, activities will not be queued and will be sent immediately. `MessageQueue` is an abstract interface that represents a message queue. Currently, there is only one implementation of `MessageQueue`, which is the `InProcessMessageQueue` class, but you can define your own `MessageQueue` implementation if you want to use a different message queue. Currently, there are only two implementations of `MessageQueue`, which are the `InProcessMessageQueue` and `DenoKvMessageQueue` classes. The `InProcessMessageQueue` class is for testing and development purposes, and the `DenoKvMessageQueue` class is a Deno KV-backed implementation for production use (as you can guess from the name, it is only available in Deno runtime). However, you can define your own `MessageQueue` implementation if you want to use a different message queue.[^1] > [!IMPORTANT] > While the `queue` option is optional, it is highly recommended to provide > a message queue implementation in production environments. If you don't > provide a message queue implementation, activities will not be queued and > will be sent immediately. This can make delivery of activities unreliable > and can cause performance issues. ### `documentLoader` Loading docs/tutorial.md +31 −27 Original line number Diff line number Diff line Loading @@ -145,10 +145,10 @@ ActivityPub activities and actors. Let's modify the server script to use the `Federation` object: ~~~~ typescript import { Federation } from "@fedify/fedify"; import { Federation, MemoryKvStore } from "@fedify/fedify"; const federation = new Federation<void>({ kv: await Deno.openKv(), kv: new MemoryKvStore(), }); ~~~~ Loading @@ -156,23 +156,12 @@ In the above code, we import the `Federation` object from the Fedify framework and create a new `Federation` object. We pass an object to the `new Federation()` constructor, which is the configuration object. The `kv` property is a key-value store that is used to store several internal data of the `Federation` object. We use the [`Deno.openKv()`] function to open data of the `Federation` object. We use the `MemoryKvStore` to open a key-value store. > [!NOTE] > Since the `Deno.openKv()` function is one of the unstable APIs in Deno as of > March 2024, you need to specify the `"unstable": ["kv"]` field in > the *deno.json* file to use the `Deno.openKv()` function. The *deno.json* > file should look like this: > > ~~~~ json > { > "imports": { > "@fedify/fedify": "jsr:@fedify/fedify@^0.3.0" > }, > "unstable": ["kv"] > } > ~~~~ > [!IMPORTANT] > Since `MemoryKvStore` is for testing and development purposes, you should > use a persistent key-value store like [`DenoKvStore`] for production use. Then, we pass the incoming `Request` to the `federation.handle()` method: Loading Loading @@ -217,10 +206,10 @@ like). Let's create an actor dispatcher for our server: ~~~~ typescript import { Federation, Person } from "@fedify/fedify"; import { Federation, MemoryKvStore, Person } from "@fedify/fedify"; const federation = new Federation<void>({ kv: await Deno.openKv(), kv: new MemoryKvStore(), }); federation.setActorDispatcher("/users/{handle}", async (ctx, handle) => { Loading Loading @@ -371,7 +360,7 @@ set the `treatHttps` property to `true` in the `Federation` object: ~~~~ typescript const federation = new Federation<void>({ kv: await Deno.openKv(), kv: new MemoryKvStore(), treatHttps: true, // Treat HTTP requests as HTTPS }); ~~~~ Loading Loading @@ -417,7 +406,7 @@ represents the `Follow` activity. We will use the `Follow` class to handle incoming follow requests: ~~~~ typescript import { Federation, Follow, Person } from "@fedify/fedify"; import { Federation, Follow, Person, MemoryKvStore } from "@fedify/fedify"; ~~~~ Then, we register an inbox listener for the `Follow` activity: Loading Loading @@ -493,7 +482,7 @@ Fedify provides helper functions to generate and export/import keys: ~~~~ typescript import { Federation, Follow, Person, Federation, Follow, Person, MemoryKvStore, // Import helper functions: exportJwk, generateCryptoKeyPair, importJwk, } from "@fedify/fedify"; Loading @@ -513,11 +502,6 @@ should be chained after the `Federation.setActorDispatcher()` method: ~~~~ typescript const kv = await Deno.openKv(); // Open the key-value store const federation = new Federation<void>({ kv, treatHttps: true, }); federation .setActorDispatcher("/users/{handle}", async (ctx, handle, key) => { if (handle !== "me") return null; Loading Loading @@ -564,6 +548,26 @@ at the first time and store it in the key-value store. When the actor *me* is dispatched again, the key pair dispatcher loads the key pair from the key-value store. > [!IMPORTANT] > In the above code, we use the `Deno.openKv()` function to open the key-value > store, which is persistent. However, Deno KV is an unstable feature as of > March 2024, so you need to add the `"unstable": ["kv"]` field to the > *deno.json* file: > > ~~~~ json > { > "imports": { > "@fedify/fedify": "jsr:@fedify/fedify@^0.4.0" > }, > "unstable": ["kv"] > } > ~~~~ > [!NOTE] > Although we use the Deno KV database in this tutorial, you can use any > other your favorite database to store the key pair. The key-value store > is just an example. Restart the server and make an HTTP request to the actor *me* using `curl`. Now you should see the actor *me* with the public key in the response: Loading examples/blog/.vscode/settings.json +1 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ "activitypub", "codegen", "deno", "denokv", "docloader", "fedify", "fediverse", Loading examples/blog/federation/mod.ts +5 −7 Original line number Diff line number Diff line import { Temporal } from "@js-temporal/polyfill"; import { parse } from "@std/semver"; import { dirname, join } from "@std/path"; import { Federation, InProcessMessageQueue, MemoryKvStore, } from "@fedify/fedify/federation"; import { Federation } from "@fedify/fedify/federation"; import { Accept, Activity, Loading @@ -19,6 +15,7 @@ import { Person, Undo, } from "@fedify/fedify/vocab"; import { DenoKvMessageQueue, DenoKvStore } from "@fedify/fedify/x/denokv"; import { getBlog } from "../models/blog.ts"; import { addComment, Comment, getComments } from "../models/comment.ts"; import { Loading @@ -28,15 +25,16 @@ import { removeFollower, } from "../models/follower.ts"; import { countPosts, getPosts, toArticle } from "../models/post.ts"; import { openKv } from "../models/kv.ts"; // The `Federation<TContextData>` object is a registry that registers // federation-related callbacks: export const federation = new Federation<void>({ // The following key-value storage is used for internal cache: kv: new MemoryKvStore(), kv: new DenoKvStore(await openKv()), // The following message queue is used for maintaining outgoing activities: queue: new InProcessMessageQueue(), queue: new DenoKvMessageQueue(await openKv()), // The following option is useful for local development, as Fresh's dev // server does not support HTTPS: Loading examples/blog/import_map.g.json +2 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ "@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", Loading @@ -37,6 +38,7 @@ "@preact/signals": "https://esm.sh/*@preact/signals@1.2.2", "@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.5.1", "@std/dotenv/load": "jsr:@std/dotenv@^0.220.1/load", "@fedify/fedify/x/denokv": "../../x/denokv.ts", "markdown-it": "npm:markdown-it@^14.0.0", "preact": "https://esm.sh/preact@10.19.6", "preact/": "https://esm.sh/preact@10.19.6/", Loading Loading
docs/manual/federation.md +23 −6 Original line number Diff line number Diff line Loading @@ -45,9 +45,15 @@ that the `Federation` object uses to store several kinds of cache data and to maintain the queue of outgoing activities. `KvStore` is an abstract interface that represents a key-value store. Currently, there is only one implementation of `KvStore`, which is the `MemoryKvStore` class, but you can define your own `KvStore` implementation if you want to use a different key-value store. Currently, there are two implementations of `KvStore`, which are the `MemoryKvStore` and `DenoKvStore` classes. The `MemoryKvStore` class is for testing and development purposes, and the `DenoKvStore` class is Deno KV-backed implementation for production use (as you can guess from the name, it is only available in Deno runtime). However, you can define your own `KvStore` implementation if you want to use a different key-value store.[^1] [^1]: We are welcome to contributions of `KvStore` implementations for other key-value stores. ### `kvPrefixes` Loading @@ -71,9 +77,20 @@ If you don't provide this option, activities will not be queued and will be sent immediately. `MessageQueue` is an abstract interface that represents a message queue. Currently, there is only one implementation of `MessageQueue`, which is the `InProcessMessageQueue` class, but you can define your own `MessageQueue` implementation if you want to use a different message queue. Currently, there are only two implementations of `MessageQueue`, which are the `InProcessMessageQueue` and `DenoKvMessageQueue` classes. The `InProcessMessageQueue` class is for testing and development purposes, and the `DenoKvMessageQueue` class is a Deno KV-backed implementation for production use (as you can guess from the name, it is only available in Deno runtime). However, you can define your own `MessageQueue` implementation if you want to use a different message queue.[^1] > [!IMPORTANT] > While the `queue` option is optional, it is highly recommended to provide > a message queue implementation in production environments. If you don't > provide a message queue implementation, activities will not be queued and > will be sent immediately. This can make delivery of activities unreliable > and can cause performance issues. ### `documentLoader` Loading
docs/tutorial.md +31 −27 Original line number Diff line number Diff line Loading @@ -145,10 +145,10 @@ ActivityPub activities and actors. Let's modify the server script to use the `Federation` object: ~~~~ typescript import { Federation } from "@fedify/fedify"; import { Federation, MemoryKvStore } from "@fedify/fedify"; const federation = new Federation<void>({ kv: await Deno.openKv(), kv: new MemoryKvStore(), }); ~~~~ Loading @@ -156,23 +156,12 @@ In the above code, we import the `Federation` object from the Fedify framework and create a new `Federation` object. We pass an object to the `new Federation()` constructor, which is the configuration object. The `kv` property is a key-value store that is used to store several internal data of the `Federation` object. We use the [`Deno.openKv()`] function to open data of the `Federation` object. We use the `MemoryKvStore` to open a key-value store. > [!NOTE] > Since the `Deno.openKv()` function is one of the unstable APIs in Deno as of > March 2024, you need to specify the `"unstable": ["kv"]` field in > the *deno.json* file to use the `Deno.openKv()` function. The *deno.json* > file should look like this: > > ~~~~ json > { > "imports": { > "@fedify/fedify": "jsr:@fedify/fedify@^0.3.0" > }, > "unstable": ["kv"] > } > ~~~~ > [!IMPORTANT] > Since `MemoryKvStore` is for testing and development purposes, you should > use a persistent key-value store like [`DenoKvStore`] for production use. Then, we pass the incoming `Request` to the `federation.handle()` method: Loading Loading @@ -217,10 +206,10 @@ like). Let's create an actor dispatcher for our server: ~~~~ typescript import { Federation, Person } from "@fedify/fedify"; import { Federation, MemoryKvStore, Person } from "@fedify/fedify"; const federation = new Federation<void>({ kv: await Deno.openKv(), kv: new MemoryKvStore(), }); federation.setActorDispatcher("/users/{handle}", async (ctx, handle) => { Loading Loading @@ -371,7 +360,7 @@ set the `treatHttps` property to `true` in the `Federation` object: ~~~~ typescript const federation = new Federation<void>({ kv: await Deno.openKv(), kv: new MemoryKvStore(), treatHttps: true, // Treat HTTP requests as HTTPS }); ~~~~ Loading Loading @@ -417,7 +406,7 @@ represents the `Follow` activity. We will use the `Follow` class to handle incoming follow requests: ~~~~ typescript import { Federation, Follow, Person } from "@fedify/fedify"; import { Federation, Follow, Person, MemoryKvStore } from "@fedify/fedify"; ~~~~ Then, we register an inbox listener for the `Follow` activity: Loading Loading @@ -493,7 +482,7 @@ Fedify provides helper functions to generate and export/import keys: ~~~~ typescript import { Federation, Follow, Person, Federation, Follow, Person, MemoryKvStore, // Import helper functions: exportJwk, generateCryptoKeyPair, importJwk, } from "@fedify/fedify"; Loading @@ -513,11 +502,6 @@ should be chained after the `Federation.setActorDispatcher()` method: ~~~~ typescript const kv = await Deno.openKv(); // Open the key-value store const federation = new Federation<void>({ kv, treatHttps: true, }); federation .setActorDispatcher("/users/{handle}", async (ctx, handle, key) => { if (handle !== "me") return null; Loading Loading @@ -564,6 +548,26 @@ at the first time and store it in the key-value store. When the actor *me* is dispatched again, the key pair dispatcher loads the key pair from the key-value store. > [!IMPORTANT] > In the above code, we use the `Deno.openKv()` function to open the key-value > store, which is persistent. However, Deno KV is an unstable feature as of > March 2024, so you need to add the `"unstable": ["kv"]` field to the > *deno.json* file: > > ~~~~ json > { > "imports": { > "@fedify/fedify": "jsr:@fedify/fedify@^0.4.0" > }, > "unstable": ["kv"] > } > ~~~~ > [!NOTE] > Although we use the Deno KV database in this tutorial, you can use any > other your favorite database to store the key pair. The key-value store > is just an example. Restart the server and make an HTTP request to the actor *me* using `curl`. Now you should see the actor *me* with the public key in the response: Loading
examples/blog/.vscode/settings.json +1 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ "activitypub", "codegen", "deno", "denokv", "docloader", "fedify", "fediverse", Loading
examples/blog/federation/mod.ts +5 −7 Original line number Diff line number Diff line import { Temporal } from "@js-temporal/polyfill"; import { parse } from "@std/semver"; import { dirname, join } from "@std/path"; import { Federation, InProcessMessageQueue, MemoryKvStore, } from "@fedify/fedify/federation"; import { Federation } from "@fedify/fedify/federation"; import { Accept, Activity, Loading @@ -19,6 +15,7 @@ import { Person, Undo, } from "@fedify/fedify/vocab"; import { DenoKvMessageQueue, DenoKvStore } from "@fedify/fedify/x/denokv"; import { getBlog } from "../models/blog.ts"; import { addComment, Comment, getComments } from "../models/comment.ts"; import { Loading @@ -28,15 +25,16 @@ import { removeFollower, } from "../models/follower.ts"; import { countPosts, getPosts, toArticle } from "../models/post.ts"; import { openKv } from "../models/kv.ts"; // The `Federation<TContextData>` object is a registry that registers // federation-related callbacks: export const federation = new Federation<void>({ // The following key-value storage is used for internal cache: kv: new MemoryKvStore(), kv: new DenoKvStore(await openKv()), // The following message queue is used for maintaining outgoing activities: queue: new InProcessMessageQueue(), queue: new DenoKvMessageQueue(await openKv()), // The following option is useful for local development, as Fresh's dev // server does not support HTTPS: Loading
examples/blog/import_map.g.json +2 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ "@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", Loading @@ -37,6 +38,7 @@ "@preact/signals": "https://esm.sh/*@preact/signals@1.2.2", "@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.5.1", "@std/dotenv/load": "jsr:@std/dotenv@^0.220.1/load", "@fedify/fedify/x/denokv": "../../x/denokv.ts", "markdown-it": "npm:markdown-it@^14.0.0", "preact": "https://esm.sh/preact@10.19.6", "preact/": "https://esm.sh/preact@10.19.6/", Loading