jiek 0.4.6 → 0.4.7-alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (164) hide show
  1. package/README.md +22 -1
  2. package/bin/jiek.js +2 -1
  3. package/dist/cli.d.mts +97 -0
  4. package/dist/cli.d.mts.map +1 -0
  5. package/dist/cli.d.ts +96 -1
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/{cli.cjs → cli.js} +355 -231
  8. package/dist/cli.js.map +1 -0
  9. package/dist/cli.min.js +1 -0
  10. package/dist/cli.min.js.map +1 -0
  11. package/dist/cli.min.mjs +1 -0
  12. package/dist/cli.min.mjs.map +1 -0
  13. package/dist/cli.mjs +803 -0
  14. package/dist/cli.mjs.map +1 -0
  15. package/dist/index.d.mts +58 -0
  16. package/dist/index.d.mts.map +1 -0
  17. package/dist/index.d.ts +47 -46
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/{index.cjs → index.js} +0 -1
  20. package/dist/index.js.map +1 -0
  21. package/dist/{index.min.cjs → index.min.js} +0 -1
  22. package/dist/index.min.js.map +1 -0
  23. package/dist/index.min.mjs +1 -0
  24. package/dist/index.min.mjs.map +1 -0
  25. package/dist/{index.esm.js → index.mjs} +0 -1
  26. package/dist/index.mjs.map +1 -0
  27. package/dist/rollup/index.d.mts +53 -0
  28. package/dist/rollup/index.d.mts.map +1 -0
  29. package/dist/rollup/index.d.ts +53 -0
  30. package/dist/rollup/index.d.ts.map +1 -0
  31. package/dist/rollup/index.js +553 -0
  32. package/dist/rollup/index.js.map +1 -0
  33. package/dist/rollup/index.min.js +1 -0
  34. package/dist/rollup/index.min.js.map +1 -0
  35. package/dist/rollup/index.min.mjs +1 -0
  36. package/dist/rollup/index.min.mjs.map +1 -0
  37. package/dist/rollup/index.mjs +551 -0
  38. package/dist/rollup/index.mjs.map +1 -0
  39. package/package.json +52 -35
  40. package/src/cli.ts +9 -0
  41. package/src/commands/base.ts +9 -0
  42. package/src/commands/build.ts +156 -0
  43. package/src/commands/init.ts +373 -0
  44. package/src/commands/publish.ts +156 -0
  45. package/src/index.ts +8 -0
  46. package/src/inner.ts +11 -0
  47. package/src/merge-package-json.ts +75 -0
  48. package/src/pkg.ts +1 -0
  49. package/src/rollup/base.ts +72 -0
  50. package/src/rollup/index.ts +420 -0
  51. package/src/rollup/plugins/globals.ts +34 -0
  52. package/src/rollup/plugins/progress.ts +26 -0
  53. package/src/rollup/plugins/skip.ts +23 -0
  54. package/src/rollup/utils/commonOptions.ts +9 -0
  55. package/src/rollup/utils/externalResolver.ts +21 -0
  56. package/src/rollup/utils/globalResolver.ts +13 -0
  57. package/src/rollup/utils/withMinify.ts +18 -0
  58. package/src/utils/filterSupport.ts +82 -0
  59. package/src/utils/getExports.ts +100 -0
  60. package/src/utils/getRoot.ts +16 -0
  61. package/src/utils/getWD.ts +31 -0
  62. package/src/utils/loadConfig.ts +93 -0
  63. package/src/utils/tsRegister.ts +22 -0
  64. package/dist/base.esm.d.ts +0 -55
  65. package/dist/cli.cjs.map +0 -1
  66. package/dist/cli.esm.d.ts +0 -2
  67. package/dist/cli.esm.js +0 -9
  68. package/dist/cli.esm.js.map +0 -1
  69. package/dist/cli.esm.min.js +0 -2
  70. package/dist/cli.esm.min.js.map +0 -1
  71. package/dist/cli.min.cjs +0 -2
  72. package/dist/cli.min.cjs.map +0 -1
  73. package/dist/commands/base.esm.js +0 -5
  74. package/dist/commands/base.esm.js.map +0 -1
  75. package/dist/commands/base.esm.min.js +0 -2
  76. package/dist/commands/base.esm.min.js.map +0 -1
  77. package/dist/commands/build.esm.js +0 -58
  78. package/dist/commands/build.esm.js.map +0 -1
  79. package/dist/commands/build.esm.min.js +0 -2
  80. package/dist/commands/build.esm.min.js.map +0 -1
  81. package/dist/commands/init.esm.js +0 -271
  82. package/dist/commands/init.esm.js.map +0 -1
  83. package/dist/commands/init.esm.min.js +0 -2
  84. package/dist/commands/init.esm.min.js.map +0 -1
  85. package/dist/commands/publish.esm.js +0 -87
  86. package/dist/commands/publish.esm.js.map +0 -1
  87. package/dist/commands/publish.esm.min.js +0 -2
  88. package/dist/commands/publish.esm.min.js.map +0 -1
  89. package/dist/index.cjs.map +0 -1
  90. package/dist/index.esm.d.ts +0 -6
  91. package/dist/index.esm.js.map +0 -1
  92. package/dist/index.esm.min.js +0 -2
  93. package/dist/index.esm.min.js.map +0 -1
  94. package/dist/index.min.cjs.map +0 -1
  95. package/dist/inner.esm.js +0 -10
  96. package/dist/inner.esm.js.map +0 -1
  97. package/dist/inner.esm.min.js +0 -2
  98. package/dist/inner.esm.min.js.map +0 -1
  99. package/dist/merge-package-json.esm.js +0 -64
  100. package/dist/merge-package-json.esm.js.map +0 -1
  101. package/dist/merge-package-json.esm.min.js +0 -2
  102. package/dist/merge-package-json.esm.min.js.map +0 -1
  103. package/dist/pkg.esm.js +0 -4
  104. package/dist/pkg.esm.js.map +0 -1
  105. package/dist/pkg.esm.min.js +0 -2
  106. package/dist/pkg.esm.min.js.map +0 -1
  107. package/dist/rollup/plugins/globals.esm.js +0 -31
  108. package/dist/rollup/plugins/globals.esm.js.map +0 -1
  109. package/dist/rollup/plugins/globals.esm.min.js +0 -2
  110. package/dist/rollup/plugins/globals.esm.min.js.map +0 -1
  111. package/dist/rollup/plugins/skip.esm.js +0 -16
  112. package/dist/rollup/plugins/skip.esm.js.map +0 -1
  113. package/dist/rollup/plugins/skip.esm.min.js +0 -2
  114. package/dist/rollup/plugins/skip.esm.min.js.map +0 -1
  115. package/dist/rollup/utils/commonOptions.esm.js +0 -9
  116. package/dist/rollup/utils/commonOptions.esm.js.map +0 -1
  117. package/dist/rollup/utils/commonOptions.esm.min.js +0 -2
  118. package/dist/rollup/utils/commonOptions.esm.min.js.map +0 -1
  119. package/dist/rollup/utils/externalResolver.esm.js +0 -12
  120. package/dist/rollup/utils/externalResolver.esm.js.map +0 -1
  121. package/dist/rollup/utils/externalResolver.esm.min.js +0 -2
  122. package/dist/rollup/utils/externalResolver.esm.min.js.map +0 -1
  123. package/dist/rollup/utils/globalResolver.esm.js +0 -9
  124. package/dist/rollup/utils/globalResolver.esm.js.map +0 -1
  125. package/dist/rollup/utils/globalResolver.esm.min.js +0 -2
  126. package/dist/rollup/utils/globalResolver.esm.min.js.map +0 -1
  127. package/dist/rollup/utils/withMinify.esm.js +0 -15
  128. package/dist/rollup/utils/withMinify.esm.js.map +0 -1
  129. package/dist/rollup/utils/withMinify.esm.min.js +0 -2
  130. package/dist/rollup/utils/withMinify.esm.min.js.map +0 -1
  131. package/dist/rollup.cjs +0 -330
  132. package/dist/rollup.cjs.map +0 -1
  133. package/dist/rollup.d.ts +0 -23
  134. package/dist/rollup.esm.d.ts +0 -23
  135. package/dist/rollup.esm.js +0 -248
  136. package/dist/rollup.esm.js.map +0 -1
  137. package/dist/rollup.esm.min.js +0 -2
  138. package/dist/rollup.esm.min.js.map +0 -1
  139. package/dist/rollup.min.cjs +0 -2
  140. package/dist/rollup.min.cjs.map +0 -1
  141. package/dist/utils/commondir.esm.js +0 -25
  142. package/dist/utils/commondir.esm.js.map +0 -1
  143. package/dist/utils/commondir.esm.min.js +0 -2
  144. package/dist/utils/commondir.esm.min.js.map +0 -1
  145. package/dist/utils/filterSupport.esm.js +0 -67
  146. package/dist/utils/filterSupport.esm.js.map +0 -1
  147. package/dist/utils/filterSupport.esm.min.js +0 -2
  148. package/dist/utils/filterSupport.esm.min.js.map +0 -1
  149. package/dist/utils/getRoot.esm.js +0 -14
  150. package/dist/utils/getRoot.esm.js.map +0 -1
  151. package/dist/utils/getRoot.esm.min.js +0 -2
  152. package/dist/utils/getRoot.esm.min.js.map +0 -1
  153. package/dist/utils/getWD.esm.js +0 -31
  154. package/dist/utils/getWD.esm.js.map +0 -1
  155. package/dist/utils/getWD.esm.min.js +0 -2
  156. package/dist/utils/getWD.esm.min.js.map +0 -1
  157. package/dist/utils/loadConfig.esm.js +0 -75
  158. package/dist/utils/loadConfig.esm.js.map +0 -1
  159. package/dist/utils/loadConfig.esm.min.js +0 -2
  160. package/dist/utils/loadConfig.esm.min.js.map +0 -1
  161. package/dist/utils/tsRegister.esm.js +0 -24
  162. package/dist/utils/tsRegister.esm.js.map +0 -1
  163. package/dist/utils/tsRegister.esm.min.js +0 -2
  164. package/dist/utils/tsRegister.esm.min.js.map +0 -1
package/package.json CHANGED
@@ -1,60 +1,84 @@
1
1
  {
2
2
  "name": "jiek",
3
- "version": "0.4.6",
3
+ "version": "0.4.7-alpha.1",
4
4
  "description": "YiJie's personal kits.",
5
5
  "bin": {
6
6
  "jiek": "bin/jiek.js",
7
7
  "jk": "bin/jiek.js"
8
8
  },
9
- "jiek": {
10
- "noBrowser": true
11
- },
12
9
  "files": [
13
- "dist"
10
+ "dist",
11
+ "src",
12
+ "bin",
13
+ "LICENSE",
14
+ "README.md"
14
15
  ],
16
+ "typesVersions": {
17
+ "<5.0": {
18
+ "*": [
19
+ "*",
20
+ "./dist/*",
21
+ "./dist/*/index.d.ts"
22
+ ]
23
+ }
24
+ },
15
25
  "exports": {
16
26
  "./package.json": "./package.json",
17
27
  ".": {
18
- "types": "./dist/index.d.ts",
19
- "import": "./dist/index.esm.js",
20
- "require": "./dist/index.cjs",
21
- "inner-src": "./src/index.ts"
28
+ "source": "./src/index.ts",
29
+ "import": "./dist/index.mjs",
30
+ "default": "./dist/index.js"
22
31
  },
23
32
  "./cli": {
24
- "types": "./dist/cli.d.ts",
25
- "import": "./dist/cli.esm.js",
26
- "require": "./dist/cli.cjs",
27
- "inner-src": "./src/cli.ts"
33
+ "source": "./src/cli.ts",
34
+ "import": "./dist/cli.mjs",
35
+ "default": "./dist/cli.js"
28
36
  },
29
37
  "./rollup": {
30
- "types": "./dist/rollup.d.ts",
31
- "import": "./dist/rollup.esm.js",
32
- "require": "./dist/rollup.cjs",
33
- "inner-src": "./src/rollup/index.ts"
38
+ "source": "./src/rollup/index.ts",
39
+ "import": "./dist/rollup/index.mjs",
40
+ "default": "./dist/rollup/index.js"
41
+ },
42
+ "./cli.js": {
43
+ "source": "./src/cli.ts",
44
+ "import": "./dist/cli.mjs",
45
+ "default": "./dist/cli.js"
46
+ },
47
+ "./rollup.js": {
48
+ "source": "./src/rollup/index.ts",
49
+ "import": "./dist/rollup/index.mjs",
50
+ "default": "./dist/rollup/index.js"
34
51
  }
35
52
  },
53
+ "imports": {
54
+ "#~/*": "./src/*"
55
+ },
36
56
  "dependencies": {
57
+ "@jiek/rollup-plugin-dts": "^6.1.1",
37
58
  "@rollup/plugin-json": "^6.0.1",
59
+ "@rollup/plugin-node-resolve": "^15.3.0",
38
60
  "@rollup/plugin-terser": "^0.4.4",
39
61
  "autoprefixer": "^10.4.16",
40
62
  "cli-progress": "^3.12.0",
41
63
  "commander": "^12.0.0",
42
64
  "detect-indent": "^6.1.0",
65
+ "execa": "9.3.1",
43
66
  "inquirer": "^8.2.6",
44
67
  "js-yaml": "^4.1.0",
45
68
  "jsonc-parser": "^3.2.1",
46
69
  "micromatch": "^4.0.5",
47
70
  "rollup": "^4.1.5",
48
71
  "rollup-plugin-copy": "^3.5.0",
49
- "@jiek/rollup-plugin-dts": "^6.1.1",
50
72
  "rollup-plugin-esbuild": "^6.1.0",
51
- "rollup-plugin-postcss": "^4.0.2",
52
- "@jiek/pkger": "0.1.10",
53
- "@jiek/utils": "0.2.0"
73
+ "typescript": "^5.0.0",
74
+ "@jiek/utils": "^0.2.0",
75
+ "@jiek/pkger": "^0.1.11"
54
76
  },
55
77
  "optionalDependencies": {
56
78
  "@pnpm/filter-workspace-packages": "^7.2.13",
57
- "esbuild-register": "^3.5.0"
79
+ "esbuild-register": "^3.5.0",
80
+ "postcss": "^8.4.47",
81
+ "rollup-plugin-postcss": "^4.0.2"
58
82
  },
59
83
  "devDependencies": {
60
84
  "@npm/types": "^1.0.2",
@@ -64,18 +88,11 @@
64
88
  "@types/inquirer": "^9.0.7",
65
89
  "@types/js-yaml": "^4.0.9",
66
90
  "@types/micromatch": "^4.0.6",
67
- "esbuild-register": "^3.5.0"
91
+ "esbuild-register": "^3.5.0",
92
+ "node-sass": "^9.0.0",
93
+ "postcss": "^8.4.47",
94
+ "rollup-plugin-postcss": "^4.0.2"
68
95
  },
69
- "types": "./dist/index.d.ts",
70
- "main": "./dist/index.cjs",
71
- "module": "./dist/index.esm.js",
72
- "typesVersions": {
73
- "<5.0": {
74
- "*": [
75
- "*",
76
- "./dist/*",
77
- "./dist/*/index.esm.d.ts"
78
- ]
79
- }
80
- }
96
+ "main": "./dist/index.js",
97
+ "module": "./dist/index.mjs"
81
98
  }
package/src/cli.ts ADDED
@@ -0,0 +1,9 @@
1
+ import './utils/filterSupport'
2
+ import './commands/base'
3
+ import './commands/build'
4
+ import './commands/init'
5
+ import './commands/publish'
6
+
7
+ import { program } from 'commander'
8
+
9
+ program.parse(process.argv)
@@ -0,0 +1,9 @@
1
+ import { program } from 'commander'
2
+
3
+ import pkg from '../pkg'
4
+
5
+ program
6
+ .version(pkg.version)
7
+ .description(pkg.description)
8
+ .option('--root <root>', 'root path')
9
+ .option('-c, --config-path <configPath>', 'config path')
@@ -0,0 +1,156 @@
1
+ import '../rollup/base'
2
+
3
+ import fs from 'node:fs'
4
+ import path from 'node:path'
5
+
6
+ import { MultiBar, Presets } from 'cli-progress'
7
+ import { program } from 'commander'
8
+ import { execaCommand } from 'execa'
9
+
10
+ import { actionDone, actionRestore } from '../inner'
11
+ import type { RollupProgressEvent } from '../rollup/base'
12
+ import { getSelectedProjectsGraph } from '../utils/filterSupport'
13
+ import { loadConfig } from '../utils/loadConfig'
14
+ import { tsRegisterName } from '../utils/tsRegister'
15
+
16
+ const FILE_TEMPLATE = (manifest: unknown) => (`
17
+ const manifest = ${JSON.stringify(manifest, null, 2)}
18
+ module.exports = require('jiek/rollup').template(manifest)
19
+ `.trimStart())
20
+
21
+ program
22
+ .command('build')
23
+ .option('-s, --silent', "Don't display logs.")
24
+ .option('-e, --entries <ENTRIES>', "Specify the entries of the package.json's 'exports' field.(support glob)")
25
+ .action(async ({
26
+ silent,
27
+ entries
28
+ }: {
29
+ silent: boolean
30
+ entries: string
31
+ }) => {
32
+ actionRestore()
33
+ const { build } = loadConfig()
34
+ silent = silent ?? build?.silent ?? false
35
+ const {
36
+ wd,
37
+ value = {}
38
+ } = await getSelectedProjectsGraph() ?? {}
39
+
40
+ if (Object.keys(value).length === 0) {
41
+ throw new Error('no package found')
42
+ }
43
+ const wdNodeModules = path.resolve(wd, 'node_modules')
44
+ if (!fs.existsSync(wdNodeModules)) {
45
+ fs.mkdirSync(wdNodeModules)
46
+ }
47
+ const jiekTempDir = (...paths: string[]) => path.resolve(wdNodeModules, '.jiek', ...paths)
48
+ if (!fs.existsSync(jiekTempDir())) {
49
+ fs.mkdirSync(jiekTempDir())
50
+ }
51
+
52
+ const rollupBinaryPath = require.resolve('rollup')
53
+ .replace(/dist\/rollup.js$/, 'dist/bin/rollup')
54
+ const multiBars = new MultiBar({
55
+ clearOnComplete: false,
56
+ hideCursor: true,
57
+ format: '- {bar} | {status} | {input} | {message}'
58
+ }, Presets.shades_classic)
59
+ let i = 0
60
+ await Promise.all(
61
+ Object.entries(value).map(async ([dir, manifest]) => {
62
+ // TODO support auto build child packages in workspaces
63
+ const escapeManifestName = manifest.name?.replace(/^@/g, '').replace(/\//g, '+')
64
+ const configFile = jiekTempDir(
65
+ `${escapeManifestName ?? `anonymous-${i++}`}.rollup.config.js`
66
+ )
67
+ fs.writeFileSync(configFile, FILE_TEMPLATE(manifest))
68
+ let prefix = ''
69
+ if (tsRegisterName) {
70
+ prefix = `node -r ${tsRegisterName} `
71
+ }
72
+ // TODO replace with `spawn` to support watch mode
73
+ const command = `${prefix}${rollupBinaryPath} --silent -c ${configFile}`
74
+ const child = execaCommand(command, {
75
+ ipc: true,
76
+ cwd: dir,
77
+ env: {
78
+ ...process.env,
79
+ JIEK_ROOT: wd,
80
+ JIEK_ENTRIES: entries
81
+ }
82
+ })
83
+ const bars: Record<string, ReturnType<typeof multiBars.create>> = {}
84
+ let inputMaxLen = 10
85
+ child.on('message', (e: RollupProgressEvent) => {
86
+ if (e.type === 'debug') console.log(...(Array.isArray(e.data) ? e.data : [e.data]))
87
+ })
88
+ !silent && child.on('message', (e: RollupProgressEvent) => {
89
+ if (e.type === 'init') {
90
+ const { leafMap, targetsLength } = e.data
91
+ const leafs = Array
92
+ .from(leafMap.entries())
93
+ .flatMap(([input, pathAndCondiions]) =>
94
+ pathAndCondiions.map(([path, ...conditions]) => ({
95
+ input,
96
+ path,
97
+ conditions
98
+ }))
99
+ )
100
+ console.log(`Package '${manifest.name}' has ${targetsLength} targets to build`)
101
+ leafs.forEach(({ input }) => {
102
+ inputMaxLen = Math.max(inputMaxLen, input.length)
103
+ })
104
+ leafs.forEach(({ input, path }) => {
105
+ const key = `${input}:${path}`
106
+ if (bars[key]) return
107
+ bars[key] = multiBars.create(50, 0, {
108
+ input: input.padEnd(inputMaxLen),
109
+ status: 'waiting'.padEnd(10)
110
+ }, {
111
+ barsize: 20,
112
+ linewrap: true
113
+ })
114
+ })
115
+ }
116
+ if (e.type === 'progress') {
117
+ const {
118
+ path,
119
+ tags,
120
+ input,
121
+ event,
122
+ message
123
+ } = e.data
124
+ const bar = bars[`${input}:${path}`]
125
+ if (!bar) return
126
+ bar.update(
127
+ {
128
+ start: 0,
129
+ resolve: 20,
130
+ end: 50
131
+ }[event ?? 'start'] ?? 0,
132
+ {
133
+ input: input.padEnd(inputMaxLen),
134
+ status: event?.padEnd(10),
135
+ message: `${tags?.join(', ')}: ${message}`
136
+ }
137
+ )
138
+ }
139
+ })
140
+ await new Promise<void>((resolve, reject) => {
141
+ let errorStr = ''
142
+ child.stderr?.on('data', (data) => {
143
+ errorStr += data
144
+ })
145
+ child.once('exit', (code) =>
146
+ code === 0
147
+ ? resolve()
148
+ : reject(new Error(`rollup build failed:\n${errorStr}`)))
149
+ })
150
+ })
151
+ ).finally(() => {
152
+ multiBars.stop()
153
+ })
154
+
155
+ actionDone()
156
+ })
@@ -0,0 +1,373 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+
4
+ import { program } from 'commander'
5
+ import detectIndent from 'detect-indent'
6
+ import inquirer from 'inquirer'
7
+ import type { Config, InitNamed } from 'jiek'
8
+ import { applyEdits, modify } from 'jsonc-parser'
9
+ import { isMatch } from 'micromatch'
10
+
11
+ import { getWD } from '../utils/getWD'
12
+ import { loadConfig } from '../utils/loadConfig'
13
+
14
+ declare module 'jiek' {
15
+ export type InitNamedFunction = (
16
+ argument: string,
17
+ paths: {
18
+ full: string
19
+ relative: string
20
+ basename?: string
21
+ }
22
+ ) => [name?: string, path?: string]
23
+ export type InitNamed =
24
+ | InitNamedFunction
25
+ | {
26
+ [key: string]: string | InitNamedFunction
27
+ }
28
+ export interface Config {
29
+ init?: {
30
+ /**
31
+ * the package.json template file path or file content
32
+ *
33
+ * if it can be parsed as json, it will be parsed
34
+ * if it is a relative file path, it will be resolved to an absolute path based on the current working directory
35
+ * if it is an absolute file path, it will be used directly
36
+ * @default '.jiek.template.package.json'
37
+ */
38
+ template?: string
39
+ /**
40
+ * the readme content
41
+ *
42
+ * $name will be replaced with the package name
43
+ * $license will be replaced with the license
44
+ */
45
+ readme?:
46
+ | string
47
+ | ((ctx: {
48
+ dir: string
49
+ packageJson: Record<string, any>
50
+ }) => string)
51
+ /**
52
+ * the readme template file path
53
+ * @default '.jiek.template.readme.md'
54
+ */
55
+ readmeTemplate?: string
56
+ bug?: {
57
+ /**
58
+ * @default 'bug_report.yml'
59
+ */
60
+ template?: string
61
+ /**
62
+ * @default ['bug']
63
+ */
64
+ labels?:
65
+ | string[]
66
+ | ((ctx: {
67
+ name: string
68
+ dir: string
69
+ }) => string[])
70
+ }
71
+ named?: InitNamed
72
+ }
73
+ }
74
+ }
75
+
76
+ const PACKAGE_JSON_TEMPLATE = `{
77
+ "name": "",
78
+ "version": "0.0.1",
79
+ "description": "",
80
+ "license": "",
81
+ "author": "",
82
+ "files": ["dist"],
83
+ "exports": {
84
+ ".": "./src/index.ts"
85
+ },
86
+ "scripts": {
87
+ },
88
+ "homepage": "",
89
+ "repository": "",
90
+ "bugs": ""
91
+ }`.trimStart()
92
+ const README_TEMPLATE = `# $name
93
+
94
+ ## Installation
95
+
96
+ \`\`\`bash
97
+ npm install $name
98
+ # or
99
+ pnpm install $name
100
+ # or
101
+ yarn add $name
102
+ \`\`\`
103
+
104
+ ## Usage
105
+
106
+
107
+ ## License
108
+
109
+ $license
110
+ `.trimStart()
111
+
112
+ function getTemplateStr(wd: string, template: string | undefined) {
113
+ let templateString = template ?? PACKAGE_JSON_TEMPLATE
114
+ let isTemplateFile = false
115
+ try {
116
+ if (template) JSON.parse(template)
117
+ } catch (e) {
118
+ isTemplateFile = true
119
+ }
120
+ if (isTemplateFile) {
121
+ const templatePath = path.resolve(wd, template!)
122
+ templateString = fs.readFileSync(templatePath, 'utf-8')
123
+ }
124
+ return templateString
125
+ }
126
+ const wdCache = new Map<string, Record<string, any>>()
127
+ function getWDPackageJSONFiled(wd: string, field: string) {
128
+ if (wdCache.has(wd)) {
129
+ return wdCache.get(wd)![field]
130
+ }
131
+ const packageJSONPath = path.resolve(wd, 'package.json')
132
+ const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath, 'utf-8'))
133
+ wdCache.set(wd, packageJSON)
134
+ return packageJSON[field]
135
+ }
136
+ async function getName(
137
+ named: InitNamed | undefined,
138
+ name: string,
139
+ {
140
+ wd,
141
+ cwd,
142
+ workspaceName
143
+ }: {
144
+ wd: string
145
+ cwd: string
146
+ workspaceName: string
147
+ }
148
+ ): Promise<[name?: string, path?: string]> {
149
+ const relativePath = cwd.replace(`${wd}/`, '')
150
+ let basename = path.basename(cwd)
151
+
152
+ if (typeof named === 'function') {
153
+ return named(name, {
154
+ full: wd,
155
+ relative: cwd
156
+ })
157
+ }
158
+
159
+ let isParentMatched = false
160
+ let matchedKey: string | undefined
161
+ let matchedRule: NonNullable<typeof named>[string] | undefined
162
+ if (typeof named === 'object') {
163
+ const isWD = cwd === wd
164
+ if (isWD) {
165
+ const { rule } = await inquirer.prompt<{ rule: string }>({
166
+ type: 'list',
167
+ name: 'rule',
168
+ message: 'choose a rule',
169
+ default: 'default',
170
+ choices: ['default'].concat(Object.keys(named))
171
+ })
172
+ if (rule !== 'default') {
173
+ matchedKey = rule
174
+ matchedRule = named[rule]
175
+ }
176
+ } else {
177
+ for (const [key, value] of Object.entries(named)) {
178
+ if (isMatch(relativePath, key)) {
179
+ matchedKey = key
180
+ matchedRule = value
181
+ break
182
+ }
183
+ if (isMatch(`${relativePath}/jiek_ignore_dont_use_same_file_name`, key)) {
184
+ isParentMatched = true
185
+ matchedKey = key
186
+ matchedRule = value
187
+ break
188
+ }
189
+ }
190
+ }
191
+ }
192
+ if (!matchedRule) {
193
+ matchedKey = 'packages/*'
194
+ matchedRule = `@${workspaceName}/$basename`
195
+ }
196
+ if (!matchedRule) {
197
+ throw new Error('no matched rule')
198
+ }
199
+ if (!name && isParentMatched) {
200
+ basename = await inquirer.prompt<{ name: string }>({
201
+ type: 'input',
202
+ name: 'name',
203
+ message: `the matched rule is \`${String(matchedRule)}\`, please input the basename\n`
204
+ }).then(({ name }) => name)
205
+ }
206
+
207
+ if (typeof matchedRule === 'function') {
208
+ return matchedRule(name, {
209
+ full: wd,
210
+ relative: cwd,
211
+ basename: basename
212
+ })
213
+ }
214
+ if (typeof matchedRule === 'string') {
215
+ const dirName = name ?? basename
216
+ return [
217
+ matchedRule.replace(/\$basename/g, dirName),
218
+ matchedKey?.replace(/\/\*$/g, `/${dirName}`)
219
+ ]
220
+ }
221
+ throw new Error('no matched rule')
222
+ }
223
+
224
+ program
225
+ .command('init [name]')
226
+ .option('-t, --template <template>', 'the package.json template file path or file content')
227
+ .action(async () => {
228
+ const [, name] = program.args
229
+ const cwd = process.cwd()
230
+ const { init = {} }: Config = loadConfig() ?? {}
231
+ const { wd } = getWD()
232
+ const workspaceName = path.basename(wd)
233
+
234
+ const {
235
+ named,
236
+ template,
237
+ bug = {},
238
+ readme: _readme = README_TEMPLATE,
239
+ readmeTemplate
240
+ } = init
241
+ const resolvedBug = {
242
+ template: 'bug_report.yml',
243
+ labels: ['bug'],
244
+ ...bug
245
+ }
246
+ let readme = _readme
247
+ if (readmeTemplate) {
248
+ const readmeTemplatePath = path.resolve(wd, readmeTemplate)
249
+ readme = fs.readFileSync(readmeTemplatePath, 'utf-8')
250
+ }
251
+
252
+ const templateString = getTemplateStr(wd, template)
253
+ // TODO detectIndent by editorconfig
254
+ const { indent = ' ' } = detectIndent(templateString)
255
+ const formattingOptions = {
256
+ tabSize: indent.length,
257
+ insertSpaces: true
258
+ }
259
+ const passFields = [
260
+ 'license',
261
+ 'author'
262
+ ]
263
+ let newJSONString = templateString
264
+ for (const field of passFields) {
265
+ newJSONString = applyEdits(
266
+ newJSONString,
267
+ modify(
268
+ newJSONString,
269
+ [field],
270
+ getWDPackageJSONFiled(wd, field),
271
+ { formattingOptions }
272
+ )
273
+ )
274
+ }
275
+ let [pkgName, pkgDir] = await getName(named, name, {
276
+ wd,
277
+ cwd,
278
+ workspaceName
279
+ })
280
+ if (!pkgDir) {
281
+ const { dir } = await inquirer.prompt<{ dir: string }>({
282
+ type: 'input',
283
+ name: 'dir',
284
+ message: 'package directory',
285
+ default: name
286
+ })
287
+ pkgDir = dir
288
+ }
289
+ if (!pkgName) {
290
+ const { name: inputName } = await inquirer.prompt<{
291
+ name: string
292
+ }>({
293
+ type: 'input',
294
+ name: 'name',
295
+ message: 'package name',
296
+ default: name
297
+ })
298
+ pkgName = inputName
299
+ }
300
+ newJSONString = applyEdits(newJSONString, modify(newJSONString, ['name'], pkgName, { formattingOptions }))
301
+
302
+ let pkgRepo = getWDPackageJSONFiled(wd, 'repository')
303
+ if (typeof pkgRepo === 'string') {
304
+ pkgRepo = {
305
+ type: 'git',
306
+ url: pkgRepo,
307
+ directory: pkgDir
308
+ }
309
+ }
310
+ newJSONString = applyEdits(
311
+ newJSONString,
312
+ modify(
313
+ newJSONString,
314
+ ['repository'],
315
+ pkgRepo,
316
+ { formattingOptions }
317
+ )
318
+ )
319
+ const homepage = `${pkgRepo?.url}/blob/master/${pkgDir}/README.md`
320
+ newJSONString = applyEdits(
321
+ newJSONString,
322
+ modify(
323
+ newJSONString,
324
+ ['homepage'],
325
+ homepage,
326
+ { formattingOptions }
327
+ )
328
+ )
329
+ let labels = resolvedBug.labels
330
+ if (typeof labels === 'function') {
331
+ labels = labels({
332
+ name: pkgName,
333
+ dir: pkgDir
334
+ })
335
+ }
336
+ labels.push(`scope:${pkgName}`)
337
+ const bugs = `${pkgRepo?.url}/issues/new?template=${resolvedBug.template}&labels=${labels.join(',')}`
338
+ newJSONString = applyEdits(
339
+ newJSONString,
340
+ modify(
341
+ newJSONString,
342
+ ['bugs'],
343
+ bugs,
344
+ { formattingOptions }
345
+ )
346
+ )
347
+
348
+ function pkgDirTo(to: string) {
349
+ if (!pkgDir) throw new Error('pkgDir is not defined')
350
+
351
+ return path.resolve(pkgDir, to)
352
+ }
353
+ if (!fs.existsSync(pkgDir)) fs.mkdirSync(pkgDir)
354
+ const pkgJSONFilePath = pkgDirTo('package.json')
355
+ if (fs.existsSync(pkgJSONFilePath)) {
356
+ throw new Error('package.json already exists')
357
+ }
358
+ fs.writeFileSync(pkgJSONFilePath, newJSONString)
359
+ console.log(newJSONString, 'written to', pkgJSONFilePath)
360
+
361
+ const license = getWDPackageJSONFiled(wd, 'license')
362
+ const readmeFilePath = pkgDirTo('README.md')
363
+ if (typeof readme === 'function') {
364
+ readme = readme({
365
+ dir: pkgDir,
366
+ packageJson: JSON.parse(newJSONString)
367
+ })
368
+ }
369
+ const readmeContent = readme
370
+ .replace(/\$name/g, pkgName)
371
+ .replace(/\$license/g, license)
372
+ fs.writeFileSync(readmeFilePath, readmeContent)
373
+ })