prototypey.org - atproto lexicon typescript toolkit - mirror https://github.com/tylersayshi/prototypey
1
fork

Configure Feed

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

output lexicon json in nested structure

`gen-emit` now writes schemas into a nested directory structure based on the NSID (e.g. `com/atproto/repo/strongRef.json` instead of `com.atproto.repo.strongRef.json`).

This is the layout expected by goat, lex, lpm, and others.

authored by

JP Hastings-Spital and committed by
Tyler Lawson
af061d64 de351e2a

+47 -15
+7
.changeset/gen-emit-nested.md
··· 1 + --- 2 + "prototypey": major 3 + --- 4 + 5 + **BREAKING:** `gen-emit` now writes schemas into a nested directory structure based on each lexicon's NSID (e.g. `com/atproto/repo/strongRef.json` instead of `com.atproto.repo.strongRef.json`). The previous flat dot-separated layout has been removed. 6 + 7 + This is the layout expected by [goat](https://github.com/bluesky-social/goat), [lex](https://github.com/bluesky-social/atproto/tree/main/packages/lex/lex), [lpm](https://github.com/lexicon-community/lpm), and other tooling in the atproto ecosystem.
+7 -3
packages/prototypey/cli/gen-emit.ts
··· 1 1 import { glob } from "tinyglobby"; 2 2 import { mkdir, writeFile } from "node:fs/promises"; 3 - import { join } from "node:path"; 3 + import { dirname, join } from "node:path"; 4 4 import { pathToFileURL } from "node:url"; 5 5 6 6 interface LexiconNamespace { ··· 84 84 // Emit JSON for each lexicon 85 85 for (const lexicon of lexicons) { 86 86 const { id } = lexicon.json; 87 - const outputPath = join(outdir, `${id}.json`); 87 + const relativePath = `${id.split(".").join("/")}.json`; 88 + const outputPath = join(outdir, relativePath); 89 + 90 + // Ensure the nested parent directory exists 91 + await mkdir(dirname(outputPath), { recursive: true }); 88 92 89 93 // Write the JSON file 90 94 await writeFile( ··· 93 97 "utf-8", 94 98 ); 95 99 96 - console.log(` ✓ ${id} -> ${id}.json`); 100 + console.log(` ✓ ${id} -> ${relativePath}`); 97 101 } 98 102 } catch (error) { 99 103 console.error(` ✗ Error processing ${sourcePath}:`, error);
+25 -10
packages/prototypey/cli/tests/gen-emit.test.ts
··· 46 46 await genEmit(outDir, lexiconFile); 47 47 48 48 // Read the emitted JSON file 49 - const outputFile = join(outDir, "app.bsky.actor.profile.json"); 49 + const outputFile = join(outDir, "app", "bsky", "actor", "profile.json"); 50 50 const content = await readFile(outputFile, "utf-8"); 51 51 const json = JSON.parse(content); 52 52 ··· 111 111 112 112 // Verify both files were created 113 113 const profileJson = JSON.parse( 114 - await readFile(join(outDir, "app.bsky.actor.profile.json"), "utf-8"), 114 + await readFile( 115 + join(outDir, "app", "bsky", "actor", "profile.json"), 116 + "utf-8", 117 + ), 115 118 ); 116 119 const postJson = JSON.parse( 117 - await readFile(join(outDir, "app.bsky.feed.post.json"), "utf-8"), 120 + await readFile(join(outDir, "app", "bsky", "feed", "post.json"), "utf-8"), 118 121 ); 119 122 120 123 expect(profileJson.id).toBe("app.bsky.actor.profile"); ··· 151 154 152 155 // Verify both files were created 153 156 const profileExists = await readFile( 154 - join(outDir, "app.bsky.actor.profile.json"), 157 + join(outDir, "app", "bsky", "actor", "profile.json"), 155 158 "utf-8", 156 159 ); 157 160 const postExists = await readFile( 158 - join(outDir, "app.bsky.feed.post.json"), 161 + join(outDir, "app", "bsky", "feed", "post.json"), 159 162 "utf-8", 160 163 ); 161 164 ··· 192 195 193 196 await genEmit(outDir, lexiconFile); 194 197 195 - const outputFile = join(outDir, "app.bsky.feed.searchPosts.json"); 198 + const outputFile = join(outDir, "app", "bsky", "feed", "searchPosts.json"); 196 199 const content = await readFile(outputFile, "utf-8"); 197 200 const json = JSON.parse(content); 198 201 ··· 264 267 265 268 await genEmit(outDir, lexiconFile); 266 269 267 - const outputFile = join(outDir, "com.atproto.repo.createRecord.json"); 270 + const outputFile = join( 271 + outDir, 272 + "com", 273 + "atproto", 274 + "repo", 275 + "createRecord.json", 276 + ); 268 277 const content = await readFile(outputFile, "utf-8"); 269 278 const json = JSON.parse(content); 270 279 ··· 338 347 339 348 await genEmit(outDir, lexiconFile); 340 349 341 - const outputFile = join(outDir, "com.atproto.sync.subscribeRepos.json"); 350 + const outputFile = join( 351 + outDir, 352 + "com", 353 + "atproto", 354 + "sync", 355 + "subscribeRepos.json", 356 + ); 342 357 const content = await readFile(outputFile, "utf-8"); 343 358 const json = JSON.parse(content); 344 359 ··· 416 431 417 432 await genEmit(outDir, lexiconFile); 418 433 419 - const outputFile = join(outDir, "app.bsky.feed.defs.json"); 434 + const outputFile = join(outDir, "app", "bsky", "feed", "defs.json"); 420 435 const content = await readFile(outputFile, "utf-8"); 421 436 const json = JSON.parse(content); 422 437 ··· 478 493 479 494 await genEmit(outDir, lexiconFile); 480 495 481 - const outputFile = join(outDir, "app.example.imagePost.json"); 496 + const outputFile = join(outDir, "app", "example", "imagePost.json"); 482 497 const content = await readFile(outputFile, "utf-8"); 483 498 const json = JSON.parse(content); 484 499
+8 -2
packages/prototypey/cli/tests/gen-from-json.test.ts
··· 414 414 await genEmit(intermediateDir, tsFile); 415 415 416 416 // Step 2: gen-from-json to create TypeScript from JSON 417 - const jsonFile = join(intermediateDir, "app.bsky.feed.post.json"); 417 + const jsonFile = join( 418 + intermediateDir, 419 + "app", 420 + "bsky", 421 + "feed", 422 + "post.json", 423 + ); 418 424 await genFromJSON(outDir, jsonFile); 419 425 420 426 // Verify the output exists 421 - const outputFile = join(outDir, "app.bsky.feed.post.ts"); 427 + const outputFile = join(outDir, "post.ts"); 422 428 const content = await readFile(outputFile, "utf-8"); 423 429 424 430 expect(content).toContain("appBskyFeedPost");