@widget-js/cli 1.0.4 → 1.0.6

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.
@@ -0,0 +1,20 @@
1
+ module.exports = {
2
+ env: {
3
+ test: {
4
+ presets: [
5
+ '@babel/preset-env'
6
+ ]
7
+ },
8
+ build: {
9
+ presets: [
10
+ [
11
+ '@babel/preset-env',
12
+ {
13
+ modules: false,
14
+ loose: true
15
+ }
16
+ ]
17
+ ]
18
+ }
19
+ }
20
+ }
package/bin/widget.js CHANGED
@@ -1,217 +1,30 @@
1
- import inquirer from "inquirer";
2
- import {chalk} from "@vue/cli-shared-utils";
3
- import fs from "fs";
4
- import path from "path";
5
- import {snakeCase, paramCase} from "change-case";
6
- import {fileURLToPath} from 'url';
7
- import shell from 'shelljs';
8
- import promptChecker from "../lib/promts/promptChecker.js";
9
- import {exit, exitProcess} from "@vue/cli-shared-utils/lib/exit.js";
10
- import ejs from "ejs";
11
- import consola from "consola";
1
+ import {program} from 'commander';
2
+
3
+ import packageJson from '../package.json' assert {type: 'json'};
4
+ import createWidget from "../lib/createWidget.js";
5
+ import release from "../lib/release/release.js";
6
+
7
+ program
8
+ .version(`@widget-js/cli ${packageJson.version}`)
9
+ .usage('<command> [options]')
10
+ program
11
+ .command('create')
12
+ .description('创建新的组件')
13
+ .action(async () => {
14
+ await createWidget()
15
+ })
16
+ program
17
+ .command('release')
18
+ .description('发布应用,仅内部使用')
19
+ .action(async () => {
20
+ await release()
21
+ })
22
+
23
+ //TODO init 初始化项目
24
+ //TODO publish 发布
25
+ //TODO delete 删除
26
+ program.parse(process.argv);
12
27
 
13
28
 
14
- let widgetJson = path.join(process.cwd(), "widget.json");
15
- if (!fs.existsSync(widgetJson)) {
16
- consola.error("没有在根目录找到widget.json文件")
17
- exit();
18
- }
19
29
 
20
- let widgetPackage = JSON.parse(fs.readFileSync(widgetJson));
21
-
22
- let widgetFolder = path.join(process.cwd(), "./src/widgets");
23
- let devOptions = widgetPackage["devOptions"] ?? {};
24
- if (devOptions["folder"]) {
25
- widgetFolder = devOptions["folder"];
26
- consola.info(`组件路径:${widgetFolder}`);
27
- } else {
28
- consola.info(`没有配置devOptions.folder,使用默认路径${widgetFolder}`);
29
- }
30
-
31
- if (!fs.existsSync(widgetFolder)) {
32
- fs.mkdirSync(widgetFolder, {recursive: true});
33
- }
34
-
35
- const __filename = fileURLToPath(import.meta.url);
36
- const __dirname = path.dirname(__filename);
37
-
38
- Array.prototype.max = function () {
39
- return Math.max.apply(null, this);
40
- };
41
-
42
- Array.prototype.min = function () {
43
- return Math.min.apply(null, this);
44
- };
45
-
46
- const getMiddleValue = (arr) => {
47
- if (arr.length === 1) {
48
- return arr[0];
49
- } else if (arr.length === 2) {
50
- return arr.max();
51
- } else {
52
- const max = arr.max();
53
- const min = arr.min();
54
- const sum = arr[0] + arr[1] + arr[2];
55
- return sum - max - min;
56
- }
57
- }
58
-
59
- let name = await promptChecker({
60
- type: "input",
61
- name: 'name',
62
- message: chalk.blue("请输入组件名(大驼峰式),如:CountdownClock")
63
- }, (answer) => {
64
- const name = answer.name;
65
- if (name == null || name === '') {
66
- consola.log(chalk.red('组件名不能为空'));
67
- return false;
68
- }
69
- return true;
70
- })
71
-
72
- consola.log(chalk.green(name))
73
-
74
- let title = await promptChecker({
75
- type: "input",
76
- name: 'title',
77
- message: chalk.blue("请输入组件标题,如:倒计时")
78
- })
79
- consola.log(chalk.green(title))
80
-
81
- let answerW = await promptChecker({
82
- type: "checkbox",
83
- name: 'w',
84
- message: chalk.blue("请选择组件宽度,最多选3个,例如选中2,4,6,代表组件最小宽为2,默认宽为4,最大宽为6,单选代表不可拉伸"),
85
- choices: [1, 2, 3, 4, 5, 6]
86
- }, (answer) => {
87
- if (answer.w.length === 0) {
88
- consola.log(chalk.red('宽度必须选择'));
89
- return false;
90
- }
91
-
92
- if (answer.w.length > 3) {
93
- consola.log(chalk.red('宽度最多选择3个'));
94
- return false;
95
- }
96
- return true;
97
- })
98
- consola.log(chalk.green(answerW))
99
-
100
- let answerH = await promptChecker({
101
- type: "checkbox",
102
- name: 'h',
103
- message: chalk.blue("请选择组件高度,最多选3个,例如选中1,2,代表组件最小高为1,默认高为2,最大高为2,单选代表不可拉伸"),
104
- choices: [1, 2, 3, 4, 5, 6]
105
- }, (answer) => {
106
- if (answer.h.length === 0) {
107
- consola.log(chalk.red('高度必须选择'));
108
- return false;
109
- }
110
-
111
- if (answer.h.length > 3) {
112
- consola.log(chalk.red('高度最多选择3个'));
113
- return false;
114
- }
115
- return true;
116
- })
117
-
118
- consola.log(chalk.green(answerH))
119
-
120
- let configurable = await promptChecker({
121
- type: "confirm",
122
- name: 'configurable',
123
- message: chalk.blue("组件是否可配置,例如修改背景颜色,字体大小等")
124
- })
125
-
126
- consola.log(chalk.green(configurable))
127
-
128
- const width = getMiddleValue(answerW);
129
- const height = getMiddleValue(answerH);
130
- const minWidth = answerW.min();
131
- const maxWidth = answerW.max();
132
- const minHeight = answerH.min();
133
- const maxHeight = answerH.max();
134
- const snakeCaseName = snakeCase(name);
135
- const paramCaseName = paramCase(name);
136
- const packageName = "com.wisdom.widgets." + snakeCaseName;
137
-
138
- const widgetDir = path.join(widgetFolder, paramCaseName)
139
- if (!fs.existsSync(widgetDir)) {
140
- fs.mkdirSync(widgetDir);
141
- } else {
142
- let answer = await inquirer.prompt([{
143
- type: 'confirm',
144
- name: 'override',
145
- message: chalk.red('组件名已存在,是否继续?')
146
- }])
147
- if (!answer.override) {
148
- exitProcess();
149
- }
150
- }
151
-
152
- const renderOptions = {
153
- name: name,
154
- snakeCaseName: snakeCaseName,
155
- paramCaseName: paramCaseName,
156
- packageName: packageName,
157
- title: title,
158
- configurable: configurable,
159
- width: width,
160
- height: height,
161
- maxWidth: maxWidth,
162
- minHeight: minHeight,
163
- maxHeight: maxHeight,
164
- minWidth: minWidth
165
- }
166
-
167
- function renderToFile(templateFile, outputFile, renderOptions) {
168
- const defineTemplatePath = path.join(__dirname, '../template', templateFile)
169
- let defineTemplate = fs.readFileSync(defineTemplatePath, 'utf8');
170
- fs.writeFileSync(outputFile, ejs.render(defineTemplate, renderOptions))
171
- }
172
-
173
- const widgetDefineFile = path.resolve(widgetDir, `${name}.widget.ts`)
174
- const widgetFile = path.resolve(widgetDir, `${name}Widget.vue`);
175
- const widgetViewFile = path.resolve(widgetDir, `${name}WidgetView.vue`)
176
- const widgetRoutesFile = path.resolve(widgetDir, `${name}WidgetRoutes.ts`)
177
-
178
- renderToFile('WidgetDefine.ejs', widgetDefineFile, renderOptions);
179
- renderToFile('Widget.ejs', widgetFile, renderOptions);
180
- renderToFile('WidgetView.ejs', widgetViewFile, renderOptions);
181
- renderToFile('WidgetRoutes.ejs', widgetRoutesFile, renderOptions);
182
- if (configurable) {
183
- const configFile = path.resolve(widgetDir, `${name}ConfigView.vue`)
184
- renderToFile('WidgetConfig.ejs', configFile, renderOptions);
185
- }
186
- if (devOptions["useStorybook"]) {
187
- const storiesFile = path.resolve(widgetDir, `${name}Widget.stories.ts`)
188
- renderToFile('stories.ejs', storiesFile, renderOptions);
189
- }
190
-
191
- // 注册路由
192
- const routeFile = path.join(widgetFolder, 'widget-router.ts');
193
- let routeContent;
194
- if (fs.existsSync(routeFile)) {
195
- routeContent = fs.readFileSync(routeFile, 'utf8');
196
- } else {
197
- routeContent = fs.readFileSync(path.join(__dirname, "../template/widget-router.ts"), 'utf8');
198
- }
199
- const importRouteStr = `import ${name}WidgetRoutes from "./${paramCaseName}/${name}WidgetRoutes";`
200
- const routeStr = `...${name}WidgetRoutes,`
201
- if (!routeContent.includes(importRouteStr)) {
202
- routeContent = routeContent.replaceAll("//FBI WANING! IMPORT PLACE", `${importRouteStr}\n//FBI WANING! IMPORT PLACE`)
203
- }
204
- if (!routeContent.includes(routeStr)) {
205
- routeContent = routeContent.replaceAll("//FBI WANING! ROUTE PLACE", `${routeStr}\n //FBI WANING! ROUTE PLACE`)
206
- }
207
-
208
- fs.writeFileSync(routeFile, routeContent)
209
-
210
- //添加到版本控制
211
- let gitAdd = `git add ${widgetDir}`;
212
- consola.info(chalk.grey(gitAdd))
213
- shell.exec(gitAdd);
214
- consola.log("=================")
215
- consola.info(`已创建组件:${widgetDir}`)
216
- consola.success("Happy coding!")
217
30
 
package/jest.config.js ADDED
@@ -0,0 +1,14 @@
1
+ module.exports = {
2
+ roots: ['<rootDir>/test'],
3
+ testMatch: [
4
+ '**/__tests__/**/*.+(ts|tsx|js)',
5
+ '**/?(*.)+(spec|test).+(ts|tsx|js)',
6
+ ],
7
+ transform: {
8
+ '^.+\\.(ts|tsx)$': ['ts-jest',{
9
+ tsconfig: 'tsconfig.json'
10
+ }],
11
+ '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
12
+ './config/fileTransformer.js',
13
+ }
14
+ }
@@ -0,0 +1,217 @@
1
+ import path from "path";
2
+ import fs from "fs";
3
+ import consola from "consola";
4
+ import {exit, exitProcess} from "@vue/cli-shared-utils/lib/exit.js";
5
+ import {fileURLToPath} from "url";
6
+ import promptChecker from "./promts/promptChecker.js";
7
+ import {chalk} from "@vue/cli-shared-utils";
8
+ import {paramCase, snakeCase} from "change-case";
9
+ import inquirer from "inquirer";
10
+ import ejs from "ejs";
11
+ import shell from "shelljs";
12
+
13
+ export default async function createWidget() {
14
+ let widgetJson = path.join(process.cwd(), "widget.json");
15
+ if (!fs.existsSync(widgetJson)) {
16
+ consola.error("没有在根目录找到widget.json文件")
17
+ exit();
18
+ }
19
+
20
+ let widgetPackage = JSON.parse(fs.readFileSync(widgetJson));
21
+
22
+ let widgetFolder = path.join(process.cwd(), "./src/widgets");
23
+ let devOptions = widgetPackage["devOptions"] ?? {};
24
+ if (devOptions["folder"]) {
25
+ widgetFolder = devOptions["folder"];
26
+ consola.info(`组件路径:${widgetFolder}`);
27
+ } else {
28
+ consola.info(`没有配置devOptions.folder,使用默认路径${widgetFolder}`);
29
+ }
30
+
31
+ if (!fs.existsSync(widgetFolder)) {
32
+ fs.mkdirSync(widgetFolder, {recursive: true});
33
+ }
34
+
35
+ const __filename = fileURLToPath(import.meta.url);
36
+ const __dirname = path.dirname(__filename);
37
+
38
+ Array.prototype.max = function () {
39
+ return Math.max.apply(null, this);
40
+ };
41
+
42
+ Array.prototype.min = function () {
43
+ return Math.min.apply(null, this);
44
+ };
45
+
46
+ const getMiddleValue = (arr) => {
47
+ if (arr.length === 1) {
48
+ return arr[0];
49
+ } else if (arr.length === 2) {
50
+ return arr.max();
51
+ } else {
52
+ const max = arr.max();
53
+ const min = arr.min();
54
+ const sum = arr[0] + arr[1] + arr[2];
55
+ return sum - max - min;
56
+ }
57
+ }
58
+
59
+ let name = await promptChecker({
60
+ type: "input",
61
+ name: 'name',
62
+ message: chalk.blue("请输入组件名(大驼峰式),如:CountdownClock")
63
+ }, (answer) => {
64
+ const name = answer.name;
65
+ if (name == null || name === '') {
66
+ consola.log(chalk.red('组件名不能为空'));
67
+ return false;
68
+ }
69
+ return true;
70
+ })
71
+
72
+ consola.log(chalk.green(name))
73
+
74
+ let title = await promptChecker({
75
+ type: "input",
76
+ name: 'title',
77
+ message: chalk.blue("请输入组件标题,如:倒计时")
78
+ })
79
+ consola.log(chalk.green(title))
80
+
81
+ let answerW = await promptChecker({
82
+ type: "checkbox",
83
+ name: 'w',
84
+ message: chalk.blue("请选择组件宽度,最多选3个,例如选中2,4,6,代表组件最小宽为2,默认宽为4,最大宽为6,单选代表不可拉伸"),
85
+ choices: [1, 2, 3, 4, 5, 6]
86
+ }, (answer) => {
87
+ if (answer.w.length === 0) {
88
+ consola.log(chalk.red('宽度必须选择'));
89
+ return false;
90
+ }
91
+
92
+ if (answer.w.length > 3) {
93
+ consola.log(chalk.red('宽度最多选择3个'));
94
+ return false;
95
+ }
96
+ return true;
97
+ })
98
+ consola.log(chalk.green(answerW))
99
+
100
+ let answerH = await promptChecker({
101
+ type: "checkbox",
102
+ name: 'h',
103
+ message: chalk.blue("请选择组件高度,最多选3个,例如选中1,2,代表组件最小高为1,默认高为2,最大高为2,单选代表不可拉伸"),
104
+ choices: [1, 2, 3, 4, 5, 6]
105
+ }, (answer) => {
106
+ if (answer.h.length === 0) {
107
+ consola.log(chalk.red('高度必须选择'));
108
+ return false;
109
+ }
110
+
111
+ if (answer.h.length > 3) {
112
+ consola.log(chalk.red('高度最多选择3个'));
113
+ return false;
114
+ }
115
+ return true;
116
+ })
117
+
118
+ consola.log(chalk.green(answerH))
119
+
120
+ let configurable = await promptChecker({
121
+ type: "confirm",
122
+ name: 'configurable',
123
+ message: chalk.blue("组件是否可配置,例如修改背景颜色,字体大小等")
124
+ })
125
+
126
+ consola.log(chalk.green(configurable))
127
+
128
+ const width = getMiddleValue(answerW);
129
+ const height = getMiddleValue(answerH);
130
+ const minWidth = answerW.min();
131
+ const maxWidth = answerW.max();
132
+ const minHeight = answerH.min();
133
+ const maxHeight = answerH.max();
134
+ const snakeCaseName = snakeCase(name);
135
+ const paramCaseName = paramCase(name);
136
+ const packageName = "com.wisdom.widgets." + snakeCaseName;
137
+
138
+ const widgetDir = path.join(widgetFolder, paramCaseName)
139
+ if (!fs.existsSync(widgetDir)) {
140
+ fs.mkdirSync(widgetDir);
141
+ } else {
142
+ let answer = await inquirer.prompt([{
143
+ type: 'confirm',
144
+ name: 'override',
145
+ message: chalk.red('组件名已存在,是否继续?')
146
+ }])
147
+ if (!answer.override) {
148
+ exitProcess();
149
+ }
150
+ }
151
+
152
+ const renderOptions = {
153
+ name: name,
154
+ snakeCaseName: snakeCaseName,
155
+ paramCaseName: paramCaseName,
156
+ packageName: packageName,
157
+ title: title,
158
+ configurable: configurable,
159
+ width: width,
160
+ height: height,
161
+ maxWidth: maxWidth,
162
+ minHeight: minHeight,
163
+ maxHeight: maxHeight,
164
+ minWidth: minWidth
165
+ }
166
+
167
+ function renderToFile(templateFile, outputFile, renderOptions) {
168
+ const defineTemplatePath = path.join(__dirname, '../template', templateFile)
169
+ let defineTemplate = fs.readFileSync(defineTemplatePath, 'utf8');
170
+ fs.writeFileSync(outputFile, ejs.render(defineTemplate, renderOptions))
171
+ }
172
+
173
+ const widgetDefineFile = path.resolve(widgetDir, `${name}.widget.ts`)
174
+ const widgetFile = path.resolve(widgetDir, `${name}Widget.vue`);
175
+ const widgetViewFile = path.resolve(widgetDir, `${name}WidgetView.vue`)
176
+ const widgetRoutesFile = path.resolve(widgetDir, `${name}WidgetRoutes.ts`)
177
+
178
+ renderToFile('WidgetDefine.ejs', widgetDefineFile, renderOptions);
179
+ renderToFile('Widget.ejs', widgetFile, renderOptions);
180
+ renderToFile('WidgetView.ejs', widgetViewFile, renderOptions);
181
+ renderToFile('WidgetRoutes.ejs', widgetRoutesFile, renderOptions);
182
+ if (configurable) {
183
+ const configFile = path.resolve(widgetDir, `${name}ConfigView.vue`)
184
+ renderToFile('WidgetConfig.ejs', configFile, renderOptions);
185
+ }
186
+ if (devOptions["useStorybook"]) {
187
+ const storiesFile = path.resolve(widgetDir, `${name}Widget.stories.ts`)
188
+ renderToFile('stories.ejs', storiesFile, renderOptions);
189
+ }
190
+
191
+ // 注册路由
192
+ const routeFile = path.join(widgetFolder, 'widget-router.ts');
193
+ let routeContent;
194
+ if (fs.existsSync(routeFile)) {
195
+ routeContent = fs.readFileSync(routeFile, 'utf8');
196
+ } else {
197
+ routeContent = fs.readFileSync(path.join(__dirname, "../template/widget-router.ts"), 'utf8');
198
+ }
199
+ const importRouteStr = `import ${name}WidgetRoutes from "./${paramCaseName}/${name}WidgetRoutes";`
200
+ const routeStr = `...${name}WidgetRoutes,`
201
+ if (!routeContent.includes(importRouteStr)) {
202
+ routeContent = routeContent.replaceAll("//FBI WANING! IMPORT PLACE", `${importRouteStr}\n//FBI WANING! IMPORT PLACE`)
203
+ }
204
+ if (!routeContent.includes(routeStr)) {
205
+ routeContent = routeContent.replaceAll("//FBI WANING! ROUTE PLACE", `${routeStr}\n //FBI WANING! ROUTE PLACE`)
206
+ }
207
+
208
+ fs.writeFileSync(routeFile, routeContent)
209
+
210
+ //添加到版本控制
211
+ let gitAdd = `git add ${widgetDir}`;
212
+ consola.info(chalk.grey(gitAdd))
213
+ shell.exec(gitAdd);
214
+ consola.log("=================")
215
+ consola.info(`已创建组件:${widgetDir}`)
216
+ consola.success("Happy coding!")
217
+ }
@@ -0,0 +1,47 @@
1
+ import OSS from "ali-oss";
2
+ import {chalk} from "@vue/cli-shared-utils";
3
+ import fs from "fs";
4
+
5
+ let packageData = JSON.parse(fs.readFileSync("./package.json").toString());
6
+ export const AccessKeyID = packageData.oss.id;
7
+ export const AccessKeySecret = packageData.oss.secret;
8
+
9
+ const headers = {
10
+ // 指定Object的存储类型。
11
+ 'x-oss-storage-class': 'Standard',
12
+ // 指定Object的访问权限。
13
+ 'x-oss-object-acl': 'public-read',
14
+ 'x-oss-forbid-overwrite': 'false',
15
+ 'Cache-Control': 'no-cache'
16
+ };
17
+
18
+ const clinet = new OSS({
19
+ // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
20
+ region: 'oss-cn-hangzhou',
21
+ // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
22
+ accessKeyId: AccessKeyID,
23
+ accessKeySecret: AccessKeySecret,
24
+ bucket: 'widget-fun',
25
+ });
26
+
27
+ export async function put(ossPath, file) {
28
+ try {
29
+ // 填写OSS文件完整路径和本地文件的完整路径。OSS文件完整路径中不能包含Bucket名称。
30
+ // 如果本地文件的完整路径中未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
31
+ const result = await clinet.put(ossPath, file, {headers});
32
+ console.log(chalk.green(`上传成功:${file}->${ossPath}`));
33
+ } catch (e) {
34
+ console.log(e);
35
+ }
36
+ }
37
+
38
+ export async function copy(dist, src) {
39
+ try {
40
+ // 填写OSS文件完整路径和本地文件的完整路径。OSS文件完整路径中不能包含Bucket名称。
41
+ // 如果本地文件的完整路径中未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
42
+ const result = await clinet.copy(dist, src, {headers});
43
+ console.log(chalk.green(`复制成功:${src}->${dist}`));
44
+ } catch (e) {
45
+ console.error(e);
46
+ }
47
+ }
@@ -0,0 +1,73 @@
1
+ import {chalk} from "@vue/cli-shared-utils";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import promptChecker from "../promts/promptChecker.js";
5
+ import zipDirectory from "./update-zip.js";
6
+ import {copy, put} from "./oss.js";
7
+
8
+ const packageJSON = JSON.parse(fs.readFileSync('package.json', 'utf-8'))
9
+ const changelogJSON = JSON.parse(fs.readFileSync('changelog.json', 'utf-8'))
10
+ const version = packageJSON["version"]
11
+ const changelog = changelogJSON[version]
12
+
13
+ async function delay(time) {
14
+ return new Promise((resolve, reject) => {
15
+ setTimeout(() => {
16
+ resolve();
17
+ }, time);
18
+ });
19
+ }
20
+
21
+ const release = async () => {
22
+ let needUpdateElectron = await promptChecker({
23
+ type: "confirm",
24
+ name: 'electron',
25
+ message: chalk.blue("用户是否需要更新Electron?")
26
+ });
27
+
28
+ let needUpdateNodeModule = await promptChecker({
29
+ type: "confirm",
30
+ name: 'electron',
31
+ message: chalk.blue("用户是否需要更新node_module?")
32
+ });
33
+
34
+ const versionInfo = {
35
+ version: version,
36
+ releaseNote: changelog,
37
+ updateElectron: needUpdateElectron,
38
+ updateNodeModule: needUpdateNodeModule,
39
+ updateWindowsApi: false,
40
+ downloadLink: ''
41
+ };
42
+
43
+ let installerPath = path.join(`./packaged/widgets-${version}-setup-win-x64.exe`);
44
+ if (!fs.existsSync(installerPath)) {
45
+ installerPath = path.join(`./packaged/electron-${version}-setup-win-x64.exe`);
46
+ }
47
+ const updateZipPath = path.join(`./packaged/update.zip`)
48
+
49
+ console.log(chalk.blue("压缩更新文件中"))
50
+ if (needUpdateNodeModule) {
51
+ await zipDirectory("packaged/win-unpacked/resources/app", updateZipPath);
52
+ } else {
53
+ await zipDirectory("release", updateZipPath);
54
+ }
55
+
56
+ console.log(chalk.blue("上传installer.exe到OSS"))
57
+ await put("version/installer.exe", installerPath)
58
+
59
+ console.log(chalk.blue("上传update.zip到OSS"))
60
+ await put("version/update.zip", updateZipPath)
61
+
62
+ console.log(chalk.blue("更新版本信息"))
63
+ versionInfo.downloadLink = "https://widget-fun.oss-cn-hangzhou.aliyuncs.com/version/update.zip"
64
+ const versionJSON = JSON.stringify(versionInfo, null, 2)
65
+ await put("version/version.json", Buffer.from(versionJSON))
66
+
67
+ copy(`version/history/${version}.exe`, "version/installer.exe")
68
+ copy(`version/history/update-${version}.zip`, "version/update.zip")
69
+
70
+ console.log(chalk.yellow(versionJSON))
71
+ }
72
+
73
+ export default release;
@@ -0,0 +1,20 @@
1
+ import fs from "fs";
2
+ import archiver from "archiver";
3
+
4
+
5
+ function zipDirectory(sourceDir, outPath) {
6
+ const archive = archiver('zip', { zlib: { level: 9 }});
7
+ const stream = fs.createWriteStream(outPath);
8
+
9
+ return new Promise((resolve, reject) => {
10
+ archive
11
+ .directory(sourceDir, false)
12
+ .on('error', err => reject(err))
13
+ .pipe(stream)
14
+ ;
15
+
16
+ stream.on('close', () => resolve());
17
+ archive.finalize();
18
+ });
19
+ }
20
+ export default zipDirectory;
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@widget-js/cli",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "main": "bin/widget.js",
5
5
  "author": "Neo Fu",
6
6
  "license": "MIT",
7
- "type": "module",
8
7
  "private": false,
9
8
  "bin": {
10
9
  "widget": "bin/widget.js"
11
10
  },
11
+ "type": "module",
12
12
  "publishConfig": {
13
13
  "access": "public"
14
14
  },
@@ -17,14 +17,41 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "@vue/cli-shared-utils": "^5.0.8",
20
+ "@widget-js/core": "^0.1.14",
21
+ "ali-oss": "^6.17.1",
22
+ "archiver": "^5.3.1",
23
+ "chalk": "^5.2.0",
20
24
  "change-case": "^4.1.2",
25
+ "commander": "^9.4.1",
21
26
  "consola": "^2.15.3",
22
27
  "ejs": "^3.1.8",
23
28
  "inquirer": "^9.1.4",
24
- "shelljs": "^0.8.5"
29
+ "shelljs": "^0.8.5",
30
+ "ws": "^8.11.0"
31
+ },
32
+ "devDependencies": {
33
+ "@babel/cli": "^7.19.3",
34
+ "@babel/core": "^7.20.2",
35
+ "@babel/node": "^7.20.2",
36
+ "@babel/preset-env": "^7.20.2",
37
+ "@types/ejs": "latest",
38
+ "@types/inquirer": "latest",
39
+ "@types/jest": "^29.2.3",
40
+ "@types/node": "^18.11.13",
41
+ "@types/shelljs": "latest",
42
+ "pinst": "^3.0.0",
43
+ "ts-jest": "^29.0.3",
44
+ "ts-loader": "^9.4.1",
45
+ "typescript": "^4.9.3",
46
+ "webpack": "^5.75.0",
47
+ "webpack-cli": "^5.0.0"
25
48
  },
26
- "devDependencies": {},
27
49
  "scripts": {
28
- "widget": "node ./bin/widget.js"
50
+ "widget": "node ./bin/widget.js",
51
+ "build": "npm run build:esm && npm run build:types && npm run build:cjs && npm run build:umd",
52
+ "build:cjs": "node tools/cleanup cjs && tsc -p config/tsconfig.cjs.json",
53
+ "build:esm": "node tools/cleanup esm && tsc -p config/tsconfig.esm.json",
54
+ "build:umd": "node tools/cleanup umd && webpack --config config/webpack.config.js",
55
+ "build:types": "node tools/cleanup types && tsc -p config/tsconfig.types.json"
29
56
  }
30
57
  }
@@ -0,0 +1,29 @@
1
+ /* eslint-disable */
2
+ const fs = require('fs')
3
+ const Path = require('path')
4
+ /* eslint-enable */
5
+
6
+ const deleteFolderRecursive = (path) => {
7
+ if (fs.existsSync(path)) {
8
+ fs.readdirSync(path).forEach((file) => {
9
+ const curPath = Path.join(path, file)
10
+ if (fs.lstatSync(curPath).isDirectory()) {
11
+ deleteFolderRecursive(curPath)
12
+ } else {
13
+ fs.unlinkSync(curPath)
14
+ }
15
+ })
16
+ fs.rmdirSync(path)
17
+ }
18
+ }
19
+
20
+ const folder = process.argv.slice(2)[0]
21
+
22
+ if (folder) {
23
+ deleteFolderRecursive(Path.join(__dirname, '../dist', folder))
24
+ } else {
25
+ deleteFolderRecursive(Path.join(__dirname, '../dist/cjs'))
26
+ deleteFolderRecursive(Path.join(__dirname, '../dist/esm'))
27
+ deleteFolderRecursive(Path.join(__dirname, '../dist/umd'))
28
+ deleteFolderRecursive(Path.join(__dirname, '../dist/types'))
29
+ }
@@ -0,0 +1,25 @@
1
+ /* eslint-disable */
2
+ const fs = require('fs')
3
+ const Path = require('path')
4
+ const fileName = '../package.json'
5
+ const file = require(fileName)
6
+ /* eslint-enable */
7
+
8
+ const args = process.argv.slice(2)
9
+
10
+ for (let i = 0, l = args.length; i < l; i++) {
11
+ if (i % 2 === 0) {
12
+ file[args[i]] = args[i + 1]
13
+ }
14
+ }
15
+
16
+ fs.writeFile(
17
+ Path.join(__dirname, fileName),
18
+ JSON.stringify(file, null, 2),
19
+ (err) => {
20
+ if (err) {
21
+ return console.log(err)
22
+ }
23
+ console.log('Writing to ' + fileName)
24
+ }
25
+ )
package/tsconfig.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "compilerOptions": {
3
+ /* Visit https://aka.ms/tsconfig.json to read more about this file */
4
+
5
+ /* Basic Options */
6
+ // "incremental": true, /* Enable incremental compilation */
7
+ "target": "ESNext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
8
+ // "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
9
+ // "lib": [], /* Specify library files to be included in the compilation. */
10
+ // "allowJs": true, /* Allow javascript files to be compiled. */
11
+ // "checkJs": true, /* Report errors in .js files. */
12
+ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
13
+ // "declaration": true, /* Generates corresponding '.d.ts' file. */
14
+ // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
15
+ // "sourceMap": true, /* Generates corresponding '.map' file. */
16
+ // "outFile": "./", /* Concatenate and emit output to single file. */
17
+ // "outDir": "./", /* Redirect output structure to the directory. */
18
+ // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
19
+ // "composite": true, /* Enable project compilation */
20
+ // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
21
+ // "removeComments": true, /* Do not emit comments to output. */
22
+ // "noEmit": true, /* Do not emit outputs. */
23
+ // "importHelpers": true, /* Import emit helpers from 'tslib'. */
24
+ // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
25
+ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
26
+
27
+ /* Strict Type-Checking Options */
28
+ "strict": true /* Enable all strict type-checking options. */,
29
+ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
30
+ // "strictNullChecks": true, /* Enable strict null checks. */
31
+ // "strictFunctionTypes": true, /* Enable strict checking of function types. */
32
+ // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
33
+ // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
34
+ // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
35
+ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
36
+
37
+ /* Additional Checks */
38
+ // "noUnusedLocals": true, /* Report errors on unused locals. */
39
+ // "noUnusedParameters": true, /* Report errors on unused parameters. */
40
+ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
41
+ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
42
+
43
+ /* Module Resolution Options */
44
+ "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
45
+ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
46
+ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
47
+ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
48
+ // "typeRoots": [], /* List of folders to include type definitions from. */
49
+ /* Type declaration files to be included in compilation. */
50
+ // "types": ["element-plus/global"],
51
+ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
52
+ // "resolveJsonModule": true,
53
+ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
54
+ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
55
+ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
56
+
57
+ /* Source Map Options */
58
+ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
59
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
60
+ // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
61
+ // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
62
+
63
+ /* Experimental Options */
64
+ // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
65
+ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
66
+
67
+ /* Advanced Options */
68
+
69
+ /* Skip type checking of declaration files. */
70
+ "skipLibCheck": true,
71
+ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
72
+ },
73
+ "include": ["src/**/*"],
74
+ }