Suite of AT Protocol TypeScript libraries built on web standards
21
fork

Configure Feed

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

fix package imports

+131 -22
+40 -3
lex-gen/codegen/client.ts
··· 9 9 import type { GeneratedAPI } from "../types.ts"; 10 10 import { gen, lexiconsTs, utilTs } from "./common.ts"; 11 11 import { 12 + collectExternalImports, 12 13 genCommonImports, 13 14 genImports, 14 15 genRecord, ··· 16 17 genXrpcInput, 17 18 genXrpcOutput, 18 19 genXrpcParams, 20 + resolveExternalImport, 19 21 } from "./lex-gen.ts"; 20 22 import { 21 23 type CodeGenOptions, ··· 72 74 file.addImportDeclaration({ 73 75 moduleSpecifier: "@atp/xrpc", 74 76 namedImports: [ 75 - { name: "XrpcClient" }, 76 - { name: "FetchHandler", isTypeOnly: true }, 77 - { name: "FetchHandlerOptions", isTypeOnly: true }, 77 + { name: "XrpcClient" }, 78 + { name: "FetchHandler", isTypeOnly: true }, 79 + { name: "FetchHandlerOptions", isTypeOnly: true }, 78 80 ], 79 81 }); 80 82 //= import {schemas} from './lexicons.ts' ··· 92 94 { name: "Un$Typed" }, 93 95 ], 94 96 }); 97 + 98 + // collect and import external lexicon references 99 + const externalImports = collectExternalImports(lexiconDocs, options); 100 + const mappings = options?.mappings; 101 + for (const [nsid, types] of externalImports) { 102 + const mapping = resolveExternalImport(nsid, mappings); 103 + if (mapping) { 104 + if (typeof mapping.imports === "string") { 105 + file.addImportDeclaration({ 106 + isTypeOnly: true, 107 + moduleSpecifier: mapping.imports, 108 + namedImports: [{ name: toTitleCase(nsid), isTypeOnly: true }], 109 + }); 110 + } else { 111 + const result = mapping.imports(nsid); 112 + if (result.type === "namespace") { 113 + file.addImportDeclaration({ 114 + isTypeOnly: true, 115 + moduleSpecifier: result.from, 116 + namespaceImport: toTitleCase(nsid), 117 + }); 118 + } else { 119 + const namedImports = Array.from(types).map((typeName) => ({ 120 + name: toTitleCase(typeName), 121 + isTypeOnly: true, 122 + })); 123 + file.addImportDeclaration({ 124 + isTypeOnly: true, 125 + moduleSpecifier: result.from, 126 + namedImports, 127 + }); 128 + } 129 + } 130 + } 131 + } 95 132 96 133 // generate type imports and re-exports 97 134 for (const lexicon of lexiconDocs) {
+52 -17
lex-gen/codegen/lex-gen.ts
··· 191 191 if (needsBlobRef) { 192 192 file.addImportDeclaration({ 193 193 isTypeOnly: true, 194 - moduleSpecifier: "@atp/lexicon", 194 + moduleSpecifier: "@atp/lexicon", 195 195 namedImports: [{ name: "BlobRef" }], 196 196 }); 197 197 } ··· 200 200 if (needsCID) { 201 201 file.addImportDeclaration({ 202 202 isTypeOnly: true, 203 - moduleSpecifier: "multiformats/cid", 203 + moduleSpecifier: "multiformats/cid", 204 204 namedImports: [{ name: "CID" }], 205 205 }); 206 206 } 207 207 208 208 const utilPath = `${ 209 - baseNsid 210 - .split(".") 211 - .map((_str) => "..") 212 - .join("/") 209 + baseNsid 210 + .split(".") 211 + .map((_str) => "..") 212 + .join("/") 213 213 }/util${importExtension}`; 214 214 215 215 if (needsTypedValidation) { ··· 280 280 } 281 281 } 282 282 283 + export function collectExternalImports( 284 + lexiconDocs: LexiconDoc[], 285 + options?: CodeGenOptions, 286 + ): Map<string, Set<string>> { 287 + const imports: Map<string, Set<string>> = new Map(); 288 + const mappings = options?.mappings; 289 + 290 + // Check if any records exist (which use ATP_METHODS) 291 + const hasRecords = lexiconDocs.some((lexiconDoc) => 292 + Object.values(lexiconDoc.defs).some((def) => def.type === "record") 293 + ); 294 + 295 + // Record classes use ATP_METHODS which may need external imports 296 + // Note: put is commented out in genRecordCls, so we don't import it 297 + if (hasRecords) { 298 + const atpMethods = [ 299 + "com.atproto.repo.listRecords", 300 + "com.atproto.repo.getRecord", 301 + "com.atproto.repo.createRecord", 302 + "com.atproto.repo.deleteRecord", 303 + ]; 304 + for (const methodNsid of atpMethods) { 305 + const mapping = resolveExternalImport(methodNsid, mappings); 306 + if (mapping) { 307 + if (!imports.has(methodNsid)) { 308 + imports.set(methodNsid, new Set()); 309 + } 310 + // These methods use QueryParams, InputSchema, etc. 311 + imports.get(methodNsid)!.add("main"); 312 + } 313 + } 314 + } 315 + return imports; 316 + } 317 + 283 318 export function genImports( 284 319 file: SourceFile, 285 320 imports: Map<string, Set<string>>, ··· 298 333 file.addImportDeclaration({ 299 334 isTypeOnly: true, 300 335 moduleSpecifier: mapping.imports, 301 - namespaceImport: toTitleCase(nsid), 336 + namedImports: [{ name: toTitleCase(nsid), isTypeOnly: true }], 302 337 }); 303 338 } else { 304 339 const result = mapping.imports(nsid); ··· 322 357 } 323 358 } else { 324 359 const targetPath = "/" + nsid.split(".").join("/") + importExtension; 325 - let resolvedPath = getRelativePath(startPath, targetPath); 326 - if (!resolvedPath.startsWith(".")) { 327 - resolvedPath = `./${resolvedPath}`; 328 - } 329 - file.addImportDeclaration({ 330 - isTypeOnly: true, 331 - moduleSpecifier: resolvedPath, 332 - namespaceImport: toTitleCase(nsid), 333 - }); 360 + let resolvedPath = getRelativePath(startPath, targetPath); 361 + if (!resolvedPath.startsWith(".")) { 362 + resolvedPath = `./${resolvedPath}`; 363 + } 364 + file.addImportDeclaration({ 365 + isTypeOnly: true, 366 + moduleSpecifier: resolvedPath, 367 + namespaceImport: toTitleCase(nsid), 368 + }); 334 369 } 335 370 } 336 371 } ··· 890 925 return `$Typed<${refToType(ref, baseNsid, imports, mappings)}>`; 891 926 } 892 927 893 - function resolveExternalImport( 928 + export function resolveExternalImport( 894 929 nsid: string, 895 930 mappings?: ImportMapping[], 896 931 ): ImportMapping | undefined {
+39 -2
lex-gen/codegen/server.ts
··· 9 9 import type { GeneratedAPI } from "../types.ts"; 10 10 import { gen, lexiconsTs, utilTs } from "./common.ts"; 11 11 import { 12 + collectExternalImports, 12 13 genCommonImports, 13 14 genImports, 14 15 genRecord, ··· 16 17 genXrpcInput, 17 18 genXrpcOutput, 18 19 genXrpcParams, 20 + resolveExternalImport, 19 21 } from "./lex-gen.ts"; 20 22 import { 21 23 type CodeGenOptions, ··· 95 97 name: "schemas", 96 98 }); 97 99 100 + // collect and import external lexicon references 101 + const externalImports = collectExternalImports(lexiconDocs, options); 102 + const mappings = options?.mappings; 103 + for (const [nsid, types] of externalImports) { 104 + const mapping = resolveExternalImport(nsid, mappings); 105 + if (mapping) { 106 + if (typeof mapping.imports === "string") { 107 + file.addImportDeclaration({ 108 + isTypeOnly: true, 109 + moduleSpecifier: mapping.imports, 110 + namedImports: [{ name: toTitleCase(nsid), isTypeOnly: true }], 111 + }); 112 + } else { 113 + const result = mapping.imports(nsid); 114 + if (result.type === "namespace") { 115 + file.addImportDeclaration({ 116 + isTypeOnly: true, 117 + moduleSpecifier: result.from, 118 + namespaceImport: toTitleCase(nsid), 119 + }); 120 + } else { 121 + const namedImports = Array.from(types).map((typeName) => ({ 122 + name: toTitleCase(typeName), 123 + isTypeOnly: true, 124 + })); 125 + file.addImportDeclaration({ 126 + isTypeOnly: true, 127 + moduleSpecifier: result.from, 128 + namedImports, 129 + }); 130 + } 131 + } 132 + } 133 + } 134 + 98 135 // generate type imports 99 136 for (const lexiconDoc of lexiconDocs) { 100 137 if ( ··· 106 143 } 107 144 file.addImportDeclaration({ 108 145 isTypeOnly: true, 109 - moduleSpecifier: `./types/${ 110 - lexiconDoc.id.split(".").join("/") 146 + moduleSpecifier: `./types/${ 147 + lexiconDoc.id.split(".").join("/") 111 148 }${importExtension}`, 112 149 namespaceImport: toTitleCase(lexiconDoc.id), 113 150 });