From 005c51e7fe87d917e90be9c0f4fd58a00b53136f Mon Sep 17 00:00:00 2001 From: Florian <45694132+flo-bit@users.noreply.github.com> Date: Sat, 23 May 2026 05:30:03 +0200 Subject: [PATCH] add oauth --- apps/example-sender/.env.example | 5 + apps/example-sender/package.json | 8 ++ apps/example-sender/src/app.d.ts | 11 +- apps/example-sender/src/hooks.server.ts | 3 + apps/example-sender/src/lib/atproto/index.ts | 15 ++ .../src/lib/atproto/oauth.remote.ts | 37 +++++ .../src/routes/demo/atproto/+page.server.ts | 73 ++++++++++ .../src/routes/demo/atproto/+page.svelte | 56 ++++++++ .../routes/demo/atproto/login/+page.server.ts | 19 +++ .../routes/demo/atproto/login/+page.svelte | 44 ++++++ apps/example-sender/svelte.config.js | 1 + apps/example-sender/vite.config.ts | 5 +- pnpm-lock.yaml | 132 ++++++++++++++++++ pnpm-workspace.yaml | 1 + 14 files changed, 407 insertions(+), 3 deletions(-) create mode 100644 apps/example-sender/.env.example create mode 100644 apps/example-sender/src/hooks.server.ts create mode 100644 apps/example-sender/src/lib/atproto/index.ts create mode 100644 apps/example-sender/src/lib/atproto/oauth.remote.ts create mode 100644 apps/example-sender/src/routes/demo/atproto/+page.server.ts create mode 100644 apps/example-sender/src/routes/demo/atproto/+page.svelte create mode 100644 apps/example-sender/src/routes/demo/atproto/login/+page.server.ts create mode 100644 apps/example-sender/src/routes/demo/atproto/login/+page.svelte diff --git a/apps/example-sender/.env.example b/apps/example-sender/.env.example new file mode 100644 index 0000000..bd13e4b --- /dev/null +++ b/apps/example-sender/.env.example @@ -0,0 +1,5 @@ + +# @svelte-atproto/oauth +ORIGIN= +COOKIE_SECRET= +CLIENT_ASSERTION_KEY= diff --git a/apps/example-sender/package.json b/apps/example-sender/package.json index 54a0cfe..a44891c 100644 --- a/apps/example-sender/package.json +++ b/apps/example-sender/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,10 @@ "typescript": "^6.0.2", "typescript-eslint": "^8.58.1", "vite": "^8.0.7" + }, + "dependencies": { + "@atcute/atproto": "^4.0.0", + "@svelte-atproto/oauth": "^0.3.0", + "valibot": "^1.0.0" } } diff --git a/apps/example-sender/src/app.d.ts b/apps/example-sender/src/app.d.ts index da08e6d..3a78063 100644 --- a/apps/example-sender/src/app.d.ts +++ b/apps/example-sender/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/example-sender/src/hooks.server.ts b/apps/example-sender/src/hooks.server.ts new file mode 100644 index 0000000..e9dba0a --- /dev/null +++ b/apps/example-sender/src/hooks.server.ts @@ -0,0 +1,3 @@ +import { atproto } from '$lib/atproto'; + +export const handle = atproto.handle; diff --git a/apps/example-sender/src/lib/atproto/index.ts b/apps/example-sender/src/lib/atproto/index.ts new file mode 100644 index 0000000..555eb72 --- /dev/null +++ b/apps/example-sender/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/example-sender/src/lib/atproto/oauth.remote.ts b/apps/example-sender/src/lib/atproto/oauth.remote.ts new file mode 100644 index 0000000..c4e7f7c --- /dev/null +++ b/apps/example-sender/src/lib/atproto/oauth.remote.ts @@ -0,0 +1,37 @@ +import { command, getRequestEvent } from '$app/server'; +import { error } from '@sveltejs/kit'; +import * as v from 'valibot'; +import { atproto } from '$lib/atproto'; +import { createTID } from '@svelte-atproto/oauth/helper'; + +export const oauthLogin = command( + v.object({ + handle: v.optional(v.pipe(v.string(), v.minLength(3))), + signup: v.optional(v.boolean()), + returnTo: v.optional(v.string()) + }), + (input) => atproto.api.startLogin(input) +); + +export const oauthLogout = command(() => atproto.api.logout()); + +const COLLECTION = 'xyz.statusphere.status'; + +export const setStatus = command(v.string(), async (status) => { + const { locals } = getRequestEvent(); + if (!locals.client || !locals.did) error(401, 'Not signed in'); + + 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 }; +}); diff --git a/apps/example-sender/src/routes/demo/atproto/+page.server.ts b/apps/example-sender/src/routes/demo/atproto/+page.server.ts new file mode 100644 index 0000000..a0f8e11 --- /dev/null +++ b/apps/example-sender/src/routes/demo/atproto/+page.server.ts @@ -0,0 +1,73 @@ +import { redirect } from '@sveltejs/kit'; +import type { PageServerLoad } from './$types'; +import { + loadHandle, + 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 }; +}; diff --git a/apps/example-sender/src/routes/demo/atproto/+page.svelte b/apps/example-sender/src/routes/demo/atproto/+page.svelte new file mode 100644 index 0000000..ba00e32 --- /dev/null +++ b/apps/example-sender/src/routes/demo/atproto/+page.svelte @@ -0,0 +1,56 @@ + + +
+

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/example-sender/src/routes/demo/atproto/login/+page.server.ts b/apps/example-sender/src/routes/demo/atproto/login/+page.server.ts new file mode 100644 index 0000000..e578edb --- /dev/null +++ b/apps/example-sender/src/routes/demo/atproto/login/+page.server.ts @@ -0,0 +1,19 @@ +import { redirect } from '@sveltejs/kit'; +import type { PageServerLoad } from './$types'; + +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 }) => { + const returnTo = safeReturnTo(url.searchParams.get('returnTo')); + if (locals.did) redirect(302, returnTo); + return { returnTo }; +}; diff --git a/apps/example-sender/src/routes/demo/atproto/login/+page.svelte b/apps/example-sender/src/routes/demo/atproto/login/+page.svelte new file mode 100644 index 0000000..482a3ab --- /dev/null +++ b/apps/example-sender/src/routes/demo/atproto/login/+page.svelte @@ -0,0 +1,44 @@ + + +
+

Sign in with atproto

+ +
+ + + {#if error} +

{error}

+ {/if} + + +
+
diff --git a/apps/example-sender/svelte.config.js b/apps/example-sender/svelte.config.js index 0c3412e..c5e9030 100644 --- a/apps/example-sender/svelte.config.js +++ b/apps/example-sender/svelte.config.js @@ -7,6 +7,7 @@ const config = { runes: ({ filename }) => (filename.split(/[/\\]/).includes('node_modules') ? undefined : true) }, kit: { + experimental: { remoteFunctions: true }, // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list. // If your environment is not supported, or you settled on a specific environment, switch out the adapter. // See https://svelte.dev/docs/kit/adapters for more information about adapters. diff --git a/apps/example-sender/vite.config.ts b/apps/example-sender/vite.config.ts index 56f40c7..6bda53b 100644 --- a/apps/example-sender/vite.config.ts +++ b/apps/example-sender/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 86e2723..2697531 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,6 +13,16 @@ importers: version: 5.9.3 apps/example-sender: + dependencies: + '@atcute/atproto': + specifier: ^4.0.0 + version: 4.0.0(@atcute/lexicons@2.0.0) + '@svelte-atproto/oauth': + specifier: ^0.3.0 + version: 0.3.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) + valibot: + specifier: ^1.0.0 + version: 1.4.0(typescript@6.0.3) devDependencies: '@eslint/compat': specifier: ^2.0.4 @@ -235,11 +245,21 @@ packages: peerDependencies: '@atcute/lexicons': ^1.0.0 + '@atcute/atproto@4.0.0': + resolution: {integrity: sha512-Rd21kW0tl/QEXhyPkJXRpUV8HYs7sMOmmXRu2z1sKMZbm1tqvHz1L3CQeTFcC/Xf/5cg7S6ITGIKRP0++zu0aw==} + peerDependencies: + '@atcute/lexicons': ^2.0.0 + '@atcute/bluesky@3.3.5': resolution: {integrity: sha512-DmzdCQ1VkPRBsIMr79EDxLWLpg0UNWVahFjMelfzau717r+I3ceJm9SxfOK/of+biLOUj4rlr00tNZT+BRe6Ww==} peerDependencies: '@atcute/lexicons': ^1.0.0 + '@atcute/bluesky@4.0.2': + resolution: {integrity: sha512-CWe4P/FYfY1CQ4GUYyOVGDqDJ/VvtaG6T4Jtaep0ur8IwUpUTVWoiwM9qDp1EA8NWsb4y+KcdcOm8CZD0tMMwg==} + peerDependencies: + '@atcute/lexicons': ^2.0.0 + '@atcute/car@6.0.0': resolution: {integrity: sha512-v3lhHfqxBi/wxq3q4N9f3/9ed44xqwKI0VAlgPge9NKjJ2xuJcEvj12v4m+P2FB758cioCsghKy58tz2s20eAA==} peerDependencies: @@ -327,6 +347,12 @@ packages: '@atcute/identity-resolver': ^1.0.0 '@atcute/lexicons': ^1.0.0 + '@atcute/oauth-browser-client@4.0.0': + resolution: {integrity: sha512-rvxmRcA6WOZz5TfcKp1kVtxUioogMzQH5OdCrW3Fm+ldEPPe2ZEyP7x1PzRWo6Es3F8lm4Q7BCJJgJFkQp2a5Q==} + peerDependencies: + '@atcute/identity-resolver': ^2.0.0 + '@atcute/lexicons': ^2.0.0 + '@atcute/oauth-crypto@0.1.0': resolution: {integrity: sha512-qZYDCNLF/4B6AndYT1rsQelN8621AC5u/sL5PHvlr/qqAbmmUwCBGjEgRSyZtHE1AqD60VNiSMlOgAuEQTSl3w==} @@ -342,9 +368,18 @@ packages: '@atcute/identity-resolver': ^1.0.0 '@atcute/lexicons': ^1.0.0 + '@atcute/oauth-node-client@2.0.0': + resolution: {integrity: sha512-1+q7eszInPXR/aTmYyyhW6RD+rnNTpHXF3vgum3mmCt44oSCTeKuzCBrR538LORpspgNwhopotvKJ1AN5UD4kQ==} + peerDependencies: + '@atcute/identity-resolver': ^2.0.0 + '@atcute/lexicons': ^2.0.0 + '@atcute/oauth-types@0.1.1': resolution: {integrity: sha512-u+3KMjse3Uc/9hDyilu1QVN7IpcnjVXgRzhddzBB8Uh6wePHNVBDdi9wQvFTVVA3zmxtMJVptXRyLLg6Ou9bqg==} + '@atcute/oauth-types@1.0.0': + resolution: {integrity: sha512-YOpjLU8H5PG6oKfgau+dx7rSmGsLxIA36MeGL7BDeopcyq80RqPSBAzOasEEsmbMRJ/nTsMRJhnmGkp3RCa/Zw==} + '@atcute/repo@1.0.0': resolution: {integrity: sha512-3s6VDKMimmYxVXn9OTlYQ7bJGPRcZRyFZ+oF/IFdfm3PsEUxwwSXajw1bG0HVXns1rNgNnDUT0PqMlUd2GnjqA==} peerDependencies: @@ -1022,6 +1057,13 @@ packages: '@sveltejs/kit': ^2.0.0 svelte: ^5.0.0 + '@svelte-atproto/oauth@0.3.0': + resolution: {integrity: sha512-Tijm4GGMg15NrA2EH715GoGE0yHxPBL4dk8h+Zmb3L7ea/TLKayjVso3OgNg5drvBjrgrthO0oI3BYSudTbT0A==} + 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: @@ -2316,11 +2358,20 @@ snapshots: dependencies: '@atcute/lexicons': 1.3.1 + '@atcute/atproto@4.0.0(@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/bluesky@4.0.2(@atcute/lexicons@2.0.0)': + dependencies: + '@atcute/atproto': 4.0.0(@atcute/lexicons@2.0.0) + '@atcute/lexicons': 2.0.0 + '@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) @@ -2351,6 +2402,13 @@ snapshots: transitivePeerDependencies: - typescript + '@atcute/client@5.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3)': + dependencies: + '@atcute/identity': 2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3) + '@atcute/lexicons': 2.0.0 + transitivePeerDependencies: + - typescript + '@atcute/crypto@2.4.1': dependencies: '@atcute/multibase': 1.2.0 @@ -2373,6 +2431,15 @@ snapshots: transitivePeerDependencies: - typescript + '@atcute/identity-resolver@2.0.0(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@2.0.0)(typescript@6.0.3)': + dependencies: + '@atcute/identity': 2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3) + '@atcute/lexicons': 2.0.0 + '@atcute/util-fetch': 2.0.0(typescript@6.0.3) + valibot: 1.4.0(typescript@6.0.3) + transitivePeerDependencies: + - typescript + '@atcute/identity@1.1.5(@atcute/lexicons@1.3.1)': dependencies: '@atcute/lexicons': 1.3.1 @@ -2385,6 +2452,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) @@ -2463,6 +2537,18 @@ snapshots: transitivePeerDependencies: - typescript + '@atcute/oauth-browser-client@4.0.0(@atcute/identity-resolver@2.0.0(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@2.0.0)(typescript@6.0.3)': + dependencies: + '@atcute/client': 5.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3) + '@atcute/identity-resolver': 2.0.0(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@2.0.0)(typescript@6.0.3) + '@atcute/lexicons': 2.0.0 + '@atcute/multibase': 1.2.0 + '@atcute/oauth-crypto': 1.0.0(typescript@6.0.3) + '@atcute/oauth-types': 1.0.0(typescript@6.0.3) + nanoid: 5.1.11 + transitivePeerDependencies: + - typescript + '@atcute/oauth-crypto@0.1.0': dependencies: '@atcute/multibase': 1.2.0 @@ -2500,6 +2586,21 @@ snapshots: transitivePeerDependencies: - typescript + '@atcute/oauth-node-client@2.0.0(@atcute/identity-resolver@2.0.0(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@2.0.0)(typescript@6.0.3)': + dependencies: + '@atcute/client': 5.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3) + '@atcute/identity': 2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3) + '@atcute/identity-resolver': 2.0.0(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@2.0.0)(typescript@6.0.3) + '@atcute/lexicons': 2.0.0 + '@atcute/oauth-crypto': 1.0.0(typescript@6.0.3) + '@atcute/oauth-keyset': 0.1.1(typescript@6.0.3) + '@atcute/oauth-types': 1.0.0(typescript@6.0.3) + '@atcute/util-fetch': 2.0.0(typescript@6.0.3) + nanoid: 5.1.11 + valibot: 1.4.0(typescript@6.0.3) + transitivePeerDependencies: + - typescript + '@atcute/oauth-types@0.1.1(typescript@6.0.3)': dependencies: '@atcute/identity': 1.1.5(@atcute/lexicons@1.3.1) @@ -2509,6 +2610,15 @@ snapshots: transitivePeerDependencies: - typescript + '@atcute/oauth-types@1.0.0(typescript@6.0.3)': + dependencies: + '@atcute/identity': 2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3) + '@atcute/lexicons': 2.0.0 + '@atcute/oauth-keyset': 0.1.1(typescript@6.0.3) + valibot: 1.4.0(typescript@6.0.3) + 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) @@ -2537,6 +2647,12 @@ snapshots: transitivePeerDependencies: - typescript + '@atcute/util-fetch@2.0.0(typescript@6.0.3)': + dependencies: + valibot: 1.4.0(typescript@6.0.3) + transitivePeerDependencies: + - typescript + '@atcute/util-text@1.3.1': dependencies: unicode-segmenter: 0.14.5 @@ -3018,6 +3134,22 @@ snapshots: - '@atcute/identity' - typescript + '@svelte-atproto/oauth@0.3.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': 4.0.0(@atcute/lexicons@2.0.0) + '@atcute/bluesky': 4.0.2(@atcute/lexicons@2.0.0) + '@atcute/client': 5.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3) + '@atcute/identity-resolver': 2.0.0(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@2.0.0)(typescript@6.0.3) + '@atcute/lexicons': 2.0.0 + '@atcute/oauth-browser-client': 4.0.0(@atcute/identity-resolver@2.0.0(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@2.0.0)(typescript@6.0.3) + '@atcute/oauth-node-client': 2.0.0(@atcute/identity-resolver@2.0.0(@atcute/identity@2.0.0(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@2.0.0)(typescript@6.0.3))(@atcute/lexicons@2.0.0)(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 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 46f664a..82f7927 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -11,3 +11,4 @@ minimumReleaseAgeExclude: - "@cloudflare/workers-types@4.20260522.1" - miniflare@4.20260521.0 - wrangler@4.94.0 + - '@svelte-atproto/oauth@0.3.0' -- 2.51.2