diff options
Diffstat (limited to 'packages/typescript-types')
-rw-r--r-- | packages/typescript-types/extract-dom-types.ts | 82 | ||||
-rw-r--r-- | packages/typescript-types/package.json | 3 | ||||
-rw-r--r-- | packages/typescript-types/src/index.ts | 15 | ||||
-rw-r--r-- | packages/typescript-types/tsconfig.json | 6 |
4 files changed, 103 insertions, 3 deletions
diff --git a/packages/typescript-types/extract-dom-types.ts b/packages/typescript-types/extract-dom-types.ts new file mode 100644 index 0000000..bc16554 --- /dev/null +++ b/packages/typescript-types/extract-dom-types.ts @@ -0,0 +1,82 @@ +// n.b. ts-morph is a sibling devDependency of typescript, so that the module +// loader will resolve our project's typescript package, not the transient +// dependency of ts-morph. We only want to reference our typescript dependency +// for its version and its lib.dom.d.ts file. If any typescript functionality +// is needed, use import { ts } from "ts-morph"; +import { + InterfaceDeclaration, + Node, + Project, + Structure, + SyntaxKind, + TypeAliasDeclaration, +} from 'ts-morph'; +import { version } from 'typescript'; + +// List of types we directly reference from the dom lib. Only interface and type +// alias identifiers are valid, since other syntax types (class, function, var) +// are implementations, which will not be available outside of the browser. +const types = [ + 'AuthenticatorAssertionResponse', + 'AttestationConveyancePreference', + 'AuthenticatorAttestationResponse', + 'AuthenticatorTransport', + 'AuthenticationExtensionsClientInputs', + 'AuthenticatorSelectionCriteria', + 'COSEAlgorithmIdentifier', + 'PublicKeyCredential', + 'PublicKeyCredentialCreationOptions', + 'PublicKeyCredentialDescriptor', + 'PublicKeyCredentialParameters', + 'PublicKeyCredentialRequestOptions', + 'PublicKeyCredentialUserEntity', + 'UserVerificationRequirement', +]; + +const project = new Project({ skipAddingFilesFromTsConfig: true }); +const domSourcePath = 'typescript/lib/lib.dom.d.ts'; +const domSourceFile = project.addSourceFileAtPath(require.resolve(domSourcePath)); +const resolvedNodes = new Set<InterfaceDeclaration | TypeAliasDeclaration>(); +const unresolvedNodes = new Set<InterfaceDeclaration | TypeAliasDeclaration>( + types.map(type => { + const node = domSourceFile.getInterface(type) ?? domSourceFile.getTypeAlias(type); + if (!node) { + throw new Error(`${type} does not refer to an interface or type alias`); + } + return node; + }), +); + +while (unresolvedNodes.size > 0) { + for (const node of unresolvedNodes.values()) { + unresolvedNodes.delete(node); + resolvedNodes.add(node); + + // Declarations in lib files are never exported because they are globally + // available. Since we are extracting the types to a module, we export them. + node.setIsExported(true); + + // Find all descendant identifiers which reference an interface or type + // alias, and add them to the unresolved list. + for (const id of node.getDescendantsOfKind(SyntaxKind.Identifier)) { + for (const dn of id.getDefinitionNodes()) { + if (Node.isInterfaceDeclaration(dn) || Node.isTypeAliasDeclaration(dn)) { + if (!resolvedNodes.has(dn)) { + unresolvedNodes.add(dn); + } + } + } + } + } +} + +const outputSourceFile = project.createSourceFile(`src/dom.ts`, undefined, { overwrite: true }); +outputSourceFile.addStatements([ + `// Generated from typescript@${version} ${domSourcePath}`, + `// To regenerate, run the following command from the project root:`, + `// npx lerna --scope=@simplewebauthn/typescript-types exec -- npm run extract-dom-types`, +]); +const resolvedStructures = Array.from(resolvedNodes).map(node => node.getStructure()); +outputSourceFile.addInterfaces(resolvedStructures.filter(Structure.isInterface)); +outputSourceFile.addTypeAliases(resolvedStructures.filter(Structure.isTypeAlias)); +outputSourceFile.saveSync(); diff --git a/packages/typescript-types/package.json b/packages/typescript-types/package.json index 4a42c95..a05db68 100644 --- a/packages/typescript-types/package.json +++ b/packages/typescript-types/package.json @@ -16,7 +16,8 @@ "access": "public" }, "scripts": { - "build": "rimraf dist && tsc", + "build": "rimraf dist && npm run extract-dom-types && tsc", + "extract-dom-types": "ts-node extract-dom-types.ts", "prepublish": "npm run build" }, "keywords": [ diff --git a/packages/typescript-types/src/index.ts b/packages/typescript-types/src/index.ts index 4f238d7..954615b 100644 --- a/packages/typescript-types/src/index.ts +++ b/packages/typescript-types/src/index.ts @@ -2,6 +2,21 @@ * @packageDocumentation * @module @simplewebauthn/typescript-types */ + +import type { + AuthenticatorAssertionResponse, + AuthenticatorAttestationResponse, + AuthenticatorTransport, + COSEAlgorithmIdentifier, + PublicKeyCredential, + PublicKeyCredentialCreationOptions, + PublicKeyCredentialDescriptor, + PublicKeyCredentialRequestOptions, + PublicKeyCredentialUserEntity, +} from './dom'; + +export * from './dom'; + /** * A variant of PublicKeyCredentialCreationOptions suitable for JSON transmission to the browser to * (eventually) get passed into navigator.credentials.create(...) in the browser. diff --git a/packages/typescript-types/tsconfig.json b/packages/typescript-types/tsconfig.json index 349e40c..6dfff5f 100644 --- a/packages/typescript-types/tsconfig.json +++ b/packages/typescript-types/tsconfig.json @@ -2,6 +2,8 @@ "extends": "../../tsconfig.json", "compilerOptions": { "baseUrl": "./src", - "outDir": "./dist" - } + "outDir": "./dist", + "emitDeclarationOnly": true + }, + "include": ["src/**/*"] } |