The recipes.blue monorepo recipes.blue
recipes appview atproto

feat: more work on modernising the codebase

hayden.moe 6469e25e 6f53d1c4

verified
+1
.gitignore
··· 147 147 .sentryclirc 148 148 149 149 .turbo 150 + apps/api/.wrangler
-76
Caddyfile
··· 1 - { 2 - storage file_system /data/ 3 - debug 4 - pki { 5 - ca hayden { 6 - name "Hayden" 7 - } 8 - } 9 - } 10 - 11 - api.dev.hayden.moe { 12 - tls { 13 - issuer internal { 14 - ca hayden 15 - } 16 - } 17 - 18 - reverse_proxy http://host.docker.internal:8080 19 - } 20 - 21 - cookware.dev.hayden.moe { 22 - tls { 23 - issuer internal { 24 - ca hayden 25 - } 26 - } 27 - 28 - reverse_proxy http://host.docker.internal:5173 29 - 30 - handle_path /xrpc/* { 31 - rewrite * /xrpc{uri} 32 - reverse_proxy http://host.docker.internal:8080 33 - } 34 - handle_path /api/* { 35 - rewrite * /api{uri} 36 - reverse_proxy http://host.docker.internal:8080 37 - } 38 - } 39 - 40 - http://*.trycloudflare.com { 41 - reverse_proxy http://host.docker.internal:5173 42 - 43 - handle_path /xrpc/* { 44 - rewrite * /xrpc{uri} 45 - reverse_proxy http://host.docker.internal:8080 46 - } 47 - handle_path /oauth/* { 48 - rewrite * /oauth{uri} 49 - reverse_proxy http://host.docker.internal:8080 50 - } 51 - handle_path /api/* { 52 - rewrite * /api{uri} 53 - reverse_proxy http://host.docker.internal:8080 54 - } 55 - } 56 - 57 - acme.dev.hayden.moe { 58 - tls { 59 - issuer internal { 60 - ca hayden 61 - } 62 - } 63 - acme_server { 64 - ca hayden 65 - } 66 - } 67 - 68 - turso.dev.hayden.moe { 69 - tls { 70 - issuer internal { 71 - ca hayden 72 - } 73 - } 74 - 75 - reverse_proxy http://libsql:8080 76 - }
+1
apps/api/migrations
··· 1 + ../../libs/database/migrations
+8 -5
apps/api/package.json
··· 2 2 "name": "@cookware/api", 3 3 "type": "module", 4 4 "private": true, 5 - "main": "dist/index.js", 5 + "main": "src/index.ts", 6 6 "publishConfig": { 7 7 "access": "public" 8 8 }, 9 9 "scripts": { 10 - "dev": "NODE_OPTIONS=--use-openssl-ca tsx watch --clear-screen=false src/index.ts | pino-pretty", 10 + "dev": "wrangler dev", 11 11 "build": "tsup", 12 12 "start": "NODE_OPTIONS=--use-openssl-ca node dist/index.cjs", 13 13 "clean": "rimraf dist" 14 14 }, 15 15 "dependencies": { 16 - "@atcute/client": "^2.0.6", 16 + "@atcute/atproto": "^3.1.9", 17 + "@atcute/client": "^4.0.5", 18 + "@atcute/lexicons": "^1.2.3", 17 19 "@atcute/xrpc-server": "^0.1.3", 18 20 "@atcute/xrpc-server-cloudflare": "^0.1.0", 19 21 "@atproto/api": "^0.13.19", ··· 38 40 "zod": "^3.23.8" 39 41 }, 40 42 "devDependencies": { 41 - "@atcute/bluesky": "^1.0.9", 43 + "@atcute/bluesky": "^3.2.10", 42 44 "@cookware/tsconfig": "workspace:*", 43 45 "@swc/core": "^1.9.3", 44 46 "@types/ws": "^8.5.13", ··· 48 50 "ts-node": "^10.9.2", 49 51 "tsup": "^8.3.5", 50 52 "tsx": "^4.19.2", 51 - "typescript": "^5.7.2" 53 + "typescript": "^5.7.2", 54 + "wrangler": "^4.50.0" 52 55 }, 53 56 "tsup": { 54 57 "entry": [
-34
apps/api/src/config/env.ts
··· 1 - import { z } from "zod"; 2 - 3 - const envSchema = z.object({ 4 - PORT: z.coerce.number().lte(65535).default(8080), 5 - HOST: z.string().ip().default('0.0.0.0'), 6 - 7 - PUBLIC_DIR: z.string().default('../web/dist'), 8 - 9 - CORS_ORIGINS: z 10 - .string() 11 - .transform((arg) => arg.split(',')) 12 - .default('http://127.0.0.1:5173,https://cookware.local.recipes.blue'), 13 - 14 - PLC_DIRECTORY_URL: z.string().url().default('https://plc.directory'), 15 - 16 - JWKS_PRIVATE_KEY: z.string().default('{"kty":"EC","x":"pew2xWIyBQ4XSY4gcCuTJBI-oC5rQqQlcDxIN8nN834","y":"aiJFNEFWyKKWGiFKPRvLAU4wdhsfgysfTfTuzTC4LNQ","crv":"P-256","d":"QS-q9RzH1u2Oj8gDiUzLk1qpGxZjKSf-3Z1oKCRL_jQ"}'), 17 - 18 - SESSION_KEY: z.string().default('bJVS+Dx03A3QWWfW3A5Om5DGx1GKptx+1IGAXzOTpw8='), 19 - SESSION_TTL: z.number().default(((60 * 60) * 24) * 5), // expire in 5 days 20 - 21 - SENTRY_DSN: z.string().or(z.undefined()), 22 - 23 - ENV: z 24 - .union([ 25 - z.literal('development'), 26 - z.literal('production'), 27 - ]) 28 - .default('development'), 29 - }); 30 - 31 - const env = envSchema.parse(process.env); 32 - 33 - export default env; 34 - export type Env = z.infer<typeof envSchema>;
+10
apps/api/src/env.d.ts
··· 1 1 /// <reference types="@atcute/bluesky/lexicons" /> 2 2 /// <reference types="@cookware/lexicons" /> 3 + 4 + import { DrizzleD1Database } from "drizzle-orm/d1"; 5 + 6 + declare global { 7 + interface RouterContext { 8 + env: Env; 9 + ctx: ExecutionContext; 10 + db: DrizzleD1Database; 11 + } 12 + }
+22 -75
apps/api/src/index.ts
··· 1 - import { json, XRPCRouter } from '@atcute/xrpc-server'; 1 + import { XRPCRouter } from '@atcute/xrpc-server'; 2 2 import { cors } from '@atcute/xrpc-server/middlewares/cors'; 3 3 import { createCloudflareWebSocket } from '@atcute/xrpc-server-cloudflare'; 4 - import { BlueRecipesFeedDefs, BlueRecipesFeedGetRecipes } from '@cookware/lexicons'; 5 - import { DID, getDidFromHandleOrDid } from '@cookware/lexicons/did'; 6 - import { db, recipeTable } from '@cookware/database'; 7 - import { desc, eq, sql } from 'drizzle-orm'; 8 - import { simpleFetchHandler, XRPC } from '@atcute/client'; 9 - import { getAuthorInfo } from './util/api.js'; 4 + import { registerGetRecipes } from './xrpc/blue.recipes.feed.getRecipes.js'; 5 + import { drizzle } from 'drizzle-orm/d1'; 6 + import { registerGetRecipe } from './xrpc/blue.recipes.feed.getRecipe.js'; 10 7 11 - const adapter = createCloudflareWebSocket(); 12 - const router = new XRPCRouter({ 13 - websocket: adapter, 14 - middlewares: [ 15 - cors({ 16 - allowedHeaders: ['Content-Type', 'Accept'], 17 - exposedHeaders: ['Content-Length'], 18 - }), 19 - ], 20 - }); 21 - 22 - router.addQuery(BlueRecipesFeedGetRecipes.mainSchema, { 23 - async handler({ params: { did: didQuery } }) { 24 - let did: DID | null = null; 25 - if (didQuery) 26 - did = await getDidFromHandleOrDid(didQuery); 27 - 28 - const recipes = await db 29 - .select({ 30 - rkey: recipeTable.rkey, 31 - title: recipeTable.title, 32 - description: recipeTable.description, 33 - time: recipeTable.time, 34 - serves: recipeTable.serves, 35 - ingredientsCount: sql`json_array_length(${recipeTable.ingredients})`, 36 - stepsCount: sql`json_array_length(${recipeTable.steps})`, 37 - createdAt: recipeTable.createdAt, 38 - authorDid: recipeTable.authorDid, 39 - imageRef: recipeTable.imageRef, 40 - uri: sql`concat(${recipeTable.authorDid}, "/", ${recipeTable.rkey})`.as('uri'), 41 - }) 42 - .from(recipeTable) 43 - .where(did ? eq(recipeTable.authorDid, did) : undefined) 44 - .orderBy(desc(recipeTable.createdAt)); 45 - 46 - const rpc = new XRPC({ 47 - handler: simpleFetchHandler({ 48 - service: 'https://public.api.bsky.app', 8 + const createRouter = (env: Env, ctx: ExecutionContext) => { 9 + const adapter = createCloudflareWebSocket(); 10 + const router = new XRPCRouter({ 11 + websocket: adapter, 12 + middlewares: [ 13 + cors({ 14 + allowedHeaders: ['Content-Type', 'Accept'], 15 + exposedHeaders: ['Content-Length'], 49 16 }), 50 - }); 51 - 52 - let authorInfo: BlueRecipesFeedDefs.AuthorInfo | null = null; 53 - if (did) { 54 - authorInfo = await getAuthorInfo(did, rpc); 55 - }; 17 + ], 18 + }); 56 19 57 - const results = []; 58 - const eachRecipe = async (r: typeof recipes[0]) => ({ 59 - author: authorInfo || await getAuthorInfo(r.authorDid, rpc), 60 - rkey: r.rkey, 61 - title: r.title, 62 - time: r.time, 63 - serves: r.serves ?? 1, 64 - description: r.description || undefined, 65 - ingredients: r.ingredientsCount as number, 66 - steps: r.stepsCount as number, 67 - imageUrl: r.imageRef 68 - ? `https://cdn.bsky.app/img/feed_thumbnail/plain/${r.authorDid}/${r.imageRef}@jpeg` 69 - : undefined, 70 - }); 20 + const db = drizzle(env.DB, { logger: true }); 71 21 72 - for (const result of recipes) { 73 - results.push(await eachRecipe(result)); 74 - } 22 + registerGetRecipes(router, { env, ctx, db }); 23 + registerGetRecipe(router, { env, ctx, db }); 75 24 76 - return json({ 77 - author: authorInfo || undefined, 78 - recipes: results, 79 - }); 80 - } 81 - }); 25 + return router; 26 + } 82 27 83 - export default router satisfies ExportedHandler; 28 + export default { 29 + fetch: (req, env, ctx) => createRouter(env, ctx).fetch(req), 30 + } satisfies ExportedHandler<Env>;
-5
apps/api/src/logger.ts
··· 1 - import { pino } from "pino"; 2 - 3 - export const rootLogger = pino({ name: 'recipes' }); 4 - export const apiLogger = pino({ name: 'recipes.api' }); 5 - export const authLogger = pino({ name: 'recipes.auth' });
-5
apps/api/src/recipes/index.ts
··· 1 - import { Hono } from "hono"; 2 - 3 - export const recipeApp = new Hono(); 4 - 5 - recipeApp.post('/', async ctx => {});
+22 -10
apps/api/src/util/api.ts
··· 1 - import { XRPC } from '@atcute/client'; 2 - import { AppBskyActorProfile } from '@atcute/client/lexicons'; 1 + import { Client } from '@atcute/client'; 2 + import { AppBskyActorProfile } from '@atcute/bluesky'; 3 3 import type { BlueRecipesFeedDefs } from '@cookware/lexicons'; 4 - import { DID, getDidDoc } from '@cookware/lexicons/did'; 4 + import { getDidDoc } from '@cookware/lexicons/did'; 5 + import { Did } from '@atcute/lexicons'; 6 + 7 + import type {} from '@atcute/atproto'; 8 + import { isBlob, isLegacyBlob } from '@atcute/lexicons/interfaces'; 5 9 6 10 export const getAuthorInfo = async ( 7 - did: DID, 8 - rpc: XRPC, 11 + did: Did, 12 + rpc: Client, 9 13 ): Promise<BlueRecipesFeedDefs.AuthorInfo> => { 10 14 const author = await getDidDoc(did); 11 - const profile = await rpc.get('com.atproto.repo.getRecord', { 15 + const { ok, data } = await rpc.get('com.atproto.repo.getRecord', { 12 16 params: { 13 17 repo: did, 14 18 collection: 'app.bsky.actor.profile', 15 19 rkey: 'self', 16 20 }, 17 21 }); 18 - const data = profile.data.value as AppBskyActorProfile.Record; 22 + 23 + if (!ok) throw new Error(`Failed to query Bluesky profile: ${data.error}`); 24 + 25 + const profile = data.value as AppBskyActorProfile.Main; 19 26 20 27 let info: BlueRecipesFeedDefs.AuthorInfo = { 21 28 did: did, 22 29 handle: author.alsoKnownAs[0]?.substring(5) as string, 23 - displayName: data.displayName, 30 + displayName: profile.displayName, 24 31 }; 25 32 26 - if (data.avatar) 27 - info['avatarUrl'] = `https://cdn.bsky.app/img/avatar_thumbnail/plain/${did}/${data.avatar.ref.$link}@jpeg`; 33 + if (profile.avatar) { 34 + if (isBlob(profile.avatar)) { 35 + info['avatarUrl'] = `https://cdn.bsky.app/img/avatar_thumbnail/plain/${did}/${profile.avatar.ref.$link}@jpeg`; 36 + } else if (isLegacyBlob(profile.avatar)) { 37 + info.avatarUrl = `https://cdn.bsky.app/img/avatar_thumbnail/plain/${did}/${profile.avatar.cid}@jpeg` 38 + } 39 + } 28 40 29 41 return info; 30 42 };
+67
apps/api/src/xrpc/blue.recipes.feed.getRecipe.ts
··· 1 + import { json, XRPCRouter, XRPCError } from '@atcute/xrpc-server'; 2 + import { BlueRecipesFeedGetRecipe } from '@cookware/lexicons'; 3 + import { getDidFromHandleOrDid } from '@cookware/lexicons/did'; 4 + import { recipeTable } from '@cookware/database'; 5 + import { and, eq } from 'drizzle-orm'; 6 + import { Client, simpleFetchHandler } from '@atcute/client'; 7 + import { getAuthorInfo } from '../util/api.js'; 8 + 9 + export const registerGetRecipe = (router: XRPCRouter, { db }: RouterContext) => { 10 + router.addQuery(BlueRecipesFeedGetRecipe.mainSchema, { 11 + async handler({ params: { did, rkey } }) { 12 + if (!did) throw new Error('Invalid DID'); 13 + if (!rkey) throw new Error('Invalid rkey'); 14 + 15 + let parsedDid = await getDidFromHandleOrDid(did); 16 + if (!parsedDid) { 17 + throw new XRPCError({ 18 + status: 404, 19 + error: 'InvalidDid', 20 + description: 'No such author was found by that identifier.', 21 + }); 22 + } 23 + 24 + const recipe = await db 25 + .select() 26 + .from(recipeTable) 27 + .where( 28 + and( 29 + eq(recipeTable.authorDid, parsedDid), 30 + eq(recipeTable.rkey, rkey), 31 + ), 32 + ) 33 + .limit(1) 34 + .get(); 35 + 36 + if (!recipe) { 37 + throw new XRPCError({ 38 + status: 404, 39 + error: 'RecipeNotFound', 40 + description: 'No such recipe was found in the index.', 41 + }); 42 + } 43 + 44 + const rpc = new Client({ 45 + handler: simpleFetchHandler({ 46 + service: 'https://public.api.bsky.app', 47 + }), 48 + }); 49 + 50 + const authorInfo = await getAuthorInfo(recipe.authorDid, rpc); 51 + 52 + return json({ 53 + recipe: { 54 + author: authorInfo, 55 + title: recipe.title, 56 + time: recipe.time, 57 + serves: recipe.serves || undefined, 58 + description: recipe.description || undefined, 59 + ingredients: recipe.ingredients, 60 + steps: recipe.steps, 61 + imageUrl: recipe.imageRef 62 + ? `https://cdn.bsky.app/img/feed_thumbnail/plain/${recipe.authorDid}/${recipe.imageRef}@jpeg` 63 + : undefined, 64 + }, 65 + }); } 66 + }); 67 + };
+70
apps/api/src/xrpc/blue.recipes.feed.getRecipes.ts
··· 1 + import { json, XRPCRouter } from '@atcute/xrpc-server'; 2 + import { BlueRecipesFeedDefs, BlueRecipesFeedGetRecipes } from '@cookware/lexicons'; 3 + import { DID, getDidFromHandleOrDid } from '@cookware/lexicons/did'; 4 + import { recipeTable } from '@cookware/database'; 5 + import { desc, eq, sql } from 'drizzle-orm'; 6 + import { simpleFetchHandler, XRPC } from '@atcute/client'; 7 + import { getAuthorInfo } from '../util/api.js'; 8 + 9 + export const registerGetRecipes = (router: XRPCRouter, { db }: RouterContext) => { 10 + router.addQuery(BlueRecipesFeedGetRecipes.mainSchema, { 11 + async handler({ params: { did: didQuery } }) { 12 + let did: DID | null = null; 13 + if (didQuery) 14 + did = await getDidFromHandleOrDid(didQuery); 15 + 16 + const recipes = await db 17 + .select({ 18 + rkey: recipeTable.rkey, 19 + title: recipeTable.title, 20 + description: recipeTable.description, 21 + time: recipeTable.time, 22 + serves: recipeTable.serves, 23 + ingredientsCount: sql`json_array_length(${recipeTable.ingredients})`, 24 + stepsCount: sql`json_array_length(${recipeTable.steps})`, 25 + createdAt: recipeTable.createdAt, 26 + authorDid: recipeTable.authorDid, 27 + imageRef: recipeTable.imageRef, 28 + uri: sql`concat(${recipeTable.authorDid}, "/", ${recipeTable.rkey})`.as('uri'), 29 + }) 30 + .from(recipeTable) 31 + .where(did ? eq(recipeTable.authorDid, did) : undefined) 32 + .orderBy(desc(recipeTable.createdAt)); 33 + 34 + const rpc = new XRPC({ 35 + handler: simpleFetchHandler({ 36 + service: 'https://public.api.bsky.app', 37 + }), 38 + }); 39 + 40 + let authorInfo: BlueRecipesFeedDefs.AuthorInfo | null = null; 41 + if (did) { 42 + authorInfo = await getAuthorInfo(did, rpc); 43 + }; 44 + 45 + const results = []; 46 + const eachRecipe = async (r: typeof recipes[0]) => ({ 47 + author: authorInfo || await getAuthorInfo(r.authorDid, rpc), 48 + rkey: r.rkey, 49 + title: r.title, 50 + time: r.time, 51 + serves: r.serves ?? 1, 52 + description: r.description || undefined, 53 + ingredients: r.ingredientsCount as number, 54 + steps: r.stepsCount as number, 55 + imageUrl: r.imageRef 56 + ? `https://cdn.bsky.app/img/feed_thumbnail/plain/${r.authorDid}/${r.imageRef}@jpeg` 57 + : undefined, 58 + }); 59 + 60 + for (const result of recipes) { 61 + results.push(await eachRecipe(result)); 62 + } 63 + 64 + return json({ 65 + author: authorInfo || undefined, 66 + recipes: results, 67 + }); 68 + } 69 + }); 70 + };
-125
apps/api/src/xrpc/index.ts
··· 1 - import { Hono } from 'hono'; 2 - import { db, recipeTable } from '@cookware/database'; 3 - import { and, desc, eq, sql } from 'drizzle-orm'; 4 - import { DID, getDidFromHandleOrDid } from '@cookware/lexicons'; 5 - import { simpleFetchHandler, XRPC } from '@atcute/client'; 6 - import { BlueRecipesFeedDefs, BlueRecipesFeedGetRecipes } from '@atcute/client/lexicons'; 7 - import { getAuthorInfo } from '../util/api.js'; 8 - 9 - export const xrpcApp = new Hono(); 10 - 11 - xrpcApp.get('/blue.recipes.feed.getRecipes', async ctx => { 12 - const { did: didQuery } = ctx.req.query(); 13 - 14 - let did: DID | null = null; 15 - if (didQuery) 16 - did = await getDidFromHandleOrDid(didQuery); 17 - 18 - const recipes = await db 19 - .select({ 20 - rkey: recipeTable.rkey, 21 - title: recipeTable.title, 22 - description: recipeTable.description, 23 - time: recipeTable.time, 24 - serves: recipeTable.serves, 25 - ingredientsCount: sql`json_array_length(${recipeTable.ingredients})`, 26 - stepsCount: sql`json_array_length(${recipeTable.steps})`, 27 - createdAt: recipeTable.createdAt, 28 - authorDid: recipeTable.authorDid, 29 - imageRef: recipeTable.imageRef, 30 - uri: sql`concat(${recipeTable.authorDid}, "/", ${recipeTable.rkey})`.as('uri'), 31 - }) 32 - .from(recipeTable) 33 - .where(did ? eq(recipeTable.authorDid, did) : undefined) 34 - .orderBy(desc(recipeTable.createdAt)); 35 - 36 - const rpc = new XRPC({ 37 - handler: simpleFetchHandler({ 38 - service: 'https://public.api.bsky.app', 39 - }), 40 - }); 41 - 42 - let authorInfo: BlueRecipesFeedDefs.AuthorInfo | null = null; 43 - if (did) { 44 - authorInfo = await getAuthorInfo(did, rpc); 45 - }; 46 - 47 - const results = []; 48 - const eachRecipe = async (r: typeof recipes[0]) => ({ 49 - author: authorInfo || await getAuthorInfo(r.authorDid, rpc), 50 - rkey: r.rkey, 51 - title: r.title, 52 - time: r.time, 53 - serves: r.serves ?? 1, 54 - description: r.description || undefined, 55 - ingredients: r.ingredientsCount as number, 56 - steps: r.stepsCount as number, 57 - imageUrl: r.imageRef 58 - ? `https://cdn.bsky.app/img/feed_thumbnail/plain/${r.authorDid}/${r.imageRef}@jpeg` 59 - : undefined, 60 - }); 61 - 62 - for (const result of recipes) { 63 - results.push(await eachRecipe(result)); 64 - } 65 - 66 - let result: BlueRecipesFeedGetRecipes.Output = { 67 - author: authorInfo || undefined, 68 - recipes: results, 69 - }; 70 - 71 - return ctx.json(result); 72 - }); 73 - 74 - xrpcApp.get('/blue.recipes.feed.getRecipe', async ctx => { 75 - const { did, rkey } = ctx.req.query(); 76 - if (!did) throw new Error('Invalid DID'); 77 - if (!rkey) throw new Error('Invalid rkey'); 78 - 79 - let parsedDid = await getDidFromHandleOrDid(did); 80 - if (!parsedDid) { 81 - ctx.status(404); 82 - return ctx.json({ 83 - error: 'invalid_did', 84 - message: 'No such author was found by that identifier.', 85 - }); 86 - } 87 - 88 - const recipe = await db.query.recipeTable.findFirst({ 89 - where: and( 90 - eq(recipeTable.authorDid, parsedDid), 91 - eq(recipeTable.rkey, rkey), 92 - ), 93 - }); 94 - 95 - if (!recipe) { 96 - ctx.status(404); 97 - return ctx.json({ 98 - error: 'not_found', 99 - message: 'No such recipe was found in the index.', 100 - }); 101 - } 102 - 103 - const rpc = new XRPC({ 104 - handler: simpleFetchHandler({ 105 - service: 'https://public.api.bsky.app', 106 - }), 107 - }); 108 - 109 - const authorInfo = await getAuthorInfo(recipe.authorDid, rpc); 110 - 111 - return ctx.json({ 112 - recipe: { 113 - author: authorInfo, 114 - title: recipe.title, 115 - time: recipe.time, 116 - serves: recipe.serves, 117 - description: recipe.description, 118 - ingredients: recipe.ingredients, 119 - steps: recipe.steps, 120 - imageUrl: recipe.imageRef 121 - ? `https://cdn.bsky.app/img/feed_thumbnail/plain/${recipe.authorDid}/${recipe.imageRef}@jpeg` 122 - : null, 123 - }, 124 - }); 125 - });
+2 -1
apps/api/worker-configuration.d.ts
··· 1 1 /* eslint-disable */ 2 - // Generated by Wrangler by running `wrangler types` (hash: b739a9c19cff1463949c4db47674ed86) 2 + // Generated by Wrangler by running `wrangler types` (hash: 973863b87c5f17b377119a1dc8be79cf) 3 3 // Runtime types generated with workerd@1.20251118.0 2025-11-23 4 4 declare namespace Cloudflare { 5 5 interface GlobalProps { 6 6 mainModule: typeof import("./src/index"); 7 7 } 8 8 interface Env { 9 + DB: D1Database; 9 10 } 10 11 } 11 12 interface Env extends Cloudflare.Env {}
+14
apps/api/wrangler.json
··· 1 + { 2 + "$schema": "./node_modules/wrangler/config-schema.json", 3 + "name": "recipes-blue-api", 4 + "main": "src/index.ts", 5 + "compatibility_date": "2025-11-23", 6 + "observability": { "enabled": true }, 7 + "d1_databases": [ 8 + { 9 + "binding": "DB", 10 + "database_name": "recipesblue", 11 + "migrations_dir": "../../libs/database/migrations" 12 + } 13 + ] 14 + }
-4
apps/api/wrangler.toml
··· 1 - name = "recipes-blue-api" 2 - main = "src/index.ts" 3 - compatibility_date = "2025-11-23" 4 - workers_dev = false
+1 -1
apps/ingester/package.json
··· 13 13 "clean": "rimraf dist" 14 14 }, 15 15 "dependencies": { 16 - "@atcute/client": "^2.0.6", 16 + "@atcute/client": "^4.0.5", 17 17 "@cookware/database": "workspace:^", 18 18 "@sentry/node": "^8.42.0", 19 19 "@skyware/jetstream": "^0.2.1",
+3 -1
apps/web/package.json
··· 10 10 "preview": "vite preview" 11 11 }, 12 12 "dependencies": { 13 - "@atcute/client": "^2.0.6", 13 + "@atcute/atproto": "^3.1.9", 14 + "@atcute/client": "^4.0.5", 15 + "@atcute/lexicons": "^1.2.3", 14 16 "@atcute/oauth-browser-client": "^1.0.7", 15 17 "@atproto/common": "^0.4.5", 16 18 "@atproto/common-web": "^0.3.1",
+6 -6
apps/web/src/hooks/use-xrpc.tsx
··· 1 1 import { SERVER_URL } from "@/lib/utils"; 2 2 import { useAuth } from "@/state/auth"; 3 - import { CredentialManager, XRPC } from "@atcute/client" 3 + import { Client, simpleFetchHandler } from "@atcute/client"; 4 4 5 5 export function useXrpc() { 6 6 const { agent } = useAuth(); 7 7 8 8 if (agent) { 9 - return new XRPC({ 9 + return new Client({ 10 10 handler: agent, 11 11 proxy: { 12 - type: 'api', 13 - service: `did:web:${SERVER_URL}`, 12 + did: `did:web:${SERVER_URL}`, 13 + serviceId: '#recipes_blue', 14 14 }, 15 15 }); 16 16 } 17 17 18 - const creds = new CredentialManager({ service: `https://${SERVER_URL}` }); 19 - return new XRPC({ handler: creds }); 18 + const handler = simpleFetchHandler({ service: `https://${SERVER_URL}` }); 19 + return new Client({ handler }); 20 20 }
+37 -21
apps/web/src/queries/recipe.ts
··· 1 1 import { useXrpc } from "@/hooks/use-xrpc"; 2 2 import { useAuth } from "@/state/auth"; 3 - import { XRPC, XRPCError } from "@atcute/client"; 4 - import { RecipeCollection } from "@cookware/lexicons"; 5 3 import { queryOptions, useMutation, useQuery } from "@tanstack/react-query"; 4 + import { Client } from "@atcute/client"; 6 5 import { notFound } from "@tanstack/react-router"; 7 6 import { UseFormReturn } from "react-hook-form"; 8 7 import { TID } from '@atproto/common-web'; 9 8 import { recipeSchema } from "@/forms/recipe"; 10 9 import { z } from "zod"; 10 + import { ActorIdentifier, Did } from "@atcute/lexicons"; 11 + 12 + import type {} from '@atcute/atproto'; 13 + import type {} from '@cookware/lexicons'; 11 14 12 15 const RQKEY_ROOT = 'posts'; 13 16 export const RQKEY = (cursor: string, did: string, rkey: string) => [RQKEY_ROOT, cursor, did, rkey]; 14 17 15 - export const useRecipesQuery = (cursor: string, did?: string) => { 18 + export const useRecipesQuery = (cursor: string, did?: Did) => { 16 19 const rpc = useXrpc(); 17 20 return useQuery({ 18 21 queryKey: RQKEY(cursor, did ?? '', ''), ··· 25 28 }); 26 29 }; 27 30 28 - export const recipeQueryOptions = (rpc: XRPC, did: string, rkey: string) => { 31 + export const recipeQueryOptions = (rpc: Client, did: Did, rkey: string) => { 29 32 return queryOptions({ 30 33 queryKey: RQKEY('', did, rkey), 31 34 queryFn: async () => { 32 - try { 33 - const res = await rpc.get('blue.recipes.feed.getRecipe', { 35 + const { ok, data } = await rpc.get('blue.recipes.feed.getRecipe', { 34 36 params: { did, rkey }, 35 37 }); 36 - return res.data; 37 - } catch (err) { 38 - if (err instanceof XRPCError && err.kind && err.kind == 'not_found') { 39 - throw notFound({ routeId: '/_' }); 38 + 39 + if (!ok) { 40 + switch (data.error) { 41 + case 'RecipeNotFound': 42 + throw notFound({ routeId: '/_' }); 43 + default: 44 + throw new Error(`Error fetching recipe: ${data.error}`); 40 45 } 41 - throw err; 42 46 } 47 + 48 + return data; 43 49 }, 44 50 }); 45 51 }; 46 52 47 - export const useRecipeQuery = (did: string, rkey: string) => { 53 + export const useRecipeQuery = (did: Did, rkey: string) => { 48 54 const rpc = useXrpc(); 49 55 return useQuery(recipeQueryOptions(rpc, did, rkey)); 50 56 }; ··· 58 64 let recipeImg = null; 59 65 if (image) { 60 66 const imageFile = image.item(0) as File; 61 - const res = await rpc.call('com.atproto.repo.uploadBlob', { 62 - data: imageFile, 67 + const { ok, data } = await rpc.post('com.atproto.repo.uploadBlob', { 68 + input: imageFile, 63 69 }); 64 - recipeImg = res.data.blob 70 + 71 + if (!ok) { 72 + throw new Error(`Image upload failed: ${data.error}`); 73 + } 74 + 75 + recipeImg = data.blob; 65 76 } 66 77 67 78 const rkey = TID.nextStr(); 68 - const res = await rpc.call(`com.atproto.repo.createRecord`, { 69 - data: { 70 - repo: agent?.session.info.sub as `did:${string}`, 79 + const { ok, data } = await rpc.post(`com.atproto.repo.createRecord`, { 80 + input: { 81 + repo: agent?.session.info.sub as ActorIdentifier, 71 82 record: { 72 83 ...recipe, 73 84 image: recipeImg, 74 85 }, 75 - collection: RecipeCollection, 86 + collection: 'blue.recipes.feed.recipe', 76 87 rkey: rkey, 77 - }, 88 + } 78 89 }); 90 + 91 + if (!ok) { 92 + throw new Error(`Recipe creation failed: ${data.error}`); 93 + } 94 + 79 95 return { 80 96 rkey: rkey, 81 - resp: res.data 97 + resp: data, 82 98 }; 83 99 }, 84 100 onError: (error) => {
+2 -2
apps/web/src/state/auth.tsx
··· 1 - import { At } from "@atcute/client/lexicons"; 1 + import { Did } from "@atcute/lexicons"; 2 2 import { finalizeAuthorization, getSession, OAuthUserAgent } from "@atcute/oauth-browser-client"; 3 3 import { createContext, PropsWithChildren, useContext, useEffect, useState } from "react"; 4 4 ··· 36 36 37 37 if (lastSignedIn) { 38 38 try { 39 - return await getSession(lastSignedIn as At.DID); 39 + return await getSession(lastSignedIn as Did); 40 40 } catch (err) { 41 41 localStorage.removeItem("lastSignedIn"); 42 42 throw err;
+184 -11
bun.lock
··· 10 10 "apps/api": { 11 11 "name": "@cookware/api", 12 12 "dependencies": { 13 - "@atcute/client": "^2.0.6", 13 + "@atcute/atproto": "^3.1.9", 14 + "@atcute/client": "^4.0.5", 15 + "@atcute/lexicons": "^1.2.3", 14 16 "@atcute/xrpc-server": "^0.1.3", 15 17 "@atcute/xrpc-server-cloudflare": "^0.1.0", 16 18 "@atproto/api": "^0.13.19", ··· 35 37 "zod": "^3.23.8", 36 38 }, 37 39 "devDependencies": { 38 - "@atcute/bluesky": "^1.0.9", 40 + "@atcute/bluesky": "^3.2.10", 39 41 "@cookware/tsconfig": "workspace:*", 40 42 "@swc/core": "^1.9.3", 41 43 "@types/ws": "^8.5.13", ··· 46 48 "tsup": "^8.3.5", 47 49 "tsx": "^4.19.2", 48 50 "typescript": "^5.7.2", 51 + "wrangler": "^4.50.0", 49 52 }, 50 53 }, 51 54 "apps/ingester": { 52 55 "name": "@cookware/ingester", 53 56 "dependencies": { 54 - "@atcute/client": "^2.0.6", 57 + "@atcute/client": "^4.0.5", 55 58 "@cookware/database": "workspace:^", 56 59 "@sentry/node": "^8.42.0", 57 60 "@skyware/jetstream": "^0.2.1", ··· 78 81 "name": "@cookware/web", 79 82 "version": "0.0.0", 80 83 "dependencies": { 81 - "@atcute/client": "^2.0.6", 84 + "@atcute/atproto": "^3.1.9", 85 + "@atcute/client": "^4.0.5", 86 + "@atcute/lexicons": "^1.2.3", 82 87 "@atcute/oauth-browser-client": "^1.0.7", 83 88 "@atproto/common": "^0.4.5", 84 89 "@atproto/common-web": "^0.3.1", ··· 179 184 180 185 "@atcute/atproto": ["@atcute/atproto@3.1.9", "", { "dependencies": { "@atcute/lexicons": "^1.2.2" } }, "sha512-DyWwHCTdR4hY2BPNbLXgVmm7lI+fceOwWbE4LXbGvbvVtSn+ejSVFaAv01Ra3kWDha0whsOmbJL8JP0QPpf1+w=="], 181 186 182 - "@atcute/bluesky": ["@atcute/bluesky@1.0.15", "", { "peerDependencies": { "@atcute/client": "^1.0.0 || ^2.0.0" } }, "sha512-+EFiybmKQ97aBAgtaD+cKRJER5AMn3cZMkEwEg/pDdWyzxYJ9m1UgemmLdTgI8VrxPufKqdXS2nl7uO7TY6BPA=="], 187 + "@atcute/bluesky": ["@atcute/bluesky@3.2.10", "", { "dependencies": { "@atcute/atproto": "^3.1.9", "@atcute/lexicons": "^1.2.2" } }, "sha512-qwQWTzRf3umnh2u41gdU+xWYkbzGlKDupc3zeOB+YjmuP1N9wEaUhwS8H7vgrqr0xC9SGNDjeUVcjC4m5BPLBg=="], 183 188 184 189 "@atcute/cbor": ["@atcute/cbor@2.2.7", "", { "dependencies": { "@atcute/cid": "^2.2.5", "@atcute/multibase": "^1.1.6", "@atcute/uint8array": "^1.0.5" } }, "sha512-/mwAF0gnokOphceZqFq3uzMGdd8sbw5y6bxF8CRutRkCCUcpjjpJc5fkLwhxyGgOveF3mZuHE6p7t/+IAqb7Aw=="], 185 190 186 191 "@atcute/cid": ["@atcute/cid@2.2.6", "", { "dependencies": { "@atcute/multibase": "^1.1.6", "@atcute/uint8array": "^1.0.5" } }, "sha512-bTAHHbJ24p+E//V4KCS4xdmd39o211jJswvqQOevj7vk+5IYcgDLx1ryZWZ1sEPOo9x875li/kj5gpKL14RDwQ=="], 187 192 188 - "@atcute/client": ["@atcute/client@2.0.9", "", {}, "sha512-QNDm9gMP6x9LY77ArwY+urQOBtQW74/onEAz42c40JxRm6Rl9K9cU4ROvNKJ+5cpVmEm1sthEWVRmDr5CSZENA=="], 193 + "@atcute/client": ["@atcute/client@4.0.5", "", { "dependencies": { "@atcute/identity": "^1.1.1", "@atcute/lexicons": "^1.2.2" } }, "sha512-R8Qen8goGmEkynYGg2m6XFlVmz0GTDvQ+9w+4QqOob+XMk8/WDpF4aImev7WKEde/rV2gjcqW7zM8E6W9NShDA=="], 189 194 190 195 "@atcute/crypto": ["@atcute/crypto@2.2.6", "", { "dependencies": { "@atcute/multibase": "^1.1.6", "@atcute/uint8array": "^1.0.5", "@noble/secp256k1": "^3.0.0" } }, "sha512-vkuexF+kmrKE1/Uqzub99Qi4QpnxA2jbu60E6PTgL4XypELQ6rb59MB/J1VbY2gs0kd3ET7+L3+NWpKD5nXyfA=="], 191 196 ··· 327 332 328 333 "@cbor-extract/cbor-extract-win32-x64": ["@cbor-extract/cbor-extract-win32-x64@2.2.0", "", { "os": "win32", "cpu": "x64" }, "sha512-l2M+Z8DO2vbvADOBNLbbh9y5ST1RY5sqkWOg/58GkUPBYou/cuNZ68SGQ644f1CvZ8kcOxyZtw06+dxWHIoN/w=="], 329 334 335 + "@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.4.0", "", { "dependencies": { "mime": "^3.0.0" } }, "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA=="], 336 + 337 + "@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.7.11", "", { "peerDependencies": { "unenv": "2.0.0-rc.24", "workerd": "^1.20251106.1" }, "optionalPeers": ["workerd"] }, "sha512-se23f1D4PxKrMKOq+Stz+Yn7AJ9ITHcEecXo2Yjb+UgbUDCEBch1FXQC6hx6uT5fNA3kmX3mfzeZiUmpK1W9IQ=="], 338 + 339 + "@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20251118.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-UmWmYEYS/LkK/4HFKN6xf3Hk8cw70PviR+ftr3hUvs9HYZS92IseZEp16pkL6ZBETrPRpZC7OrzoYF7ky6kHsg=="], 340 + 341 + "@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20251118.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RockU7Qzf4rxNfY1lx3j4rvwutNLjTIX7rr2hogbQ4mzLo8Ea40/oZTzXVxl+on75joLBrt0YpenGW8o/r44QA=="], 342 + 343 + "@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20251118.0", "", { "os": "linux", "cpu": "x64" }, "sha512-aT97GnOAbJDuuOG0zPVhgRk0xFtB1dzBMrxMZ09eubDLoU4djH4BuORaqvxNRMmHgKfa4T6drthckT0NjUvBdw=="], 344 + 345 + "@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20251118.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-bXZPJcwlq00MPOXqP7DMWjr+goYj0+Fqyw6zgEC2M3FR1+SWla4yjghnZ4IdpN+H1t7VbUrsi5np2LzMUFs0NA=="], 346 + 347 + "@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20251118.0", "", { "os": "win32", "cpu": "x64" }, "sha512-2LV99AHSlpr8WcCb/BYbU2QsYkXLUL1izN6YKWkN9Eibv80JKX0RtgmD3dfmajE5sNvClavxZejgzVvHD9N9Ag=="], 348 + 330 349 "@cookware/api": ["@cookware/api@workspace:apps/api"], 331 350 332 351 "@cookware/database": ["@cookware/database@workspace:libs/database"], ··· 352 371 "@dnd-kit/utilities": ["@dnd-kit/utilities@3.2.2", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg=="], 353 372 354 373 "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="], 374 + 375 + "@emnapi/runtime": ["@emnapi/runtime@1.7.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA=="], 355 376 356 377 "@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="], 357 378 ··· 447 468 448 469 "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], 449 470 471 + "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="], 472 + 473 + "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="], 474 + 475 + "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg=="], 476 + 477 + "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ=="], 478 + 479 + "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.0.5", "", { "os": "linux", "cpu": "arm" }, "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g=="], 480 + 481 + "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA=="], 482 + 483 + "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.0.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA=="], 484 + 485 + "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw=="], 486 + 487 + "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA=="], 488 + 489 + "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw=="], 490 + 491 + "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.0.5" }, "os": "linux", "cpu": "arm" }, "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ=="], 492 + 493 + "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA=="], 494 + 495 + "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.0.4" }, "os": "linux", "cpu": "s390x" }, "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q=="], 496 + 497 + "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA=="], 498 + 499 + "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g=="], 500 + 501 + "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw=="], 502 + 503 + "@img/sharp-wasm32": ["@img/sharp-wasm32@0.33.5", "", { "dependencies": { "@emnapi/runtime": "^1.2.0" }, "cpu": "none" }, "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg=="], 504 + 505 + "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.33.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ=="], 506 + 507 + "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="], 508 + 450 509 "@ipld/dag-cbor": ["@ipld/dag-cbor@7.0.3", "", { "dependencies": { "cborg": "^1.6.0", "multiformats": "^9.5.4" } }, "sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA=="], 451 510 452 511 "@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="], ··· 575 634 576 635 "@pinojs/redact": ["@pinojs/redact@0.4.0", "", {}, "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg=="], 577 636 637 + "@poppinss/colors": ["@poppinss/colors@4.1.5", "", { "dependencies": { "kleur": "^4.1.5" } }, "sha512-FvdDqtcRCtz6hThExcFOgW0cWX+xwSMWcRuQe5ZEb2m7cVQOAVZOIMt+/v9RxGiD9/OY16qJBXK4CVKWAPalBw=="], 638 + 639 + "@poppinss/dumper": ["@poppinss/dumper@0.6.5", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@sindresorhus/is": "^7.0.2", "supports-color": "^10.0.0" } }, "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw=="], 640 + 641 + "@poppinss/exception": ["@poppinss/exception@1.2.2", "", {}, "sha512-m7bpKCD4QMlFCjA/nKTs23fuvoVFoA83brRKmObCUNmi/9tVu8Ve3w4YQAnJu4q3Tjf5fr685HYIC/IA2zHRSg=="], 642 + 578 643 "@prisma/instrumentation": ["@prisma/instrumentation@5.22.0", "", { "dependencies": { "@opentelemetry/api": "^1.8", "@opentelemetry/instrumentation": "^0.49 || ^0.50 || ^0.51 || ^0.52.0 || ^0.53.0", "@opentelemetry/sdk-trace-base": "^1.22" } }, "sha512-LxccF392NN37ISGxIurUljZSh1YWnphO34V5a0+T7FVQG2u9bhAXRTJpgmQ3483woVhkraQZFF7cbRrpbw/F4Q=="], 579 644 580 645 "@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="], ··· 699 764 700 765 "@sentry/opentelemetry": ["@sentry/opentelemetry@8.55.0", "", { "dependencies": { "@sentry/core": "8.55.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1", "@opentelemetry/core": "^1.30.1", "@opentelemetry/instrumentation": "^0.57.1", "@opentelemetry/sdk-trace-base": "^1.30.1", "@opentelemetry/semantic-conventions": "^1.28.0" } }, "sha512-UvatdmSr3Xf+4PLBzJNLZ2JjG1yAPWGe/VrJlJAqyTJ2gKeTzgXJJw8rp4pbvNZO8NaTGEYhhO+scLUj0UtLAQ=="], 701 766 767 + "@sindresorhus/is": ["@sindresorhus/is@7.1.1", "", {}, "sha512-rO92VvpgMc3kfiTjGT52LEtJ8Yc5kCWhZjLQ3LwlA4pSgPpQO7bVpYXParOD8Jwf+cVQECJo3yP/4I8aZtUQTQ=="], 768 + 702 769 "@skyware/jetstream": ["@skyware/jetstream@0.2.5", "", { "dependencies": { "@atcute/atproto": "^3.1.0", "@atcute/bluesky": "^3.1.4", "@atcute/lexicons": "^1.1.0", "partysocket": "^1.1.3", "tiny-emitter": "^2.1.0" } }, "sha512-fM/zs03DLwqRyzZZJFWN20e76KrdqIp97Tlm8Cek+vxn96+tu5d/fx79V6H85L0QN6HvGiX2l9A8hWFqHvYlOA=="], 703 770 771 + "@speed-highlight/core": ["@speed-highlight/core@1.2.12", "", {}, "sha512-uilwrK0Ygyri5dToHYdZSjcvpS2ZwX0w5aSt3GCEN9hrjxWCoeV4Z2DTXuxjwbntaLQIEEAlCeNQss5SoHvAEA=="], 772 + 704 773 "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], 705 774 706 775 "@swc/core": ["@swc/core@1.15.3", "", { "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.25" }, "optionalDependencies": { "@swc/core-darwin-arm64": "1.15.3", "@swc/core-darwin-x64": "1.15.3", "@swc/core-linux-arm-gnueabihf": "1.15.3", "@swc/core-linux-arm64-gnu": "1.15.3", "@swc/core-linux-arm64-musl": "1.15.3", "@swc/core-linux-x64-gnu": "1.15.3", "@swc/core-linux-x64-musl": "1.15.3", "@swc/core-win32-arm64-msvc": "1.15.3", "@swc/core-win32-ia32-msvc": "1.15.3", "@swc/core-win32-x64-msvc": "1.15.3" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" }, "optionalPeers": ["@swc/helpers"] }, "sha512-Qd8eBPkUFL4eAONgGjycZXj1jFCBW8Fd+xF0PzdTlBCWQIV1xnUT7B93wUANtW3KGjl3TRcOyxwSx/u/jyKw/Q=="], ··· 865 934 866 935 "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], 867 936 937 + "blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="], 938 + 868 939 "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], 869 940 870 941 "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], ··· 909 980 910 981 "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], 911 982 983 + "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], 984 + 912 985 "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], 913 986 914 987 "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], 915 988 989 + "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], 990 + 916 991 "colord": ["colord@2.9.3", "", {}, "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw=="], 917 992 918 993 "colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], ··· 928 1003 "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="], 929 1004 930 1005 "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], 1006 + 1007 + "cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="], 931 1008 932 1009 "cookie-es": ["cookie-es@2.0.0", "", {}, "sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg=="], 933 1010 ··· 995 1072 996 1073 "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], 997 1074 1075 + "error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="], 1076 + 998 1077 "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], 999 1078 1000 1079 "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], ··· 1041 1120 1042 1121 "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], 1043 1122 1123 + "exit-hook": ["exit-hook@2.2.1", "", {}, "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw=="], 1124 + 1044 1125 "fast-copy": ["fast-copy@3.0.2", "", {}, "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ=="], 1045 1126 1046 1127 "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], ··· 1100 1181 "glob": ["glob@13.0.0", "", { "dependencies": { "minimatch": "^10.1.1", "minipass": "^7.1.2", "path-scurry": "^2.0.0" } }, "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA=="], 1101 1182 1102 1183 "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], 1184 + 1185 + "glob-to-regexp": ["glob-to-regexp@0.4.1", "", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="], 1103 1186 1104 1187 "globals": ["globals@15.15.0", "", {}, "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg=="], 1105 1188 ··· 1137 1220 1138 1221 "iron-webcrypto": ["iron-webcrypto@1.2.1", "", {}, "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg=="], 1139 1222 1223 + "is-arrayish": ["is-arrayish@0.3.4", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="], 1224 + 1140 1225 "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], 1141 1226 1142 1227 "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], ··· 1177 1262 1178 1263 "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], 1179 1264 1265 + "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], 1266 + 1180 1267 "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], 1181 1268 1182 1269 "libsql": ["libsql@0.4.7", "", { "dependencies": { "@neon-rs/load": "^0.0.4", "detect-libc": "2.0.2" }, "optionalDependencies": { "@libsql/darwin-arm64": "0.4.7", "@libsql/darwin-x64": "0.4.7", "@libsql/linux-arm64-gnu": "0.4.7", "@libsql/linux-arm64-musl": "0.4.7", "@libsql/linux-x64-gnu": "0.4.7", "@libsql/linux-x64-musl": "0.4.7", "@libsql/win32-x64-msvc": "0.4.7" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ] }, "sha512-T9eIRCs6b0J1SHKYIvD8+KCJMcWZ900iZyxdnSCdqxN12Z1ijzT+jY5nrk72Jw4B0HGzms2NgpryArlJqvc3Lw=="], ··· 1211 1298 1212 1299 "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], 1213 1300 1301 + "mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="], 1302 + 1214 1303 "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], 1215 1304 1216 1305 "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], 1306 + 1307 + "miniflare": ["miniflare@4.20251118.1", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "sharp": "^0.33.5", "stoppable": "1.1.0", "undici": "7.14.0", "workerd": "1.20251118.0", "ws": "8.18.0", "youch": "4.1.0-beta.10", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-uLSAE/DvOm392fiaig4LOaatxLjM7xzIniFRG5Y3yF9IduOYLLK/pkCPQNCgKQH3ou0YJRHnTN+09LPfqYNTQQ=="], 1217 1308 1218 1309 "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], 1219 1310 ··· 1278 1369 "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], 1279 1370 1280 1371 "path-scurry": ["path-scurry@2.0.1", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA=="], 1372 + 1373 + "path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="], 1281 1374 1282 1375 "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], 1283 1376 ··· 1455 1548 1456 1549 "seroval-plugins": ["seroval-plugins@1.4.0", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-zir1aWzoiax6pbBVjoYVd0O1QQXgIL3eVGBMsBsNmM8Ukq90yGaWlfx0AB9dTS8GPqrOrbXn79vmItCUP9U3BQ=="], 1457 1550 1551 + "sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="], 1552 + 1458 1553 "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], 1459 1554 1460 1555 "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], 1461 1556 1462 1557 "shimmer": ["shimmer@1.2.1", "", {}, "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw=="], 1558 + 1559 + "simple-swizzle": ["simple-swizzle@0.2.4", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw=="], 1463 1560 1464 1561 "solid-js": ["solid-js@1.9.10", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "~1.3.0", "seroval-plugins": "~1.3.0" } }, "sha512-Coz956cos/EPDlhs6+jsdTxKuJDPT7B5SVIWgABwROyxjY7Xbr8wkzD68Et+NxnV7DLJ3nJdAC2r9InuV/4Jew=="], 1465 1562 ··· 1472 1569 "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="], 1473 1570 1474 1571 "split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="], 1572 + 1573 + "stoppable": ["stoppable@1.1.0", "", {}, "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw=="], 1475 1574 1476 1575 "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], 1477 1576 ··· 1551 1650 1552 1651 "uint8arrays": ["uint8arrays@5.1.0", "", { "dependencies": { "multiformats": "^13.0.0" } }, "sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww=="], 1553 1652 1554 - "undici": ["undici@6.22.0", "", {}, "sha512-hU/10obOIu62MGYjdskASR3CUAiYaFTtC9Pa6vHyf//mAipSvSQg6od2CnJswq7fvzNS3zJhxoRkgNVaHurWKw=="], 1653 + "undici": ["undici@7.14.0", "", {}, "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ=="], 1555 1654 1556 1655 "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], 1656 + 1657 + "unenv": ["unenv@2.0.0-rc.24", "", { "dependencies": { "pathe": "^2.0.3" } }, "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw=="], 1557 1658 1558 1659 "unplugin": ["unplugin@2.3.11", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww=="], 1559 1660 ··· 1581 1682 1582 1683 "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], 1583 1684 1685 + "workerd": ["workerd@1.20251118.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20251118.0", "@cloudflare/workerd-darwin-arm64": "1.20251118.0", "@cloudflare/workerd-linux-64": "1.20251118.0", "@cloudflare/workerd-linux-arm64": "1.20251118.0", "@cloudflare/workerd-windows-64": "1.20251118.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-Om5ns0Lyx/LKtYI04IV0bjIrkBgoFNg0p6urzr2asekJlfP18RqFzyqMFZKf0i9Gnjtz/JfAS/Ol6tjCe5JJsQ=="], 1686 + 1687 + "wrangler": ["wrangler@4.50.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.0", "@cloudflare/unenv-preset": "2.7.11", "blake3-wasm": "2.1.5", "esbuild": "0.25.4", "miniflare": "4.20251118.1", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20251118.0" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20251118.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-+nuZuHZxDdKmAyXOSrHlciGshCoAPiy5dM+t6mEohWm7HpXvTHmWQGUf/na9jjWlWJHCJYOWzkA1P5HBJqrIEA=="], 1688 + 1584 1689 "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], 1585 1690 1586 1691 "ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="], ··· 1592 1697 "yn": ["yn@3.1.1", "", {}, "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="], 1593 1698 1594 1699 "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], 1700 + 1701 + "youch": ["youch@4.1.0-beta.10", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@poppinss/dumper": "^0.6.4", "@speed-highlight/core": "^1.2.7", "cookie": "^1.0.2", "youch-core": "^0.3.3" } }, "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ=="], 1702 + 1703 + "youch-core": ["youch-core@0.3.3", "", { "dependencies": { "@poppinss/exception": "^1.2.2", "error-stack-parser-es": "^1.0.5" } }, "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA=="], 1595 1704 1596 1705 "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], 1597 1706 1598 - "@atcute/oauth-browser-client/@atcute/client": ["@atcute/client@4.0.5", "", { "dependencies": { "@atcute/identity": "^1.1.1", "@atcute/lexicons": "^1.2.2" } }, "sha512-R8Qen8goGmEkynYGg2m6XFlVmz0GTDvQ+9w+4QqOob+XMk8/WDpF4aImev7WKEde/rV2gjcqW7zM8E6W9NShDA=="], 1707 + "@atproto-labs/fetch-node/undici": ["undici@6.22.0", "", {}, "sha512-hU/10obOIu62MGYjdskASR3CUAiYaFTtC9Pa6vHyf//mAipSvSQg6od2CnJswq7fvzNS3zJhxoRkgNVaHurWKw=="], 1599 1708 1600 1709 "@atproto-labs/identity-resolver/@atproto/syntax": ["@atproto/syntax@0.4.0", "", {}, "sha512-b9y5ceHS8YKOfP3mdKmwAx5yVj9294UN7FG2XzP6V5aKUdFazEYRnR9m5n5ZQFKa3GNvz7de9guZCJ/sUTcOAA=="], 1601 1710 ··· 1639 1748 1640 1749 "@babel/helper-create-class-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], 1641 1750 1642 - "@cookware/lexicons/@atcute/client": ["@atcute/client@4.0.5", "", { "dependencies": { "@atcute/identity": "^1.1.1", "@atcute/lexicons": "^1.2.2" } }, "sha512-R8Qen8goGmEkynYGg2m6XFlVmz0GTDvQ+9w+4QqOob+XMk8/WDpF4aImev7WKEde/rV2gjcqW7zM8E6W9NShDA=="], 1751 + "@cookware/web/@atcute/bluesky": ["@atcute/bluesky@1.0.15", "", { "peerDependencies": { "@atcute/client": "^1.0.0 || ^2.0.0" } }, "sha512-+EFiybmKQ97aBAgtaD+cKRJER5AMn3cZMkEwEg/pDdWyzxYJ9m1UgemmLdTgI8VrxPufKqdXS2nl7uO7TY6BPA=="], 1643 1752 1644 1753 "@cookware/web/typescript": ["typescript@5.6.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw=="], 1645 1754 ··· 1666 1775 "@opentelemetry/resources/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.28.0", "", {}, "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA=="], 1667 1776 1668 1777 "@opentelemetry/sdk-trace-base/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.28.0", "", {}, "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA=="], 1778 + 1779 + "@poppinss/dumper/supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], 1669 1780 1670 1781 "@prisma/instrumentation/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.53.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.53.0", "@types/shimmer": "^1.2.0", "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^7.1.1", "semver": "^7.5.2", "shimmer": "^1.2.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A=="], 1671 1782 ··· 1719 1830 1720 1831 "@radix-ui/react-visually-hidden/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], 1721 1832 1722 - "@skyware/jetstream/@atcute/bluesky": ["@atcute/bluesky@3.2.10", "", { "dependencies": { "@atcute/atproto": "^3.1.9", "@atcute/lexicons": "^1.2.2" } }, "sha512-qwQWTzRf3umnh2u41gdU+xWYkbzGlKDupc3zeOB+YjmuP1N9wEaUhwS8H7vgrqr0xC9SGNDjeUVcjC4m5BPLBg=="], 1723 - 1724 1833 "@tanstack/react-router-devtools/vite": ["vite@7.2.4", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w=="], 1725 1834 1726 1835 "@tanstack/router-devtools/vite": ["vite@7.2.4", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w=="], ··· 1747 1856 1748 1857 "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], 1749 1858 1859 + "miniflare/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], 1860 + 1861 + "miniflare/acorn-walk": ["acorn-walk@8.3.2", "", {}, "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A=="], 1862 + 1863 + "miniflare/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], 1864 + 1865 + "miniflare/zod": ["zod@3.22.3", "", {}, "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug=="], 1866 + 1750 1867 "postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], 1751 1868 1752 1869 "postcss-calc/postcss-selector-parser": ["postcss-selector-parser@7.1.0", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA=="], ··· 1761 1878 1762 1879 "recast/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], 1763 1880 1881 + "sharp/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], 1882 + 1764 1883 "solid-js/seroval": ["seroval@1.3.2", "", {}, "sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ=="], 1765 1884 1766 1885 "solid-js/seroval-plugins": ["seroval-plugins@1.3.3", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-16OL3NnUBw8JG1jBLUoZJsLnQq0n5Ua6aHalhJK4fMQkz1lqR7Osz1sA30trBtd9VUDc2NgkuRCn8+/pBwqZ+w=="], ··· 1783 1902 1784 1903 "vite/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], 1785 1904 1905 + "wrangler/esbuild": ["esbuild@0.25.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.4", "@esbuild/android-arm": "0.25.4", "@esbuild/android-arm64": "0.25.4", "@esbuild/android-x64": "0.25.4", "@esbuild/darwin-arm64": "0.25.4", "@esbuild/darwin-x64": "0.25.4", "@esbuild/freebsd-arm64": "0.25.4", "@esbuild/freebsd-x64": "0.25.4", "@esbuild/linux-arm": "0.25.4", "@esbuild/linux-arm64": "0.25.4", "@esbuild/linux-ia32": "0.25.4", "@esbuild/linux-loong64": "0.25.4", "@esbuild/linux-mips64el": "0.25.4", "@esbuild/linux-ppc64": "0.25.4", "@esbuild/linux-riscv64": "0.25.4", "@esbuild/linux-s390x": "0.25.4", "@esbuild/linux-x64": "0.25.4", "@esbuild/netbsd-arm64": "0.25.4", "@esbuild/netbsd-x64": "0.25.4", "@esbuild/openbsd-arm64": "0.25.4", "@esbuild/openbsd-x64": "0.25.4", "@esbuild/sunos-x64": "0.25.4", "@esbuild/win32-arm64": "0.25.4", "@esbuild/win32-ia32": "0.25.4", "@esbuild/win32-x64": "0.25.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q=="], 1906 + 1786 1907 "@atproto/api/@atproto/common-web/uint8arrays": ["uint8arrays@3.0.0", "", { "dependencies": { "multiformats": "^9.4.2" } }, "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA=="], 1787 1908 1788 1909 "@atproto/common/@atproto/common-web/uint8arrays": ["uint8arrays@3.0.0", "", { "dependencies": { "multiformats": "^9.4.2" } }, "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA=="], ··· 1798 1919 "@atproto/common/pino/thread-stream": ["thread-stream@2.7.0", "", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw=="], 1799 1920 1800 1921 "@atproto/lexicon/@atproto/common-web/uint8arrays": ["uint8arrays@3.0.0", "", { "dependencies": { "multiformats": "^9.4.2" } }, "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA=="], 1922 + 1923 + "@cookware/web/@atcute/bluesky/@atcute/client": ["@atcute/client@2.0.9", "", {}, "sha512-QNDm9gMP6x9LY77ArwY+urQOBtQW74/onEAz42c40JxRm6Rl9K9cU4ROvNKJ+5cpVmEm1sthEWVRmDr5CSZENA=="], 1801 1924 1802 1925 "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="], 1803 1926 ··· 2032 2155 "vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], 2033 2156 2034 2157 "vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], 2158 + 2159 + "wrangler/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q=="], 2160 + 2161 + "wrangler/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.4", "", { "os": "android", "cpu": "arm" }, "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ=="], 2162 + 2163 + "wrangler/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.4", "", { "os": "android", "cpu": "arm64" }, "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A=="], 2164 + 2165 + "wrangler/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.4", "", { "os": "android", "cpu": "x64" }, "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ=="], 2166 + 2167 + "wrangler/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g=="], 2168 + 2169 + "wrangler/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A=="], 2170 + 2171 + "wrangler/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ=="], 2172 + 2173 + "wrangler/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ=="], 2174 + 2175 + "wrangler/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.4", "", { "os": "linux", "cpu": "arm" }, "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ=="], 2176 + 2177 + "wrangler/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ=="], 2178 + 2179 + "wrangler/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.4", "", { "os": "linux", "cpu": "ia32" }, "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ=="], 2180 + 2181 + "wrangler/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.4", "", { "os": "linux", "cpu": "none" }, "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA=="], 2182 + 2183 + "wrangler/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.4", "", { "os": "linux", "cpu": "none" }, "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg=="], 2184 + 2185 + "wrangler/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag=="], 2186 + 2187 + "wrangler/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.4", "", { "os": "linux", "cpu": "none" }, "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA=="], 2188 + 2189 + "wrangler/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g=="], 2190 + 2191 + "wrangler/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.4", "", { "os": "linux", "cpu": "x64" }, "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA=="], 2192 + 2193 + "wrangler/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.4", "", { "os": "none", "cpu": "arm64" }, "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ=="], 2194 + 2195 + "wrangler/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.4", "", { "os": "none", "cpu": "x64" }, "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw=="], 2196 + 2197 + "wrangler/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.4", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A=="], 2198 + 2199 + "wrangler/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.4", "", { "os": "openbsd", "cpu": "x64" }, "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw=="], 2200 + 2201 + "wrangler/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.4", "", { "os": "sunos", "cpu": "x64" }, "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q=="], 2202 + 2203 + "wrangler/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ=="], 2204 + 2205 + "wrangler/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg=="], 2206 + 2207 + "wrangler/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.4", "", { "os": "win32", "cpu": "x64" }, "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ=="], 2035 2208 2036 2209 "@tanstack/react-router-devtools/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], 2037 2210
+3 -3
config/dev/caddy/Caddyfile
··· 11 11 12 12 api.local.recipes.blue { 13 13 import tls_config 14 - reverse_proxy http://host.docker.internal:8080 14 + reverse_proxy http://host.docker.internal:8787 15 15 } 16 16 17 17 local.recipes.blue { ··· 20 20 21 21 handle_path /xrpc/* { 22 22 rewrite * /xrpc{uri} 23 - reverse_proxy http://host.docker.internal:8080 23 + reverse_proxy http://host.docker.internal:8787 24 24 } 25 25 handle_path /api/* { 26 26 rewrite * /api{uri} 27 - reverse_proxy http://host.docker.internal:8080 27 + reverse_proxy http://host.docker.internal:8787 28 28 } 29 29 } 30 30
+1 -3
libs/database/drizzle.config.ts
··· 1 - import env from './src/config'; 2 1 import type { Config } from "drizzle-kit"; 3 2 4 3 export default { 5 4 schema: "./src/schema.ts", 6 5 out: "./migrations", 7 6 dialect: "sqlite", 8 - dbCredentials: { 9 - }, 7 + driver: "d1-http" 10 8 } satisfies Config;
+3
libs/database/migrations/0000_boring_tenebrous.sql libs/database/migrations/0000_fantastic_magma.sql
··· 12 12 `id` integer PRIMARY KEY NOT NULL, 13 13 `rkey` text NOT NULL, 14 14 `title` text NOT NULL, 15 + `image_ref` text, 16 + `time` integer DEFAULT 0 NOT NULL, 17 + `serves` integer, 15 18 `description` text, 16 19 `ingredients` text NOT NULL, 17 20 `steps` text NOT NULL,
-1
libs/database/migrations/0001_icy_killmonger.sql
··· 1 - ALTER TABLE `recipes` ADD `time` integer DEFAULT 0 NOT NULL;
-5
libs/database/migrations/0002_redundant_wither.sql
··· 1 - DROP INDEX IF EXISTS "recipes_id_unique";--> statement-breakpoint 2 - DROP INDEX IF EXISTS "recipes_rkey_author_did_unique";--> statement-breakpoint 3 - ALTER TABLE `recipes` ALTER COLUMN "title" TO "title" text;--> statement-breakpoint 4 - CREATE UNIQUE INDEX `recipes_id_unique` ON `recipes` (`id`);--> statement-breakpoint 5 - CREATE UNIQUE INDEX `recipes_rkey_author_did_unique` ON `recipes` (`rkey`,`author_did`);
-6
libs/database/migrations/0003_fixed_peter_parker.sql
··· 1 - DROP INDEX IF EXISTS "recipes_id_unique";--> statement-breakpoint 2 - DROP INDEX IF EXISTS "recipes_rkey_author_did_unique";--> statement-breakpoint 3 - ALTER TABLE `recipes` ALTER COLUMN "title" TO "title" text NOT NULL;--> statement-breakpoint 4 - CREATE UNIQUE INDEX `recipes_id_unique` ON `recipes` (`id`);--> statement-breakpoint 5 - CREATE UNIQUE INDEX `recipes_rkey_author_did_unique` ON `recipes` (`rkey`,`author_did`);--> statement-breakpoint 6 - ALTER TABLE `recipes` ADD `image_ref` text;
-1
libs/database/migrations/0004_left_sersi.sql
··· 1 - ALTER TABLE `recipes` ADD `serves` integer;
+23 -1
libs/database/migrations/meta/0000_snapshot.json
··· 1 1 { 2 2 "version": "6", 3 3 "dialect": "sqlite", 4 - "id": "1c01d686-877c-426c-ac8a-31f47df9385d", 4 + "id": "2d4a90ff-be48-461c-8876-50c11cb2b91d", 5 5 "prevId": "00000000-0000-0000-0000-000000000000", 6 6 "tables": { 7 7 "auth_session": { ··· 74 74 "type": "text", 75 75 "primaryKey": false, 76 76 "notNull": true, 77 + "autoincrement": false 78 + }, 79 + "image_ref": { 80 + "name": "image_ref", 81 + "type": "text", 82 + "primaryKey": false, 83 + "notNull": false, 84 + "autoincrement": false 85 + }, 86 + "time": { 87 + "name": "time", 88 + "type": "integer", 89 + "primaryKey": false, 90 + "notNull": true, 91 + "autoincrement": false, 92 + "default": 0 93 + }, 94 + "serves": { 95 + "name": "serves", 96 + "type": "integer", 97 + "primaryKey": false, 98 + "notNull": false, 77 99 "autoincrement": false 78 100 }, 79 101 "description": {
-156
libs/database/migrations/meta/0001_snapshot.json
··· 1 - { 2 - "version": "6", 3 - "dialect": "sqlite", 4 - "id": "2c6fca6c-38c3-4482-b189-6defabb5f8c8", 5 - "prevId": "1c01d686-877c-426c-ac8a-31f47df9385d", 6 - "tables": { 7 - "auth_session": { 8 - "name": "auth_session", 9 - "columns": { 10 - "key": { 11 - "name": "key", 12 - "type": "text", 13 - "primaryKey": true, 14 - "notNull": true, 15 - "autoincrement": false 16 - }, 17 - "session": { 18 - "name": "session", 19 - "type": "text", 20 - "primaryKey": false, 21 - "notNull": true, 22 - "autoincrement": false 23 - } 24 - }, 25 - "indexes": {}, 26 - "foreignKeys": {}, 27 - "compositePrimaryKeys": {}, 28 - "uniqueConstraints": {}, 29 - "checkConstraints": {} 30 - }, 31 - "auth_state": { 32 - "name": "auth_state", 33 - "columns": { 34 - "key": { 35 - "name": "key", 36 - "type": "text", 37 - "primaryKey": true, 38 - "notNull": true, 39 - "autoincrement": false 40 - }, 41 - "state": { 42 - "name": "state", 43 - "type": "text", 44 - "primaryKey": false, 45 - "notNull": true, 46 - "autoincrement": false 47 - } 48 - }, 49 - "indexes": {}, 50 - "foreignKeys": {}, 51 - "compositePrimaryKeys": {}, 52 - "uniqueConstraints": {}, 53 - "checkConstraints": {} 54 - }, 55 - "recipes": { 56 - "name": "recipes", 57 - "columns": { 58 - "id": { 59 - "name": "id", 60 - "type": "integer", 61 - "primaryKey": true, 62 - "notNull": true, 63 - "autoincrement": false 64 - }, 65 - "rkey": { 66 - "name": "rkey", 67 - "type": "text", 68 - "primaryKey": false, 69 - "notNull": true, 70 - "autoincrement": false 71 - }, 72 - "title": { 73 - "name": "title", 74 - "type": "text", 75 - "primaryKey": false, 76 - "notNull": true, 77 - "autoincrement": false 78 - }, 79 - "time": { 80 - "name": "time", 81 - "type": "integer", 82 - "primaryKey": false, 83 - "notNull": true, 84 - "autoincrement": false, 85 - "default": 0 86 - }, 87 - "description": { 88 - "name": "description", 89 - "type": "text", 90 - "primaryKey": false, 91 - "notNull": false, 92 - "autoincrement": false 93 - }, 94 - "ingredients": { 95 - "name": "ingredients", 96 - "type": "text", 97 - "primaryKey": false, 98 - "notNull": true, 99 - "autoincrement": false 100 - }, 101 - "steps": { 102 - "name": "steps", 103 - "type": "text", 104 - "primaryKey": false, 105 - "notNull": true, 106 - "autoincrement": false 107 - }, 108 - "created_at": { 109 - "name": "created_at", 110 - "type": "text", 111 - "primaryKey": false, 112 - "notNull": true, 113 - "autoincrement": false 114 - }, 115 - "author_did": { 116 - "name": "author_did", 117 - "type": "text", 118 - "primaryKey": false, 119 - "notNull": true, 120 - "autoincrement": false 121 - } 122 - }, 123 - "indexes": { 124 - "recipes_id_unique": { 125 - "name": "recipes_id_unique", 126 - "columns": [ 127 - "id" 128 - ], 129 - "isUnique": true 130 - }, 131 - "recipes_rkey_author_did_unique": { 132 - "name": "recipes_rkey_author_did_unique", 133 - "columns": [ 134 - "rkey", 135 - "author_did" 136 - ], 137 - "isUnique": true 138 - } 139 - }, 140 - "foreignKeys": {}, 141 - "compositePrimaryKeys": {}, 142 - "uniqueConstraints": {}, 143 - "checkConstraints": {} 144 - } 145 - }, 146 - "views": {}, 147 - "enums": {}, 148 - "_meta": { 149 - "schemas": {}, 150 - "tables": {}, 151 - "columns": {} 152 - }, 153 - "internal": { 154 - "indexes": {} 155 - } 156 - }
-156
libs/database/migrations/meta/0002_snapshot.json
··· 1 - { 2 - "version": "6", 3 - "dialect": "sqlite", 4 - "id": "5e0d9054-f192-4db9-8afe-afcabe08e661", 5 - "prevId": "2c6fca6c-38c3-4482-b189-6defabb5f8c8", 6 - "tables": { 7 - "auth_session": { 8 - "name": "auth_session", 9 - "columns": { 10 - "key": { 11 - "name": "key", 12 - "type": "text", 13 - "primaryKey": true, 14 - "notNull": true, 15 - "autoincrement": false 16 - }, 17 - "session": { 18 - "name": "session", 19 - "type": "text", 20 - "primaryKey": false, 21 - "notNull": true, 22 - "autoincrement": false 23 - } 24 - }, 25 - "indexes": {}, 26 - "foreignKeys": {}, 27 - "compositePrimaryKeys": {}, 28 - "uniqueConstraints": {}, 29 - "checkConstraints": {} 30 - }, 31 - "auth_state": { 32 - "name": "auth_state", 33 - "columns": { 34 - "key": { 35 - "name": "key", 36 - "type": "text", 37 - "primaryKey": true, 38 - "notNull": true, 39 - "autoincrement": false 40 - }, 41 - "state": { 42 - "name": "state", 43 - "type": "text", 44 - "primaryKey": false, 45 - "notNull": true, 46 - "autoincrement": false 47 - } 48 - }, 49 - "indexes": {}, 50 - "foreignKeys": {}, 51 - "compositePrimaryKeys": {}, 52 - "uniqueConstraints": {}, 53 - "checkConstraints": {} 54 - }, 55 - "recipes": { 56 - "name": "recipes", 57 - "columns": { 58 - "id": { 59 - "name": "id", 60 - "type": "integer", 61 - "primaryKey": true, 62 - "notNull": true, 63 - "autoincrement": false 64 - }, 65 - "rkey": { 66 - "name": "rkey", 67 - "type": "text", 68 - "primaryKey": false, 69 - "notNull": true, 70 - "autoincrement": false 71 - }, 72 - "title": { 73 - "name": "title", 74 - "type": "text", 75 - "primaryKey": false, 76 - "notNull": false, 77 - "autoincrement": false 78 - }, 79 - "time": { 80 - "name": "time", 81 - "type": "integer", 82 - "primaryKey": false, 83 - "notNull": true, 84 - "autoincrement": false, 85 - "default": 0 86 - }, 87 - "description": { 88 - "name": "description", 89 - "type": "text", 90 - "primaryKey": false, 91 - "notNull": false, 92 - "autoincrement": false 93 - }, 94 - "ingredients": { 95 - "name": "ingredients", 96 - "type": "text", 97 - "primaryKey": false, 98 - "notNull": true, 99 - "autoincrement": false 100 - }, 101 - "steps": { 102 - "name": "steps", 103 - "type": "text", 104 - "primaryKey": false, 105 - "notNull": true, 106 - "autoincrement": false 107 - }, 108 - "created_at": { 109 - "name": "created_at", 110 - "type": "text", 111 - "primaryKey": false, 112 - "notNull": true, 113 - "autoincrement": false 114 - }, 115 - "author_did": { 116 - "name": "author_did", 117 - "type": "text", 118 - "primaryKey": false, 119 - "notNull": true, 120 - "autoincrement": false 121 - } 122 - }, 123 - "indexes": { 124 - "recipes_id_unique": { 125 - "name": "recipes_id_unique", 126 - "columns": [ 127 - "id" 128 - ], 129 - "isUnique": true 130 - }, 131 - "recipes_rkey_author_did_unique": { 132 - "name": "recipes_rkey_author_did_unique", 133 - "columns": [ 134 - "rkey", 135 - "author_did" 136 - ], 137 - "isUnique": true 138 - } 139 - }, 140 - "foreignKeys": {}, 141 - "compositePrimaryKeys": {}, 142 - "uniqueConstraints": {}, 143 - "checkConstraints": {} 144 - } 145 - }, 146 - "views": {}, 147 - "enums": {}, 148 - "_meta": { 149 - "schemas": {}, 150 - "tables": {}, 151 - "columns": {} 152 - }, 153 - "internal": { 154 - "indexes": {} 155 - } 156 - }
-163
libs/database/migrations/meta/0003_snapshot.json
··· 1 - { 2 - "version": "6", 3 - "dialect": "sqlite", 4 - "id": "fa77a98d-2ae1-49d5-ab93-81492dcbdebd", 5 - "prevId": "5e0d9054-f192-4db9-8afe-afcabe08e661", 6 - "tables": { 7 - "auth_session": { 8 - "name": "auth_session", 9 - "columns": { 10 - "key": { 11 - "name": "key", 12 - "type": "text", 13 - "primaryKey": true, 14 - "notNull": true, 15 - "autoincrement": false 16 - }, 17 - "session": { 18 - "name": "session", 19 - "type": "text", 20 - "primaryKey": false, 21 - "notNull": true, 22 - "autoincrement": false 23 - } 24 - }, 25 - "indexes": {}, 26 - "foreignKeys": {}, 27 - "compositePrimaryKeys": {}, 28 - "uniqueConstraints": {}, 29 - "checkConstraints": {} 30 - }, 31 - "auth_state": { 32 - "name": "auth_state", 33 - "columns": { 34 - "key": { 35 - "name": "key", 36 - "type": "text", 37 - "primaryKey": true, 38 - "notNull": true, 39 - "autoincrement": false 40 - }, 41 - "state": { 42 - "name": "state", 43 - "type": "text", 44 - "primaryKey": false, 45 - "notNull": true, 46 - "autoincrement": false 47 - } 48 - }, 49 - "indexes": {}, 50 - "foreignKeys": {}, 51 - "compositePrimaryKeys": {}, 52 - "uniqueConstraints": {}, 53 - "checkConstraints": {} 54 - }, 55 - "recipes": { 56 - "name": "recipes", 57 - "columns": { 58 - "id": { 59 - "name": "id", 60 - "type": "integer", 61 - "primaryKey": true, 62 - "notNull": true, 63 - "autoincrement": false 64 - }, 65 - "rkey": { 66 - "name": "rkey", 67 - "type": "text", 68 - "primaryKey": false, 69 - "notNull": true, 70 - "autoincrement": false 71 - }, 72 - "title": { 73 - "name": "title", 74 - "type": "text", 75 - "primaryKey": false, 76 - "notNull": true, 77 - "autoincrement": false 78 - }, 79 - "image_ref": { 80 - "name": "image_ref", 81 - "type": "text", 82 - "primaryKey": false, 83 - "notNull": false, 84 - "autoincrement": false 85 - }, 86 - "time": { 87 - "name": "time", 88 - "type": "integer", 89 - "primaryKey": false, 90 - "notNull": true, 91 - "autoincrement": false, 92 - "default": 0 93 - }, 94 - "description": { 95 - "name": "description", 96 - "type": "text", 97 - "primaryKey": false, 98 - "notNull": false, 99 - "autoincrement": false 100 - }, 101 - "ingredients": { 102 - "name": "ingredients", 103 - "type": "text", 104 - "primaryKey": false, 105 - "notNull": true, 106 - "autoincrement": false 107 - }, 108 - "steps": { 109 - "name": "steps", 110 - "type": "text", 111 - "primaryKey": false, 112 - "notNull": true, 113 - "autoincrement": false 114 - }, 115 - "created_at": { 116 - "name": "created_at", 117 - "type": "text", 118 - "primaryKey": false, 119 - "notNull": true, 120 - "autoincrement": false 121 - }, 122 - "author_did": { 123 - "name": "author_did", 124 - "type": "text", 125 - "primaryKey": false, 126 - "notNull": true, 127 - "autoincrement": false 128 - } 129 - }, 130 - "indexes": { 131 - "recipes_id_unique": { 132 - "name": "recipes_id_unique", 133 - "columns": [ 134 - "id" 135 - ], 136 - "isUnique": true 137 - }, 138 - "recipes_rkey_author_did_unique": { 139 - "name": "recipes_rkey_author_did_unique", 140 - "columns": [ 141 - "rkey", 142 - "author_did" 143 - ], 144 - "isUnique": true 145 - } 146 - }, 147 - "foreignKeys": {}, 148 - "compositePrimaryKeys": {}, 149 - "uniqueConstraints": {}, 150 - "checkConstraints": {} 151 - } 152 - }, 153 - "views": {}, 154 - "enums": {}, 155 - "_meta": { 156 - "schemas": {}, 157 - "tables": {}, 158 - "columns": {} 159 - }, 160 - "internal": { 161 - "indexes": {} 162 - } 163 - }
-170
libs/database/migrations/meta/0004_snapshot.json
··· 1 - { 2 - "version": "6", 3 - "dialect": "sqlite", 4 - "id": "d6e34451-dba5-4458-8471-ac988decffec", 5 - "prevId": "fa77a98d-2ae1-49d5-ab93-81492dcbdebd", 6 - "tables": { 7 - "auth_session": { 8 - "name": "auth_session", 9 - "columns": { 10 - "key": { 11 - "name": "key", 12 - "type": "text", 13 - "primaryKey": true, 14 - "notNull": true, 15 - "autoincrement": false 16 - }, 17 - "session": { 18 - "name": "session", 19 - "type": "text", 20 - "primaryKey": false, 21 - "notNull": true, 22 - "autoincrement": false 23 - } 24 - }, 25 - "indexes": {}, 26 - "foreignKeys": {}, 27 - "compositePrimaryKeys": {}, 28 - "uniqueConstraints": {}, 29 - "checkConstraints": {} 30 - }, 31 - "auth_state": { 32 - "name": "auth_state", 33 - "columns": { 34 - "key": { 35 - "name": "key", 36 - "type": "text", 37 - "primaryKey": true, 38 - "notNull": true, 39 - "autoincrement": false 40 - }, 41 - "state": { 42 - "name": "state", 43 - "type": "text", 44 - "primaryKey": false, 45 - "notNull": true, 46 - "autoincrement": false 47 - } 48 - }, 49 - "indexes": {}, 50 - "foreignKeys": {}, 51 - "compositePrimaryKeys": {}, 52 - "uniqueConstraints": {}, 53 - "checkConstraints": {} 54 - }, 55 - "recipes": { 56 - "name": "recipes", 57 - "columns": { 58 - "id": { 59 - "name": "id", 60 - "type": "integer", 61 - "primaryKey": true, 62 - "notNull": true, 63 - "autoincrement": false 64 - }, 65 - "rkey": { 66 - "name": "rkey", 67 - "type": "text", 68 - "primaryKey": false, 69 - "notNull": true, 70 - "autoincrement": false 71 - }, 72 - "title": { 73 - "name": "title", 74 - "type": "text", 75 - "primaryKey": false, 76 - "notNull": true, 77 - "autoincrement": false 78 - }, 79 - "image_ref": { 80 - "name": "image_ref", 81 - "type": "text", 82 - "primaryKey": false, 83 - "notNull": false, 84 - "autoincrement": false 85 - }, 86 - "time": { 87 - "name": "time", 88 - "type": "integer", 89 - "primaryKey": false, 90 - "notNull": true, 91 - "autoincrement": false, 92 - "default": 0 93 - }, 94 - "serves": { 95 - "name": "serves", 96 - "type": "integer", 97 - "primaryKey": false, 98 - "notNull": false, 99 - "autoincrement": false 100 - }, 101 - "description": { 102 - "name": "description", 103 - "type": "text", 104 - "primaryKey": false, 105 - "notNull": false, 106 - "autoincrement": false 107 - }, 108 - "ingredients": { 109 - "name": "ingredients", 110 - "type": "text", 111 - "primaryKey": false, 112 - "notNull": true, 113 - "autoincrement": false 114 - }, 115 - "steps": { 116 - "name": "steps", 117 - "type": "text", 118 - "primaryKey": false, 119 - "notNull": true, 120 - "autoincrement": false 121 - }, 122 - "created_at": { 123 - "name": "created_at", 124 - "type": "text", 125 - "primaryKey": false, 126 - "notNull": true, 127 - "autoincrement": false 128 - }, 129 - "author_did": { 130 - "name": "author_did", 131 - "type": "text", 132 - "primaryKey": false, 133 - "notNull": true, 134 - "autoincrement": false 135 - } 136 - }, 137 - "indexes": { 138 - "recipes_id_unique": { 139 - "name": "recipes_id_unique", 140 - "columns": [ 141 - "id" 142 - ], 143 - "isUnique": true 144 - }, 145 - "recipes_rkey_author_did_unique": { 146 - "name": "recipes_rkey_author_did_unique", 147 - "columns": [ 148 - "rkey", 149 - "author_did" 150 - ], 151 - "isUnique": true 152 - } 153 - }, 154 - "foreignKeys": {}, 155 - "compositePrimaryKeys": {}, 156 - "uniqueConstraints": {}, 157 - "checkConstraints": {} 158 - } 159 - }, 160 - "views": {}, 161 - "enums": {}, 162 - "_meta": { 163 - "schemas": {}, 164 - "tables": {}, 165 - "columns": {} 166 - }, 167 - "internal": { 168 - "indexes": {} 169 - } 170 - }
+2 -30
libs/database/migrations/meta/_journal.json
··· 5 5 { 6 6 "idx": 0, 7 7 "version": "6", 8 - "when": 1733683012154, 9 - "tag": "0000_boring_tenebrous", 10 - "breakpoints": true 11 - }, 12 - { 13 - "idx": 1, 14 - "version": "6", 15 - "when": 1734630004978, 16 - "tag": "0001_icy_killmonger", 17 - "breakpoints": true 18 - }, 19 - { 20 - "idx": 2, 21 - "version": "6", 22 - "when": 1734642833768, 23 - "tag": "0002_redundant_wither", 24 - "breakpoints": true 25 - }, 26 - { 27 - "idx": 3, 28 - "version": "6", 29 - "when": 1734643156502, 30 - "tag": "0003_fixed_peter_parker", 31 - "breakpoints": true 32 - }, 33 - { 34 - "idx": 4, 35 - "version": "6", 36 - "when": 1735493787990, 37 - "tag": "0004_left_sersi", 8 + "when": 1763864322315, 9 + "tag": "0000_fantastic_magma", 38 10 "breakpoints": true 39 11 } 40 12 ]
-15
libs/database/src/config.ts
··· 1 - import { z } from "zod"; 2 - 3 - const envSchema = z.object({ 4 - ENV: z 5 - .union([ 6 - z.literal('development'), 7 - z.literal('production'), 8 - ]) 9 - .default('development'), 10 - }); 11 - 12 - const env = envSchema.parse(process.env); 13 - 14 - export default env; 15 - export type Env = z.infer<typeof envSchema>;
-4
libs/database/src/database.ts
··· 1 - import { drizzle } from "drizzle-orm/d1"; 2 - import * as schema from "./schema.js"; 3 - 4 - export const db = drizzle({ schema });
-1
libs/database/src/index.ts
··· 1 - export * from './database.js'; 2 1 export * from './schema.js';
+5 -6
libs/database/src/schema.ts
··· 1 1 import { customType, int, sqliteTable, text, unique } from "drizzle-orm/sqlite-core"; 2 - import { DID } from "@cookware/lexicons"; 3 - import { Ingredient, Step } from "@cookware/lexicons"; 4 - import { NodeSavedSession, NodeSavedState } from "@atproto/oauth-client-node"; 2 + import { BlueRecipesFeedRecipe } from "@cookware/lexicons"; 3 + import { Did, NodeSavedSession, NodeSavedState } from "@atproto/oauth-client-node"; 5 4 6 - const did = customType<{ data: DID }>({ 5 + const did = customType<{ data: Did }>({ 7 6 dataType() { 8 7 return "text"; 9 8 }, ··· 25 24 time: int('time').notNull().default(0), 26 25 serves: int('serves'), 27 26 description: text('description'), 28 - ingredients: text('ingredients', { mode: 'json' }).$type<Partial<Ingredient>[]>().notNull(), 29 - steps: text('steps', { mode: 'json' }).$type<Partial<Step>[]>().notNull(), 27 + ingredients: text('ingredients', { mode: 'json' }).$type<BlueRecipesFeedRecipe.Main['ingredients']>().notNull(), 28 + steps: text('steps', { mode: 'json' }).$type<BlueRecipesFeedRecipe.Main['steps']>().notNull(), 30 29 createdAt: dateIsoText("created_at").notNull(), 31 30 authorDid: did("author_did").notNull(), 32 31 }, t => ({
+8 -7
libs/lexicons/src/did.ts
··· 1 + import { Did } from "@atcute/lexicons"; 1 2 import { z } from "zod"; 2 3 3 4 type Brand<K, T> = K & { __brand: T }; 4 5 export type DID = Brand<string, "DID">; 5 6 6 - export function isDid(s: string): s is DID { 7 + export function isDid(s: string): s is Did { 7 8 return s.startsWith("did:"); 8 9 } 9 10 10 - export function parseDid(s: string): DID | null { 11 + export function parseDid(s: string): Did | null { 11 12 if (!isDid(s)) { 12 13 return null; 13 14 } 14 15 return s; 15 16 } 16 17 17 - export const getDidDoc = async (did: DID) => { 18 + export const getDidDoc = async (did: Did) => { 18 19 let url = `https://plc.directory/${did}`; 19 20 if (did.startsWith('did:web')) { 20 21 url = `https://${did.split(':')[2]}/.well-known/did.json`; ··· 25 26 return PlcDocument.parse(await response.json()); 26 27 }; 27 28 28 - export const getPdsUrl = async (did: DID) => { 29 + export const getPdsUrl = async (did: Did) => { 29 30 const plc = await getDidDoc(did); 30 31 31 32 return ( ··· 57 58 ), 58 59 }); 59 60 60 - async function getAtprotoDidFromDns(handle: string) { 61 + async function getAtprotoDidFromDns(handle: string): Promise<Did | null> { 61 62 const url = new URL("https://cloudflare-dns.com/dns-query"); 62 63 url.searchParams.set("type", "TXT"); 63 64 url.searchParams.set("name", `_atproto.${handle}`); ··· 74 75 ? JSON.parse(Answer[0]?.data).split("did=")[1] 75 76 : null; 76 77 77 - return val ? parseDid(val) : null; 78 + return parseDid(val); 78 79 } 79 80 80 81 const getAtprotoFromHttps = async (handle: string) => { ··· 124 125 return plcHandle.toLowerCase() === handle.toLowerCase() ? did : null; 125 126 }; 126 127 127 - export const getDidFromHandleOrDid = async (handleOrDid: string) => { 128 + export const getDidFromHandleOrDid = async (handleOrDid: string): Promise<Did | null> => { 128 129 const decodedHandleOrDid = decodeURIComponent(handleOrDid); 129 130 if (isDid(decodedHandleOrDid)) { 130 131 return decodedHandleOrDid;