diff --git a/apps/web/.env.example b/apps/web/.env.example new file mode 100644 index 0000000..bd13e4b --- /dev/null +++ b/apps/web/.env.example @@ -0,0 +1,5 @@ + +# @svelte-atproto/oauth +ORIGIN= +COOKIE_SECRET= +CLIENT_ASSERTION_KEY= diff --git a/apps/web/package.json b/apps/web/package.json index 95de91a..1832d91 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -4,6 +4,9 @@ "version": "0.0.1", "type": "module", "scripts": { + "atproto:setup": "atproto-oauth setup", + "atproto:keygen": "atproto-oauth keygen", + "atproto:secret": "atproto-oauth secret", "dev": "vite dev", "build": "vite build", "preview": "vite preview", @@ -36,5 +39,9 @@ "typescript": "^6.0.2", "typescript-eslint": "^8.58.1", "vite": "^8.0.7" + }, + "dependencies": { + "@atcute/atproto": "^3.1.10", + "@svelte-atproto/oauth": "^0.1.0" } } diff --git a/apps/web/src/app.d.ts b/apps/web/src/app.d.ts index da08e6d..3a78063 100644 --- a/apps/web/src/app.d.ts +++ b/apps/web/src/app.d.ts @@ -1,9 +1,16 @@ // See https://svelte.dev/docs/kit/types#app.d.ts -// for information about these interfaces +import type { OAuthSession } from '@atcute/oauth-node-client'; +import type { Client } from '@atcute/client'; +import type { Did } from '@atcute/lexicons'; + declare global { namespace App { // interface Error {} - // interface Locals {} + interface Locals { + session: OAuthSession | null; + client: Client | null; + did: Did | null; + } // interface PageData {} // interface PageState {} // interface Platform {} diff --git a/apps/web/src/hooks.server.ts b/apps/web/src/hooks.server.ts new file mode 100644 index 0000000..e9dba0a --- /dev/null +++ b/apps/web/src/hooks.server.ts @@ -0,0 +1,3 @@ +import { atproto } from '$lib/atproto'; + +export const handle = atproto.handle; diff --git a/apps/web/src/lib/atproto/index.ts b/apps/web/src/lib/atproto/index.ts new file mode 100644 index 0000000..555eb72 --- /dev/null +++ b/apps/web/src/lib/atproto/index.ts @@ -0,0 +1,15 @@ +// Side-effect: loads `com.atproto.*` lexicon types into the atcute Client. +import '@atcute/atproto'; +import { createAtprotoAuth } from '@svelte-atproto/oauth/server'; +import { cloudflareKV } from '@svelte-atproto/oauth/server/stores/cloudflare'; +import { env } from '$env/dynamic/private'; + +// To enable signup, add: signupPDS: 'https://your-pds.example/' +export const atproto = createAtprotoAuth({ + origin: env.ORIGIN, + cookieSecret: env.COOKIE_SECRET, + clientAssertionKey: env.CLIENT_ASSERTION_KEY, + scope: 'atproto repo:xyz.statusphere.status', + sessions: cloudflareKV('OAUTH_SESSIONS'), + states: cloudflareKV('OAUTH_STATES', { ttl: 600 }) +}); diff --git a/apps/web/src/routes/demo/atproto/+page.server.ts b/apps/web/src/routes/demo/atproto/+page.server.ts new file mode 100644 index 0000000..1a385c6 --- /dev/null +++ b/apps/web/src/routes/demo/atproto/+page.server.ts @@ -0,0 +1,102 @@ +import { redirect, fail } from '@sveltejs/kit'; +import type { Actions, PageServerLoad } from './$types'; +import { atproto } from '$lib/atproto'; +import { + loadHandle, + createTID, + recentRecords, + loadHandles, + listRecords, + parseUri +} from '@svelte-atproto/oauth/helper'; +import { memory } from '@svelte-atproto/oauth/server/stores/memory'; + +// In-memory cache for handle lookups — fine for dev. For prod, swap in +// cloudflareKV or upstashRedis (any `Store` works). +const profileCache = memory(); +const COLLECTION = 'xyz.statusphere.status'; + +export const load: PageServerLoad = async ({ locals, url }) => { + if (!locals.did) { + const returnTo = encodeURIComponent(url.pathname + url.search); + redirect(302, `/demo/atproto/login?returnTo=${returnTo}`); + } + + // Lightweight: just resolve the handle from the user's PDS. + // For richer Bluesky profile data (display name, avatar) swap to: + // import { loadBskyProfile } from '@svelte-atproto/oauth/bsky'; + // const profile = await loadBskyProfile(locals.did, { cache: profileCache }); + const handle = await loadHandle(locals.did, { cache: profileCache }); + + // Recent statuses globally, from the firehose via UFO. UFO is slightly + // behind the firehose, so we also pull the user's own records and merge + // them in front so just-published statuses show up immediately. + const [globalRecent, own] = await Promise.all([ + recentRecords(COLLECTION), + locals.client + ? listRecords({ did: locals.did, collection: COLLECTION, client: locals.client, limit: 10 }) + : Promise.resolve([]) + ]); + + const ownAsItems = own.map((r) => { + const parts = parseUri(r.uri); + const record = r.value as { $type: string; createdAt?: string; [k: string]: unknown }; + const parsed = + typeof record.createdAt === 'string' ? new Date(record.createdAt).getTime() : NaN; + const time_us = (Number.isFinite(parsed) ? parsed : Date.now()) * 1000; + return { + did: parts?.repo ?? locals.did, + collection: parts?.collection ?? COLLECTION, + rkey: parts?.rkey ?? '', + record, + time_us + }; + }); + + // Own records first so they win the dedupe (UFO can be stale on a record + // the user just published). Then sort by time_us so the merged list is + // in true reverse-chronological order regardless of source. + const seen = new Set(); + const merged = []; + for (const item of [...ownAsItems, ...globalRecent]) { + const key = `${item.did}/${item.rkey}`; + if (seen.has(key)) continue; + seen.add(key); + merged.push(item); + } + const recent = merged.sort((a, b) => b.time_us - a.time_us); + + // Resolve the author handles in parallel (cached). + // For richer profile data, swap `loadHandles` for: + // import { loadBskyProfiles } from '@svelte-atproto/oauth/bsky'; + const authorDids = [...new Set(recent.map((r) => r.did))]; + const authors = await loadHandles(authorDids, { cache: profileCache }); + return { did: locals.did, handle, recent, authors }; +}; + +export const actions: Actions = { + setStatus: async ({ request, locals }) => { + if (!locals.client || !locals.did) return fail(401, { message: 'Not signed in' }); + const fd = await request.formData(); + const status = fd.get('status')?.toString(); + if (!status) return fail(400, { message: 'Missing status' }); + + await locals.client.post('com.atproto.repo.putRecord', { + input: { + repo: locals.did, + collection: COLLECTION, + rkey: createTID(), + record: { + $type: COLLECTION, + status, + createdAt: new Date().toISOString() + } + } + }); + return { ok: true }; + }, + signOut: async () => { + await atproto.api.logout(); + redirect(303, '/demo/atproto/login'); + } +}; diff --git a/apps/web/src/routes/demo/atproto/+page.svelte b/apps/web/src/routes/demo/atproto/+page.svelte new file mode 100644 index 0000000..ff3da73 --- /dev/null +++ b/apps/web/src/routes/demo/atproto/+page.svelte @@ -0,0 +1,44 @@ + + +
+

What's your status?

+

Hi {data.handle ?? data.did}.

+ +
+ {#each emojis as emoji} + + {/each} +
+ + {#if data.recent?.length} +

Recent statuses (firehose)

+ + {/if} + +
+ +
+
diff --git a/apps/web/src/routes/demo/atproto/login/+page.server.ts b/apps/web/src/routes/demo/atproto/login/+page.server.ts new file mode 100644 index 0000000..c1b52eb --- /dev/null +++ b/apps/web/src/routes/demo/atproto/login/+page.server.ts @@ -0,0 +1,36 @@ +import { fail, redirect } from '@sveltejs/kit'; +import type { Actions, PageServerLoad } from './$types'; +import { atproto } from '$lib/atproto'; + +const DEFAULT_RETURN_TO = '/demo/atproto'; + +function safeReturnTo(value: string | null | undefined): string { + if (!value) return DEFAULT_RETURN_TO; + try { + const decoded = decodeURIComponent(value); + if (decoded.startsWith('/') && !decoded.startsWith('//')) return decoded; + } catch {} + return DEFAULT_RETURN_TO; +} + +export const load: PageServerLoad = ({ locals, url }) => { + if (locals.did) redirect(302, safeReturnTo(url.searchParams.get('returnTo'))); + return { returnTo: safeReturnTo(url.searchParams.get('returnTo')) }; +}; + +export const actions: Actions = { + signIn: async ({ request }) => { + const fd = await request.formData(); + const handle = fd.get('handle')?.toString().trim(); + const returnTo = safeReturnTo(fd.get('returnTo')?.toString()); + if (!handle) return fail(400, { message: 'Handle or DID is required' }); + + try { + const { url } = await atproto.api.startLogin({ handle, returnTo }); + redirect(303, url); + } catch (e) { + if (e && typeof e === 'object' && 'status' in e && 'location' in e) throw e; + return fail(400, { message: e instanceof Error ? e.message : 'Sign-in failed' }); + } + } +}; diff --git a/apps/web/src/routes/demo/atproto/login/+page.svelte b/apps/web/src/routes/demo/atproto/login/+page.svelte new file mode 100644 index 0000000..4a032b0 --- /dev/null +++ b/apps/web/src/routes/demo/atproto/login/+page.svelte @@ -0,0 +1,32 @@ + + +
+

Sign in with atproto

+ +
+ + + + + {#if form?.message} +

{form.message}

+ {/if} + + +
+
diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts index 56f40c7..6bda53b 100644 --- a/apps/web/vite.config.ts +++ b/apps/web/vite.config.ts @@ -2,4 +2,7 @@ import tailwindcss from '@tailwindcss/vite'; import { sveltekit } from '@sveltejs/kit/vite'; import { defineConfig } from 'vite'; -export default defineConfig({ plugins: [tailwindcss(), sveltekit()] }); +export default defineConfig({ + server: { host: '127.0.0.1' }, + plugins: [tailwindcss(), sveltekit()] +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 08a019d..89c72be 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,6 +53,13 @@ importers: version: 4.94.0(@cloudflare/workers-types@4.20260522.1) apps/web: + dependencies: + '@atcute/atproto': + specifier: ^3.1.10 + version: 3.1.12(@atcute/lexicons@2.0.0) + '@svelte-atproto/oauth': + specifier: ^0.1.0 + version: 0.1.0(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@sveltejs/kit@2.60.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.59.4))(vite@8.0.14(@types/node@22.19.19)(esbuild@0.27.3)(jiti@2.7.0)))(svelte@5.55.9(@typescript-eslint/types@8.59.4))(typescript@6.0.3)(vite@8.0.14(@types/node@22.19.19)(esbuild@0.27.3)(jiti@2.7.0)))(svelte@5.55.9(@typescript-eslint/types@8.59.4))(typescript@6.0.3) devDependencies: '@eslint/compat': specifier: ^2.0.4 @@ -136,6 +143,16 @@ importers: packages: + '@atcute/atproto@3.1.12': + resolution: {integrity: sha512-SaHY0vV5+VfS2ViOcbYtxPmmh82vbxoK5ccHTGn5+ciHNY2arEVcBUFbIQKtsQP4PPZ+lNAVooH+Wh62flvCzg==} + peerDependencies: + '@atcute/lexicons': ^1.0.0 + + '@atcute/bluesky@3.3.5': + resolution: {integrity: sha512-DmzdCQ1VkPRBsIMr79EDxLWLpg0UNWVahFjMelfzau717r+I3ceJm9SxfOK/of+biLOUj4rlr00tNZT+BRe6Ww==} + peerDependencies: + '@atcute/lexicons': ^1.0.0 + '@atcute/car@6.0.0': resolution: {integrity: sha512-v3lhHfqxBi/wxq3q4N9f3/9ed44xqwKI0VAlgPge9NKjJ2xuJcEvj12v4m+P2FB758cioCsghKy58tz2s20eAA==} peerDependencies: @@ -150,6 +167,11 @@ packages: '@atcute/cid@2.4.1': resolution: {integrity: sha512-bwhna69RCv7yetXudtj+2qrMPYvhhIQqvJz6YUpUS98v7OdF3X2dnye9Nig2NDrklZcuyOsu7sQo7GOykJXRLQ==} + '@atcute/client@4.2.2': + resolution: {integrity: sha512-z16BaGgdO6WIkDCxqeI+zhnh2KmW9jsjd312PJ6YYsoDBpPPqL+WkBmxQ7eO9C6CMFxXsZpYcM81RzZEETA4PQ==} + peerDependencies: + '@atcute/lexicons': ^1.0.0 + '@atcute/client@5.0.0': resolution: {integrity: sha512-Dtrc1no1oAtpUTmkBxH0xKSgy8qcnk8orPf/PkEATW+MB3k8FPHtPH2fshiKd55rioZkb+xaN+7A29WtqPQHRA==} peerDependencies: @@ -158,12 +180,23 @@ packages: '@atcute/crypto@2.4.1': resolution: {integrity: sha512-tJ3Pi/XYcAsABKtqSlSOTKfO5YiQ4XdqlTuPS8HiRZSezOPcXBFFzAFWpSIJPURbVPFQL3LLrrK0Ea24wl5qeQ==} + '@atcute/identity-resolver@1.2.3': + resolution: {integrity: sha512-q891zLUMtgoD60y5Pv2YmTg4wIf4ipFuIhZlIuQTTB7qM9sGxmBbe2quzTRCTl3pnsLEmTz7l+3Dszgoutsp5w==} + peerDependencies: + '@atcute/identity': ^1.0.0 + '@atcute/lexicons': ^1.0.0 + '@atcute/identity-resolver@2.0.0': resolution: {integrity: sha512-IKg1BDQAF2bIdN10DL6KAXmTjK+3enTU2IRbuani9TsFahBwGZ7O5FiVmTiL6QlGfauGNW5S0xNCOxWXWMoR2Q==} peerDependencies: '@atcute/identity': ^2.0.0 '@atcute/lexicons': ^2.0.0 + '@atcute/identity@1.1.5': + resolution: {integrity: sha512-5i9nl1UVnBDPCumUwrLNl4BZpGvQ/XABEXbjhiw3PQwRUfpQA8FqByDGxXy2gWpFDrNvQ9yVuOoNsjzxJgjjVA==} + peerDependencies: + '@atcute/lexicons': ^1.0.0 + '@atcute/identity@2.0.0': resolution: {integrity: sha512-YXFsggO7eJYifqkN85+kUXJE2a1iI9AyuzPTDjtS/4WE1Zs1/XiPkWmwZlAgtp+pYhVtjm3mJqy/h/mZ0OnIVw==} peerDependencies: @@ -186,6 +219,9 @@ packages: '@atcute/lexicon-doc': ^3.0.0 '@atcute/lexicons': ^2.0.0 + '@atcute/lexicons@1.3.1': + resolution: {integrity: sha512-2JVxDmHt+QwsUoPyVYWIN7ZLRLfLx4GeJxKFjA9ofStuby9hCMv7Q4GAPIXuJD8wPv8vrnhr1yRNQhiJX+bthw==} + '@atcute/lexicons@2.0.0': resolution: {integrity: sha512-fIlwP+TPEAGoF5aU5s+f8N5sOjOu8Mww/sQL1B57Dp2hj3G/EWG9XwOHPokzycBCgXx+UxIIrzZCGy8whsVDZw==} @@ -198,6 +234,30 @@ packages: '@atcute/multibase@1.2.0': resolution: {integrity: sha512-ZK2GRra+qIYq9nNuQB52m2ul0hOmCQEtPobGfTSUxm7pF0OGEkWGkWHugFhNEDVzHzTwPxHp6VGotdZFue4lYQ==} + '@atcute/oauth-browser-client@3.0.1': + resolution: {integrity: sha512-1eyqsPUyGzjsclyrScr73L/0I8iyv2kJlBD9Atyq8Fwhkv6DLCIMf3wTCbjOE0uZOmQMk3tRGzVC33fEIoktxw==} + peerDependencies: + '@atcute/identity-resolver': ^1.0.0 + '@atcute/lexicons': ^1.0.0 + + '@atcute/oauth-crypto@0.1.0': + resolution: {integrity: sha512-qZYDCNLF/4B6AndYT1rsQelN8621AC5u/sL5PHvlr/qqAbmmUwCBGjEgRSyZtHE1AqD60VNiSMlOgAuEQTSl3w==} + + '@atcute/oauth-crypto@1.0.0': + resolution: {integrity: sha512-2UC1msk4PyUArk/5Pl8zgtz1T8O+LZdFfB8ENLHjQVYitpqzGj2ZpDJaWZvCF3Y8lly4KoeUHLpFPDzbP+3u+g==} + + '@atcute/oauth-keyset@0.1.1': + resolution: {integrity: sha512-BpaaXSuMawxILhWTOR0YIpKzFSA0MQC1W5Hn0HGE+giTqYFAKcdf0oA+2RZG9ZLVIzfO2txBsTeMpxB5qL6lEQ==} + + '@atcute/oauth-node-client@1.1.1': + resolution: {integrity: sha512-BylK1doT4c4PQlNZXXhr3Wg+b9EHnpq5spNUkD0wpAe6SIft//6ZcWtFlYEZxnjD/8E0IjBIDqxP9OI/0FYGgw==} + peerDependencies: + '@atcute/identity-resolver': ^1.0.0 + '@atcute/lexicons': ^1.0.0 + + '@atcute/oauth-types@0.1.1': + resolution: {integrity: sha512-u+3KMjse3Uc/9hDyilu1QVN7IpcnjVXgRzhddzBB8Uh6wePHNVBDdi9wQvFTVVA3zmxtMJVptXRyLLg6Ou9bqg==} + '@atcute/repo@1.0.0': resolution: {integrity: sha512-3s6VDKMimmYxVXn9OTlYQ7bJGPRcZRyFZ+oF/IFdfm3PsEUxwwSXajw1bG0HVXns1rNgNnDUT0PqMlUd2GnjqA==} peerDependencies: @@ -205,9 +265,18 @@ packages: '@atcute/cid': ^2.0.0 '@atcute/lexicons': ^2.0.0 + '@atcute/tid@1.1.2': + resolution: {integrity: sha512-bmPuOX/TOfcm/vsK9vM98spjkcx2wgd9S2PeK5oLgEr8IbNRPq7iMCAPzOL1nu5XAW3LlkOYQEbYRcw5vcQ37w==} + + '@atcute/time-ms@1.3.2': + resolution: {integrity: sha512-F+qOyR9pO55g1d/QmN+Gr+fimoUQQLusdGSB6pjV0wW5KPILR4oQ4e2ZhWzqUbeHLAgWvgoTTMsMDdz62Xa2tg==} + '@atcute/uint8array@1.1.2': resolution: {integrity: sha512-n+lutnbN9mKzSjSVdfsYfzJ40u2971H+iLSL46D6d7zcrA4delxusf/ftGFvj5oGW03OioaFgQOy3Lqa3JmTeA==} + '@atcute/util-fetch@1.0.5': + resolution: {integrity: sha512-qjHj01BGxjSjIFdPiAjSARnodJIIyKxnCMMEcXMESo9TAyND6XZQqrie5fia+LlYWVXdpsTds8uFQwc9jdKTig==} + '@atcute/util-fetch@2.0.0': resolution: {integrity: sha512-v+4aFQ/tuBqTV+URDJaFgm3mASWdglKXiPaGutJ1bs7QtQKmPZeesPY5MzW/a+MtI8GWCEJk8X9wOfalPOFSlg==} @@ -222,6 +291,10 @@ packages: peerDependencies: '@atcute/lexicons': ^2.0.0 + '@badrap/valita@0.4.6': + resolution: {integrity: sha512-4kdqcjyxo/8RQ8ayjms47HCWZIF5981oE5nIenbfThKDxWXtEHKipAOWlflpPJzZx9y/JWYQkp18Awr7VuepFg==} + engines: {node: '>= 18'} + '@cloudflare/kv-asset-handler@0.5.0': resolution: {integrity: sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==} engines: {node: '>=22.0.0'} @@ -824,6 +897,13 @@ packages: '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@svelte-atproto/oauth@0.1.0': + resolution: {integrity: sha512-jLQcadl9c03/+PFhyzYI+kHS5mh0dDKwyZlDYq+UrwPzQ7F0peHa4Hz0B0UgFB4H732QKgY827Yuuo255Qi/hQ==} + hasBin: true + peerDependencies: + '@sveltejs/kit': ^2.0.0 + svelte: ^5.0.0 + '@sveltejs/acorn-typescript@1.0.10': resolution: {integrity: sha512-4WfKk68eTih+MiJD4fSbxN7E8kVBmTMPWHUPYjvl2N0rMs53YLTT8/YjKU5Dtnz5LqDjl7LEw4U7lXR2W3J5WA==} peerDependencies: @@ -1987,6 +2067,19 @@ packages: snapshots: + '@atcute/atproto@3.1.12(@atcute/lexicons@1.3.1)': + dependencies: + '@atcute/lexicons': 1.3.1 + + '@atcute/atproto@3.1.12(@atcute/lexicons@2.0.0)': + dependencies: + '@atcute/lexicons': 2.0.0 + + '@atcute/bluesky@3.3.5(@atcute/lexicons@1.3.1)': + dependencies: + '@atcute/atproto': 3.1.12(@atcute/lexicons@1.3.1) + '@atcute/lexicons': 1.3.1 + '@atcute/car@6.0.0(@atcute/cbor@2.3.3(@atcute/cid@2.4.1))(@atcute/cid@2.4.1)': dependencies: '@atcute/cbor': 2.3.3(@atcute/cid@2.4.1) @@ -2005,6 +2098,11 @@ snapshots: '@atcute/multibase': 1.2.0 '@atcute/uint8array': 1.1.2 + '@atcute/client@4.2.2(@atcute/lexicons@1.3.1)': + dependencies: + '@atcute/identity': 1.1.5(@atcute/lexicons@1.3.1) + '@atcute/lexicons': 1.3.1 + '@atcute/client@5.0.0(@atcute/lexicons@2.0.0)(typescript@5.9.3)': dependencies: '@atcute/identity': 2.0.0(@atcute/lexicons@2.0.0)(typescript@5.9.3) @@ -2018,6 +2116,13 @@ snapshots: '@atcute/uint8array': 1.1.2 '@noble/secp256k1': 3.1.0 + '@atcute/identity-resolver@1.2.3(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@2.0.0)': + dependencies: + '@atcute/identity': 2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3) + '@atcute/lexicons': 2.0.0 + '@atcute/util-fetch': 1.0.5 + '@badrap/valita': 0.4.6 + '@atcute/identity-resolver@2.0.0(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@5.9.3))(@atcute/lexicons@2.0.0)(typescript@5.9.3)': dependencies: '@atcute/identity': 2.0.0(@atcute/lexicons@2.0.0)(typescript@5.9.3) @@ -2027,6 +2132,11 @@ snapshots: transitivePeerDependencies: - typescript + '@atcute/identity@1.1.5(@atcute/lexicons@1.3.1)': + dependencies: + '@atcute/lexicons': 1.3.1 + '@badrap/valita': 0.4.6 + '@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@5.9.3)': dependencies: '@atcute/lexicons': 2.0.0 @@ -2034,6 +2144,13 @@ snapshots: transitivePeerDependencies: - typescript + '@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3)': + dependencies: + '@atcute/lexicons': 2.0.0 + valibot: 1.4.0(typescript@6.0.3) + transitivePeerDependencies: + - typescript + '@atcute/lex-cli@3.1.0(@atcute/cbor@2.3.3(@atcute/cid@2.4.1))(@atcute/cid@2.4.1)(typescript@5.9.3)': dependencies: '@atcute/identity': 2.0.0(@atcute/lexicons@2.0.0)(typescript@5.9.3) @@ -2076,6 +2193,13 @@ snapshots: - '@atcute/cid' - typescript + '@atcute/lexicons@1.3.1': + dependencies: + '@atcute/uint8array': 1.1.2 + '@atcute/util-text': 1.3.1 + '@standard-schema/spec': 1.1.0 + esm-env: 1.2.2 + '@atcute/lexicons@2.0.0': dependencies: '@atcute/uint8array': 1.1.2 @@ -2093,6 +2217,64 @@ snapshots: dependencies: '@atcute/uint8array': 1.1.2 + '@atcute/oauth-browser-client@3.0.1(@atcute/identity-resolver@1.2.3(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@1.3.1))(@atcute/lexicons@1.3.1)(typescript@6.0.3)': + dependencies: + '@atcute/client': 4.2.2(@atcute/lexicons@1.3.1) + '@atcute/identity-resolver': 1.2.3(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@2.0.0) + '@atcute/lexicons': 1.3.1 + '@atcute/multibase': 1.2.0 + '@atcute/oauth-crypto': 0.1.0 + '@atcute/oauth-types': 0.1.1(typescript@6.0.3) + nanoid: 5.1.11 + transitivePeerDependencies: + - typescript + + '@atcute/oauth-crypto@0.1.0': + dependencies: + '@atcute/multibase': 1.2.0 + '@atcute/uint8array': 1.1.2 + '@badrap/valita': 0.4.6 + nanoid: 5.1.11 + + '@atcute/oauth-crypto@1.0.0(typescript@6.0.3)': + dependencies: + '@atcute/multibase': 1.2.0 + '@atcute/uint8array': 1.1.2 + nanoid: 5.1.11 + valibot: 1.4.0(typescript@6.0.3) + transitivePeerDependencies: + - typescript + + '@atcute/oauth-keyset@0.1.1(typescript@6.0.3)': + dependencies: + '@atcute/oauth-crypto': 1.0.0(typescript@6.0.3) + transitivePeerDependencies: + - typescript + + '@atcute/oauth-node-client@1.1.1(@atcute/identity-resolver@1.2.3(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@1.3.1))(@atcute/lexicons@1.3.1)(typescript@6.0.3)': + dependencies: + '@atcute/client': 4.2.2(@atcute/lexicons@1.3.1) + '@atcute/identity': 1.1.5(@atcute/lexicons@1.3.1) + '@atcute/identity-resolver': 1.2.3(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@2.0.0) + '@atcute/lexicons': 1.3.1 + '@atcute/oauth-crypto': 0.1.0 + '@atcute/oauth-keyset': 0.1.1(typescript@6.0.3) + '@atcute/oauth-types': 0.1.1(typescript@6.0.3) + '@atcute/util-fetch': 1.0.5 + '@badrap/valita': 0.4.6 + nanoid: 5.1.11 + transitivePeerDependencies: + - typescript + + '@atcute/oauth-types@0.1.1(typescript@6.0.3)': + dependencies: + '@atcute/identity': 1.1.5(@atcute/lexicons@1.3.1) + '@atcute/lexicons': 1.3.1 + '@atcute/oauth-keyset': 0.1.1(typescript@6.0.3) + '@badrap/valita': 0.4.6 + transitivePeerDependencies: + - typescript + '@atcute/repo@1.0.0(@atcute/cbor@2.3.3(@atcute/cid@2.4.1))(@atcute/cid@2.4.1)(@atcute/lexicons@2.0.0)': dependencies: '@atcute/car': 6.0.0(@atcute/cbor@2.3.3(@atcute/cid@2.4.1))(@atcute/cid@2.4.1) @@ -2103,8 +2285,18 @@ snapshots: '@atcute/mst': 1.0.1(@atcute/cbor@2.3.3(@atcute/cid@2.4.1))(@atcute/cid@2.4.1) '@atcute/uint8array': 1.1.2 + '@atcute/tid@1.1.2': + dependencies: + '@atcute/time-ms': 1.3.2 + + '@atcute/time-ms@1.3.2': {} + '@atcute/uint8array@1.1.2': {} + '@atcute/util-fetch@1.0.5': + dependencies: + '@badrap/valita': 0.4.6 + '@atcute/util-fetch@2.0.0(typescript@5.9.3)': dependencies: valibot: 1.4.0(typescript@5.9.3) @@ -2132,6 +2324,8 @@ snapshots: - '@atcute/cid' - typescript + '@badrap/valita@0.4.6': {} + '@cloudflare/kv-asset-handler@0.5.0': {} '@cloudflare/unenv-preset@2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260521.1)': @@ -2534,6 +2728,22 @@ snapshots: '@standard-schema/spec@1.1.0': {} + '@svelte-atproto/oauth@0.1.0(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@sveltejs/kit@2.60.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.59.4))(vite@8.0.14(@types/node@22.19.19)(esbuild@0.27.3)(jiti@2.7.0)))(svelte@5.55.9(@typescript-eslint/types@8.59.4))(typescript@6.0.3)(vite@8.0.14(@types/node@22.19.19)(esbuild@0.27.3)(jiti@2.7.0)))(svelte@5.55.9(@typescript-eslint/types@8.59.4))(typescript@6.0.3)': + dependencies: + '@atcute/atproto': 3.1.12(@atcute/lexicons@1.3.1) + '@atcute/bluesky': 3.3.5(@atcute/lexicons@1.3.1) + '@atcute/client': 4.2.2(@atcute/lexicons@1.3.1) + '@atcute/identity-resolver': 1.2.3(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@2.0.0) + '@atcute/lexicons': 1.3.1 + '@atcute/oauth-browser-client': 3.0.1(@atcute/identity-resolver@1.2.3(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@1.3.1))(@atcute/lexicons@1.3.1)(typescript@6.0.3) + '@atcute/oauth-node-client': 1.1.1(@atcute/identity-resolver@1.2.3(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@1.3.1))(@atcute/lexicons@1.3.1)(typescript@6.0.3) + '@atcute/tid': 1.1.2 + '@sveltejs/kit': 2.60.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.59.4))(vite@8.0.14(@types/node@22.19.19)(esbuild@0.27.3)(jiti@2.7.0)))(svelte@5.55.9(@typescript-eslint/types@8.59.4))(typescript@6.0.3)(vite@8.0.14(@types/node@22.19.19)(esbuild@0.27.3)(jiti@2.7.0)) + svelte: 5.55.9(@typescript-eslint/types@8.59.4) + transitivePeerDependencies: + - '@atcute/identity' + - typescript + '@sveltejs/acorn-typescript@1.0.10(acorn@8.16.0)': dependencies: acorn: 8.16.0 @@ -3480,6 +3690,10 @@ snapshots: optionalDependencies: typescript: 5.9.3 + valibot@1.4.0(typescript@6.0.3): + optionalDependencies: + typescript: 6.0.3 + vite@8.0.14(@types/node@22.19.19)(esbuild@0.27.3)(jiti@2.7.0): dependencies: lightningcss: 1.32.0