130 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
/*
 | 
						|
 * 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<VariableDeclarationStructure>[] = [];
 | 
						|
 | 
						|
  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`);
 | 
						|
};
 |