diff --git a/src/SchemaGenerator.ts b/src/SchemaGenerator.ts index 7c990d479..4d9665f1d 100644 --- a/src/SchemaGenerator.ts +++ b/src/SchemaGenerator.ts @@ -31,8 +31,8 @@ export class SchemaGenerator { rootType: this.nodeParser.createType(rootNode, new Context()), })); - const rootTypeDefinition = - roots.length === 1 ? this.getRootTypeDefinition(roots[0].rootType, roots[0].rootNode) : undefined; + const rootTypeDefinitions = roots.map((root) => this.getRootTypeDefinition(root.rootType, root.rootNode)); + const rootTypeDefinition = rootTypeDefinitions.length === 1 ? rootTypeDefinitions[0] : undefined; const definitions: StringMap = {}; for (const root of roots) { @@ -47,7 +47,10 @@ export class SchemaGenerator { } } - const reachableDefinitions = removeUnreachable(rootTypeDefinition, definitions); + const reachableDefinitions = rootTypeDefinitions.reduce>( + (acc, def) => Object.assign(acc, removeUnreachable(def, definitions)), + {}, + ); return { ...(this.config?.schemaId ? { $id: this.config.schemaId } : {}), @@ -229,11 +232,18 @@ export class SchemaGenerator { return; } - // export { variable } clauses + if (node.exportClause) { + // export { Foo } from './lib' or export { Foo }; + // export * as Foo from './lib' should not import all exports + ts.forEachChild(node.exportClause, (subnode) => this.inspectNode(subnode, typeChecker, allTypes)); + return; + } + if (!node.moduleSpecifier) { return; } + // export * from './lib' const symbol = typeChecker.getSymbolAtLocation(node.moduleSpecifier); // should never hit this (maybe type error in user's code) diff --git a/test/valid-data-type.test.ts b/test/valid-data-type.test.ts index 9a3d882b3..045ac1816 100644 --- a/test/valid-data-type.test.ts +++ b/test/valid-data-type.test.ts @@ -151,4 +151,8 @@ describe("valid-data-type", () => { it("promise-extensions", assertValidSchema("promise-extensions", "*")); it("export-star", assertValidSchema("export-star", "*", undefined, { mainTsOnly: true })); + it( + "export-star-prune-unreachable", + assertValidSchema("export-star-prune-unreachable", "*", undefined, { mainTsOnly: true }), + ); }); diff --git a/test/valid-data/export-star-prune-unreachable/dep.ts b/test/valid-data/export-star-prune-unreachable/dep.ts new file mode 100644 index 000000000..7c0f0ed42 --- /dev/null +++ b/test/valid-data/export-star-prune-unreachable/dep.ts @@ -0,0 +1,5 @@ +export interface SomeInterface { + foo?: string; +} + +export type DepType = string; diff --git a/test/valid-data/export-star-prune-unreachable/dep2.ts b/test/valid-data/export-star-prune-unreachable/dep2.ts new file mode 100644 index 000000000..355b63a6d --- /dev/null +++ b/test/valid-data/export-star-prune-unreachable/dep2.ts @@ -0,0 +1 @@ +export type DepType2 = string; diff --git a/test/valid-data/export-star-prune-unreachable/main.ts b/test/valid-data/export-star-prune-unreachable/main.ts new file mode 100644 index 000000000..96b35de71 --- /dev/null +++ b/test/valid-data/export-star-prune-unreachable/main.ts @@ -0,0 +1,14 @@ +import type { SomeInterface } from "./dep"; +export { DepType } from "./dep"; +export * from "./dep2"; + +export type MyType = string; + +export interface MyObject extends SomeInterface { + bar?: number; + baz?: Internal; +} + +interface Internal { + nested?: boolean; +} diff --git a/test/valid-data/export-star-prune-unreachable/schema.json b/test/valid-data/export-star-prune-unreachable/schema.json new file mode 100644 index 000000000..bcf4007c7 --- /dev/null +++ b/test/valid-data/export-star-prune-unreachable/schema.json @@ -0,0 +1,35 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "DepType": { + "type": "string" + }, + "DepType2": { + "type": "string" + }, + "MyObject": { + "additionalProperties": false, + "properties": { + "bar": { + "type": "number" + }, + "baz": { + "additionalProperties": false, + "properties": { + "nested": { + "type": "boolean" + } + }, + "type": "object" + }, + "foo": { + "type": "string" + } + }, + "type": "object" + }, + "MyType": { + "type": "string" + } + } +}