Skip to content

Commit

Permalink
temp
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurfiorette committed May 22, 2024
1 parent a699a4d commit 8b39cf2
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 8 deletions.
74 changes: 66 additions & 8 deletions src/SchemaGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,12 @@ export class SchemaGenerator {
this.inspectNode(sourceFile, typeChecker, types);
}
}
protected inspectNode(node: ts.Node, typeChecker: ts.TypeChecker, allTypes: Map<string, ts.Node>): void {
protected inspectNode(
node: ts.Node,
typeChecker: ts.TypeChecker,
allTypes: Map<string, ts.Node>,
forceExpose = false,
): void {
switch (node.kind) {
case ts.SyntaxKind.VariableDeclaration: {
const variableDeclarationNode = node as ts.VariableDeclaration;
Expand All @@ -155,6 +160,7 @@ export class SchemaGenerator {
case ts.SyntaxKind.EnumDeclaration:
case ts.SyntaxKind.TypeAliasDeclaration:
if (
forceExpose ||
this.config?.expose === "all" ||
(this.isExportType(node) && !this.isGenericType(node as ts.TypeAliasDeclaration))
) {
Expand All @@ -171,18 +177,55 @@ export class SchemaGenerator {
case ts.SyntaxKind.ExportSpecifier: {
const exportSpecifierNode = node as ts.ExportSpecifier;
const symbol = typeChecker.getExportSpecifierLocalTargetSymbol(exportSpecifierNode);
if (symbol?.declarations?.length === 1) {
const declaration = symbol.declarations[0];

// should never hit this (maybe type error in user's code)
if (!symbol || !symbol.declarations) {
return;
}

for (const declaration of symbol.declarations) {
if (declaration.kind === ts.SyntaxKind.ImportSpecifier) {
// Handling the `Foo` in `import { Foo } from "./lib"; export { Foo };`
const importSpecifierNode = declaration as ts.ImportSpecifier;
const type = typeChecker.getTypeAtLocation(importSpecifierNode);
if (type.symbol?.declarations?.length === 1) {
this.inspectNode(type.symbol.declarations[0], typeChecker, allTypes);

const symbol =
typeChecker.getTypeAtLocation(importSpecifierNode).symbol ||
typeChecker.getSymbolAtLocation(importSpecifierNode) ||
importSpecifierNode.symbol;

// should never hit this (maybe type error in user's code)
if (!symbol?.declarations) {
return;
}

for (const declaration of symbol.declarations) {
// all statements here were inside a export { Foo } statement,
// so they must be exported

// recursion doesn't work here
if (ts.isImportSpecifier(declaration)) {
// directly import/exported nodes.
const symbol =
typeChecker.getTypeAtLocation(declaration).symbol ||
typeChecker.getSymbolAtLocation(declaration) ||
declaration.symbol;

// should never hit this (maybe type error in user's code)
if (!symbol?.declarations) {
console.log(symbol);
return;
}

for (const subdecl of symbol.declarations) {
console.log(subdecl.kind, subdecl.getText());
}
} else {
this.inspectNode(declaration, typeChecker, allTypes, true);
}
}
} else {
// Handling the `Bar` in `export { Bar } from './lib';`
this.inspectNode(declaration, typeChecker, allTypes);
this.inspectNode(declaration, typeChecker, allTypes, true);
}
}
return;
Expand All @@ -192,8 +235,23 @@ export class SchemaGenerator {
return;
}

// export { variable } clauses
if (!node.moduleSpecifier) {
if (!node.exportClause) {
throw new Error(
`ExportDeclaration has no moduleSpecifier or exportClause: ${node.pos === -1 ? "<unresolved>" : node.getText()}`,
);
}

if (ts.isNamespaceExport(node.exportClause)) {
throw new Error(
`Namespace exports are not supported: ${node.pos === -1 ? "<unresolved>" : node.getText()}`,
);
}

for (const element of node.exportClause.elements) {
this.inspectNode(element, typeChecker, allTypes);
}

return;
}

Expand Down
1 change: 1 addition & 0 deletions test/valid-data-type.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,5 @@ describe("valid-data-type", () => {
it("promise-extensions", assertValidSchema("promise-extensions", "*"));

it("export-star", assertValidSchema("export-star", "*", undefined, { mainTsOnly: true }));
it.only("export-braces", assertValidSchema("export-braces", "*", undefined, { mainTsOnly: true }));
});
5 changes: 5 additions & 0 deletions test/valid-data/export-braces/literal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export type A = 1;

export type B = "string";

type C = "internal";
8 changes: 8 additions & 0 deletions test/valid-data/export-braces/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { A, B } from "./literal";
import { D, E } from "./object";

type External = 1;

type Internal = 2;

export { A, B, D, E, type External };
11 changes: 11 additions & 0 deletions test/valid-data/export-braces/object.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export interface D {
a: 1;
}

export class E {
b: 2;
}

interface F {
internal: true;
}
43 changes: 43 additions & 0 deletions test/valid-data/export-braces/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"A": {
"const": 1,
"type": "number"
},
"B": {
"const": "string",
"type": "string"
},
"D": {
"additionalProperties": false,
"properties": {
"a": {
"const": 1,
"type": "number"
}
},
"required": [
"a"
],
"type": "object"
},
"E": {
"additionalProperties": false,
"properties": {
"b": {
"const": 2,
"type": "number"
}
},
"required": [
"b"
],
"type": "object"
},
"External": {
"const": 1,
"type": "number"
}
}
}

0 comments on commit 8b39cf2

Please sign in to comment.