@liuli-util/cli 3.20.2 → 3.22.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +22 -0
- package/README.md +69 -25
- package/README.zh-CN.md +7 -7
- package/package.json +40 -36
- package/src/commands/deploy/DeployService.ts +20 -2
- package/src/commands/deploy/__tests__/DeployService.test.ts +23 -4
- package/src/commands/esbuild/ESBuildProgram.ts +5 -9
- package/src/commands/esbuild/__tests__/ESBuildProgram.test.ts +2 -2
- package/src/commands/esbuild/util/autoExternal.ts +22 -0
- package/src/commands/esbuild/util/env.ts +67 -0
- package/src/commands/esbuild/util/index.ts +10 -0
- package/src/commands/esbuild/util/log.ts +20 -0
- package/src/commands/esbuild/util/metafile.ts +17 -0
- package/src/commands/esbuild/util/nativeNodeModules.ts +43 -0
- package/src/commands/esbuild/util/nodeExternal.ts +16 -0
- package/src/commands/esbuild/util/raw.ts +27 -0
- package/src/commands/esbuild/util/resolve.ts +22 -0
- package/src/commands/esbuild/util/sideEffect.ts +29 -0
- package/src/commands/esbuild/util/userJS.ts +38 -0
- package/templates/cli/package.json +35 -33
- package/templates/lib/package.json +24 -19
- package/dist/PathUtil.d.ts +0 -7
- package/dist/PathUtil.d.ts.map +0 -1
- package/dist/bin.d.ts +0 -2
- package/dist/bin.d.ts.map +0 -1
- package/dist/bin.js +0 -171
- package/dist/bin.js.map +0 -7
- package/dist/commands/deploy/DeployService.d.ts +0 -70
- package/dist/commands/deploy/DeployService.d.ts.map +0 -1
- package/dist/commands/deploy/deploy.d.ts +0 -3
- package/dist/commands/deploy/deploy.d.ts.map +0 -1
- package/dist/commands/deploy/index.d.ts +0 -3
- package/dist/commands/deploy/index.d.ts.map +0 -1
- package/dist/commands/deploy/util/PromiseUtil.d.ts +0 -14
- package/dist/commands/deploy/util/PromiseUtil.d.ts.map +0 -1
- package/dist/commands/deploy/util/createArchive.d.ts +0 -10
- package/dist/commands/deploy/util/createArchive.d.ts.map +0 -1
- package/dist/commands/deploy/util/execPromise.d.ts +0 -4
- package/dist/commands/deploy/util/execPromise.d.ts.map +0 -1
- package/dist/commands/deploy/util/validate.d.ts +0 -8
- package/dist/commands/deploy/util/validate.d.ts.map +0 -1
- package/dist/commands/deploy/util/wait.d.ts +0 -9
- package/dist/commands/deploy/util/wait.d.ts.map +0 -1
- package/dist/commands/esbuild/ESBuildProgram.d.ts +0 -83
- package/dist/commands/esbuild/ESBuildProgram.d.ts.map +0 -1
- package/dist/commands/esbuild/index.d.ts +0 -3
- package/dist/commands/esbuild/index.d.ts.map +0 -1
- package/dist/commands/esbuild/util/debounce.d.ts +0 -15
- package/dist/commands/esbuild/util/debounce.d.ts.map +0 -1
- package/dist/commands/esbuild/util/esbuildPlugins.d.ts +0 -32
- package/dist/commands/esbuild/util/esbuildPlugins.d.ts.map +0 -1
- package/dist/commands/esbuild/util/getPkgGlobalName.d.ts +0 -6
- package/dist/commands/esbuild/util/getPkgGlobalName.d.ts.map +0 -1
- package/dist/commands/generate/GenerateProgram.d.ts +0 -18
- package/dist/commands/generate/GenerateProgram.d.ts.map +0 -1
- package/dist/commands/generate/index.d.ts +0 -3
- package/dist/commands/generate/index.d.ts.map +0 -1
- package/dist/commands/sync/SyncProgram.d.ts +0 -15
- package/dist/commands/sync/SyncProgram.d.ts.map +0 -1
- package/dist/commands/sync/index.d.ts +0 -3
- package/dist/commands/sync/index.d.ts.map +0 -1
- package/dist/commands/sync/when.d.ts +0 -21
- package/dist/commands/sync/when.d.ts.map +0 -1
- package/dist/index.d.ts +0 -4
- package/dist/index.d.ts.map +0 -1
- package/dist/index.esm.js +0 -8
- package/dist/index.esm.js.map +0 -7
- package/dist/index.js +0 -8
- package/dist/index.js.map +0 -7
- package/dist/utils/AsyncArray.d.ts +0 -21
- package/dist/utils/AsyncArray.d.ts.map +0 -1
- package/dist/utils/appendScript.d.ts +0 -7
- package/dist/utils/appendScript.d.ts.map +0 -1
- package/dist/utils/arrayToMap.d.ts +0 -3
- package/dist/utils/arrayToMap.d.ts.map +0 -1
- package/dist/utils/findParent.d.ts +0 -8
- package/dist/utils/findParent.d.ts.map +0 -1
- package/dist/utils/index.d.ts +0 -5
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/nodeCacheDir.d.ts +0 -2
- package/dist/utils/nodeCacheDir.d.ts.map +0 -1
- package/src/commands/esbuild/__tests__/.temp/package.json +0 -1
- package/src/commands/esbuild/__tests__/.temp/src/index.ts +0 -1
- package/src/commands/esbuild/util/__tests__/.temp/index.js +0 -1
- package/src/commands/esbuild/util/__tests__/esbuildPlugins.test.ts +0 -52
- package/src/commands/esbuild/util/esbuildPlugins.ts +0 -196
- package/src/commands/generate/__tests__/.temp/README.md +0 -1
- package/src/commands/generate/__tests__/.temp/package.json +0 -3
- package/src/commands/generate/__tests__/.temp/test-cli/CHANGELOG.md +0 -1
- package/src/commands/generate/__tests__/.temp/test-cli/README.md +0 -1
- package/src/commands/generate/__tests__/.temp/test-cli/bin.js +0 -3
- package/src/commands/generate/__tests__/.temp/test-cli/package.json +0 -33
- package/src/commands/generate/__tests__/.temp/test-cli/src/bin.ts +0 -13
- package/src/commands/generate/__tests__/.temp/test-cli/src/index.ts +0 -1
- package/src/commands/generate/__tests__/.temp/test-cli/tsconfig.json +0 -28
- package/src/commands/sync/__tests__/.temp/package.json +0 -16
- package/wallaby.conf.js +0 -3
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,27 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 3.21.0
|
4
|
+
|
5
|
+
- feat: 支持配置增量更新,将部署 gh-pages 的默认行为修改为清理 dest
|
6
|
+
|
7
|
+
## 3.20.2
|
8
|
+
|
9
|
+
- fix: 修复使用 boolean 类型无法设置默认为 true 的问题
|
10
|
+
|
11
|
+
## 3.20.1
|
12
|
+
|
13
|
+
- fix: 修复 liuli-cli generate 命令行参数声明的问题
|
14
|
+
|
15
|
+
## 3.20.0
|
16
|
+
|
17
|
+
- feat: 支持以非交互式的方式创建模板项目
|
18
|
+
- fix: 恢复错误被删除的 userjs 插件
|
19
|
+
- feat: 添加一些 esbuild 插件
|
20
|
+
|
21
|
+
## 3.19.2
|
22
|
+
|
23
|
+
- fix: 修复拉取项目时没有指定参数 --allow-unrelated-histories 的问题
|
24
|
+
|
3
25
|
## 3.19.1
|
4
26
|
|
5
27
|
- fix: 修复同步 eslint+simple hooks 错误处理 css 文件的问题
|
package/README.md
CHANGED
@@ -2,50 +2,94 @@
|
|
2
2
|
|
3
3
|
> [中文](https://github.com/rxliuli/liuli-tools/tree/master/apps/liuli-cli/README.zh-CN.md)
|
4
4
|
|
5
|
-
A zero-configuration CLI
|
5
|
+
A zero-configuration CLI for packaging libraries and CLI applications.
|
6
6
|
|
7
|
-
## Getting
|
7
|
+
## Getting Started
|
8
8
|
|
9
9
|
### Install
|
10
10
|
|
11
11
|
```sh
|
12
|
-
|
13
|
-
|
12
|
+
pnpm i -D @liuli-util/cli # Local installation
|
13
|
+
pnpm i -g @liuli-util/cli # global install
|
14
14
|
```
|
15
15
|
|
16
|
-
###
|
16
|
+
### Packages
|
17
17
|
|
18
18
|
```sh
|
19
|
-
|
20
|
-
|
19
|
+
liuli-cli build lib # Package the library
|
20
|
+
liuli-cli build cli # Package cli references
|
21
21
|
```
|
22
22
|
|
23
|
-
>
|
23
|
+
> Adding the `-w` option starts the rollup monitoring mode, the dist/ will not be compressed and the dependencies will not be added to the bundle.
|
24
24
|
|
25
|
-
![
|
25
|
+
![watchdog mode](https://liuli.dev/images/liuli-cli%20%E7%9B%91%E8%A7%86%E6%A8%A1%E5%BC%8F.gif)
|
26
26
|
|
27
27
|
### Generate
|
28
28
|
|
29
29
|
```sh
|
30
|
-
|
31
|
-
|
30
|
+
liuli-cli generate <name> --template lib # Generate ts-lib project
|
31
|
+
liuli-cli generate <name> --template cli # generate cli project
|
32
32
|
```
|
33
33
|
|
34
34
|
util also supports interactive project creation
|
35
35
|
|
36
36
|
```shell
|
37
|
-
|
37
|
+
liuli-cli generate
|
38
38
|
```
|
39
39
|
|
40
|
-
![
|
40
|
+
![liuli-cli interactive creation screenshot](https://liuli.dev/images/liuli-cli%20%E4%BA%A4%E4%BA%92%E5%BC%8F%E5%88%9B%E5%BB%BA%E6%88%AA%E5%9B%BE.gif)
|
41
|
+
|
42
|
+
### Deployment
|
43
|
+
|
44
|
+
Support for deploying front-end resources to a remote location via sftp/gh-pages, with configuration information in the `deploy` field in package.json
|
45
|
+
|
46
|
+
```sh
|
47
|
+
liuli deploy
|
48
|
+
```
|
49
|
+
|
50
|
+
public
|
51
|
+
|
52
|
+
| configuration | description | defaults |
|
53
|
+
| ------------- | --------------------------------- | -------- |
|
54
|
+
| ``type` | deployment type, ``sftp/gh-pgaes` | none |
|
55
|
+
| `dist` | Static resource directory | None |
|
56
|
+
| `dest` | deployed remote directory | none |
|
57
|
+
|
58
|
+
sftp
|
59
|
+
|
60
|
+
| configuration | description | defaults |
|
61
|
+
| -------------------- | ----------------- | -------- |
|
62
|
+
| `sshConfig.host` | ip address of ssh | |
|
63
|
+
| `sshConfig.port` | ssh's port number | 22 |
|
64
|
+
| `sshConfig.username` | ssh's username | |
|
65
|
+
|
66
|
+
gh-pages
|
67
|
+
|
68
|
+
| configuration | description | default |
|
69
|
+
| ----------------- | ----------------------------------------- | --------------------------------------- |
|
70
|
+
| `repo?: string` | the git address of the project to push to | the default is the current project |
|
71
|
+
| `remote?: string` | push remote | defaults to origin |
|
72
|
+
| `branch?: string` | remote branch name | defaults to gh-pages |
|
73
|
+
| `add?: boolean` | whether to push incrementally | cleans up the dest directory by default |
|
74
|
+
|
75
|
+
Example configuration for deploying a vuepress documentation site
|
76
|
+
|
77
|
+
```json
|
78
|
+
{
|
79
|
+
"deploy": {
|
80
|
+
"type": "gh-pages",
|
81
|
+
"dist": "docs/.vuepress/dist"
|
82
|
+
}
|
83
|
+
}
|
84
|
+
```
|
41
85
|
|
42
86
|
### Sync configuration
|
43
87
|
|
44
88
|
```shell
|
45
|
-
|
89
|
+
liuli-cli sync
|
46
90
|
```
|
47
91
|
|
48
|
-
|
92
|
+
You need to specify which configuration to sync in package.json
|
49
93
|
|
50
94
|
```json
|
51
95
|
{
|
@@ -64,25 +108,25 @@ Currently supported configuration items
|
|
64
108
|
- eslint-vue-ts
|
65
109
|
- jest
|
66
110
|
|
67
|
-
Future goals: By default will include checking the
|
111
|
+
Future goals: By default, this will include checking the cli's own sync (if it needs to be used outside of monorepo), eslint/style-lint, and interactive cli when not configured
|
68
112
|
|
69
|
-
> Note: Currently only
|
113
|
+
> Note: Currently, only dependencies are synchronized and no installation is performed
|
70
114
|
|
71
|
-
Interactive initialization
|
115
|
+
Interactive initialization of synchronized configuration is also supported
|
72
116
|
|
73
117
|
```shell
|
74
|
-
|
118
|
+
liuli-cli sync init
|
75
119
|
```
|
76
120
|
|
77
|
-
##
|
121
|
+
## Design philosophy
|
78
122
|
|
79
|
-
-
|
80
|
-
-
|
81
|
-
-
|
82
|
-
-
|
123
|
+
- Conventions outweigh configuration and should be left out if possible. VitePress does the same thing, see: https://vitepress.vuejs.org/#lighter-page-weight This leads to a number of constraints, including the following
|
124
|
+
- The entry file must be `src/index.ts` when packaging the library, and the exit file must be `dist/index.esm.js` and `dist/index.js`
|
125
|
+
- The entry file must be `src/bin.ts` and the exit file is `dist/bin.js` when packaging the CLI.
|
126
|
+
- When packaging lib, all dependencies are treated as external dependencies, while when packaging cli, all dependencies are typed into the bundle
|
83
127
|
|
84
128
|
## FAQ
|
85
129
|
|
86
130
|
### Why not bundle external dependencies
|
87
131
|
|
88
|
-
The main reason is that
|
132
|
+
The main reason is that we want to leave the bundling to the final application, to avoid bundling the same dependencies over and over again, and to avoid dealing with the problem of using `worker_threads` directly on the filesystem in nodejs.
|
package/README.zh-CN.md
CHANGED
@@ -63,11 +63,12 @@ sftp
|
|
63
63
|
|
64
64
|
gh-pages
|
65
65
|
|
66
|
-
| 配置
|
67
|
-
|
|
68
|
-
| `repo` |
|
69
|
-
| `remote` |
|
70
|
-
| `branch` |
|
66
|
+
| 配置 | 说明 | 默认值 |
|
67
|
+
| ----------------- | ------------------- | -------------------- |
|
68
|
+
| `repo?: string` | 推送的项目 git 地址 | 默认为当前项目 |
|
69
|
+
| `remote?: string` | 推送的远端 | 默认为 origin |
|
70
|
+
| `branch?: string` | 远端分支名 | 默认为 gh-pages |
|
71
|
+
| `add?: boolean` | 是否增量推送 | 默认会清理 dest 目录 |
|
71
72
|
|
72
73
|
部署 vuepress 文档网站示例配置
|
73
74
|
|
@@ -75,8 +76,7 @@ gh-pages
|
|
75
76
|
{
|
76
77
|
"deploy": {
|
77
78
|
"type": "gh-pages",
|
78
|
-
"
|
79
|
-
"remote": "/"
|
79
|
+
"dist": "docs/.vuepress/dist"
|
80
80
|
}
|
81
81
|
}
|
82
82
|
```
|
package/package.json
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
{
|
2
2
|
"name": "@liuli-util/cli",
|
3
|
-
"version": "3.
|
3
|
+
"version": "3.22.0",
|
4
4
|
"description": "一个针对于库和 CLI 应用程序打包的零配置 CLI",
|
5
|
-
"main": "dist/index.js",
|
6
|
-
"module": "dist/index.esm.js",
|
7
|
-
"types": "dist/index.d.ts",
|
5
|
+
"main": "./dist/index.js",
|
6
|
+
"module": "./dist/index.esm.js",
|
7
|
+
"types": "./dist/index.d.ts",
|
8
8
|
"license": "MIT",
|
9
9
|
"bin": {
|
10
10
|
"liuli-cli": "./bin.js"
|
@@ -20,55 +20,59 @@
|
|
20
20
|
"registry": "https://registry.npmjs.org/"
|
21
21
|
},
|
22
22
|
"dependencies": {
|
23
|
-
"@liuli-util/commitlint-standard-config": "
|
24
|
-
"@liuli-util/eslint-config-react-ts": "
|
25
|
-
"@liuli-util/eslint-config-ts": "
|
26
|
-
"@liuli-util/prettier-standard-config": "
|
27
|
-
"ajv": "^8.
|
23
|
+
"@liuli-util/commitlint-standard-config": "0.1.6",
|
24
|
+
"@liuli-util/eslint-config-react-ts": "0.2.1",
|
25
|
+
"@liuli-util/eslint-config-ts": "0.4.0",
|
26
|
+
"@liuli-util/prettier-standard-config": "0.3.0",
|
27
|
+
"ajv": "^8.11.0",
|
28
28
|
"ajv-formats": "^2.1.1",
|
29
29
|
"ajv-i18n": "^4.2.0",
|
30
|
-
"chokidar": "^3.5.
|
31
|
-
"commander": "^
|
32
|
-
"conf": "^10.
|
30
|
+
"chokidar": "^3.5.3",
|
31
|
+
"commander": "^9.4.0",
|
32
|
+
"conf": "^10.2.0",
|
33
33
|
"enquirer": "^2.3.6",
|
34
|
-
"esbuild": "
|
35
|
-
"fs-extra": "^10.
|
36
|
-
"glob": "^
|
37
|
-
"glob-promise": "^
|
38
|
-
"json5": "^2.2.
|
39
|
-
"simple-git": "^
|
34
|
+
"esbuild": "0.14.39",
|
35
|
+
"fs-extra": "^10.1.0",
|
36
|
+
"glob": "^8.0.3",
|
37
|
+
"glob-promise": "^5.0.0",
|
38
|
+
"json5": "^2.2.1",
|
39
|
+
"simple-git": "^3.11.0",
|
40
40
|
"spinnies": "^0.5.1",
|
41
|
-
"ssh2": "^1.
|
42
|
-
"ssh2-sftp-client": "^
|
41
|
+
"ssh2": "^1.11.0",
|
42
|
+
"ssh2-sftp-client": "^9.0.3",
|
43
43
|
"tar": "^6.1.11",
|
44
|
-
"ts-morph": "^
|
44
|
+
"ts-morph": "^15.1.0"
|
45
45
|
},
|
46
46
|
"devDependencies": {
|
47
47
|
"@types/fs-extra": "^9.0.13",
|
48
|
-
"@types/glob": "^7",
|
49
|
-
"@types/jest": "^
|
50
|
-
"@types/lodash": "^4.14.
|
51
|
-
"@types/node": "^
|
52
|
-
"@types/ssh2-sftp-client": "^7.
|
53
|
-
"
|
54
|
-
"jest": "^27.4.7",
|
48
|
+
"@types/glob": "^7.2.0",
|
49
|
+
"@types/jest": "^28.1.6",
|
50
|
+
"@types/lodash": "^4.14.182",
|
51
|
+
"@types/node": "^18.6.4",
|
52
|
+
"@types/ssh2-sftp-client": "^7.1.0",
|
53
|
+
"jest": "^28.1.3",
|
55
54
|
"lodash": "^4.17.21",
|
56
55
|
"rimraf": "^3.0.2",
|
57
|
-
"ts-jest": "^
|
58
|
-
"
|
59
|
-
"
|
56
|
+
"ts-jest": "^28.0.7",
|
57
|
+
"tsx": "^3.9.0",
|
58
|
+
"type-fest": "^2.18.0",
|
59
|
+
"typescript": "^4.7.4"
|
60
60
|
},
|
61
61
|
"repository": {
|
62
62
|
"type": "git",
|
63
63
|
"url": "https://github.com/rxliuli/liuli-tools/tree/master/apps/liuli-cli"
|
64
64
|
},
|
65
|
+
"exports": {
|
66
|
+
"import": "./dist/index.esm.js",
|
67
|
+
"require": "./dist/index.js",
|
68
|
+
"types": "./dist/index.d.ts"
|
69
|
+
},
|
65
70
|
"scripts": {
|
66
71
|
"setup": "pnpm build",
|
67
|
-
"build": "
|
68
|
-
"dev": "
|
69
|
-
"start": "
|
72
|
+
"build": "tsx src/bin.ts build cli",
|
73
|
+
"dev": "tsx src/bin.ts build cli -w",
|
74
|
+
"start": "tsx src/bin.ts",
|
70
75
|
"test": "jest --all",
|
71
76
|
"lint": "eslint --fix src/**"
|
72
|
-
}
|
73
|
-
"readme": "# @liuli-util/cli\r\n\r\n> [中文](https://github.com/rxliuli/liuli-tools/tree/master/apps/liuli-cli/README.zh-CN.md)\r\n\r\nA zero-configuration CLI packaged for libraries and CLI applications.\r\n\r\n## Getting started\r\n\r\n### Install\r\n\r\n```sh\r\nyarn add -D @liuli-util/cli # local installation\r\nnpm i -g @liuli-util/cli # install globally\r\n```\r\n\r\n### Bale\r\n\r\n```sh\r\nyarn liuli-cli build lib # package library\r\nyarn liuli-cli build cli # package cli reference program\r\n```\r\n\r\n> Add the `-w` option to start the watch mode of rollup, the packaged dist/ will not be compressed and the dependencies will not be included in the bundle.\r\n\r\n![Monitor Mode](https://liuli.dev/images/liuli-cli%20%E7%9B%91%E8%A7%86%E6%A8%A1%E5%BC%8F.gif)\r\n\r\n### Generate\r\n\r\n```sh\r\nyarn liuli-cli generate <name> --template lib # Generate ts-lib project\r\nyarn liuli-cli generate <name> --template cli # Generate cli project\r\n```\r\n\r\nutil also supports interactive project creation\r\n\r\n```shell\r\nyarn liuli-cli generate\r\n```\r\n\r\n![Liuli-cli interactively create screenshots](https://liuli.dev/images/liuli-cli%20%E4%BA%A4%E4%BA%92%E5%BC%8F%E5%88%9B %E5%BB%BA%E6%88%AA%E5%9B%BE.gif)\r\n\r\n### Sync configuration\r\n\r\n```shell\r\nyarn liuli-cli sync\r\n```\r\n\r\nWhich configuration needs to be synced in package.json\r\n\r\n```json\r\n{\r\n \"sync\": [\"prettier\", \"workspaces\", \"commitlint\", \"simplehooks\"]\r\n}\r\n```\r\n\r\nCurrently supported configuration items\r\n\r\n- prettier\r\n- commitlint\r\n- simplehooks\r\n- workspaces\r\n- gitignore\r\n- eslint-ts\r\n- eslint-vue-ts\r\n- jest\r\n\r\nFuture goals: By default will include checking the synchronization of the cli itself (if it needs to be used outside of a monorepo), eslint/style-lint etc., and implementing an interactive cli when not configured\r\n\r\n> Note: Currently only the dependencies are synced and no installation is performed\r\n\r\nInteractive initialization synchronization configuration is also supported\r\n\r\n```shell\r\nyarn liuli-cli sync init\r\n```\r\n\r\n## design concept\r\n\r\n- Convention over configuration, configuration should not be provided if possible. VitePress does this too, reference: https://vitepress.vuejs.org/#lighter-page-weight This leads to some constraints, including the following\r\n - When packaging the library, the entry file must be `src/index.ts`, and the export file must be `dist/index.esm.js` and `dist/index.js`\r\n - When packaging the CLI, the entry file must be `src/bin.ts`, and the exit file must be `dist/bin.js`\r\n - All dependencies will be treated as external dependencies when packaging lib, and all dependencies will be bundled when packaging cli\r\n\r\n## FAQ\r\n\r\n### Why not bundle external dependencies\r\n\r\nThe main reason is that you want to leave the bundling work to the final application, avoid bundling the same dependencies repeatedly, and also avoid dealing with the problem of using `worker_threads` directly based on the file system in nodejs.\r\n"
|
77
|
+
}
|
74
78
|
}
|
@@ -2,11 +2,12 @@ import { EventExtPromise, PromiseUtil } from './util/PromiseUtil'
|
|
2
2
|
import Client, { ConnectOptions } from 'ssh2-sftp-client'
|
3
3
|
import * as path from 'path'
|
4
4
|
import * as os from 'os'
|
5
|
-
import { copy, mkdirp, pathExists, readFile } from 'fs-extra'
|
5
|
+
import { copy, emptyDir, mkdirp, pathExists, readdir, readFile, remove } from 'fs-extra'
|
6
6
|
import simpleGit from 'simple-git'
|
7
7
|
import { nodeCacheDir } from '../../utils/nodeCacheDir'
|
8
8
|
import { performance, PerformanceObserver } from 'perf_hooks'
|
9
9
|
import { validate } from './util/validate'
|
10
|
+
import { AsyncArray } from '../../utils'
|
10
11
|
|
11
12
|
export interface DeployEvents {
|
12
13
|
process(title: string): void
|
@@ -105,6 +106,10 @@ export interface GhPagesDeployOptions extends Omit<BaseDeployOptions, 'type'> {
|
|
105
106
|
* 远端分支名,默认为 gh-pages
|
106
107
|
*/
|
107
108
|
branch?: string
|
109
|
+
/**
|
110
|
+
* 是否增量推送,默认会清理 dest 目录
|
111
|
+
*/
|
112
|
+
add?: boolean
|
108
113
|
}
|
109
114
|
|
110
115
|
/**
|
@@ -170,8 +175,20 @@ export class GhPagesDeployService implements IDeployService {
|
|
170
175
|
'--allow-unrelated-histories': null,
|
171
176
|
})
|
172
177
|
}
|
178
|
+
const remoteDestPath = path.resolve(path.join(localRepoPath, this.options.dest ?? './'))
|
179
|
+
if (!this.options.add) {
|
180
|
+
mark('清理文件')
|
181
|
+
if (remoteDestPath === localRepoPath) {
|
182
|
+
const whiteList = ['.git']
|
183
|
+
await AsyncArray.forEach(
|
184
|
+
(await readdir(remoteDestPath)).filter((name) => !whiteList.includes(name)),
|
185
|
+
(name) => remove(path.resolve(remoteDestPath, name)),
|
186
|
+
)
|
187
|
+
} else {
|
188
|
+
await emptyDir(remoteDestPath)
|
189
|
+
}
|
190
|
+
}
|
173
191
|
mark('复制文件')
|
174
|
-
const remoteDestPath = path.join(localRepoPath, this.options.dest ?? './')
|
175
192
|
await mkdirp(remoteDestPath)
|
176
193
|
await copy(path.resolve(this.options.cwd, this.options.dist), remoteDestPath)
|
177
194
|
mark('提交所有文件')
|
@@ -201,6 +218,7 @@ export class GhPagesDeployService implements IDeployService {
|
|
201
218
|
repo: { type: 'string', nullable: true },
|
202
219
|
remote: { type: 'string', nullable: true },
|
203
220
|
branch: { type: 'string', nullable: true },
|
221
|
+
add: { type: 'boolean', nullable: true },
|
204
222
|
},
|
205
223
|
required: ['debug', 'cwd', 'dist'],
|
206
224
|
},
|
@@ -55,7 +55,7 @@ describe.skip('测试 SftpDeployService', () => {
|
|
55
55
|
})
|
56
56
|
})
|
57
57
|
|
58
|
-
describe
|
58
|
+
describe('测试 GhPagesDeployService', () => {
|
59
59
|
const options: GhPagesDeployOptions = {
|
60
60
|
debug: false,
|
61
61
|
cwd: tempPath,
|
@@ -86,19 +86,38 @@ describe.skip('测试 GhPagesDeployService', () => {
|
|
86
86
|
)
|
87
87
|
mock.mockClear()
|
88
88
|
})
|
89
|
-
it('基本示例', async () => {
|
89
|
+
it.skip('基本示例', async () => {
|
90
|
+
await ghPagesDeployService.deploy().on('process', mock)
|
91
|
+
console.log(mock.mock.calls)
|
92
|
+
expect(mock.mock.calls.some((item: string[]) => item.includes('完成推送'))).toBeTruthy()
|
93
|
+
}, 10_000)
|
94
|
+
it.skip('测试推送到子目录', async () => {
|
95
|
+
const ghPagesDeployService = new GhPagesDeployService({
|
96
|
+
...options,
|
97
|
+
dest: '/test',
|
98
|
+
})
|
99
|
+
await ghPagesDeployService.deploy().on('process', mock)
|
100
|
+
console.log(mock.mock.calls)
|
101
|
+
expect(mock.mock.calls.some((item: string[]) => item.includes('完成推送'))).toBeTruthy()
|
102
|
+
}, 10_000)
|
103
|
+
it('测试增量推送', async () => {
|
104
|
+
const ghPagesDeployService = new GhPagesDeployService({
|
105
|
+
...options,
|
106
|
+
dist: './',
|
107
|
+
add: true,
|
108
|
+
})
|
90
109
|
await ghPagesDeployService.deploy().on('process', mock)
|
91
110
|
console.log(mock.mock.calls)
|
92
111
|
expect(mock.mock.calls.some((item: string[]) => item.includes('完成推送'))).toBeTruthy()
|
93
112
|
}, 10_000)
|
94
|
-
it('测试没有任何修改', async () => {
|
113
|
+
it.skip('测试没有任何修改', async () => {
|
95
114
|
await writeFile(path.resolve(distPath, 'index.html'), 'test')
|
96
115
|
await ghPagesDeployService.deploy().on('process', mock)
|
97
116
|
await ghPagesDeployService.deploy().on('process', mock)
|
98
117
|
expect(mock.mock.calls.some((item: string[]) => item.includes('没有任何提交,跳过提交'))).toBeTruthy()
|
99
118
|
expect(mock.mock.calls.some((item: string[]) => item.includes('没有更新,跳过推送'))).toBeTruthy()
|
100
119
|
}, 20_000)
|
101
|
-
it('测试首次拉取代码', async () => {
|
120
|
+
it.skip('测试首次拉取代码', async () => {
|
102
121
|
const dir = path.resolve(nodeCacheDir('liuli-cli'), 'gh-pages', options.repo!.replace(new RegExp('[/:]', 'g'), '_'))
|
103
122
|
await remove(dir)
|
104
123
|
await ghPagesDeployService.deploy().on('process', mock)
|
@@ -5,12 +5,12 @@ import { PackageJson } from 'type-fest'
|
|
5
5
|
import { Project } from 'ts-morph'
|
6
6
|
import { promise } from 'glob-promise'
|
7
7
|
import { IOptions } from 'glob'
|
8
|
-
import { nativeNodeModules, nodeExternals, userJS } from './util/esbuildPlugins'
|
9
8
|
import { watch } from 'chokidar'
|
10
9
|
import Spinnies from 'spinnies'
|
11
10
|
import { debounce } from './util/debounce'
|
12
11
|
import { parse } from 'json5'
|
13
12
|
import { getPkgGlobalName } from './util/getPkgGlobalName'
|
13
|
+
import { nativeNodeModules, nodeExternal, resolve, userJS } from './util'
|
14
14
|
|
15
15
|
interface ESBuildProgramOptions {
|
16
16
|
base: string
|
@@ -108,7 +108,7 @@ export class ESBuildProgram {
|
|
108
108
|
bundle: true,
|
109
109
|
external: [...ESBuildProgram.globalExternal],
|
110
110
|
platform: 'browser',
|
111
|
-
plugins: [userJS()],
|
111
|
+
plugins: [userJS() as any],
|
112
112
|
incremental: this.options.isWatch,
|
113
113
|
absWorkingDir: this.options.base,
|
114
114
|
}
|
@@ -117,8 +117,6 @@ export class ESBuildProgram {
|
|
117
117
|
/**
|
118
118
|
* 获取构建 cjs 的选项
|
119
119
|
* @param deps
|
120
|
-
* @param platform
|
121
|
-
* @param plugins
|
122
120
|
*/
|
123
121
|
getBuildCjsOption({ deps, platform }: { deps: string[]; platform: Platform }): BuildOptions {
|
124
122
|
return {
|
@@ -132,14 +130,13 @@ export class ESBuildProgram {
|
|
132
130
|
minify: !this.options.isWatch,
|
133
131
|
incremental: this.options.isWatch,
|
134
132
|
metafile: this.options.isWatch,
|
133
|
+
plugins: [resolve([['@liuli-util/esbuild-plugins/src/', '@liuli-util/esbuild-plugins']])] as any,
|
135
134
|
}
|
136
135
|
}
|
137
136
|
|
138
137
|
/**
|
139
138
|
* 获取构建 esm 的选项
|
140
139
|
* @param deps
|
141
|
-
* @param platform
|
142
|
-
* @param plugins
|
143
140
|
*/
|
144
141
|
getBuildESMOption({ deps, platform }: { deps: string[]; platform: Platform }): BuildOptions {
|
145
142
|
return {
|
@@ -153,13 +150,13 @@ export class ESBuildProgram {
|
|
153
150
|
minify: !this.options.isWatch,
|
154
151
|
incremental: this.options.isWatch,
|
155
152
|
metafile: this.options.isWatch,
|
153
|
+
plugins: [resolve([['@liuli-util/esbuild-plugins/src/', '@liuli-util/esbuild-plugins']])] as any,
|
156
154
|
}
|
157
155
|
}
|
158
156
|
|
159
157
|
/**
|
160
158
|
* 获取构建 iife 的选项
|
161
159
|
* @param deps
|
162
|
-
* @param platform
|
163
160
|
*/
|
164
161
|
getBuildIifeOption({ platform, globalName }: { platform: Platform; globalName: string }): BuildOptions {
|
165
162
|
return {
|
@@ -180,7 +177,6 @@ export class ESBuildProgram {
|
|
180
177
|
/**
|
181
178
|
* 获取构建 cli 的选项
|
182
179
|
* @param deps
|
183
|
-
* @param platform
|
184
180
|
*/
|
185
181
|
getBuildCliOption({ platform }: { deps: string[]; platform: Platform }): BuildOptions {
|
186
182
|
const plugins = ESBuildProgram.getPlugins(platform)
|
@@ -205,7 +201,7 @@ export class ESBuildProgram {
|
|
205
201
|
static getPlugins(platform: string): Plugin[] {
|
206
202
|
const plugins: Plugin[] = []
|
207
203
|
if (platform === 'node') {
|
208
|
-
plugins.push(
|
204
|
+
plugins.push(nodeExternal() as any, nativeNodeModules() as any)
|
209
205
|
}
|
210
206
|
return plugins
|
211
207
|
}
|
@@ -3,8 +3,8 @@ import * as path from 'path'
|
|
3
3
|
import { mkdirp, pathExists, remove, writeFile, writeJson } from 'fs-extra'
|
4
4
|
import { PackageJson } from 'type-fest'
|
5
5
|
import { build, Platform } from 'esbuild'
|
6
|
-
import { nativeNodeModules, nodeExternals } from '../util/esbuildPlugins'
|
7
6
|
import { findParent } from '../../../utils'
|
7
|
+
import { nativeNodeModules, nodeExternals } from '@liuli-util/esbuild-plugins/src'
|
8
8
|
|
9
9
|
describe('测试 ESBuildProgram', () => {
|
10
10
|
const base: string = path.resolve(__dirname, '.temp')
|
@@ -159,7 +159,7 @@ it('测试 esbuild', async () => {
|
|
159
159
|
// ...(await ESBuildProgram.getDeps(path.resolve())),
|
160
160
|
],
|
161
161
|
platform: 'node',
|
162
|
-
plugins: [nativeNodeModules(), nodeExternals()],
|
162
|
+
plugins: [nativeNodeModules(), nodeExternals()] as any,
|
163
163
|
treeShaking: true,
|
164
164
|
})
|
165
165
|
})
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import { Plugin } from 'esbuild'
|
2
|
+
|
3
|
+
/**
|
4
|
+
* 自动排除所有依赖项
|
5
|
+
* golang 不支持 js 的一些语法,参考 https://github.com/evanw/esbuild/issues/1634
|
6
|
+
*/
|
7
|
+
export function autoExternal(): Plugin {
|
8
|
+
return {
|
9
|
+
name: 'autoExternal',
|
10
|
+
setup(build) {
|
11
|
+
build.onResolve({ filter: /.*/ }, (args) => {
|
12
|
+
if (/^\.{1,2}\//.test(args.path)) {
|
13
|
+
return
|
14
|
+
}
|
15
|
+
return {
|
16
|
+
path: args.path,
|
17
|
+
external: true,
|
18
|
+
}
|
19
|
+
})
|
20
|
+
},
|
21
|
+
}
|
22
|
+
}
|
@@ -0,0 +1,67 @@
|
|
1
|
+
import { Plugin } from 'esbuild'
|
2
|
+
|
3
|
+
/**
|
4
|
+
* @param {string} str
|
5
|
+
*/
|
6
|
+
function isValidId(str: string) {
|
7
|
+
try {
|
8
|
+
new Function(`var ${str};`)
|
9
|
+
} catch (err) {
|
10
|
+
return false
|
11
|
+
}
|
12
|
+
return true
|
13
|
+
}
|
14
|
+
|
15
|
+
/**
|
16
|
+
* Create a map of replacements for environment variables.
|
17
|
+
* @return A map of variables.
|
18
|
+
*/
|
19
|
+
export function defineProcessEnv() {
|
20
|
+
/**
|
21
|
+
* @type {{ [key: string]: string }}
|
22
|
+
*/
|
23
|
+
const definitions: Record<string, string> = {}
|
24
|
+
definitions['process.env.NODE_ENV'] = JSON.stringify(process.env.NODE_ENV || 'development')
|
25
|
+
Object.keys(process.env).forEach((key) => {
|
26
|
+
if (isValidId(key)) {
|
27
|
+
definitions[`process.env.${key}`] = JSON.stringify(process.env[key])
|
28
|
+
}
|
29
|
+
})
|
30
|
+
definitions['process.env'] = '{}'
|
31
|
+
|
32
|
+
return definitions
|
33
|
+
}
|
34
|
+
|
35
|
+
export function defineImportEnv() {
|
36
|
+
const definitions: Record<string, string> = {}
|
37
|
+
Object.keys(process.env).forEach((key) => {
|
38
|
+
if (isValidId(key)) {
|
39
|
+
definitions[`import.meta.env.${key}`] = JSON.stringify(process.env[key])
|
40
|
+
}
|
41
|
+
})
|
42
|
+
definitions['import.meta.env'] = '{}'
|
43
|
+
return definitions
|
44
|
+
}
|
45
|
+
|
46
|
+
/**
|
47
|
+
* Pass environment variables to esbuild.
|
48
|
+
* @return An esbuild plugin.
|
49
|
+
*/
|
50
|
+
export function env(options: { process?: boolean; import?: boolean }): Plugin {
|
51
|
+
return {
|
52
|
+
name: 'env',
|
53
|
+
setup(build) {
|
54
|
+
const { platform, define = {} } = build.initialOptions
|
55
|
+
if (platform === 'node') {
|
56
|
+
return
|
57
|
+
}
|
58
|
+
build.initialOptions.define = define
|
59
|
+
if (options.import) {
|
60
|
+
Object.assign(build.initialOptions.define, defineImportEnv())
|
61
|
+
}
|
62
|
+
if (options.process) {
|
63
|
+
Object.assign(build.initialOptions.define, defineProcessEnv())
|
64
|
+
}
|
65
|
+
},
|
66
|
+
}
|
67
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
export * from './autoExternal'
|
2
|
+
export * from './env'
|
3
|
+
export * from './log'
|
4
|
+
export * from './metafile'
|
5
|
+
export * from './nativeNodeModules'
|
6
|
+
export * from './nodeExternal'
|
7
|
+
export * from './raw'
|
8
|
+
export * from './resolve'
|
9
|
+
export * from './sideEffect'
|
10
|
+
export * from './userJS'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { Plugin, PluginBuild } from 'esbuild'
|
2
|
+
|
3
|
+
export function log(): Plugin {
|
4
|
+
return {
|
5
|
+
name: 'log',
|
6
|
+
setup(builder: PluginBuild) {
|
7
|
+
let start: number
|
8
|
+
builder.onStart(() => {
|
9
|
+
start = Date.now()
|
10
|
+
})
|
11
|
+
builder.onEnd((result) => {
|
12
|
+
if (result.errors.length !== 0) {
|
13
|
+
console.error('build failed', result.errors)
|
14
|
+
return
|
15
|
+
}
|
16
|
+
console.log(`build complete, time ${Date.now() - start}ms`)
|
17
|
+
})
|
18
|
+
},
|
19
|
+
}
|
20
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { Plugin } from 'esbuild'
|
2
|
+
import { writeJson } from 'fs-extra'
|
3
|
+
|
4
|
+
/**
|
5
|
+
* 生成 metafile 的插件
|
6
|
+
* @param metafilePath
|
7
|
+
*/
|
8
|
+
export function metafile(metafilePath: string): Plugin {
|
9
|
+
return {
|
10
|
+
name: 'metafile',
|
11
|
+
setup(builder) {
|
12
|
+
builder.onEnd(async (result) => {
|
13
|
+
await writeJson(metafilePath, result.metafile)
|
14
|
+
})
|
15
|
+
},
|
16
|
+
}
|
17
|
+
}
|