core-types-ts
Advanced tools
Comparing version 3.1.0 to 3.2.0
@@ -5,2 +5,5 @@ import { NodeDocument, ConversionResult, NamedType } from "core-types"; | ||
export declare function convertCoreTypesToTypeScript(doc: NodeDocument, opts?: ToTsOptions): ConversionResult; | ||
export declare function convertSingleCoreTypeToTypeScriptAst(node: NamedType, opts?: Pick<ToTsOptions, 'useUnknown' | 'declaration'>): ts.Declaration; | ||
export declare function convertSingleCoreTypeToTypeScriptAst(node: NamedType, opts?: Pick<ToTsOptions, 'useUnknown' | 'declaration' | 'namespaces'>): { | ||
declaration: ts.Declaration; | ||
namespaceList: string[]; | ||
}; |
@@ -18,2 +18,7 @@ "use strict"; | ||
const convertedTypes = []; | ||
const wrapInNamespaces = (code, namespaceList) => namespaceList.length === 0 | ||
? code | ||
: namespaceList.map(ns => `namespace ${ns} {`).join(' ') + | ||
`\n${code}\n` + | ||
namespaceList.map(() => '}').join(' '); | ||
const sourceCode = types | ||
@@ -26,3 +31,3 @@ .map(node => { | ||
}) | ||
.map(tsNode => (0, ts_helpers_1.generateCode)(tsNode)) | ||
.map(({ declaration: tsNode, namespaceList }) => wrapInNamespaces((0, ts_helpers_1.generateCode)(tsNode), namespaceList)) | ||
.join("\n\n"); | ||
@@ -44,7 +49,7 @@ const header = (0, ts_helpers_1.createCodeHeader)({ | ||
function convertSingleCoreTypeToTypeScriptAst(node, opts = {}) { | ||
const { useUnknown = false, declaration = false, } = opts; | ||
const { useUnknown = false, declaration = false, namespaces = 'ignore', } = opts; | ||
const ctx = { | ||
useUnknown, | ||
}; | ||
const { name } = node; | ||
const { name, namespaces: namespaceList } = makeNameAndNamespace(node.name, namespaces); | ||
const ret = tsType(ctx, node); | ||
@@ -55,5 +60,18 @@ const doExport = (tsNode) => (0, ts_helpers_1.wrapAnnotations)(tsNode, node); | ||
: declareInterface(declaration, name, ret.properties); | ||
return doExport(typeDeclaration); | ||
return { | ||
declaration: doExport(typeDeclaration), | ||
namespaceList, | ||
}; | ||
} | ||
exports.convertSingleCoreTypeToTypeScriptAst = convertSingleCoreTypeToTypeScriptAst; | ||
function makeNameAndNamespace(name, namespaces) { | ||
if (!namespaces || namespaces === 'ignore') | ||
return { name, namespaces: [] }; | ||
const parts = name | ||
.split(namespaces === 'dot' ? '.' : | ||
namespaces === 'underscore' ? '_' : | ||
/[._]/); | ||
const lastPart = parts.pop(); | ||
return { name: lastPart, namespaces: parts }; | ||
} | ||
function createExportModifier(declaration) { | ||
@@ -60,0 +78,0 @@ return factory.createModifiersFromModifierFlags(declaration |
@@ -20,12 +20,63 @@ "use strict"; | ||
function convertTypeScriptToCoreTypes(sourceCode, options) { | ||
const { warn = defaultWarn(sourceCode), nonExported = 'include-if-referenced', unsupported = 'ignore', } = options !== null && options !== void 0 ? options : {}; | ||
const { warn = defaultWarn(sourceCode), namespaces = 'ignore', nonExported = 'include-if-referenced', unsupported = 'ignore', } = options !== null && options !== void 0 ? options : {}; | ||
const sourceFile = ts.createSourceFile("filename.ts", sourceCode, ts.ScriptTarget.Latest, | ||
/*setParentNodes */ true); | ||
const declarations = sourceFile.statements | ||
.filter((statement) => ts.isTypeAliasDeclaration(statement) | ||
const isTopLevelDeclaration = (statement) => ts.isTypeAliasDeclaration(statement) | ||
|| | ||
ts.isInterfaceDeclaration(statement)); | ||
ts.isInterfaceDeclaration(statement); | ||
const recurseNamespaces = (namespaceParents, statements) => [ | ||
...statements | ||
.filter((statement) => ts.isModuleDeclaration(statement)) | ||
.flatMap(statement => statement.body.kind !== ts.SyntaxKind.ModuleBlock | ||
? [] | ||
: recurseNamespaces([...namespaceParents, statement.name.getText()], statement.body.statements)), | ||
...statements | ||
.filter(isTopLevelDeclaration) | ||
.map((statement) => { | ||
if (namespaceParents.length > 0 && | ||
namespaces === 'ignore') | ||
return undefined; | ||
return { namespaceParents, declaration: statement }; | ||
}) | ||
.filter((v) => !!v), | ||
]; | ||
const filterConflicts = (declarations) => { | ||
const byName = new Map(); | ||
declarations.forEach((exportedDeclaration) => { | ||
const { declaration, namespaceParents } = exportedDeclaration; | ||
const name = declaration.name.getText(); | ||
const item = byName.get(name); | ||
if (!item) { | ||
byName.set(name, exportedDeclaration); | ||
return; | ||
} | ||
if (item.namespaceParents.length > namespaceParents.length) { | ||
// Replace with higher-level declaration | ||
byName.set(name, exportedDeclaration); | ||
} | ||
}); | ||
return [...byName.values()]; | ||
}; | ||
// Given the <namespaces> configuration, set an appropriate name for the | ||
// exported type. | ||
const renameDeclaration = ({ declaration, namespaceParents }) => { | ||
const name = declaration.name.getText(); | ||
const fullName = namespaces === 'hoist' || namespaces === 'ignore' | ||
? name | ||
: [...namespaceParents, name] | ||
.join(namespaces === 'join-dot' ? '.' : '_'); | ||
const identifier = ts.factory.createIdentifier(fullName); | ||
identifier.getText = _ => fullName; | ||
declaration.name = identifier; | ||
return declaration; | ||
}; | ||
const flattenAndFilterConflicts = (declarations) => (namespaces === 'hoist' | ||
? filterConflicts(declarations) | ||
: declarations) | ||
.map(renameDeclaration); | ||
const declarations = flattenAndFilterConflicts(recurseNamespaces([], sourceFile.statements)); | ||
const ctx = { | ||
options: { | ||
warn, | ||
namespaces, | ||
nonExported, | ||
@@ -32,0 +83,0 @@ unsupported, |
@@ -39,2 +39,13 @@ import { WarnFunction } from 'core-types'; | ||
/** | ||
* Try to reconstruct namespaces: | ||
* | ||
* - `ignore`: Don't try to reconstruct namespaces (default) | ||
* - `dot`: Split names by dot (.) as namespaces for top-level types | ||
* - `underscore`: Split names by underscore (_) as namespaces for | ||
* top-level types | ||
* - `all`: Split by dot (.) and/or underscores (_) as namespaces for | ||
* top-level types | ||
*/ | ||
namespaces?: 'ignore' | 'dot' | 'underscore' | 'all'; | ||
/** | ||
* What to do when detecting an unsupported type | ||
@@ -51,2 +62,15 @@ * | ||
/** | ||
* How to deal with namespaces: | ||
* | ||
* - `ignore`: Ignore namespaces entirely (default) | ||
* - `hoist`: Hoist types inside namespaces to top-level, so that the | ||
* types are included, but without their namespace. This can cause | ||
* conflicts, in which case deeper declarations will be dropped in favor | ||
* of more top-level declarations. Same-level will be exported | ||
* non-deterministically. | ||
* - `join-dot`: Join namespaces and types with a dot (.) | ||
* - `join-underscore`: Join namespaces and types with an underscore (_) | ||
*/ | ||
namespaces?: 'ignore' | 'hoist' | 'join-dot' | 'join-underscore'; | ||
/** | ||
* What to do when detecting a non-exported type: | ||
@@ -53,0 +77,0 @@ * |
{ | ||
"name": "core-types-ts", | ||
"version": "3.1.0", | ||
"version": "3.2.0", | ||
"description": "core-types ⬌ TypeScript interface conversion", | ||
@@ -5,0 +5,0 @@ "author": "Gustaf Räntilä", |
@@ -59,2 +59,3 @@ [![npm version][npm-image]][npm-url] | ||
noDescriptiveHeader?: boolean; | ||
namespaces?: 'ignore'| 'dot'| 'underscore'| 'all'; | ||
unsupported?: 'ignore' | 'warn' | 'error'; | ||
@@ -75,2 +76,7 @@ } | ||
* `noDescriptiveHeader`: Do no write a top-level descriptive comment about the auto-generated file | ||
* `namespaces`: Try to reconstruct namespaces | ||
* `ignore`: Don't try to reconstruct namespaces (default) | ||
* `dot`: Split names by dot (.) as namespaces for top-level types | ||
* `underscore`: Split names by underscore (_) as namespaces for top-level types | ||
* `all`: Split by dot (.) and/or underscores (_) as namespaces for top-level types | ||
* `unsupported`: What to do when detecting an unsupported type | ||
@@ -100,2 +106,3 @@ * `ignore`: Ignore (skip) type | ||
warn?: WarnFunction; | ||
namespaces?: 'ignore' | 'hoist' | 'join-dot' | 'join-underscore'; | ||
nonExported?: 'fail' | 'ignore' | 'include' | 'inline' | 'include-if-referenced'; | ||
@@ -107,2 +114,7 @@ unsupported?: 'ignore' | 'warn' | 'error'; | ||
* `warn`: The same warn function as in [CoreTypesToGraphqlOptions](#core-types-to-graphql) | ||
* `namespaces`: How to deal with namespaces | ||
*`ignore`: Ignore namespaces entirely (default) | ||
* `hoist`: Hoist types inside namespaces to top-level, so that the types are included, but without their namespace. This can cause conflicts, in which case deeper declarations will be dropped in favor of more top-level declarations. Same-level will be exported non-deterministically. | ||
* `join-dot`: Join namespaces and types with a dot (.) | ||
* `join-underscore`: Join namespaces and types with an underscore (_) | ||
* `nonExported`: How to handle references to non-exported types | ||
@@ -109,0 +121,0 @@ * `fail`: Fail conversion with an Error |
50309
965
143