jiek 0.4.5 → 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} +361 -226
  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 -76
  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
@@ -0,0 +1,420 @@
1
+ import '../rollup/base'
2
+
3
+ import fs from 'node:fs'
4
+ import { dirname, relative, resolve } from 'node:path'
5
+
6
+ import type { RecursiveRecord } from '@jiek/pkger/entrypoints'
7
+ import { getAllLeafs } from '@jiek/pkger/entrypoints'
8
+ import { dts } from '@jiek/rollup-plugin-dts'
9
+ import { getWorkspaceDir } from '@jiek/utils/getWorkspaceDir'
10
+ import json from '@rollup/plugin-json'
11
+ import { nodeResolve } from '@rollup/plugin-node-resolve'
12
+ import terser from '@rollup/plugin-terser'
13
+ import { sendMessage } from 'execa'
14
+ import { parse } from 'jsonc-parser'
15
+ import { isMatch } from 'micromatch'
16
+ import type { OutputOptions, OutputPlugin, RollupOptions } from 'rollup'
17
+ import esbuild from 'rollup-plugin-esbuild'
18
+ import ts from 'typescript'
19
+
20
+ import { getExports } from '../utils/getExports'
21
+ import { loadConfig } from '../utils/loadConfig'
22
+ import type { RollupProgressEvent, TemplateOptions } from './base'
23
+ import progress from './plugins/progress'
24
+ import skip from './plugins/skip'
25
+ import externalResolver from './utils/externalResolver'
26
+
27
+ interface PackageJSON {
28
+ name?: string
29
+ type?: string
30
+ exports?: Record<string, unknown> | string | string[]
31
+ }
32
+
33
+ const {
34
+ JIEK_ROOT,
35
+ JIEK_ENTRIES
36
+ } = process.env
37
+ const WORKSPACE_ROOT = JIEK_ROOT ?? getWorkspaceDir()
38
+ const COMMON_OPTIONS = {} satisfies RollupOptions
39
+ const COMMON_PLUGINS = [
40
+ json()
41
+ ]
42
+
43
+ const config = loadConfig() ?? {}
44
+ const { build = {} } = config
45
+ const jsOutdir = `./${
46
+ relative(
47
+ process.cwd(),
48
+ resolve(
49
+ (
50
+ typeof build?.output?.dir === 'object'
51
+ // the outdir only affect js output in this function
52
+ ? build.output.dir.js
53
+ : build?.output?.dir
54
+ ) ?? 'dist'
55
+ )
56
+ )
57
+ }`
58
+
59
+ const STYLE_REGEXP = /\.(css|s[ac]ss|less|styl)$/
60
+
61
+ // eslint-disable-next-line unused-imports/no-unused-vars
62
+ const debug = (...args: unknown[]) => sendMessage({ type: 'debug', data: args } satisfies RollupProgressEvent)
63
+
64
+ const resolveWorkspacePath = (p: string) => resolve(WORKSPACE_ROOT, p)
65
+
66
+ const intersection = <T>(a: Set<T>, b: Set<T>) => new Set([...a].filter(i => b.has(i)))
67
+
68
+ const pascalCase = (str: string) =>
69
+ str
70
+ .replace(/[@|/-](\w)/g, (_, $1) => $1.toUpperCase())
71
+ .replace(/(?:^|-)(\w)/g, (_, $1) => $1.toUpperCase())
72
+
73
+ const reveal = (obj: string | Record<string, unknown>, keys: string[]) =>
74
+ keys.reduce((acc, key) => {
75
+ if (typeof acc === 'string') throw new Error('key not found in exports')
76
+ if (!(key in acc)) throw new Error(`key ${key} not found in exports`)
77
+ return acc[key] as string | Record<string, unknown>
78
+ }, obj)
79
+
80
+ const withMinify = (
81
+ output: OutputOptions & {
82
+ plugins?: OutputPlugin[]
83
+ },
84
+ minify = build?.output?.minify
85
+ ) =>
86
+ minify === false
87
+ ? [output]
88
+ : minify === 'only-minify'
89
+ ? [{
90
+ ...output,
91
+ // TODO replace suffix when pubish to npm and the `build.output.minify` is 'only-minify'
92
+ // TODO resolve dts output file name
93
+ file: output.file?.replace(/(\.[cm]?js)$/, '.min$1'),
94
+ plugins: [
95
+ ...(output.plugins ?? []),
96
+ terser()
97
+ ]
98
+ }]
99
+ : [
100
+ output,
101
+ {
102
+ ...output,
103
+ file: output.file?.replace(/(\.[cm]?js)$/, '.min$1'),
104
+ plugins: [
105
+ ...(output.plugins ?? []),
106
+ terser()
107
+ ]
108
+ }
109
+ ]
110
+
111
+ type TSConfig = {
112
+ extends?: string | string[]
113
+ compilerOptions?: Record<string, unknown>
114
+ references?: { path: string }[]
115
+ files?: string[]
116
+ include?: string[]
117
+ exclude?: string[]
118
+ }
119
+
120
+ const getTSConfig = (p: string): TSConfig =>
121
+ !fs.existsSync(p) || !fs.statSync(p).isFile()
122
+ ? {}
123
+ : parse(fs.readFileSync(p, 'utf-8'), [], { allowTrailingComma: true, allowEmptyContent: true })
124
+
125
+ const getExtendTSConfig = (tsconfigPath: string): TSConfig => {
126
+ tsconfigPath = resolve(tsconfigPath)
127
+ const tsconfigPathDirname = dirname(tsconfigPath)
128
+ const { extends: exts, ...tsconfig } = getTSConfig(tsconfigPath)
129
+ const resolvePaths = (paths: string[] | undefined) => paths?.map(p => resolve(tsconfigPathDirname, p)) ?? []
130
+
131
+ const extendsPaths = resolvePaths(
132
+ exts ? Array.isArray(exts) ? exts : [exts] : []
133
+ )
134
+ if (extendsPaths.length === 0) return tsconfig
135
+ return extendsPaths
136
+ .map(getExtendTSConfig)
137
+ // https://www.typescriptlang.org/tsconfig/#files:~:text=Currently%2C%20the%20only%20top%2Dlevel%20property%20that%20is%20excluded%20from%20inheritance%20is%20references.
138
+ // Currently, the only top-level property that is excluded from inheritance is references.
139
+ .reduce((acc, { compilerOptions = {}, references: _, ...curr }) => ({
140
+ ...acc,
141
+ ...curr,
142
+ compilerOptions: {
143
+ ...acc.compilerOptions,
144
+ ...compilerOptions
145
+ }
146
+ }), tsconfig)
147
+ }
148
+
149
+ const getCompilerOptionsByFilePath = (tsconfigPath: string, filePath: string): Record<string, unknown> | undefined => {
150
+ tsconfigPath = resolve(tsconfigPath)
151
+ filePath = resolve(filePath)
152
+ const tsconfigPathDirname = dirname(tsconfigPath)
153
+ // https://www.typescriptlang.org/tsconfig/#files:~:text=It%E2%80%99s%20worth%20noting%20that%20files%2C%20include%2C%20and%20exclude%20from%20the%20inheriting%20config%20file%20overwrite%20those%20from%20the%20base%20config%20file%2C%20and%20that%20circularity%20between%20configuration%20files%20is%20not%20allowed.
154
+ // It’s worth noting that files, include, and exclude from the inheriting config file overwrite
155
+ // those from the base config file, and that circularity between configuration files is not allowed.
156
+ const tsconfig = getExtendTSConfig(tsconfigPath)
157
+
158
+ const resolvePaths = (paths: string[] | undefined) => paths?.map(p => resolve(tsconfigPathDirname, p)) ?? []
159
+
160
+ const [
161
+ references,
162
+ files,
163
+ include,
164
+ exclude
165
+ ] = [
166
+ tsconfig.references?.map(({ path }) => path),
167
+ tsconfig.files,
168
+ tsconfig.include,
169
+ tsconfig.exclude
170
+ ].map(resolvePaths)
171
+ if (exclude.length > 0 && exclude.some(i => isMatch(filePath, i))) return
172
+
173
+ // when files or include is not empty, the tsconfig should be ignored
174
+ if (tsconfig.files?.length === 0 && tsconfig.include?.length === 0) return
175
+ let isInclude = false
176
+ isInclude ||= files.length > 0 && files.includes(filePath)
177
+ isInclude ||= include.length > 0 && include.some(i => isMatch(filePath, i))
178
+ if (isInclude) {
179
+ return tsconfig.compilerOptions ?? {}
180
+ } else {
181
+ // when files or include is not empty, but the file is not matched, the tsconfig should be ignored
182
+ if (
183
+ (tsconfig.files && tsconfig.files.length > 0)
184
+ || (tsconfig.include && tsconfig.include.length > 0)
185
+ ) return
186
+ }
187
+
188
+ references.reverse()
189
+ for (const ref of references) {
190
+ const compilerOptions = getCompilerOptionsByFilePath(ref, filePath)
191
+ if (compilerOptions) return compilerOptions
192
+ }
193
+ return tsconfig.compilerOptions
194
+ }
195
+
196
+ const generateConfigs = ({
197
+ path,
198
+ name,
199
+ input,
200
+ output,
201
+ external,
202
+ pkgIsModule,
203
+ conditionals
204
+ }: {
205
+ path: string
206
+ name: string
207
+ input: string
208
+ output: string
209
+ external: (string | RegExp)[]
210
+ pkgIsModule: boolean
211
+ conditionals: string[]
212
+ }, options: TemplateOptions = {}): RollupOptions[] => {
213
+ const isModule = conditionals.includes('import')
214
+ const isCommonJS = conditionals.includes('require')
215
+ const isBrowser = conditionals.includes('browser')
216
+ const dtsTSConfigPaths = [
217
+ resolveWorkspacePath('tsconfig.json'),
218
+ resolveWorkspacePath('tsconfig.dts.json')
219
+ ]
220
+ let dtsTSConfigPath: string | undefined
221
+ dtsTSConfigPaths.forEach(p => {
222
+ if (fs.existsSync(p) && fs.statSync(p).isFile()) {
223
+ dtsTSConfigPath = p
224
+ }
225
+ })
226
+ let compilerOptions: ts.CompilerOptions = {}
227
+ if (dtsTSConfigPath) {
228
+ const jsonCompilerOptions = getCompilerOptionsByFilePath(dtsTSConfigPath, resolve(input))
229
+ const { options, errors } = ts.convertCompilerOptionsFromJson(
230
+ jsonCompilerOptions,
231
+ dirname(dtsTSConfigPath)
232
+ )
233
+ if (errors.length > 0) {
234
+ throw new Error(errors.map(e => e.messageText).join('\n'))
235
+ }
236
+ compilerOptions = options
237
+ }
238
+ const exportConditions = [...conditionals, ...(compilerOptions.customConditions ?? [])]
239
+ const throughEventProps: RollupProgressEvent & { type: 'progress' } = {
240
+ type: 'progress',
241
+ data: { name, path, exportConditions, input }
242
+ }
243
+ const outdir = options?.output?.dir
244
+ return [
245
+ {
246
+ input,
247
+ external,
248
+ output: [
249
+ ...withMinify({
250
+ file: output,
251
+ name,
252
+ sourcemap: typeof options?.output?.sourcemap === 'object'
253
+ ? options.output.sourcemap.js
254
+ : options?.output?.sourcemap,
255
+ format: isModule ? 'esm' : (
256
+ isCommonJS ? 'cjs' : (
257
+ isBrowser ? 'umd' : (
258
+ pkgIsModule ? 'esm' : 'cjs'
259
+ )
260
+ )
261
+ ),
262
+ strict: typeof options?.output?.strict === 'object'
263
+ ? options.output.strict.js
264
+ : options?.output?.strict
265
+ })
266
+ ],
267
+ plugins: [
268
+ nodeResolve({ exportConditions }),
269
+ import('rollup-plugin-postcss')
270
+ .then(({ default: postcss }) =>
271
+ postcss({
272
+ extract: resolve(output.replace(/\.[cm]?js$/, '.css')),
273
+ minimize: true
274
+ })
275
+ )
276
+ .catch(() => void 0),
277
+ esbuild(),
278
+ progress({
279
+ onEvent: (event, message) =>
280
+ sendMessage(
281
+ {
282
+ ...throughEventProps,
283
+ data: { ...throughEventProps.data, event, message, tags: ['js'] }
284
+ } satisfies RollupProgressEvent
285
+ )
286
+ })
287
+ ]
288
+ },
289
+ {
290
+ input,
291
+ external,
292
+ output: [
293
+ {
294
+ dir: resolve((typeof outdir === 'object' ? outdir.dts : outdir) ?? 'dist'),
295
+ sourcemap: typeof options?.output?.sourcemap === 'object'
296
+ ? options.output.sourcemap.dts
297
+ : options?.output?.sourcemap,
298
+ entryFileNames: () =>
299
+ output
300
+ .replace(`${jsOutdir}/`, '')
301
+ .replace(/(\.[cm]?)js$/, '.d$1ts'),
302
+ strict: typeof options?.output?.strict === 'object'
303
+ ? options.output.strict.dts
304
+ : options?.output?.strict
305
+ }
306
+ ],
307
+ plugins: [
308
+ nodeResolve({ exportConditions }),
309
+ skip({ patterns: [STYLE_REGEXP] }),
310
+ dts({
311
+ respectExternal: true,
312
+ compilerOptions
313
+ }),
314
+ progress({
315
+ onEvent: (event, message) =>
316
+ sendMessage(
317
+ {
318
+ ...throughEventProps,
319
+ data: { ...throughEventProps.data, event, message, tags: ['dts'] }
320
+ } satisfies RollupProgressEvent
321
+ )
322
+ })
323
+ ]
324
+ }
325
+ ]
326
+ }
327
+
328
+ export function template(packageJSON: PackageJSON): RollupOptions[] {
329
+ const { name, type, exports: entrypoints } = packageJSON
330
+ const pkgIsModule = type === 'module'
331
+ if (!name) throw new Error('package.json name is required')
332
+ if (!entrypoints) throw new Error('package.json exports is required')
333
+
334
+ const entries = JIEK_ENTRIES
335
+ ?.split(',')
336
+ .map(e => e.trim())
337
+ .map(e => ({
338
+ 'index': '.'
339
+ }[e] ?? e))
340
+
341
+ const packageName = pascalCase(name)
342
+
343
+ const external = externalResolver(packageJSON as Record<string, unknown>)
344
+
345
+ const [filteredResolvedEntrypoints, exports] = getExports({
346
+ entrypoints,
347
+ pkgIsModule,
348
+ entries,
349
+ config
350
+ })
351
+
352
+ const leafMap = new Map<string, string[][]>()
353
+ getAllLeafs(filteredResolvedEntrypoints as RecursiveRecord<string>, ({ keys, value }) => {
354
+ if (typeof value === 'string') {
355
+ const keysArr = leafMap.get(value) ?? []
356
+ leafMap.set(value, keysArr)
357
+ keysArr.push(keys)
358
+ }
359
+ return false
360
+ })
361
+
362
+ const configs: RollupOptions[] = []
363
+ leafMap.forEach((keysArr, input) =>
364
+ keysArr.forEach((keys) => {
365
+ const [path, ...conditionals] = keys
366
+
367
+ const name = packageName + (path === '.' ? '' : pascalCase(path))
368
+ const keyExports = reveal(exports, keys)
369
+ const commonOptions = {
370
+ path,
371
+ name,
372
+ input,
373
+ external,
374
+ pkgIsModule
375
+ }
376
+
377
+ switch (typeof keyExports) {
378
+ case 'string': {
379
+ configs.push(...generateConfigs({
380
+ ...commonOptions,
381
+ output: keyExports,
382
+ conditionals
383
+ }, build))
384
+ break
385
+ }
386
+ case 'object': {
387
+ getAllLeafs(keyExports as RecursiveRecord<string>, ({ keys: nextKeys, value }) => {
388
+ const allConditionals = [...new Set([...conditionals, ...nextKeys])]
389
+ if (typeof value === 'string') {
390
+ configs.push(...generateConfigs({
391
+ ...commonOptions,
392
+ output: value,
393
+ conditionals: allConditionals
394
+ }, build))
395
+ }
396
+ return false
397
+ })
398
+ break
399
+ }
400
+ }
401
+ })
402
+ )
403
+ sendMessage(
404
+ {
405
+ type: 'init',
406
+ data: {
407
+ leafMap,
408
+ targetsLength: configs.length
409
+ }
410
+ } satisfies RollupProgressEvent
411
+ )
412
+ return configs.map(c => ({
413
+ ...COMMON_OPTIONS,
414
+ ...c,
415
+ plugins: [
416
+ ...COMMON_PLUGINS,
417
+ c.plugins
418
+ ]
419
+ }))
420
+ }
@@ -0,0 +1,34 @@
1
+ import type { Plugin, PluginImpl } from 'rollup'
2
+
3
+ import globalResolver from '../utils/globalResolver'
4
+
5
+ interface GlobalsOptions {
6
+ external?: (string | RegExp)[]
7
+ }
8
+
9
+ export function createGlobalsLinkage() {
10
+ let globals = {}
11
+ const dependencies = new Set<string>([])
12
+ return [
13
+ (({ external } = {}) => {
14
+ return {
15
+ name: 'globals',
16
+ resolveId(id) {
17
+ if (external?.some(dep => dep instanceof RegExp ? dep.test(id) : dep === id)) {
18
+ dependencies.add(id)
19
+ return { id, external: true }
20
+ }
21
+ return null
22
+ },
23
+ outputOptions(options) {
24
+ globals = [...dependencies].reduce((acc, value) => ({
25
+ ...acc,
26
+ [value]: globalResolver(value)
27
+ }), {})
28
+ return { ...options, globals }
29
+ }
30
+ }
31
+ }) as PluginImpl<GlobalsOptions>,
32
+ { outputOptions: options => ({ ...options, globals }) } as Plugin
33
+ ] as const
34
+ }
@@ -0,0 +1,26 @@
1
+ import type { PluginImpl } from 'rollup'
2
+
3
+ interface Options {
4
+ onEvent?: (event: string, message?: string) => void
5
+ }
6
+
7
+ export default ((options = {}) => {
8
+ const { onEvent } = options
9
+ return {
10
+ name: 'progress',
11
+ buildStart: () => onEvent?.('start', 'Start building...'),
12
+ buildEnd: () => onEvent?.('end', 'Build completed!'),
13
+ resolveId: {
14
+ order: 'post',
15
+ handler: source => onEvent?.('resolve', `Resolving ${source}...`)
16
+ },
17
+ load: {
18
+ order: 'post',
19
+ handler: id => onEvent?.('load', `Loading ${id}...`)
20
+ },
21
+ transform: {
22
+ order: 'post',
23
+ handler: (_, id) => onEvent?.('transform', `Transforming ${id}...`)
24
+ }
25
+ }
26
+ }) as PluginImpl<Options>
@@ -0,0 +1,23 @@
1
+ import type { PluginImpl } from 'rollup'
2
+
3
+ interface Options {
4
+ patterns?: (string | RegExp)[]
5
+ }
6
+
7
+ export default ((options = {}) => {
8
+ return {
9
+ name: 'skip',
10
+ // skip the specified files by `options.patterns`
11
+ load(id) {
12
+ if (
13
+ options.patterns?.some((pattern) =>
14
+ typeof pattern === 'string'
15
+ ? id.includes(pattern)
16
+ : pattern.test(id)
17
+ )
18
+ ) {
19
+ return ''
20
+ }
21
+ }
22
+ }
23
+ }) as PluginImpl<Options>
@@ -0,0 +1,9 @@
1
+ import type { OutputOptions } from 'rollup'
2
+
3
+ const defineOutput = <O extends OutputOptions>(output: O) => output
4
+
5
+ export const commonOutputOptions = defineOutput({
6
+ exports: 'named',
7
+ interop: 'auto',
8
+ sourcemap: true
9
+ })
@@ -0,0 +1,21 @@
1
+ import fs from 'node:fs'
2
+
3
+ export default function(json: Record<string, unknown>): (string | RegExp)[]
4
+ export default function(path?: string): (string | RegExp)[]
5
+ export default function(jsonOrPath: string | Record<string, unknown> = process.cwd()): (string | RegExp)[] {
6
+ const pkg = typeof jsonOrPath === 'string'
7
+ ? fs.existsSync(`${jsonOrPath}/package.json`)
8
+ ? JSON.parse(fs.readFileSync(`${jsonOrPath}/package.json`, 'utf-8'))
9
+ : {}
10
+ : jsonOrPath
11
+ const { dependencies = {}, peerDependencies = {}, optionalDependencies = {} } = pkg
12
+ const external = <(string | RegExp)[]> Object
13
+ .keys(dependencies)
14
+ .concat(Object.keys(peerDependencies))
15
+ .concat(Object.keys(optionalDependencies))
16
+ return external
17
+ .map(dep => new RegExp(`^${dep}(/.*)?$`))
18
+ .concat([
19
+ /^node:/
20
+ ])
21
+ }
@@ -0,0 +1,13 @@
1
+ export default function (external: string) {
2
+ // a/b => AB
3
+ // a-b => AB
4
+ // a@b => AB
5
+ // a@b/c => ABC
6
+ // node:a => a
7
+ // node:a_b => a_b
8
+ if (external.startsWith('node:')) {
9
+ return external.slice(5)
10
+ }
11
+ return external
12
+ .replace(/[@|/-](\w)/g, (_, $1) => $1.toUpperCase())
13
+ }
@@ -0,0 +1,18 @@
1
+ import terser from '@rollup/plugin-terser'
2
+ import type { OutputOptions, OutputPlugin } from 'rollup'
3
+
4
+ export default function(
5
+ output: OutputOptions & {
6
+ entryFileNames?: string
7
+ plugins?: OutputPlugin[]
8
+ }
9
+ ): OutputOptions[] {
10
+ return [
11
+ output,
12
+ {
13
+ ...output,
14
+ entryFileNames: output.entryFileNames?.replace(/(\.[cm]?js)$/, '.min$1'),
15
+ plugins: [...(output.plugins ?? []), terser()]
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,82 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+
4
+ import { filterPackagesFromDir } from '@pnpm/filter-workspace-packages'
5
+ import { program } from 'commander'
6
+ import { load } from 'js-yaml'
7
+
8
+ import { getRoot } from './getRoot'
9
+ import { getWD } from './getWD'
10
+
11
+ export let type = ''
12
+
13
+ try {
14
+ require.resolve('@pnpm/filter-workspace-packages')
15
+ type = 'pnpm'
16
+ } catch { /* empty */ }
17
+ if (type !== '') {
18
+ program
19
+ .option('-f, --filter <filter>', 'filter packages')
20
+ }
21
+
22
+ interface ProjectsGraph {
23
+ wd: string
24
+ root: string
25
+ value?: Record<string, {
26
+ name?: string
27
+ type?: string
28
+ exports?: string | string[] | Record<string, unknown>
29
+ }>
30
+ }
31
+
32
+ export async function getSelectedProjectsGraph(): Promise<ProjectsGraph> {
33
+ let filter = program.getOptionValue('filter')
34
+ const root = getRoot()
35
+ const { wd, notWorkspace } = getWD()
36
+ if (!notWorkspace && type === 'pnpm') {
37
+ const pnpmWorkspaceFilePath = path.resolve(wd, 'pnpm-workspace.yaml')
38
+ const pnpmWorkspaceFileContent = fs.readFileSync(pnpmWorkspaceFilePath, 'utf-8')
39
+ const pnpmWorkspace = load(pnpmWorkspaceFileContent) as {
40
+ packages: string[]
41
+ }
42
+ if (root === wd && !filter) {
43
+ throw new Error('root path is workspace root, please provide a filter')
44
+ // TODO inquirer prompt support user select packages
45
+ }
46
+ if (root !== wd && !filter) {
47
+ const packageJSONIsExist = fs.existsSync(path.resolve(root, 'package.json'))
48
+ if (!packageJSONIsExist) {
49
+ throw new Error('root path is not workspace root, please provide a filter')
50
+ }
51
+ const packageJSON = JSON.parse(fs.readFileSync(path.resolve(root, 'package.json'), 'utf-8'))
52
+ if (!packageJSON.name) {
53
+ throw new Error('root path is not workspace root, please provide a filter')
54
+ }
55
+ filter = packageJSON.name
56
+ }
57
+ const { selectedProjectsGraph } = await filterPackagesFromDir(wd, [{
58
+ filter: filter ?? '',
59
+ followProdDepsOnly: true
60
+ }], {
61
+ prefix: root,
62
+ workspaceDir: wd,
63
+ patterns: pnpmWorkspace.packages
64
+ })
65
+ return {
66
+ wd,
67
+ root,
68
+ value: Object.entries(selectedProjectsGraph)
69
+ .reduce((acc, [key, value]) => {
70
+ acc[key] = value.package.manifest
71
+ return acc
72
+ }, {} as NonNullable<ProjectsGraph['value']>)
73
+ }
74
+ }
75
+ return {
76
+ wd,
77
+ root,
78
+ value: {
79
+ [wd]: JSON.parse(fs.readFileSync(path.resolve(wd, 'package.json'), 'utf-8'))
80
+ }
81
+ }
82
+ }