Something went wrong. Try again.
A fork of @slices.network/slices forked from slices.network/slices
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244import { assertEquals, assertStringIncludes } from "jsr:@std/assert";import { Project } from "ts-morph";import { generateInterfaces } from "../src/interfaces.ts";import type { Lexicon } from "../src/mod.ts";
function createTestProject() { return new Project({ useInMemoryFileSystem: true });}
Deno.test("generateInterfaces - creates record interfaces", () => { const project = createTestProject(); const sourceFile = project.createSourceFile("test.ts", "");
const lexicons: Lexicon[] = [ { id: "com.example.post", definitions: { main: { type: "record", record: { type: "record", properties: { text: { type: "string" }, createdAt: { type: "string", format: "datetime" }, likes: { type: "integer" }, }, required: ["text", "createdAt"], }, }, }, }, ];
generateInterfaces(sourceFile, lexicons); const result = sourceFile.getFullText();
// Should create interface for the record assertStringIncludes(result, "export interface ComExamplePost"); assertStringIncludes(result, "text: string;"); assertStringIncludes(result, "createdAt: string;"); assertStringIncludes(result, "likes?: number;");
// Should create sort fields type alias assertStringIncludes(result, "export type ComExamplePostSortFields"); assertStringIncludes(result, '"text" | "createdAt" | "likes"');});
Deno.test("generateInterfaces - creates object interfaces", () => { const project = createTestProject(); const sourceFile = project.createSourceFile("test.ts", "");
const lexicons: Lexicon[] = [ { id: "app.bsky.embed.defs", definitions: { aspectRatio: { type: "object", properties: { width: { type: "integer" }, height: { type: "integer" }, }, required: ["width", "height"], }, }, }, ];
generateInterfaces(sourceFile, lexicons); const result = sourceFile.getFullText();
assertStringIncludes(result, "export interface AppBskyEmbedDefsAspectRatio"); assertStringIncludes(result, "width: number;"); assertStringIncludes(result, "height: number;");});
Deno.test("generateInterfaces - creates union type aliases", () => { const project = createTestProject(); const sourceFile = project.createSourceFile("test.ts", "");
const lexicons: Lexicon[] = [ { id: "app.bsky.embed.defs", definitions: { view: { type: "union", refs: ["#imageView", "#videoView"], closed: false, }, imageView: { type: "object", properties: { alt: { type: "string" } }, }, videoView: { type: "object", properties: { duration: { type: "integer" } }, }, }, }, ];
generateInterfaces(sourceFile, lexicons); const result = sourceFile.getFullText();
assertStringIncludes(result, "export type AppBskyEmbedDefsView"); assertStringIncludes(result, "AppBskyEmbedDefs[\"ImageView\"]"); assertStringIncludes(result, "AppBskyEmbedDefs[\"VideoView\"]"); // Open union should include unknown type assertStringIncludes(result, "{ $type: string; [key: string]: unknown }");});
Deno.test("generateInterfaces - creates known values types", () => { const project = createTestProject(); const sourceFile = project.createSourceFile("test.ts", "");
const lexicons: Lexicon[] = [ { id: "com.example.post", definitions: { main: { type: "record", record: { type: "record", properties: { status: { type: "string", knownValues: ["draft", "published", "archived"], }, }, }, }, }, }, ];
generateInterfaces(sourceFile, lexicons); const result = sourceFile.getFullText();
assertStringIncludes(result, "export type ComExamplePostStatus"); assertStringIncludes(result, "'draft'"); assertStringIncludes(result, "'published'"); assertStringIncludes(result, "'archived'"); assertStringIncludes(result, "(string & Record<string, never>)");});
Deno.test("generateInterfaces - creates namespace interfaces", () => { const project = createTestProject(); const sourceFile = project.createSourceFile("test.ts", "");
const lexicons: Lexicon[] = [ { id: "app.bsky.embed.defs", definitions: { aspectRatio: { type: "object", properties: { width: { type: "integer" } }, }, view: { type: "union", refs: ["#aspectRatio"], }, }, }, ];
generateInterfaces(sourceFile, lexicons); const result = sourceFile.getFullText();
// Should create namespace interface for multiple definitions assertStringIncludes(result, "export interface AppBskyEmbedDefs"); assertStringIncludes(result, "readonly AspectRatio: AppBskyEmbedDefsAspectRatio;"); assertStringIncludes(result, "readonly View: AppBskyEmbedDefsView;");});
Deno.test("generateInterfaces - generates from network.slices lexicons", () => { const project = createTestProject(); const sourceFile = project.createSourceFile("test.ts", "");
const lexicons = [ { id: "network.slices.slice", definitions: { main: { type: "record", record: { type: "record", properties: { name: { type: "string" }, }, required: ["name"], }, }, }, }, ];
generateInterfaces(sourceFile, lexicons); const result = sourceFile.getFullText();
assertStringIncludes(result, "export interface NetworkSlicesSlice"); assertStringIncludes(result, "name: string;");});
Deno.test("generateInterfaces - generates empty output for empty lexicons", () => { const project = createTestProject(); const sourceFile = project.createSourceFile("test.ts", "");
generateInterfaces(sourceFile, []); const result = sourceFile.getFullText();
// Should have minimal output for empty lexicons assertEquals(result.trim(), "");});
Deno.test("generateInterfaces - handles single definition lexicons", () => { const project = createTestProject(); const sourceFile = project.createSourceFile("test.ts", "");
const lexicons: Lexicon[] = [ { id: "com.atproto.repo.strongRef", definitions: { main: { type: "object", properties: { uri: { type: "string" }, cid: { type: "string" }, }, required: ["uri", "cid"], }, }, }, ];
generateInterfaces(sourceFile, lexicons); const result = sourceFile.getFullText();
// Should use clean name for single definition assertStringIncludes(result, "export interface ComAtprotoRepoStrongRef"); assertStringIncludes(result, "uri: string;"); assertStringIncludes(result, "cid: string;");
// Should NOT create namespace interface for single definition assertEquals(result.includes("readonly Main:"), false);});