@dypnb/dev-tools 1.0.12 → 1.0.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,228 +0,0 @@
1
- #! /usr/bin/env node
2
-
3
- // 将swagger 转换为 vue api代码
4
- import path from "path";
5
- import fs from "fs";
6
- import http from "http";
7
- import { getGlobalConfig, getDirname, errorLog, log, successLog, } from "../utils/index.js";
8
- const __dirname = getDirname();
9
-
10
-
11
- async function getSwaggerConfig() {
12
- return await getGlobalConfig('swaggerConfig');
13
- }
14
-
15
- getSwaggerConfig().then(res => {
16
- // swagger配置
17
- const swaggerConfig = res;
18
- if (!swaggerConfig) {
19
- errorLog('swaggerConfig 未配置')
20
- }
21
-
22
- // 生成api文件地址
23
- const srcFolder = `${process.env.PWD}${swaggerConfig.outputDir}`;
24
- // swagger接口地址
25
- const url = `${swaggerConfig.path}${swaggerConfig.staticPath}`;
26
-
27
- genSwagger(srcFolder, url);
28
-
29
- })
30
-
31
-
32
- // 生成本地文件
33
- function mkdirsSync(dirname) {
34
- if (fs.existsSync(dirname)) {
35
- return true;
36
- } else {
37
- if (mkdirsSync(path.dirname(dirname))) {
38
- fs.mkdirSync(dirname);
39
- return true;
40
- }
41
- }
42
- }
43
-
44
- function getPath(pathUrl) {
45
- return path.resolve(__dirname, pathUrl);
46
- }
47
-
48
- function generateTemplate(arr) {
49
- return `import request from '@/utils/request'\n`;
50
- }
51
-
52
- // 下划线转换驼峰
53
- function toHump(name) {
54
- return name.replace(/\/(\w)/g, function (all, letter) {
55
- return letter.toUpperCase();
56
- });
57
- }
58
-
59
- // 短横线转换驼峰
60
- function shortToHump(name) {
61
- return name.replace(/-(\w)/g, function (all, letter) {
62
- return letter.toUpperCase();
63
- });
64
- }
65
-
66
- // 去除花括号,获取干净的字段
67
- function removeBrace(value) {
68
- const regex = /\{(.+?)\}/g; // {} 花括号,大括号
69
- const str = value.match(regex)[0] || "";
70
- return str.replace(/\{|}/g, "");
71
- }
72
-
73
- /**
74
- * 生成具体的api:
75
- * export function postRsArticle(data) {
76
- * return request({
77
- * url: '/rs/article',
78
- * method: 'post',
79
- * data: data
80
- * })
81
- * }
82
- */
83
- function generateFunc(url, summary, type = "post") {
84
- // 去除 url 环境前缀: /dev-risk-api/sc/apply/{applyId} ==> /sc/apply/{applyId}
85
- // url = url.split('/');
86
- // url.splice(1,1)
87
- // url = url.join('/');
88
-
89
- const isBrace = url.indexOf("{") !== -1;
90
- let funcName = shortToHump(toHump(type + url));
91
- let splitUrl = "";
92
- let braceKey = "";
93
- if (isBrace) {
94
- splitUrl = url.split("{")[0];
95
- braceKey = removeBrace(url);
96
- funcName = shortToHump(toHump(type + splitUrl + braceKey));
97
- }
98
-
99
- const funcArguments = `${
100
- isBrace
101
- ? braceKey
102
- : !isBrace && (type === "post" || type === "put")
103
- ? "data"
104
- : "query"
105
- }`;
106
- const funcUrl = `${!isBrace ? `'${url}'` : `'${splitUrl}' + ${braceKey}`}`;
107
- const funcParams = `${
108
- isBrace
109
- ? ""
110
- : !isBrace && (type === "post" || type === "put")
111
- ? "\n data: data"
112
- : "\n params: query"
113
- }`;
114
-
115
- return `
116
- // ${summary || ""}
117
- export function ${funcName}(${funcArguments}) {
118
- return request({
119
- url: ${funcUrl},
120
- method: '${type}', ${funcParams}
121
- })
122
- }\n`;
123
- }
124
-
125
- function httpgetJson(url) {
126
- return new Promise((resolve, reject) => {
127
- http
128
- .get(url, (res) => {
129
- const { statusCode } = res;
130
- const contentType = res.headers["content-type"];
131
-
132
- let error;
133
- if (statusCode !== 200) {
134
- error = new Error("请求失败。\n" + `状态码: ${statusCode}`);
135
- } else if (!/^application\/json/.test(contentType)) {
136
- error = new Error(
137
- "无效的 content-type.\n" +
138
- `期望 application/json 但获取的是 ${contentType}`
139
- );
140
- }
141
- if (error) {
142
- errorLog(error.message);
143
- // 消耗响应数据以释放内存
144
- res.resume();
145
- return;
146
- }
147
-
148
- res.setEncoding("utf8");
149
- let rawData = "";
150
- res.on("data", (chunk) => {
151
- rawData += chunk;
152
- });
153
- res.on("end", () => {
154
- try {
155
- const parsedData = JSON.parse(rawData);
156
- resolve(parsedData);
157
- } catch (e) {
158
- reject(`错误: ${e.message}`);
159
- }
160
- });
161
- })
162
- .on("error", (e) => {
163
- reject(`错误: ${e.message}`);
164
- });
165
- });
166
- }
167
-
168
- async function genSwagger(srcFolder, url) {
169
- log("获取远程json文件中...");
170
- const { paths } = await httpgetJson(url);
171
- successLog("获取成功正在生成api文件");
172
- const obj = {};
173
- /**
174
- * 将数据转换成格式
175
- * se-ex-exam-controller: [
176
- * {
177
- * folder:'exam'
178
- * name:'/ex/exam'
179
- * summary:'修改考试考卷'
180
- * tag:'se-ex-exam-controller'
181
- * type:'put'
182
- * }
183
- * ...
184
- * ]
185
- */
186
- for (const name in paths) {
187
- const path = paths[name] || {};
188
- const pathKeys = Object.keys(path) || [];
189
- for (let i = 0, len = pathKeys.length; i < len; i++) {
190
- const apiType = pathKeys[i];
191
- const tag = path[apiType].tags[0];
192
- if (!tag) continue;
193
- log(tag);
194
- const urlArray = name.slice(1).split("/");
195
- const folder = urlArray[1];
196
- const item = {
197
- summary: path[apiType].summary,
198
- tag,
199
- name,
200
- type: apiType,
201
- folder,
202
- };
203
- if (obj[path[apiType].tags[0]]) {
204
- obj[path[apiType].tags[0]].push(item);
205
- } else {
206
- obj[path[apiType].tags[0]] = [item];
207
- }
208
- }
209
- }
210
- for (const tagName in obj) {
211
- let jsString = "";
212
- const requestTypes = [];
213
- let folder = "";
214
- for (const item of obj[tagName]) {
215
- const requestType = requestTypes.filter((o) => o === item.type);
216
- if (requestType.length === 0) requestTypes.push(item.type);
217
- jsString += generateFunc(item.name, item.summary, item.type);
218
- folder = item.folder;
219
- }
220
- jsString = generateTemplate(requestTypes) + jsString;
221
- mkdirsSync(getPath(`${srcFolder}/${folder}`));
222
- // console.log(jsString)
223
- fs.writeFileSync(getPath(`${srcFolder}/${folder}/${tagName}.js`), jsString);
224
- }
225
- successLog("生成完毕");
226
- }
227
-
228
-
package/src/index.js DELETED
@@ -1,12 +0,0 @@
1
- const genPage = require("./gen-page");
2
- const genSwagger = require("./gen-swagger");
3
- const publishServer = require("./publish-server");
4
- const wxServerNotice = require("./wx-server-notice");
5
-
6
-
7
- module.exports = {
8
- genPage,
9
- genSwagger,
10
- publishServer,
11
- wxServerNotice
12
- }
@@ -1,144 +0,0 @@
1
- #! /usr/bin/env node
2
-
3
- // scp2 : https://www.npmjs.com/package/
4
- // 引入scp2
5
- import client from "scp2";
6
- import ora from "ora";
7
- import moment from "moment";
8
- import { getGlobalConfig, getGitInfo, errorLog, magentaLog, log, warningLog, successLog, cyanLog } from "../utils/index.js";
9
- import { wxNotify } from "../wx-server-notice/index.js";
10
- import pkg from 'ssh2';
11
- const { Client } = pkg;
12
-
13
- moment.locale('zh-cn');
14
-
15
- async function getUploadServeConfig() {
16
- return await getGlobalConfig();
17
- }
18
-
19
- getUploadServeConfig().then(res => {
20
- const {
21
- projectInfo = { // 项目基本信息
22
- name: '', // 项目名称
23
- },
24
- locaPath, // 本地上传地址
25
- protocol = 'http', //协议 http、https
26
- staticPath = {}, // 服务器静态资源地址
27
- serverOption = {}, // 服务器配置
28
- shell // shell 命令
29
- } = res['uploadServeConfig'] || {};
30
-
31
- const wxServerConfig = res['wxServerConfig'];
32
-
33
- const isProduction = process.env.VUE_APP_PACK_ENV === "production"; // 是否是生产环境
34
-
35
- const lineVersion = process.env.VUE_APP_LINE_VERSION; //线上环境版本(多个显示环境可使用此字段区分)
36
-
37
- const isNewPro = isProduction && +lineVersion === 2; // 是否是新的线上版本
38
-
39
- const curtHost = !isNewPro ? serverOption.host[0] : serverOption.host[1];
40
-
41
- const curtStaticPath = !isProduction ? staticPath.dev : staticPath.pro;
42
-
43
- const onlinePath = `${protocol}://${curtHost}/${curtStaticPath}`;
44
-
45
- const server = {
46
- port: 22, // 端口默认22
47
- ...serverOption,
48
- host: curtHost, // 服务器 ip
49
- locaPath: `${process.env.PWD}${locaPath}`, // 本地打包文件的位置
50
- pathNmae: `${serverOption.pathNmae}${curtStaticPath}` // 上传到服务器的位置
51
- };
52
-
53
-
54
- // 服务器删除静态资源命令
55
- const shellCommand = !shell ? `rm -rf ${server.pathNmae}/*` : shell;
56
-
57
- const gitInfo = getGitInfo();
58
-
59
-
60
- const packInfo = {
61
- ...(projectInfo || {}),
62
- serverPath: server.pathNmae
63
- }
64
-
65
-
66
- function wxMsg(status) {
67
- return `<div class="gray">${moment().format('lll')}</div><div class="highlight">${projectInfo.name}${isProduction ? "生产" : "开发"}环境发布${status}</div><div class="normal">commitId:${gitInfo.commitId}</div><div class="normal">commitMsg:${gitInfo.commitMsg}</div><div class="normal">访问地址:${onlinePath}</div>`
68
- }
69
-
70
-
71
- cyanLog("本次打包信息 =>", packInfo);
72
-
73
-
74
- const spinner = ora(
75
- "正在发布到" + (isProduction ? "生产" : "开发") + "服务器..."
76
- );
77
-
78
- // 创建shell脚本
79
- const conn = new Client();
80
-
81
- magentaLog("正在建立连接");
82
-
83
- conn
84
- .on("ready", function() {
85
- log("已连接");
86
- if (!server.pathNmae) {
87
- log("连接已关闭");
88
- conn.end();
89
- return false;
90
- }
91
- // 这里我拼接了放置服务器资源目录的位置 ,首选通过rm -rf删除了这个目录下的文件
92
- conn.exec(shellCommand, function(err, stream) {
93
- warningLog("已删除服务端文件")
94
- stream.on("close", function(code, signal) {
95
- log("开始上传");
96
- spinner.start();
97
- client.scp(
98
- server.locaPath,
99
- {
100
- host: server.host,
101
- port: server.port,
102
- username: server.username,
103
- password: server.password,
104
- path: server.pathNmae
105
- },
106
- err => {
107
- spinner.stop();
108
- if (!err) {
109
- successLog("Success! 成功发布到" + (isProduction ? "生产" : "开发") + "服务器!", `访问地址====>${onlinePath}`)
110
- wxNotify({
111
- msgtype: "textcard",
112
- textcard: {
113
- title: "发布成功",
114
- description: wxMsg('成功'),
115
- url: onlinePath,
116
- btntxt: "更多"
117
- }
118
- }, wxServerConfig);
119
- } else {
120
- errorLog("发布失败.\n", err);
121
- wxNotify({
122
- msgtype: "textcard",
123
- textcard: {
124
- title: "发布失败",
125
- description: wxMsg('失败'),
126
- url: onlinePath,
127
- btntxt: "更多"
128
- }
129
- }, wxServerConfig);
130
- }
131
- conn.end(); // 结束命令
132
- }
133
- );
134
- });
135
- });
136
- })
137
- .connect({
138
- host: server.host,
139
- port: server.port,
140
- username: server.username,
141
- password: server.password,
142
- privateKey: server.privateKey || undefined //使用 私钥密钥登录 目前测试服务器不需要用到
143
- });
144
- })
@@ -1,82 +0,0 @@
1
- import findup from "findup-sync";
2
- import chalk from "chalk";
3
- import execa from "execa";
4
-
5
- // 最新 node 核心包的导入写法
6
- import { fileURLToPath } from "node:url";
7
- import { dirname } from "node:path";
8
-
9
-
10
- export async function getGlobalConfig(type) {
11
- const name = findup("dyp.config.js", { cwd: process.env.PWD });
12
- const dypConfig = await import(name);
13
- if (type) {
14
- return dypConfig["default"][type];
15
- }
16
- return dypConfig["default"];
17
- }
18
-
19
- // 首字母大写
20
- export function strCase(str) {
21
- return str.toLowerCase().replace(/( |^)[a-z]/g, (L) => L.toUpperCase());
22
- }
23
-
24
- // 获取文件名
25
- export function getFilename() {
26
- return fileURLToPath(import.meta.url);
27
- }
28
-
29
- // 获取根路径
30
- export function getDirname() {
31
- return dirname(fileURLToPath(import.meta.url));
32
- }
33
-
34
- export function log(mainMsg, laterMsg) {
35
- return chalkLog("blue", mainMsg, laterMsg);
36
- }
37
-
38
- export function cyanLog(mainMsg, laterMsg = "") {
39
- return chalkLog("cyan", mainMsg, laterMsg);
40
- }
41
-
42
- export function magentaLog(mainMsg, laterMsg = "") {
43
- return chalkLog("magenta", mainMsg, laterMsg);
44
- }
45
-
46
- export function successLog(mainMsg, laterMsg = "") {
47
- return chalkLog("green", mainMsg, laterMsg);
48
- }
49
-
50
- export function warningLog(mainMsg, laterMsg = "") {
51
- return chalkLog("yellow", mainMsg, laterMsg);
52
- }
53
-
54
- export function errorLog(mainMsg, laterMsg = "") {
55
- return chalkLog("red", mainMsg, laterMsg);
56
- }
57
-
58
- export function chalkLog(chalkType, mainMsg, laterMsg = "") {
59
- if (!laterMsg) {
60
- return console.log(chalk[chalkType](`${mainMsg}`));
61
- }
62
- return console.log(chalk[chalkType](`${mainMsg}`), laterMsg);
63
- }
64
-
65
- /**
66
- * 获取最新 commit 提交信息
67
- * git 获取提交信息参考:https://www.cnblogs.com/ruiy/p/15904295.html
68
- * @returns {commitId, commitMsg}
69
- */
70
-
71
- export function getGitInfo() {
72
- const shortCommid = execa.commandSync("git rev-parse --short HEAD");
73
-
74
- const gitComMsg = `git log --pretty=format:“%s” ${shortCommid.stdout} -1`;
75
-
76
- const { stdout, stderr } = execa.commandSync(gitComMsg);
77
-
78
- return {
79
- commitId: shortCommid.stdout,
80
- commitMsg: stdout,
81
- };
82
- }
@@ -1,59 +0,0 @@
1
- ### 需要的变量
2
-
3
- ```txt
4
- WX_COMPANY_ID= 企业ID
5
- WX_APP_ID= 应用ID
6
- WX_APP_SECRET= 应用 Secret
7
-
8
- TIAN_API_KEY= 天行数据 key
9
- ```
10
-
11
- <details><summary>点击查看企业微信的注册步骤的详细示例</summary>
12
-
13
- #### 第一步,注册企业
14
-
15
- 用电脑打开[企业微信官网](https://work.weixin.qq.com/),注册一个企业。有手机号就可以注册,不用营业执照!不用营业执照!不用营业执照!
16
-
17
- #### 第二步,创建应用
18
-
19
- 注册成功后,点「管理企业」进入管理界面,选择「应用管理」 → 「自建」 → 「创建应用」
20
-
21
- ![创建应用-1](images/qiyewx-2.png)
22
-
23
- 应用名称随意填,可见范围选择公司名(或指定组织、个人,建议选择全部,然后在代码里指定用户)。
24
-
25
- ![创建应用-2](images/qiyewx-3.png)
26
-
27
- 指定成员或组织
28
-
29
- ![指定范围](images/qiyewx-3-2.png)
30
-
31
- 创建完成后进入应用详情页,可以得到应用 ID( agentid )①,应用 Secret( secret )②。
32
-
33
- ![创建应用-3](images/qiyewx-3-1.png)
34
-
35
- #### 第三步,获取企业 ID
36
-
37
- 进入「[我的企业](https://work.weixin.qq.com/wework_admin/frame#profile)」页面,拉到最下边,可以得到企业 ID③。
38
-
39
- ![企业ID](images/qiyewx-6.png)
40
-
41
- #### 第四步,推送消息到微信
42
-
43
- 进入「我的企业」 → 「[微信插件](https://work.weixin.qq.com/wework_admin/frame#profile/wxPlugin)」,拉到下边扫描二维码,关注以后即可收到推送的消息。
44
-
45
- ![第四步](images/qiyewx-4.png)
46
-
47
- #### 无法接收到消息的异常情况处理
48
-
49
- PS:如果出现`接口请求正常,企业微信接受消息正常,个人微信无法收到消息`的情况:
50
-
51
- 1. 进入「我的企业」 → 「微信插件」,拉到最下方,勾选 “允许成员在微信插件中接收和回复聊天消息”
52
-
53
- ![异常情况-1](images/qiyewx-5.jpg)
54
-
55
- 2. 在企业微信客户端 「我」 → 「设置」 → 「新消息通知」中关闭 “仅在企业微信中接受消息” 限制条件
56
-
57
- ![异常情况-2](images/qiyewx-5-1.jpg)
58
-
59
- </details>
@@ -1,45 +0,0 @@
1
-
2
-
3
- /**
4
- * @description 根据企业ID、应用secret 获取token
5
- * @returns token
6
- */
7
- import axios from 'axios';
8
- const BASE_URL = 'https://qyapi.weixin.qq.com'
9
-
10
- // 获取token
11
- export async function getToken({ id, secret }) {
12
- try {
13
- const response = await axios({
14
- url: `${BASE_URL}/cgi-bin/gettoken?corpid=${id}&corpsecret=${secret}`,
15
- method: 'GET',
16
- headers: {
17
- 'Content-Type': 'application/json',
18
- },
19
- })
20
- return response.data.access_token
21
- }
22
- catch (error) {
23
- console.log(error)
24
- return ''
25
- }
26
- }
27
-
28
- /**
29
- * 发送消息通知到企业微信
30
- *
31
- * api示列: https://developer.work.weixin.qq.com/tutorial/application-message/3
32
- * api: https://developer.work.weixin.qq.com/document/path/90372
33
- */
34
- export const postMsg = async(accessToken, config) => {
35
- const response = await axios({
36
- url: `${BASE_URL}/cgi-bin/message/send?access_token=${accessToken}`,
37
- method: 'POST',
38
- data: {
39
- touser: config.touser || '@all',
40
- ...config,
41
- },
42
- })
43
- return response.data
44
- }
45
-
@@ -1,62 +0,0 @@
1
- /**
2
- * @name WXbot
3
- * @description 获取环境变量参数,执行微信消息通知函数
4
- */
5
- import { getGlobalConfig, errorLog, successLog, } from "../utils/index.js";
6
- import { getToken, postMsg } from "./api.js";
7
-
8
- async function getWxServerConfig() {
9
- return await getGlobalConfig('wxServerConfig');
10
- }
11
-
12
- // 主函数
13
- export async function wxNotify(config, wxServerConfig) {
14
- let configs= {};
15
- if (wxServerConfig && Object.keys(wxServerConfig).length !== 0) {
16
- configs = wxServerConfig;
17
- } else {
18
- configs = await getWxServerConfig();
19
- }
20
-
21
- const { WX_COMPANY_ID, WX_APP_ID, WX_APP_SECRET } = configs ;
22
-
23
- try {
24
- // 获取token
25
- const accessToken = await getToken({
26
- id: WX_COMPANY_ID,
27
- secret: WX_APP_SECRET
28
- });
29
-
30
- // 发送消息
31
- const defaultConfig = {
32
- msgtype: "text",
33
- agentid: WX_APP_ID,
34
- ...config
35
- };
36
- const option = { ...defaultConfig, ...config };
37
- const res = await postMsg(accessToken, option);
38
- successLog("wx:信息发送成功!", res);
39
- return true;
40
- } catch (error) {
41
- errorLog("wx:信息发送失败!", error);
42
- return false;
43
- }
44
- }
45
-
46
- // wxNotify({
47
- // msgtype: "text",
48
- // text: {
49
- // content: `${moment().format('lll')}`
50
- // }
51
- // });
52
-
53
- // wxNotify({
54
- // msgtype: "textcard",
55
- // textcard: {
56
- // title: "应用发布提醒",
57
- // description:
58
- // '<div class="gray">2016年9月26日</div> <div class="normal">恭喜你抽中iPhone 7一台,领奖码:xxxx</div><div class="highlight">请于2016年10月10日前联系行政同事领取</div>',
59
- // url: "www.baidu.com",
60
- // btntxt: "更多"
61
- // }
62
- // });