Skip to content

Commit 99e45b7

Browse files
committed
add create
1 parent c478530 commit 99e45b7

16 files changed

+191
-291
lines changed

.eslintrc.yml

+2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
root: true
22
extends: dwing
3+
rules:
4+
no-bitwise: 0

.npmignore

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
node_modules/
22
demo/
3-
temp/
43
.nyc_output/
54

65
.DS_Store

bin/scf.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ const list = require('cli-list');
33
const minimist = require('minimist');
44
const endpoint = require('../src');
55

6-
const [{ _: cmd = [], ...args }] = list(process.argv.slice(2)).map(item => minimist(item));
6+
const [{ _: cmd = [] }] = list(process.argv.slice(2)).map(item => minimist(item));
77

8-
endpoint(cmd, args);
8+
endpoint(cmd);

src/create.js

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
const inquirer = require('inquirer');
2+
const chalk = require('chalk');
3+
const fse = require('fs-extra');
4+
const path = require('path');
5+
const SDK = require('./lib/sdk');
6+
const pack = require('./lib/pack');
7+
const { input, envEditor } = require('./lib/prompt');
8+
9+
module.exports = async (fn = '') => {
10+
const FunctionName = fn || await input();
11+
const prompts = await inquirer.prompt([
12+
{
13+
type: 'input',
14+
name: 'MemorySize',
15+
message: '函数运行时内存大小, 以 128MB 为阶梯',
16+
default: 128,
17+
validate: v => ((~~v >= 128 && ~~v <= 1536 && ~~v % 128 === 0) ? true : '可选范围 128MB-1536MB,并且以 128MB 为阶梯')
18+
},
19+
{
20+
type: 'input',
21+
name: 'Timeout',
22+
message: '函数最长执行时间, 单位为秒',
23+
default: 3,
24+
validate: v => ((~~v >= 1 && ~~v <= 300) ? true : '可选值范围 1-300 秒')
25+
}
26+
]);
27+
const env = await envEditor();
28+
29+
const zip = await pack();
30+
31+
const sdk = SDK();
32+
const {
33+
Response: {
34+
Error: {
35+
Message = ''
36+
} = {}
37+
}
38+
} = await sdk.CreateFunction({
39+
FunctionName,
40+
'Code.ZipFile': zip,
41+
Handler: 'index.main_handler',
42+
...prompts,
43+
...env,
44+
Runtime: 'Nodejs8.9'
45+
});
46+
if (Message === '') {
47+
// eslint-disable-next-line no-console
48+
console.log(chalk`{green.bold 创建成功!}`);
49+
fse.copySync(path.join(__dirname, '../template'), `./${FunctionName}`);
50+
} else {
51+
// eslint-disable-next-line no-console
52+
console.log(chalk`{red.bold 创建失败:} ${Message}`);
53+
}
54+
};

src/delete.js

+13-7
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
const fs = require('fs-extra');
22
const chalk = require('chalk');
3-
const select = require('./lib/select');
3+
const { select } = require('./lib/prompt');
44
const SDK = require('./lib/sdk');
55

6-
module.exports = async (functionName = '') => {
7-
const fn = functionName || await select();
6+
module.exports = async (fn = '') => {
7+
const FunctionName = fn || await select();
88
const sdk = SDK();
9-
const { codeDesc = '', message = '' } = await sdk.DeleteFunction({
10-
functionName: fn
9+
const {
10+
Response: {
11+
Error: {
12+
Message = ''
13+
} = {}
14+
}
15+
} = await sdk.DeleteFunction({
16+
FunctionName
1117
});
12-
if (codeDesc === 'Success') {
18+
if (Message === '') {
1319
// eslint-disable-next-line no-console
1420
console.log(chalk`{green.bold 删除成功!}`);
1521
} else {
1622
// eslint-disable-next-line no-console
17-
console.log(chalk`{red.bold 删除失败:} ${message}`);
23+
console.log(chalk`{red.bold 删除失败:} ${Message}`);
1824
}
1925
fs.removeSync(fn);
2026
};

src/index.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
const main = require('./main');
22
const login = require('./login');
3+
const create = require('./create');
34
const deleter = require('./delete');
45
const list = require('./list');
56
const help = require('./help');
67

78
const cmds = {
89
main,
10+
create,
911
delete: deleter,
1012
list,
1113
help,
@@ -22,4 +24,4 @@ const call = new Proxy({}, {
2224
}
2325
});
2426

25-
module.exports = ([cmd = 'main', functionName = ''] = [], args = {}) => call[cmd](functionName, args);
27+
module.exports = ([cmd = 'main', functionName = ''] = []) => call[cmd](functionName);

src/lib/common.js

Whitespace-only changes.

src/lib/pack.js

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
const archiver = require('archiver');
4+
5+
const getDefer = () => {
6+
const deferred = {};
7+
deferred.promise = new Promise((resolve, reject) => {
8+
deferred.resolve = resolve;
9+
deferred.reject = reject;
10+
});
11+
return deferred;
12+
};
13+
14+
module.exports = (fn = 'template') => {
15+
const deferred = getDefer();
16+
const filepath = path.join(__dirname, `../../temp/${fn}.zip`);
17+
const output = fs.createWriteStream(filepath);
18+
const archive = archiver('zip', {
19+
zlib: { level: 9 }
20+
});
21+
archive.on('warning', (err) => {
22+
if (err.code === 'ENOENT') {
23+
// log warning
24+
} else {
25+
deferred.reject(err);
26+
}
27+
});
28+
archive.on('error', (err) => {
29+
deferred.reject(err);
30+
});
31+
archive.pipe(output);
32+
archive.directory(fn === 'templage' ? path.join(__dirname, '../template/') : `./${fn}`, false);
33+
archive.finalize();
34+
output.on('close', () => {
35+
deferred.resolve(
36+
fs.readFileSync(filepath, 'base64')
37+
);
38+
});
39+
return deferred.promise;
40+
};

src/lib/prompt.js

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
const inquirer = require('inquirer');
2+
const fs = require('fs');
3+
4+
exports.select = () => {
5+
const files = fs.readdirSync('.', { withFileTypes: true });
6+
const dirs = files.filter(x => x.isDirectory() && !x.name.startsWith('.') && x.name !== 'node_modules').map(x => x.name);
7+
return inquirer.prompt([{
8+
type: 'list',
9+
name: 'result',
10+
message: '选择本地云函数',
11+
choices: dirs
12+
}]).then(({ result }) => result);
13+
};
14+
15+
exports.input = () => inquirer.prompt([{
16+
type: 'input',
17+
name: 'result',
18+
message: '输入云函数名称',
19+
validate: v => (/^[a-zA-Z][\w-]{0,58}[a-zA-Z0-9]$/.test(v) ? true : '函数名称支持26个英文字母大小写、数字、连接符和下划线,第一个字符只能以字母开头,最后一个字符不能为连接符或者下划线,名称长度2-60')
20+
}]).then(({ result }) => result);
21+
22+
exports.envEditor = () => inquirer.prompt([
23+
{
24+
type: 'confirm',
25+
name: 'confirm',
26+
message: '是否要设置环境变量?',
27+
default: false
28+
},
29+
{
30+
type: 'editor',
31+
name: 'env',
32+
message: '环境变量,请每行输入一个,参考格式`NODE_ENV=produection`',
33+
defaut: '',
34+
when: answers => answers.confirm
35+
}
36+
]).then(({ env = '' }) => {
37+
const envArr = env.split(/\s*\n\s*/).reduce((r, i) => {
38+
const [, key = '', val = ''] = i.match(/(\w+)\s*=\s*(\S+)/) || [];
39+
if (key !== '') {
40+
r.push([key, val]);
41+
}
42+
return r;
43+
}, []);
44+
const obj = {};
45+
envArr.forEach(([key, val], i) => {
46+
obj[`Environment.Variables.${i}.Key`] = key;
47+
if (val !== '') {
48+
obj[`Environment.Variables.${i}.Value`] = val;
49+
}
50+
});
51+
return obj;
52+
});

src/lib/sdk.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const fs = require('fs');
2+
const fse = require('fs-extra');
23
const chalk = require('chalk');
34
const { SCF } = require('wqcloud');
45
const { globalPath, localPath } = require('../config');
@@ -9,6 +10,9 @@ module.exports = () => {
910
console.log(chalk`请先执行 {red.bold csf loign} 进行登录`);
1011
process.exit(0);
1112
}
12-
const config = fs.readFileSync(fs.existsSync(localPath) ? localPath : globalPath, 'utf8');
13-
return SCF(JSON.parse(config));
13+
const config = fse.readJSONSync(fs.existsSync(localPath) ? localPath : globalPath);
14+
return SCF({
15+
...config,
16+
Version: '2018-04-16'
17+
});
1418
};

src/lib/select.js

-13
This file was deleted.

src/list.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@ module.exports = async () => {
77
const getted = [];
88
while (getted.length < allTotal) {
99
const {
10-
data: {
11-
functions,
12-
total = 0
10+
Response: {
11+
Functions = [],
12+
TotalCount = 0
1313
}
1414
// eslint-disable-next-line no-await-in-loop
1515
} = await sdk.ListFunctions({
1616
Limit: 100,
1717
Offset: getted.length
1818
});
19-
allTotal = total;
20-
getted.push(...functions);
19+
allTotal = TotalCount;
20+
getted.push(...Functions);
2121
}
2222
// eslint-disable-next-line no-console
23-
getted.forEach(({ functionName, addTime, modTime }) => console.log(chalk`{magenta.bold ${functionName}} (修改时间: ${modTime} | 添加时间:${addTime})`));
23+
getted.forEach(({ FunctionName, AddTime, ModTime }) => console.log(chalk`{magenta.bold ${FunctionName}} (修改时间: ${ModTime} | 添加时间:${AddTime})`));
2424
};

src/main.js

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const inquirer = require('inquirer');
22
const login = require('./login');
3+
const create = require('./create');
34
const deleter = require('./delete');
45
const list = require('./list');
56
const help = require('./help');
@@ -20,7 +21,7 @@ const choices = [
2021
new inquirer.Separator()
2122
];
2223

23-
module.exports = async (_, args) => {
24+
module.exports = async () => {
2425
const { cmd = 'help' } = await inquirer.prompt([
2526
{
2627
type: 'list',
@@ -31,15 +32,19 @@ module.exports = async (_, args) => {
3132
]);
3233
switch (choices.findIndex(x => x === cmd)) {
3334
case 0: {
34-
login('', args);
35+
login();
36+
break;
37+
}
38+
case 2: {
39+
create();
3540
break;
3641
}
3742
case 3: {
38-
deleter('', args);
43+
deleter('');
3944
break;
4045
}
4146
case 5: {
42-
list('', args);
47+
list();
4348
break;
4449
}
4550
default: {

temp/.gitkeep

Whitespace-only changes.

template/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
"version": "1.0.0",
44
"description": "腾讯云无服务器函数SCF命令行辅助工具",
55
"dependencies": {
6+
"wqcloud": "latest"
67
}
78
}

0 commit comments

Comments
 (0)