@liuli-util/cli 3.17.1 → 3.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +30 -42
  3. package/README.zh-CN.md +130 -0
  4. package/dist/bin.js +114 -94
  5. package/dist/bin.js.map +3 -3
  6. package/dist/commands/deploy/DeployService.d.ts +25 -7
  7. package/dist/commands/deploy/DeployService.d.ts.map +1 -1
  8. package/dist/commands/deploy/util/validate.d.ts +8 -0
  9. package/dist/commands/deploy/util/validate.d.ts.map +1 -0
  10. package/dist/commands/esbuild/ESBuildProgram.d.ts +5 -2
  11. package/dist/commands/esbuild/ESBuildProgram.d.ts.map +1 -1
  12. package/dist/commands/esbuild/index.d.ts.map +1 -1
  13. package/dist/commands/esbuild/util/esbuildPlugins.d.ts +1 -0
  14. package/dist/commands/esbuild/util/esbuildPlugins.d.ts.map +1 -1
  15. package/dist/commands/sync/when.d.ts.map +1 -1
  16. package/dist/index.esm.js +4 -2
  17. package/dist/index.esm.js.map +2 -2
  18. package/dist/index.js +4 -2
  19. package/dist/index.js.map +2 -2
  20. package/package.json +16 -15
  21. package/src/commands/deploy/DeployService.ts +83 -45
  22. package/src/commands/deploy/__tests__/.temp/test.lock +0 -0
  23. package/src/commands/deploy/__tests__/DeployService.test.ts +52 -20
  24. package/src/commands/deploy/__tests__/conf.test.ts +0 -1
  25. package/src/commands/deploy/__tests__/simpleGit.test.ts +24 -1
  26. package/src/commands/deploy/__tests__/util/deployGhPageWorker.ts +3 -2
  27. package/src/commands/deploy/util/validate.ts +18 -0
  28. package/src/commands/esbuild/ESBuildProgram.ts +25 -5
  29. package/src/commands/esbuild/__tests__/.temp/package.json +1 -0
  30. package/src/commands/esbuild/__tests__/.temp/src/index.ts +1 -0
  31. package/src/commands/esbuild/__tests__/ESBuildProgram.test.ts +50 -13
  32. package/src/commands/esbuild/index.ts +26 -13
  33. package/src/commands/esbuild/util/esbuildPlugins.ts +37 -1
  34. package/src/commands/generate/__tests__/.temp/README.md +1 -0
  35. package/src/commands/generate/__tests__/.temp/package.json +3 -0
  36. package/src/commands/generate/__tests__/.temp/test-cli/package.json +8 -18
  37. package/src/commands/generate/__tests__/.temp/test-cli/src/bin.ts +1 -1
  38. package/src/commands/generate/__tests__/.temp/test-cli/tsconfig.json +28 -28
  39. package/src/commands/sync/SyncProgram.ts +1 -1
  40. package/src/commands/sync/__tests__/.temp/package.json +16 -0
  41. package/src/commands/sync/__tests__/SyncProgram.test.ts +1 -1
  42. package/src/commands/sync/__tests__/when.test.ts +3 -7
  43. package/src/commands/sync/when.ts +8 -23
  44. package/templates/cli/package.json +5 -9
  45. package/templates/cli/src/bin.ts +1 -1
  46. package/templates/cli/tsconfig.json +28 -28
  47. package/templates/lib/package.json +4 -11
  48. package/templates/lib/tsconfig.json +28 -28
  49. package/tsconfig.json +34 -34
  50. package/dist/commands/deploy/util/FileLock.d.ts +0 -14
  51. package/dist/commands/deploy/util/FileLock.d.ts.map +0 -1
  52. package/src/commands/deploy/__tests__/FileLock.test.ts +0 -27
  53. package/src/commands/deploy/util/FileLock.ts +0 -31
  54. package/src/commands/esbuild/__tests__/.temp/getDeps/package.json +0 -1
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/commands/esbuild/ESBuildProgram.ts", "../src/commands/esbuild/util/esbuildPlugins.ts", "../src/commands/esbuild/util/debounce.ts", "../src/commands/esbuild/util/getPkgGlobalName.ts", "../src/commands/generate/GenerateProgram.ts", "../src/commands/sync/SyncProgram.ts", "../src/commands/sync/when.ts", "../src/utils/arrayToMap.ts", "../src/utils/appendScript.ts", "../src/utils/findParent.ts", "../src/utils/AsyncArray.ts", "../src/PathUtil.ts"],
4
- "sourcesContent": ["export * from './commands/esbuild/ESBuildProgram'\r\nexport * from './commands/generate/GenerateProgram'\r\nexport * from './commands/sync/SyncProgram'\r\n", "import { build, BuildOptions, Platform, Plugin } from 'esbuild'\r\nimport { pathExists, readFile, readJson } from 'fs-extra'\r\nimport * as path from 'path'\r\nimport { PackageJson } from 'type-fest'\r\nimport { Project } from 'ts-morph'\r\nimport { promise } from 'glob-promise'\r\nimport { IOptions } from 'glob'\r\nimport { nativeNodeModules, nodeExternals } from './util/esbuildPlugins'\r\nimport { watch } from 'chokidar'\r\nimport Spinnies from 'spinnies'\r\nimport { debounce } from './util/debounce'\r\nimport { parse } from 'json5'\r\nimport { getPkgGlobalName } from './util/getPkgGlobalName'\r\n\r\ninterface ESBuildProgramOptions {\r\n base: string\r\n isWatch: boolean\r\n}\r\n\r\ninterface Task {\r\n title: string\r\n task(): Promise<any>\r\n}\r\n\r\nexport type TaskTypeEnum = 'esm' | 'cjs' | 'iife' | 'cli' | 'dts'\r\n\r\nexport class ESBuildProgram {\r\n constructor(private readonly options: ESBuildProgramOptions) {}\r\n\r\n set isWatch(isWatch: boolean) {\r\n this.options.isWatch = isWatch\r\n }\r\n\r\n static readonly globalExternal = ['esbuild', 'pnpapi', 'ts-morph', 'ssh2']\r\n\r\n /**\r\n * \u83B7\u53D6\u6240\u6709\u4F9D\u8D56\r\n */\r\n static async getDeps(base: string): Promise<string[]> {\r\n const json = (await readJson(path.resolve(base, 'package.json'))) as PackageJson\r\n return Object.keys({\r\n ...json.dependencies,\r\n ...json.devDependencies,\r\n ...json.peerDependencies,\r\n })\r\n }\r\n\r\n /**\r\n * \u83B7\u53D6\u6240\u5728\u6A21\u5757\u7684\u7C7B\u578B\r\n */\r\n static async getPlatform(base: string): Promise<Platform> {\r\n const tsconfigPath = path.resolve(base, 'tsconfig.json')\r\n if (await pathExists(tsconfigPath)) {\r\n const tsconfigJson = parse(await readFile(tsconfigPath, 'utf-8'))\r\n if ((tsconfigJson.compilerOptions.lib as string[]).some((lib) => lib.toLowerCase() === 'dom')) {\r\n return 'browser'\r\n }\r\n }\r\n const pkgPath = path.resolve(base, 'package.json')\r\n if (await pathExists(pkgPath)) {\r\n const pkgJson = (await readJson(pkgPath)) as PackageJson\r\n if (Object.keys(pkgJson.devDependencies ?? {}).includes('@types/node')) {\r\n return 'node'\r\n }\r\n }\r\n return 'neutral'\r\n }\r\n static getWatchOptions(base: string): {\r\n pattern: string\r\n options: IOptions\r\n } {\r\n const pattern = 'src/**/*.ts'\r\n const options: Pick<IOptions, 'cwd' | 'ignore'> = {\r\n cwd: base,\r\n ignore: '**/__tests__/**/*',\r\n }\r\n return { pattern, options }\r\n }\r\n /**\r\n * \u751F\u6210\u7C7B\u578B\u5B9A\u4E49\r\n */\r\n async genDTS(): Promise<void> {\r\n const base = this.options.base\r\n const { pattern, options } = ESBuildProgram.getWatchOptions(this.options.base)\r\n const project = new Project({\r\n tsConfigFilePath: path.resolve(base, 'tsconfig.json'),\r\n skipAddingFilesFromTsConfig: true,\r\n compilerOptions: {\r\n emitDeclarationOnly: true,\r\n noEmit: false,\r\n incremental: this.options.isWatch,\r\n },\r\n })\r\n const fileList = (await promise(pattern, options)).map((filePath) => path.resolve(base, filePath))\r\n project.addSourceFilesAtPaths(fileList)\r\n await project.emit({\r\n emitOnlyDtsFiles: true,\r\n })\r\n }\r\n\r\n /**\r\n * \u83B7\u53D6\u6784\u5EFA cjs \u7684\u9009\u9879\r\n * @param deps\r\n * @param platform\r\n * @param plugins\r\n */\r\n getBuildCjsOption({ deps, platform }: { deps: string[]; platform: Platform }): BuildOptions {\r\n return {\r\n entryPoints: [path.resolve(this.options.base, './src/index.ts')],\r\n outfile: path.resolve(this.options.base, './dist/index.js'),\r\n format: 'cjs',\r\n sourcemap: true,\r\n bundle: true,\r\n external: [...ESBuildProgram.globalExternal, ...deps],\r\n platform: platform,\r\n minify: !this.options.isWatch,\r\n incremental: this.options.isWatch,\r\n metafile: this.options.isWatch,\r\n }\r\n }\r\n\r\n /**\r\n * \u83B7\u53D6\u6784\u5EFA esm \u7684\u9009\u9879\r\n * @param deps\r\n * @param platform\r\n * @param plugins\r\n */\r\n getBuildESMOption({ deps, platform }: { deps: string[]; platform: Platform }): BuildOptions {\r\n return {\r\n entryPoints: [path.resolve(this.options.base, './src/index.ts')],\r\n outfile: path.resolve(this.options.base, './dist/index.esm.js'),\r\n format: 'esm',\r\n sourcemap: true,\r\n bundle: true,\r\n external: [...ESBuildProgram.globalExternal, ...deps],\r\n platform: platform,\r\n minify: !this.options.isWatch,\r\n incremental: this.options.isWatch,\r\n metafile: this.options.isWatch,\r\n }\r\n }\r\n\r\n /**\r\n * \u83B7\u53D6\u6784\u5EFA iife \u7684\u9009\u9879\r\n * @param deps\r\n * @param platform\r\n * @param plugins\r\n */\r\n getBuildIifeOption({ platform, globalName }: { platform: Platform; globalName: string }): BuildOptions {\r\n return {\r\n entryPoints: [path.resolve(this.options.base, './src/index.ts')],\r\n outfile: path.resolve(this.options.base, './dist/index.iife.js'),\r\n format: 'iife',\r\n sourcemap: true,\r\n bundle: true,\r\n external: [...ESBuildProgram.globalExternal],\r\n platform: platform,\r\n minify: !this.options.isWatch,\r\n incremental: this.options.isWatch,\r\n metafile: this.options.isWatch,\r\n globalName,\r\n }\r\n }\r\n\r\n /**\r\n * \u83B7\u53D6\u6784\u5EFA cli \u7684\u9009\u9879\r\n * @param deps\r\n * @param platform\r\n */\r\n getBuildCliOption({ platform }: { deps: string[]; platform: Platform }): BuildOptions {\r\n const plugins = ESBuildProgram.getPlugins(platform)\r\n return {\r\n entryPoints: [path.resolve(this.options.base, './src/bin.ts')],\r\n outfile: path.resolve(this.options.base, './dist/bin.js'),\r\n format: 'cjs',\r\n sourcemap: true,\r\n platform: platform,\r\n bundle: true,\r\n banner: {\r\n js: '#!/usr/bin/env node',\r\n },\r\n external: [...ESBuildProgram.globalExternal],\r\n plugins,\r\n minify: !this.options.isWatch,\r\n incremental: this.options.isWatch,\r\n metafile: this.options.isWatch,\r\n }\r\n }\r\n\r\n static getPlugins(platform: string): Plugin[] {\r\n const plugins: Plugin[] = []\r\n if (platform === 'node') {\r\n plugins.push(nodeExternals(), nativeNodeModules())\r\n }\r\n return plugins\r\n }\r\n\r\n async build(options: BuildOptions): Promise<void> {\r\n // if (this.options.isWatch) {\r\n // options.plugins = [...(options.plugins ?? []), metafile(options.outfile + '.meta.json')]\r\n // }\r\n await build(options)\r\n }\r\n\r\n async getTasks(): Promise<Record<TaskTypeEnum, Task>> {\r\n const deps = await ESBuildProgram.getDeps(this.options.base)\r\n const platform = await ESBuildProgram.getPlatform(this.options.base)\r\n return {\r\n esm: {\r\n title: '\u6784\u5EFA esm',\r\n task: () =>\r\n this.build(\r\n this.getBuildESMOption({\r\n deps: deps,\r\n platform: platform,\r\n }),\r\n ),\r\n },\r\n cjs: {\r\n title: '\u6784\u5EFA cjs',\r\n task: () =>\r\n this.build(\r\n this.getBuildCjsOption({\r\n deps: deps,\r\n platform: platform,\r\n }),\r\n ),\r\n },\r\n iife: {\r\n title: '\u6784\u5EFA iife',\r\n task: async () => {\r\n return await this.build(\r\n this.getBuildIifeOption({\r\n platform: platform,\r\n globalName: getPkgGlobalName(\r\n ((await readJson(path.resolve(this.options.base, './package.json'))) as PackageJson).name!,\r\n ),\r\n }),\r\n )\r\n },\r\n },\r\n cli: {\r\n title: '\u6784\u5EFA cli',\r\n task: () =>\r\n build(\r\n this.getBuildCliOption({\r\n deps: deps,\r\n platform: platform,\r\n }),\r\n ),\r\n },\r\n dts: {\r\n title: '\u751F\u6210\u7C7B\u578B\u5B9A\u4E49',\r\n task: () => this.genDTS(),\r\n },\r\n }\r\n }\r\n\r\n static async execTask(spinnies: Spinnies, task: Task): Promise<void> {\r\n const start = Date.now()\r\n spinnies.add(task.title, { text: task.title })\r\n try {\r\n await task.task()\r\n spinnies.succeed(task.title, {\r\n text: `${task.title}: ${Date.now() - start}ms`,\r\n })\r\n } catch (e) {\r\n spinnies.fail(task.title, { text: task.title })\r\n }\r\n }\r\n async execTasks(tasks: Task[]): Promise<void> {\r\n const run = async () => {\r\n const start = Date.now()\r\n const spinnies = new Spinnies()\r\n await Promise.all(tasks.map(async (task) => ESBuildProgram.execTask(spinnies, task)))\r\n console.log(`\u6784\u5EFA\u5B8C\u6210: ${Date.now() - start}ms`)\r\n }\r\n\r\n if (!this.options.isWatch) {\r\n await run()\r\n return\r\n }\r\n\r\n const { pattern, options } = ESBuildProgram.getWatchOptions(this.options.base)\r\n await new Promise((resolve, reject) => {\r\n watch(pattern, options).on('error', reject).on('all', debounce(run, 10))\r\n })\r\n }\r\n}\r\n", "import { Plugin } from 'esbuild'\r\nimport { writeJson } from 'fs-extra'\r\n\r\n/**\r\n * \u5904\u7406 nodejs \u539F\u751F\u6A21\u5757\r\n * @link https://github.com/evanw/esbuild/issues/1051#issuecomment-806325487\r\n */\r\nexport function nativeNodeModules(): Plugin {\r\n return {\r\n name: 'native-node-modules',\r\n setup(build) {\r\n // If a \".node\" file is imported within a module in the \"file\" namespace, resolve\r\n // it to an absolute path and put it into the \"node-file\" virtual namespace.\r\n build.onResolve({ filter: /\\.node$/, namespace: 'file' }, (args) => ({\r\n path: require.resolve(args.path, { paths: [args.resolveDir] }),\r\n namespace: 'node-file',\r\n }))\r\n\r\n // Files in the \"node-file\" virtual namespace call \"require()\" on the\r\n // path from esbuild of the \".node\" file in the output directory.\r\n build.onLoad({ filter: /.*/, namespace: 'node-file' }, (args) => ({\r\n contents: `\r\n import path from ${JSON.stringify(args.path)}\r\n try { module.exports = require(path) }\r\n catch {}\r\n `,\r\n }))\r\n\r\n // If a \".node\" file is imported within a module in the \"node-file\" namespace, put\r\n // it in the \"file\" namespace where esbuild's default loading behavior will handle\r\n // it. It is already an absolute path since we resolved it to one above.\r\n build.onResolve({ filter: /\\.node$/, namespace: 'node-file' }, (args) => ({\r\n path: args.path,\r\n namespace: 'file',\r\n }))\r\n\r\n // Tell esbuild's default loading behavior to use the \"file\" loader for\r\n // these \".node\" files.\r\n const opts = build.initialOptions\r\n opts.loader = opts.loader || {}\r\n opts.loader['.node'] = 'file'\r\n },\r\n }\r\n}\r\n\r\n/**\r\n * \u6392\u9664\u548C\u66FF\u6362 node \u5185\u7F6E\u6A21\u5757\r\n */\r\nexport function nodeExternals(): Plugin {\r\n return {\r\n name: 'esbuild-plugin-node-externals',\r\n setup(build) {\r\n build.onResolve({ filter: /(^node:)/ }, (args) => ({\r\n path: args.path.slice(5),\r\n external: true,\r\n }))\r\n },\r\n }\r\n}\r\n\r\n/**\r\n * \u81EA\u52A8\u6392\u9664\u6240\u6709\u4F9D\u8D56\u9879\r\n * golang \u4E0D\u652F\u6301 js \u7684\u4E00\u4E9B\u8BED\u6CD5\uFF0C\u53C2\u8003 https://github.com/evanw/esbuild/issues/1634\r\n */\r\nexport function autoExternal(): Plugin {\r\n return {\r\n name: 'esbuild-plugin-auto-external',\r\n setup(build) {\r\n build.onResolve({ filter: /.*/ }, (args) => {\r\n if (/^\\.{1,2}\\//.test(args.path)) {\r\n return\r\n }\r\n return {\r\n path: args.path,\r\n external: true,\r\n }\r\n })\r\n },\r\n }\r\n}\r\n\r\n/**\r\n * \u751F\u6210 metafile \u7684\u63D2\u4EF6\r\n * @param metafilePath\r\n */\r\nexport function metafile(metafilePath: string): Plugin {\r\n return {\r\n name: 'esbuild-plugin-metafile',\r\n setup(builder) {\r\n builder.onEnd(async (result) => {\r\n await writeJson(metafilePath, result.metafile)\r\n })\r\n },\r\n }\r\n}\r\n", "/**\r\n * \u51FD\u6570\u53BB\u6296\r\n * \u53BB\u6296 (debounce) \u53BB\u6296\u5C31\u662F\u5BF9\u4E8E\u4E00\u5B9A\u65F6\u95F4\u6BB5\u7684\u8FDE\u7EED\u7684\u51FD\u6570\u8C03\u7528\uFF0C\u53EA\u8BA9\u5176\u6267\u884C\u4E00\u6B21\r\n * \u6CE8: \u5305\u88C5\u540E\u7684\u51FD\u6570\u5982\u679C\u4E24\u6B21\u64CD\u4F5C\u95F4\u9694\u5C0F\u4E8E delay \u5219\u4E0D\u4F1A\u88AB\u6267\u884C, \u5982\u679C\u4E00\u76F4\u5728\u64CD\u4F5C\u5C31\u4F1A\u4E00\u76F4\u4E0D\u6267\u884C, \u76F4\u5230\u64CD\u4F5C\u505C\u6B62\u7684\u65F6\u95F4\u5927\u4E8E delay \u6700\u5C0F\u95F4\u9694\u65F6\u95F4\u624D\u4F1A\u6267\u884C\u4E00\u6B21, \u4E0D\u7BA1\u4EFB\u4F55\u65F6\u95F4\u8C03\u7528\u90FD\u9700\u8981\u505C\u6B62\u64CD\u4F5C\u7B49\u5F85\u6700\u5C0F\u5EF6\u8FDF\u65F6\u95F4\r\n * \u5E94\u7528\u573A\u666F\u4E3B\u8981\u5728\u90A3\u4E9B\u8FDE\u7EED\u7684\u64CD\u4F5C, \u4F8B\u5982\u9875\u9762\u6EDA\u52A8\u76D1\u542C, \u5305\u88C5\u540E\u7684\u51FD\u6570\u53EA\u4F1A\u6267\u884C\u6700\u540E\u4E00\u6B21\r\n * \u6CE8: \u8BE5\u51FD\u6570\u7B2C\u4E00\u6B21\u8C03\u7528\u4E00\u5B9A\u4E0D\u4F1A\u6267\u884C\uFF0C\u7B2C\u4E00\u6B21\u4E00\u5B9A\u62FF\u4E0D\u5230\u7F13\u5B58\u503C\uFF0C\u540E\u9762\u7684\u8FDE\u7EED\u8C03\u7528\u90FD\u4F1A\u62FF\u5230\u4E0A\u4E00\u6B21\u7684\u7F13\u5B58\u503C\u3002\u5982\u679C\u9700\u8981\u5728\u7B2C\u4E00\u6B21\u8C03\u7528\u83B7\u53D6\u5230\u7684\u7F13\u5B58\u503C\uFF0C\u5219\u9700\u8981\u4F20\u5165\u7B2C\u4E09\u4E2A\u53C2\u6570 {@param init}\uFF0C\u9ED8\u8BA4\u4E3A {@code undefined} \u7684\u53EF\u9009\u53C2\u6570\r\n * \u6CE8: \u8FD4\u56DE\u51FD\u6570\u7ED3\u679C\u7684\u9AD8\u9636\u51FD\u6570\u9700\u8981\u4F7F\u7528 {@see Proxy} \u5B9E\u73B0\uFF0C\u4EE5\u907F\u514D\u539F\u51FD\u6570\u539F\u578B\u94FE\u4E0A\u7684\u4FE1\u606F\u4E22\u5931\r\n *\r\n * @param fn \u771F\u6B63\u9700\u8981\u6267\u884C\u7684\u64CD\u4F5C\r\n * @param delay \u6700\u5C0F\u5EF6\u8FDF\u65F6\u95F4\uFF0C\u5355\u4F4D\u4E3A ms\r\n * @param init \u521D\u59CB\u7684\u7F13\u5B58\u503C\uFF0C\u4E0D\u586B\u9ED8\u8BA4\u4E3A {@see undefined}\r\n * @return \u5305\u88C5\u540E\u6709\u53BB\u6296\u529F\u80FD\u7684\u51FD\u6570\u3002\u8BE5\u51FD\u6570\u662F\u5F02\u6B65\u7684\uFF0C\u4E0E\u9700\u8981\u5305\u88C5\u7684\u51FD\u6570 {@param fn} \u662F\u5426\u5F02\u6B65\u6CA1\u6709\u592A\u5927\u5173\u8054\r\n */\r\nexport function debounce<\r\n T extends (...args: any[]) => any,\r\n R extends (...args: Parameters<T>) => Promise<ReturnType<T>>,\r\n>(fn: T, delay: number, init: any = null): R {\r\n let flag: number\r\n let result = init\r\n return async function (...args) {\r\n return new Promise((resolve) => {\r\n if (flag) {\r\n clearTimeout(flag as any)\r\n }\r\n flag = setTimeout(() => resolve((result = fn(...args))), delay) as any\r\n setTimeout(() => resolve(result), delay)\r\n })\r\n } as R\r\n}\r\n", "/**\r\n * \u8F6C\u6362 npm \u5305\u540D\u4E3A\u4E00\u4E2A\u5408\u9002\u7684\u5168\u5C40\u53D8\u91CF\u540D\r\n * @param name\r\n */\r\nexport function getPkgGlobalName(name: string): string {\r\n const temp = name.startsWith('@') ? name.slice(name.indexOf('/') + 1) : name\r\n return temp\r\n .split('-')\r\n .map((s) => s.slice(0, 1).toUpperCase() + s.slice(1).toLowerCase())\r\n .join('')\r\n}\r\n", "import path from 'path'\r\nimport { copy, pathExists, readdir, readFile, readJSON, remove, writeFile, writeJSON } from 'fs-extra'\r\nimport { prompt } from 'enquirer'\r\nimport { SyncProgram } from '../sync/SyncProgram'\r\nimport { PathUtil } from '../../PathUtil'\r\n\r\nexport enum TemplateTypeEnum {\r\n Cli = 'cli',\r\n Lib = 'lib',\r\n}\r\n\r\nexport interface GenerateConfig {\r\n template: TemplateTypeEnum\r\n dest: string\r\n initSync?: boolean\r\n}\r\n\r\nexport class GenerateProgram {\r\n /**\r\n * \u751F\u6210\u9879\u76EE\r\n */\r\n async generate(config: GenerateConfig): Promise<void> {\r\n if (!config.dest) {\r\n const { dest } = await prompt<{ dest: string }>({\r\n name: 'dest',\r\n type: 'input',\r\n message: '\u8BF7\u8F93\u5165\u9879\u76EE\u540D',\r\n validate(input: string): boolean {\r\n return input.trim() !== ''\r\n },\r\n })\r\n config.dest = path.resolve(dest)\r\n }\r\n if (!config.template) {\r\n const { template } = await prompt<{ template: TemplateTypeEnum }>({\r\n name: 'template',\r\n type: 'select',\r\n message: '\u8BF7\u9009\u62E9\u6A21\u677F',\r\n choices: [TemplateTypeEnum.Lib, TemplateTypeEnum.Cli] as TemplateTypeEnum[],\r\n })\r\n config.template = template\r\n }\r\n\r\n /*\r\n \u514B\u9686\u9879\u76EE\r\n \u4FEE\u6539\u4E00\u4E9B\u5185\u5BB9\r\n \u5171\u901A\u4FEE\u6539\r\n - \u4FEE\u6539 package.json\uFF0C\u5220\u9664 private\uFF0C\u4FEE\u6539\u540D\u5B57\r\n \u6A21\u677F\u7279\u5B9A\u4FEE\u6539\r\n */\r\n const srcFile = path.resolve(PathUtil.RootPath, `templates/${config.template}`)\r\n const destFile = path.resolve(config.dest)\r\n if ((await pathExists(destFile)) && (await readdir(destFile)).some((file) => pathExists(file))) {\r\n const { override } = await prompt<{\r\n override: boolean\r\n }>({\r\n name: 'override',\r\n type: 'confirm',\r\n initial: true,\r\n message: '\u76EE\u6807\u4F4D\u7F6E\u4E0D\u662F\u4E00\u4E2A\u7A7A\u76EE\u5F55\uFF0C\u786E\u8BA4\u8981\u8986\u76D6\u4E48\uFF1F',\r\n })\r\n if (!override) {\r\n return\r\n }\r\n }\r\n await remove(destFile)\r\n await copy(srcFile, destFile, {\r\n filter: (source) => path.basename(source) !== 'node_modules',\r\n })\r\n await GenerateProgram.updatePackageJSON(destFile)\r\n await GenerateProgram.updateReadme(destFile)\r\n if (config.initSync) {\r\n const syncProgram = new SyncProgram(path.resolve(config.dest))\r\n await syncProgram.init()\r\n await syncProgram.sync()\r\n }\r\n }\r\n\r\n static async updatePackageJSON(destFile: string): Promise<void> {\r\n const pkgPath = path.resolve(destFile, 'package.json')\r\n await writeJSON(\r\n pkgPath,\r\n {\r\n ...(await readJSON(pkgPath)),\r\n name: path.basename(destFile),\r\n },\r\n {\r\n spaces: 2,\r\n },\r\n )\r\n }\r\n\r\n static async updateReadme(destFile: string): Promise<void> {\r\n const readmePath = path.resolve(destFile, 'README.md')\r\n let readmeFile = await readFile(readmePath, 'utf-8')\r\n readmeFile = readmeFile.replace('template', path.basename(destFile))\r\n await writeFile(readmePath, readmeFile)\r\n }\r\n}\r\n", "import { readFile, readJson, writeFile, writeJson } from 'fs-extra'\r\nimport path from 'path'\r\nimport { merge } from 'lodash-es'\r\nimport { PackageJson } from 'type-fest'\r\nimport prettier from '@liuli-util/prettier-standard-config/package.json'\r\nimport eslintTs from '@liuli-util/eslint-config-ts/package.json'\r\nimport eslintReactTs from '@liuli-util/eslint-config-react-ts/package.json'\r\nimport commitlint from '@liuli-util/commitlint-standard-config/package.json'\r\nimport { prompt } from 'enquirer'\r\nimport { isIncludeDep, isNpmPackage, isYarnRoot, isYarnSubModule } from './when'\r\nimport { appendScript, arrayToMap, AsyncArray } from '../../utils'\r\nimport { PathUtil } from '../../PathUtil'\r\n\r\nexport async function mergeJson(base: string, json: object): Promise<void> {\r\n const pkgJsonFilePath = path.resolve(base, './package.json')\r\n await writeJson(pkgJsonFilePath, merge(await readJson(pkgJsonFilePath), json), {\r\n spaces: 2,\r\n })\r\n}\r\n\r\nexport type SyncConfigType =\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 | 'eslint-react-ts'\r\n | 'jest'\r\n\r\nexport interface SyncConfig {\r\n type: SyncConfigType\r\n handler(): Promise<void>\r\n when?(): Promise<boolean>\r\n}\r\n\r\nexport class SyncProgram {\r\n constructor(private readonly base: string) {}\r\n private syncConfigs: SyncConfig[] = [\r\n {\r\n type: 'workspaces',\r\n handler: async () => {\r\n const pkgPath = path.resolve(this.base, './package.json')\r\n const lernaPath = path.resolve(this.base, 'lerna.json')\r\n const pkgJson = (await readJson(pkgPath)) as { workspaces: string[] }\r\n const lernaJson = await readJson(lernaPath)\r\n lernaJson.packages = pkgJson.workspaces\r\n await writeJson(lernaPath, lernaJson, {\r\n spaces: 2,\r\n })\r\n },\r\n when: isYarnRoot,\r\n },\r\n {\r\n type: 'prettier',\r\n handler: async () => {\r\n await mergeJson(this.base, {\r\n prettier: '@liuli-util/prettier-standard-config',\r\n devDependencies: {\r\n prettier: '^2.3.2',\r\n '@liuli-util/prettier-standard-config': `^${prettier.version}`,\r\n },\r\n } as PackageJson)\r\n },\r\n async when(): Promise<boolean> {\r\n return (await isNpmPackage()) && ((await isYarnRoot()) || !(await isYarnSubModule()))\r\n },\r\n },\r\n {\r\n type: 'commitlint',\r\n handler: async () => {\r\n await mergeJson(this.base, {\r\n 'simple-git-hooks': {\r\n 'commit-msg': 'yarn commitlint --edit $1',\r\n },\r\n commitlint: {\r\n extends: ['@liuli-util/commitlint-standard-config'],\r\n },\r\n devDependencies: {\r\n '@commitlint/cli': '^12.1.4',\r\n '@liuli-util/commitlint-standard-config': `^${commitlint.version}`,\r\n },\r\n } as PackageJson)\r\n },\r\n async when(): Promise<boolean> {\r\n return (await isNpmPackage()) && ((await isYarnRoot()) || !(await isYarnSubModule()))\r\n },\r\n },\r\n {\r\n type: 'gitignore',\r\n handler: async () => {\r\n const gitignorePath = path.resolve(this.base, '.gitignore')\r\n await writeFile(gitignorePath, await readFile(path.resolve(PathUtil.RootPath, '_gitignore'), 'utf-8'))\r\n },\r\n },\r\n {\r\n type: 'eslint-ts',\r\n handler: async () => {\r\n await mergeJson(this.base, {\r\n eslintConfig: {\r\n extends: ['@liuli-util/eslint-config-ts'],\r\n },\r\n devDependencies: {\r\n '@liuli-util/eslint-config-ts': `^${eslintTs.version}`,\r\n },\r\n } as PackageJson)\r\n },\r\n async when(): Promise<boolean> {\r\n return (await isNpmPackage()) && !(await isIncludeDep(['vue'])) && !(await isIncludeDep(['react']))\r\n },\r\n },\r\n {\r\n type: 'eslint-react-ts',\r\n handler: async () => {\r\n await mergeJson(this.base, {\r\n eslintConfig: {\r\n extends: ['@liuli-util/eslint-config-react-ts'],\r\n },\r\n devDependencies: {\r\n '@liuli-util/eslint-config-react-ts': `^${eslintReactTs.version}`,\r\n },\r\n } as PackageJson)\r\n },\r\n async when(): Promise<boolean> {\r\n return (await isNpmPackage()) && (await isIncludeDep(['react']))\r\n },\r\n },\r\n {\r\n type: 'jest',\r\n handler: async () => {\r\n await mergeJson(this.base, {\r\n jest: {\r\n preset: 'ts-jest',\r\n testMatch: ['<rootDir>/src/**/__tests__/*.test.ts'],\r\n },\r\n devDependencies: {\r\n jest: '^27.4.3',\r\n 'ts-jest': '^27.0.7',\r\n },\r\n })\r\n },\r\n },\r\n //\u5FC5\u987B\u653E\u5230\u6700\u540E\u4E00\u4E2A\uFF0C\u540E\u7EED\u6839\u636E\u68C0\u6D4B\u7ED3\u679C\u6DFB\u52A0 hooks\r\n {\r\n type: 'simplehooks',\r\n handler: async () => {\r\n const json = await readJson(path.resolve(this.base, './package.json'))\r\n const lintStaged: string[] = []\r\n if (json.prettier) {\r\n lintStaged.push('prettier --write')\r\n }\r\n if (json.eslintConfig) {\r\n lintStaged.push('eslint --fix')\r\n }\r\n let config = {\r\n scripts: {\r\n postinstall: appendScript(json?.scripts?.postinstall, 'npx simple-git-hooks'),\r\n },\r\n 'simple-git-hooks': {\r\n 'pre-commit': 'yarn lint-staged',\r\n },\r\n 'lint-staged': {\r\n '*.{ts,tsx,js,jsx,css,vue}': [...lintStaged, 'git add'],\r\n },\r\n devDependencies: {\r\n 'simple-git-hooks': '^2.5.1',\r\n 'lint-staged': '^11.1.1',\r\n },\r\n }\r\n if (json.commitlint) {\r\n config = merge(config, {\r\n 'simple-git-hooks': {\r\n 'commit-msg': 'yarn commitlint --edit $1',\r\n },\r\n })\r\n }\r\n await mergeJson(this.base, config as PackageJson)\r\n },\r\n async when(): Promise<boolean> {\r\n return (await isNpmPackage()) && ((await isYarnRoot()) || !(await isYarnSubModule()))\r\n },\r\n },\r\n ]\r\n\r\n async sync(): Promise<void> {\r\n const { sync } = (await readJson(path.resolve(this.base, 'package.json'))) as {\r\n sync?: SyncConfigType[]\r\n }\r\n if (!sync) {\r\n return\r\n }\r\n const syncConfigs = this.syncConfigs.filter((config) => sync.includes(config.type))\r\n for (const syncConfig of syncConfigs) {\r\n await syncConfig.handler()\r\n }\r\n }\r\n\r\n async init(): Promise<void> {\r\n const configMap = arrayToMap(\r\n await AsyncArray.filter(this.syncConfigs, async (config) => {\r\n if (!config.when) {\r\n return true\r\n }\r\n return await config.when()\r\n }),\r\n (item) => item.type,\r\n )\r\n const res = await prompt<{\r\n sync: string[]\r\n }>({\r\n type: 'multiselect',\r\n message: '\u8BF7\u9009\u62E9\u9700\u8981\u540C\u6B65\u7684\u914D\u7F6E\u9879',\r\n name: 'sync',\r\n choices: [...configMap.keys()],\r\n })\r\n await mergeJson(this.base, {\r\n sync: res.sync,\r\n })\r\n }\r\n}\r\n", "import { pathExists, readJson } from 'fs-extra'\r\nimport path from 'path'\r\nimport { PackageJson } from 'type-fest'\r\nimport { findParent } from '../../utils'\r\n\r\n/**\r\n * \u5224\u65AD\u662F\u5426\u5305\u542B package.json\r\n * @param cwd\r\n */\r\nexport async function isNpmPackage(\r\n cwd: string = process.cwd(),\r\n): Promise<boolean> {\r\n return await pathExists(path.resolve(cwd, './package.json'))\r\n}\r\n\r\n/**\r\n * \u5224\u65AD\u662F yarn2 monorepo \u9879\u76EE\r\n * @param cwd\r\n */\r\nexport async function isYarnRoot(\r\n cwd: string = process.cwd(),\r\n): Promise<boolean> {\r\n if (!(await isNpmPackage(cwd))) {\r\n return false\r\n }\r\n const json = (await readJson(\r\n path.resolve(cwd, './package.json'),\r\n )) as PackageJson\r\n return !!json.workspaces\r\n}\r\n\r\n/**\r\n * \u5224\u65AD\u662F yarn2 monorepo \u7684\u5B50\u6A21\u5757\r\n */\r\nexport async function isYarnSubModule(\r\n cwd: string = process.cwd(),\r\n): Promise<boolean> {\r\n if (!(await isNpmPackage(cwd))) {\r\n return false\r\n }\r\n //\u5982\u679C\u662F yarn monorepo \u6839\u6A21\u5757\u5219\u76F4\u63A5\u8FD4\u56DE true\r\n if (await isYarnRoot(cwd)) {\r\n return false\r\n }\r\n return (await findParent(path.dirname(cwd), isYarnRoot)) !== null\r\n}\r\n\r\n/**\r\n * \u662F\u5426\u5305\u542B\u6307\u5B9A\u4F9D\u8D56\r\n * @param deps\r\n * @param cwd\r\n */\r\nexport async function isIncludeDep(\r\n deps: string[],\r\n cwd: string = process.cwd(),\r\n): Promise<boolean> {\r\n if (!(await isNpmPackage(cwd))) {\r\n return false\r\n }\r\n const json = (await readJson(\r\n path.resolve(cwd, './package.json'),\r\n )) as PackageJson\r\n const set = new Set(\r\n Object.keys({ ...json.dependencies, ...json.devDependencies }),\r\n )\r\n return deps.every((dep) => set.has(dep))\r\n}\r\n", "export function arrayToMap<T, K>(\r\n arr: T[],\r\n kFn: (item: T, index: number, arr: T[]) => K,\r\n): Map<K, T>\r\nexport function arrayToMap<T, K, V>(\r\n arr: T[],\r\n kFn: (item: T, index: number, arr: T[]) => K,\r\n vFn: (item: T, index: number, arr: T[]) => V,\r\n): Map<K, V>\r\n/**\r\n * \u5C06\u6570\u7EC4\u6620\u5C04\u4E3A Map\r\n * @param arr \u6570\u7EC4\r\n * @param kFn \u4EA7\u751F Map \u5143\u7D20\u552F\u4E00\u6807\u8BC6\u7684\u51FD\u6570\r\n * @param vFn \u4EA7\u751F Map \u503C\u7684\u51FD\u6570\uFF0C\u9ED8\u8BA4\u4E3A\u8FD4\u56DE\u6570\u7EC4\u7684\u5143\u7D20\r\n * @returns \u6620\u5C04\u4EA7\u751F\u7684 map \u96C6\u5408\r\n */\r\nexport function arrayToMap<T, K, V>(\r\n arr: T[],\r\n kFn: (item: T, index: number, arr: T[]) => K,\r\n vFn: (item: T, index: number, arr: T[]) => V = (v) => v as any,\r\n): Map<K, V> {\r\n return arr.reduce(\r\n (res, item, index, arr) =>\r\n res.set(kFn(item, index, arr), vFn(item, index, arr)),\r\n new Map<K, V>(),\r\n )\r\n}\r\n", "/**\r\n * \u5728\u4E4B\u524D\u7684\u811A\u672C\u4E2D\u8FFD\u52A0\u65B0\u7684\u811A\u672C\r\n * @param oldScript\r\n * @param newScript\r\n */\r\nexport function appendScript(\r\n oldScript: string | undefined,\r\n newScript: string,\r\n): string {\r\n if (!oldScript) {\r\n return newScript\r\n }\r\n if (oldScript.includes(newScript)) {\r\n return oldScript\r\n }\r\n return oldScript + ' && ' + newScript\r\n}\r\n", "import path from 'path'\r\n\r\n/**\r\n * \u5411\u4E0A\u67E5\u627E\u76EE\u5F55\r\n * @param cwd\r\n * @param predicate\r\n */\r\nexport function findParent(\r\n cwd: string,\r\n predicate: (dir: string) => boolean,\r\n): string | null\r\nexport function findParent(\r\n cwd: string,\r\n predicate: (dir: string) => Promise<boolean>,\r\n): Promise<string | null>\r\nexport function findParent<\r\n T extends (dir: string) => boolean | Promise<boolean>,\r\n R extends string | null,\r\n>(\r\n cwd: string,\r\n predicate: T,\r\n): ReturnType<T> extends Promise<any> ? Promise<R> : R {\r\n const res = predicate(cwd)\r\n function f(res: boolean): string | null {\r\n if (res) {\r\n return cwd\r\n }\r\n const parent = path.dirname(cwd)\r\n if (parent === cwd) {\r\n return null\r\n }\r\n return findParent(parent, predicate as any)\r\n }\r\n\r\n return res instanceof Promise ? res.then(f) : (f(res) as any)\r\n}\r\n", "import { IterableElement } from 'type-fest'\r\n\r\nenum ActionTypeEnum {\r\n Filter = 'filter',\r\n Map = 'map',\r\n ForEach = 'forEach',\r\n Reduce = 'reduce',\r\n FlatMap = 'flatMap',\r\n}\r\n\r\nclass Action {\r\n public static Type = ActionTypeEnum\r\n\r\n constructor(\r\n public readonly type: ActionTypeEnum,\r\n public readonly args: any[],\r\n ) {\r\n this.type = type\r\n this.args = args\r\n }\r\n}\r\n\r\n/**\r\n * \u5F02\u6B65\u6570\u7EC4\uFF0C\u652F\u6301\u9759\u6001\u65B9\u6CD5\u548C\u94FE\u5F0F\u8C03\u7528\r\n */\r\nexport class AsyncArray<T> implements PromiseLike<T[]> {\r\n static reduce<T extends any[], R>(\r\n arr: T,\r\n fn: (res: R, item: IterableElement<T>, index: number) => Promise<R>,\r\n res: R,\r\n ): Promise<R> {\r\n return arr.reduce(\r\n (res: Promise<R>, item: IterableElement<T>, index: number) =>\r\n res.then((r) => fn(r, item, index)),\r\n Promise.resolve(res),\r\n )\r\n }\r\n\r\n static map<T, R>(\r\n arr: T[],\r\n fn: (item: T, index: number) => Promise<R>,\r\n ): Promise<R[]> {\r\n return Promise.all(arr.map((item, index) => fn(item, index)))\r\n }\r\n\r\n static async filter<T>(\r\n arr: T[],\r\n fn: (item: T, index: number) => Promise<boolean>,\r\n ): Promise<T[]> {\r\n const res: T[] = []\r\n await AsyncArray.map(arr, async (item, index) => {\r\n if (await fn(item, index)) {\r\n res.push(item)\r\n }\r\n })\r\n return res\r\n }\r\n\r\n static async flatMap<T, R>(\r\n arr: T[],\r\n fn: (item: T, index: number) => Promise<R[]>,\r\n ): Promise<R[]> {\r\n return (\r\n await Promise.all(arr.map((item, index) => fn(item, index)))\r\n ).flatMap((r) => r)\r\n }\r\n\r\n static async forEach<T extends any[]>(\r\n arr: T,\r\n fn: (item: IterableElement<T>, index: number) => Promise<void>,\r\n ): Promise<void> {\r\n await AsyncArray.map(arr, fn)\r\n }\r\n\r\n private tasks: Action[] = []\r\n\r\n constructor(private readonly arr: T[]) {}\r\n\r\n map<R>(fn: (item: T, index: number) => Promise<R>): AsyncArray<R> {\r\n this.tasks.push(new Action(ActionTypeEnum.Map, [fn]))\r\n return this as any\r\n }\r\n\r\n flatMap<R>(fn: (item: T, index: number) => Promise<R[]>): AsyncArray<R> {\r\n this.tasks.push(new Action(ActionTypeEnum.FlatMap, [fn]))\r\n return this as any\r\n }\r\n\r\n filter(fn: (item: T, index: number) => Promise<boolean>): this {\r\n this.tasks.push(new Action(ActionTypeEnum.Filter, [fn]))\r\n return this\r\n }\r\n\r\n async forEach<R>(fn: (item: T, index: number) => Promise<R>): Promise<void> {\r\n this.tasks.push(new Action(ActionTypeEnum.Map, [fn]))\r\n await this\r\n }\r\n\r\n then<TResult1 = T[], TResult2 = never>(\r\n resolve?:\r\n | ((value: T[]) => PromiseLike<TResult1> | TResult1)\r\n | undefined\r\n | null,\r\n reject?:\r\n | ((reason: any) => PromiseLike<TResult2> | TResult2)\r\n | undefined\r\n | null,\r\n ): PromiseLike<TResult1 | TResult2> {\r\n const res = this.value()\r\n res\r\n .then((r) => {\r\n resolve && resolve(res as any)\r\n return r\r\n })\r\n .catch((e) => {\r\n reject && reject(e as any)\r\n throw e\r\n })\r\n return res as any\r\n }\r\n\r\n private async value(): Promise<any> {\r\n let res = this.arr\r\n for (const task of this.tasks) {\r\n switch (task.type) {\r\n case ActionTypeEnum.Filter:\r\n res = await AsyncArray.filter(res, task.args[0])\r\n break\r\n case ActionTypeEnum.Map:\r\n res = await AsyncArray.map(res, task.args[0])\r\n break\r\n case ActionTypeEnum.FlatMap:\r\n res = await AsyncArray.flatMap(res, task.args[0])\r\n break\r\n case ActionTypeEnum.ForEach:\r\n await AsyncArray.forEach(res, task.args[0])\r\n return\r\n case ActionTypeEnum.Reduce:\r\n return await AsyncArray.reduce(res, task.args[0], task.args[1])\r\n }\r\n }\r\n return res\r\n }\r\n}\r\n", "import path from 'path'\r\n\r\nexport class PathUtil {\r\n /**\r\n * \u4ECE\u8FD9\u4E2A\u9879\u76EE\u7684\u6839\u76EE\u5F55\u8BFB\u53D6\uFF0C\u5F00\u53D1\u73AF\u5883\u662F src/../\uFF0C\u8FD0\u884C\u65F6\u5219\u662F dist/../\r\n */\r\n static readonly RootPath = path.resolve(__dirname, '..')\r\n}\r\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["export * from './commands/esbuild/ESBuildProgram'\r\nexport * from './commands/generate/GenerateProgram'\r\nexport * from './commands/sync/SyncProgram'\r\n", "import { build, BuildOptions, Platform, Plugin } from 'esbuild'\r\nimport { pathExists, readFile, readJson, remove } from 'fs-extra'\r\nimport * as path from 'path'\r\nimport { PackageJson } from 'type-fest'\r\nimport { Project } from 'ts-morph'\r\nimport { promise } from 'glob-promise'\r\nimport { IOptions } from 'glob'\r\nimport { nativeNodeModules, nodeExternals, userJS } from './util/esbuildPlugins'\r\nimport { watch } from 'chokidar'\r\nimport Spinnies from 'spinnies'\r\nimport { debounce } from './util/debounce'\r\nimport { parse } from 'json5'\r\nimport { getPkgGlobalName } from './util/getPkgGlobalName'\r\n\r\ninterface ESBuildProgramOptions {\r\n base: string\r\n isWatch: boolean\r\n}\r\n\r\ninterface Task {\r\n title: string\r\n task(): Promise<any>\r\n}\r\n\r\nexport type TaskTypeEnum = 'esm' | 'cjs' | 'iife' | 'cli' | 'dts' | 'userjs'\r\n\r\nexport class ESBuildProgram {\r\n constructor(private readonly options: ESBuildProgramOptions) {}\r\n\r\n set isWatch(isWatch: boolean) {\r\n this.options.isWatch = isWatch\r\n }\r\n\r\n static readonly globalExternal = ['esbuild', 'pnpapi', 'ts-morph', 'ssh2']\r\n\r\n /**\r\n * \u83B7\u53D6\u6240\u6709\u4F9D\u8D56\r\n */\r\n static async getDeps(base: string): Promise<string[]> {\r\n const json = (await readJson(path.resolve(base, 'package.json'))) as PackageJson\r\n return Object.keys({\r\n ...json.dependencies,\r\n ...json.devDependencies,\r\n ...json.peerDependencies,\r\n })\r\n }\r\n\r\n /**\r\n * \u83B7\u53D6\u6240\u5728\u6A21\u5757\u7684\u7C7B\u578B\r\n */\r\n static async getPlatform(base: string): Promise<Platform> {\r\n const tsconfigPath = path.resolve(base, 'tsconfig.json')\r\n if (await pathExists(tsconfigPath)) {\r\n const tsconfigJson = parse(await readFile(tsconfigPath, 'utf-8'))\r\n if ((tsconfigJson?.compilerOptions?.lib as string[])?.some((lib) => lib.toLowerCase() === 'dom')) {\r\n return 'browser'\r\n }\r\n }\r\n const pkgPath = path.resolve(base, 'package.json')\r\n if (await pathExists(pkgPath)) {\r\n const pkgJson = (await readJson(pkgPath)) as PackageJson\r\n if (Object.keys(pkgJson.devDependencies ?? {}).includes('@types/node')) {\r\n return 'node'\r\n }\r\n }\r\n return 'neutral'\r\n }\r\n static getWatchOptions(base: string): {\r\n pattern: string\r\n options: IOptions\r\n } {\r\n const pattern = 'src/**/*.ts'\r\n const options: Pick<IOptions, 'cwd' | 'ignore'> = {\r\n cwd: base,\r\n ignore: '**/__tests__/**/*',\r\n }\r\n return { pattern, options }\r\n }\r\n /**\r\n * \u751F\u6210\u7C7B\u578B\u5B9A\u4E49\r\n */\r\n async genDTS(): Promise<void> {\r\n const base = this.options.base\r\n const { pattern, options } = ESBuildProgram.getWatchOptions(this.options.base)\r\n const project = new Project({\r\n tsConfigFilePath: path.resolve(base, 'tsconfig.json'),\r\n skipAddingFilesFromTsConfig: true,\r\n compilerOptions: {\r\n emitDeclarationOnly: true,\r\n noEmit: false,\r\n incremental: this.options.isWatch,\r\n },\r\n })\r\n const fileList = (await promise(pattern, options)).map((filePath) => path.resolve(base, filePath))\r\n project.addSourceFilesAtPaths(fileList)\r\n await project.emit({\r\n emitOnlyDtsFiles: true,\r\n })\r\n }\r\n /**\r\n * \u83B7\u53D6\u6784\u5EFA cjs \u7684\u9009\u9879\r\n */\r\n getBuildUserJSOption(): BuildOptions {\r\n return {\r\n entryPoints: [path.resolve(this.options.base, './src/index.ts')],\r\n outfile: path.resolve(this.options.base, './dist/index.user.js'),\r\n format: 'iife',\r\n bundle: true,\r\n external: [...ESBuildProgram.globalExternal],\r\n platform: 'browser',\r\n plugins: [userJS()],\r\n incremental: this.options.isWatch,\r\n absWorkingDir: this.options.base,\r\n }\r\n }\r\n\r\n /**\r\n * \u83B7\u53D6\u6784\u5EFA cjs \u7684\u9009\u9879\r\n * @param deps\r\n * @param platform\r\n * @param plugins\r\n */\r\n getBuildCjsOption({ deps, platform }: { deps: string[]; platform: Platform }): BuildOptions {\r\n return {\r\n entryPoints: [path.resolve(this.options.base, './src/index.ts')],\r\n outfile: path.resolve(this.options.base, './dist/index.js'),\r\n format: 'cjs',\r\n sourcemap: true,\r\n bundle: true,\r\n external: [...ESBuildProgram.globalExternal, ...deps],\r\n platform: platform,\r\n minify: !this.options.isWatch,\r\n incremental: this.options.isWatch,\r\n metafile: this.options.isWatch,\r\n }\r\n }\r\n\r\n /**\r\n * \u83B7\u53D6\u6784\u5EFA esm \u7684\u9009\u9879\r\n * @param deps\r\n * @param platform\r\n * @param plugins\r\n */\r\n getBuildESMOption({ deps, platform }: { deps: string[]; platform: Platform }): BuildOptions {\r\n return {\r\n entryPoints: [path.resolve(this.options.base, './src/index.ts')],\r\n outfile: path.resolve(this.options.base, './dist/index.esm.js'),\r\n format: 'esm',\r\n sourcemap: true,\r\n bundle: true,\r\n external: [...ESBuildProgram.globalExternal, ...deps],\r\n platform: platform,\r\n minify: !this.options.isWatch,\r\n incremental: this.options.isWatch,\r\n metafile: this.options.isWatch,\r\n }\r\n }\r\n\r\n /**\r\n * \u83B7\u53D6\u6784\u5EFA iife \u7684\u9009\u9879\r\n * @param deps\r\n * @param platform\r\n */\r\n getBuildIifeOption({ platform, globalName }: { platform: Platform; globalName: string }): BuildOptions {\r\n return {\r\n entryPoints: [path.resolve(this.options.base, './src/index.ts')],\r\n outfile: path.resolve(this.options.base, './dist/index.iife.js'),\r\n format: 'iife',\r\n sourcemap: true,\r\n bundle: true,\r\n external: [...ESBuildProgram.globalExternal],\r\n platform: platform,\r\n minify: !this.options.isWatch,\r\n incremental: this.options.isWatch,\r\n metafile: this.options.isWatch,\r\n globalName,\r\n }\r\n }\r\n\r\n /**\r\n * \u83B7\u53D6\u6784\u5EFA cli \u7684\u9009\u9879\r\n * @param deps\r\n * @param platform\r\n */\r\n getBuildCliOption({ platform }: { deps: string[]; platform: Platform }): BuildOptions {\r\n const plugins = ESBuildProgram.getPlugins(platform)\r\n return {\r\n entryPoints: [path.resolve(this.options.base, './src/bin.ts')],\r\n outfile: path.resolve(this.options.base, './dist/bin.js'),\r\n format: 'cjs',\r\n sourcemap: true,\r\n platform: platform,\r\n bundle: true,\r\n banner: {\r\n js: '#!/usr/bin/env node',\r\n },\r\n external: [...ESBuildProgram.globalExternal],\r\n plugins,\r\n minify: !this.options.isWatch,\r\n incremental: this.options.isWatch,\r\n metafile: this.options.isWatch,\r\n }\r\n }\r\n\r\n static getPlugins(platform: string): Plugin[] {\r\n const plugins: Plugin[] = []\r\n if (platform === 'node') {\r\n plugins.push(nodeExternals(), nativeNodeModules())\r\n }\r\n return plugins\r\n }\r\n\r\n async build(options: BuildOptions): Promise<void> {\r\n // if (this.options.isWatch) {\r\n // options.plugins = [...(options.plugins ?? []), metafile(options.outfile + '.meta.json')]\r\n // }\r\n await build(options)\r\n }\r\n\r\n async getTasks(): Promise<Record<TaskTypeEnum, Task>> {\r\n const deps = await ESBuildProgram.getDeps(this.options.base)\r\n const platform = await ESBuildProgram.getPlatform(this.options.base)\r\n return {\r\n esm: {\r\n title: '\u6784\u5EFA esm',\r\n task: () =>\r\n this.build(\r\n this.getBuildESMOption({\r\n deps: deps,\r\n platform: platform,\r\n }),\r\n ),\r\n },\r\n cjs: {\r\n title: '\u6784\u5EFA cjs',\r\n task: () =>\r\n this.build(\r\n this.getBuildCjsOption({\r\n deps: deps,\r\n platform: platform,\r\n }),\r\n ),\r\n },\r\n iife: {\r\n title: '\u6784\u5EFA iife',\r\n task: async () => {\r\n return await this.build(\r\n this.getBuildIifeOption({\r\n platform: platform,\r\n globalName: getPkgGlobalName(\r\n ((await readJson(path.resolve(this.options.base, './package.json'))) as PackageJson).name!,\r\n ),\r\n }),\r\n )\r\n },\r\n },\r\n cli: {\r\n title: '\u6784\u5EFA cli',\r\n task: () =>\r\n build(\r\n this.getBuildCliOption({\r\n deps: deps,\r\n platform: platform,\r\n }),\r\n ),\r\n },\r\n dts: {\r\n title: '\u751F\u6210\u7C7B\u578B\u5B9A\u4E49',\r\n task: () => this.genDTS(),\r\n },\r\n userjs: {\r\n title: '\u6253\u5305 userjs',\r\n task: () => this.build(this.getBuildUserJSOption()),\r\n },\r\n }\r\n }\r\n\r\n static async execTask(spinnies: Spinnies, task: Task): Promise<void> {\r\n const start = Date.now()\r\n spinnies.add(task.title, { text: task.title })\r\n try {\r\n await task.task()\r\n spinnies.succeed(task.title, {\r\n text: `${task.title}: ${Date.now() - start}ms`,\r\n })\r\n } catch (e) {\r\n spinnies.fail(task.title, { text: task.title })\r\n }\r\n }\r\n async execTasks(tasks: Task[]): Promise<void> {\r\n const run = async () => {\r\n const start = Date.now()\r\n const spinnies = new Spinnies()\r\n await Promise.all(tasks.map(async (task) => ESBuildProgram.execTask(spinnies, task)))\r\n console.log(`\u6784\u5EFA\u5B8C\u6210: ${Date.now() - start}ms`)\r\n }\r\n\r\n if (!this.options.isWatch) {\r\n await remove(path.resolve(this.options.base, 'dist'))\r\n await run()\r\n return\r\n }\r\n\r\n const { pattern, options } = ESBuildProgram.getWatchOptions(this.options.base)\r\n await new Promise((resolve, reject) => {\r\n watch(pattern, options).on('error', reject).on('all', debounce(run, 10))\r\n })\r\n }\r\n}\r\n", "import { Plugin } from 'esbuild'\r\nimport { readJson, writeJson } from 'fs-extra'\r\nimport path from 'path'\r\n\r\n/**\r\n * \u5904\u7406 nodejs \u539F\u751F\u6A21\u5757\r\n * @link https://github.com/evanw/esbuild/issues/1051#issuecomment-806325487\r\n */\r\nexport function nativeNodeModules(): Plugin {\r\n return {\r\n name: 'native-node-modules',\r\n setup(build) {\r\n // If a \".node\" file is imported within a module in the \"file\" namespace, resolve\r\n // it to an absolute path and put it into the \"node-file\" virtual namespace.\r\n build.onResolve({ filter: /\\.node$/, namespace: 'file' }, (args) => ({\r\n path: require.resolve(args.path, { paths: [args.resolveDir] }),\r\n namespace: 'node-file',\r\n }))\r\n\r\n // Files in the \"node-file\" virtual namespace call \"require()\" on the\r\n // path from esbuild of the \".node\" file in the output directory.\r\n build.onLoad({ filter: /.*/, namespace: 'node-file' }, (args) => ({\r\n contents: `\r\n import path from ${JSON.stringify(args.path)}\r\n try { module.exports = require(path) }\r\n catch {}\r\n `,\r\n }))\r\n\r\n // If a \".node\" file is imported within a module in the \"node-file\" namespace, put\r\n // it in the \"file\" namespace where esbuild's default loading behavior will handle\r\n // it. It is already an absolute path since we resolved it to one above.\r\n build.onResolve({ filter: /\\.node$/, namespace: 'node-file' }, (args) => ({\r\n path: args.path,\r\n namespace: 'file',\r\n }))\r\n\r\n // Tell esbuild's default loading behavior to use the \"file\" loader for\r\n // these \".node\" files.\r\n const opts = build.initialOptions\r\n opts.loader = opts.loader || {}\r\n opts.loader['.node'] = 'file'\r\n },\r\n }\r\n}\r\n\r\n/**\r\n * \u6392\u9664\u548C\u66FF\u6362 node \u5185\u7F6E\u6A21\u5757\r\n */\r\nexport function nodeExternals(): Plugin {\r\n return {\r\n name: 'esbuild-plugin-node-externals',\r\n setup(build) {\r\n build.onResolve({ filter: /(^node:)/ }, (args) => ({\r\n path: args.path.slice(5),\r\n external: true,\r\n }))\r\n },\r\n }\r\n}\r\n\r\n/**\r\n * \u81EA\u52A8\u6392\u9664\u6240\u6709\u4F9D\u8D56\u9879\r\n * golang \u4E0D\u652F\u6301 js \u7684\u4E00\u4E9B\u8BED\u6CD5\uFF0C\u53C2\u8003 https://github.com/evanw/esbuild/issues/1634\r\n */\r\nexport function autoExternal(): Plugin {\r\n return {\r\n name: 'esbuild-plugin-auto-external',\r\n setup(build) {\r\n build.onResolve({ filter: /.*/ }, (args) => {\r\n if (/^\\.{1,2}\\//.test(args.path)) {\r\n return\r\n }\r\n return {\r\n path: args.path,\r\n external: true,\r\n }\r\n })\r\n },\r\n }\r\n}\r\n\r\n/**\r\n * \u751F\u6210 metafile \u7684\u63D2\u4EF6\r\n * @param metafilePath\r\n */\r\nexport function metafile(metafilePath: string): Plugin {\r\n return {\r\n name: 'esbuild-plugin-metafile',\r\n setup(builder) {\r\n builder.onEnd(async (result) => {\r\n await writeJson(metafilePath, result.metafile)\r\n })\r\n },\r\n }\r\n}\r\n\r\nfunction generateBanner(meta: object) {\r\n return (\r\n [\r\n '// ==UserScript==',\r\n ...Object.entries(meta)\r\n .map(([key, value]) => {\r\n if (Array.isArray(value)) {\r\n return value.map((item) => `// @${key} ${item}`)\r\n }\r\n return `// @${key} ${value}`\r\n })\r\n .flat(),\r\n '// ==/UserScript==',\r\n ].join('\\n') + '\\n'\r\n )\r\n}\r\n\r\nexport function userJS(): Plugin {\r\n return {\r\n name: 'esbuild-plugin-userjs',\r\n async setup(build) {\r\n const json = (await readJson(path.resolve(build.initialOptions.absWorkingDir!, 'package.json'))) as {\r\n userjs: object\r\n }\r\n if (!json.userjs) {\r\n throw new Error('userjs is not supported')\r\n }\r\n if (!build.initialOptions.banner) {\r\n build.initialOptions.banner = {}\r\n }\r\n build.initialOptions.banner!['js'] = generateBanner(json.userjs)\r\n },\r\n }\r\n}\r\n", "/**\r\n * \u51FD\u6570\u53BB\u6296\r\n * \u53BB\u6296 (debounce) \u53BB\u6296\u5C31\u662F\u5BF9\u4E8E\u4E00\u5B9A\u65F6\u95F4\u6BB5\u7684\u8FDE\u7EED\u7684\u51FD\u6570\u8C03\u7528\uFF0C\u53EA\u8BA9\u5176\u6267\u884C\u4E00\u6B21\r\n * \u6CE8: \u5305\u88C5\u540E\u7684\u51FD\u6570\u5982\u679C\u4E24\u6B21\u64CD\u4F5C\u95F4\u9694\u5C0F\u4E8E delay \u5219\u4E0D\u4F1A\u88AB\u6267\u884C, \u5982\u679C\u4E00\u76F4\u5728\u64CD\u4F5C\u5C31\u4F1A\u4E00\u76F4\u4E0D\u6267\u884C, \u76F4\u5230\u64CD\u4F5C\u505C\u6B62\u7684\u65F6\u95F4\u5927\u4E8E delay \u6700\u5C0F\u95F4\u9694\u65F6\u95F4\u624D\u4F1A\u6267\u884C\u4E00\u6B21, \u4E0D\u7BA1\u4EFB\u4F55\u65F6\u95F4\u8C03\u7528\u90FD\u9700\u8981\u505C\u6B62\u64CD\u4F5C\u7B49\u5F85\u6700\u5C0F\u5EF6\u8FDF\u65F6\u95F4\r\n * \u5E94\u7528\u573A\u666F\u4E3B\u8981\u5728\u90A3\u4E9B\u8FDE\u7EED\u7684\u64CD\u4F5C, \u4F8B\u5982\u9875\u9762\u6EDA\u52A8\u76D1\u542C, \u5305\u88C5\u540E\u7684\u51FD\u6570\u53EA\u4F1A\u6267\u884C\u6700\u540E\u4E00\u6B21\r\n * \u6CE8: \u8BE5\u51FD\u6570\u7B2C\u4E00\u6B21\u8C03\u7528\u4E00\u5B9A\u4E0D\u4F1A\u6267\u884C\uFF0C\u7B2C\u4E00\u6B21\u4E00\u5B9A\u62FF\u4E0D\u5230\u7F13\u5B58\u503C\uFF0C\u540E\u9762\u7684\u8FDE\u7EED\u8C03\u7528\u90FD\u4F1A\u62FF\u5230\u4E0A\u4E00\u6B21\u7684\u7F13\u5B58\u503C\u3002\u5982\u679C\u9700\u8981\u5728\u7B2C\u4E00\u6B21\u8C03\u7528\u83B7\u53D6\u5230\u7684\u7F13\u5B58\u503C\uFF0C\u5219\u9700\u8981\u4F20\u5165\u7B2C\u4E09\u4E2A\u53C2\u6570 {@param init}\uFF0C\u9ED8\u8BA4\u4E3A {@code undefined} \u7684\u53EF\u9009\u53C2\u6570\r\n * \u6CE8: \u8FD4\u56DE\u51FD\u6570\u7ED3\u679C\u7684\u9AD8\u9636\u51FD\u6570\u9700\u8981\u4F7F\u7528 {@see Proxy} \u5B9E\u73B0\uFF0C\u4EE5\u907F\u514D\u539F\u51FD\u6570\u539F\u578B\u94FE\u4E0A\u7684\u4FE1\u606F\u4E22\u5931\r\n *\r\n * @param fn \u771F\u6B63\u9700\u8981\u6267\u884C\u7684\u64CD\u4F5C\r\n * @param delay \u6700\u5C0F\u5EF6\u8FDF\u65F6\u95F4\uFF0C\u5355\u4F4D\u4E3A ms\r\n * @param init \u521D\u59CB\u7684\u7F13\u5B58\u503C\uFF0C\u4E0D\u586B\u9ED8\u8BA4\u4E3A {@see undefined}\r\n * @return \u5305\u88C5\u540E\u6709\u53BB\u6296\u529F\u80FD\u7684\u51FD\u6570\u3002\u8BE5\u51FD\u6570\u662F\u5F02\u6B65\u7684\uFF0C\u4E0E\u9700\u8981\u5305\u88C5\u7684\u51FD\u6570 {@param fn} \u662F\u5426\u5F02\u6B65\u6CA1\u6709\u592A\u5927\u5173\u8054\r\n */\r\nexport function debounce<\r\n T extends (...args: any[]) => any,\r\n R extends (...args: Parameters<T>) => Promise<ReturnType<T>>,\r\n>(fn: T, delay: number, init: any = null): R {\r\n let flag: number\r\n let result = init\r\n return async function (...args) {\r\n return new Promise((resolve) => {\r\n if (flag) {\r\n clearTimeout(flag as any)\r\n }\r\n flag = setTimeout(() => resolve((result = fn(...args))), delay) as any\r\n setTimeout(() => resolve(result), delay)\r\n })\r\n } as R\r\n}\r\n", "/**\r\n * \u8F6C\u6362 npm \u5305\u540D\u4E3A\u4E00\u4E2A\u5408\u9002\u7684\u5168\u5C40\u53D8\u91CF\u540D\r\n * @param name\r\n */\r\nexport function getPkgGlobalName(name: string): string {\r\n const temp = name.startsWith('@') ? name.slice(name.indexOf('/') + 1) : name\r\n return temp\r\n .split('-')\r\n .map((s) => s.slice(0, 1).toUpperCase() + s.slice(1).toLowerCase())\r\n .join('')\r\n}\r\n", "import path from 'path'\r\nimport { copy, pathExists, readdir, readFile, readJSON, remove, writeFile, writeJSON } from 'fs-extra'\r\nimport { prompt } from 'enquirer'\r\nimport { SyncProgram } from '../sync/SyncProgram'\r\nimport { PathUtil } from '../../PathUtil'\r\n\r\nexport enum TemplateTypeEnum {\r\n Cli = 'cli',\r\n Lib = 'lib',\r\n}\r\n\r\nexport interface GenerateConfig {\r\n template: TemplateTypeEnum\r\n dest: string\r\n initSync?: boolean\r\n}\r\n\r\nexport class GenerateProgram {\r\n /**\r\n * \u751F\u6210\u9879\u76EE\r\n */\r\n async generate(config: GenerateConfig): Promise<void> {\r\n if (!config.dest) {\r\n const { dest } = await prompt<{ dest: string }>({\r\n name: 'dest',\r\n type: 'input',\r\n message: '\u8BF7\u8F93\u5165\u9879\u76EE\u540D',\r\n validate(input: string): boolean {\r\n return input.trim() !== ''\r\n },\r\n })\r\n config.dest = path.resolve(dest)\r\n }\r\n if (!config.template) {\r\n const { template } = await prompt<{ template: TemplateTypeEnum }>({\r\n name: 'template',\r\n type: 'select',\r\n message: '\u8BF7\u9009\u62E9\u6A21\u677F',\r\n choices: [TemplateTypeEnum.Lib, TemplateTypeEnum.Cli] as TemplateTypeEnum[],\r\n })\r\n config.template = template\r\n }\r\n\r\n /*\r\n \u514B\u9686\u9879\u76EE\r\n \u4FEE\u6539\u4E00\u4E9B\u5185\u5BB9\r\n \u5171\u901A\u4FEE\u6539\r\n - \u4FEE\u6539 package.json\uFF0C\u5220\u9664 private\uFF0C\u4FEE\u6539\u540D\u5B57\r\n \u6A21\u677F\u7279\u5B9A\u4FEE\u6539\r\n */\r\n const srcFile = path.resolve(PathUtil.RootPath, `templates/${config.template}`)\r\n const destFile = path.resolve(config.dest)\r\n if ((await pathExists(destFile)) && (await readdir(destFile)).some((file) => pathExists(file))) {\r\n const { override } = await prompt<{\r\n override: boolean\r\n }>({\r\n name: 'override',\r\n type: 'confirm',\r\n initial: true,\r\n message: '\u76EE\u6807\u4F4D\u7F6E\u4E0D\u662F\u4E00\u4E2A\u7A7A\u76EE\u5F55\uFF0C\u786E\u8BA4\u8981\u8986\u76D6\u4E48\uFF1F',\r\n })\r\n if (!override) {\r\n return\r\n }\r\n }\r\n await remove(destFile)\r\n await copy(srcFile, destFile, {\r\n filter: (source) => path.basename(source) !== 'node_modules',\r\n })\r\n await GenerateProgram.updatePackageJSON(destFile)\r\n await GenerateProgram.updateReadme(destFile)\r\n if (config.initSync) {\r\n const syncProgram = new SyncProgram(path.resolve(config.dest))\r\n await syncProgram.init()\r\n await syncProgram.sync()\r\n }\r\n }\r\n\r\n static async updatePackageJSON(destFile: string): Promise<void> {\r\n const pkgPath = path.resolve(destFile, 'package.json')\r\n await writeJSON(\r\n pkgPath,\r\n {\r\n ...(await readJSON(pkgPath)),\r\n name: path.basename(destFile),\r\n },\r\n {\r\n spaces: 2,\r\n },\r\n )\r\n }\r\n\r\n static async updateReadme(destFile: string): Promise<void> {\r\n const readmePath = path.resolve(destFile, 'README.md')\r\n let readmeFile = await readFile(readmePath, 'utf-8')\r\n readmeFile = readmeFile.replace('template', path.basename(destFile))\r\n await writeFile(readmePath, readmeFile)\r\n }\r\n}\r\n", "import { readFile, readJson, writeFile, writeJson } from 'fs-extra'\r\nimport path from 'path'\r\nimport { merge } from 'lodash'\r\nimport { PackageJson } from 'type-fest'\r\nimport prettier from '@liuli-util/prettier-standard-config/package.json'\r\nimport eslintTs from '@liuli-util/eslint-config-ts/package.json'\r\nimport eslintReactTs from '@liuli-util/eslint-config-react-ts/package.json'\r\nimport commitlint from '@liuli-util/commitlint-standard-config/package.json'\r\nimport { prompt } from 'enquirer'\r\nimport { isIncludeDep, isNpmPackage, isYarnRoot, isYarnSubModule } from './when'\r\nimport { appendScript, arrayToMap, AsyncArray } from '../../utils'\r\nimport { PathUtil } from '../../PathUtil'\r\n\r\nexport async function mergeJson(base: string, json: object): Promise<void> {\r\n const pkgJsonFilePath = path.resolve(base, './package.json')\r\n await writeJson(pkgJsonFilePath, merge(await readJson(pkgJsonFilePath), json), {\r\n spaces: 2,\r\n })\r\n}\r\n\r\nexport type SyncConfigType =\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 | 'eslint-react-ts'\r\n | 'jest'\r\n\r\nexport interface SyncConfig {\r\n type: SyncConfigType\r\n handler(): Promise<void>\r\n when?(): Promise<boolean>\r\n}\r\n\r\nexport class SyncProgram {\r\n constructor(private readonly base: string) {}\r\n private syncConfigs: SyncConfig[] = [\r\n {\r\n type: 'workspaces',\r\n handler: async () => {\r\n const pkgPath = path.resolve(this.base, './package.json')\r\n const lernaPath = path.resolve(this.base, 'lerna.json')\r\n const pkgJson = (await readJson(pkgPath)) as { workspaces: string[] }\r\n const lernaJson = await readJson(lernaPath)\r\n lernaJson.packages = pkgJson.workspaces\r\n await writeJson(lernaPath, lernaJson, {\r\n spaces: 2,\r\n })\r\n },\r\n when: isYarnRoot,\r\n },\r\n {\r\n type: 'prettier',\r\n handler: async () => {\r\n await mergeJson(this.base, {\r\n prettier: '@liuli-util/prettier-standard-config',\r\n devDependencies: {\r\n prettier: '^2.3.2',\r\n '@liuli-util/prettier-standard-config': `^${prettier.version}`,\r\n },\r\n } as PackageJson)\r\n },\r\n async when(): Promise<boolean> {\r\n return (await isNpmPackage()) && ((await isYarnRoot()) || !(await isYarnSubModule()))\r\n },\r\n },\r\n {\r\n type: 'commitlint',\r\n handler: async () => {\r\n await mergeJson(this.base, {\r\n 'simple-git-hooks': {\r\n 'commit-msg': 'yarn commitlint --edit $1',\r\n },\r\n commitlint: {\r\n extends: ['@liuli-util/commitlint-standard-config'],\r\n },\r\n devDependencies: {\r\n '@commitlint/cli': '^12.1.4',\r\n '@liuli-util/commitlint-standard-config': `^${commitlint.version}`,\r\n },\r\n } as PackageJson)\r\n },\r\n async when(): Promise<boolean> {\r\n return (await isNpmPackage()) && ((await isYarnRoot()) || !(await isYarnSubModule()))\r\n },\r\n },\r\n {\r\n type: 'gitignore',\r\n handler: async () => {\r\n const gitignorePath = path.resolve(this.base, '.gitignore')\r\n await writeFile(gitignorePath, await readFile(path.resolve(PathUtil.RootPath, '_gitignore'), 'utf-8'))\r\n },\r\n },\r\n {\r\n type: 'eslint-ts',\r\n handler: async () => {\r\n await mergeJson(this.base, {\r\n eslintConfig: {\r\n extends: ['@liuli-util/eslint-config-ts'],\r\n },\r\n devDependencies: {\r\n '@liuli-util/eslint-config-ts': `^${eslintTs.version}`,\r\n },\r\n } as PackageJson)\r\n },\r\n async when(): Promise<boolean> {\r\n return (await isNpmPackage()) && !(await isIncludeDep(['vue'])) && !(await isIncludeDep(['react']))\r\n },\r\n },\r\n {\r\n type: 'eslint-react-ts',\r\n handler: async () => {\r\n await mergeJson(this.base, {\r\n eslintConfig: {\r\n extends: ['@liuli-util/eslint-config-react-ts'],\r\n },\r\n devDependencies: {\r\n '@liuli-util/eslint-config-react-ts': `^${eslintReactTs.version}`,\r\n },\r\n } as PackageJson)\r\n },\r\n async when(): Promise<boolean> {\r\n return (await isNpmPackage()) && (await isIncludeDep(['react']))\r\n },\r\n },\r\n {\r\n type: 'jest',\r\n handler: async () => {\r\n await mergeJson(this.base, {\r\n jest: {\r\n preset: 'ts-jest',\r\n testMatch: ['<rootDir>/src/**/__tests__/*.test.ts'],\r\n },\r\n devDependencies: {\r\n jest: '^27.4.3',\r\n 'ts-jest': '^27.0.7',\r\n },\r\n })\r\n },\r\n },\r\n //\u5FC5\u987B\u653E\u5230\u6700\u540E\u4E00\u4E2A\uFF0C\u540E\u7EED\u6839\u636E\u68C0\u6D4B\u7ED3\u679C\u6DFB\u52A0 hooks\r\n {\r\n type: 'simplehooks',\r\n handler: async () => {\r\n const json = await readJson(path.resolve(this.base, './package.json'))\r\n const lintStaged: string[] = []\r\n if (json.prettier) {\r\n lintStaged.push('prettier --write')\r\n }\r\n if (json.eslintConfig) {\r\n lintStaged.push('eslint --fix')\r\n }\r\n let config = {\r\n scripts: {\r\n postinstall: appendScript(json?.scripts?.postinstall, 'npx simple-git-hooks'),\r\n },\r\n 'simple-git-hooks': {\r\n 'pre-commit': 'yarn lint-staged',\r\n },\r\n 'lint-staged': {\r\n '*.{ts,tsx,js,jsx,css,vue}': [...lintStaged, 'git add'],\r\n },\r\n devDependencies: {\r\n 'simple-git-hooks': '^2.5.1',\r\n 'lint-staged': '^11.1.1',\r\n },\r\n }\r\n if (json.commitlint) {\r\n config = merge(config, {\r\n 'simple-git-hooks': {\r\n 'commit-msg': 'yarn commitlint --edit $1',\r\n },\r\n })\r\n }\r\n await mergeJson(this.base, config as PackageJson)\r\n },\r\n async when(): Promise<boolean> {\r\n return (await isNpmPackage()) && ((await isYarnRoot()) || !(await isYarnSubModule()))\r\n },\r\n },\r\n ]\r\n\r\n async sync(): Promise<void> {\r\n const { sync } = (await readJson(path.resolve(this.base, 'package.json'))) as {\r\n sync?: SyncConfigType[]\r\n }\r\n if (!sync) {\r\n return\r\n }\r\n const syncConfigs = this.syncConfigs.filter((config) => sync.includes(config.type))\r\n for (const syncConfig of syncConfigs) {\r\n await syncConfig.handler()\r\n }\r\n }\r\n\r\n async init(): Promise<void> {\r\n const configMap = arrayToMap(\r\n await AsyncArray.filter(this.syncConfigs, async (config) => {\r\n if (!config.when) {\r\n return true\r\n }\r\n return await config.when()\r\n }),\r\n (item) => item.type,\r\n )\r\n const res = await prompt<{\r\n sync: string[]\r\n }>({\r\n type: 'multiselect',\r\n message: '\u8BF7\u9009\u62E9\u9700\u8981\u540C\u6B65\u7684\u914D\u7F6E\u9879',\r\n name: 'sync',\r\n choices: [...configMap.keys()],\r\n })\r\n await mergeJson(this.base, {\r\n sync: res.sync,\r\n })\r\n }\r\n}\r\n", "import { pathExists, readJson } from 'fs-extra'\r\nimport * as path from 'path'\r\nimport { PackageJson } from 'type-fest'\r\nimport { findParent } from '../../utils'\r\n\r\n/**\r\n * \u5224\u65AD\u662F\u5426\u5305\u542B package.json\r\n * @param cwd\r\n */\r\nexport async function isNpmPackage(cwd: string = process.cwd()): Promise<boolean> {\r\n return await pathExists(path.resolve(cwd, './package.json'))\r\n}\r\n\r\n/**\r\n * \u5224\u65AD\u662F yarn2 monorepo \u9879\u76EE\r\n * @param cwd\r\n */\r\nexport async function isYarnRoot(cwd: string = process.cwd()): Promise<boolean> {\r\n if (!(await isNpmPackage(cwd))) {\r\n return false\r\n }\r\n const json = (await readJson(path.resolve(cwd, './package.json'))) as PackageJson\r\n return !!json.workspaces\r\n}\r\n\r\n/**\r\n * \u5224\u65AD\u662F yarn2 monorepo \u7684\u5B50\u6A21\u5757\r\n */\r\nexport async function isYarnSubModule(cwd: string = process.cwd()): Promise<boolean> {\r\n if (!(await isNpmPackage(cwd))) {\r\n return false\r\n }\r\n //\u5982\u679C\u662F yarn monorepo \u6839\u6A21\u5757\u5219\u76F4\u63A5\u8FD4\u56DE true\r\n if (await isYarnRoot(cwd)) {\r\n return false\r\n }\r\n return (await findParent(path.dirname(cwd), isYarnRoot)) !== null\r\n}\r\n\r\n/**\r\n * \u662F\u5426\u5305\u542B\u6307\u5B9A\u4F9D\u8D56\r\n * @param deps\r\n * @param cwd\r\n */\r\nexport async function isIncludeDep(deps: string[], cwd: string = process.cwd()): Promise<boolean> {\r\n if (!(await isNpmPackage(cwd))) {\r\n return false\r\n }\r\n const json = (await readJson(path.resolve(cwd, './package.json'))) as PackageJson\r\n const set = new Set(Object.keys({ ...json.dependencies, ...json.devDependencies }))\r\n return deps.every((dep) => set.has(dep))\r\n}\r\n", "export function arrayToMap<T, K>(\r\n arr: T[],\r\n kFn: (item: T, index: number, arr: T[]) => K,\r\n): Map<K, T>\r\nexport function arrayToMap<T, K, V>(\r\n arr: T[],\r\n kFn: (item: T, index: number, arr: T[]) => K,\r\n vFn: (item: T, index: number, arr: T[]) => V,\r\n): Map<K, V>\r\n/**\r\n * \u5C06\u6570\u7EC4\u6620\u5C04\u4E3A Map\r\n * @param arr \u6570\u7EC4\r\n * @param kFn \u4EA7\u751F Map \u5143\u7D20\u552F\u4E00\u6807\u8BC6\u7684\u51FD\u6570\r\n * @param vFn \u4EA7\u751F Map \u503C\u7684\u51FD\u6570\uFF0C\u9ED8\u8BA4\u4E3A\u8FD4\u56DE\u6570\u7EC4\u7684\u5143\u7D20\r\n * @returns \u6620\u5C04\u4EA7\u751F\u7684 map \u96C6\u5408\r\n */\r\nexport function arrayToMap<T, K, V>(\r\n arr: T[],\r\n kFn: (item: T, index: number, arr: T[]) => K,\r\n vFn: (item: T, index: number, arr: T[]) => V = (v) => v as any,\r\n): Map<K, V> {\r\n return arr.reduce(\r\n (res, item, index, arr) =>\r\n res.set(kFn(item, index, arr), vFn(item, index, arr)),\r\n new Map<K, V>(),\r\n )\r\n}\r\n", "/**\r\n * \u5728\u4E4B\u524D\u7684\u811A\u672C\u4E2D\u8FFD\u52A0\u65B0\u7684\u811A\u672C\r\n * @param oldScript\r\n * @param newScript\r\n */\r\nexport function appendScript(\r\n oldScript: string | undefined,\r\n newScript: string,\r\n): string {\r\n if (!oldScript) {\r\n return newScript\r\n }\r\n if (oldScript.includes(newScript)) {\r\n return oldScript\r\n }\r\n return oldScript + ' && ' + newScript\r\n}\r\n", "import path from 'path'\r\n\r\n/**\r\n * \u5411\u4E0A\u67E5\u627E\u76EE\u5F55\r\n * @param cwd\r\n * @param predicate\r\n */\r\nexport function findParent(\r\n cwd: string,\r\n predicate: (dir: string) => boolean,\r\n): string | null\r\nexport function findParent(\r\n cwd: string,\r\n predicate: (dir: string) => Promise<boolean>,\r\n): Promise<string | null>\r\nexport function findParent<\r\n T extends (dir: string) => boolean | Promise<boolean>,\r\n R extends string | null,\r\n>(\r\n cwd: string,\r\n predicate: T,\r\n): ReturnType<T> extends Promise<any> ? Promise<R> : R {\r\n const res = predicate(cwd)\r\n function f(res: boolean): string | null {\r\n if (res) {\r\n return cwd\r\n }\r\n const parent = path.dirname(cwd)\r\n if (parent === cwd) {\r\n return null\r\n }\r\n return findParent(parent, predicate as any)\r\n }\r\n\r\n return res instanceof Promise ? res.then(f) : (f(res) as any)\r\n}\r\n", "import { IterableElement } from 'type-fest'\r\n\r\nenum ActionTypeEnum {\r\n Filter = 'filter',\r\n Map = 'map',\r\n ForEach = 'forEach',\r\n Reduce = 'reduce',\r\n FlatMap = 'flatMap',\r\n}\r\n\r\nclass Action {\r\n public static Type = ActionTypeEnum\r\n\r\n constructor(\r\n public readonly type: ActionTypeEnum,\r\n public readonly args: any[],\r\n ) {\r\n this.type = type\r\n this.args = args\r\n }\r\n}\r\n\r\n/**\r\n * \u5F02\u6B65\u6570\u7EC4\uFF0C\u652F\u6301\u9759\u6001\u65B9\u6CD5\u548C\u94FE\u5F0F\u8C03\u7528\r\n */\r\nexport class AsyncArray<T> implements PromiseLike<T[]> {\r\n static reduce<T extends any[], R>(\r\n arr: T,\r\n fn: (res: R, item: IterableElement<T>, index: number) => Promise<R>,\r\n res: R,\r\n ): Promise<R> {\r\n return arr.reduce(\r\n (res: Promise<R>, item: IterableElement<T>, index: number) =>\r\n res.then((r) => fn(r, item, index)),\r\n Promise.resolve(res),\r\n )\r\n }\r\n\r\n static map<T, R>(\r\n arr: T[],\r\n fn: (item: T, index: number) => Promise<R>,\r\n ): Promise<R[]> {\r\n return Promise.all(arr.map((item, index) => fn(item, index)))\r\n }\r\n\r\n static async filter<T>(\r\n arr: T[],\r\n fn: (item: T, index: number) => Promise<boolean>,\r\n ): Promise<T[]> {\r\n const res: T[] = []\r\n await AsyncArray.map(arr, async (item, index) => {\r\n if (await fn(item, index)) {\r\n res.push(item)\r\n }\r\n })\r\n return res\r\n }\r\n\r\n static async flatMap<T, R>(\r\n arr: T[],\r\n fn: (item: T, index: number) => Promise<R[]>,\r\n ): Promise<R[]> {\r\n return (\r\n await Promise.all(arr.map((item, index) => fn(item, index)))\r\n ).flatMap((r) => r)\r\n }\r\n\r\n static async forEach<T extends any[]>(\r\n arr: T,\r\n fn: (item: IterableElement<T>, index: number) => Promise<void>,\r\n ): Promise<void> {\r\n await AsyncArray.map(arr, fn)\r\n }\r\n\r\n private tasks: Action[] = []\r\n\r\n constructor(private readonly arr: T[]) {}\r\n\r\n map<R>(fn: (item: T, index: number) => Promise<R>): AsyncArray<R> {\r\n this.tasks.push(new Action(ActionTypeEnum.Map, [fn]))\r\n return this as any\r\n }\r\n\r\n flatMap<R>(fn: (item: T, index: number) => Promise<R[]>): AsyncArray<R> {\r\n this.tasks.push(new Action(ActionTypeEnum.FlatMap, [fn]))\r\n return this as any\r\n }\r\n\r\n filter(fn: (item: T, index: number) => Promise<boolean>): this {\r\n this.tasks.push(new Action(ActionTypeEnum.Filter, [fn]))\r\n return this\r\n }\r\n\r\n async forEach<R>(fn: (item: T, index: number) => Promise<R>): Promise<void> {\r\n this.tasks.push(new Action(ActionTypeEnum.Map, [fn]))\r\n await this\r\n }\r\n\r\n then<TResult1 = T[], TResult2 = never>(\r\n resolve?:\r\n | ((value: T[]) => PromiseLike<TResult1> | TResult1)\r\n | undefined\r\n | null,\r\n reject?:\r\n | ((reason: any) => PromiseLike<TResult2> | TResult2)\r\n | undefined\r\n | null,\r\n ): PromiseLike<TResult1 | TResult2> {\r\n const res = this.value()\r\n res\r\n .then((r) => {\r\n resolve && resolve(res as any)\r\n return r\r\n })\r\n .catch((e) => {\r\n reject && reject(e as any)\r\n throw e\r\n })\r\n return res as any\r\n }\r\n\r\n private async value(): Promise<any> {\r\n let res = this.arr\r\n for (const task of this.tasks) {\r\n switch (task.type) {\r\n case ActionTypeEnum.Filter:\r\n res = await AsyncArray.filter(res, task.args[0])\r\n break\r\n case ActionTypeEnum.Map:\r\n res = await AsyncArray.map(res, task.args[0])\r\n break\r\n case ActionTypeEnum.FlatMap:\r\n res = await AsyncArray.flatMap(res, task.args[0])\r\n break\r\n case ActionTypeEnum.ForEach:\r\n await AsyncArray.forEach(res, task.args[0])\r\n return\r\n case ActionTypeEnum.Reduce:\r\n return await AsyncArray.reduce(res, task.args[0], task.args[1])\r\n }\r\n }\r\n return res\r\n }\r\n}\r\n", "import path from 'path'\r\n\r\nexport class PathUtil {\r\n /**\r\n * \u4ECE\u8FD9\u4E2A\u9879\u76EE\u7684\u6839\u76EE\u5F55\u8BFB\u53D6\uFF0C\u5F00\u53D1\u73AF\u5883\u662F src/../\uFF0C\u8FD0\u884C\u65F6\u5219\u662F dist/../\r\n */\r\n static readonly RootPath = path.resolve(__dirname, '..')\r\n}\r\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liuli-util/cli",
3
- "version": "3.17.1",
3
+ "version": "3.19.0",
4
4
  "description": "一个针对于库和 CLI 应用程序打包的零配置 CLI",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",
@@ -11,9 +11,9 @@
11
11
  },
12
12
  "jest": {
13
13
  "preset": "ts-jest",
14
- "moduleNameMapper": {
15
- "lodash-es": "lodash"
16
- }
14
+ "testMatch": [
15
+ "<rootDir>/src/**/__tests__/*.test.ts"
16
+ ]
17
17
  },
18
18
  "publishConfig": {
19
19
  "access": "public",
@@ -25,39 +25,38 @@
25
25
  "@liuli-util/eslint-config-ts": "^0.2.0",
26
26
  "@liuli-util/prettier-standard-config": "^0.1.0",
27
27
  "ajv": "^8.8.2",
28
+ "ajv-formats": "^2.1.1",
28
29
  "ajv-i18n": "^4.2.0",
29
30
  "chokidar": "^3.5.2",
30
31
  "commander": "^8.2.0",
31
32
  "conf": "^10.1.1",
32
33
  "enquirer": "^2.3.6",
33
- "esbuild": "^0.13.2",
34
+ "esbuild": "^0.13.15",
34
35
  "fs-extra": "^10.0.0",
35
36
  "glob": "^7.2.0",
36
37
  "glob-promise": "^4.2.0",
37
38
  "json5": "^2.2.0",
38
- "lodash-es": "^4.17.21",
39
39
  "simple-git": "^2.45.1",
40
40
  "spinnies": "^0.5.1",
41
41
  "ssh2": "^1.5.0",
42
42
  "ssh2-sftp-client": "^7.2.1",
43
+ "tar": "^6.1.11",
43
44
  "ts-morph": "^12.0.0"
44
45
  },
45
46
  "devDependencies": {
46
- "@types/find-cache-dir": "^3.2.1",
47
47
  "@types/fs-extra": "^9.0.13",
48
48
  "@types/glob": "^7",
49
49
  "@types/jest": "^27.0.2",
50
- "@types/lodash-es": "^4.17.5",
50
+ "@types/lodash": "^4.14.178",
51
51
  "@types/node": "^16.9.6",
52
52
  "@types/ssh2-sftp-client": "^7.0.0",
53
- "comlink": "^4.3.1",
54
53
  "esno": "^0.9.1",
55
- "jest": "^27.2.1",
54
+ "jest": "^27.4.7",
56
55
  "lodash": "^4.17.21",
57
56
  "rimraf": "^3.0.2",
58
- "ts-jest": "^27.0.5",
57
+ "ts-jest": "^27.1.3",
59
58
  "type-fest": "^2.3.4",
60
- "typescript": "^4.4.3"
59
+ "typescript": "^4.5.5"
61
60
  },
62
61
  "repository": {
63
62
  "type": "git",
@@ -65,9 +64,11 @@
65
64
  },
66
65
  "scripts": {
67
66
  "setup": "pnpm build",
68
- "build": "rimraf dist && pnpm start build cli",
67
+ "build": "esno src/bin.ts build cli",
69
68
  "dev": "esno src/bin.ts build cli -w",
70
- "start": "esno src/bin.ts"
69
+ "start": "esno src/bin.ts",
70
+ "test": "jest --all",
71
+ "lint": "eslint --fix src/**"
71
72
  },
72
- "readme": "# @liuli-util/cli\r\n\r\n一个针对于库和 CLI 应用程序打包的零配置 CLI。\r\n\r\n## 起步\r\n\r\n### 安装\r\n\r\n```sh\r\nyarn add -D @liuli-util/cli # 局部安装\r\nnpm i -g @liuli-util/cli # 全局安装\r\n```\r\n\r\n### 打包\r\n\r\n```sh\r\nyarn liuli-cli build lib # 打包库\r\nyarn liuli-cli build cli # 打包 cli 引用程序\r\n```\r\n\r\n> 添加 `-w` 选项则启动 rollup 的监视模式,打包出来的 dist/ 不会压缩且不会将依赖项打进 bundle。\r\n\r\n![监视模式](https://liuli.dev/images/liuli-cli%20%E7%9B%91%E8%A7%86%E6%A8%A1%E5%BC%8F.gif)\r\n\r\n### 生成\r\n\r\n```sh\r\nyarn liuli-cli generate <name> --template lib # 生成 ts-lib 项目\r\nyarn liuli-cli generate <name> --template cli # 生成 cli 项目\r\n```\r\n\r\nutil 也支持交互式的创建项目\r\n\r\n```shell\r\nyarn liuli-cli generate\r\n```\r\n\r\n![liuli-cli 交互式创建截图](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### 同步配置\r\n\r\n```shell\r\nyarn liuli-cli sync\r\n```\r\n\r\n需要在 package.json 中指定同步哪些配置\r\n\r\n```json\r\n{\r\n \"sync\": [\"prettier\", \"workspaces\", \"commitlint\", \"simplehooks\"]\r\n}\r\n```\r\n\r\n目前支持的配置项\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\n未来的目标:默认将包括检查 cli 自身的同步(如果需要在 monorepo 之外使用的话),eslint/style-lint 之类,还有在没有配置时实现交互式 cli\r\n\r\n> 注:目前仅同步依赖而不会执行安装\r\n\r\n也支持交互式的初始化同步配置\r\n\r\n```shell\r\nyarn liuli-cli sync init\r\n```\r\n\r\n## 设计理念\r\n\r\n- 约定大于配置,如果可能应该不提供配置。VitePress 也是这样做的,参考:https://vitepress.vuejs.org/#lighter-page-weight 这会导致一些约束,包括以下内容\r\n - 打包库时入口文件必须是 `src/index.ts`,出口文件则是 `dist/index.esm.js` `dist/index.js`\r\n - 打包 CLI 时入口文件必须是 `src/bin.ts`,出口文件则是 `dist/bin.js`\r\n - 在打包 lib 时会将所有的依赖作为外部依赖处理,而在打包 cli 时会将所有依赖项打进 bundle\r\n\r\n## FAQ\r\n\r\n### 为什么底层没有选择 esbuild\r\n\r\n事实上,esbuild 本身非常非常非常快(重要的事情说三遍),但如果使用 js 封装 CLI,则性能会迅速降低。\r\n\r\n打包这个项目使用 esbuild、cli 封装、rollup 的时间对比如下\r\n\r\n| 打包方式 | 时间 |\r\n| -------- | ----- |\r\n| esbuild | 0.49s |\r\n| cli 封装 | 3.2s |\r\n| rollup | 3.65s |\r\n\r\n> 现在 [vscode 插件打包官方推荐使用 esbuild](https://code.visualstudio.com/api/working-with-extensions/bundling-extension) ,吾辈在生产项目中也有过实践,长期而言吾辈比较看好这类更高性能的打包工具。\r\n\r\n### 为什么不捆绑外部依赖项\r\n\r\n主要原因是希望将捆绑的工作交由最终应用完成,避免重复捆绑相同的依赖,而且还可以避免处理 nodejs 中直接基于文件系统使用 `worker_threads` 的问题。\r\n"
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"
73
74
  }
@@ -3,30 +3,15 @@ import Client, { ConnectOptions } from 'ssh2-sftp-client'
3
3
  import * as path from 'path'
4
4
  import * as os from 'os'
5
5
  import { copy, mkdirp, pathExists, readFile } from 'fs-extra'
6
- import Ajv from 'ajv'
7
- import localize from 'ajv-i18n/localize'
8
6
  import simpleGit from 'simple-git'
9
7
  import { nodeCacheDir } from '../../utils/nodeCacheDir'
10
8
  import { performance, PerformanceObserver } from 'perf_hooks'
9
+ import { validate } from './util/validate'
11
10
 
12
11
  export interface DeployEvents {
13
12
  process(title: string): void
14
13
  }
15
14
 
16
- /**
17
- * 使用 ajv 校验数据
18
- * @param schema
19
- * @param data
20
- */
21
- function ajvValidate(schema: object, data: object): [isValid: boolean, errorText: string] {
22
- const ajv = new Ajv({ allErrors: true, messages: false })
23
- const res = ajv.validate(schema, data)
24
- if (!res) {
25
- localize.zh(ajv.errors)
26
- }
27
- return [res, ajv.errorsText()]
28
- }
29
-
30
15
  /**
31
16
  * 部署服务接口
32
17
  */
@@ -49,9 +34,9 @@ export interface BaseDeployOptions {
49
34
  type: DeployTypeEnum
50
35
  }
51
36
 
52
- export type SftpDeployOptions = Omit<BaseDeployOptions, 'type'> & {
37
+ export interface SftpDeployOptions extends Omit<BaseDeployOptions, 'type'> {
38
+ dist: string
53
39
  dest: string
54
- remote: string
55
40
  sshConfig: ConnectOptions
56
41
  }
57
42
 
@@ -69,38 +54,57 @@ export class SftpDeployService implements IDeployService {
69
54
  ...this.options.sshConfig,
70
55
  privateKey,
71
56
  })
72
- await client.mkdir(this.options.remote, true)
73
- await client.uploadDir(path.resolve(this.options.cwd, this.options.dest), this.options.remote)
57
+ await client.mkdir(this.options.dest, true)
58
+ await client.uploadDir(path.resolve(this.options.cwd, this.options.dist), this.options.dest)
74
59
  await client.end()
75
60
  })
76
61
  }
77
62
 
78
63
  validate(): [isValidate: boolean, errorText: string] {
79
- return ajvValidate(
64
+ return validate<SftpDeployOptions>(
80
65
  {
81
66
  type: 'object',
82
67
  properties: {
68
+ debug: { type: 'boolean' },
83
69
  cwd: { type: 'string' },
70
+ dist: { type: 'string' },
84
71
  dest: { type: 'string' },
85
- remote: { type: 'string' },
86
72
  sshConfig: {
87
73
  type: 'object',
88
74
  properties: {
89
75
  host: { type: 'string' },
90
76
  username: { type: 'string' },
91
77
  },
92
- },
78
+ } as any,
93
79
  },
94
- required: ['cwd', 'dest', 'remote', 'sshConfig'],
80
+ required: ['cwd', 'dist', 'dest', 'sshConfig', 'debug'],
95
81
  },
96
82
  this.options,
97
83
  )
98
84
  }
99
85
  }
100
86
 
101
- export type GhPagesDeployOptions = Omit<BaseDeployOptions, 'type'> & {
102
- dest: string
103
- remote: string
87
+ export interface GhPagesDeployOptions extends Omit<BaseDeployOptions, 'type'> {
88
+ /**
89
+ * 推送的本地目录
90
+ */
91
+ dist: string
92
+ /**
93
+ * 推送的远端目录,默认为分支根目录
94
+ */
95
+ dest?: string
96
+ /**
97
+ * 推送的项目 git 地址,默认为当前项目
98
+ */
99
+ repo?: string
100
+ /**
101
+ * 推送的远端,默认为 origin
102
+ */
103
+ remote?: string
104
+ /**
105
+ * 远端分支名,默认为 gh-pages
106
+ */
107
+ branch?: string
104
108
  }
105
109
 
106
110
  /**
@@ -110,10 +114,10 @@ export class GhPagesDeployService implements IDeployService {
110
114
  constructor(private readonly options: GhPagesDeployOptions) {}
111
115
 
112
116
  deploy(): EventExtPromise<void, DeployEvents> {
113
- const defaultRemote = 'origin'
114
- const defaultBranch = 'gh-pages'
117
+ const defaultRemote = this.options.remote ?? 'origin'
118
+ const defaultBranch = this.options.branch ?? 'gh-pages'
115
119
  return PromiseUtil.wrapOnEvent(async (events: DeployEvents) => {
116
- const obs = new PerformanceObserver((perfObserverList, observer) => {
120
+ const obs = new PerformanceObserver((perfObserverList) => {
117
121
  if (this.options.debug) {
118
122
  console.log(perfObserverList.getEntries())
119
123
  }
@@ -126,47 +130,81 @@ export class GhPagesDeployService implements IDeployService {
126
130
  }
127
131
  mark('开始推送')
128
132
  const git = simpleGit(this.options.cwd)
129
- mark('获取当前项目的远端配置')
130
- const originRemote = (await git.getRemotes(true)).find((item) => item.name === defaultRemote)
131
- if (!originRemote) {
132
- throw new Error('当前目录不是一个 git 项目或没有配置 git remote')
133
+ if (!this.options.repo) {
134
+ mark('获取当前项目的远端配置')
135
+ const originRemote = (await git.getRemotes(true)).find((item) => item.name === defaultRemote)
136
+ if (!originRemote) {
137
+ throw new Error('当前目录不是一个 git 项目或没有配置 git remote')
138
+ }
139
+ this.options.repo = originRemote.refs.fetch
133
140
  }
134
141
  const ghPagesRoot = path.resolve(nodeCacheDir('liuli-cli'), 'gh-pages')
135
- const originRepoName = originRemote.refs.fetch.replace(new RegExp('[/:]', 'g'), '_')
142
+ const originRepoName = this.options.repo.replace(new RegExp('[/:]', 'g'), '_')
136
143
  const localRepoPath = path.resolve(ghPagesRoot, originRepoName)
144
+ let forcePush = false
137
145
  if (!(await pathExists(localRepoPath))) {
138
146
  mark('克隆项目')
139
- await git.clone(originRemote.refs.fetch, localRepoPath, { '--branch': defaultBranch })
147
+ //如果失败,应该尝试克隆主分支,然后 checkout
148
+ try {
149
+ await git.clone(this.options.repo, localRepoPath, {
150
+ '--branch': defaultBranch,
151
+ '--single-branch': null,
152
+ '--depth': 1,
153
+ })
154
+ } catch (e) {
155
+ mark(`未找到 ${defaultBranch} 分支,尝试自动创建`)
156
+ await git.clone(this.options.repo, localRepoPath, {
157
+ '--single-branch': null,
158
+ '--depth': 1,
159
+ })
160
+ await git.cwd(localRepoPath)
161
+ await git.checkout({
162
+ '--orphan': defaultBranch,
163
+ })
164
+ forcePush = true
165
+ }
140
166
  } else {
167
+ await git.cwd(localRepoPath)
141
168
  mark('更新项目')
142
169
  await git.pull()
143
170
  }
144
171
  mark('复制文件')
145
- const remoteDestPath = path.join(localRepoPath, this.options.remote)
172
+ const remoteDestPath = path.join(localRepoPath, this.options.dest ?? './')
146
173
  await mkdirp(remoteDestPath)
147
- await copy(path.resolve(this.options.cwd, this.options.dest), remoteDestPath)
148
- mark('推送到远端')
174
+ await copy(path.resolve(this.options.cwd, this.options.dist), remoteDestPath)
175
+ mark('提交所有文件')
149
176
  await git.cwd(localRepoPath)
150
177
  await git.add('-A')
151
- if ((await git.status()).files.length !== 0) {
178
+ if ((await git.status()).files.length === 0) {
179
+ mark('没有任何提交,跳过提交')
180
+ } else {
152
181
  await git.commit('Updates gh-pages by liuli-cli')
182
+ }
183
+ mark('推送到远端')
184
+ if ((await git.status()).ahead > 0 || forcePush) {
153
185
  await git.push(defaultRemote, defaultBranch)
186
+ mark('完成推送')
187
+ } else {
188
+ mark('没有更新,跳过推送')
154
189
  }
155
- mark('完成推送')
156
190
  obs.disconnect()
157
191
  })
158
192
  }
159
193
 
160
194
  validate(): [isValid: boolean, errorText: string] {
161
- return ajvValidate(
195
+ return validate<GhPagesDeployOptions>(
162
196
  {
163
197
  type: 'object',
164
198
  properties: {
199
+ debug: { type: 'boolean' },
165
200
  cwd: { type: 'string' },
166
- dest: { type: 'string' },
167
- remote: { type: 'string' },
201
+ dist: { type: 'string' },
202
+ dest: { type: 'string', nullable: true },
203
+ repo: { type: 'string', nullable: true },
204
+ remote: { type: 'string', nullable: true },
205
+ branch: { type: 'string', nullable: true },
168
206
  },
169
- required: ['cwd', 'dest', 'remote'],
207
+ required: ['debug', 'cwd', 'dist'],
170
208
  },
171
209
  this.options,
172
210
  )
File without changes