diff --git a/generator/generators/aliyun/generator.ts b/generator/generators/aliyun/generator.ts new file mode 100644 index 00000000..d87ef857 --- /dev/null +++ b/generator/generators/aliyun/generator.ts @@ -0,0 +1,21 @@ +import { ClassData, extractSDKData, getAST } from '../../parsers/aliyun/parser'; + +export const generateAliyunClass = ( + serviceClass: unknown, + serviceName: string +) => { + const sdkfile = serviceClass[Object.keys(serviceClass)[0]]; + getAST(sdkfile) + .then(async result => { + const sdkClassAst = result; + try { + const classData: ClassData = extractSDKData(sdkClassAst, serviceClass); + classData.serviceName = serviceName; + } catch (err) { + console.error('Error : ', err); + } + }) + .catch(error => { + console.error('Error : ', error); + }); +}; diff --git a/generator/main.ts b/generator/main.ts index 5c567bcb..d8d00e21 100644 --- a/generator/main.ts +++ b/generator/main.ts @@ -1,6 +1,7 @@ import * as fs from 'fs'; import * as yaml from 'js-yaml'; +import { generateAliyunClass } from './generators/aliyun/generator'; import { generateAWSClass } from './generators/aws/generator'; import { generateAzureClass } from './generators/azure/generator'; import { generateDOClass } from './generators/do/generator'; @@ -18,6 +19,8 @@ try { generateGCPClass(services[service][provider], service); } else if (provider == 'DO') { generateDOClass(services[service][provider], service); + } else if (provider === 'Ali') { + generateAliyunClass(services[service][provider], service); } }); }); diff --git a/generator/node-cloud.yml b/generator/node-cloud.yml index 88d97d24..14202b60 100644 --- a/generator/node-cloud.yml +++ b/generator/node-cloud.yml @@ -43,6 +43,14 @@ StorageBucket: list: storage storage.d.ts getBuckets upload: storage bucket.d.ts upload makePublic: storage file.d.ts makePublic + Ali: + setRegion: oss index.d.ts setRegion + create: oss index.d.ts create + listBuckets: oss index.d.ts listBuckets + delete: oss index.d.ts delete + describeBucket: oss index.d.ts describeBucket + listBucketObjects: oss index.d.ts listBucketObjects + uploadLocalObject: oss index.d.ts uploadLocalObject PaaS: AWS: diff --git a/generator/package.json b/generator/package.json index bc3fca71..ed88d30e 100644 --- a/generator/package.json +++ b/generator/package.json @@ -31,6 +31,7 @@ "@google-cloud/pubsub": "^2.1.0", "@google-cloud/storage": "^5.1.1", "@google-cloud/translate": "^6.0.0", + "aliyun-v2-typescript-sdk": "^0.1.1", "aws-sdk": "^2.686.0", "config": "^1.26.1", "do-wrapper": "^4.5.1", diff --git a/generator/parsers/aliyun/parser.ts b/generator/parsers/aliyun/parser.ts new file mode 100644 index 00000000..145bfc64 --- /dev/null +++ b/generator/parsers/aliyun/parser.ts @@ -0,0 +1,114 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import { createSourceFile, ScriptTarget, SyntaxKind } from 'typescript'; + +export const getAST = (sdkFilePath: string) => { + return new Promise(async (resolve, reject) => { + const [module, rootFile, service] = sdkFilePath.split(' '); + try { + const file = path.join( + __dirname, + '../../../node_modules/aliyun-v2-typescript-sdk/dist/modules/', + module.toLowerCase(), + rootFile + ); + + const ast = createSourceFile( + file, + fs.readFileSync(file).toString(), + ScriptTarget.Latest, + true + ); + + let cloned = null; + + await ast.forEachChild(child => { + if (SyntaxKind[child.kind] === 'ClassDeclaration') { + cloned = Object.assign({}, child); + } + }); + + if (!cloned) { + reject(new Error('Class not found!')); + } else { + resolve(cloned); + } + } catch (error) { + if (error.code === 'ENOENT') { + reject(new Error('File not found!')); + } else { + reject(error); + } + } + }); +}; + +export const extractSDKData = (sdkClassAst, serviceClass): ClassData => { + const methods: FunctionData[] = []; + const functions = []; + + Object.keys(serviceClass).forEach((key: string) => { + functions.push(serviceClass[key].split(' ')[2]); + }); + + sdkClassAst.members.forEach(method => { + if (method.name && functions.includes(method.name.text)) { + let name; + Object.keys(serviceClass).forEach((key: string) => { + if (serviceClass[key].split(' ')[2] === method.name.text) { + name = key; + } + }); + + const parameters = []; + method.parameters.forEach(param => { + if (param.name.text !== 'callback') { + const parameter = { + name: param.name.text, + optional: param.questionToken ? true : false, + type: SyntaxKind[param.type.kind], + typeName: null, + }; + + if (parameter.type === 'TypeReference' && param.type.typeName) { + parameter.typeName = param.type.typeName.text; + } + + parameters.push(parameter); + } + }); + + methods.push({ + functionName: name.toString(), + SDKFunctionName: method.name.text.toString(), + params: parameters, + }); + } + }); + + const classData: ClassData = { + className: sdkClassAst.name.text, + functions: methods, + serviceName: null, + }; + + return classData; +}; + +export interface ClassData { + className: string; + functions: FunctionData[]; + serviceName: string; +} + +interface FunctionData { + functionName: string; + SDKFunctionName: string; + params: param[]; +} + +interface param { + name: string; + type: string; + typeName: string; +} diff --git a/generator/test/parsers/aliyun/parser.test.ts b/generator/test/parsers/aliyun/parser.test.ts new file mode 100644 index 00000000..7379815b --- /dev/null +++ b/generator/test/parsers/aliyun/parser.test.ts @@ -0,0 +1,26 @@ +import { expect } from 'chai'; +import { SyntaxKind } from 'typescript'; + +import { getAST } from '../../../parsers/aliyun/parser'; + +describe('Aliyun getAST Implementation', () => { + const sdkFilePath = 'oss index.d.ts setRegion'; + const invalidPath = 'oss unknown.d.ts setRegion'; + context('With existing file', () => { + it('Should return Abstract syntax tree of the class', async () => { + const ast: any = await getAST(sdkFilePath); + expect(ast).to.be.an('object'); + expect(SyntaxKind[ast.kind] === 'ClassDeclaration').to.be.true; + }); + }); + + context('With non-existing file', () => { + it('should return File not found Error', async () => { + try { + await getAST(invalidPath); + } catch (error) { + expect(error.message).to.eql('File not found!'); + } + }); + }); +});