ts-morph#Project TypeScript Examples
The following examples show how to use
ts-morph#Project.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: gengen.ts From gengen with MIT License | 6 votes |
export async function init(options: IOptions = defaultOptions): Promise<void> {
const generator = new ConfigGenerator();
const project = new Project(generatorsOptions);
project.createSourceFile(
`${options.configOutput}/${configOptions.filename}`,
{ statements: generator.getConfigCodeStructure() },
{ overwrite: true }
);
await project.save();
}
Example #2
Source File: gengen.ts From gengen with MIT License | 6 votes |
export async function config(options: IOptions): Promise<void> {
const settings = getOptions(options);
const swaggerJson = await getOpenAPISpec(settings);
const typesGuard = new OpenAPITypesGuard();
const openAPIService = new OpenAPIService(swaggerJson, typesGuard);
const endpointNameResolver = new EndpointNameResolver();
const endpointsService = new EndpointsService(openAPIService, endpointNameResolver);
const controllers = endpointsService.getActionsGroupedByController();
const project = new Project(generatorsOptions);
const generator = new ConfigGenerator();
const sourceFile = project.createSourceFile(
`${settings.configOutput}/${configOptions.className.toLowerCase()}.ts`,
{ statements: generator.getEndpointsCodeStructure(controllers) },
{ overwrite: true }
);
sourceFile.formatText();
await project.save();
}
Example #3
Source File: api-client-generator.ts From selling-partner-api-sdk with MIT License | 6 votes |
function generateExportStatements(project: Project, apiModels: APIModel[]) {
log.info(`Starting exporting api clients`)
const compileExportStatement = template(`export * from './<%= apiClientFileName %>'`)
const exportStatements = apiModels.map((apiModel) =>
compileExportStatement({
apiClientFileName: generateAPIClientFileName(apiModel),
}),
)
project.createSourceFile('src/api-clients/index.ts', exportStatements.join('\n'), {
overwrite: true,
})
log.info(`Finished exporting api clients`)
}
Example #4
Source File: api-client-generator.ts From selling-partner-api-sdk with MIT License | 6 votes |
export function generateAPIClients(apiModels: APIModel[]): void {
const compileAPIClient = template(apiClientTemplate)
const project = new Project({
tsConfigFilePath: TS_CONFIG_FILE_PATH,
libFolderPath: TS_LIB_FOLDER_PATH,
})
for (const apiModel of apiModels) {
const apiClientFileName = generateAPIClientFileName(apiModel)
generateAPIClient(
project,
compileAPIClient,
apiModel,
apiClientFileName,
generateAPIClientClassname(apiClientFileName),
)
}
generateExportStatements(project, apiModels)
project.saveSync()
}
Example #5
Source File: api-model-generator.ts From selling-partner-api-sdk with MIT License | 6 votes |
export async function generateExportStatement(model: APIModel): Promise<string> {
// Export all enums and interfaces
const sourceFile = new Project({
tsConfigFilePath: TS_CONFIG_FILE_PATH,
libFolderPath: TS_LIB_FOLDER_PATH,
}).getSourceFileOrThrow(`${model.outputPath}/${API_MODEL_FILE_NAME}`)
const exports = [...sourceFile.getEnums(), ...sourceFile.getInterfaces()]
.map(
(declaration) =>
`${declaration.getName()} as ${upperFirst(
camelCase(model.dirname),
)}${declaration.getName()}`,
)
.join(', ')
return `export { ${exports} } from './${model.dirname}'`
}
Example #6
Source File: enum-mapping.ts From selling-partner-api-sdk with MIT License | 6 votes |
export function mapEnums2UnionType(): Promise<void>[] {
const project = new Project({
tsConfigFilePath: TS_CONFIG_FILE_PATH,
libFolderPath: TS_LIB_FOLDER_PATH,
})
return project.getSourceFiles(`src/api-models/**/${API_MODEL_FILE_NAME}`).map((sourceFile) => {
const filePath = `${sourceFile.getDirectory().getBaseName()}/${sourceFile.getBaseName()}`
log.info(`Starting mapping ${filePath}`)
const interfaceMembers: TypeElementTypes[] = sourceFile
.getInterfaces()
?.map((itf) => itf.getMembers())
.flat()
const enumsOrUnion = interfaceMembers?.filter((member) => {
const memberType = member.getType()
// TODO: filter both union and intersection type.
return memberType.isUnion() || memberType.isEnum() || memberType.isEnumLiteral()
})
const arrayOrUnion = interfaceMembers?.filter((member) => {
const memberType = member.getType()
// TODO: filter both union and intersection type.
return memberType.isUnion() || memberType.isArray()
})
if (enumsOrUnion) {
processEnumNodes(sourceFile, enumsOrUnion)
}
if (arrayOrUnion) {
processArrayNodes(sourceFile, arrayOrUnion)
}
log.info(`Finished mapping ${filePath}`)
return project.save()
})
}
Example #7
Source File: GenGenCodeGen.ts From gengen with MIT License | 6 votes |
protected generateProject(modelsCode: StatementStructures[], servicesCode: StatementStructures[]): Project {
const project = new Project(generatorsOptions);
project
.createSourceFile(
`${this.options.output}/${this.injector.aliasResolver.getModelsFileName()}`,
{ statements: modelsCode },
{ overwrite: true }
)
.formatText();
project
.createSourceFile(
`${this.options.output}/${this.injector.aliasResolver.getServicesFileName()}`,
{ statements: servicesCode },
{ overwrite: true }
)
.formatText();
return project;
}
Example #8
Source File: apiCamelCase.ts From taiga-front-next with GNU Affero General Public License v3.0 | 6 votes |
function compile() {
const project = new Project({
tsConfigFilePath: 'tsconfig.json',
addFilesFromTsConfig: false,
});
project.addSourceFilesAtPaths('src/**/*.ts');
project.getSourceFiles().forEach((sourceFile) => {
apiCamelCaseReplacements(sourceFile);
sourceFile.save();
});
}
Example #9
Source File: index.ts From tarojs-router-next with MIT License | 6 votes |
constructor(private readonly root: RouterCodeGenerator) {
this.targetModulePath = path.resolve(this.root.ctx.paths.nodeModulesPath, 'tarojs-router-next')
const tsConfigFilePath = path.resolve(this.targetModulePath, 'tsconfig.json')
this.project = new Project({
tsConfigFilePath,
})
this.routerSourceFile = this.project.addSourceFileAtPath(
path.resolve(this.targetModulePath, './src/router/index.ts')
)
}
Example #10
Source File: instructions.ts From adonis5-jwt with MIT License | 6 votes |
async function getTsMorphProject(projectRoot: string) {
const { indentationText, newLineKind } = await getIntendationConfigForTsMorph(projectRoot);
return new Project({
tsConfigFilePath: projectRoot + "/tsconfig.json",
manipulationSettings: {
indentationText: indentationText,
newLineKind: newLineKind,
useTrailingCommas: true,
},
});
}
Example #11
Source File: index.ts From tarojs-router-next with MIT License | 6 votes |
/** 解析传入包的所有路由方法 */
parse(options: { pkg: PackageConfig }) {
const { pkg } = options
const project = new Project()
const configSourceFiles = this.readConfigSourceFiles({ pkg, project })
let pages = this.createPages({ pkg })
for (const p of pages) {
p.config = pkg.pageConfigs.find((it) => it.dir === p.dir)
}
for (const sourceFile of configSourceFiles) {
const page = pages.find((p) => {
return path.resolve(p.fullPath, 'route.config.ts') === path.normalize(sourceFile.compilerNode.fileName)
})
if (!page) continue
this.parseSourceFile({
page,
project,
sourceFile,
})
}
pkg.pages = pages
}
Example #12
Source File: factory-get-source-file.ts From prisma-nestjs-graphql with MIT License | 6 votes |
export function factoryGetSourceFile(args: {
output: string;
outputFilePattern: string;
project: Project;
getModelName(name: string): string | undefined;
eventEmitter: AwaitEventEmitter;
}) {
const { outputFilePattern, output, getModelName, project } = args;
return function getSourceFile(args: { type: string; name: string }) {
const { name, type } = args;
let filePath = generateFileName({
getModelName,
name,
type,
template: outputFilePattern,
});
filePath = `${output}/${filePath}`;
return (
project.getSourceFile(filePath) ||
project.createSourceFile(filePath, undefined, { overwrite: true })
);
};
}
Example #13
Source File: swagger.handler.ts From cli with MIT License | 5 votes |
async function swaggerHandlerCore(
{ cwd: projectDirPath }: ICoreInstance,
opts: SwaggerOptions
) {
consola.info(`Project location: ${chalk.green(projectDirPath)}`);
const { dry } = applyDefaultValueToSharedOption(opts);
const { ui = false, namespace = 'swagger' } = opts;
if (dry) {
consola.success('Executing in `dry run` mode, nothing will happen.');
}
if (ui) {
consola.info(
'`swagger-ui-dist` will be installed as `dependencies` by enabled `--ui` option.'
);
SWAGGER_DEP.push(...SWAGGER_DEV_DEP);
SWAGGER_DEV_DEP.pop();
}
dry
? consola.info('`[DryRun]` Skip `dependencies` installation check.')
: await ensureDepsInstalled(SWAGGER_DEP, projectDirPath);
dry
? consola.info('`[DryRun]` Skip `devDependencies` installation check.')
: await ensureDevDepsInstalled(SWAGGER_DEV_DEP, projectDirPath);
if (!dry) {
consola.info('Source code will be transformed.');
const project = new Project();
const configurationPath = path.resolve(
projectDirPath,
'./src/configuration.ts'
);
if (!fs.existsSync(configurationPath)) {
consola.error(
`Cannot find ${chalk.cyan('configuration.ts')} in ${chalk.green(
configurationPath
)}.`
);
process.exit(0);
}
const configurationSource = project.addSourceFileAtPath(configurationPath);
addImportDeclaration(
configurationSource,
namespace,
'@midwayjs/swagger',
ImportType.NAMESPACE_IMPORT
);
updateDecoratorArrayArgs(
configurationSource,
'Configuration',
'imports',
namespace
);
formatTSFile(configurationPath);
} else {
consola.info('`[DryRun]` Source code will be transformed.');
}
}
Example #14
Source File: generate.spec.ts From prisma-nestjs-graphql with MIT License | 5 votes |
describe('scalar arrays with noAtomicOperations', () => {
let project: Project;
before(async () => {
({ project } = await testGenerate({
schema: `
model User {
id String @id
ints Int[]
articles Article[] @relation("ArticleAuthor")
}
model Article {
id String @id
author User @relation(name: "ArticleAuthor", fields: [authorId], references: [id])
authorId String
}
`,
options: [
`
noAtomicOperations = true
`,
],
}));
});
describe('ints should be array', () => {
for (const className of ['UserCreateInput']) {
it(className, () => {
const s = testSourceFile({
project,
class: className,
property: 'ints',
});
expect(s.fieldDecoratorType).toEqual('() => [Int]');
});
}
});
it('create many inputs should not be deleted', () => {
const s = testSourceFile({
project,
class: 'UserCreateInput',
property: 'articles',
});
expect(s.property?.type).toBe('ArticleCreateNestedManyWithoutAuthorInput');
});
});
Example #15
Source File: sample.ts From cli with MIT License | 5 votes |
project = new Project()
Example #16
Source File: mongodb.spec.ts From prisma-nestjs-graphql with MIT License | 5 votes |
project: Project
Example #17
Source File: custom-decorators.spec.ts From prisma-nestjs-graphql with MIT License | 5 votes |
project: Project
Example #18
Source File: hide-field.spec.ts From prisma-nestjs-graphql with MIT License | 5 votes |
project: Project
Example #19
Source File: helpers.ts From prisma-nestjs-graphql with MIT License | 5 votes |
export function testSourceFile(args: {
project: Project;
file?: string;
class?: string;
property?: string;
}) {
const { project, file, property, class: className } = args;
let sourceFile: SourceFile;
if (file) {
sourceFile = project.getSourceFileOrThrow(s => s.getFilePath().endsWith(file));
} else if (className) {
sourceFile = project.getSourceFileOrThrow(s => Boolean(s.getClass(className)));
} else {
throw new TypeError('file or class must be provided');
}
const importDeclarations = sourceFile
.getImportDeclarations()
.map(d => d.getStructure());
const classFile = sourceFile.getClass(() => true)!;
const propertyStructure =
property && classFile.getProperty(p => p.getName() === property)?.getStructure();
const propertyDecorators = (
propertyStructure as PropertyDeclarationStructure | undefined
)?.decorators;
const fieldDecorator = propertyDecorators?.find(d => d.name === 'Field');
type ImportElement = { name: string; specifier: string };
const namedImports: ImportElement[] = [];
const namespaceImports: ImportElement[] = [];
for (const d of importDeclarations) {
if (d.namespaceImport) {
namespaceImports.push({
name: d.namespaceImport,
specifier: d.moduleSpecifier,
});
}
for (const s of (d.namedImports || []) as ImportSpecifierStructure[]) {
namedImports.push({
name: s.name,
specifier: d.moduleSpecifier,
});
}
}
return {
sourceFile,
classFile,
sourceText: sourceFile.getText(),
namedImports,
namespaceImports,
property: propertyStructure as PropertyDeclarationStructure | undefined,
propertyDecorators,
fieldDecorator,
fieldDecoratorType: fieldDecorator?.arguments?.[0],
fieldDecoratorOptions: fieldDecorator?.arguments?.[1],
};
}
Example #20
Source File: decimal.spec.ts From prisma-nestjs-graphql with MIT License | 5 votes |
describe('decimal graphql noAtomicOperations', () => {
let project: Project;
before(async () => {
({ project } = await testGenerate({
schema: `
model User {
id String @id
transfers Decimal[]
}
`,
options: `
noAtomicOperations = true
`,
}));
});
it('should be array', () => {
const s = testSourceFile({
project,
class: 'UserCreateInput',
property: 'transfers',
});
expect(s.propertyDecorators).toContainEqual(
expect.objectContaining({
name: 'Type',
arguments: ['() => Object'],
}),
);
expect(s.propertyDecorators).toContainEqual(
expect.objectContaining({
name: 'Transform',
arguments: ['transformToDecimal'],
}),
);
expect(s.property?.type).toEqual('Array<Decimal>');
});
});
Example #21
Source File: decimal.spec.ts From prisma-nestjs-graphql with MIT License | 5 votes |
describe('nested object decorate', () => {
let project: Project;
before(async () => {
({ project } = await testGenerate({
schema: `
model Job {
id Int @id
salaryId Int?
salary Salary? @relation(fields: [salaryId], references: [id], onDelete: Cascade)
}
model Salary {
id Int @id
from Decimal
to Decimal
job Job[]
}
`,
options: `
noAtomicOperations = true
`,
}));
});
it('deep field should be decorated up to root', () => {
const s = testSourceFile({
project,
class: 'JobCreateInput',
property: 'salary',
});
expect(s.propertyDecorators).toContainEqual(
expect.objectContaining({ name: 'Type' }),
);
});
describe('should be decorated by type', () => {
[
'create',
'connectOrCreate',
'upsert',
'createMany',
'set',
'disconnect',
'delete',
'connect',
'update',
'updateMany',
'deleteMany',
// eslint-disable-next-line unicorn/no-array-for-each
].forEach(property => {
it(property, () => {
const s = testSourceFile({
project,
class: 'JobUncheckedUpdateManyWithoutSalaryInput',
property,
});
expect(s.propertyDecorators).toContainEqual(
expect.objectContaining({ name: 'Type' }),
);
});
});
});
it('property data should be decorated', () => {
const s = testSourceFile({
project,
class: 'JobCreateManySalaryInputEnvelope',
property: 'data',
});
expect(s.propertyDecorators).toContainEqual(
expect.objectContaining({ name: 'Type' }),
);
});
});
Example #22
Source File: generate.spec.ts From prisma-nestjs-graphql with MIT License | 5 votes |
project: Project
Example #23
Source File: test.spec.ts From prisma-nestjs-graphql with MIT License | 5 votes |
project: Project
Example #24
Source File: oss.handler.ts From cli with MIT License | 5 votes |
async function ossHandlerCore(
{ cwd: projectDirPath }: ICoreInstance,
opts: OSSOptions
) {
consola.info(`Project location: ${chalk.green(projectDirPath)}`);
const { dry } = applyDefaultValueToSharedOption(opts);
const { namespace = 'oss' } = opts;
if (dry) {
consola.success('Executing in `dry run` mode, nothing will happen.');
}
dry
? consola.info('`[DryRun]` Skip `dependencies` installation check.')
: await ensureDepsInstalled(OSS_DEP, projectDirPath);
dry
? consola.info('`[DryRun]` Skip `devDependencies` installation check.')
: await ensureDevDepsInstalled(OSS_DEV_DEP, projectDirPath);
if (!dry) {
consola.info('Source code will be transformed.');
const project = new Project();
const configurationPath = path.resolve(
projectDirPath,
'./src/configuration.ts'
);
if (!fs.existsSync(configurationPath)) {
consola.error(
`Cannot find ${chalk.cyan('configuration.ts')} in ${chalk.green(
configurationPath
)}.`
);
process.exit(0);
}
const configurationSource = project.addSourceFileAtPath(configurationPath);
addImportDeclaration(
configurationSource,
namespace,
'@midwayjs/oss',
ImportType.NAMESPACE_IMPORT
);
updateDecoratorArrayArgs(
configurationSource,
'Configuration',
'imports',
namespace
);
formatTSFile(configurationPath);
} else {
consola.info('`[DryRun]` Source code will be transformed.');
}
}
Example #25
Source File: transformer.ts From telefunc with MIT License | 5 votes |
generateShield = (
telefuncFileCode: string
): string => {
const project = new Project({
compilerOptions: {
strict: true
}
})
project.createSourceFile("types.ts", typesSrc)
const telefuncFileSource = project.createSourceFile("telefunc.ts", telefuncFileCode)
// this source file is used for evaluating the template literal types' values
const shieldStrSource = project.createSourceFile("shield-str.ts")
shieldStrSource.addImportDeclaration({
moduleSpecifier: "./types",
namedImports: ["ShieldArrStr"]
})
const telefunctions = telefuncFileSource.getFunctions().filter(f => f.isExported())
const telefunctionNames = telefunctions.flatMap(telefunction => {
const name = telefunction.getName()
if (!name) return []
return [name]
})
shieldStrSource.addImportDeclaration({
moduleSpecifier: "./telefunc",
namedImports: telefunctionNames
})
// assign the template literal type to a string
// then diagnostics are used to get the value of the template literal type
for (const telefunctionName of telefunctionNames) {
shieldStrSource.addTypeAlias({
name: `${telefunctionName}Shield`,
type: `ShieldArrStr<Parameters<typeof ${telefunctionName}>>`
})
}
const shieldAlias = '__shieldGenerator_shield' // alias for shield
telefuncFileSource.addImportDeclaration({
moduleSpecifier: 'telefunc',
namedImports: [{
name: 'shield',
alias: shieldAlias
}]
})
telefuncFileSource.addVariableStatement({
declarationKind: VariableDeclarationKind.Const,
declarations: [{
name: tAlias,
initializer: `${shieldAlias}.type`,
}]
})
for (const telefunctionName of telefunctionNames) {
const typeAlias = shieldStrSource.getTypeAlias(`${telefunctionName}Shield`)
assert(typeAlias, `Failed to get typeAlias '${telefunctionName}Shield'.`)
const shieldStr = typeAlias.getType().getLiteralValue()
if (!shieldStr || typeof shieldStr !== 'string') {
assertWarning(false, `Failed to generate shield() for telefunction ${telefunctionName}()`, { onlyOnce: false })
continue
}
const shieldStrWithAlias = replaceShieldTypeAlias(shieldStr)
telefuncFileSource.addStatements(`${shieldAlias}(${telefunctionName}, ${shieldStrWithAlias}, { __autoGenerated: true })`)
}
return telefuncFileSource.getText()
}
Example #26
Source File: cache.handler.ts From cli with MIT License | 5 votes |
async function cacheHandlerCore(
{ cwd: projectDirPath }: ICoreInstance,
opts: CacheOptions
) {
consola.info(`Project location: ${chalk.green(projectDirPath)}`);
const { dry } = applyDefaultValueToSharedOption(opts);
const { namespace = 'cache' } = opts;
if (dry) {
consola.success('Executing in `dry run` mode, nothing will happen.');
}
dry
? consola.info('`[DryRun]` Skip `dependencies` installation check.')
: await ensureDepsInstalled(CACHE_DEP, projectDirPath);
dry
? consola.info('`[DryRun]` Skip `devDependencies` installation check.')
: await ensureDevDepsInstalled(CACHE_DEV_DEP, projectDirPath);
if (!dry) {
consola.info('Source code will be transformed.');
const project = new Project();
const configurationPath = path.resolve(
projectDirPath,
'./src/configuration.ts'
);
if (!fs.existsSync(configurationPath)) {
consola.error(
`Cannot find ${chalk.cyan('configuration.ts')} in ${chalk.green(
configurationPath
)}.`
);
process.exit(0);
}
const configurationSource = project.addSourceFileAtPath(configurationPath);
addImportDeclaration(
configurationSource,
namespace,
'@midwayjs/cache',
ImportType.NAMESPACE_IMPORT
);
updateDecoratorArrayArgs(
configurationSource,
'Configuration',
'imports',
namespace
);
formatTSFile(configurationPath);
} else {
consola.info('`[DryRun]` Source code will be transformed.');
}
}
Example #27
Source File: axios.handler.ts From cli with MIT License | 5 votes |
async function axiosHandlerCore(
{ cwd: projectDirPath }: ICoreInstance,
opts: AxiosOptions
) {
consola.info(`Project location: ${chalk.green(projectDirPath)}`);
const { dry } = applyDefaultValueToSharedOption(opts);
const { namespace = 'axios' } = opts;
if (dry) {
consola.success('Executing in `dry run` mode, nothing will happen.');
}
dry
? consola.info('`[DryRun]` Skip `dependencies` installation check.')
: await ensureDepsInstalled(AXIOS_DEP, projectDirPath);
if (!dry) {
consola.info('Source code will be transformed.');
const project = new Project();
const configurationPath = path.resolve(
projectDirPath,
'./src/configuration.ts'
);
if (!fs.existsSync(configurationPath)) {
consola.error(
`Cannot find ${chalk.cyan('configuration.ts')} in ${chalk.green(
configurationPath
)}.`
);
process.exit(0);
}
const configurationSource = project.addSourceFileAtPath(configurationPath);
addImportDeclaration(
configurationSource,
namespace,
'@midwayjs/axios',
ImportType.NAMESPACE_IMPORT
);
updateDecoratorArrayArgs(
configurationSource,
'Configuration',
'imports',
namespace
);
formatTSFile(configurationPath);
} else {
consola.info('`[DryRun]` Source code will be transformed.');
}
}
Example #28
Source File: index.ts From tarojs-router-next with MIT License | 5 votes |
/** 解析 route.config.ts 导出的 Params、Data、Ext */
parseSourceFile(options: { page: Page; project: Project; sourceFile: SourceFile }) {
const { page, project, sourceFile } = options
const checker = project.getTypeChecker()
const pageQuery: {
params?: QueryMeta
data?: QueryMeta
ext?: string
} = {}
sourceFile.getExportedDeclarations().forEach((declarations, name) => {
if (declarations.length > 1) return
const declaration = declarations[0] as any
switch (name) {
case 'Params':
pageQuery.params = extractType({
name,
declaration,
checker,
})
break
case 'Data':
pageQuery.data = extractType({
name,
declaration,
checker,
})
break
case 'Ext':
pageQuery.ext = extractValue({
name,
declaration,
checker,
})
break
}
})
page.query = pageQuery
return page
}
Example #29
Source File: index.ts From tarojs-router-next with MIT License | 5 votes |
/** 读取传入包的所有 route.config.ts 配置文件 */
readConfigSourceFiles(options: { pkg: PackageConfig; project: Project }) {
const { project } = options
const { fullPagesPath } = options.pkg
project.addSourceFilesAtPaths(fullPagesPath + '/**/route.config.ts')
project.resolveSourceFileDependencies()
return project.getSourceFiles().filter((it) => it.compilerNode.fileName.endsWith('route.config.ts'))
}