@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.
Files changed (97) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +69 -25
  3. package/README.zh-CN.md +7 -7
  4. package/package.json +40 -36
  5. package/src/commands/deploy/DeployService.ts +20 -2
  6. package/src/commands/deploy/__tests__/DeployService.test.ts +23 -4
  7. package/src/commands/esbuild/ESBuildProgram.ts +5 -9
  8. package/src/commands/esbuild/__tests__/ESBuildProgram.test.ts +2 -2
  9. package/src/commands/esbuild/util/autoExternal.ts +22 -0
  10. package/src/commands/esbuild/util/env.ts +67 -0
  11. package/src/commands/esbuild/util/index.ts +10 -0
  12. package/src/commands/esbuild/util/log.ts +20 -0
  13. package/src/commands/esbuild/util/metafile.ts +17 -0
  14. package/src/commands/esbuild/util/nativeNodeModules.ts +43 -0
  15. package/src/commands/esbuild/util/nodeExternal.ts +16 -0
  16. package/src/commands/esbuild/util/raw.ts +27 -0
  17. package/src/commands/esbuild/util/resolve.ts +22 -0
  18. package/src/commands/esbuild/util/sideEffect.ts +29 -0
  19. package/src/commands/esbuild/util/userJS.ts +38 -0
  20. package/templates/cli/package.json +35 -33
  21. package/templates/lib/package.json +24 -19
  22. package/dist/PathUtil.d.ts +0 -7
  23. package/dist/PathUtil.d.ts.map +0 -1
  24. package/dist/bin.d.ts +0 -2
  25. package/dist/bin.d.ts.map +0 -1
  26. package/dist/bin.js +0 -171
  27. package/dist/bin.js.map +0 -7
  28. package/dist/commands/deploy/DeployService.d.ts +0 -70
  29. package/dist/commands/deploy/DeployService.d.ts.map +0 -1
  30. package/dist/commands/deploy/deploy.d.ts +0 -3
  31. package/dist/commands/deploy/deploy.d.ts.map +0 -1
  32. package/dist/commands/deploy/index.d.ts +0 -3
  33. package/dist/commands/deploy/index.d.ts.map +0 -1
  34. package/dist/commands/deploy/util/PromiseUtil.d.ts +0 -14
  35. package/dist/commands/deploy/util/PromiseUtil.d.ts.map +0 -1
  36. package/dist/commands/deploy/util/createArchive.d.ts +0 -10
  37. package/dist/commands/deploy/util/createArchive.d.ts.map +0 -1
  38. package/dist/commands/deploy/util/execPromise.d.ts +0 -4
  39. package/dist/commands/deploy/util/execPromise.d.ts.map +0 -1
  40. package/dist/commands/deploy/util/validate.d.ts +0 -8
  41. package/dist/commands/deploy/util/validate.d.ts.map +0 -1
  42. package/dist/commands/deploy/util/wait.d.ts +0 -9
  43. package/dist/commands/deploy/util/wait.d.ts.map +0 -1
  44. package/dist/commands/esbuild/ESBuildProgram.d.ts +0 -83
  45. package/dist/commands/esbuild/ESBuildProgram.d.ts.map +0 -1
  46. package/dist/commands/esbuild/index.d.ts +0 -3
  47. package/dist/commands/esbuild/index.d.ts.map +0 -1
  48. package/dist/commands/esbuild/util/debounce.d.ts +0 -15
  49. package/dist/commands/esbuild/util/debounce.d.ts.map +0 -1
  50. package/dist/commands/esbuild/util/esbuildPlugins.d.ts +0 -32
  51. package/dist/commands/esbuild/util/esbuildPlugins.d.ts.map +0 -1
  52. package/dist/commands/esbuild/util/getPkgGlobalName.d.ts +0 -6
  53. package/dist/commands/esbuild/util/getPkgGlobalName.d.ts.map +0 -1
  54. package/dist/commands/generate/GenerateProgram.d.ts +0 -18
  55. package/dist/commands/generate/GenerateProgram.d.ts.map +0 -1
  56. package/dist/commands/generate/index.d.ts +0 -3
  57. package/dist/commands/generate/index.d.ts.map +0 -1
  58. package/dist/commands/sync/SyncProgram.d.ts +0 -15
  59. package/dist/commands/sync/SyncProgram.d.ts.map +0 -1
  60. package/dist/commands/sync/index.d.ts +0 -3
  61. package/dist/commands/sync/index.d.ts.map +0 -1
  62. package/dist/commands/sync/when.d.ts +0 -21
  63. package/dist/commands/sync/when.d.ts.map +0 -1
  64. package/dist/index.d.ts +0 -4
  65. package/dist/index.d.ts.map +0 -1
  66. package/dist/index.esm.js +0 -8
  67. package/dist/index.esm.js.map +0 -7
  68. package/dist/index.js +0 -8
  69. package/dist/index.js.map +0 -7
  70. package/dist/utils/AsyncArray.d.ts +0 -21
  71. package/dist/utils/AsyncArray.d.ts.map +0 -1
  72. package/dist/utils/appendScript.d.ts +0 -7
  73. package/dist/utils/appendScript.d.ts.map +0 -1
  74. package/dist/utils/arrayToMap.d.ts +0 -3
  75. package/dist/utils/arrayToMap.d.ts.map +0 -1
  76. package/dist/utils/findParent.d.ts +0 -8
  77. package/dist/utils/findParent.d.ts.map +0 -1
  78. package/dist/utils/index.d.ts +0 -5
  79. package/dist/utils/index.d.ts.map +0 -1
  80. package/dist/utils/nodeCacheDir.d.ts +0 -2
  81. package/dist/utils/nodeCacheDir.d.ts.map +0 -1
  82. package/src/commands/esbuild/__tests__/.temp/package.json +0 -1
  83. package/src/commands/esbuild/__tests__/.temp/src/index.ts +0 -1
  84. package/src/commands/esbuild/util/__tests__/.temp/index.js +0 -1
  85. package/src/commands/esbuild/util/__tests__/esbuildPlugins.test.ts +0 -52
  86. package/src/commands/esbuild/util/esbuildPlugins.ts +0 -196
  87. package/src/commands/generate/__tests__/.temp/README.md +0 -1
  88. package/src/commands/generate/__tests__/.temp/package.json +0 -3
  89. package/src/commands/generate/__tests__/.temp/test-cli/CHANGELOG.md +0 -1
  90. package/src/commands/generate/__tests__/.temp/test-cli/README.md +0 -1
  91. package/src/commands/generate/__tests__/.temp/test-cli/bin.js +0 -3
  92. package/src/commands/generate/__tests__/.temp/test-cli/package.json +0 -33
  93. package/src/commands/generate/__tests__/.temp/test-cli/src/bin.ts +0 -13
  94. package/src/commands/generate/__tests__/.temp/test-cli/src/index.ts +0 -1
  95. package/src/commands/generate/__tests__/.temp/test-cli/tsconfig.json +0 -28
  96. package/src/commands/sync/__tests__/.temp/package.json +0 -16
  97. 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 packaged for libraries and CLI applications.
5
+ A zero-configuration CLI for packaging libraries and CLI applications.
6
6
 
7
- ## Getting started
7
+ ## Getting Started
8
8
 
9
9
  ### Install
10
10
 
11
11
  ```sh
12
- yarn add -D @liuli-util/cli # local installation
13
- npm i -g @liuli-util/cli # install globally
12
+ pnpm i -D @liuli-util/cli # Local installation
13
+ pnpm i -g @liuli-util/cli # global install
14
14
  ```
15
15
 
16
- ### Bale
16
+ ### Packages
17
17
 
18
18
  ```sh
19
- yarn liuli-cli build lib # package library
20
- yarn liuli-cli build cli # package cli reference program
19
+ liuli-cli build lib # Package the library
20
+ liuli-cli build cli # Package cli references
21
21
  ```
22
22
 
23
- > 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.
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
- ![Monitor Mode](https://liuli.dev/images/liuli-cli%20%E7%9B%91%E8%A7%86%E6%A8%A1%E5%BC%8F.gif)
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
- yarn liuli-cli generate <name> --template lib # Generate ts-lib project
31
- yarn liuli-cli generate <name> --template cli # Generate cli project
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
- yarn liuli-cli generate
37
+ liuli-cli generate
38
38
  ```
39
39
 
40
- ![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)
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
- yarn liuli-cli sync
89
+ liuli-cli sync
46
90
  ```
47
91
 
48
- Which configuration needs to be synced in package.json
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 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
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 the dependencies are synced and no installation is performed
113
+ > Note: Currently, only dependencies are synchronized and no installation is performed
70
114
 
71
- Interactive initialization synchronization configuration is also supported
115
+ Interactive initialization of synchronized configuration is also supported
72
116
 
73
117
  ```shell
74
- yarn liuli-cli sync init
118
+ liuli-cli sync init
75
119
  ```
76
120
 
77
- ## design concept
121
+ ## Design philosophy
78
122
 
79
- - 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
80
- - 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`
81
- - When packaging the CLI, the entry file must be `src/bin.ts`, and the exit file must be `dist/bin.js`
82
- - All dependencies will be treated as external dependencies when packaging lib, and all dependencies will be bundled when packaging cli
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 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.
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` | 部署的 git 项目地址 | 当前 git 项目的 remote 地址 |
69
- | `remote` | 远端名 | origin |
70
- | `branch` | 远端分支 | gh-pages |
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
- "dest": "docs/.vuepress/dist",
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.20.2",
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": "^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.2.0",
27
- "ajv": "^8.8.2",
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.2",
31
- "commander": "^8.2.0",
32
- "conf": "^10.1.1",
30
+ "chokidar": "^3.5.3",
31
+ "commander": "^9.4.0",
32
+ "conf": "^10.2.0",
33
33
  "enquirer": "^2.3.6",
34
- "esbuild": "^0.13.15",
35
- "fs-extra": "^10.0.0",
36
- "glob": "^7.2.0",
37
- "glob-promise": "^4.2.0",
38
- "json5": "^2.2.0",
39
- "simple-git": "^2.45.1",
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.5.0",
42
- "ssh2-sftp-client": "^7.2.1",
41
+ "ssh2": "^1.11.0",
42
+ "ssh2-sftp-client": "^9.0.3",
43
43
  "tar": "^6.1.11",
44
- "ts-morph": "^12.0.0"
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": "^27.0.2",
50
- "@types/lodash": "^4.14.178",
51
- "@types/node": "^16.9.6",
52
- "@types/ssh2-sftp-client": "^7.0.0",
53
- "esno": "^0.9.1",
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": "^27.1.3",
58
- "type-fest": "^2.3.4",
59
- "typescript": "^4.5.5"
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": "esno src/bin.ts build cli",
68
- "dev": "esno src/bin.ts build cli -w",
69
- "start": "esno src/bin.ts",
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.skip('测试 GhPagesDeployService', () => {
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(nodeExternals(), nativeNodeModules())
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
+ }