๐Ÿ‘๏ธ
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

scoped oauth

+70 -17
+1 -2
.claude/ATPROTO.md
··· 152 152 153 153 **Generating types:** 154 154 ```bash 155 - npm run build:typelex # TypeSpec โ†’ JSON lexicons 156 - # Types are auto-generated to src/lib/lexicons/ 155 + npm run lexicons:all # TypeSpec โ†’ JSON โ†’ TypeScript types + OAuth scopes 157 156 ``` 158 157 159 158 ## Query Integration
+3 -3
.claude/TYPELEX.md
··· 89 89 > lexicons/com/atproto/repo/strongRef.json 90 90 ``` 91 91 92 - 2. **Run typelex** - it auto-generates `typelex/externals.tsp` with `@external` stubs: 92 + 2. **Run lexicons:compile** - it auto-generates `typelex/externals.tsp` with `@external` stubs: 93 93 ```bash 94 - npm run build:typelex 94 + npm run lexicons:compile 95 95 ``` 96 96 97 97 3. **Reference the external type** using the full namespace + `.Main`: ··· 132 132 ## Compilation 133 133 134 134 ```bash 135 - npm run build:typelex 135 + npm run lexicons:compile 136 136 # runs: typelex compile com.deckbelcher.* 137 137 ``` 138 138
+9 -6
CLAUDE.md
··· 34 34 npm run check # Check both linting and formatting 35 35 npm run typecheck # Check TypeScript types 36 36 37 - # Typelex (schema generation) 38 - npm run build:typelex # Compile lexicons from typelex/*.tsp to lexicons/ 39 - npm run build:lexicons # Generate TS types from lexicons/ to src/lib/lexicons/ 37 + # Lexicons (schema generation) 38 + npm run lexicons:compile # Compile TypeSpec (.tsp) โ†’ JSON lexicons 39 + npm run lexicons:codegen # Generate TypeScript types from JSON lexicons 40 + npm run lexicons:scopes # Generate OAuth scopes from JSON lexicons 41 + npm run lexicons:all # Run all three in sequence 40 42 ``` 41 43 42 44 ## Architecture ··· 69 71 - **Source**: `typelex/*.tsp` - TypeSpec definitions for AT Protocol lexicons 70 72 - **Generated JSON**: `lexicons/com/deckbelcher/**/*.json` - Compiled lexicon schemas 71 73 - **Generated TS**: `src/lib/lexicons/` - TypeScript types from lexicons 72 - - After modifying `.tsp` files, run both: 73 - 1. `npm run build:typelex` - compiles TypeSpec โ†’ JSON lexicons 74 - 2. `npm run build:lexicons` - generates TypeScript types from JSON lexicons 74 + - After modifying `.tsp` files, run `npm run lexicons:all` which: 75 + 1. `lexicons:compile` - compiles TypeSpec โ†’ JSON lexicons 76 + 2. `lexicons:codegen` - generates TypeScript types from JSON lexicons 77 + 3. `lexicons:scopes` - updates OAuth scopes in `public/client-metadata.json` 75 78 - Lexicons follow AT Protocol conventions (used for ATProto/Bluesky integrations) 76 79 77 80 ### Styling
+4 -2
package.json
··· 17 17 "check": "biome check", 18 18 "typecheck": "tsc --noEmit", 19 19 "typecheck:faster": "npm run typecheck -- --skipLibCheck --incremental", 20 - "build:typelex": "typelex compile com.deckbelcher.*", 21 - "build:lexicons": "lex-cli generate -c ./lex.config.js", 20 + "lexicons:compile": "typelex compile com.deckbelcher.*", 21 + "lexicons:codegen": "lex-cli generate -c ./lex.config.js", 22 + "lexicons:scopes": "node --experimental-strip-types scripts/generate-oauth-scopes.ts", 23 + "lexicons:all": "npm run lexicons:compile && npm run lexicons:codegen && npm run lexicons:scopes", 22 24 "download:scryfall": "node --experimental-strip-types scripts/download-scryfall.ts" 23 25 }, 24 26 "dependencies": {
+11 -4
public/client-metadata.json
··· 2 2 "client_id": "https://deckbelcher.com/client-metadata.json", 3 3 "client_name": "DeckBelcher", 4 4 "client_uri": "https://deckbelcher.com", 5 - "redirect_uris": ["https://deckbelcher.com/oauth/callback"], 6 - "scope": "atproto transition:generic", 7 - "grant_types": ["authorization_code", "refresh_token"], 8 - "response_types": ["code"], 5 + "redirect_uris": [ 6 + "https://deckbelcher.com/oauth/callback" 7 + ], 8 + "scope": "atproto repo:com.deckbelcher.actor.profile repo:com.deckbelcher.collection.list repo:com.deckbelcher.deck.list repo:com.deckbelcher.social.comment repo:com.deckbelcher.social.like repo:com.deckbelcher.social.reply", 9 + "grant_types": [ 10 + "authorization_code", 11 + "refresh_token" 12 + ], 13 + "response_types": [ 14 + "code" 15 + ], 9 16 "application_type": "web", 10 17 "token_endpoint_auth_method": "none", 11 18 "dpop_bound_access_tokens": true
+42
scripts/generate-oauth-scopes.ts
··· 1 + import { readdirSync, readFileSync, statSync, writeFileSync } from "node:fs"; 2 + import { join } from "node:path"; 3 + 4 + const LEXICONS_DIR = "lexicons/com/deckbelcher"; 5 + const CLIENT_METADATA_PATH = "public/client-metadata.json"; 6 + 7 + function findRecordTypes(dir: string, nsidPrefix: string): string[] { 8 + const records: string[] = []; 9 + 10 + for (const entry of readdirSync(dir)) { 11 + const fullPath = join(dir, entry); 12 + const stat = statSync(fullPath); 13 + 14 + if (stat.isDirectory()) { 15 + records.push(...findRecordTypes(fullPath, `${nsidPrefix}.${entry}`)); 16 + } else if (entry.endsWith(".json")) { 17 + const content = JSON.parse(readFileSync(fullPath, "utf-8")); 18 + if (content.defs?.main?.type === "record") { 19 + const nsid = `${nsidPrefix}.${entry.replace(".json", "")}`; 20 + records.push(nsid); 21 + } 22 + } 23 + } 24 + 25 + return records; 26 + } 27 + 28 + const recordTypes = findRecordTypes(LEXICONS_DIR, "com.deckbelcher"); 29 + const repoScopes = recordTypes.map((nsid) => `repo:${nsid}`).join(" "); 30 + const scope = `atproto ${repoScopes}`; 31 + 32 + console.log("Found record types:", recordTypes); 33 + console.log("Generated scope:", scope); 34 + 35 + const metadata = JSON.parse(readFileSync(CLIENT_METADATA_PATH, "utf-8")); 36 + metadata.scope = scope; 37 + writeFileSync( 38 + CLIENT_METADATA_PATH, 39 + JSON.stringify(metadata, null, "\t") + "\n", 40 + ); 41 + 42 + console.log("Updated", CLIENT_METADATA_PATH);