From 0d172c8f6fbccd893d018a091189f2b44ee2d952 Mon Sep 17 00:00:00 2001 From: Pranjal Walia Date: Wed, 6 Jul 2022 17:16:51 +0530 Subject: [PATCH 1/7] chore: update nodecloud conf --- generator/node-cloud.yml | 8 ++++++++ 1 file changed, 8 insertions(+) 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: From 6e40593a29ad045cccef3a164aa3c83ba359f326 Mon Sep 17 00:00:00 2001 From: Pranjal Walia Date: Wed, 6 Jul 2022 17:18:12 +0530 Subject: [PATCH 2/7] feat: add SDK in workspace generator --- generator/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/generator/package.json b/generator/package.json index 9ac31b84..2f66dccd 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", From 260bd55ce6c833d22650a08b88d804eb29dbbc65 Mon Sep 17 00:00:00 2001 From: Pranjal Walia Date: Wed, 6 Jul 2022 17:19:11 +0530 Subject: [PATCH 3/7] feat: add parser for service aliyun --- generator/parsers/aliyun/parser.ts | 117 +++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 generator/parsers/aliyun/parser.ts diff --git a/generator/parsers/aliyun/parser.ts b/generator/parsers/aliyun/parser.ts new file mode 100644 index 00000000..878cd88e --- /dev/null +++ b/generator/parsers/aliyun/parser.ts @@ -0,0 +1,117 @@ +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; +} \ No newline at end of file From 0e6e998b19a0590c3ec335b182bef843e1b9c61f Mon Sep 17 00:00:00 2001 From: Pranjal Walia Date: Wed, 6 Jul 2022 17:19:54 +0530 Subject: [PATCH 4/7] feat: update parser consumption --- generator/generators/aliyun/generator.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 generator/generators/aliyun/generator.ts diff --git a/generator/generators/aliyun/generator.ts b/generator/generators/aliyun/generator.ts new file mode 100644 index 00000000..79f15166 --- /dev/null +++ b/generator/generators/aliyun/generator.ts @@ -0,0 +1,24 @@ +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); + }); +}; \ No newline at end of file From 83d0048eb81e1656531117951941fe482ecbf518 Mon Sep 17 00:00:00 2001 From: Pranjal Walia Date: Wed, 6 Jul 2022 17:20:21 +0530 Subject: [PATCH 5/7] tests: add tests for the aliyun parser --- generator/test/parsers/aliyun/parser.test.ts | 26 ++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 generator/test/parsers/aliyun/parser.test.ts diff --git a/generator/test/parsers/aliyun/parser.test.ts b/generator/test/parsers/aliyun/parser.test.ts new file mode 100644 index 00000000..771fa901 --- /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!'); + } + }); + }); +}); \ No newline at end of file From 11fa9bcaea1e14f47fd6b12b29f7437fe14a6633 Mon Sep 17 00:00:00 2001 From: Pranjal Walia Date: Wed, 6 Jul 2022 17:20:50 +0530 Subject: [PATCH 6/7] chore: update main file --- generator/main.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/generator/main.ts b/generator/main.ts index 5374718c..719bb434 100644 --- a/generator/main.ts +++ b/generator/main.ts @@ -1,10 +1,11 @@ import * as fs from "fs"; import * as yaml from "js-yaml"; -import { generateAWSClass } from "./generators/aws/generator"; -import { generateAzureClass } from "./generators/azure/generator"; -import { generateDOClass } from "./generators/do/generator"; -import { generateGCPClass } from "./generators/googleCloud/generator"; +import { generateAliyunClass } from './generators/aliyun/generator'; +import { generateAWSClass } from './generators/aws/generator'; +import { generateAzureClass } from './generators/azure/generator'; +import { generateDOClass } from './generators/do/generator'; +import { generateGCPClass } from './generators/googleCloud/generator'; try { const services = yaml.safeLoad(fs.readFileSync("node-cloud.yml", "utf8")); @@ -18,7 +19,9 @@ try { generateGCPClass(services[service][provider], service); } else if (provider == "DO") { generateDOClass(services[service][provider], service); - } + } else if (provider === 'Ali') { + generateAliyunClass(services[service][provider], service); + } }); }); } catch (error) { From 150374c8c858facd000b9bdb4e940f294c5f4cbd Mon Sep 17 00:00:00 2001 From: Pranjal Walia Date: Sun, 17 Jul 2022 01:01:40 +0530 Subject: [PATCH 7/7] chore: run formatter on remaining files --- generator/generators/aliyun/generator.ts | 37 ++-- generator/parsers/aliyun/parser.ts | 197 +++++++++---------- generator/test/parsers/aliyun/parser.test.ts | 38 ++-- 3 files changed, 133 insertions(+), 139 deletions(-) diff --git a/generator/generators/aliyun/generator.ts b/generator/generators/aliyun/generator.ts index 79f15166..d87ef857 100644 --- a/generator/generators/aliyun/generator.ts +++ b/generator/generators/aliyun/generator.ts @@ -1,24 +1,21 @@ import { ClassData, extractSDKData, getAST } from '../../parsers/aliyun/parser'; export const generateAliyunClass = ( - serviceClass: unknown, - serviceName: string + 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); - }); -}; \ No newline at end of file + 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/parsers/aliyun/parser.ts b/generator/parsers/aliyun/parser.ts index 878cd88e..145bfc64 100644 --- a/generator/parsers/aliyun/parser.ts +++ b/generator/parsers/aliyun/parser.ts @@ -3,115 +3,112 @@ 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); - } - } - }); + 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; + 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; + className: string; + functions: FunctionData[]; + serviceName: string; } interface FunctionData { - functionName: string; - SDKFunctionName: string; - params: param[]; + functionName: string; + SDKFunctionName: string; + params: param[]; } interface param { - name: string; - type: string; - typeName: string; -} \ No newline at end of file + name: string; + type: string; + typeName: string; +} diff --git a/generator/test/parsers/aliyun/parser.test.ts b/generator/test/parsers/aliyun/parser.test.ts index 771fa901..7379815b 100644 --- a/generator/test/parsers/aliyun/parser.test.ts +++ b/generator/test/parsers/aliyun/parser.test.ts @@ -4,23 +4,23 @@ 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; - }); - }); + 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!'); - } - }); - }); -}); \ No newline at end of file + 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!'); + } + }); + }); +});