/* * Copyright 2025 coze-dev Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { Project, SyntaxKind, PropertyAssignment, ShorthandPropertyAssignment, SpreadAssignment, VariableDeclarationKind, TypeFormatFlags, type VariableDeclarationStructure, type OptionalKind, } from 'ts-morph'; interface TUpdateDTSParams { inputFileName: string; envVarName: string; outputFileName: string; } export const updateDTS = ( { inputFileName, envVarName, outputFileName }: TUpdateDTSParams = { inputFileName: 'env/index.ts', envVarName: 'envs', outputFileName: 'src/typing/env/index.d.ts', }, ) => { const start = Date.now(); // 初始化一个 ts-morph 项目 const project = new Project({ compilerOptions: { incremental: true, allowJs: false, skipLibCheck: true, strictNullChecks: true, noEmitOnError: true, }, }); // 添加想要解析的文件 const file = project.addSourceFileAtPath(inputFileName); // 获取你想要解析的变量 const envs = file.getVariableDeclarationOrThrow(envVarName); // 获取 envs 变量的初始值 const initializer = envs.getInitializerIfKindOrThrow( SyntaxKind.ObjectLiteralExpression, ); // 获取 envs 对象的属性 const properties = initializer.getProperties(); // 创建一个新的文件,用来保存生成的类型定义 const typeDefs = project.createSourceFile( outputFileName, `// 基于${inputFileName}自动生成,请勿手动修改`, { overwrite: true, }, ); const declarations: OptionalKind[] = []; const addDeclaration = (name: string, type: string) => { declarations.push({ name, type, }); }; // 遍历每一个属性 properties.forEach(property => { if ( property instanceof PropertyAssignment || property instanceof ShorthandPropertyAssignment ) { addDeclaration(property.getName(), property.getType().getText()); } else if (property instanceof SpreadAssignment) { const expression = property.getExpression(); const type = expression.getType(); if (type.isObject()) { // 如果类型是一个对象类型,获取其属性 const spreadProperties = type.getProperties(); // 遍历属性 for (const spreadProperty of spreadProperties) { const declaration = spreadProperty.getDeclarations()?.[0]; if (declaration) { addDeclaration( spreadProperty.getName(), declaration .getType() .getText( undefined, TypeFormatFlags.UseSingleQuotesForStringLiteralType, ), ); } } } } }); // 保存文件 typeDefs.addVariableStatements( declarations .sort((a, b) => (a.name > b.name ? 1 : -1)) .map(d => ({ declarationKind: VariableDeclarationKind.Const, hasDeclareKeyword: true, declarations: [d], })), ); typeDefs.saveSync(); console.info(`DTS generated in ${Date.now() - start} ms`); };