jiek 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +26 -0
- package/bin/jiek.js +13 -0
- package/dist/cli.cjs +5041 -0
- package/dist/cli.d.cts +112 -0
- package/dist/cli.d.ts +112 -0
- package/dist/cli.js +5010 -0
- package/dist/cli.min.cjs +19 -0
- package/dist/cli.min.js +19 -0
- package/dist/index.cjs +5 -0
- package/dist/index.d.cts +73 -0
- package/dist/index.d.ts +73 -0
- package/dist/index.js +3 -0
- package/dist/index.min.cjs +1 -0
- package/dist/index.min.js +1 -0
- package/dist/rollup/index.cjs +4688 -0
- package/dist/rollup/index.d.cts +53 -0
- package/dist/rollup/index.d.ts +53 -0
- package/dist/rollup/index.js +4673 -0
- package/dist/rollup/index.min.cjs +19 -0
- package/dist/rollup/index.min.js +19 -0
- package/package.json +89 -4
- package/src/cli.ts +9 -0
- package/src/commands/base.ts +8 -0
- package/src/commands/build.ts +158 -0
- package/src/commands/init.ts +373 -0
- package/src/commands/publish.ts +170 -0
- package/src/index.ts +8 -0
- package/src/inner.ts +11 -0
- package/src/merge-package-json.ts +75 -0
- package/src/rollup/base.ts +72 -0
- package/src/rollup/index.ts +422 -0
- package/src/rollup/plugins/globals.ts +34 -0
- package/src/rollup/plugins/progress.ts +26 -0
- package/src/rollup/plugins/skip.ts +23 -0
- package/src/rollup/utils/commonOptions.ts +9 -0
- package/src/rollup/utils/externalResolver.ts +21 -0
- package/src/rollup/utils/globalResolver.ts +13 -0
- package/src/rollup/utils/withMinify.ts +18 -0
- package/src/utils/filterSupport.ts +84 -0
- package/src/utils/getExports.ts +104 -0
- package/src/utils/getRoot.ts +16 -0
- package/src/utils/getWD.ts +31 -0
- package/src/utils/loadConfig.ts +93 -0
- package/src/utils/tsRegister.ts +26 -0
- package/index.js +0 -1
@@ -0,0 +1,422 @@
|
|
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 commonjs from '@rollup/plugin-commonjs'
|
11
|
+
import json from '@rollup/plugin-json'
|
12
|
+
import { nodeResolve } from '@rollup/plugin-node-resolve'
|
13
|
+
import terser from '@rollup/plugin-terser'
|
14
|
+
import { sendMessage } from 'execa'
|
15
|
+
import { parse } from 'jsonc-parser'
|
16
|
+
import { isMatch } from 'micromatch'
|
17
|
+
import type { OutputOptions, OutputPlugin, RollupOptions } from 'rollup'
|
18
|
+
import esbuild from 'rollup-plugin-esbuild'
|
19
|
+
import ts from 'typescript'
|
20
|
+
|
21
|
+
import { getExports } from '../utils/getExports'
|
22
|
+
import { loadConfig } from '../utils/loadConfig'
|
23
|
+
import type { RollupProgressEvent, TemplateOptions } from './base'
|
24
|
+
import progress from './plugins/progress'
|
25
|
+
import skip from './plugins/skip'
|
26
|
+
import externalResolver from './utils/externalResolver'
|
27
|
+
|
28
|
+
interface PackageJSON {
|
29
|
+
name?: string
|
30
|
+
type?: string
|
31
|
+
exports?: Record<string, unknown> | string | string[]
|
32
|
+
}
|
33
|
+
|
34
|
+
const {
|
35
|
+
JIEK_ROOT,
|
36
|
+
JIEK_ENTRIES
|
37
|
+
} = process.env
|
38
|
+
const WORKSPACE_ROOT = JIEK_ROOT ?? getWorkspaceDir()
|
39
|
+
const COMMON_OPTIONS = {} satisfies RollupOptions
|
40
|
+
const COMMON_PLUGINS = [
|
41
|
+
json()
|
42
|
+
]
|
43
|
+
|
44
|
+
const config = loadConfig() ?? {}
|
45
|
+
const { build = {} } = config
|
46
|
+
const jsOutdir = `./${
|
47
|
+
relative(
|
48
|
+
process.cwd(),
|
49
|
+
resolve(
|
50
|
+
(
|
51
|
+
typeof build?.output?.dir === 'object'
|
52
|
+
// the outdir only affect js output in this function
|
53
|
+
? build.output.dir.js
|
54
|
+
: build?.output?.dir
|
55
|
+
) ?? 'dist'
|
56
|
+
)
|
57
|
+
)
|
58
|
+
}`
|
59
|
+
|
60
|
+
const STYLE_REGEXP = /\.(css|s[ac]ss|less|styl)$/
|
61
|
+
|
62
|
+
// eslint-disable-next-line unused-imports/no-unused-vars
|
63
|
+
const debug = (...args: unknown[]) => sendMessage({ type: 'debug', data: args } satisfies RollupProgressEvent)
|
64
|
+
|
65
|
+
const resolveWorkspacePath = (p: string) => resolve(WORKSPACE_ROOT, p)
|
66
|
+
|
67
|
+
const pascalCase = (str: string) =>
|
68
|
+
str
|
69
|
+
.replace(/[@|/-](\w)/g, (_, $1) => $1.toUpperCase())
|
70
|
+
.replace(/(?:^|-)(\w)/g, (_, $1) => $1.toUpperCase())
|
71
|
+
|
72
|
+
const reveal = (obj: string | Record<string, unknown>, keys: string[]) =>
|
73
|
+
keys.reduce((acc, key) => {
|
74
|
+
if (typeof acc === 'string') throw new Error('key not found in exports')
|
75
|
+
if (!(key in acc)) throw new Error(`key ${key} not found in exports`)
|
76
|
+
return acc[key] as string | Record<string, unknown>
|
77
|
+
}, obj)
|
78
|
+
|
79
|
+
const withMinify = (
|
80
|
+
output: OutputOptions & {
|
81
|
+
plugins?: OutputPlugin[]
|
82
|
+
},
|
83
|
+
minify = build?.output?.minify
|
84
|
+
) =>
|
85
|
+
minify === false
|
86
|
+
? [output]
|
87
|
+
: minify === 'only-minify'
|
88
|
+
? [{
|
89
|
+
...output,
|
90
|
+
// TODO replace suffix when pubish to npm and the `build.output.minify` is 'only-minify'
|
91
|
+
// TODO resolve dts output file name
|
92
|
+
file: output.file?.replace(/(\.[cm]?js)$/, '.min$1'),
|
93
|
+
plugins: [
|
94
|
+
...(output.plugins ?? []),
|
95
|
+
terser()
|
96
|
+
]
|
97
|
+
}]
|
98
|
+
: [
|
99
|
+
output,
|
100
|
+
{
|
101
|
+
...output,
|
102
|
+
file: output.file?.replace(/(\.[cm]?js)$/, '.min$1'),
|
103
|
+
plugins: [
|
104
|
+
...(output.plugins ?? []),
|
105
|
+
terser()
|
106
|
+
]
|
107
|
+
}
|
108
|
+
]
|
109
|
+
|
110
|
+
type TSConfig = {
|
111
|
+
extends?: string | string[]
|
112
|
+
compilerOptions?: Record<string, unknown>
|
113
|
+
references?: { path: string }[]
|
114
|
+
files?: string[]
|
115
|
+
include?: string[]
|
116
|
+
exclude?: string[]
|
117
|
+
}
|
118
|
+
|
119
|
+
const getTSConfig = (p: string): TSConfig =>
|
120
|
+
!fs.existsSync(p) || !fs.statSync(p).isFile()
|
121
|
+
? {}
|
122
|
+
: parse(fs.readFileSync(p, 'utf-8'), [], { allowTrailingComma: true, allowEmptyContent: true })
|
123
|
+
|
124
|
+
const getExtendTSConfig = (tsconfigPath: string): TSConfig => {
|
125
|
+
tsconfigPath = resolve(tsconfigPath)
|
126
|
+
const tsconfigPathDirname = dirname(tsconfigPath)
|
127
|
+
const { extends: exts, ...tsconfig } = getTSConfig(tsconfigPath)
|
128
|
+
const resolvePaths = (paths: string[] | undefined) => paths?.map(p => resolve(tsconfigPathDirname, p)) ?? []
|
129
|
+
|
130
|
+
const extendsPaths = resolvePaths(
|
131
|
+
exts ? Array.isArray(exts) ? exts : [exts] : []
|
132
|
+
)
|
133
|
+
if (extendsPaths.length === 0) return tsconfig
|
134
|
+
return extendsPaths
|
135
|
+
.map(getExtendTSConfig)
|
136
|
+
.concat(tsconfig)
|
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
|
+
}), {})
|
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
|
+
interop: 'auto',
|
253
|
+
sourcemap: typeof options?.output?.sourcemap === 'object'
|
254
|
+
? options.output.sourcemap.js
|
255
|
+
: options?.output?.sourcemap,
|
256
|
+
format: isModule ? 'esm' : (
|
257
|
+
isCommonJS ? 'cjs' : (
|
258
|
+
isBrowser ? 'umd' : (
|
259
|
+
pkgIsModule ? 'esm' : 'cjs'
|
260
|
+
)
|
261
|
+
)
|
262
|
+
),
|
263
|
+
strict: typeof options?.output?.strict === 'object'
|
264
|
+
? options.output.strict.js
|
265
|
+
: options?.output?.strict
|
266
|
+
})
|
267
|
+
],
|
268
|
+
plugins: [
|
269
|
+
nodeResolve({ exportConditions }),
|
270
|
+
import('rollup-plugin-postcss')
|
271
|
+
.then(({ default: postcss }) =>
|
272
|
+
postcss({
|
273
|
+
extract: resolve(output.replace(/\.[cm]?js$/, '.css')),
|
274
|
+
minimize: true
|
275
|
+
})
|
276
|
+
)
|
277
|
+
.catch(() => void 0),
|
278
|
+
esbuild(),
|
279
|
+
commonjs(),
|
280
|
+
progress({
|
281
|
+
onEvent: (event, message) =>
|
282
|
+
sendMessage(
|
283
|
+
{
|
284
|
+
...throughEventProps,
|
285
|
+
data: { ...throughEventProps.data, event, message, tags: ['js'] }
|
286
|
+
} satisfies RollupProgressEvent
|
287
|
+
)
|
288
|
+
})
|
289
|
+
]
|
290
|
+
},
|
291
|
+
{
|
292
|
+
input,
|
293
|
+
external,
|
294
|
+
output: [
|
295
|
+
{
|
296
|
+
dir: resolve((typeof outdir === 'object' ? outdir.dts : outdir) ?? 'dist'),
|
297
|
+
sourcemap: typeof options?.output?.sourcemap === 'object'
|
298
|
+
? options.output.sourcemap.dts
|
299
|
+
: options?.output?.sourcemap,
|
300
|
+
entryFileNames: () =>
|
301
|
+
output
|
302
|
+
.replace(`${jsOutdir}/`, '')
|
303
|
+
.replace(/(\.[cm]?)js$/, '.d$1ts'),
|
304
|
+
strict: typeof options?.output?.strict === 'object'
|
305
|
+
? options.output.strict.dts
|
306
|
+
: options?.output?.strict
|
307
|
+
}
|
308
|
+
],
|
309
|
+
plugins: [
|
310
|
+
nodeResolve({ exportConditions }),
|
311
|
+
skip({ patterns: [STYLE_REGEXP] }),
|
312
|
+
dts({
|
313
|
+
respectExternal: true,
|
314
|
+
compilerOptions
|
315
|
+
}),
|
316
|
+
progress({
|
317
|
+
onEvent: (event, message) =>
|
318
|
+
sendMessage(
|
319
|
+
{
|
320
|
+
...throughEventProps,
|
321
|
+
data: { ...throughEventProps.data, event, message, tags: ['dts'] }
|
322
|
+
} satisfies RollupProgressEvent
|
323
|
+
)
|
324
|
+
})
|
325
|
+
]
|
326
|
+
}
|
327
|
+
]
|
328
|
+
}
|
329
|
+
|
330
|
+
export function template(packageJSON: PackageJSON): RollupOptions[] {
|
331
|
+
const { name, type, exports: entrypoints } = packageJSON
|
332
|
+
const pkgIsModule = type === 'module'
|
333
|
+
if (!name) throw new Error('package.json name is required')
|
334
|
+
if (!entrypoints) throw new Error('package.json exports is required')
|
335
|
+
|
336
|
+
const entries = JIEK_ENTRIES
|
337
|
+
?.split(',')
|
338
|
+
.map(e => e.trim())
|
339
|
+
.map(e => ({
|
340
|
+
'index': '.'
|
341
|
+
}[e] ?? e))
|
342
|
+
|
343
|
+
const packageName = pascalCase(name)
|
344
|
+
|
345
|
+
const external = externalResolver(packageJSON as Record<string, unknown>)
|
346
|
+
|
347
|
+
const [filteredResolvedEntrypoints, exports] = getExports({
|
348
|
+
entrypoints,
|
349
|
+
pkgIsModule,
|
350
|
+
entries,
|
351
|
+
config
|
352
|
+
})
|
353
|
+
|
354
|
+
const leafMap = new Map<string, string[][]>()
|
355
|
+
getAllLeafs(filteredResolvedEntrypoints as RecursiveRecord<string>, ({ keys, value }) => {
|
356
|
+
if (typeof value === 'string') {
|
357
|
+
const keysArr = leafMap.get(value) ?? []
|
358
|
+
leafMap.set(value, keysArr)
|
359
|
+
keysArr.push(keys)
|
360
|
+
}
|
361
|
+
return false
|
362
|
+
})
|
363
|
+
|
364
|
+
const configs: RollupOptions[] = []
|
365
|
+
leafMap.forEach((keysArr, input) =>
|
366
|
+
keysArr.forEach((keys) => {
|
367
|
+
const [path, ...conditionals] = keys
|
368
|
+
|
369
|
+
const name = packageName + (path === '.' ? '' : pascalCase(path))
|
370
|
+
const keyExports = reveal(exports, keys)
|
371
|
+
const commonOptions = {
|
372
|
+
path,
|
373
|
+
name,
|
374
|
+
input,
|
375
|
+
external,
|
376
|
+
pkgIsModule
|
377
|
+
}
|
378
|
+
|
379
|
+
switch (typeof keyExports) {
|
380
|
+
case 'string': {
|
381
|
+
configs.push(...generateConfigs({
|
382
|
+
...commonOptions,
|
383
|
+
output: keyExports,
|
384
|
+
conditionals
|
385
|
+
}, build))
|
386
|
+
break
|
387
|
+
}
|
388
|
+
case 'object': {
|
389
|
+
getAllLeafs(keyExports as RecursiveRecord<string>, ({ keys: nextKeys, value }) => {
|
390
|
+
const allConditionals = [...new Set([...conditionals, ...nextKeys])]
|
391
|
+
if (typeof value === 'string') {
|
392
|
+
configs.push(...generateConfigs({
|
393
|
+
...commonOptions,
|
394
|
+
output: value,
|
395
|
+
conditionals: allConditionals
|
396
|
+
}, build))
|
397
|
+
}
|
398
|
+
return false
|
399
|
+
})
|
400
|
+
break
|
401
|
+
}
|
402
|
+
}
|
403
|
+
})
|
404
|
+
)
|
405
|
+
sendMessage(
|
406
|
+
{
|
407
|
+
type: 'init',
|
408
|
+
data: {
|
409
|
+
leafMap,
|
410
|
+
targetsLength: configs.length
|
411
|
+
}
|
412
|
+
} satisfies RollupProgressEvent
|
413
|
+
)
|
414
|
+
return configs.map(c => ({
|
415
|
+
...COMMON_OPTIONS,
|
416
|
+
...c,
|
417
|
+
plugins: [
|
418
|
+
...COMMON_PLUGINS,
|
419
|
+
c.plugins
|
420
|
+
]
|
421
|
+
}))
|
422
|
+
}
|
@@ -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,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,84 @@
|
|
1
|
+
import fs from 'node:fs'
|
2
|
+
import { createRequire } from 'node:module'
|
3
|
+
import path from 'node:path'
|
4
|
+
|
5
|
+
import { filterPackagesFromDir } from '@pnpm/filter-workspace-packages'
|
6
|
+
import { program } from 'commander'
|
7
|
+
import { load } from 'js-yaml'
|
8
|
+
|
9
|
+
import { getRoot } from './getRoot'
|
10
|
+
import { getWD } from './getWD'
|
11
|
+
|
12
|
+
export let type = ''
|
13
|
+
|
14
|
+
try {
|
15
|
+
const require = createRequire(import.meta.url)
|
16
|
+
require.resolve('@pnpm/filter-workspace-packages')
|
17
|
+
type = 'pnpm'
|
18
|
+
} catch { /* empty */ }
|
19
|
+
if (type !== '') {
|
20
|
+
program
|
21
|
+
.option('-f, --filter <filter>', 'filter packages')
|
22
|
+
}
|
23
|
+
|
24
|
+
interface ProjectsGraph {
|
25
|
+
wd: string
|
26
|
+
root: string
|
27
|
+
value?: Record<string, {
|
28
|
+
name?: string
|
29
|
+
type?: string
|
30
|
+
exports?: string | string[] | Record<string, unknown>
|
31
|
+
}>
|
32
|
+
}
|
33
|
+
|
34
|
+
export async function getSelectedProjectsGraph(): Promise<ProjectsGraph> {
|
35
|
+
let filter = program.getOptionValue('filter')
|
36
|
+
const root = getRoot()
|
37
|
+
const { wd, notWorkspace } = getWD()
|
38
|
+
if (!notWorkspace && type === 'pnpm') {
|
39
|
+
const pnpmWorkspaceFilePath = path.resolve(wd, 'pnpm-workspace.yaml')
|
40
|
+
const pnpmWorkspaceFileContent = fs.readFileSync(pnpmWorkspaceFilePath, 'utf-8')
|
41
|
+
const pnpmWorkspace = load(pnpmWorkspaceFileContent) as {
|
42
|
+
packages: string[]
|
43
|
+
}
|
44
|
+
if (root === wd && !filter) {
|
45
|
+
throw new Error('root path is workspace root, please provide a filter')
|
46
|
+
// TODO inquirer prompt support user select packages
|
47
|
+
}
|
48
|
+
if (root !== wd && !filter) {
|
49
|
+
const packageJSONIsExist = fs.existsSync(path.resolve(root, 'package.json'))
|
50
|
+
if (!packageJSONIsExist) {
|
51
|
+
throw new Error('root path is not workspace root, please provide a filter')
|
52
|
+
}
|
53
|
+
const packageJSON = JSON.parse(fs.readFileSync(path.resolve(root, 'package.json'), 'utf-8'))
|
54
|
+
if (!packageJSON.name) {
|
55
|
+
throw new Error('root path is not workspace root, please provide a filter')
|
56
|
+
}
|
57
|
+
filter = packageJSON.name
|
58
|
+
}
|
59
|
+
const { selectedProjectsGraph } = await filterPackagesFromDir(wd, [{
|
60
|
+
filter: filter ?? '',
|
61
|
+
followProdDepsOnly: true
|
62
|
+
}], {
|
63
|
+
prefix: root,
|
64
|
+
workspaceDir: wd,
|
65
|
+
patterns: pnpmWorkspace.packages
|
66
|
+
})
|
67
|
+
return {
|
68
|
+
wd,
|
69
|
+
root,
|
70
|
+
value: Object.entries(selectedProjectsGraph)
|
71
|
+
.reduce((acc, [key, value]) => {
|
72
|
+
acc[key] = value.package.manifest
|
73
|
+
return acc
|
74
|
+
}, {} as NonNullable<ProjectsGraph['value']>)
|
75
|
+
}
|
76
|
+
}
|
77
|
+
return {
|
78
|
+
wd,
|
79
|
+
root,
|
80
|
+
value: {
|
81
|
+
[wd]: JSON.parse(fs.readFileSync(path.resolve(wd, 'package.json'), 'utf-8'))
|
82
|
+
}
|
83
|
+
}
|
84
|
+
}
|