diff --git a/lex-gen/codegen/client.ts b/lex-gen/codegen/client.ts index fef92ba..0ec6a9d 100644 --- a/lex-gen/codegen/client.ts +++ b/lex-gen/codegen/client.ts @@ -74,9 +74,9 @@ const indexTs = ( file.addImportDeclaration({ moduleSpecifier: "@atp/xrpc", namedImports: [ - { name: "XrpcClient" }, - { name: "FetchHandler", isTypeOnly: true }, - { name: "FetchHandlerOptions", isTypeOnly: true }, + { name: "XrpcClient" }, + { name: "FetchHandler", isTypeOnly: true }, + { name: "FetchHandlerOptions", isTypeOnly: true }, ], }); //= import {schemas} from './lexicons.ts' @@ -637,6 +637,7 @@ function genClientXrpcCommon( name: "toKnownErr", isExported: true, parameters: [{ name: "e", type: "unknown" }], + returnType: "unknown", statements: customErrors.length ? [ "if (e instanceof XRPCError) {", diff --git a/lex-gen/codegen/lex-gen.ts b/lex-gen/codegen/lex-gen.ts index d696c38..efb98a4 100644 --- a/lex-gen/codegen/lex-gen.ts +++ b/lex-gen/codegen/lex-gen.ts @@ -191,7 +191,7 @@ export function genCommonImports( if (needsBlobRef) { file.addImportDeclaration({ isTypeOnly: true, - moduleSpecifier: "@atp/lexicon", + moduleSpecifier: "@atp/lexicon", namedImports: [{ name: "BlobRef" }], }); } @@ -200,16 +200,16 @@ export function genCommonImports( if (needsCID) { file.addImportDeclaration({ isTypeOnly: true, - moduleSpecifier: "multiformats/cid", + moduleSpecifier: "multiformats/cid", namedImports: [{ name: "CID" }], }); } const utilPath = `${ - baseNsid - .split(".") - .map((_str) => "..") - .join("/") + baseNsid + .split(".") + .map((_str) => "..") + .join("/") }/util${importExtension}`; if (needsTypedValidation) { @@ -225,6 +225,13 @@ export function genCommonImports( }) .addNamedImports([{ name: "validate", alias: "_validate" }]); + //= import type { ValidationResult } from '@atp/lexicon' + file.addImportDeclaration({ + isTypeOnly: true, + moduleSpecifier: "@atp/lexicon", + namedImports: [{ name: "ValidationResult" }], + }); + // tsc adds protection against circular imports, which hurts bundle size. // Since we know that lexicon.ts and util.ts do not depend on the file being // generated, we can safely bypass this protection. @@ -286,12 +293,12 @@ export function collectExternalImports( ): Map> { const imports: Map> = new Map(); const mappings = options?.mappings; - + // Check if any records exist (which use ATP_METHODS) const hasRecords = lexiconDocs.some((lexiconDoc) => Object.values(lexiconDoc.defs).some((def) => def.type === "record") ); - + // Record classes use ATP_METHODS which may need external imports // Note: put is commented out in genRecordCls, so we don't import it if (hasRecords) { @@ -357,15 +364,15 @@ export function genImports( } } else { const targetPath = "/" + nsid.split(".").join("/") + importExtension; - let resolvedPath = getRelativePath(startPath, targetPath); - if (!resolvedPath.startsWith(".")) { - resolvedPath = `./${resolvedPath}`; - } - file.addImportDeclaration({ - isTypeOnly: true, - moduleSpecifier: resolvedPath, - namespaceImport: toTitleCase(nsid), - }); + let resolvedPath = getRelativePath(startPath, targetPath); + if (!resolvedPath.startsWith(".")) { + resolvedPath = `./${resolvedPath}`; + } + file.addImportDeclaration({ + isTypeOnly: true, + moduleSpecifier: resolvedPath, + namespaceImport: toTitleCase(nsid), + }); } } } @@ -563,6 +570,7 @@ export function genToken(file: SourceFile, lexUri: string, def: LexToken) { declarations: [ { name: toScreamingSnakeCase(getHash(lexUri)), + type: "string", initializer: `\`\${id}#${getHash(lexUri)}\``, }, ], @@ -868,24 +876,26 @@ function genObjHelpers( const isX = toCamelCase(`is-${ifaceName}`); - //= export function is{X}(v: V) {...} + //= export function is{X}(v: V): v is {ifaceName} & V {...} file .addFunction({ name: isX, typeParameters: [{ name: `V` }], parameters: [{ name: `v`, type: `V` }], + returnType: `v is ${ifaceName} & V`, isExported: true, }) .setBodyText(`return is$typed(v, id, ${hashVar})`); const validateX = toCamelCase(`validate-${ifaceName}`); - //= export function validate{X}(v: unknown) {...} + //= export function validate{X}(v: V): ValidationResult<{ifaceName} & V> {...} file .addFunction({ name: validateX, typeParameters: [{ name: `V` }], parameters: [{ name: `v`, type: `V` }], + returnType: `ValidationResult<${ifaceName} & V>`, isExported: true, }) .setBodyText( diff --git a/lex-gen/codegen/server.ts b/lex-gen/codegen/server.ts index 73aefae..1ac8ac2 100644 --- a/lex-gen/codegen/server.ts +++ b/lex-gen/codegen/server.ts @@ -143,8 +143,8 @@ const indexTs = ( } file.addImportDeclaration({ isTypeOnly: true, - moduleSpecifier: `./types/${ - lexiconDoc.id.split(".").join("/") + moduleSpecifier: `./types/${ + lexiconDoc.id.split(".").join("/") }${importExtension}`, namespaceImport: toTitleCase(lexiconDoc.id), });