Loading examples/sveltekit/src/data/store.ts 0 → 100644 +14 −0 Original line number Diff line number Diff line declare global { var keyPairsStore: Map<string, Array<CryptoKeyPair>>; var relationStore: Map<string, string>; } export const keyPairsStore: Map<string, Array<CryptoKeyPair>> = globalThis.keyPairsStore ?? new Map(); export const relationStore: Map<string, string> = globalThis.relationStore ?? new Map(); // this is just a hack to demo nextjs // never do this in production, use safe and secure storage globalThis.keyPairsStore = keyPairsStore; globalThis.relationStore = relationStore; examples/sveltekit/src/federation/index.ts 0 → 100644 +100 −0 Original line number Diff line number Diff line import { Accept, createFederation, Endpoints, Follow, generateCryptoKeyPair, MemoryKvStore, Person, Undo, } from "@fedify/fedify"; import { keyPairsStore, relationStore } from "@/data/store"; const federation = createFederation({ kv: new MemoryKvStore(), }); federation .setActorDispatcher( "/users/{identifier}", async (context, identifier) => { if (identifier != "demo") { return null; } const keyPairs = await context.getActorKeyPairs(identifier); return new Person({ id: context.getActorUri(identifier), name: "Fedify Demo", summary: "This is a Fedify Demo account.", preferredUsername: identifier, url: new URL("/", context.url), inbox: context.getInboxUri(identifier), endpoints: new Endpoints({ sharedInbox: context.getInboxUri(), }), publicKey: keyPairs[0].cryptographicKey, assertionMethods: keyPairs.map((keyPair) => keyPair.multikey), }); }, ) .setKeyPairsDispatcher(async (_, identifier) => { if (identifier != "demo") { return []; } const keyPairs = keyPairsStore.get(identifier); if (keyPairs) { return keyPairs; } const { privateKey, publicKey } = await generateCryptoKeyPair(); keyPairsStore.set(identifier, [{ privateKey, publicKey }]); return [{ privateKey, publicKey }]; }) /* .mapAlias() */; federation .setInboxListeners("/users/{identifier}/inbox", "/inbox") .on(Follow, async (context, follow) => { if ( follow.id == null || follow.actorId == null || follow.objectId == null ) { return; } const result = context.parseUri(follow.objectId); if (result?.type !== "actor" || result.identifier !== "demo") { return; } const follower = await follow.getActor(context); if (follower?.id == null) { throw new Error("follower is null"); } await context.sendActivity( { identifier: result.identifier }, follower, new Accept({ id: new URL( `#accepts/${follower.id.href}`, context.getActorUri("demo"), ), actor: follow.objectId, object: follow, }), ); relationStore.set(follower.id.href, follow.objectId.href); }) .on(Undo, async (context, undo) => { const activity = await undo.getObject(context); if (activity instanceof Follow) { if (activity.id == null) { return; } if (undo.actorId == null) { return; } relationStore.delete(undo.actorId.href); } else { console.debug(undo); } }); export default federation; examples/sveltekit/tsconfig.json +20 −17 Original line number Diff line number Diff line Loading @@ -9,7 +9,10 @@ "skipLibCheck": true, "sourceMap": true, "strict": true, "moduleResolution": "bundler" "moduleResolution": "bundler", "paths": { "@/*": ["./src/*"] } } // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files Loading Loading
examples/sveltekit/src/data/store.ts 0 → 100644 +14 −0 Original line number Diff line number Diff line declare global { var keyPairsStore: Map<string, Array<CryptoKeyPair>>; var relationStore: Map<string, string>; } export const keyPairsStore: Map<string, Array<CryptoKeyPair>> = globalThis.keyPairsStore ?? new Map(); export const relationStore: Map<string, string> = globalThis.relationStore ?? new Map(); // this is just a hack to demo nextjs // never do this in production, use safe and secure storage globalThis.keyPairsStore = keyPairsStore; globalThis.relationStore = relationStore;
examples/sveltekit/src/federation/index.ts 0 → 100644 +100 −0 Original line number Diff line number Diff line import { Accept, createFederation, Endpoints, Follow, generateCryptoKeyPair, MemoryKvStore, Person, Undo, } from "@fedify/fedify"; import { keyPairsStore, relationStore } from "@/data/store"; const federation = createFederation({ kv: new MemoryKvStore(), }); federation .setActorDispatcher( "/users/{identifier}", async (context, identifier) => { if (identifier != "demo") { return null; } const keyPairs = await context.getActorKeyPairs(identifier); return new Person({ id: context.getActorUri(identifier), name: "Fedify Demo", summary: "This is a Fedify Demo account.", preferredUsername: identifier, url: new URL("/", context.url), inbox: context.getInboxUri(identifier), endpoints: new Endpoints({ sharedInbox: context.getInboxUri(), }), publicKey: keyPairs[0].cryptographicKey, assertionMethods: keyPairs.map((keyPair) => keyPair.multikey), }); }, ) .setKeyPairsDispatcher(async (_, identifier) => { if (identifier != "demo") { return []; } const keyPairs = keyPairsStore.get(identifier); if (keyPairs) { return keyPairs; } const { privateKey, publicKey } = await generateCryptoKeyPair(); keyPairsStore.set(identifier, [{ privateKey, publicKey }]); return [{ privateKey, publicKey }]; }) /* .mapAlias() */; federation .setInboxListeners("/users/{identifier}/inbox", "/inbox") .on(Follow, async (context, follow) => { if ( follow.id == null || follow.actorId == null || follow.objectId == null ) { return; } const result = context.parseUri(follow.objectId); if (result?.type !== "actor" || result.identifier !== "demo") { return; } const follower = await follow.getActor(context); if (follower?.id == null) { throw new Error("follower is null"); } await context.sendActivity( { identifier: result.identifier }, follower, new Accept({ id: new URL( `#accepts/${follower.id.href}`, context.getActorUri("demo"), ), actor: follow.objectId, object: follow, }), ); relationStore.set(follower.id.href, follow.objectId.href); }) .on(Undo, async (context, undo) => { const activity = await undo.getObject(context); if (activity instanceof Follow) { if (activity.id == null) { return; } if (undo.actorId == null) { return; } relationStore.delete(undo.actorId.href); } else { console.debug(undo); } }); export default federation;
examples/sveltekit/tsconfig.json +20 −17 Original line number Diff line number Diff line Loading @@ -9,7 +9,10 @@ "skipLibCheck": true, "sourceMap": true, "strict": true, "moduleResolution": "bundler" "moduleResolution": "bundler", "paths": { "@/*": ["./src/*"] } } // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files Loading