@liuli-util/cli 3.13.0 → 3.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/dist/bin.js +96 -77
- package/dist/bin.js.map +3 -3
- package/dist/commands/deploy/DeployService.d.ts +51 -0
- package/dist/commands/deploy/DeployService.d.ts.map +1 -0
- package/dist/commands/deploy/deploy.d.ts +3 -0
- package/dist/commands/deploy/deploy.d.ts.map +1 -0
- package/dist/commands/deploy/index.d.ts +3 -0
- package/dist/commands/deploy/index.d.ts.map +1 -0
- package/dist/commands/deploy/util/FileLock.d.ts +14 -0
- package/dist/commands/deploy/util/FileLock.d.ts.map +1 -0
- package/dist/commands/deploy/util/PromiseUtil.d.ts +14 -0
- package/dist/commands/deploy/util/PromiseUtil.d.ts.map +1 -0
- package/dist/commands/deploy/util/createArchive.d.ts +10 -0
- package/dist/commands/deploy/util/createArchive.d.ts.map +1 -0
- package/dist/commands/deploy/util/execPromise.d.ts +4 -0
- package/dist/commands/deploy/util/execPromise.d.ts.map +1 -0
- package/dist/commands/deploy/util/wait.d.ts +9 -0
- package/dist/commands/deploy/util/wait.d.ts.map +1 -0
- package/dist/commands/esbuild/ESBuildProgram.d.ts +1 -2
- package/dist/commands/esbuild/ESBuildProgram.d.ts.map +1 -1
- package/dist/commands/generate/GenerateProgram.d.ts.map +1 -1
- package/dist/commands/sync/SyncProgram.d.ts.map +1 -1
- package/dist/index.esm.js +3 -3
- package/dist/index.esm.js.map +2 -2
- package/dist/index.js +3 -3
- package/dist/index.js.map +2 -2
- package/dist/utils/nodeCacheDir.d.ts +2 -0
- package/dist/utils/nodeCacheDir.d.ts.map +1 -0
- package/package.json +13 -7
- package/src/bin.ts +3 -2
- package/src/commands/deploy/DeployService.ts +157 -0
- package/src/commands/deploy/__tests__/DeployService.test.ts +75 -0
- package/src/commands/deploy/__tests__/FileLock.test.ts +27 -0
- package/src/commands/deploy/__tests__/conf.test.ts +29 -0
- package/src/commands/deploy/__tests__/simpleGit.test.ts +29 -0
- package/src/commands/deploy/__tests__/util/deployGhPageWorker.ts +16 -0
- package/src/commands/deploy/deploy.ts +48 -0
- package/src/commands/deploy/index.ts +7 -0
- package/src/commands/deploy/util/FileLock.ts +31 -0
- package/src/commands/deploy/util/PromiseUtil.ts +34 -0
- package/src/commands/deploy/util/createArchive.ts +30 -0
- package/src/commands/deploy/util/execPromise.ts +13 -0
- package/src/commands/deploy/util/wait.ts +23 -0
- package/src/commands/esbuild/ESBuildProgram.ts +3 -12
- package/src/commands/esbuild/__tests__/.temp/getDeps/package.json +1 -0
- package/src/commands/esbuild/__tests__/ESBuildProgram.test.ts +0 -1
- package/src/commands/generate/GenerateProgram.ts +8 -24
- package/src/commands/generate/__tests__/.temp/test-cli/CHANGELOG.md +1 -0
- package/src/commands/generate/__tests__/.temp/test-cli/README.md +1 -0
- package/src/commands/generate/__tests__/.temp/test-cli/bin.js +3 -0
- package/src/commands/generate/__tests__/.temp/test-cli/package.json +44 -0
- package/src/commands/generate/__tests__/.temp/test-cli/src/bin.ts +13 -0
- package/src/commands/generate/__tests__/.temp/test-cli/src/index.ts +1 -0
- package/src/commands/generate/__tests__/.temp/test-cli/tsconfig.json +28 -0
- package/src/commands/generate/__tests__/GenerateProgram.test.ts +17 -17
- package/src/commands/sync/SyncProgram.ts +15 -41
- package/src/commands/sync/__tests__/SyncProgram.test.ts +13 -1
- package/src/utils/__tests__/nodeCacheDir.test.ts +6 -0
- package/src/utils/nodeCacheDir.ts +54 -0
- package/templates/cli/package.json +4 -10
- package/templates/cli/tsconfig.json +28 -28
- package/templates/lib/package.json +2 -8
- package/templates/lib/tsconfig.json +28 -28
- package/tsconfig.json +34 -34
- package/src/commands/sync/__tests__/.temp/lerna.json +0 -6
- package/src/commands/sync/__tests__/.temp/package.json +0 -58
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { GhPagesDeployService } from '../../DeployService'
|
|
2
|
+
import * as path from 'path'
|
|
3
|
+
|
|
4
|
+
async function deployGhPages() {
|
|
5
|
+
const tempPath = path.resolve(__dirname, '../.temp/')
|
|
6
|
+
const ghPagesDeployService = new GhPagesDeployService({
|
|
7
|
+
cwd: tempPath,
|
|
8
|
+
dest: 'dist',
|
|
9
|
+
remote: 'examples/test-app',
|
|
10
|
+
})
|
|
11
|
+
const now = Date.now()
|
|
12
|
+
await ghPagesDeployService.deploy().on('process', (title) => console.log(`[${now}] ${title}`))
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// noinspection JSIgnoredPromiseFromCall
|
|
16
|
+
deployGhPages()
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseDeployOptions,
|
|
3
|
+
DeployTypeEnum,
|
|
4
|
+
GhPagesDeployService,
|
|
5
|
+
IDeployService,
|
|
6
|
+
SftpDeployOptions,
|
|
7
|
+
SftpDeployService,
|
|
8
|
+
} from './DeployService'
|
|
9
|
+
import * as path from 'path'
|
|
10
|
+
import { pathExists, readJson } from 'fs-extra'
|
|
11
|
+
|
|
12
|
+
async function getOptions(cwd: string): Promise<BaseDeployOptions> {
|
|
13
|
+
const pkgJsonPath = path.resolve(cwd, 'package.json')
|
|
14
|
+
if (await pathExists(pkgJsonPath)) {
|
|
15
|
+
const config = (await readJson(pkgJsonPath)).deploy
|
|
16
|
+
if (!config) {
|
|
17
|
+
throw new Error('找不到配置')
|
|
18
|
+
}
|
|
19
|
+
return config
|
|
20
|
+
}
|
|
21
|
+
throw new Error('找不到配置')
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function deploy(options: Omit<BaseDeployOptions, 'type'>): Promise<void> {
|
|
25
|
+
const deployOptions = await getOptions(options.cwd)
|
|
26
|
+
let service: IDeployService
|
|
27
|
+
const _options = {
|
|
28
|
+
...options,
|
|
29
|
+
...deployOptions,
|
|
30
|
+
} as unknown as SftpDeployOptions
|
|
31
|
+
switch (deployOptions.type) {
|
|
32
|
+
case DeployTypeEnum.Sftp:
|
|
33
|
+
service = new SftpDeployService(_options)
|
|
34
|
+
break
|
|
35
|
+
case DeployTypeEnum.GhPages:
|
|
36
|
+
service = new GhPagesDeployService(_options)
|
|
37
|
+
break
|
|
38
|
+
default:
|
|
39
|
+
throw new Error('未知的部署预设类型 ' + deployOptions.type)
|
|
40
|
+
}
|
|
41
|
+
const [isValidate, errorText] = service.validate()
|
|
42
|
+
if (!isValidate) {
|
|
43
|
+
throw new Error(errorText)
|
|
44
|
+
}
|
|
45
|
+
await service.deploy().on('process', (title) => {
|
|
46
|
+
console.info(title)
|
|
47
|
+
})
|
|
48
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { close, open, remove } from 'fs-extra'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
|
|
4
|
+
export class FileLock {
|
|
5
|
+
constructor(private readonly lockFilePath: string) {}
|
|
6
|
+
|
|
7
|
+
private lockId?: number
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 加锁
|
|
11
|
+
*/
|
|
12
|
+
async lock(): Promise<boolean> {
|
|
13
|
+
try {
|
|
14
|
+
this.lockId = await open(path.resolve(this.lockFilePath), 'wx')
|
|
15
|
+
return true
|
|
16
|
+
} catch (e) {
|
|
17
|
+
return false
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 解锁
|
|
23
|
+
*/
|
|
24
|
+
async unlock(): Promise<void> {
|
|
25
|
+
if (!this.lockId) {
|
|
26
|
+
throw new Error('未加锁')
|
|
27
|
+
}
|
|
28
|
+
await remove(path.resolve(this.lockFilePath))
|
|
29
|
+
close(this.lockId)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ConditionalKeys, PromiseValue } from 'type-fest'
|
|
2
|
+
|
|
3
|
+
type VoidFunc = ((...args: any[]) => void) | undefined
|
|
4
|
+
|
|
5
|
+
export type EventExtPromise<T, E> = Promise<T> & {
|
|
6
|
+
on<K extends ConditionalKeys<E, VoidFunc>>(type: K, callback: E[K]): EventExtPromise<T, E>
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class PromiseUtil {
|
|
10
|
+
/**
|
|
11
|
+
* 创建一个支持 on* 事件的 Promise 实例
|
|
12
|
+
* @param executor
|
|
13
|
+
*/
|
|
14
|
+
static wrapOnEvent<
|
|
15
|
+
F extends (events: any) => Promise<any>,
|
|
16
|
+
E extends Parameters<F>[0],
|
|
17
|
+
K extends ConditionalKeys<E, VoidFunc>,
|
|
18
|
+
>(executor: F): EventExtPromise<PromiseValue<ReturnType<F>>, E> {
|
|
19
|
+
const events: Partial<Pick<E, K>> = {}
|
|
20
|
+
const res = new Promise(async (resolve, reject) => {
|
|
21
|
+
await new Promise((resolve) => setTimeout(resolve, 0))
|
|
22
|
+
try {
|
|
23
|
+
resolve(await executor(events))
|
|
24
|
+
} catch (e) {
|
|
25
|
+
reject(e)
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
Reflect.set(res, 'on', (type: K, callback: E[K]) => {
|
|
29
|
+
events[type] = callback
|
|
30
|
+
return res
|
|
31
|
+
})
|
|
32
|
+
return res as any
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { create, CreateOptions } from 'tar'
|
|
2
|
+
import { promise } from 'glob-promise'
|
|
3
|
+
import * as path from 'path'
|
|
4
|
+
|
|
5
|
+
export type ArchiveOptions = {
|
|
6
|
+
// sourceDir 源目录,一般设置为 dist
|
|
7
|
+
sourceDir: string
|
|
8
|
+
// destPath 目标位置,可能是 <packageName>.jpl
|
|
9
|
+
destPath: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 创建 jpl 压缩文件
|
|
14
|
+
* @param options
|
|
15
|
+
*/
|
|
16
|
+
export async function createArchive(options: ArchiveOptions): Promise<void> {
|
|
17
|
+
const sourceDir = path.resolve(options.sourceDir)
|
|
18
|
+
const destPath = path.resolve(options.destPath)
|
|
19
|
+
const distFiles = (await promise(`${sourceDir}/**/*`, { nodir: true })).map((f) => f.substr(sourceDir.length + 1))
|
|
20
|
+
await create(
|
|
21
|
+
{
|
|
22
|
+
strict: true,
|
|
23
|
+
portable: true,
|
|
24
|
+
file: destPath,
|
|
25
|
+
cwd: sourceDir,
|
|
26
|
+
sync: true,
|
|
27
|
+
} as Partial<CreateOptions>,
|
|
28
|
+
distFiles,
|
|
29
|
+
)
|
|
30
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { exec, ExecOptions } from 'child_process'
|
|
2
|
+
|
|
3
|
+
export function execPromise(command: string, options?: ExecOptions): Promise<string | Buffer> {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
exec(command, options, (error, stdout) => {
|
|
6
|
+
if (error) {
|
|
7
|
+
reject(error)
|
|
8
|
+
return
|
|
9
|
+
}
|
|
10
|
+
resolve(stdout)
|
|
11
|
+
})
|
|
12
|
+
})
|
|
13
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 等待指定的时间/等待指定表达式成立
|
|
3
|
+
* 如果未指定等待条件则立刻执行
|
|
4
|
+
* 注: 此实现在 nodejs 10- 会存在宏任务与微任务的问题,切记 async-await 本质上还是 Promise 的语法糖,实际上并非真正的同步函数!!!即便在浏览器,也不要依赖于这种特性。
|
|
5
|
+
* @param param 等待时间/等待条件
|
|
6
|
+
* @returns Promise 对象
|
|
7
|
+
*/
|
|
8
|
+
export function wait(param?: number | (() => boolean | Promise<boolean>)): Promise<void> {
|
|
9
|
+
return new Promise((resolve) => {
|
|
10
|
+
if (typeof param === 'number') {
|
|
11
|
+
setTimeout(resolve, param)
|
|
12
|
+
} else if (typeof param === 'function') {
|
|
13
|
+
const timer = setInterval(async () => {
|
|
14
|
+
if (await param()) {
|
|
15
|
+
clearInterval(timer)
|
|
16
|
+
resolve()
|
|
17
|
+
}
|
|
18
|
+
}, 100)
|
|
19
|
+
} else {
|
|
20
|
+
resolve()
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
}
|
|
@@ -31,7 +31,7 @@ export class ESBuildProgram {
|
|
|
31
31
|
this.options.isWatch = isWatch
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
static readonly globalExternal = ['esbuild', 'pnpapi', 'ts-morph']
|
|
34
|
+
static readonly globalExternal = ['esbuild', 'pnpapi', 'ts-morph', 'ssh2']
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* 获取所有依赖
|
|
@@ -146,22 +146,14 @@ export class ESBuildProgram {
|
|
|
146
146
|
* @param platform
|
|
147
147
|
* @param plugins
|
|
148
148
|
*/
|
|
149
|
-
getBuildIifeOption({
|
|
150
|
-
deps,
|
|
151
|
-
platform,
|
|
152
|
-
globalName,
|
|
153
|
-
}: {
|
|
154
|
-
deps: string[]
|
|
155
|
-
platform: Platform
|
|
156
|
-
globalName: string
|
|
157
|
-
}): BuildOptions {
|
|
149
|
+
getBuildIifeOption({ platform, globalName }: { platform: Platform; globalName: string }): BuildOptions {
|
|
158
150
|
return {
|
|
159
151
|
entryPoints: [path.resolve(this.options.base, './src/index.ts')],
|
|
160
152
|
outfile: path.resolve(this.options.base, './dist/index.iife.js'),
|
|
161
153
|
format: 'iife',
|
|
162
154
|
sourcemap: true,
|
|
163
155
|
bundle: true,
|
|
164
|
-
external: [...ESBuildProgram.globalExternal
|
|
156
|
+
external: [...ESBuildProgram.globalExternal],
|
|
165
157
|
platform: platform,
|
|
166
158
|
minify: !this.options.isWatch,
|
|
167
159
|
incremental: this.options.isWatch,
|
|
@@ -239,7 +231,6 @@ export class ESBuildProgram {
|
|
|
239
231
|
task: async () => {
|
|
240
232
|
return await this.build(
|
|
241
233
|
this.getBuildIifeOption({
|
|
242
|
-
deps: deps,
|
|
243
234
|
platform: platform,
|
|
244
235
|
globalName: getPkgGlobalName(
|
|
245
236
|
((await readJson(path.resolve(this.options.base, './package.json'))) as PackageJson).name!,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"devDependencies":{"@types/node":"16"},"dependencies":{"ora":"^6"},"peerDependencies":{"typescript":"^4"}}
|
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
import path from 'path'
|
|
2
|
-
import {
|
|
3
|
-
copy,
|
|
4
|
-
pathExists,
|
|
5
|
-
readdir,
|
|
6
|
-
readFile,
|
|
7
|
-
readJSON,
|
|
8
|
-
remove,
|
|
9
|
-
writeFile,
|
|
10
|
-
writeJSON,
|
|
11
|
-
} from 'fs-extra'
|
|
2
|
+
import { copy, pathExists, readdir, readFile, readJSON, remove, writeFile, writeJSON } from 'fs-extra'
|
|
12
3
|
import { prompt } from 'enquirer'
|
|
13
4
|
import { SyncProgram } from '../sync/SyncProgram'
|
|
14
5
|
import { PathUtil } from '../../PathUtil'
|
|
@@ -43,12 +34,9 @@ export class GenerateProgram {
|
|
|
43
34
|
if (!config.template) {
|
|
44
35
|
const { template } = await prompt<{ template: TemplateTypeEnum }>({
|
|
45
36
|
name: 'template',
|
|
46
|
-
type: '
|
|
37
|
+
type: 'select',
|
|
47
38
|
message: '请选择模板',
|
|
48
|
-
choices: [
|
|
49
|
-
TemplateTypeEnum.Lib,
|
|
50
|
-
TemplateTypeEnum.Cli,
|
|
51
|
-
] as TemplateTypeEnum[],
|
|
39
|
+
choices: [TemplateTypeEnum.Lib, TemplateTypeEnum.Cli] as TemplateTypeEnum[],
|
|
52
40
|
})
|
|
53
41
|
config.template = template
|
|
54
42
|
}
|
|
@@ -60,15 +48,9 @@ export class GenerateProgram {
|
|
|
60
48
|
- 修改 package.json,删除 private,修改名字
|
|
61
49
|
模板特定修改
|
|
62
50
|
*/
|
|
63
|
-
const srcFile = path.resolve(
|
|
64
|
-
PathUtil.RootPath,
|
|
65
|
-
`templates/${config.template}`,
|
|
66
|
-
)
|
|
51
|
+
const srcFile = path.resolve(PathUtil.RootPath, `templates/${config.template}`)
|
|
67
52
|
const destFile = path.resolve(config.dest)
|
|
68
|
-
if (
|
|
69
|
-
(await pathExists(destFile)) &&
|
|
70
|
-
(await readdir(destFile)).some((file) => pathExists(file))
|
|
71
|
-
) {
|
|
53
|
+
if ((await pathExists(destFile)) && (await readdir(destFile)).some((file) => pathExists(file))) {
|
|
72
54
|
const { override } = await prompt<{
|
|
73
55
|
override: boolean
|
|
74
56
|
}>({
|
|
@@ -82,7 +64,9 @@ export class GenerateProgram {
|
|
|
82
64
|
}
|
|
83
65
|
}
|
|
84
66
|
await remove(destFile)
|
|
85
|
-
await copy(srcFile, destFile
|
|
67
|
+
await copy(srcFile, destFile, {
|
|
68
|
+
filter: (source) => path.basename(source) !== 'node_modules',
|
|
69
|
+
})
|
|
86
70
|
await GenerateProgram.updatePackageJSON(destFile)
|
|
87
71
|
await GenerateProgram.updateReadme(destFile)
|
|
88
72
|
if (config.initSync) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# CHANGELOG
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @liuli-util/cli-test-cli
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "test-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"module": "dist/index.esm.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "rimraf dist && liuli-cli build cli",
|
|
10
|
+
"dev": "liuli-cli build cli -w",
|
|
11
|
+
"start": "esno src/bin.ts",
|
|
12
|
+
"docs:server": "live-server docs",
|
|
13
|
+
"docs:dev": "typedoc --watch",
|
|
14
|
+
"docs:build": "rimraf docs && typedoc",
|
|
15
|
+
"docs:deploy": "yarn docs:build && gh-pages -d docs/ -e / -a"
|
|
16
|
+
},
|
|
17
|
+
"bin": {
|
|
18
|
+
"cli-name": "./bin.js"
|
|
19
|
+
},
|
|
20
|
+
"jest": {
|
|
21
|
+
"preset": "ts-jest"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"commander": "^8.2.0",
|
|
25
|
+
"fs-extra": "^10.0.0",
|
|
26
|
+
"inquirer": "^8.1.5"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@liuli-util/cli": "^3.11.1",
|
|
30
|
+
"@types/fs-extra": "^9.0.13",
|
|
31
|
+
"@types/inquirer": "^8.1.2",
|
|
32
|
+
"@types/jest": "^27.0.2",
|
|
33
|
+
"@types/lodash": "^4.14.173",
|
|
34
|
+
"@types/node": "^16.9.6",
|
|
35
|
+
"esno": "^0.9.1",
|
|
36
|
+
"gh-pages": "^3.2.3",
|
|
37
|
+
"jest": "^27.2.1",
|
|
38
|
+
"rimraf": "^3.0.2",
|
|
39
|
+
"ts-jest": "^27.0.5",
|
|
40
|
+
"type-fest": "^2.3.4",
|
|
41
|
+
"typedoc": "^0.22.4",
|
|
42
|
+
"typescript": "^4.4.3"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
import { prompt } from 'inquirer'
|
|
3
|
+
|
|
4
|
+
new Command()
|
|
5
|
+
.action(async () => {
|
|
6
|
+
const { name } = await prompt<{ name: string }>({
|
|
7
|
+
type: 'input',
|
|
8
|
+
name: 'name',
|
|
9
|
+
message: '请输入名字',
|
|
10
|
+
})
|
|
11
|
+
console.log(`hello ${name}`)
|
|
12
|
+
})
|
|
13
|
+
.parse()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"lib": [
|
|
5
|
+
"ESNext"
|
|
6
|
+
],
|
|
7
|
+
"outDir": "./dist",
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"strict": true,
|
|
11
|
+
"module": "ESNext",
|
|
12
|
+
"moduleResolution": "node",
|
|
13
|
+
"sourceMap": true,
|
|
14
|
+
"declaration": true,
|
|
15
|
+
"declarationMap": true
|
|
16
|
+
},
|
|
17
|
+
"include": [
|
|
18
|
+
"src"
|
|
19
|
+
],
|
|
20
|
+
"typedocOptions": {
|
|
21
|
+
"entryPoints": [
|
|
22
|
+
"src/index.ts"
|
|
23
|
+
],
|
|
24
|
+
"out": "docs",
|
|
25
|
+
"readme": "README.md",
|
|
26
|
+
"gitRemote": "origin"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -1,19 +1,11 @@
|
|
|
1
1
|
import { GenerateProgram, TemplateTypeEnum } from '../GenerateProgram'
|
|
2
2
|
import path from 'path'
|
|
3
|
-
import {
|
|
4
|
-
mkdir,
|
|
5
|
-
pathExists,
|
|
6
|
-
readFile,
|
|
7
|
-
readJson,
|
|
8
|
-
remove,
|
|
9
|
-
writeFile,
|
|
10
|
-
writeJson,
|
|
11
|
-
} from 'fs-extra'
|
|
3
|
+
import { mkdir, pathExists, readFile, readJson, remove, writeFile, writeJson } from 'fs-extra'
|
|
12
4
|
import { PackageJson } from 'type-fest'
|
|
13
5
|
|
|
14
6
|
describe('测试 InitProgram', () => {
|
|
15
7
|
const initProgram = new GenerateProgram()
|
|
16
|
-
const tempPath = path.resolve(__dirname, 'temp')
|
|
8
|
+
const tempPath = path.resolve(__dirname, '.temp')
|
|
17
9
|
it('生成项目', async () => {
|
|
18
10
|
const dest = path.resolve(tempPath, 'lib-demo')
|
|
19
11
|
await remove(dest)
|
|
@@ -22,7 +14,7 @@ describe('测试 InitProgram', () => {
|
|
|
22
14
|
dest,
|
|
23
15
|
})
|
|
24
16
|
expect(await pathExists(dest)).toBeTruthy()
|
|
25
|
-
}
|
|
17
|
+
})
|
|
26
18
|
describe('测试一些钩子', () => {
|
|
27
19
|
beforeAll(async () => {
|
|
28
20
|
await remove(tempPath)
|
|
@@ -34,18 +26,26 @@ describe('测试 InitProgram', () => {
|
|
|
34
26
|
name: '@liuli-util/template',
|
|
35
27
|
})
|
|
36
28
|
await GenerateProgram.updatePackageJSON(tempPath)
|
|
37
|
-
expect(
|
|
38
|
-
((await readJson(jsonPath)) as PackageJson).name?.endsWith('temp'),
|
|
39
|
-
).toBeTruthy()
|
|
29
|
+
expect(((await readJson(jsonPath)) as PackageJson).name?.endsWith('temp')).toBeTruthy()
|
|
40
30
|
})
|
|
41
31
|
it('测试修改 readme', async () => {
|
|
42
32
|
const readmePath = path.resolve(tempPath, 'README.md')
|
|
43
33
|
await writeFile(readmePath, `# @liuli-util/template`)
|
|
44
34
|
await GenerateProgram.updateReadme(tempPath)
|
|
45
35
|
console.log('readme: ', await readFile(readmePath, 'utf-8'))
|
|
46
|
-
expect(
|
|
47
|
-
|
|
48
|
-
|
|
36
|
+
expect((await readFile(readmePath, 'utf-8')).endsWith('temp')).toBeTruthy()
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
describe('测试错误修复', () => {
|
|
40
|
+
it('修复 monorepo 中使用 cli 会复制 node_modules 的错误', async () => {
|
|
41
|
+
const program = new GenerateProgram()
|
|
42
|
+
const destPath = path.resolve(tempPath, 'test-cli')
|
|
43
|
+
await program.generate({
|
|
44
|
+
template: TemplateTypeEnum.Cli,
|
|
45
|
+
dest: destPath,
|
|
46
|
+
initSync: false,
|
|
47
|
+
})
|
|
48
|
+
expect(await pathExists(path.resolve(destPath, 'node_modules'))).toBeFalsy()
|
|
49
49
|
})
|
|
50
50
|
})
|
|
51
51
|
})
|
|
@@ -13,13 +13,9 @@ import { PathUtil } from '../../PathUtil'
|
|
|
13
13
|
|
|
14
14
|
export async function mergeJson(base: string, json: object): Promise<void> {
|
|
15
15
|
const pkgJsonFilePath = path.resolve(base, './package.json')
|
|
16
|
-
await writeJson(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
{
|
|
20
|
-
spaces: 2,
|
|
21
|
-
},
|
|
22
|
-
)
|
|
16
|
+
await writeJson(pkgJsonFilePath, merge(await readJson(pkgJsonFilePath), json), {
|
|
17
|
+
spaces: 2,
|
|
18
|
+
})
|
|
23
19
|
}
|
|
24
20
|
|
|
25
21
|
export type SyncConfigType =
|
|
@@ -68,10 +64,7 @@ export class SyncProgram {
|
|
|
68
64
|
} as PackageJson)
|
|
69
65
|
},
|
|
70
66
|
async when(): Promise<boolean> {
|
|
71
|
-
return (
|
|
72
|
-
(await isNpmPackage()) &&
|
|
73
|
-
((await isYarnRoot()) || !(await isYarnSubModule()))
|
|
74
|
-
)
|
|
67
|
+
return (await isNpmPackage()) && ((await isYarnRoot()) || !(await isYarnSubModule()))
|
|
75
68
|
},
|
|
76
69
|
},
|
|
77
70
|
{
|
|
@@ -91,23 +84,14 @@ export class SyncProgram {
|
|
|
91
84
|
} as PackageJson)
|
|
92
85
|
},
|
|
93
86
|
async when(): Promise<boolean> {
|
|
94
|
-
return (
|
|
95
|
-
(await isNpmPackage()) &&
|
|
96
|
-
((await isYarnRoot()) || !(await isYarnSubModule()))
|
|
97
|
-
)
|
|
87
|
+
return (await isNpmPackage()) && ((await isYarnRoot()) || !(await isYarnSubModule()))
|
|
98
88
|
},
|
|
99
89
|
},
|
|
100
90
|
{
|
|
101
91
|
type: 'gitignore',
|
|
102
92
|
handler: async () => {
|
|
103
93
|
const gitignorePath = path.resolve(this.base, '.gitignore')
|
|
104
|
-
await writeFile(
|
|
105
|
-
gitignorePath,
|
|
106
|
-
await readFile(
|
|
107
|
-
path.resolve(PathUtil.RootPath, '_gitignore'),
|
|
108
|
-
'utf-8',
|
|
109
|
-
),
|
|
110
|
-
)
|
|
94
|
+
await writeFile(gitignorePath, await readFile(path.resolve(PathUtil.RootPath, '_gitignore'), 'utf-8'))
|
|
111
95
|
},
|
|
112
96
|
},
|
|
113
97
|
{
|
|
@@ -123,11 +107,7 @@ export class SyncProgram {
|
|
|
123
107
|
} as PackageJson)
|
|
124
108
|
},
|
|
125
109
|
async when(): Promise<boolean> {
|
|
126
|
-
return (
|
|
127
|
-
(await isNpmPackage()) &&
|
|
128
|
-
!(await isIncludeDep(['vue'])) &&
|
|
129
|
-
!(await isIncludeDep(['react']))
|
|
130
|
-
)
|
|
110
|
+
return (await isNpmPackage()) && !(await isIncludeDep(['vue'])) && !(await isIncludeDep(['react']))
|
|
131
111
|
},
|
|
132
112
|
},
|
|
133
113
|
{
|
|
@@ -154,6 +134,10 @@ export class SyncProgram {
|
|
|
154
134
|
preset: 'ts-jest',
|
|
155
135
|
testMatch: ['<rootDir>/src/**/__tests__/*.test.ts'],
|
|
156
136
|
},
|
|
137
|
+
devDependencies: {
|
|
138
|
+
jest: '^27.4.3',
|
|
139
|
+
'ts-jest': '^27.0.7',
|
|
140
|
+
},
|
|
157
141
|
})
|
|
158
142
|
},
|
|
159
143
|
},
|
|
@@ -171,10 +155,7 @@ export class SyncProgram {
|
|
|
171
155
|
}
|
|
172
156
|
let config = {
|
|
173
157
|
scripts: {
|
|
174
|
-
postinstall: appendScript(
|
|
175
|
-
json?.scripts?.postinstall,
|
|
176
|
-
'npx simple-git-hooks',
|
|
177
|
-
),
|
|
158
|
+
postinstall: appendScript(json?.scripts?.postinstall, 'npx simple-git-hooks'),
|
|
178
159
|
},
|
|
179
160
|
'simple-git-hooks': {
|
|
180
161
|
'pre-commit': 'yarn lint-staged',
|
|
@@ -197,26 +178,19 @@ export class SyncProgram {
|
|
|
197
178
|
await mergeJson(this.base, config as PackageJson)
|
|
198
179
|
},
|
|
199
180
|
async when(): Promise<boolean> {
|
|
200
|
-
return (
|
|
201
|
-
(await isNpmPackage()) &&
|
|
202
|
-
((await isYarnRoot()) || !(await isYarnSubModule()))
|
|
203
|
-
)
|
|
181
|
+
return (await isNpmPackage()) && ((await isYarnRoot()) || !(await isYarnSubModule()))
|
|
204
182
|
},
|
|
205
183
|
},
|
|
206
184
|
]
|
|
207
185
|
|
|
208
186
|
async sync(): Promise<void> {
|
|
209
|
-
const { sync } = (await readJson(
|
|
210
|
-
path.resolve(this.base, 'package.json'),
|
|
211
|
-
)) as {
|
|
187
|
+
const { sync } = (await readJson(path.resolve(this.base, 'package.json'))) as {
|
|
212
188
|
sync?: SyncConfigType[]
|
|
213
189
|
}
|
|
214
190
|
if (!sync) {
|
|
215
191
|
return
|
|
216
192
|
}
|
|
217
|
-
const syncConfigs = this.syncConfigs.filter((config) =>
|
|
218
|
-
sync.includes(config.type),
|
|
219
|
-
)
|
|
193
|
+
const syncConfigs = this.syncConfigs.filter((config) => sync.includes(config.type))
|
|
220
194
|
for (const syncConfig of syncConfigs) {
|
|
221
195
|
await syncConfig.handler()
|
|
222
196
|
}
|
|
@@ -30,7 +30,7 @@ describe('测试 SyncProgram', () => {
|
|
|
30
30
|
workspaces,
|
|
31
31
|
} as PackageJson)
|
|
32
32
|
await syncProgram.sync()
|
|
33
|
-
}
|
|
33
|
+
})
|
|
34
34
|
|
|
35
35
|
it.skip('测试初始化同步配置', async () => {
|
|
36
36
|
await writeJson(path.resolve(tempPath, 'lerna.json'), {})
|
|
@@ -42,6 +42,18 @@ describe('测试 SyncProgram', () => {
|
|
|
42
42
|
await syncProgram.init()
|
|
43
43
|
expect(((await readJson(file)).sync as string[]).length).toBeGreaterThan(0)
|
|
44
44
|
}, 100_000)
|
|
45
|
+
|
|
46
|
+
it('测试同步 jest', async () => {
|
|
47
|
+
const jsonPath = path.resolve(tempPath, 'package.json')
|
|
48
|
+
await writeJson(jsonPath, {
|
|
49
|
+
name: 'temp',
|
|
50
|
+
sync: ['jest'] as SyncConfigType[],
|
|
51
|
+
} as PackageJson)
|
|
52
|
+
await syncProgram.sync()
|
|
53
|
+
const json = (await readJson(jsonPath)) as PackageJson
|
|
54
|
+
const devDeps = Object.keys(json.devDependencies!)
|
|
55
|
+
expect(devDeps.includes('jest') && devDeps.includes('ts-jest')).toBeTruthy()
|
|
56
|
+
})
|
|
45
57
|
})
|
|
46
58
|
|
|
47
59
|
it('测试 lodash-es.merge', () => {
|