@cloudbase/cli 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/tcb.js +62 -33
- package/jest.config.js +2 -2
- package/lib/commands/common.js +13 -2
- package/lib/commands/db/base.js +395 -0
- package/lib/commands/db/index.js +17 -0
- package/lib/commands/index.js +1 -0
- package/lib/commands/lowcode/app.js +154 -1
- package/lib/commands/lowcode/comps.js +1 -1
- package/lib/db/index.js +84 -0
- package/lib/utils/dts.js +153 -0
- package/lib/utils/net/cloud-api-request.js +1 -1
- package/package.json +5 -3
- package/types/commands/common.d.ts +1 -0
- package/types/commands/db/base.d.ts +44 -0
- package/types/commands/db/index.d.ts +1 -0
- package/types/commands/index.d.ts +1 -0
- package/types/commands/lowcode/app.d.ts +26 -0
- package/types/db/index.d.ts +24 -0
- package/types/utils/dts.d.ts +6 -0
package/bin/tcb.js
CHANGED
|
@@ -14,6 +14,7 @@ const { CloudApiService } = require('@cloudbase/cloud-api')
|
|
|
14
14
|
const { getCredentialWithoutCheck } = require('@cloudbase/toolbox')
|
|
15
15
|
const { Confirm } = require('enquirer')
|
|
16
16
|
const execa = require('execa')
|
|
17
|
+
const semver = require('semver')
|
|
17
18
|
|
|
18
19
|
const pkg = require('../package.json')
|
|
19
20
|
const store = require('../lib/utils/store')
|
|
@@ -22,15 +23,14 @@ const { getProxy } = require('../lib/utils/net')
|
|
|
22
23
|
const { getCloudBaseConfig, getPrivateSettings } = require('../lib/utils/config')
|
|
23
24
|
const { registerCommands } = require('../lib')
|
|
24
25
|
|
|
25
|
-
|
|
26
26
|
const regionSupported = ['ap-shanghai', 'ap-beijing', 'ap-guangzhou']
|
|
27
27
|
const regionSupportedMap = {
|
|
28
28
|
'ap-shanghai': '上海',
|
|
29
29
|
'ap-beijing': '北京',
|
|
30
30
|
'ap-guangzhou': '广州',
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
sh: '上海',
|
|
32
|
+
bj: '北京',
|
|
33
|
+
gz: '广州'
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
async function main() {
|
|
@@ -38,13 +38,36 @@ async function main() {
|
|
|
38
38
|
const isBeta = pkg.version.indexOf('-') > -1
|
|
39
39
|
process.CLI_VERSION = pkg.version
|
|
40
40
|
|
|
41
|
-
const
|
|
41
|
+
const currentMajorVersion = +semver.major(process.version)
|
|
42
|
+
|
|
43
|
+
// 定义最小版本和推荐版本
|
|
44
|
+
const NODE_MIN_VERSION = 14
|
|
45
|
+
const NODE_RECOMMENDED_VERSIONS = [16, 18]
|
|
42
46
|
|
|
43
|
-
//
|
|
44
|
-
if (
|
|
45
|
-
console.
|
|
47
|
+
// 检查当前版本是否满足最小版本要求
|
|
48
|
+
if (NODE_MIN_VERSION > currentMajorVersion) {
|
|
49
|
+
console.error(
|
|
46
50
|
chalk.bold.red(
|
|
47
|
-
|
|
51
|
+
`当前 Node.js 版本为 v${currentMajorVersion}。请升级到至少 v${NODE_MIN_VERSION} 版本。`
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
console.warn(
|
|
55
|
+
chalk.bold.yellow(
|
|
56
|
+
`建议使用 ${NODE_RECOMMENDED_VERSIONS.map((item) => `v${item}`).join(
|
|
57
|
+
' 或 '
|
|
58
|
+
)} 版本。`
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
process.exit(1)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 检查当前版本是否在推荐版本列表中
|
|
65
|
+
if (!NODE_RECOMMENDED_VERSIONS.some((version) => currentMajorVersion === version)) {
|
|
66
|
+
console.warn(
|
|
67
|
+
chalk.bold.yellow(
|
|
68
|
+
`当前 Node.js 版本为 v${currentMajorVersion}。建议使用 ${NODE_RECOMMENDED_VERSIONS.map(
|
|
69
|
+
(item) => `v${item}`
|
|
70
|
+
).join(' 或 ')} 版本。`
|
|
48
71
|
)
|
|
49
72
|
)
|
|
50
73
|
}
|
|
@@ -67,17 +90,15 @@ async function main() {
|
|
|
67
90
|
console.log(chalk.gray(`CloudBase Framework ${frameworkPkg.version}`))
|
|
68
91
|
console.log(chalk.gray(`Weda ${wedaPkg.version}`))
|
|
69
92
|
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
const privateSettings = getPrivateSettings(config);
|
|
93
|
+
const yargsParsedResult = yargsParser(process.argv.slice(2))
|
|
94
|
+
const config = await getCloudBaseConfig(yargsParsedResult.configFile)
|
|
95
|
+
const privateSettings = getPrivateSettings(config)
|
|
74
96
|
if (privateSettings) {
|
|
75
97
|
console.log(chalk.gray(`检测到私有化配置`))
|
|
76
98
|
if (privateSettings.endpoints && privateSettings.endpoints.cliApi) {
|
|
77
99
|
// 初始化 lowcode 服务cliapi入口
|
|
78
|
-
process.env.CLOUDBASE_LOWCODE_CLOUDAPI_URL = privateSettings.endpoints.cliApi
|
|
100
|
+
process.env.CLOUDBASE_LOWCODE_CLOUDAPI_URL = privateSettings.endpoints.cliApi
|
|
79
101
|
}
|
|
80
|
-
|
|
81
102
|
}
|
|
82
103
|
// 注册命令
|
|
83
104
|
await registerCommands()
|
|
@@ -106,7 +127,7 @@ async function main() {
|
|
|
106
127
|
// HACK: 隐藏自动生成的 help 信息
|
|
107
128
|
program.helpOption(false)
|
|
108
129
|
}
|
|
109
|
-
const isCommandEmpty = yargsParsedResult._.length === 0
|
|
130
|
+
const isCommandEmpty = yargsParsedResult._.length === 0
|
|
110
131
|
|
|
111
132
|
// -v 时输出的版本信息,设置时避免影响其他命令使用 -v
|
|
112
133
|
if (isCommandEmpty) {
|
|
@@ -161,7 +182,9 @@ async function main() {
|
|
|
161
182
|
try {
|
|
162
183
|
program.parse(processArgv)
|
|
163
184
|
} catch (e) {
|
|
164
|
-
const errMsg = `${logSymbols.error} ${
|
|
185
|
+
const errMsg = `${logSymbols.error} ${
|
|
186
|
+
e.message || '参数异常,请检查您是否使用了正确的命令!'
|
|
187
|
+
}`
|
|
165
188
|
console.log(errMsg)
|
|
166
189
|
}
|
|
167
190
|
|
|
@@ -185,11 +208,13 @@ async function main() {
|
|
|
185
208
|
// 多地域错误提示
|
|
186
209
|
if (errMsg.includes('Environment') && errMsg.includes('not found')) {
|
|
187
210
|
// 检查是否已经指定了 -r 或 --region 参数,如未指定则尝试获取地域信息
|
|
188
|
-
const regionSpecified =
|
|
211
|
+
const regionSpecified =
|
|
212
|
+
processArgv.indexOf('-r') !== -1 || processArgv.indexOf('--region') !== -1
|
|
189
213
|
const region = yargsParsedResult.r || yargsParsedResult.region
|
|
190
|
-
const multiRegionErrMsg = `\n此环境可能不属于当前账号,或为非${
|
|
214
|
+
const multiRegionErrMsg = `\n此环境可能不属于当前账号,或为非${
|
|
215
|
+
regionSupportedMap[region] || '上海'
|
|
216
|
+
}地域环境,如需切换地域请追加参数(例:-r gz),请检查环境归属,参考多地域使用方法:https://docs.cloudbase.net/cli-v1/region.html`
|
|
191
217
|
if (!regionSpecified) {
|
|
192
|
-
|
|
193
218
|
// 从 -e 参数、--envId 参数和配置文件中获取环境 id
|
|
194
219
|
const envId = yargsParsedResult.e || yargsParsedResult.envId || config.envId
|
|
195
220
|
|
|
@@ -215,7 +240,9 @@ async function main() {
|
|
|
215
240
|
}
|
|
216
241
|
// 重新执行命令
|
|
217
242
|
const newArgvStr = processArgv.slice(2).join(' ')
|
|
218
|
-
console.log(
|
|
243
|
+
console.log(
|
|
244
|
+
`\n${chalk.yellow.bold('正在重新执行命令:')} tcb ${newArgvStr}\n`
|
|
245
|
+
)
|
|
219
246
|
await execa('tcb', processArgv.slice(2), {
|
|
220
247
|
stdio: 'inherit'
|
|
221
248
|
})
|
|
@@ -243,20 +270,23 @@ async function main() {
|
|
|
243
270
|
}
|
|
244
271
|
|
|
245
272
|
const isTokenExpired = (credential, gap = 120) =>
|
|
246
|
-
credential.accessTokenExpired &&
|
|
273
|
+
credential.accessTokenExpired &&
|
|
274
|
+
Number(credential.accessTokenExpired) < Date.now() + gap * 1000
|
|
247
275
|
|
|
248
276
|
async function tryTellEnvRegion(envId) {
|
|
249
277
|
// 依次调用不同地域的 API 接口查询环境信息
|
|
250
|
-
const fetchedRegion = await Promise.all(
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
278
|
+
const fetchedRegion = await Promise.all(
|
|
279
|
+
regionSupported.map(async (region) => {
|
|
280
|
+
const { EnvList = [] } = await fetchEnvInfoWithRegion(envId, region)
|
|
281
|
+
if (EnvList.length !== 0 && EnvList.find((item) => item.EnvId === envId)) {
|
|
282
|
+
return res.EnvList[0].Region
|
|
283
|
+
}
|
|
284
|
+
return ''
|
|
285
|
+
})
|
|
286
|
+
)
|
|
257
287
|
|
|
258
288
|
let predictRegion = ''
|
|
259
|
-
fetchedRegion.forEach(region => {
|
|
289
|
+
fetchedRegion.forEach((region) => {
|
|
260
290
|
if (region) {
|
|
261
291
|
predictRegion = region
|
|
262
292
|
}
|
|
@@ -293,7 +323,7 @@ async function main() {
|
|
|
293
323
|
region
|
|
294
324
|
})
|
|
295
325
|
const res = await tcbApi.request(apiName, {
|
|
296
|
-
EnvId: envId
|
|
326
|
+
EnvId: envId
|
|
297
327
|
})
|
|
298
328
|
return res
|
|
299
329
|
}
|
|
@@ -316,7 +346,6 @@ async function main() {
|
|
|
316
346
|
notifier.notify({
|
|
317
347
|
isGlobal: true
|
|
318
348
|
})
|
|
319
|
-
|
|
320
349
|
}
|
|
321
350
|
|
|
322
351
|
if (require.main === module) {
|
|
@@ -330,4 +359,4 @@ process.on('unhandledRejection', (err) => {
|
|
|
330
359
|
console.log('unhandledRejection', err)
|
|
331
360
|
})
|
|
332
361
|
|
|
333
|
-
exports.main = main
|
|
362
|
+
exports.main = main
|
package/jest.config.js
CHANGED
|
@@ -2,7 +2,7 @@ module.exports = {
|
|
|
2
2
|
roots: ['<rootDir>/test'],
|
|
3
3
|
globals: {
|
|
4
4
|
'ts-jest': {
|
|
5
|
-
|
|
5
|
+
tsconfig: 'tsconfig.test.json'
|
|
6
6
|
}
|
|
7
7
|
},
|
|
8
8
|
transform: {
|
|
@@ -11,7 +11,7 @@ module.exports = {
|
|
|
11
11
|
transformIgnorePatterns: ['node_modules'],
|
|
12
12
|
testEnvironment: 'node',
|
|
13
13
|
// https://github.com/facebook/jest/issues/5164
|
|
14
|
-
globalSetup: './test/global-setup-hook.js',
|
|
14
|
+
// globalSetup: './test/global-setup-hook.js',
|
|
15
15
|
// globalTeardown: './test/global-teardown-hook.js',
|
|
16
16
|
coverageReporters: ['json', 'lcov', 'clover', 'text-summary']
|
|
17
17
|
}
|
package/lib/commands/common.js
CHANGED
|
@@ -42,7 +42,9 @@ const events_1 = require("events");
|
|
|
42
42
|
const commander_1 = require("commander");
|
|
43
43
|
const yargs_parser_1 = __importDefault(require("yargs-parser"));
|
|
44
44
|
const error_1 = require("../error");
|
|
45
|
+
const toolbox_1 = require("@cloudbase/toolbox");
|
|
45
46
|
const utils_1 = require("../utils");
|
|
47
|
+
const auth_1 = require("../auth");
|
|
46
48
|
const registrableCommands = [];
|
|
47
49
|
const cmdMap = new Map();
|
|
48
50
|
const defaultCmdDecoratorOpts = {
|
|
@@ -134,7 +136,7 @@ class Command extends events_1.EventEmitter {
|
|
|
134
136
|
}
|
|
135
137
|
}
|
|
136
138
|
createProgram(instance, deprecate, newCmd) {
|
|
137
|
-
const { cmd, desc, options, requiredEnvId = true, withoutAuth = false } = this.options;
|
|
139
|
+
const { cmd, desc, options, requiredEnvId = true, withoutAuth = false, autoRunLogin = false } = this.options;
|
|
138
140
|
instance.storeOptionsAsProperties(false);
|
|
139
141
|
options.forEach((option) => {
|
|
140
142
|
const { hideHelp } = option;
|
|
@@ -161,7 +163,16 @@ class Command extends events_1.EventEmitter {
|
|
|
161
163
|
loginState = (yield utils_1.authSupevisor.getLoginState());
|
|
162
164
|
}
|
|
163
165
|
if (!withoutAuth && !loginState) {
|
|
164
|
-
|
|
166
|
+
if (autoRunLogin) {
|
|
167
|
+
console.log(chalk_1.default.bold.yellowBright('无有效身份信息,将自动为您打开授权页面。'));
|
|
168
|
+
yield (0, toolbox_1.execWithLoading)(() => (0, auth_1.login)(), {
|
|
169
|
+
startTip: '请在浏览器中打开的授权页面进行授权...',
|
|
170
|
+
successTip: '授权登录成功!'
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
throw new error_1.CloudBaseError('无有效身份信息,请使用 cloudbase login 登录');
|
|
175
|
+
}
|
|
165
176
|
}
|
|
166
177
|
if (!envId && requiredEnvId) {
|
|
167
178
|
throw new error_1.CloudBaseError('未识别到有效的环境 Id,请使用 cloudbaserc 配置文件进行操作或通过 -e 参数指定环境 Id');
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
15
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
16
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
17
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
18
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
19
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
20
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
24
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
25
|
+
};
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.DbPushCommand = exports.DbPullCommand = exports.DbListCommand = void 0;
|
|
28
|
+
const path_1 = __importDefault(require("path"));
|
|
29
|
+
const common_1 = require("../common");
|
|
30
|
+
const error_1 = require("../../error");
|
|
31
|
+
const lodash_1 = require("lodash");
|
|
32
|
+
const db_1 = require("../../db");
|
|
33
|
+
const env_1 = require("../../env");
|
|
34
|
+
const decorators_1 = require("../../decorators");
|
|
35
|
+
const utils_1 = require("../../utils");
|
|
36
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
37
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
38
|
+
const dts_1 = require("../../utils/dts");
|
|
39
|
+
let DbListCommand = class DbListCommand extends common_1.Command {
|
|
40
|
+
get options() {
|
|
41
|
+
return {
|
|
42
|
+
cmd: 'db',
|
|
43
|
+
childCmd: 'list',
|
|
44
|
+
options: [
|
|
45
|
+
{
|
|
46
|
+
flags: '-e, --envId <envId>',
|
|
47
|
+
desc: '环境 Id'
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
requiredEnvId: false,
|
|
51
|
+
autoRunLogin: true,
|
|
52
|
+
desc: '列出云端所有数据模型',
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
execute(envId, log) {
|
|
56
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
57
|
+
const loading = (0, utils_1.loadingFactory)();
|
|
58
|
+
if (!envId) {
|
|
59
|
+
envId = yield selectEnv();
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
log.info(`当前环境 Id:${envId}`);
|
|
63
|
+
}
|
|
64
|
+
if (!(yield fs_extra_1.default.pathExists('cloudbaserc.json'))) {
|
|
65
|
+
yield fs_extra_1.default.writeFile('cloudbaserc.json', JSON.stringify({
|
|
66
|
+
version: '2.0',
|
|
67
|
+
envId
|
|
68
|
+
}, null, 2), 'utf8');
|
|
69
|
+
}
|
|
70
|
+
loading.start('数据加载中...');
|
|
71
|
+
const data = yield (0, db_1.listModels)({ envId });
|
|
72
|
+
loading.stop();
|
|
73
|
+
const head = ['名称', '标识', '创建时间'];
|
|
74
|
+
const sortData = data.sort((prev, next) => {
|
|
75
|
+
if (prev.Alias > next.Alias) {
|
|
76
|
+
return 1;
|
|
77
|
+
}
|
|
78
|
+
if (prev.Alias < next.Alias) {
|
|
79
|
+
return -1;
|
|
80
|
+
}
|
|
81
|
+
return 0;
|
|
82
|
+
});
|
|
83
|
+
const tableData = sortData.map((item) => [
|
|
84
|
+
item.Title,
|
|
85
|
+
item.Name,
|
|
86
|
+
item.CreatedAt
|
|
87
|
+
]);
|
|
88
|
+
(0, utils_1.printHorizontalTable)(head, tableData);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
__decorate([
|
|
93
|
+
(0, decorators_1.InjectParams)(),
|
|
94
|
+
__param(0, (0, decorators_1.EnvId)()),
|
|
95
|
+
__param(1, (0, decorators_1.Log)()),
|
|
96
|
+
__metadata("design:type", Function),
|
|
97
|
+
__metadata("design:paramtypes", [Object, decorators_1.Logger]),
|
|
98
|
+
__metadata("design:returntype", Promise)
|
|
99
|
+
], DbListCommand.prototype, "execute", null);
|
|
100
|
+
DbListCommand = __decorate([
|
|
101
|
+
(0, common_1.ICommand)()
|
|
102
|
+
], DbListCommand);
|
|
103
|
+
exports.DbListCommand = DbListCommand;
|
|
104
|
+
let DbPullCommand = class DbPullCommand extends common_1.Command {
|
|
105
|
+
get options() {
|
|
106
|
+
return {
|
|
107
|
+
cmd: 'db',
|
|
108
|
+
childCmd: 'pull',
|
|
109
|
+
options: [
|
|
110
|
+
{
|
|
111
|
+
flags: '-e, --envId <envId>',
|
|
112
|
+
desc: '环境 Id'
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
flags: '-d, --dir <dir>',
|
|
116
|
+
desc: '本地存储数据库模型定义的目录,默认为 database-schemas'
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
flags: '-n, --name <name>',
|
|
120
|
+
desc: '要拉取的模型英文标识列表,可指定多个,使用逗号分隔.不指定的情况下默认会拉取所有模型'
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
requiredEnvId: false,
|
|
124
|
+
autoRunLogin: true,
|
|
125
|
+
desc: '从云端拉取多个数据模型到本地',
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
execute(envId, params, log) {
|
|
129
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
130
|
+
if (!(yield fs_extra_1.default.pathExists('tsconfig.json'))) {
|
|
131
|
+
yield fs_extra_1.default.writeFile('tsconfig.json', JSON.stringify({
|
|
132
|
+
compilerOptions: {
|
|
133
|
+
allowJs: true
|
|
134
|
+
}
|
|
135
|
+
}, null, 2), 'utf8');
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
const config = yield fs_extra_1.default.readJson('tsconfig.json', 'utf8');
|
|
139
|
+
(0, lodash_1.set)(config, 'compilerOptions.allowJs', true);
|
|
140
|
+
yield fs_extra_1.default.writeFile('tsconfig.json', JSON.stringify(config, null, 2), 'utf8');
|
|
141
|
+
}
|
|
142
|
+
if (!envId) {
|
|
143
|
+
envId = yield selectEnv();
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
log.info(`当前环境 Id:${envId}`);
|
|
147
|
+
}
|
|
148
|
+
if (!(yield fs_extra_1.default.pathExists('cloudbaserc.json'))) {
|
|
149
|
+
yield fs_extra_1.default.writeFile('cloudbaserc.json', JSON.stringify({
|
|
150
|
+
version: '2.0',
|
|
151
|
+
envId
|
|
152
|
+
}, null, 2), 'utf8');
|
|
153
|
+
}
|
|
154
|
+
let { name = '', dir } = params;
|
|
155
|
+
name = name.split(',').map(item => item.trim()).filter(item => item);
|
|
156
|
+
if (!name.length) {
|
|
157
|
+
name = yield selectModel(envId);
|
|
158
|
+
}
|
|
159
|
+
const data = yield (0, db_1.listModels)({
|
|
160
|
+
envId,
|
|
161
|
+
name
|
|
162
|
+
});
|
|
163
|
+
const dataModelList = data.map((item) => {
|
|
164
|
+
const schema = JSON.parse(item.Schema);
|
|
165
|
+
schema.title = item.Title;
|
|
166
|
+
return {
|
|
167
|
+
name: item.Name,
|
|
168
|
+
schema,
|
|
169
|
+
title: item.Title
|
|
170
|
+
};
|
|
171
|
+
});
|
|
172
|
+
if (!dir) {
|
|
173
|
+
dir = 'database-schemas';
|
|
174
|
+
if (!fs_extra_1.default.existsSync(dir)) {
|
|
175
|
+
fs_extra_1.default.mkdirSync(dir);
|
|
176
|
+
}
|
|
177
|
+
dataModelList.forEach((item) => {
|
|
178
|
+
const fileName = `${dir}/${item.name}.json`;
|
|
179
|
+
fs_extra_1.default.writeFileSync(fileName, JSON.stringify(item.schema, null, 4));
|
|
180
|
+
log.success(`同步数据模型成功。文件名称:${fileName}`);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
const dts = yield (0, dts_1.generateDataModelDTS)(dataModelList);
|
|
184
|
+
const dtsFileName = 'cloud-models.d.ts';
|
|
185
|
+
yield fs_extra_1.default.writeFile(dtsFileName, dts);
|
|
186
|
+
log.success('同步数据模型类型定义文件成功,调用 SDK 时可支持智能字段提示。文件名称:' + dtsFileName);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
__decorate([
|
|
191
|
+
(0, decorators_1.InjectParams)(),
|
|
192
|
+
__param(0, (0, decorators_1.EnvId)()),
|
|
193
|
+
__param(1, (0, decorators_1.ArgsParams)()),
|
|
194
|
+
__param(2, (0, decorators_1.Log)()),
|
|
195
|
+
__metadata("design:type", Function),
|
|
196
|
+
__metadata("design:paramtypes", [Object, Object, decorators_1.Logger]),
|
|
197
|
+
__metadata("design:returntype", Promise)
|
|
198
|
+
], DbPullCommand.prototype, "execute", null);
|
|
199
|
+
DbPullCommand = __decorate([
|
|
200
|
+
(0, common_1.ICommand)()
|
|
201
|
+
], DbPullCommand);
|
|
202
|
+
exports.DbPullCommand = DbPullCommand;
|
|
203
|
+
let DbPushCommand = class DbPushCommand extends common_1.Command {
|
|
204
|
+
get options() {
|
|
205
|
+
return {
|
|
206
|
+
cmd: 'db',
|
|
207
|
+
childCmd: 'push',
|
|
208
|
+
options: [
|
|
209
|
+
{
|
|
210
|
+
flags: '-e, --envId <envId>',
|
|
211
|
+
desc: '环境 Id'
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
flags: '-d, --dir <dir>',
|
|
215
|
+
desc: '本地存储数据库模型定义的目录,默认为 database-schemas'
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
flags: '-n, --name <name>',
|
|
219
|
+
desc: '要推送的模型名称列表,可指定多个,使用逗号分隔.不指定的情况下默认会推送本地目录下的所有数据模型'
|
|
220
|
+
}
|
|
221
|
+
],
|
|
222
|
+
requiredEnvId: false,
|
|
223
|
+
autoRunLogin: true,
|
|
224
|
+
desc: '从云端拉取多个数据模型到本地',
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
execute(envId, params, log) {
|
|
228
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
229
|
+
if (!envId) {
|
|
230
|
+
envId = yield selectEnv();
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
log.info(`使用环境 Id:${envId}`);
|
|
234
|
+
}
|
|
235
|
+
let { name = '', dir } = params;
|
|
236
|
+
name = name.split(',').map(item => item.trim()).filter(item => item);
|
|
237
|
+
if (!dir) {
|
|
238
|
+
dir = 'database-schemas';
|
|
239
|
+
if (!fs_extra_1.default.existsSync(dir)) {
|
|
240
|
+
throw new error_1.CloudBaseError(`目录 ${dir} 不存在,请指定正确的目录`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (!name.length) {
|
|
244
|
+
name = fs_extra_1.default.readdirSync(dir).map(item => item.replace('.json', ''));
|
|
245
|
+
}
|
|
246
|
+
if (!name.length) {
|
|
247
|
+
throw new error_1.CloudBaseError(`目录 ${dir} 中没有找到任何数据模型`);
|
|
248
|
+
}
|
|
249
|
+
const ids = [];
|
|
250
|
+
for (const modelName of name) {
|
|
251
|
+
log.info(`开始检查数据模型 ${modelName}`);
|
|
252
|
+
const modelPath = path_1.default.join(process.cwd(), dir, `${modelName}.json`);
|
|
253
|
+
const model = require(modelPath);
|
|
254
|
+
const existModel = yield (0, db_1.getModel)({
|
|
255
|
+
envId,
|
|
256
|
+
name: modelName
|
|
257
|
+
});
|
|
258
|
+
if (existModel) {
|
|
259
|
+
const confirm = yield inquirer_1.default.prompt([
|
|
260
|
+
{
|
|
261
|
+
type: 'confirm',
|
|
262
|
+
name: 'confirm',
|
|
263
|
+
message: `数据模型 ${modelName} 已存在,是否更新?`
|
|
264
|
+
}
|
|
265
|
+
]);
|
|
266
|
+
if (!confirm.confirm) {
|
|
267
|
+
log.info(`跳过更新数据模型 ${modelName}`);
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
yield (0, db_1.updateModel)({
|
|
271
|
+
envId,
|
|
272
|
+
id: existModel.Id,
|
|
273
|
+
title: model.title || existModel.Title,
|
|
274
|
+
schema: model
|
|
275
|
+
});
|
|
276
|
+
ids.push(existModel.Id);
|
|
277
|
+
const link = (0, utils_1.genClickableLink)(`https://tcb.cloud.tencent.com/cloud-admin/#/management/data-model/${existModel.Id}}`);
|
|
278
|
+
log.success(`更新数据模型 ${modelName} 成功,点击查看 ${link}`);
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
const confirm = yield inquirer_1.default.prompt([
|
|
282
|
+
{
|
|
283
|
+
type: 'confirm',
|
|
284
|
+
name: 'confirm',
|
|
285
|
+
message: `数据模型 ${modelName} 不存在,是否创建?`
|
|
286
|
+
}
|
|
287
|
+
]);
|
|
288
|
+
if (!confirm.confirm) {
|
|
289
|
+
log.info(`跳过创建数据模型 ${modelName}`);
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
const createModelRes = yield (0, db_1.createModel)({
|
|
293
|
+
envId,
|
|
294
|
+
name: modelName,
|
|
295
|
+
title: model.title || modelName,
|
|
296
|
+
schema: model
|
|
297
|
+
});
|
|
298
|
+
ids.push(createModelRes.Id);
|
|
299
|
+
const link = (0, utils_1.genClickableLink)(`https://tcb.cloud.tencent.com/cloud-admin/#/management/data-model/${createModelRes.Id}}`);
|
|
300
|
+
log.success(`创建数据模型 ${modelName} 成功, 点击查看 ${link}`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
const confirmPublish = yield inquirer_1.default.prompt([
|
|
304
|
+
{
|
|
305
|
+
type: 'confirm',
|
|
306
|
+
name: 'confirm',
|
|
307
|
+
message: `数据模型已经导入成功,是否发布?`
|
|
308
|
+
}
|
|
309
|
+
]);
|
|
310
|
+
if (confirmPublish.confirm) {
|
|
311
|
+
const publishRes = yield (0, db_1.publishModel)({
|
|
312
|
+
envId,
|
|
313
|
+
ids
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
__decorate([
|
|
320
|
+
(0, decorators_1.InjectParams)(),
|
|
321
|
+
__param(0, (0, decorators_1.EnvId)()),
|
|
322
|
+
__param(1, (0, decorators_1.ArgsParams)()),
|
|
323
|
+
__param(2, (0, decorators_1.Log)()),
|
|
324
|
+
__metadata("design:type", Function),
|
|
325
|
+
__metadata("design:paramtypes", [Object, Object, decorators_1.Logger]),
|
|
326
|
+
__metadata("design:returntype", Promise)
|
|
327
|
+
], DbPushCommand.prototype, "execute", null);
|
|
328
|
+
DbPushCommand = __decorate([
|
|
329
|
+
(0, common_1.ICommand)()
|
|
330
|
+
], DbPushCommand);
|
|
331
|
+
exports.DbPushCommand = DbPushCommand;
|
|
332
|
+
function selectEnv() {
|
|
333
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
334
|
+
const data = yield (0, env_1.listEnvs)();
|
|
335
|
+
const sortData = data.sort((prev, next) => {
|
|
336
|
+
if (prev.Alias > next.Alias) {
|
|
337
|
+
return 1;
|
|
338
|
+
}
|
|
339
|
+
if (prev.Alias < next.Alias) {
|
|
340
|
+
return -1;
|
|
341
|
+
}
|
|
342
|
+
return 0;
|
|
343
|
+
});
|
|
344
|
+
const choices = sortData.map((item) => {
|
|
345
|
+
return {
|
|
346
|
+
name: `${item.Alias || item.EnvId} (${item.EnvId}) ${item.Status === 'NORMAL' ? '正常' : '不可用'}`,
|
|
347
|
+
value: item.EnvId,
|
|
348
|
+
short: item.envId
|
|
349
|
+
};
|
|
350
|
+
});
|
|
351
|
+
const questions = [
|
|
352
|
+
{
|
|
353
|
+
type: 'list',
|
|
354
|
+
name: 'env',
|
|
355
|
+
message: '请先选择一个云开发环境',
|
|
356
|
+
choices: choices
|
|
357
|
+
}
|
|
358
|
+
];
|
|
359
|
+
const answers = yield inquirer_1.default.prompt(questions);
|
|
360
|
+
return answers.env;
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
function selectModel(envId) {
|
|
364
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
365
|
+
const data = yield (0, db_1.listModels)({
|
|
366
|
+
envId
|
|
367
|
+
});
|
|
368
|
+
const sortData = data.sort((prev, next) => {
|
|
369
|
+
if (prev.CreatedAt > next.CreatedAt) {
|
|
370
|
+
return 1;
|
|
371
|
+
}
|
|
372
|
+
if (prev.CreatedAt < next.CreatedAt) {
|
|
373
|
+
return -1;
|
|
374
|
+
}
|
|
375
|
+
return 0;
|
|
376
|
+
});
|
|
377
|
+
const choices = sortData.map((item) => {
|
|
378
|
+
return {
|
|
379
|
+
name: `${item.Title} (${item.Name})`,
|
|
380
|
+
value: item.Name,
|
|
381
|
+
short: item.Name
|
|
382
|
+
};
|
|
383
|
+
});
|
|
384
|
+
const questions = [
|
|
385
|
+
{
|
|
386
|
+
type: 'checkbox',
|
|
387
|
+
name: 'model',
|
|
388
|
+
message: '请选择数据模型',
|
|
389
|
+
choices: choices
|
|
390
|
+
}
|
|
391
|
+
];
|
|
392
|
+
const answers = yield inquirer_1.default.prompt(questions);
|
|
393
|
+
return answers.model;
|
|
394
|
+
});
|
|
395
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./base"), exports);
|
package/lib/commands/index.js
CHANGED
|
@@ -54,12 +54,20 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
54
54
|
}
|
|
55
55
|
return t;
|
|
56
56
|
};
|
|
57
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
58
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
59
|
+
};
|
|
57
60
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
58
|
-
exports.LowCodeDeployApp = exports.LowCodePreviewApp = exports.LowCodeBuildApp = exports.LowCodeWatch = void 0;
|
|
61
|
+
exports.ModelTypeSync = exports.LowCodeDeployApp = exports.LowCodeBuildAppConfig = exports.LowCodePreviewApp = exports.LowCodeBuildApp = exports.LowCodeWatch = void 0;
|
|
62
|
+
const lodash_1 = require("lodash");
|
|
59
63
|
const common_1 = require("../common");
|
|
60
64
|
const decorators_1 = require("../../decorators");
|
|
61
65
|
const utils_1 = require("./utils");
|
|
62
66
|
const utils_2 = require("../../utils");
|
|
67
|
+
const cloud_api_1 = require("@cloudbase/cloud-api");
|
|
68
|
+
const toolbox_1 = require("@cloudbase/toolbox");
|
|
69
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
70
|
+
const dts_1 = require("../../utils/dts");
|
|
63
71
|
let lowcodeCli;
|
|
64
72
|
if (process.argv.includes('lowcode')) {
|
|
65
73
|
(0, utils_1.getLowcodeCli)().then((_) => (lowcodeCli = _));
|
|
@@ -210,6 +218,55 @@ LowCodePreviewApp = __decorate([
|
|
|
210
218
|
(0, common_1.ICommand)({ supportPrivate: true })
|
|
211
219
|
], LowCodePreviewApp);
|
|
212
220
|
exports.LowCodePreviewApp = LowCodePreviewApp;
|
|
221
|
+
let LowCodeBuildAppConfig = class LowCodeBuildAppConfig extends common_1.Command {
|
|
222
|
+
get options() {
|
|
223
|
+
return {
|
|
224
|
+
cmd: 'lowcode',
|
|
225
|
+
childCmd: 'build:app-config',
|
|
226
|
+
options: [
|
|
227
|
+
{
|
|
228
|
+
flags: '--out <out>',
|
|
229
|
+
desc: '输出目录'
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
flags: '--build-type-list <type...>',
|
|
233
|
+
desc: '输出目录'
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
flags: '--domain <domain>',
|
|
237
|
+
desc: '托管域名'
|
|
238
|
+
}
|
|
239
|
+
],
|
|
240
|
+
desc: '构建应用配置',
|
|
241
|
+
requiredEnvId: false
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
execute(ctx, log, options) {
|
|
245
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
246
|
+
const config = (0, utils_1.getCmdConfig)(ctx.config, this.options);
|
|
247
|
+
const mergesOptions = (0, utils_1.getMergedOptions)(config, options);
|
|
248
|
+
yield lowcodeCli.buildAppConfig({
|
|
249
|
+
envId: ctx.envId || ctx.config.envId,
|
|
250
|
+
projectPath: process.cwd(),
|
|
251
|
+
logger: log,
|
|
252
|
+
privateSettings: (0, utils_2.getPrivateSettings)(ctx.config, this.options.cmd)
|
|
253
|
+
}, mergesOptions);
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
__decorate([
|
|
258
|
+
(0, decorators_1.InjectParams)(),
|
|
259
|
+
__param(0, (0, decorators_1.CmdContext)()),
|
|
260
|
+
__param(1, (0, decorators_1.Log)()),
|
|
261
|
+
__param(2, (0, decorators_1.ArgsOptions)()),
|
|
262
|
+
__metadata("design:type", Function),
|
|
263
|
+
__metadata("design:paramtypes", [Object, decorators_1.Logger, Object]),
|
|
264
|
+
__metadata("design:returntype", Promise)
|
|
265
|
+
], LowCodeBuildAppConfig.prototype, "execute", null);
|
|
266
|
+
LowCodeBuildAppConfig = __decorate([
|
|
267
|
+
(0, common_1.ICommand)({ supportPrivate: true })
|
|
268
|
+
], LowCodeBuildAppConfig);
|
|
269
|
+
exports.LowCodeBuildAppConfig = LowCodeBuildAppConfig;
|
|
213
270
|
let LowCodeDeployApp = class LowCodeDeployApp extends common_1.Command {
|
|
214
271
|
get options() {
|
|
215
272
|
return {
|
|
@@ -219,6 +276,10 @@ let LowCodeDeployApp = class LowCodeDeployApp extends common_1.Command {
|
|
|
219
276
|
{
|
|
220
277
|
flags: '--src <src>',
|
|
221
278
|
desc: '部署目录'
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
flags: '--sync-cloud',
|
|
282
|
+
desc: '是否同步云端部署记录'
|
|
222
283
|
}
|
|
223
284
|
],
|
|
224
285
|
desc: '发布应用',
|
|
@@ -260,3 +321,95 @@ LowCodeDeployApp = __decorate([
|
|
|
260
321
|
(0, common_1.ICommand)({ supportPrivate: true })
|
|
261
322
|
], LowCodeDeployApp);
|
|
262
323
|
exports.LowCodeDeployApp = LowCodeDeployApp;
|
|
324
|
+
let ModelTypeSync = class ModelTypeSync extends common_1.Command {
|
|
325
|
+
get options() {
|
|
326
|
+
return {
|
|
327
|
+
cmd: 'sync-model-dts',
|
|
328
|
+
options: [
|
|
329
|
+
{
|
|
330
|
+
flags: '--envId <envId>',
|
|
331
|
+
desc: '环境 ID'
|
|
332
|
+
}
|
|
333
|
+
],
|
|
334
|
+
desc: '同步数据模型类型定义文件',
|
|
335
|
+
requiredEnvId: true,
|
|
336
|
+
autoRunLogin: true
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
execute(ctx, log, options) {
|
|
340
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
341
|
+
log.info('同步中...');
|
|
342
|
+
if (!(yield fs_extra_1.default.pathExists('cloudbaserc.json'))) {
|
|
343
|
+
yield fs_extra_1.default.writeFile('cloudbaserc.json', JSON.stringify({
|
|
344
|
+
version: '2.0',
|
|
345
|
+
envId: ctx.envId
|
|
346
|
+
}, null, 2), 'utf8');
|
|
347
|
+
}
|
|
348
|
+
if (!(yield fs_extra_1.default.pathExists('tsconfig.json'))) {
|
|
349
|
+
yield fs_extra_1.default.writeFile('tsconfig.json', JSON.stringify({
|
|
350
|
+
compilerOptions: {
|
|
351
|
+
allowJs: true
|
|
352
|
+
}
|
|
353
|
+
}, null, 2), 'utf8');
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
const config = yield fs_extra_1.default.readJson('tsconfig.json', 'utf8');
|
|
357
|
+
(0, lodash_1.set)(config, 'compilerOptions.allowJs', true);
|
|
358
|
+
yield fs_extra_1.default.writeFile('tsconfig.json', JSON.stringify(config, null, 2), 'utf8');
|
|
359
|
+
}
|
|
360
|
+
const cloudService = yield getCloudServiceInstance(ctx);
|
|
361
|
+
const datasourceList = yield cloudService.lowcode.request('DescribeDataSourceList', {
|
|
362
|
+
EnvId: ctx.envId,
|
|
363
|
+
PageIndex: 1,
|
|
364
|
+
PageSize: 1000,
|
|
365
|
+
QuerySystemModel: true,
|
|
366
|
+
QueryConnector: 0
|
|
367
|
+
});
|
|
368
|
+
const rows = datasourceList.Data.Rows;
|
|
369
|
+
const dataModelList = rows.map((item) => ({
|
|
370
|
+
name: item.Name,
|
|
371
|
+
schema: JSON.parse(item.Schema),
|
|
372
|
+
title: item.Title
|
|
373
|
+
}));
|
|
374
|
+
const dts = yield (0, dts_1.generateDataModelDTS)(dataModelList);
|
|
375
|
+
const dtsFileName = 'cloud-models.d.ts';
|
|
376
|
+
yield fs_extra_1.default.writeFile(dtsFileName, dts);
|
|
377
|
+
log.success('同步数据模型类型定义文件成功。文件名称:' + dtsFileName);
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
__decorate([
|
|
382
|
+
(0, decorators_1.InjectParams)(),
|
|
383
|
+
__param(0, (0, decorators_1.CmdContext)()),
|
|
384
|
+
__param(1, (0, decorators_1.Log)()),
|
|
385
|
+
__param(2, (0, decorators_1.ArgsOptions)()),
|
|
386
|
+
__metadata("design:type", Function),
|
|
387
|
+
__metadata("design:paramtypes", [Object, decorators_1.Logger, Object]),
|
|
388
|
+
__metadata("design:returntype", Promise)
|
|
389
|
+
], ModelTypeSync.prototype, "execute", null);
|
|
390
|
+
ModelTypeSync = __decorate([
|
|
391
|
+
(0, common_1.ICommand)({ supportPrivate: true })
|
|
392
|
+
], ModelTypeSync);
|
|
393
|
+
exports.ModelTypeSync = ModelTypeSync;
|
|
394
|
+
function getCloudServiceInstance(ctx) {
|
|
395
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
396
|
+
let credential;
|
|
397
|
+
if (ctx.hasPrivateSettings) {
|
|
398
|
+
process.env.IS_PRIVATE = 'true';
|
|
399
|
+
const privateSettings = (0, utils_2.getPrivateSettings)(ctx.config, this.options.cmd);
|
|
400
|
+
credential = privateSettings.credential;
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
credential = yield utils_2.authSupevisor.getLoginState();
|
|
404
|
+
}
|
|
405
|
+
return {
|
|
406
|
+
lowcode: cloud_api_1.CloudApiService.getInstance({
|
|
407
|
+
service: 'lowcode',
|
|
408
|
+
proxy: (0, toolbox_1.getProxy)(),
|
|
409
|
+
credential,
|
|
410
|
+
version: '2021-01-08'
|
|
411
|
+
}),
|
|
412
|
+
tcb: cloud_api_1.CloudApiService.getInstance({ service: 'tcb', proxy: (0, toolbox_1.getProxy)(), credential })
|
|
413
|
+
};
|
|
414
|
+
});
|
|
415
|
+
}
|
|
@@ -123,7 +123,7 @@ let LowCodeCreateComps = class LowCodeCreateComps extends common_1.Command {
|
|
|
123
123
|
else {
|
|
124
124
|
const comp = comps.rows.find((row) => row.groupName === compsName);
|
|
125
125
|
if (!comp) {
|
|
126
|
-
throw new error_1.CloudBaseError(`云端不存在组件库 ${compsName}
|
|
126
|
+
throw new error_1.CloudBaseError(`云端不存在组件库 ${compsName},请在微搭控制台-应用菜单中,打开任意一个应用的编辑器,点击素材-组件库管理模块,并创建组件库`);
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
yield lowcodeCli.bootstrap(compsName, log);
|
package/lib/db/index.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.publishModel = exports.getModel = exports.updateModel = exports.createModel = exports.listModels = void 0;
|
|
13
|
+
const net_1 = require("../utils/net");
|
|
14
|
+
const lowCodeService = new net_1.CloudApiService('lowcode', {}, '2021-01-08');
|
|
15
|
+
function listModels(options = {}) {
|
|
16
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
const { envId } = options;
|
|
18
|
+
const datasourceList = yield lowCodeService.request('DescribeDataSourceList', {
|
|
19
|
+
EnvId: envId,
|
|
20
|
+
PageIndex: 1,
|
|
21
|
+
PageSize: 1000,
|
|
22
|
+
DataSourceNames: options.name,
|
|
23
|
+
QuerySystemModel: true,
|
|
24
|
+
QueryConnector: 0
|
|
25
|
+
});
|
|
26
|
+
const rows = datasourceList.Data.Rows;
|
|
27
|
+
return rows;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
exports.listModels = listModels;
|
|
31
|
+
function createModel({ envId, name, title, schema }) {
|
|
32
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
return ((yield lowCodeService.request('CreateDataSourceDetail', {
|
|
34
|
+
EnvId: envId,
|
|
35
|
+
Title: title,
|
|
36
|
+
Name: name,
|
|
37
|
+
Type: 'database',
|
|
38
|
+
TableNameRule: "only_name",
|
|
39
|
+
Schema: JSON.stringify(schema)
|
|
40
|
+
})).Data);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
exports.createModel = createModel;
|
|
44
|
+
function updateModel({ envId, id, title, schema }) {
|
|
45
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
46
|
+
return ((yield lowCodeService.request('ModifyDataSource', {
|
|
47
|
+
Id: id,
|
|
48
|
+
EnvId: envId,
|
|
49
|
+
Title: title,
|
|
50
|
+
Schema: JSON.stringify(schema)
|
|
51
|
+
})).Data);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
exports.updateModel = updateModel;
|
|
55
|
+
function getModel(options) {
|
|
56
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
57
|
+
const { envId, name } = options;
|
|
58
|
+
try {
|
|
59
|
+
return (yield lowCodeService.request('DescribeDataSource', {
|
|
60
|
+
EnvId: envId,
|
|
61
|
+
Name: name
|
|
62
|
+
})).Data;
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
if (e.original.Code === 'ResourceNotFound') {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
throw e;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
exports.getModel = getModel;
|
|
75
|
+
function publishModel(options) {
|
|
76
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
77
|
+
const { envId, ids } = options;
|
|
78
|
+
return (yield lowCodeService.request('BatchPublishDataSources', {
|
|
79
|
+
EnvId: envId,
|
|
80
|
+
DataSourceIds: ids
|
|
81
|
+
})).Data;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
exports.publishModel = publishModel;
|
package/lib/utils/dts.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.generateDataModelDTS = void 0;
|
|
13
|
+
const json_schema_to_typescript_1 = require("json-schema-to-typescript");
|
|
14
|
+
const lodash_1 = require("lodash");
|
|
15
|
+
const tools_1 = require("./tools");
|
|
16
|
+
function generateDataModelDTS(dataModelList) {
|
|
17
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
18
|
+
const dtsList = yield Promise.all(dataModelList.map((item) => __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
let dts = yield _handleOne(item.name, item.schema);
|
|
20
|
+
return {
|
|
21
|
+
name: item.name,
|
|
22
|
+
title: item.title,
|
|
23
|
+
dts
|
|
24
|
+
};
|
|
25
|
+
})));
|
|
26
|
+
const result = `
|
|
27
|
+
import { DataModelMethods } from "@cloudbase/wx-cloud-client-sdk";
|
|
28
|
+
${dtsList.map((item) => item.dts).join('\n')}
|
|
29
|
+
|
|
30
|
+
interface IModels {
|
|
31
|
+
${dtsList
|
|
32
|
+
.map((item) => {
|
|
33
|
+
return `
|
|
34
|
+
/**
|
|
35
|
+
* 数据模型:${item.title}
|
|
36
|
+
*/
|
|
37
|
+
${_toValidFieldName(item.name)}: DataModelMethods<${getModelInterfaceName(item.name)}>;`;
|
|
38
|
+
})
|
|
39
|
+
.join('\n')}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
declare module "@cloudbase/wx-cloud-client-sdk" {
|
|
43
|
+
interface OrmClient extends IModels {}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
declare global {
|
|
47
|
+
interface WxCloud {
|
|
48
|
+
models: IModels;
|
|
49
|
+
}
|
|
50
|
+
}`;
|
|
51
|
+
return result;
|
|
52
|
+
function _handleOne(name, schema) {
|
|
53
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
54
|
+
if (!(schema === null || schema === void 0 ? void 0 : schema.properties))
|
|
55
|
+
return `interface ${getModelInterfaceName(name)} {}`;
|
|
56
|
+
Object.keys(schema.properties).forEach((key) => {
|
|
57
|
+
if (schema.properties[key]['x-system']) {
|
|
58
|
+
delete schema.properties[key];
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
Object.keys(schema.properties).forEach((key) => {
|
|
62
|
+
const field = schema.properties[key];
|
|
63
|
+
if (['related', 'father-son'].includes(field.format)) {
|
|
64
|
+
schema.properties[`@${key}`] = {
|
|
65
|
+
type: 'object',
|
|
66
|
+
description: `关联${field.title}对象`,
|
|
67
|
+
properties: {
|
|
68
|
+
v1: {
|
|
69
|
+
type: 'object',
|
|
70
|
+
properties: {
|
|
71
|
+
record: {
|
|
72
|
+
type: 'string',
|
|
73
|
+
format: field.format,
|
|
74
|
+
'x-parent': {
|
|
75
|
+
parentDataSourceName: field['x-parent'].parentDataSourceName
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
schema.properties[key].format = '';
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
schema = JSON.parse(JSON.stringify(schema, (_, value) => {
|
|
86
|
+
if ((0, lodash_1.has)(value, 'title') && !(0, lodash_1.has)(value, 'title.title')) {
|
|
87
|
+
(0, lodash_1.set)(value, 'description', value['title'] + '\n' + value['description']);
|
|
88
|
+
delete value['title'];
|
|
89
|
+
}
|
|
90
|
+
return value;
|
|
91
|
+
}));
|
|
92
|
+
const dts = yield _compile(name, schema);
|
|
93
|
+
return dts;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function _compile(name, jsonschema) {
|
|
97
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
98
|
+
try {
|
|
99
|
+
let dts = yield (0, json_schema_to_typescript_1.compile)(jsonschema, getModelInterfaceName(name), {
|
|
100
|
+
additionalProperties: false,
|
|
101
|
+
bannerComment: '',
|
|
102
|
+
format: true,
|
|
103
|
+
unknownAny: false,
|
|
104
|
+
customName(_schema) {
|
|
105
|
+
var _a, _b;
|
|
106
|
+
const format = _schema.format;
|
|
107
|
+
let name = '';
|
|
108
|
+
if (['one-one', 'many-one', 'related', 'father-son'].includes(format)) {
|
|
109
|
+
name = getModelInterfaceName((_a = _schema === null || _schema === void 0 ? void 0 : _schema['x-parent']) === null || _a === void 0 ? void 0 : _a.parentDataSourceName);
|
|
110
|
+
}
|
|
111
|
+
if (['one-many', 'many-many'].includes(format)) {
|
|
112
|
+
name = `ARRAY_TYPE_${getModelInterfaceName((_b = _schema === null || _schema === void 0 ? void 0 : _schema['x-parent']) === null || _b === void 0 ? void 0 : _b.parentDataSourceName)}`;
|
|
113
|
+
}
|
|
114
|
+
if (name) {
|
|
115
|
+
name = `${name}_TAIL${(0, tools_1.uuidv4)()}_END_`;
|
|
116
|
+
}
|
|
117
|
+
return name || undefined;
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
dts = dts
|
|
121
|
+
.replace(/export interface/g, 'interface')
|
|
122
|
+
.replace(/ARRAY_TYPE_(.*);/g, '$1[]')
|
|
123
|
+
.replace(/_TAIL.*?_END_/g, '')
|
|
124
|
+
.replace(/[\s\S]*?(?=interface)/, '');
|
|
125
|
+
return dts;
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
console.error('_compile error:', e);
|
|
129
|
+
return '';
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function _toValidFieldName(name) {
|
|
134
|
+
let result = name.replace(/[^a-zA-Z0-9_$]/g, '_');
|
|
135
|
+
if (/^[0-9]/.test(result)) {
|
|
136
|
+
result = '_' + result;
|
|
137
|
+
}
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
function getModelInterfaceName(name) {
|
|
141
|
+
if (!name)
|
|
142
|
+
return '';
|
|
143
|
+
return (0, lodash_1.upperFirst)((0, lodash_1.deburr)(`IModal_${name}`)
|
|
144
|
+
.replace(/(^\s*[^a-zA-Z_$])|([^a-zA-Z_$\d])/g, ' ')
|
|
145
|
+
.replace(/^_[a-z]/g, (match) => match.toUpperCase())
|
|
146
|
+
.replace(/_[a-z]/g, (match) => match.substr(1, match.length).toUpperCase())
|
|
147
|
+
.replace(/([\d$]+[a-zA-Z])/g, (match) => match.toUpperCase())
|
|
148
|
+
.replace(/\s+([a-zA-Z])/g, (match) => (0, lodash_1.trim)(match.toUpperCase()))
|
|
149
|
+
.replace(/\s/g, ''));
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
exports.generateDataModelDTS = generateDataModelDTS;
|
|
@@ -30,7 +30,7 @@ class CloudApiService {
|
|
|
30
30
|
constructor(service, baseParams, version = '') {
|
|
31
31
|
this.apiService = new cloud_api_1.CloudApiService({
|
|
32
32
|
service,
|
|
33
|
-
version:
|
|
33
|
+
version: version || '2019-09-24',
|
|
34
34
|
baseParams,
|
|
35
35
|
proxy: (0, toolbox_1.getProxy)(),
|
|
36
36
|
timeout: constant_1.REQUEST_TIMEOUT,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudbase/cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "cli tool for cloudbase",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"watch": "rimraf lib types && tsc -w",
|
|
9
9
|
"dev": "rimraf lib types && tsc -w",
|
|
10
10
|
"eslint": "eslint \"./**/*.ts\"",
|
|
11
|
-
"test": "jest --runInBand --forceExit --detectOpenHandles --coverage --verbose --testTimeout=10000",
|
|
11
|
+
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --runInBand --forceExit --detectOpenHandles --coverage --verbose --testTimeout=10000",
|
|
12
12
|
"tsc": "tsc",
|
|
13
13
|
"pkg": "pkg ./bin/cloudbase.js --out-path ./pkg",
|
|
14
14
|
"postinstall": "node ./post-install.js || exit 0",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@cloudbase/cloud-api": "^0.5.5",
|
|
35
35
|
"@cloudbase/framework-core": "^1.9.7",
|
|
36
|
-
"@cloudbase/lowcode-cli": "^0.21.
|
|
36
|
+
"@cloudbase/lowcode-cli": "^0.21.1",
|
|
37
37
|
"@cloudbase/manager-node": "4.2.8",
|
|
38
38
|
"@cloudbase/toolbox": "^0.7.5",
|
|
39
39
|
"@sentry/node": "^5.10.2",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"fs-extra": "^8.1.0",
|
|
49
49
|
"https-proxy-agent": "^5.0.1",
|
|
50
50
|
"inquirer": "^6.5.0",
|
|
51
|
+
"json-schema-to-typescript": "^14.0.5",
|
|
51
52
|
"lodash": "^4.17.21",
|
|
52
53
|
"log-symbols": "^3.0.0",
|
|
53
54
|
"lowdb": "^1.0.0",
|
|
@@ -69,6 +70,7 @@
|
|
|
69
70
|
"yargs-parser": "^21.0.1"
|
|
70
71
|
},
|
|
71
72
|
"devDependencies": {
|
|
73
|
+
"@types/fs-extra": "^11.0.4",
|
|
72
74
|
"@types/jest": "^27",
|
|
73
75
|
"@types/koa__router": "^8.0.11",
|
|
74
76
|
"@types/lodash": "^4.14.182",
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Command } from '../common';
|
|
2
|
+
import { Logger } from '../../decorators';
|
|
3
|
+
export declare class DbListCommand extends Command {
|
|
4
|
+
get options(): {
|
|
5
|
+
cmd: string;
|
|
6
|
+
childCmd: string;
|
|
7
|
+
options: {
|
|
8
|
+
flags: string;
|
|
9
|
+
desc: string;
|
|
10
|
+
}[];
|
|
11
|
+
requiredEnvId: boolean;
|
|
12
|
+
autoRunLogin: boolean;
|
|
13
|
+
desc: string;
|
|
14
|
+
};
|
|
15
|
+
execute(envId: any, log: Logger): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
export declare class DbPullCommand extends Command {
|
|
18
|
+
get options(): {
|
|
19
|
+
cmd: string;
|
|
20
|
+
childCmd: string;
|
|
21
|
+
options: {
|
|
22
|
+
flags: string;
|
|
23
|
+
desc: string;
|
|
24
|
+
}[];
|
|
25
|
+
requiredEnvId: boolean;
|
|
26
|
+
autoRunLogin: boolean;
|
|
27
|
+
desc: string;
|
|
28
|
+
};
|
|
29
|
+
execute(envId: any, params: any, log: Logger): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
export declare class DbPushCommand extends Command {
|
|
32
|
+
get options(): {
|
|
33
|
+
cmd: string;
|
|
34
|
+
childCmd: string;
|
|
35
|
+
options: {
|
|
36
|
+
flags: string;
|
|
37
|
+
desc: string;
|
|
38
|
+
}[];
|
|
39
|
+
requiredEnvId: boolean;
|
|
40
|
+
autoRunLogin: boolean;
|
|
41
|
+
desc: string;
|
|
42
|
+
};
|
|
43
|
+
execute(envId: any, params: any, log: Logger): Promise<void>;
|
|
44
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './base';
|
|
@@ -40,6 +40,19 @@ export declare class LowCodePreviewApp extends Command {
|
|
|
40
40
|
};
|
|
41
41
|
execute(ctx: ICommandContext, log: Logger, options: any): Promise<void>;
|
|
42
42
|
}
|
|
43
|
+
export declare class LowCodeBuildAppConfig extends Command {
|
|
44
|
+
get options(): {
|
|
45
|
+
cmd: string;
|
|
46
|
+
childCmd: string;
|
|
47
|
+
options: {
|
|
48
|
+
flags: string;
|
|
49
|
+
desc: string;
|
|
50
|
+
}[];
|
|
51
|
+
desc: string;
|
|
52
|
+
requiredEnvId: boolean;
|
|
53
|
+
};
|
|
54
|
+
execute(ctx: ICommandContext, log: Logger, options: any): Promise<void>;
|
|
55
|
+
}
|
|
43
56
|
export declare class LowCodeDeployApp extends Command {
|
|
44
57
|
get options(): {
|
|
45
58
|
cmd: string;
|
|
@@ -53,3 +66,16 @@ export declare class LowCodeDeployApp extends Command {
|
|
|
53
66
|
};
|
|
54
67
|
execute(ctx: ICommandContext, log: Logger, options: any): Promise<void>;
|
|
55
68
|
}
|
|
69
|
+
export declare class ModelTypeSync extends Command {
|
|
70
|
+
get options(): {
|
|
71
|
+
cmd: string;
|
|
72
|
+
options: {
|
|
73
|
+
flags: string;
|
|
74
|
+
desc: string;
|
|
75
|
+
}[];
|
|
76
|
+
desc: string;
|
|
77
|
+
requiredEnvId: boolean;
|
|
78
|
+
autoRunLogin: boolean;
|
|
79
|
+
};
|
|
80
|
+
execute(ctx: ICommandContext, log: Logger, options: any): Promise<void>;
|
|
81
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare function listModels(options?: {
|
|
2
|
+
envId?: string;
|
|
3
|
+
name?: string[];
|
|
4
|
+
}): Promise<any[]>;
|
|
5
|
+
export declare function createModel({ envId, name, title, schema }: {
|
|
6
|
+
envId: string;
|
|
7
|
+
name: string;
|
|
8
|
+
title: string;
|
|
9
|
+
schema: any;
|
|
10
|
+
}): Promise<any>;
|
|
11
|
+
export declare function updateModel({ envId, id, title, schema }: {
|
|
12
|
+
envId: string;
|
|
13
|
+
id: string;
|
|
14
|
+
title: string;
|
|
15
|
+
schema: any;
|
|
16
|
+
}): Promise<any>;
|
|
17
|
+
export declare function getModel(options: {
|
|
18
|
+
envId: string;
|
|
19
|
+
name: string;
|
|
20
|
+
}): Promise<any>;
|
|
21
|
+
export declare function publishModel(options: {
|
|
22
|
+
envId: string;
|
|
23
|
+
ids: string[];
|
|
24
|
+
}): Promise<any>;
|