158 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
			
		
		
	
	
			158 lines
		
	
	
		
			4.5 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 path from 'path';
 | |
| 
 | |
| import {
 | |
|   Project,
 | |
|   SyntaxKind,
 | |
|   PropertyAssignment,
 | |
|   ShorthandPropertyAssignment,
 | |
|   SpreadAssignment,
 | |
|   VariableDeclarationKind,
 | |
|   TypeFormatFlags,
 | |
|   type VariableDeclarationStructure,
 | |
|   type OptionalKind,
 | |
| } from 'ts-morph';
 | |
| 
 | |
| interface TUpdateDTSParams {
 | |
|   inputFileName: string;
 | |
|   envVarName: string;
 | |
|   outputFileName: string;
 | |
| }
 | |
| 
 | |
| const updateDTS = ({
 | |
|   inputFileName,
 | |
|   envVarName,
 | |
|   outputFileName,
 | |
| }: TUpdateDTSParams) => {
 | |
|   // Initialize a ts-morph project
 | |
|   const project = new Project({
 | |
|     compilerOptions: {
 | |
|       incremental: true,
 | |
|       allowJs: false,
 | |
|       skipLibCheck: true,
 | |
|       strictNullChecks: true,
 | |
|       noEmitOnError: true,
 | |
|     },
 | |
|   });
 | |
|   // Add the file you want to parse
 | |
|   const file = project.addSourceFileAtPath(inputFileName);
 | |
| 
 | |
|   // Get the variable you want to parse
 | |
|   const envs = file.getVariableDeclarationOrThrow(envVarName);
 | |
|   // Get the initial value of the envs variable
 | |
|   const initializer = envs.getInitializerIfKindOrThrow(
 | |
|     SyntaxKind.ObjectLiteralExpression,
 | |
|   );
 | |
|   // Get the properties of the envs object
 | |
|   const properties = initializer.getProperties();
 | |
| 
 | |
|   const baseDir = path.resolve(__dirname, '../');
 | |
|   // Create a new file to hold the generated type definition
 | |
|   const typeDefs = project.createSourceFile(
 | |
|     outputFileName,
 | |
|     `/*
 | |
|  * 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.
 | |
|  */
 | |
| /* eslint-disable */
 | |
| /* prettier-ignore */
 | |
| // Automatically generated based on ${path.relative(
 | |
|       baseDir,
 | |
|       inputFileName,
 | |
|     )}, do not modify manually `,
 | |
|     {
 | |
|       overwrite: true,
 | |
|     },
 | |
|   );
 | |
| 
 | |
|   const declarations: OptionalKind<VariableDeclarationStructure>[] = [];
 | |
| 
 | |
|   const addDeclaration = (name: string, type: string) => {
 | |
|     declarations.push({
 | |
|       name,
 | |
|       type,
 | |
|     });
 | |
|   };
 | |
| 
 | |
|   // Iterate through each attribute
 | |
|   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()) {
 | |
|         // If the type is an object type, obtain its properties
 | |
|         const spreadProperties = type.getProperties();
 | |
|         // traversal properties
 | |
|         for (const spreadProperty of spreadProperties) {
 | |
|           const declaration = spreadProperty.getDeclarations()?.[0];
 | |
|           if (declaration) {
 | |
|             addDeclaration(
 | |
|               spreadProperty.getName(),
 | |
|               declaration
 | |
|                 .getType()
 | |
|                 .getText(
 | |
|                   undefined,
 | |
|                   TypeFormatFlags.UseSingleQuotesForStringLiteralType,
 | |
|                 ),
 | |
|             );
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   });
 | |
|   // Save file
 | |
|   typeDefs.addVariableStatements(
 | |
|     declarations
 | |
|       .sort((a, b) => (a.name > b.name ? 1 : -1))
 | |
|       .map(d => ({
 | |
|         declarationKind: VariableDeclarationKind.Const,
 | |
|         hasDeclareKeyword: true,
 | |
|         declarations: [d],
 | |
|       })),
 | |
|   );
 | |
|   typeDefs.saveSync();
 | |
| };
 | |
| 
 | |
| export const build = () => {
 | |
|   const start = Date.now();
 | |
|   const root = path.resolve(__dirname, '../src');
 | |
|   updateDTS({
 | |
|     inputFileName: path.resolve(root, 'index.ts'),
 | |
|     envVarName: 'envs',
 | |
|     outputFileName: path.resolve(root, 'typings.d.ts'),
 | |
|   });
 | |
|   console.info(`DTS generated in  ${Date.now() - start} ms`);
 | |
| };
 |