The recipes.blue monorepo recipes.blue
recipes appview atproto

feat: implement ingester service

+2
.gitignore
··· 145 146 # Sentry Config File 147 .sentryclirc
··· 145 146 # Sentry Config File 147 .sentryclirc 148 + 149 + .turbo
-8
Dockerfile
··· 8 WORKDIR /usr/src/app 9 RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile 10 RUN pnpm run -r build 11 - RUN pnpm deploy --filter=@cookware/api --prod /prod/api 12 - 13 - FROM base AS api 14 - COPY --from=build /prod/api /app 15 - COPY --from=build /usr/src/app/apps/web/dist /app/public 16 - WORKDIR /app 17 - EXPOSE 8080 18 - CMD [ "node", "dist/index.js" ]
··· 8 WORKDIR /usr/src/app 9 RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile 10 RUN pnpm run -r build
+2 -2
apps/api/drizzle.config.ts libs/database/drizzle.config.ts
··· 1 - import env from './src/config/env'; 2 import type { Config } from "drizzle-kit"; 3 4 export default { 5 - schema: "./src/db/schema.ts", 6 out: "./migrations", 7 dialect: "turso", 8 dbCredentials: {
··· 1 + import env from './src/config'; 2 import type { Config } from "drizzle-kit"; 3 4 export default { 5 + schema: "./src/schema.ts", 6 out: "./migrations", 7 dialect: "turso", 8 dbCredentials: {
+10
apps/api/migrations/0000_empty_silver_fox.sql libs/database/migrations/0000_boring_tenebrous.sql
··· 1 CREATE TABLE `recipes` ( 2 `id` integer PRIMARY KEY NOT NULL, 3 `rkey` text NOT NULL,
··· 1 + CREATE TABLE `auth_session` ( 2 + `key` text PRIMARY KEY NOT NULL, 3 + `session` text NOT NULL 4 + ); 5 + --> statement-breakpoint 6 + CREATE TABLE `auth_state` ( 7 + `key` text PRIMARY KEY NOT NULL, 8 + `state` text NOT NULL 9 + ); 10 + --> statement-breakpoint 11 CREATE TABLE `recipes` ( 12 `id` integer PRIMARY KEY NOT NULL, 13 `rkey` text NOT NULL,
-9
apps/api/migrations/0001_ancient_polaris.sql
··· 1 - CREATE TABLE `auth_session` ( 2 - `key` text PRIMARY KEY NOT NULL, 3 - `session` text NOT NULL 4 - ); 5 - --> statement-breakpoint 6 - CREATE TABLE `auth_state` ( 7 - `key` text PRIMARY KEY NOT NULL, 8 - `state` text NOT NULL 9 - );
···
-100
apps/api/migrations/meta/0000_snapshot.json
··· 1 - { 2 - "version": "6", 3 - "dialect": "sqlite", 4 - "id": "4c6d1917-abfe-4ae1-ba3d-6017f11a8f9f", 5 - "prevId": "00000000-0000-0000-0000-000000000000", 6 - "tables": { 7 - "recipes": { 8 - "name": "recipes", 9 - "columns": { 10 - "id": { 11 - "name": "id", 12 - "type": "integer", 13 - "primaryKey": true, 14 - "notNull": true, 15 - "autoincrement": false 16 - }, 17 - "rkey": { 18 - "name": "rkey", 19 - "type": "text", 20 - "primaryKey": false, 21 - "notNull": true, 22 - "autoincrement": false 23 - }, 24 - "title": { 25 - "name": "title", 26 - "type": "text", 27 - "primaryKey": false, 28 - "notNull": true, 29 - "autoincrement": false 30 - }, 31 - "description": { 32 - "name": "description", 33 - "type": "text", 34 - "primaryKey": false, 35 - "notNull": false, 36 - "autoincrement": false 37 - }, 38 - "ingredients": { 39 - "name": "ingredients", 40 - "type": "text", 41 - "primaryKey": false, 42 - "notNull": true, 43 - "autoincrement": false 44 - }, 45 - "steps": { 46 - "name": "steps", 47 - "type": "text", 48 - "primaryKey": false, 49 - "notNull": true, 50 - "autoincrement": false 51 - }, 52 - "created_at": { 53 - "name": "created_at", 54 - "type": "text", 55 - "primaryKey": false, 56 - "notNull": true, 57 - "autoincrement": false 58 - }, 59 - "author_did": { 60 - "name": "author_did", 61 - "type": "text", 62 - "primaryKey": false, 63 - "notNull": true, 64 - "autoincrement": false 65 - } 66 - }, 67 - "indexes": { 68 - "recipes_id_unique": { 69 - "name": "recipes_id_unique", 70 - "columns": [ 71 - "id" 72 - ], 73 - "isUnique": true 74 - }, 75 - "recipes_rkey_author_did_unique": { 76 - "name": "recipes_rkey_author_did_unique", 77 - "columns": [ 78 - "rkey", 79 - "author_did" 80 - ], 81 - "isUnique": true 82 - } 83 - }, 84 - "foreignKeys": {}, 85 - "compositePrimaryKeys": {}, 86 - "uniqueConstraints": {}, 87 - "checkConstraints": {} 88 - } 89 - }, 90 - "views": {}, 91 - "enums": {}, 92 - "_meta": { 93 - "schemas": {}, 94 - "tables": {}, 95 - "columns": {} 96 - }, 97 - "internal": { 98 - "indexes": {} 99 - } 100 - }
···
+2 -2
apps/api/migrations/meta/0001_snapshot.json libs/database/migrations/meta/0000_snapshot.json
··· 1 { 2 "version": "6", 3 "dialect": "sqlite", 4 - "id": "e48d1172-ebce-45bf-8598-4a852aa61d44", 5 - "prevId": "4c6d1917-abfe-4ae1-ba3d-6017f11a8f9f", 6 "tables": { 7 "auth_session": { 8 "name": "auth_session",
··· 1 { 2 "version": "6", 3 "dialect": "sqlite", 4 + "id": "1c01d686-877c-426c-ac8a-31f47df9385d", 5 + "prevId": "00000000-0000-0000-0000-000000000000", 6 "tables": { 7 "auth_session": { 8 "name": "auth_session",
-20
apps/api/migrations/meta/_journal.json
··· 1 - { 2 - "version": "7", 3 - "dialect": "sqlite", 4 - "entries": [ 5 - { 6 - "idx": 0, 7 - "version": "6", 8 - "when": 1733263246874, 9 - "tag": "0000_empty_silver_fox", 10 - "breakpoints": true 11 - }, 12 - { 13 - "idx": 1, 14 - "version": "6", 15 - "when": 1733660667552, 16 - "tag": "0001_ancient_polaris", 17 - "breakpoints": true 18 - } 19 - ] 20 - }
···
+2 -4
apps/api/package.json
··· 10 "dev": "NODE_OPTIONS=--use-openssl-ca tsx watch --clear-screen=false src/index.ts | pino-pretty", 11 "build": "tsup", 12 "start": "NODE_OPTIONS=--use-openssl-ca node dist/index.cjs", 13 - "clean": "rimraf dist", 14 - "db:generate": "NODE_OPTIONS=--use-openssl-ca drizzle-kit generate", 15 - "db:migrate": "NODE_OPTIONS=--use-openssl-ca drizzle-kit migrate", 16 - "db:studio": "NODE_OPTIONS=--use-openssl-ca drizzle-kit studio" 17 }, 18 "dependencies": { 19 "@atcute/client": "^2.0.6", 20 "@atproto/api": "^0.13.19", 21 "@atproto/jwk-jose": "^0.1.2", 22 "@atproto/oauth-client-node": "^0.2.3", 23 "@hono/node-server": "^1.13.7", 24 "@libsql/client": "^0.14.0", 25 "@sentry/node": "^8.42.0",
··· 10 "dev": "NODE_OPTIONS=--use-openssl-ca tsx watch --clear-screen=false src/index.ts | pino-pretty", 11 "build": "tsup", 12 "start": "NODE_OPTIONS=--use-openssl-ca node dist/index.cjs", 13 + "clean": "rimraf dist" 14 }, 15 "dependencies": { 16 "@atcute/client": "^2.0.6", 17 "@atproto/api": "^0.13.19", 18 "@atproto/jwk-jose": "^0.1.2", 19 "@atproto/oauth-client-node": "^0.2.3", 20 + "@cookware/database": "workspace:^", 21 "@hono/node-server": "^1.13.7", 22 "@libsql/client": "^0.14.0", 23 "@sentry/node": "^8.42.0",
+1 -2
apps/api/src/auth/storage.ts
··· 4 NodeSavedState, 5 NodeSavedStateStore, 6 } from '@atproto/oauth-client-node' 7 - import { db } from '../db/index.js' 8 import { eq } from 'drizzle-orm'; 9 - import { authSessionTable, authStateTable } from '../db/schema.js'; 10 11 export class StateStore implements NodeSavedStateStore { 12 constructor() {}
··· 4 NodeSavedState, 5 NodeSavedStateStore, 6 } from '@atproto/oauth-client-node' 7 + import { db, authSessionTable, authStateTable } from '@cookware/database' 8 import { eq } from 'drizzle-orm'; 9 10 export class StateStore implements NodeSavedStateStore { 11 constructor() {}
-7
apps/api/src/config/env.ts
··· 8 9 CORS_ORIGINS: z.array(z.string()).default(['http://localhost:5173', 'https://cookware.dev.hayden.moe']), 10 11 - TURSO_CONNECTION_URL: z.string().default('https://turso.dev.hayden.moe'), 12 - TURSO_AUTH_TOKEN: z.string().or(z.undefined()), 13 - 14 - JETSTREAM_ENDPOINT: z 15 - .string() 16 - .url() 17 - .default('wss://jetstream1.us-east.bsky.network/subscribe'), 18 PLC_DIRECTORY_URL: z.string().url().default('https://plc.directory'), 19 20 JWKS_PRIVATE_KEY: z.string().default('{"kty":"EC","x":"pew2xWIyBQ4XSY4gcCuTJBI-oC5rQqQlcDxIN8nN834","y":"aiJFNEFWyKKWGiFKPRvLAU4wdhsfgysfTfTuzTC4LNQ","crv":"P-256","d":"QS-q9RzH1u2Oj8gDiUzLk1qpGxZjKSf-3Z1oKCRL_jQ"}'),
··· 8 9 CORS_ORIGINS: z.array(z.string()).default(['http://localhost:5173', 'https://cookware.dev.hayden.moe']), 10 11 PLC_DIRECTORY_URL: z.string().url().default('https://plc.directory'), 12 13 JWKS_PRIVATE_KEY: z.string().default('{"kty":"EC","x":"pew2xWIyBQ4XSY4gcCuTJBI-oC5rQqQlcDxIN8nN834","y":"aiJFNEFWyKKWGiFKPRvLAU4wdhsfgysfTfTuzTC4LNQ","crv":"P-256","d":"QS-q9RzH1u2Oj8gDiUzLk1qpGxZjKSf-3Z1oKCRL_jQ"}'),
+1 -1
apps/api/src/db/index.ts libs/database/src/database.ts
··· 1 import { drizzle } from "drizzle-orm/libsql"; 2 import { createClient } from "@libsql/client"; 3 import * as schema from "./schema.js"; 4 - import env from "../config/env.js"; 5 6 const client = createClient({ 7 url: env.TURSO_CONNECTION_URL,
··· 1 import { drizzle } from "drizzle-orm/libsql"; 2 import { createClient } from "@libsql/client"; 3 import * as schema from "./schema.js"; 4 + import env from "./config.js"; 5 6 const client = createClient({ 7 url: env.TURSO_CONNECTION_URL,
apps/api/src/db/schema.ts libs/database/src/schema.ts
-3
apps/api/src/index.ts
··· 11 import { CookwareSession } from "./util/api.js"; 12 import { serveStatic } from "@hono/node-server/serve-static"; 13 import * as Sentry from "@sentry/node" 14 - import { readFileSync } from "fs"; 15 - import path from "path"; 16 17 if (env.SENTRY_DSN) { 18 Sentry.init({ ··· 92 app.use('/assets/*', serveStatic({ root: env.PUBLIC_DIR })); 93 app.use('/*', serveStatic({ root: env.PUBLIC_DIR, rewriteRequestPath: () => 'index.html' })); 94 95 - newIngester().start(); 96 serve({ 97 fetch: app.fetch, 98 hostname: env.HOST,
··· 11 import { CookwareSession } from "./util/api.js"; 12 import { serveStatic } from "@hono/node-server/serve-static"; 13 import * as Sentry from "@sentry/node" 14 15 if (env.SENTRY_DSN) { 16 Sentry.init({ ··· 90 app.use('/assets/*', serveStatic({ root: env.PUBLIC_DIR })); 91 app.use('/*', serveStatic({ root: env.PUBLIC_DIR, rewriteRequestPath: () => 'index.html' })); 92 93 serve({ 94 fetch: app.fetch, 95 hostname: env.HOST,
+4 -3
apps/api/src/ingest.ts apps/ingester/src/index.ts
··· 1 import { Jetstream } from "@skyware/jetstream"; 2 import { WebSocket } from "ws"; 3 import { ingestLogger } from "./logger.js"; 4 - import env from "./config/env.js"; 5 import { RecipeCollection, RecipeRecord, parseDid } from "@cookware/lexicons"; 6 - import { db } from "./db/index.js"; 7 - import { recipeTable } from "./db/schema.js"; 8 import { and, eq } from "drizzle-orm"; 9 10 export const newIngester = () => { ··· 81 82 return jetstream; 83 };
··· 1 import { Jetstream } from "@skyware/jetstream"; 2 import { WebSocket } from "ws"; 3 import { ingestLogger } from "./logger.js"; 4 + import env from "./config.js"; 5 import { RecipeCollection, RecipeRecord, parseDid } from "@cookware/lexicons"; 6 + import { db, recipeTable } from "@cookware/database"; 7 import { and, eq } from "drizzle-orm"; 8 9 export const newIngester = () => { ··· 80 81 return jetstream; 82 }; 83 + 84 + newIngester().start();
-1
apps/api/src/logger.ts
··· 2 3 export const rootLogger = pino({ name: 'cookware' }); 4 export const apiLogger = pino({ name: 'cookware.api' }); 5 - export const ingestLogger = pino({ name: 'cookware.ingest' }); 6 export const authLogger = pino({ name: 'cookware.auth' });
··· 2 3 export const rootLogger = pino({ name: 'cookware' }); 4 export const apiLogger = pino({ name: 'cookware.api' }); 5 export const authLogger = pino({ name: 'cookware.auth' });
+1 -2
apps/api/src/xrpc/index.ts
··· 1 import { Hono } from 'hono'; 2 - import { db } from '../db/index.js'; 3 - import { recipeTable } from '../db/schema.js'; 4 import { and, eq, sql } from 'drizzle-orm'; 5 import { getDidDoc, getDidFromHandleOrDid } from '@cookware/lexicons'; 6
··· 1 import { Hono } from 'hono'; 2 + import { db, recipeTable } from '@cookware/database'; 3 import { and, eq, sql } from 'drizzle-orm'; 4 import { getDidDoc, getDidFromHandleOrDid } from '@cookware/lexicons'; 5
+49
apps/ingester/package.json
···
··· 1 + { 2 + "name": "@cookware/ingester", 3 + "type": "module", 4 + "private": true, 5 + "main": "dist/index.js", 6 + "publishConfig": { 7 + "access": "public" 8 + }, 9 + "scripts": { 10 + "dev": "NODE_OPTIONS=--use-openssl-ca tsx watch --clear-screen=false src/index.ts | pino-pretty", 11 + "build": "tsup", 12 + "start": "NODE_OPTIONS=--use-openssl-ca node dist/index.cjs", 13 + "clean": "rimraf dist" 14 + }, 15 + "dependencies": { 16 + "@atcute/client": "^2.0.6", 17 + "@cookware/database": "workspace:^", 18 + "@sentry/node": "^8.42.0", 19 + "@skyware/jetstream": "^0.2.1", 20 + "bufferutil": "^4.0.8", 21 + "drizzle-orm": "^0.37.0", 22 + "pino": "^9.5.0", 23 + "ws": "^8.18.0", 24 + "zod": "^3.23.8" 25 + }, 26 + "devDependencies": { 27 + "@cookware/lexicons": "workspace:*", 28 + "@cookware/tsconfig": "workspace:*", 29 + "@types/node": "^22.10.1", 30 + "@types/ws": "^8.5.13", 31 + "pino-pretty": "^13.0.0", 32 + "rimraf": "^6.0.1", 33 + "ts-node": "^10.9.2", 34 + "tsup": "^8.3.5", 35 + "tsx": "^4.19.2", 36 + "typescript": "^5.7.2" 37 + }, 38 + "tsup": { 39 + "entry": [ 40 + "src", 41 + "!src/**/__tests__/**", 42 + "!src/**/*.test.*" 43 + ], 44 + "splitting": false, 45 + "sourcemap": true, 46 + "clean": true, 47 + "format": "esm" 48 + } 49 + }
+38
apps/ingester/src/config.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('./public'), 8 + 9 + CORS_ORIGINS: z.array(z.string()).default(['http://localhost:5173', 'https://cookware.dev.hayden.moe']), 10 + 11 + TURSO_CONNECTION_URL: z.string().default('https://turso.dev.hayden.moe'), 12 + TURSO_AUTH_TOKEN: z.string().or(z.undefined()), 13 + 14 + JETSTREAM_ENDPOINT: z 15 + .string() 16 + .url() 17 + .default('wss://jetstream1.us-east.bsky.network/subscribe'), 18 + PLC_DIRECTORY_URL: z.string().url().default('https://plc.directory'), 19 + 20 + JWKS_PRIVATE_KEY: z.string().default('{"kty":"EC","x":"pew2xWIyBQ4XSY4gcCuTJBI-oC5rQqQlcDxIN8nN834","y":"aiJFNEFWyKKWGiFKPRvLAU4wdhsfgysfTfTuzTC4LNQ","crv":"P-256","d":"QS-q9RzH1u2Oj8gDiUzLk1qpGxZjKSf-3Z1oKCRL_jQ"}'), 21 + 22 + SESSION_KEY: z.string().default('bJVS+Dx03A3QWWfW3A5Om5DGx1GKptx+1IGAXzOTpw8='), 23 + SESSION_TTL: z.number().default(((60 * 60) * 24) * 5), // expire in 5 days 24 + 25 + SENTRY_DSN: z.string().or(z.undefined()), 26 + 27 + ENV: z 28 + .union([ 29 + z.literal('development'), 30 + z.literal('production'), 31 + ]) 32 + .default('development'), 33 + }); 34 + 35 + const env = envSchema.parse(process.env); 36 + 37 + export default env; 38 + export type Env = z.infer<typeof envSchema>;
+4
apps/ingester/src/logger.ts
···
··· 1 + import { pino } from "pino"; 2 + 3 + export const rootLogger = pino({ name: 'cookware' }); 4 + export const ingestLogger = pino({ name: 'cookware.ingest' });
+4
apps/ingester/tsconfig.json
···
··· 1 + { 2 + "extends": "@cookware/tsconfig/base.json", 3 + "include": ["src", "scripts"] 4 + }
+14 -1
fly.toml
··· 3 4 [build] 5 dockerfile = "Dockerfile" 6 - build-target = "api" 7 8 [[services]] 9 http_checks = []
··· 3 4 [build] 5 dockerfile = "Dockerfile" 6 + 7 + [processes] 8 + web "cd apps/api && node dist/index.js" 9 + ingester = "cd apps/ingester && node dist/index.js" 10 + 11 + [[vm]] 12 + size = "shared-cpu-1x" 13 + memory = 256 14 + processes = ["web"] 15 + 16 + [[vm]] 17 + size = "shared-cpu-1x" 18 + memory = 256 19 + processes = ["ingester"] 20 21 [[services]] 22 http_checks = []
+13
libs/database/migrations/meta/_journal.json
···
··· 1 + { 2 + "version": "7", 3 + "dialect": "sqlite", 4 + "entries": [ 5 + { 6 + "idx": 0, 7 + "version": "6", 8 + "when": 1733683012154, 9 + "tag": "0000_boring_tenebrous", 10 + "breakpoints": true 11 + } 12 + ] 13 + }
+27
libs/database/package.json
···
··· 1 + { 2 + "name": "@cookware/database", 3 + "version": "0.0.0", 4 + "private": true, 5 + "main": "dist/index.js", 6 + "type": "module", 7 + "scripts": { 8 + "dev": "tsc --watch", 9 + "build": "tsc", 10 + "db:generate": "NODE_OPTIONS=--use-openssl-ca drizzle-kit generate", 11 + "db:migrate": "NODE_OPTIONS=--use-openssl-ca drizzle-kit migrate", 12 + "db:studio": "NODE_OPTIONS=--use-openssl-ca drizzle-kit studio" 13 + }, 14 + "devDependencies": { 15 + "@atproto/oauth-client-node": "^0.2.3", 16 + "@cookware/lexicons": "workspace:^", 17 + "@cookware/tsconfig": "workspace:*", 18 + "@types/node": "^22.10.1", 19 + "drizzle-kit": "^0.29.0", 20 + "typescript": "^5.2.2" 21 + }, 22 + "dependencies": { 23 + "@libsql/client": "^0.14.0", 24 + "drizzle-orm": "^0.37.0", 25 + "zod": "^3.23.8" 26 + } 27 + }
+18
libs/database/src/config.ts
···
··· 1 + import { z } from "zod"; 2 + 3 + const envSchema = z.object({ 4 + TURSO_CONNECTION_URL: z.string().default('https://turso.dev.hayden.moe'), 5 + TURSO_AUTH_TOKEN: z.string().or(z.undefined()), 6 + 7 + ENV: z 8 + .union([ 9 + z.literal('development'), 10 + z.literal('production'), 11 + ]) 12 + .default('development'), 13 + }); 14 + 15 + const env = envSchema.parse(process.env); 16 + 17 + export default env; 18 + export type Env = z.infer<typeof envSchema>;
+2
libs/database/src/index.ts
···
··· 1 + export * from './database.js'; 2 + export * from './schema.js';
+8
libs/database/tsconfig.json
···
··· 1 + { 2 + "extends": "@cookware/tsconfig/base.json", 3 + "include": ["src"], 4 + "compilerOptions": { 5 + "declaration": true, 6 + "outDir": "dist" 7 + } 8 + }
+11 -1
package.json
··· 1 { 2 - "private": true 3 }
··· 1 { 2 + "private": true, 3 + "packageManager": "pnpm@9.12.2", 4 + "devDependencies": { 5 + "turbo": "^2.3.3" 6 + }, 7 + "scripts": { 8 + "dev": "turbo dev", 9 + "build": "turbo build", 10 + "db:generate": "turbo db:generate", 11 + "db:migrate": "turbo db:migrate" 12 + } 13 }
+162 -1
pnpm-lock.yaml
··· 6 7 importers: 8 9 - .: {} 10 11 apps/api: 12 dependencies: ··· 22 '@atproto/oauth-client-node': 23 specifier: ^0.2.3 24 version: 0.2.3 25 '@hono/node-server': 26 specifier: ^1.13.7 27 version: 1.13.7(hono@4.6.12) ··· 96 specifier: ^5.7.2 97 version: 5.7.2 98 99 apps/web: 100 dependencies: 101 '@atcute/client': ··· 226 specifier: ^6.0.1 227 version: 6.0.2(@types/node@22.10.1)(jiti@2.4.1)(tsx@4.19.2)(yaml@2.6.1) 228 229 libs/lexicons: 230 devDependencies: 231 '@atcute/client': ··· 2848 2849 libsql@0.4.7: 2850 resolution: {integrity: sha512-T9eIRCs6b0J1SHKYIvD8+KCJMcWZ900iZyxdnSCdqxN12Z1ijzT+jY5nrk72Jw4B0HGzms2NgpryArlJqvc3Lw==} 2851 os: [darwin, linux, win32] 2852 2853 lilconfig@3.1.3: ··· 3468 engines: {node: '>=18.0.0'} 3469 hasBin: true 3470 3471 type-check@0.4.0: 3472 resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 3473 engines: {node: '>= 0.8.0'} ··· 6751 get-tsconfig: 4.8.1 6752 optionalDependencies: 6753 fsevents: 2.3.3 6754 6755 type-check@0.4.0: 6756 dependencies:
··· 6 7 importers: 8 9 + .: 10 + devDependencies: 11 + turbo: 12 + specifier: ^2.3.3 13 + version: 2.3.3 14 15 apps/api: 16 dependencies: ··· 26 '@atproto/oauth-client-node': 27 specifier: ^0.2.3 28 version: 0.2.3 29 + '@cookware/database': 30 + specifier: workspace:^ 31 + version: link:../../libs/database 32 '@hono/node-server': 33 specifier: ^1.13.7 34 version: 1.13.7(hono@4.6.12) ··· 103 specifier: ^5.7.2 104 version: 5.7.2 105 106 + apps/ingester: 107 + dependencies: 108 + '@atcute/client': 109 + specifier: ^2.0.6 110 + version: 2.0.6 111 + '@cookware/database': 112 + specifier: workspace:^ 113 + version: link:../../libs/database 114 + '@sentry/node': 115 + specifier: ^8.42.0 116 + version: 8.42.0 117 + '@skyware/jetstream': 118 + specifier: ^0.2.1 119 + version: 0.2.1(@atcute/client@2.0.6) 120 + bufferutil: 121 + specifier: ^4.0.8 122 + version: 4.0.8 123 + drizzle-orm: 124 + specifier: ^0.37.0 125 + version: 0.37.0(@libsql/client@0.14.0(bufferutil@4.0.8))(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(@types/react@19.0.1)(react@19.0.0) 126 + pino: 127 + specifier: ^9.5.0 128 + version: 9.5.0 129 + ws: 130 + specifier: ^8.18.0 131 + version: 8.18.0(bufferutil@4.0.8) 132 + zod: 133 + specifier: ^3.23.8 134 + version: 3.23.8 135 + devDependencies: 136 + '@cookware/lexicons': 137 + specifier: workspace:* 138 + version: link:../../libs/lexicons 139 + '@cookware/tsconfig': 140 + specifier: workspace:* 141 + version: link:../../libs/tsconfig 142 + '@types/node': 143 + specifier: ^22.10.1 144 + version: 22.10.1 145 + '@types/ws': 146 + specifier: ^8.5.13 147 + version: 8.5.13 148 + pino-pretty: 149 + specifier: ^13.0.0 150 + version: 13.0.0 151 + rimraf: 152 + specifier: ^6.0.1 153 + version: 6.0.1 154 + ts-node: 155 + specifier: ^10.9.2 156 + version: 10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2) 157 + tsup: 158 + specifier: ^8.3.5 159 + version: 8.3.5(@swc/core@1.9.3)(jiti@2.4.1)(postcss@8.4.49)(tsx@4.19.2)(typescript@5.7.2)(yaml@2.6.1) 160 + tsx: 161 + specifier: ^4.19.2 162 + version: 4.19.2 163 + typescript: 164 + specifier: ^5.7.2 165 + version: 5.7.2 166 + 167 apps/web: 168 dependencies: 169 '@atcute/client': ··· 294 specifier: ^6.0.1 295 version: 6.0.2(@types/node@22.10.1)(jiti@2.4.1)(tsx@4.19.2)(yaml@2.6.1) 296 297 + libs/database: 298 + dependencies: 299 + '@libsql/client': 300 + specifier: ^0.14.0 301 + version: 0.14.0(bufferutil@4.0.8) 302 + drizzle-orm: 303 + specifier: ^0.37.0 304 + version: 0.37.0(@libsql/client@0.14.0(bufferutil@4.0.8))(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(@types/react@19.0.1)(react@19.0.0) 305 + zod: 306 + specifier: ^3.23.8 307 + version: 3.23.8 308 + devDependencies: 309 + '@atproto/oauth-client-node': 310 + specifier: ^0.2.3 311 + version: 0.2.3 312 + '@cookware/lexicons': 313 + specifier: workspace:^ 314 + version: link:../lexicons 315 + '@cookware/tsconfig': 316 + specifier: workspace:* 317 + version: link:../tsconfig 318 + '@types/node': 319 + specifier: ^22.10.1 320 + version: 22.10.1 321 + drizzle-kit: 322 + specifier: ^0.29.0 323 + version: 0.29.0 324 + typescript: 325 + specifier: ^5.2.2 326 + version: 5.7.2 327 + 328 libs/lexicons: 329 devDependencies: 330 '@atcute/client': ··· 2947 2948 libsql@0.4.7: 2949 resolution: {integrity: sha512-T9eIRCs6b0J1SHKYIvD8+KCJMcWZ900iZyxdnSCdqxN12Z1ijzT+jY5nrk72Jw4B0HGzms2NgpryArlJqvc3Lw==} 2950 + cpu: [x64, arm64, wasm32] 2951 os: [darwin, linux, win32] 2952 2953 lilconfig@3.1.3: ··· 3568 engines: {node: '>=18.0.0'} 3569 hasBin: true 3570 3571 + turbo-darwin-64@2.3.3: 3572 + resolution: {integrity: sha512-bxX82xe6du/3rPmm4aCC5RdEilIN99VUld4HkFQuw+mvFg6darNBuQxyWSHZTtc25XgYjQrjsV05888w1grpaA==} 3573 + cpu: [x64] 3574 + os: [darwin] 3575 + 3576 + turbo-darwin-arm64@2.3.3: 3577 + resolution: {integrity: sha512-DYbQwa3NsAuWkCUYVzfOUBbSUBVQzH5HWUFy2Kgi3fGjIWVZOFk86ss+xsWu//rlEAfYwEmopigsPYSmW4X15A==} 3578 + cpu: [arm64] 3579 + os: [darwin] 3580 + 3581 + turbo-linux-64@2.3.3: 3582 + resolution: {integrity: sha512-eHj9OIB0dFaP6BxB88jSuaCLsOQSYWBgmhy2ErCu6D2GG6xW3b6e2UWHl/1Ho9FsTg4uVgo4DB9wGsKa5erjUA==} 3583 + cpu: [x64] 3584 + os: [linux] 3585 + 3586 + turbo-linux-arm64@2.3.3: 3587 + resolution: {integrity: sha512-NmDE/NjZoDj1UWBhMtOPmqFLEBKhzGS61KObfrDEbXvU3lekwHeoPvAMfcovzswzch+kN2DrtbNIlz+/rp8OCg==} 3588 + cpu: [arm64] 3589 + os: [linux] 3590 + 3591 + turbo-windows-64@2.3.3: 3592 + resolution: {integrity: sha512-O2+BS4QqjK3dOERscXqv7N2GXNcqHr9hXumkMxDj/oGx9oCatIwnnwx34UmzodloSnJpgSqjl8iRWiY65SmYoQ==} 3593 + cpu: [x64] 3594 + os: [win32] 3595 + 3596 + turbo-windows-arm64@2.3.3: 3597 + resolution: {integrity: sha512-dW4ZK1r6XLPNYLIKjC4o87HxYidtRRcBeo/hZ9Wng2XM/MqqYkAyzJXJGgRMsc0MMEN9z4+ZIfnSNBrA0b08ag==} 3598 + cpu: [arm64] 3599 + os: [win32] 3600 + 3601 + turbo@2.3.3: 3602 + resolution: {integrity: sha512-DUHWQAcC8BTiUZDRzAYGvpSpGLiaOQPfYXlCieQbwUvmml/LRGIe3raKdrOPOoiX0DYlzxs2nH6BoWJoZrj8hA==} 3603 + hasBin: true 3604 + 3605 type-check@0.4.0: 3606 resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 3607 engines: {node: '>= 0.8.0'} ··· 6885 get-tsconfig: 4.8.1 6886 optionalDependencies: 6887 fsevents: 2.3.3 6888 + 6889 + turbo-darwin-64@2.3.3: 6890 + optional: true 6891 + 6892 + turbo-darwin-arm64@2.3.3: 6893 + optional: true 6894 + 6895 + turbo-linux-64@2.3.3: 6896 + optional: true 6897 + 6898 + turbo-linux-arm64@2.3.3: 6899 + optional: true 6900 + 6901 + turbo-windows-64@2.3.3: 6902 + optional: true 6903 + 6904 + turbo-windows-arm64@2.3.3: 6905 + optional: true 6906 + 6907 + turbo@2.3.3: 6908 + optionalDependencies: 6909 + turbo-darwin-64: 2.3.3 6910 + turbo-darwin-arm64: 2.3.3 6911 + turbo-linux-64: 2.3.3 6912 + turbo-linux-arm64: 2.3.3 6913 + turbo-windows-64: 2.3.3 6914 + turbo-windows-arm64: 2.3.3 6915 6916 type-check@0.4.0: 6917 dependencies:
+18
turbo.json
···
··· 1 + { 2 + "$schema": "https://turbo.build/schema.json", 3 + "tasks": { 4 + "build": { 5 + "outputs": ["dist/**"] 6 + }, 7 + "dev": { 8 + "persistent": true, 9 + "cache": false 10 + }, 11 + "db:generate": { 12 + "cache": false 13 + }, 14 + "db:migrate": { 15 + "cache": false 16 + } 17 + } 18 + }