cloudcc-cli 1.9.8 → 2.0.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.
@@ -3,6 +3,8 @@ const inquirer = require("inquirer")
3
3
  const exec = require('child_process').execSync;
4
4
  const chalk = require("chalk")
5
5
  const { readCache, writeCache } = require("./cache")
6
+ const fs = require('fs');
7
+ const path = require('path');
6
8
 
7
9
  function checkNpmVersion() {
8
10
  let currentVersion = Number(config.version.replace(/\./g, ""));
@@ -77,6 +79,7 @@ async function checkUpdate(path = process.cwd()) {
77
79
 
78
80
  let onlineVersion;
79
81
  try {
82
+ checkAndReplaceJar();
80
83
  onlineVersion = checkNpmVersion();
81
84
  cache[cacheKey] = {
82
85
  timestamp: now
@@ -99,4 +102,55 @@ async function checkUpdate(path = process.cwd()) {
99
102
  return false
100
103
  }
101
104
 
102
- module.exports = { checkUpdate }
105
+ function checkAndReplaceJar(projectPath = process.cwd()) {
106
+ const projectLibPath = path.join(projectPath, 'lib');
107
+ const templateLibPath = path.join(__dirname, '../template/lib');
108
+
109
+ if (!fs.existsSync(projectLibPath)) {
110
+ console.log(chalk.red('Project lib folder does not exist.'));
111
+ return;
112
+ }
113
+
114
+ const projectJar = fs.readdirSync(projectLibPath).find(file => file.startsWith('ccopenapi') && file.endsWith('.jar'));
115
+ if (!projectJar) {
116
+ return;
117
+ }
118
+
119
+ const projectVersion = projectJar.match(/ccopenapi-(\d+\.\d+\.\d+)/)?.[1];
120
+ if (!projectVersion) {
121
+ console.log(chalk.red('Failed to parse the version of the ccopenapi jar in the project.'));
122
+ return;
123
+ }
124
+
125
+ const templateJar = fs.readdirSync(templateLibPath).find(file => file.startsWith('ccopenapi') && file.endsWith('.jar'));
126
+ if (!templateJar) {
127
+ console.log(chalk.yellow('No ccopenapi jar found in the template lib folder.'));
128
+ return;
129
+ }
130
+
131
+ const templateVersion = templateJar.match(/ccopenapi-(\d+\.\d+\.\d+)/)?.[1];
132
+ if (!templateVersion) {
133
+ console.log(chalk.red('Failed to parse the version of the ccopenapi jar in the template.'));
134
+ return;
135
+ }
136
+
137
+ const compareVersions = (v1, v2) => {
138
+ const [major1, minor1, patch1] = v1.split('.').map(Number);
139
+ const [major2, minor2, patch2] = v2.split('.').map(Number);
140
+ if (major1 !== major2) return major1 - major2;
141
+ if (minor1 !== minor2) return minor1 - minor2;
142
+ return patch1 - patch2;
143
+ };
144
+
145
+ if (compareVersions(templateVersion, projectVersion) > 0) {
146
+ // Delete the old jar file
147
+ fs.unlinkSync(path.join(projectLibPath, projectJar));
148
+ // Copy the new jar file
149
+ fs.copyFileSync(
150
+ path.join(templateLibPath, templateJar),
151
+ path.join(projectLibPath, templateJar)
152
+ );
153
+ }
154
+ }
155
+
156
+ module.exports = { checkUpdate };
package/utils/config.js CHANGED
@@ -1,18 +1,81 @@
1
1
  const fs = require("fs");
2
2
  const path = require("path");
3
-
3
+ // 引入解密函数
4
+ const { getDevConsoleConfig, decryptCloudCCDevInfo } = require("./utils");
5
+ const { readCache } = require("./cache")
6
+ /**
7
+ * 1.0版本的配置文件
8
+ * @param {string} projectPath baseUrl
9
+ * @returns
10
+ */
4
11
  function getPackageJson_old(projectPath = process.cwd()) {
5
12
  const packageJson = JSON.parse(fs.readFileSync(path.join(projectPath, "package.json")), 'utf8');
6
13
  return packageJson.devConsoleConfig;
7
14
  }
8
-
9
- function getPackageJson(projectPath = process.cwd()) {
10
- let config = getPackageJson_old(projectPath);
11
- if (!config) {
12
- config = require(path.join(projectPath, "cloudcc-cli.config.js"))
13
- config = config[config.use]
15
+ /**
16
+ * 2.0版本的配置文件
17
+ * 配置参数移入cloudcc-cli.config.js,最多需要配置9个参数
18
+ * @param {string} projectPath baseUrl
19
+ * @returns
20
+ */
21
+ async function getPackageJson2(projectPath = process.cwd()) {
22
+ let config = require(path.join(projectPath, "cloudcc-cli.config.js"))
23
+ config = config[config.use]
24
+ if (config.baseUrl && !config.baseUrl.includes("ccdomaingateway")) {
25
+ config.baseUrl = config.baseUrl + "/ccdomaingateway"
14
26
  }
27
+ config = await getDevConsoleConfig(projectPath, config)
15
28
  return config
16
29
  }
30
+ /**
31
+ * 3.0版本的配置文件
32
+ * 将多个参数压缩到一个参数重,方便配置
33
+ * @param {string} projectPath baseUrl
34
+ * @returns
35
+ */
36
+ async function getPackageJson3(projectPath = process.cwd()) {
37
+ let config = require(path.join(projectPath, "cloudcc-cli.config.js"))
38
+ config = config[config.use]
39
+ // 检查并解密CloudCCDev信息
40
+ if (config && config.CloudCCDev) {
41
+ const decryptedInfo = decryptCloudCCDevInfo(config.CloudCCDev);
42
+ if (decryptedInfo) {
43
+ config = { ...decryptedInfo, ...config }
44
+ if (config.baseUrl && !config.baseUrl.includes("ccdomaingateway")) {
45
+ config.baseUrl = config.baseUrl + "/ccdomaingateway"
46
+ }
47
+ config = await getDevConsoleConfig(projectPath, config)
48
+ }
49
+ } else {
50
+ config = null;
51
+ }
52
+ return config;
53
+ }
17
54
 
18
- module.exports = { getPackageJson }
55
+
56
+ /**
57
+ * 从缓存读取
58
+ * @returns 配置参数
59
+ */
60
+ async function getPackageJsonCache(projectPath = process.cwd()) {
61
+ let config = require(path.join(projectPath, "cloudcc-cli.config.js"));
62
+ const cacheData = readCache()[config[config.use].safetyMark || config[config.use].secretKey];
63
+
64
+ if (cacheData && cacheData.timestamp) {
65
+ const oneHour = 60 * 60 * 1000; // 1小时的毫秒数
66
+ const currentTime = Date.now();
67
+ if (currentTime - cacheData.timestamp > oneHour) {
68
+ return null;
69
+ }
70
+ }
71
+ return cacheData;
72
+ }
73
+
74
+ async function getPackageJson(projectPath = process.cwd()) {
75
+ return getPackageJson_old(projectPath) || await getPackageJsonCache(projectPath) || await getPackageJson3(projectPath) || await getPackageJson2(projectPath)
76
+ }
77
+
78
+
79
+ module.exports = {
80
+ getPackageJson,
81
+ }
package/utils/http.js CHANGED
@@ -1,8 +1,7 @@
1
1
  const https = require("https")
2
2
  const http = require("http")
3
3
  const axios = require("axios")
4
- const { getPackageJson } = require("./config")
5
-
4
+ const chalk = require("chalk")
6
5
  const httpsAgent = new https.Agent({
7
6
  rejectUnauthorized: false,
8
7
  })
@@ -22,14 +21,12 @@ const service = axios.create({
22
21
 
23
22
  service.interceptors.request.use(
24
23
  config => {
25
- if (global.accessToken) {
26
- config.headers.accessToken = global.accessToken
27
- }
28
24
  return config
29
25
  },
30
26
  error => {
31
-
32
- Promise.reject(error)
27
+ console.log()
28
+ console.log(error)
29
+ console.log()
33
30
  }
34
31
  )
35
32
 
@@ -44,12 +41,15 @@ service.interceptors.response.use(
44
41
  }
45
42
  },
46
43
  error => {
47
- return Promise.reject(error)
44
+ console.log("")
45
+ console.log("error", error)
46
+ console.log("")
47
+ process.exit(1)
48
48
  }
49
49
  )
50
50
  const formateData = (data, header) => {
51
51
  if (header) {
52
- Object.assign(header, { source: getPackageJson().source || "cloudcc_cli" })
52
+ Object.assign(header, { source: "cloudcc_cli" })
53
53
  }
54
54
  return {
55
55
  head: {
@@ -61,21 +61,6 @@ const formateData = (data, header) => {
61
61
  }
62
62
  }
63
63
  module.exports = {
64
- get: (url, data = {}, responseType = '') => {
65
- return service({
66
- url: url,
67
- method: 'get',
68
- params: formateData(data),
69
- responseType: responseType
70
- })
71
- },
72
- getParams: (url, data = {}) => {
73
- return service({
74
- url: url,
75
- method: 'get',
76
- params: data,
77
- })
78
- },
79
64
  post: (url, data = {}, header = { appVersion: "1.0.0" }, responseType = '') => {
80
65
  return service({
81
66
  url: url,
@@ -84,40 +69,21 @@ module.exports = {
84
69
  responseType: responseType
85
70
  })
86
71
  },
87
- postParams: (url, data = {}) => {
88
- return service({
89
- url: url,
90
- method: 'post',
91
- params: data,
92
- })
93
- },
94
- postNormal: (url, data = {}) => {
95
- return service({
96
- url: url,
97
- method: 'post',
98
- data: data
99
- })
100
- },
101
- patch: (url, data = {}) => {
102
- return service({
103
- url: url,
104
- method: 'patch',
105
- data: formateData(data)
106
- })
107
- },
108
- delete: (url, data = {}) => {
109
- return service({
110
- url: url,
111
- method: 'delete',
112
- data: formateData(data)
113
- })
72
+ postClass: (url, data = {}, accessToken) => {
73
+ if (accessToken) {
74
+ return service({
75
+ url: url,
76
+ method: 'post',
77
+ headers: {
78
+ "accessToken": accessToken,
79
+ },
80
+ data: data
81
+ })
82
+ } else {
83
+ console.log()
84
+ console.log(chalk.red('Failed: \nOpenAPI Token is null. \nPlease check your cloudcc-cli.config file! \nor delete the .cloudcc-cache.json file and re-run the command!'));
85
+ console.log()
86
+ process.exit(1)
87
+ }
114
88
  },
115
- put: (url, data = {}) => {
116
- return service({
117
- url: url,
118
- method: 'put',
119
- data: formateData(data)
120
- })
121
- }
122
-
123
89
  }
package/utils/utils.js CHANGED
@@ -1,98 +1,157 @@
1
- const { getParams, postNormal } = require("./http")
2
1
  const chalk = require("chalk")
3
- const { getPackageJson } = require("./config")
4
- const { readCache, writeCache } = require("./cache")
2
+ const { writeCache } = require("./cache")
3
+ const axios = require("axios")
4
+ const BaseUrl = "https://developer.apis.cloudcc.cn"
5
5
 
6
- async function getBaseUrl(path, devConfig) {
7
- const cache = readCache(path);
8
- const cacheKey = devConfig.secretKey;
9
- const now = Date.now();
10
- const oneHour = 60 * 60 * 1000;
11
-
12
- // Check if cache is valid
13
- if (cache[cacheKey] &&
14
- cache[cacheKey].apiSvc &&
15
- cache[cacheKey].setupSvc &&
16
- cache[cacheKey].timestamp &&
17
- (now - cache[cacheKey].timestamp) < oneHour) {
18
- global.apiSvc = cache[cacheKey].apiSvc;
19
- global.setupSvc = cache[cacheKey].setupSvc;
20
- return;
6
+ const formateData = (data, header = { appVersion: "1.0.0" }) => {
7
+ if (header) {
8
+ Object.assign(header, { source: "cloudcc_cli" })
21
9
  }
22
-
23
- if (devConfig.baseUrl) {
24
- global.apiSvc = devConfig.baseUrl + (devConfig.apiSvcPrefix || "/apitfs")
25
- global.setupSvc = devConfig.baseUrl + (devConfig.setupSvcPrefix || "/setup")
10
+ return {
11
+ head: {
12
+ ...header
13
+ },
14
+ body: {
15
+ ...data
16
+ }
17
+ }
18
+ }
19
+ /**
20
+ * 获取网关地址
21
+ * @param {object} config 配置参数
22
+ */
23
+ async function getBaseUrl(config) {
24
+ if (config.baseUrl) {
25
+ config.apiSvc = config.baseUrl + (config.apiSvcPrefix || "/apisvc")
26
+ config.setupSvc = config.baseUrl + (config.setupSvcPrefix || "/setup")
26
27
  } else {
27
- let u = "https://developer.apis.cloudcc.cn/oauth/apidomain?scope=cloudccCRM&orgId=" + devConfig.orgId
28
- let res = await getParams(u)
29
- global.apiSvc = res.orgapi_address
30
- global.setupSvc = new URL(res.orgapi_address).origin + (devConfig.setupSvcPrefix || "/setup")
28
+ let u = "https://developer.apis.cloudcc.cn/oauth/apidomain?scope=cloudccCRM&orgId=" + config.orgId
29
+ let res = await axios({
30
+ url: u,
31
+ method: 'get'
32
+ })
33
+ if (200 == res.status && res.data && res.data.result) {
34
+ config.apiSvc = res.data.orgapi_address
35
+ config.setupSvc = new URL(res.data.orgapi_address).origin + (config.setupSvcPrefix || "/setup")
36
+ }
31
37
  }
32
-
33
- // Update cache with apiSvc and setupSvc
34
- cache[cacheKey] = {
35
- ...(cache[cacheKey] || {}),
36
- apiSvc: global.apiSvc,
37
- setupSvc: global.setupSvc,
38
- timestamp: now
39
- };
40
- writeCache(path, cache);
38
+ return config;
41
39
  }
42
-
43
- async function getBusToken(path = process.cwd()) {
44
- let devConfig = getPackageJson(path);
45
- if (!devConfig.username || !devConfig.safetyMark || !devConfig.clientId || !devConfig.openSecretKey || !devConfig.orgId) {
46
- console.log(chalk.red('The security tag configuration is incorrect. Please check the documentation for configuration.'));
47
- console.log();
48
- return false;
40
+ /**
41
+ * 获取发布组件的token
42
+ * @param {object} config 配置参数
43
+ * @returns config
44
+ */
45
+ async function getPluginToken(config) {
46
+ let res = await axios({
47
+ method: 'post',
48
+ url: (config.baseUrl || BaseUrl) + "/sysconfig/auth/pc/1.0/post/tokenInfo",
49
+ data: formateData({ username: config.username, secretKey: config.secretKey }),
50
+ headers: {
51
+ 'Content-Type': 'application/json; charset=utf-8',
52
+ },
53
+ });
54
+ if (res.data.returnCode == 200) {
55
+ config.pluginToken = res.data.data.accessToken;
56
+ } else {
57
+ console.error(chalk.red(`Get Plugin Token Failed:`, res.data.returnInfo, "\nPrivate cloud, please check whether the baseUrl is configured correctly"));
58
+ process.exit(1)
49
59
  }
60
+ return config
61
+ }
62
+ /**
63
+ * 获取OpenAPI的token
64
+ * @returns token值
65
+ */
66
+ async function getBusToken(config) {
67
+ if (config.username && config.safetyMark && config.clientId && config.openSecretKey && config.orgId) {
68
+ let body = {
69
+ username: config.username,
70
+ safetyMark: config.safetyMark,
71
+ clientId: config.clientId,
72
+ secretKey: config.openSecretKey,
73
+ orgId: config.orgId
74
+ }
50
75
 
51
- const cache = readCache(path);
52
- const cacheKey = devConfig.secretKey;
53
- const now = Date.now();
54
- const oneHour = 60 * 60 * 1000;
55
- // Check if cache is valid
56
- if (cache[cacheKey] &&
57
- cache[cacheKey].token &&
58
- cache[cacheKey].apiSvc &&
59
- cache[cacheKey].setupSvc &&
60
- cache[cacheKey].timestamp &&
61
- (now - cache[cacheKey].timestamp) < oneHour) {
62
- global.accessToken = cache[cacheKey].token;
63
- global.apiSvc = cache[cacheKey].apiSvc;
64
- global.setupSvc = cache[cacheKey].setupSvc;
65
- return cache[cacheKey].token;
76
+ const res = await axios({
77
+ method: 'post',
78
+ url: config.apiSvc + "/api/cauth/token",
79
+ headers: {
80
+ 'Content-Type': 'application/json; charset=utf-8',
81
+ },
82
+ data: body
83
+ });
84
+ if (res.data.result) {
85
+ config.accessToken = res.data.data.accessToken;
86
+ } else {
87
+ console.error(chalk.red(`Get OpenAPI Token Failed:`, res.data.returnInfo));
88
+ process.exit(1)
89
+ }
66
90
  }
91
+ return config;
92
+ }
67
93
 
68
- let body = {
69
- username: devConfig.username,
70
- safetyMark: devConfig.safetyMark,
71
- clientId: devConfig.clientId,
72
- secretKey: devConfig.openSecretKey,
73
- orgId: devConfig.orgId
94
+ /**
95
+ * 获取密钥
96
+ * @param {Object} config - 配置对象,需包含username
97
+ * @return {Promise<Object>} 返回密钥信息
98
+ */
99
+ async function getSecretKey(config) {
100
+ try {
101
+ const response = await axios({
102
+ method: 'post',
103
+ url: (config.baseUrl || BaseUrl) + '/sysconfig/auth/secretkey/get',
104
+ headers: {
105
+ 'Content-Type': 'application/x-www-form-urlencoded'
106
+ },
107
+ data: `username=${config.username}`
108
+ });
109
+ config.secretKey = response.data.data.secretKey;
110
+ return config;
111
+ } catch (error) {
112
+ console.log(chalk.red('Get Plugin SecretKey Failed:', error.message));
113
+ process.exit(1)
74
114
  }
75
- await getBaseUrl(path, devConfig)
76
- // return path
77
- let res = await postNormal(global.apiSvc + "/api/cauth/token", body)
78
- if (res.result) {
79
- global.accessToken = res.data.accessToken;
80
- // Update cache
81
- cache[cacheKey] = {
82
- token: res.data.accessToken,
83
- apiSvc: global.apiSvc,
84
- setupSvc: global.setupSvc,
85
- timestamp: now
86
- };
115
+ }
87
116
 
88
- writeCache(path, cache);
89
- return res.data.accessToken;
90
- } else {
91
- console.log(chalk.red(res.returnInfo));
117
+ async function getDevConsoleConfig(projectPath = process.cwd(), config) {
118
+ config = await getBaseUrl(config);
119
+ config = await getBusToken(config);
120
+ config = await getSecretKey(config);
121
+ config = await getPluginToken(config);
122
+ config.timestamp = Date.now();
123
+ writeCache(projectPath, { [config.safetyMark || config.secretKey]: config })
124
+ return config;
125
+ }
126
+
127
+ /**
128
+ * 解密CloudCC开发信息
129
+ * @param {string} encryptedData - 加密后的CloudCC开发信息
130
+ * @return {Object} 解密后的对象
131
+ * {
132
+ "username": "cloudccone@one.lightning",
133
+ "baseUrl": "https://one.lightning.cloudcc.cn",
134
+ "orgId": "org83dd9d283484bbe20",
135
+ "clientId": "RElFpKQUeCs7mtObkk2xvJFFs",
136
+ "openSecretKey": "11a69c74-dec0-4c05-a2fd-4b6c5e485db1"
137
+ }
138
+ */
139
+ function decryptCloudCCDevInfo(encryptedData) {
140
+ try {
141
+ const binaryData = new Uint8Array(Buffer.from(encryptedData, 'base64'));
142
+ const decoder = new TextDecoder();
143
+ const jsonString = decoder.decode(binaryData);
144
+ return JSON.parse(jsonString);
145
+ } catch (error) {
146
+ console.error(error);
147
+ return null;
92
148
  }
93
- return false;
94
149
  }
150
+
151
+ /**
152
+ * 正则表达式,用于匹配Java代码中的源代码内容
153
+ */
95
154
  const javaContentRegular = /\/\/\s*@SOURCE_CONTENT_START\r?\n([\s\S]*?)\r?\n\s*\/\/\s*@SOURCE_CONTENT_END/
96
155
 
97
156
 
98
- module.exports = { getBusToken, javaContentRegular }
157
+ module.exports = { getDevConsoleConfig, javaContentRegular, decryptCloudCCDevInfo }
Binary file