pkgbld 1.36.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs DELETED
@@ -1,1626 +0,0 @@
1
- import '@niceties/draftlog-appender';
2
- import { createLogger } from '@niceties/logger';
3
- import { rollup } from 'rollup';
4
- import fs, { readFile, access, stat, constants, writeFile, rm, readdir, mkdir, rename } from 'node:fs/promises';
5
- import path, { dirname, join } from 'node:path';
6
- import { cli, command } from 'cleye';
7
- import refiner from '@slimlib/refine-partition';
8
- import camelCase from 'lodash/camelCase.js';
9
- import kleur from 'kleur';
10
- import { fileURLToPath } from 'node:url';
11
- import cloneDeep from 'lodash/cloneDeep.js';
12
- import isEqual from 'lodash/isEqual.js';
13
-
14
- async function createSubpackages(inputs, config) {
15
- for (const input of inputs) {
16
- const basename = path.basename(input, path.extname(input));
17
- if (basename !== 'index') {
18
- const pkg = {
19
- type: 'module',
20
- types: `../${config.dir}/${basename}.d.ts`,
21
- main: `../${config.dir}/${basename}.mjs`
22
- };
23
- await fs.mkdir(basename, { recursive: true });
24
- await fs.writeFile(`${basename}/package.json`, JSON.stringify(pkg, null, 2));
25
- }
26
- }
27
- }
28
-
29
- function CommaSeparatedString(value) {
30
- return value.split(',').map((arg) => arg.trim());
31
- }
32
- function CommaSeparatedStringOrBoolean(value) {
33
- if (typeof value === 'boolean') {
34
- return value;
35
- }
36
- // TODO check how we get array here
37
- if (Array.isArray(value) && value.length === 0) {
38
- return true;
39
- }
40
- return CommaSeparatedString(value);
41
- }
42
- const cliFlagsDefaults = {
43
- formats: ['es', 'cjs'],
44
- umd: [],
45
- compress: ['umd'],
46
- sourcemaps: ['umd'],
47
- preprocess: [],
48
- dest: 'dist',
49
- src: 'src',
50
- bin: undefined,
51
- includeExternals: false,
52
- eject: false,
53
- noTsConfig: false,
54
- noUpdatePackageJson: false,
55
- commonjsPattern: '[name].cjs',
56
- esmPattern: '[name].mjs',
57
- umdPattern: '[name].umd.js',
58
- formatPackageJson: false,
59
- noSubpackages: false,
60
- };
61
- const cliFlags = {
62
- umd: {
63
- type: CommaSeparatedString,
64
- description: 'Package subpath exports in UMD format',
65
- default: cliFlagsDefaults.umd,
66
- },
67
- compress: {
68
- type: CommaSeparatedString,
69
- description: 'Compress formats using terser',
70
- default: cliFlagsDefaults.compress,
71
- },
72
- sourcemaps: {
73
- type: CommaSeparatedString,
74
- description: 'Emit sourcemaps for the specified formats',
75
- default: cliFlagsDefaults.sourcemaps,
76
- },
77
- formats: {
78
- type: CommaSeparatedString,
79
- description: 'Formats to emit',
80
- default: cliFlagsDefaults.formats,
81
- },
82
- preprocess: {
83
- type: CommaSeparatedString,
84
- description: 'Preprocess entry points / subpath exports',
85
- default: cliFlagsDefaults.preprocess,
86
- },
87
- dest: {
88
- type: String,
89
- description: 'Output directory',
90
- default: cliFlagsDefaults.dest,
91
- },
92
- src: {
93
- type: String,
94
- description: 'Source directory',
95
- default: cliFlagsDefaults.src,
96
- },
97
- bin: {
98
- type: CommaSeparatedString,
99
- description: 'Executable files',
100
- default: cliFlagsDefaults.bin,
101
- },
102
- includeExternals: {
103
- type: CommaSeparatedStringOrBoolean,
104
- description: 'Include all/specified externals into the result bundle(s)',
105
- default: cliFlagsDefaults.includeExternals,
106
- },
107
- eject: {
108
- type: Boolean,
109
- description: 'Eject config',
110
- default: cliFlagsDefaults.eject,
111
- },
112
- noTsConfig: {
113
- type: Boolean,
114
- description: 'Do not create / update tsconfig.json',
115
- default: cliFlagsDefaults.noTsConfig,
116
- },
117
- noUpdatePackageJson: {
118
- type: Boolean,
119
- description: 'Do not create / update package.json',
120
- default: cliFlagsDefaults.noUpdatePackageJson,
121
- },
122
- commonjsPattern: {
123
- type: String,
124
- description: 'CommonJS output file name pattern',
125
- default: cliFlagsDefaults.commonjsPattern,
126
- },
127
- esmPattern: {
128
- type: String,
129
- description: 'ES output file name pattern',
130
- default: cliFlagsDefaults.esmPattern,
131
- },
132
- umdPattern: {
133
- type: String,
134
- description: 'UMD output file name pattern',
135
- default: cliFlagsDefaults.umdPattern,
136
- },
137
- formatPackageJson: {
138
- type: Boolean,
139
- description: 'Format package.json',
140
- default: cliFlagsDefaults.formatPackageJson,
141
- },
142
- noPack: {
143
- type: Boolean,
144
- description: 'Do not pack',
145
- default: false,
146
- },
147
- noExports: {
148
- type: Boolean,
149
- description: 'Do not add exports field to package.json',
150
- default: false,
151
- },
152
- noClean: {
153
- type: Boolean,
154
- description: 'Do not clean the output directory',
155
- default: false,
156
- },
157
- noBundle: {
158
- type: Boolean,
159
- description: 'Do not bundle',
160
- default: false,
161
- },
162
- removeLegalComments: {
163
- type: Boolean,
164
- description: 'Remove legal comments',
165
- default: false,
166
- },
167
- noSubpackages: {
168
- type: Boolean,
169
- description: 'Do not create subpackage directories with package.json files',
170
- default: cliFlagsDefaults.noSubpackages,
171
- },
172
- };
173
- const packageJsonFieldsOrder = new Set([
174
- 'private',
175
- 'type',
176
- 'version',
177
- 'name',
178
- 'scope', // custom
179
- 'description',
180
- 'license',
181
- 'author',
182
- 'contributors',
183
- 'funding',
184
- 'bin',
185
- 'main',
186
- 'browser',
187
- 'unpkg',
188
- 'module',
189
- 'svelte',
190
- 'exports',
191
- 'imports',
192
- 'types',
193
- 'typings',
194
- 'typesVersions', // non standard but required for typescript with resolution other than nodenext
195
- 'files',
196
- 'packageManager',
197
- 'sideEffects',
198
- 'engines',
199
- 'os',
200
- 'cpu',
201
- 'man',
202
- 'directories',
203
- 'repository',
204
- 'bugs',
205
- 'homepage',
206
- 'readme',
207
- 'keywords',
208
- 'scripts',
209
- 'config',
210
- 'dependencies',
211
- 'devDependencies',
212
- 'peerDependencies',
213
- 'peerDependenciesMeta',
214
- 'bundleDependencies',
215
- 'bundledDependencies',
216
- 'optionalDependencies',
217
- 'overrides',
218
- 'publishConfig',
219
- 'workspaces',
220
- ]);
221
- function processPackageJson(pkg, needTreatment, treatKey) {
222
- const newPkg = {};
223
- for (const key of packageJsonFieldsOrder) {
224
- if (needTreatment(key)) {
225
- newPkg[key] = treatKey(key);
226
- }
227
- }
228
- for (const key in pkg) {
229
- if (!packageJsonFieldsOrder.has(key)) {
230
- newPkg[key] = pkg[key];
231
- }
232
- }
233
- return newPkg;
234
- }
235
- function toFormattedJson(json) {
236
- return `${JSON.stringify(json, null, 2)}\n`;
237
- }
238
-
239
- function FlattenParam(value) {
240
- if (typeof value === 'boolean') {
241
- return value; // false
242
- }
243
- if (value === '') {
244
- return true; // means auto
245
- }
246
- return value; // string
247
- }
248
- function getCliOptions(plugins, pkg) {
249
- const cliOptions = cli({
250
- name: 'pkgbld',
251
- version: pkg.version ?? '<unknown>',
252
- flags: cliFlags,
253
- commands: [
254
- command({
255
- name: 'prune',
256
- description: 'prune devDependencies and redundant scripts from package.json',
257
- flags: {
258
- profile: {
259
- type: String,
260
- description: 'profile to use',
261
- default: 'library'
262
- },
263
- flatten: {
264
- type: FlattenParam,
265
- description: 'flatten package files',
266
- default: false
267
- },
268
- removeSourcemaps: {
269
- type: Boolean,
270
- description: 'remove sourcemaps',
271
- default: false
272
- },
273
- optimizeFiles: {
274
- type: Boolean,
275
- description: 'optimize files array',
276
- default: true
277
- }
278
- }
279
- })
280
- ]
281
- });
282
- if (cliOptions.command === 'prune') {
283
- return {
284
- kind: 'prune',
285
- profile: cliOptions.flags.profile,
286
- flatten: cliOptions.flags.flatten,
287
- removeSourcemaps: cliOptions.flags.removeSourcemaps,
288
- optimizeFiles: cliOptions.flags.optimizeFiles
289
- };
290
- }
291
- const flags = cliOptions.flags;
292
- const options = {
293
- kind: 'build',
294
- umdInputs: flags.umd,
295
- compressFormats: flags.compress,
296
- sourcemapFormats: flags.sourcemaps,
297
- formats: flags.formats,
298
- formatsOverridden: flags.formats !== cliFlagsDefaults.formats,
299
- preprocess: flags.preprocess,
300
- dir: flags.dest,
301
- sourceDir: flags.src,
302
- bin: flags.bin,
303
- includeExternals: flags.includeExternals,
304
- eject: flags.eject,
305
- noTsConfig: flags.noTsConfig,
306
- noUpdatePackageJson: flags.noUpdatePackageJson,
307
- commonjsPattern: flags.commonjsPattern,
308
- esPattern: flags.esmPattern,
309
- umdPattern: flags.umdPattern,
310
- formatPackageJson: flags.formatPackageJson,
311
- noPack: flags.noPack,
312
- noExports: flags.noExports,
313
- noClean: flags.noClean,
314
- noBundle: flags.noBundle,
315
- removeLegalComments: flags.removeLegalComments,
316
- noSubpackages: flags.noSubpackages
317
- };
318
- for (const plugin of plugins) {
319
- plugin.options?.(flags, options);
320
- }
321
- return options;
322
- }
323
-
324
- async function getJson(fileName) {
325
- const pkgPath = path.resolve(fileName);
326
- const buffer = await fs.readFile(pkgPath);
327
- return [pkgPath, JSON.parse(buffer.toString())];
328
- }
329
-
330
- const Priority = {
331
- preprocess: 1000,
332
- cleanup: 1000,
333
- externals: 2000,
334
- resolve: 3000,
335
- commonjs: 4000,
336
- transpile: 6000,
337
- compress: 10000,
338
- finalize: 20000
339
- };
340
-
341
- async function clean (provider, config) {
342
- if (config.noClean) {
343
- return;
344
- }
345
- const pluginClean = await provider.import('@rollup-extras/plugin-clean');
346
- const pluginInstance = pluginClean();
347
- provider.provide(pluginFactory, Priority.cleanup, { outputPlugin: true });
348
- let firstPluginInstance = true;
349
- function pluginFactory() {
350
- const result = firstPluginInstance ? pluginInstance : pluginInstance.api.addInstance();
351
- firstPluginInstance = false;
352
- return result;
353
- }
354
- }
355
-
356
- async function commonjs (provider) {
357
- const pluginCommonjs = await provider.import('@rollup/plugin-commonjs');
358
- provider.provide(() => pluginCommonjs(), Priority.commonjs);
359
- }
360
-
361
- async function externals (provider, config, inputs, inputsExt) {
362
- if (config.includeExternals === true) {
363
- return;
364
- }
365
- const pluginExternals = await provider.import('@rollup-extras/plugin-externals');
366
- const allowGenericUmd = config.umdInputs.length === 1 && inputs.length === 1;
367
- if (config.formats.length > 0) {
368
- const format = (allowGenericUmd ? undefined : config.formats.filter(format => format !== 'umd'));
369
- provider.provide(() => pluginExternals(config.includeExternals === false
370
- ? {}
371
- : (id, external, importer) => includeExternals(importer, external, id, config)), Priority.externals, { format });
372
- // for eject config
373
- provider.globalImport('path', 'path');
374
- provider.globalSetup(includeExternals);
375
- }
376
- if (!allowGenericUmd && config.umdInputs.length > 0) {
377
- const curry = (await provider.import('lodash/curry.js'));
378
- for (const currentInput of config.umdInputs) {
379
- const isExternal = curry((currentInput, id, external, importer) => includeExternals(importer, external, id, config) || isExternalInput(currentInput, inputs, inputsExt, id, config))(currentInput);
380
- provider.provide(() => pluginExternals(isExternal), Priority.externals, { format: 'umd', inputs: [`./${config.sourceDir}/${currentInput}.${inputsExt.get(currentInput)}`] });
381
- }
382
- // for eject config
383
- if (config.formats.length === 0) {
384
- provider.globalImport('path', 'path');
385
- provider.globalSetup(includeExternals);
386
- }
387
- provider.globalSetup(isExternalInput);
388
- }
389
- }
390
- function includeExternals(importer, external, id, config) {
391
- if (config.includeExternals === false)
392
- return external;
393
- if (!external)
394
- return false;
395
- const internals = config.includeExternals;
396
- if (internals.includes(id) || internals.some(internal => id.includes(internal))) {
397
- return false;
398
- }
399
- return true;
400
- }
401
- function isExternalInput(currentInput, inputs, inputsExt, id, config) {
402
- const normalizedPath = path.isAbsolute(currentInput)
403
- ? `./${path.relative(process.cwd(), `${currentInput}.${inputsExt.get(currentInput)}`)}`
404
- : `./${path.join(config.sourceDir, `${currentInput}.${inputsExt.get(currentInput)}`)}`;
405
- const normalizedId = path.isAbsolute(id) ? `./${path.relative(process.cwd(), id)}` : id;
406
- return normalizedPath !== normalizedId && inputs.includes(normalizedPath);
407
- }
408
-
409
- async function preprocess (provider, config, inputs, inputsExt) {
410
- if (config.preprocess.length > 0) {
411
- const pluginPreprocess = await provider.import('rollup-plugin-preprocess');
412
- const include = config.preprocess.map(name => `${config.sourceDir}/${name}.${inputsExt.get(name)}`);
413
- for (const format of config.formats) {
414
- if (format !== 'umd') {
415
- provider.provide(() => pluginPreprocess.default({ include, context: { [format]: true } }), Priority.preprocess, { format });
416
- }
417
- else {
418
- for (const currentInput of config.umdInputs) {
419
- provider.provide(() => pluginPreprocess.default({ include, context: { umd: true } }), Priority.preprocess, { format, inputs: [`./${config.sourceDir}/${currentInput}.${inputsExt.get(currentInput)}`] });
420
- }
421
- }
422
- }
423
- }
424
- }
425
-
426
- async function resolve (provider) {
427
- const pluginResolve = await provider.import('@rollup/plugin-node-resolve');
428
- provider.provide(() => pluginResolve(), Priority.resolve);
429
- }
430
-
431
- async function terser (provider, config, inputs, inputsExt) {
432
- const filteredFormats = config.compressFormats.filter(format => config.formats.includes(format));
433
- if (filteredFormats.length > 0) {
434
- const pluginTerser = await provider.import('@rollup/plugin-terser');
435
- const options = {
436
- mangle: {
437
- properties: {
438
- regex: /_$/
439
- }
440
- }
441
- };
442
- if (config.removeLegalComments) {
443
- options.output = {
444
- comments: false,
445
- };
446
- }
447
- if (filteredFormats.length > 0) {
448
- for (const format of filteredFormats) {
449
- if (format !== 'umd') {
450
- provider.provide(() => pluginTerser(options), Priority.compress, { format, outputPlugin: true });
451
- }
452
- else {
453
- for (const currentInput of config.umdInputs) {
454
- provider.provide(() => pluginTerser(options), Priority.compress, { format, outputPlugin: true, inputs: [`./${config.sourceDir}/${currentInput}.${inputsExt.get(currentInput)}`] });
455
- }
456
- }
457
- }
458
- }
459
- }
460
- }
461
-
462
- async function typescript (provider, config, inputs) {
463
- const typescriptInputs = inputs.filter(input => input.endsWith('.ts') || input.endsWith('.tsx'));
464
- if (typescriptInputs.length > 0) {
465
- const pluginTypescript = await provider.import('rollup-plugin-typescript2');
466
- provider.provide(() => pluginTypescript(), Priority.transpile, typescriptInputs.length === inputs.length ? undefined : { inputs: typescriptInputs });
467
- }
468
- }
469
-
470
- async function binify (provider, config) {
471
- if (config.bin != null && config.bin.length > 0) {
472
- const pluginBinify = await provider.import('@rollup-extras/plugin-binify');
473
- provider.provide(() => pluginBinify({
474
- filter: (item) => item.type === 'chunk' && item.isEntry && config.bin.some(input => input === `./${config.dir}/${item.fileName}`)
475
- }), Priority.finalize, { outputPlugin: true, format: 'cjs' });
476
- }
477
- }
478
-
479
- async function json (provider) {
480
- const pluginJson = await provider.import('@rollup/plugin-json');
481
- provider.provide(() => pluginJson(), Priority.preprocess);
482
- }
483
-
484
- const plugins = [
485
- clean,
486
- commonjs,
487
- externals,
488
- preprocess,
489
- resolve,
490
- terser,
491
- typescript,
492
- binify,
493
- json
494
- ];
495
- const noop = () => undefined;
496
- function createProvider(preimportMap) {
497
- const plugins = [];
498
- return [{
499
- provide: (plugin, priority, options) => {
500
- plugins.push({ priority, plugin, format: options?.format, inputs: options?.inputs, outputPlugin: options?.outputPlugin });
501
- },
502
- import: async (name, exportName) => {
503
- const result = preimportMap.has(name) ? await preimportMap.get(name) : await import(name);
504
- return result[exportName ?? 'default'];
505
- },
506
- globalImport: noop,
507
- globalSetup: noop
508
- }, plugins];
509
- }
510
-
511
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
512
- function getHelpers(pkgName) {
513
- function getGlobalName(anInput) {
514
- return camelCase(path.join(pkgName, path.basename(anInput, path.extname(anInput)) !== 'index' ? path.basename(anInput, path.extname(anInput)) : ''));
515
- }
516
- function getExternalGlobalName(id) {
517
- if (path.isAbsolute(id)) {
518
- return getGlobalName(path.relative(__dirname, id));
519
- }
520
- return camelCase(id);
521
- }
522
- return {
523
- getGlobalName,
524
- getExternalGlobalName
525
- };
526
- }
527
- function toArray(object) {
528
- if (Array.isArray(object)) {
529
- return object;
530
- }
531
- if (object == null) {
532
- return [];
533
- }
534
- return [object];
535
- }
536
- function formatInput(input) {
537
- return (Array.isArray(input) ? input : [input ?? '']).map(item => kleur.magenta(path.basename(item, path.extname(item)))).join(', ');
538
- }
539
- function formatOutput(output, field) {
540
- //? can we avoid it
541
- if (output == null) {
542
- return '';
543
- }
544
- return (Array.isArray(output) ? output : [output ?? '']).map(item => kleur.cyan(item[field])).join(', ');
545
- }
546
- function getTimeDiff(starting) {
547
- const diff = Date.now() - starting;
548
- return diff >= 1000 ? `${(diff / 1000).toFixed(1)}s` : `${diff}ms`;
549
- }
550
- const areSetsEqual = (a, b) => a.size === b.size ? [...a].every(value => b.has(value)) : false;
551
- function formatPackageJson(pkg) {
552
- return processPackageJson(pkg, key => key in pkg, key => pkg[key]);
553
- }
554
- async function isExists(file) {
555
- try {
556
- await access(file);
557
- }
558
- catch (e) {
559
- if (typeof e === 'object' && e != null && 'code' in e && e.code === 'ENOENT') {
560
- return false;
561
- }
562
- throw e;
563
- }
564
- return file;
565
- }
566
- // it is borrowed from vite logic, basically the same but simplified
567
- // without recursion and fully async
568
- async function isReadable(file) {
569
- try {
570
- await stat(file);
571
- }
572
- catch {
573
- return false;
574
- }
575
- try {
576
- await access(file, constants.R_OK);
577
- return true;
578
- }
579
- catch {
580
- return false;
581
- }
582
- }
583
- function hasFile(root, file) {
584
- const path = join(root, file);
585
- return isExists(path);
586
- }
587
- async function hasWorkspacePackageJson(root) {
588
- const path = join(root, 'package.json');
589
- if (!await isReadable(path)) {
590
- return false;
591
- }
592
- try {
593
- const content = (JSON.parse(await readFile(path, 'utf-8')) || {});
594
- return !!content.workspaces;
595
- }
596
- catch {
597
- return false;
598
- }
599
- }
600
- async function searchForPackageRoot(current) {
601
- const root = current;
602
- let dir = current;
603
- while (dir) {
604
- if (await hasFile(dir, 'package.json'))
605
- return dir;
606
- const parentDir = dirname(dir);
607
- if (parentDir === dir)
608
- break; // Reached the filesystem root
609
- dir = parentDir;
610
- }
611
- return root;
612
- }
613
- async function searchForWorkspaceRoot(current) {
614
- const root = await searchForPackageRoot(current);
615
- let dir = current;
616
- while (dir) {
617
- if (await hasFile(dir, 'pnpm-workspace.yaml'))
618
- return dir;
619
- if (await hasWorkspacePackageJson(dir))
620
- return dir;
621
- const parentDir = dirname(dir);
622
- if (parentDir === dir)
623
- break; // Reached the filesystem root
624
- dir = parentDir;
625
- }
626
- return root;
627
- }
628
-
629
- async function getRollupConfigs([provider, plugins$1], inputs, inputsExt, config, helpers, externalPlugins) {
630
- const factoryInProgress = [];
631
- const fileNamePatterns = {
632
- 'es': config.esPattern,
633
- 'cjs': config.commonjsPattern,
634
- 'umd': config.umdPattern
635
- };
636
- for (const factory of plugins) {
637
- factoryInProgress.push(factory(provider, config, inputs, inputsExt));
638
- }
639
- for (const ePlugin of externalPlugins) {
640
- if (ePlugin.providePlugins) {
641
- factoryInProgress.push(ePlugin.providePlugins(provider, config, inputs, inputsExt));
642
- }
643
- }
644
- await Promise.all(factoryInProgress);
645
- const expandInputs = new Set;
646
- for (const plugin of plugins$1) {
647
- if (plugin.format && plugin.inputs?.length && !plugin.outputPlugin) {
648
- for (const format of toArray(plugin.format)) {
649
- expandInputs.add(format);
650
- }
651
- }
652
- }
653
- const refineNext = refiner();
654
- refineNext(doExpandInputs(toArray(config.formats)));
655
- for (const plugin of plugins$1) {
656
- if (plugin.format && !plugin.outputPlugin) {
657
- const formats = toArray(plugin.format);
658
- if (!plugin.inputs || plugin.inputs.length === 0) {
659
- refineNext(doExpandInputs(formats));
660
- }
661
- else if (inputs.length === 1) {
662
- refineNext(formats);
663
- }
664
- else {
665
- const expanded = [];
666
- for (const format of formats) {
667
- for (const input of plugin.inputs) {
668
- expanded.push(`${format}.${input}`);
669
- }
670
- }
671
- refineNext(expanded);
672
- }
673
- }
674
- }
675
- const refined = refineNext();
676
- const partitions = [];
677
- for (const partition of refined) {
678
- const result = [];
679
- for (const format of partition) {
680
- if (format.includes('.')) {
681
- const [, realFormat, input] = format.split(/(.*?)\.(.*)/gm);
682
- result.push({ format: realFormat, input });
683
- }
684
- else {
685
- result.push({ format });
686
- }
687
- }
688
- const mapFormatInputs = new Map;
689
- const formatsWithoutInputs = new Set;
690
- for (const { format, input } of result) {
691
- if (input) {
692
- if (mapFormatInputs.has(format)) {
693
- // biome-ignore lint/style/noNonNullAssertion: <explanation>
694
- mapFormatInputs.get(format).add(input);
695
- }
696
- else {
697
- mapFormatInputs.set(format, new Set([input]));
698
- }
699
- }
700
- else {
701
- formatsWithoutInputs.add(format);
702
- }
703
- }
704
- for (const format of formatsWithoutInputs) {
705
- if (mapFormatInputs.has(format)) {
706
- throw new Error(`${format} is both used with inputs and without in plugins configuration and was not expanded / handled correctly. Please file an issue for pkgbld.`);
707
- }
708
- mapFormatInputs.set(format, new Set(inputs));
709
- }
710
- let prevInputs;
711
- for (const inputs of mapFormatInputs.values()) {
712
- if (prevInputs) {
713
- if (!areSetsEqual(inputs, prevInputs)) {
714
- throw new Error(`unbalanced inputs for partition: ${JSON.stringify(partition)}`);
715
- }
716
- }
717
- prevInputs = inputs;
718
- }
719
- partitions.push({ formats: [...mapFormatInputs.keys()], inputs: [...prevInputs] });
720
- }
721
- return partitions.map(({ formats, inputs }) => {
722
- return {
723
- input: inputs,
724
- output: formats.map(format => ({
725
- format,
726
- dir: config.dir,
727
- entryFileNames: fileNamePatterns[format],
728
- plugins: getPlugins([format], inputs, true),
729
- sourcemap: config.sourcemapFormats.includes(format),
730
- // this requires more work
731
- // preserveModules: true,
732
- // preserveModulesRoot: config.sourceDir,
733
- ...getExtraOutputSettings(format, inputs)
734
- })),
735
- plugins: getPlugins(formats, inputs, false)
736
- };
737
- });
738
- function getExtraOutputSettings(format, inputs) {
739
- let result = {};
740
- switch (format) {
741
- case 'cjs':
742
- case 'es':
743
- result = { chunkFileNames: fileNamePatterns[format] };
744
- break;
745
- case 'umd':
746
- if (inputs.length <= 0) {
747
- break;
748
- }
749
- if (inputs.length > 1) {
750
- throw new Error(`Cannot produce global name for multiple umd inputs in one output: ${inputs}`);
751
- }
752
- result = {
753
- name: helpers.getGlobalName(inputs.join('_')),
754
- globals: helpers.getExternalGlobalName,
755
- };
756
- break;
757
- }
758
- for (const ePlugin of externalPlugins) {
759
- if (ePlugin.getExtraOutputSettings) {
760
- Object.assign(result, ePlugin.getExtraOutputSettings(format, inputs));
761
- }
762
- }
763
- return result;
764
- }
765
- function getPlugins(formats, inputs, outputPlugin) {
766
- const filteredPlugins = [];
767
- for (const plugin of plugins$1) {
768
- if ((!!plugin.outputPlugin) === outputPlugin) {
769
- if ((!plugin.format || toArray(plugin.format).some(format => formats.includes(format)))
770
- && (!plugin.inputs || plugin.inputs.every(input => inputs.includes(input)))) {
771
- filteredPlugins.push({
772
- instance: plugin.plugin(),
773
- priority: plugin.priority
774
- });
775
- }
776
- }
777
- }
778
- filteredPlugins.sort((a, b) => a.priority - b.priority);
779
- return filteredPlugins.map(plugin => plugin.instance);
780
- }
781
- function doExpandInputs(formats) {
782
- if (inputs.length === 1) {
783
- return formats;
784
- }
785
- const expanded = [];
786
- for (const format of formats) {
787
- if (expandInputs.has(format)) {
788
- if (format !== 'umd') {
789
- for (const input of inputs) {
790
- expanded.push(`${format}.${input}`);
791
- }
792
- }
793
- else {
794
- for (const input of config.umdInputs) {
795
- expanded.push(`${format}../${config.sourceDir}/${input}.${inputsExt.get(input)}`);
796
- }
797
- }
798
- }
799
- else {
800
- expanded.push(format);
801
- }
802
- }
803
- return expanded;
804
- }
805
- }
806
-
807
- const mainLoggerText = (sourceDir, dir, configsCount, startingTime, finishedCount = 0) => (final = false) => `${sourceDir} → ${dir} ${final ? configsCount : finishedCount++} / ${configsCount}${final ? (` in ${getTimeDiff(startingTime)}`) : ''}`;
808
-
809
- const emptySet = new Set;
810
- const sourceFileSuffixes = ['ts', 'tsx', 'js', 'jsx', 'cjs', 'mjs']; // svelte, vue, etc. are not supported yet
811
- async function processPackage(pkg, config, plugins, tsConfig) {
812
- const typingsFilePattern = '[name].d.ts';
813
- const indexId = 'index';
814
- const typesVersionsLastFields = new Set(['*']);
815
- // check if declarations enabled
816
- const isDeclarations = typeof tsConfig === 'object'
817
- && tsConfig != null && 'compilerOptions' in tsConfig
818
- && typeof tsConfig.compilerOptions === 'object' && tsConfig.compilerOptions !== null
819
- && 'declaration' in tsConfig.compilerOptions && tsConfig.compilerOptions.declaration === true;
820
- const inputs = [];
821
- const inputsExt = new Map;
822
- const logger = createLogger();
823
- const allowEsm = (config.formatsOverridden && config.formats.includes('es') || !config.formatsOverridden);
824
- const allowCjs = (config.formatsOverridden && config.formats.includes('cjs') || !config.formatsOverridden);
825
- const allowUmd = (config.formatsOverridden && config.formats.includes('umd') || !config.formatsOverridden || config.umdInputs);
826
- if (typeof pkg !== 'object' || Array.isArray(pkg) || pkg == null) {
827
- logger.finish('expecting object on top level of package.json', 3 /* LogLevel.error */);
828
- process.exit(-1);
829
- }
830
- if (typeof pkg.name !== 'string' && config.umdInputs.length > 0) {
831
- logger.finish('expecting name to be a string in package.json', 3 /* LogLevel.error */);
832
- process.exit(-1);
833
- }
834
- if (!Array.isArray(pkg.files)) {
835
- pkg.files = [];
836
- }
837
- if (!pkg.files.includes(config.dir)) {
838
- pkg.files.push(config.dir);
839
- }
840
- if (typeof pkg.scripts !== 'object' && pkg.scripts !== null) {
841
- pkg.scripts = {};
842
- }
843
- if (!config.noPack && !('prepack' in pkg.scripts)) {
844
- const binary = typeof pkg.scripts.build === 'string' && pkg.scripts.build?.startsWith('pkgbld-internal') ? 'pkgbld-internal' : 'pkgbld';
845
- pkg.scripts.prepack = `${binary} prune`;
846
- }
847
- if (allowEsm && !allowCjs && typeof pkg.type !== 'string') {
848
- pkg.type = 'module';
849
- }
850
- const exportsFields = new Set([
851
- 'types',
852
- 'svelte',
853
- pkg.type === 'module' ? 'require' : 'import',
854
- pkg.type === 'module' ? 'import' : 'require',
855
- 'default'
856
- ]);
857
- if (typeof pkg.typings === 'string') {
858
- pkg.typings = undefined;
859
- }
860
- if (isDeclarations) {
861
- pkg.types = `./${config.dir}/${patternToName(typingsFilePattern, 'index')}`;
862
- }
863
- if (allowUmd && typeof pkg.umd === 'string') {
864
- pkg.umd = `./${config.dir}/${patternToName(config.umdPattern, indexId)}`;
865
- if (!config.umdInputs.includes(indexId)) {
866
- config.umdInputs.push(indexId);
867
- }
868
- }
869
- if (allowCjs) {
870
- pkg.main = `./${config.dir}/${patternToName(config.commonjsPattern, indexId)}`;
871
- }
872
- if (allowEsm && !allowCjs) {
873
- pkg.main = `./${config.dir}/${patternToName(config.esPattern, indexId)}`;
874
- }
875
- if (allowCjs && allowEsm && typeof pkg.module !== 'string') {
876
- pkg.module = `./${config.dir}/${patternToName(config.esPattern, indexId)}`;
877
- }
878
- if (allowUmd && config.umdInputs.includes(indexId)) {
879
- pkg.unpkg = `./${config.dir}/${patternToName(config.umdPattern, indexId)}`;
880
- }
881
- if (isDeclarations) {
882
- if (typeof pkg.typesVersions !== 'object' && pkg.typesVersions !== null) {
883
- pkg.typesVersions = {};
884
- }
885
- if (typeof pkg.typesVersions['*'] !== 'object' && pkg.typesVersions['*'] !== null) {
886
- pkg.typesVersions['*'] = {};
887
- }
888
- }
889
- if (!config.noExports) {
890
- if (typeof pkg.exports !== 'object' && pkg.exports !== null) {
891
- pkg.exports = {};
892
- }
893
- if (pkg.exports['.'] == null) {
894
- pkg.exports['.'] = {};
895
- }
896
- pkg.exports['./package.json'] = './package.json';
897
- if (allowCjs && pkg.main !== pkg.exports['.'].require) {
898
- pkg.exports['.'].require = pkg.main;
899
- }
900
- if (pkg.module !== pkg.exports['.']?.default) {
901
- pkg.exports['.'].default = pkg.module;
902
- }
903
- for (const id in pkg.exports) {
904
- if (id === './package.json')
905
- continue;
906
- const basename = id === '.' ? indexId : path.join(path.dirname(id), path.basename(id));
907
- if (typeof pkg.exports[id] !== 'object') {
908
- pkg.exports[id] = {};
909
- }
910
- if (isDeclarations) {
911
- pkg.typesVersions['*'][id] = [`${config.dir}/${patternToName(typingsFilePattern, basename)}`];
912
- pkg.exports[id].types = `./${config.dir}/${patternToName(typingsFilePattern, basename)}`;
913
- }
914
- const cjsFieldName = pkg.type === 'module' ? 'require' : 'default';
915
- const esmFieldName = pkg.type === 'module' ? 'default' : 'import';
916
- if (allowEsm) {
917
- pkg.exports[id][esmFieldName] = `./${config.dir}/${patternToName(config.esPattern, basename)}`;
918
- }
919
- if (allowCjs) {
920
- pkg.exports[id][cjsFieldName] = `./${config.dir}/${patternToName(config.commonjsPattern, basename)}`;
921
- }
922
- pkg.exports[id] = orderFields(exportsFields, pkg.exports[id]);
923
- if (basename !== indexId && !config.noSubpackages) {
924
- if (!pkg.files.includes(basename)) {
925
- pkg.files.push(basename);
926
- }
927
- }
928
- await updateExtensions(basename);
929
- }
930
- }
931
- else {
932
- await updateExtensions(indexId);
933
- }
934
- if (isDeclarations) {
935
- pkg.typesVersions['*']['*'] = [
936
- `${config.dir}/${patternToName(typingsFilePattern, indexId)}`,
937
- `${config.dir}/*`
938
- ];
939
- pkg.typesVersions['*'] = orderFields(emptySet, pkg.typesVersions['*'], typesVersionsLastFields);
940
- }
941
- if (allowUmd && config.umdInputs.length > 0 && !config.formats.includes('umd')) {
942
- config.formats.push('umd');
943
- }
944
- for (const plugin of plugins) {
945
- plugin.processPackageJson?.(pkg, inputs);
946
- }
947
- if (config.bin) {
948
- if (config.bin.length > 0) {
949
- if (config.bin[0] !== '') {
950
- pkg.bin = config.bin[0];
951
- }
952
- config.bin = config.bin.filter(Boolean);
953
- if (config.bin.length === 0) {
954
- config.bin = undefined;
955
- }
956
- }
957
- }
958
- else if (allowCjs && inputs.length > 0) {
959
- if (typeof pkg.bin === 'string') {
960
- if (inputs.some(input => pkg.bin === `./${config.dir}/${patternToName(config.commonjsPattern, path.basename(input, path.extname(input)))}`)) {
961
- config.bin = [pkg.bin];
962
- }
963
- }
964
- else if (typeof pkg.bin === 'object' && pkg.bin !== null) {
965
- const executables = Object.values(pkg.bin).filter(value => typeof value === 'string' && inputs.some(input => value === `./${config.dir}/${patternToName(config.commonjsPattern, path.basename(input, path.extname(input)))}`));
966
- if (executables.length > 0) {
967
- config.bin = executables;
968
- }
969
- }
970
- if (typeof pkg.directories === 'object' && pkg.directories != null && 'bin' in pkg.directories && typeof pkg.directories.bin === 'string') {
971
- if (path.resolve(pkg.directories.bin) === path.resolve(config.dir)) {
972
- config.bin?.push(...inputs.map(input => `./${config.dir}/${patternToName(config.commonjsPattern, input)}`));
973
- config.bin = Array.from(new Set(config.bin));
974
- }
975
- }
976
- }
977
- return [inputs, inputsExt];
978
- async function updateExtensions(id) {
979
- const sourceFileWithoutSuffix = `./${config.sourceDir}/${id}.`;
980
- for (const suffix of sourceFileSuffixes) {
981
- const file = sourceFileWithoutSuffix + suffix;
982
- if (await isExists(file)) {
983
- inputs.push(file);
984
- inputsExt.set(id, suffix);
985
- break;
986
- }
987
- }
988
- }
989
- }
990
- function patternToName(pattern, input) {
991
- return pattern.replace('[name]', input);
992
- }
993
- function orderFields(firstFields, exports, lastFields = emptySet) {
994
- const ordered = {};
995
- for (const key of firstFields) {
996
- if (key in exports) {
997
- ordered[key] = exports[key];
998
- }
999
- }
1000
- for (const key in exports) {
1001
- if (!firstFields.has(key) && !lastFields.has(key)) {
1002
- ordered[key] = exports[key];
1003
- }
1004
- }
1005
- for (const key of lastFields) {
1006
- if (key in exports) {
1007
- ordered[key] = exports[key];
1008
- }
1009
- }
1010
- return ordered;
1011
- }
1012
-
1013
- async function writeJson(path, json) {
1014
- await fs.writeFile(path, toFormattedJson(json));
1015
- }
1016
-
1017
- var dependencies = {
1018
- "@niceties/logger": "^1.1.13",
1019
- "@niceties/draftlog-appender": "^1.3.3",
1020
- lodash: "^4.17.21",
1021
- rollup: "^4.34.7",
1022
- "rollup-plugin-typescript2": "^0.36.0",
1023
- "rollup-plugin-preprocess": "^0.0.4",
1024
- "@rollup/plugin-commonjs": "^28.0.2",
1025
- "@rollup/plugin-terser": "^0.4.4",
1026
- "@rollup/plugin-json": "^6.1.0",
1027
- "@rollup/plugin-node-resolve": "^16.0.0",
1028
- "@rollup-extras/plugin-clean": "^1.3.9",
1029
- "@rollup-extras/plugin-binify": "^1.1.10",
1030
- "@rollup-extras/plugin-externals": "^1.2.2",
1031
- "@slimlib/refine-partition": "^1.0.3",
1032
- "@slimlib/smart-mock": "^0.1.6",
1033
- "is-builtin-module": "^3.2.1",
1034
- terser: "^5.39.0",
1035
- kleur: "^4.1.5",
1036
- cleye: "^1.3.4",
1037
- jsonata: "^2.0.6"
1038
- };
1039
- var pkgbldPkg = {
1040
- dependencies: dependencies};
1041
-
1042
- const imports = new Map;
1043
- const setup = new Set;
1044
- let generate, generateGlobals;
1045
- async function createEjectProvider(preimportMap) {
1046
- const createMockProvider = (await import('@slimlib/smart-mock')).default;
1047
- const provider = createMockProvider();
1048
- const createMock = provider.createMock;
1049
- generate = provider.generate;
1050
- generateGlobals = provider.generateGlobals;
1051
- const plugins = [];
1052
- return [{
1053
- provide: (plugin, priority, options) => {
1054
- plugins.push({ priority, plugin, format: options?.format, inputs: options?.inputs, outputPlugin: options?.outputPlugin });
1055
- },
1056
- import: async (name, exportName) => {
1057
- const result = preimportMap.has(name) ? await preimportMap.get(name) : await import(name);
1058
- const exports = result[exportName ?? 'default'];
1059
- const mangledName = camelCase(name);
1060
- imports.set(name, mangledName);
1061
- return createMock(exports, mangledName);
1062
- },
1063
- globalImport: (module, exportName) => {
1064
- imports.set(module, exportName ?? 'default');
1065
- },
1066
- // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
1067
- globalSetup: (code) => {
1068
- if (typeof code === 'function') {
1069
- setup.add(code.toString());
1070
- }
1071
- setup.add(String(code));
1072
- }
1073
- }, plugins];
1074
- }
1075
- async function ejectConfig(config, pkgPath, options, inputs, inputsExt, helpers, pkg) {
1076
- const pkgName = pkg.name;
1077
- // generate from config
1078
- const text = generate(config);
1079
- setup.add(generateGlobals());
1080
- // generate globals for config functions
1081
- setup.add(`const config = ${generate(options)}`);
1082
- setup.add(`const inputs = ${generate(inputs)}`);
1083
- setup.add(`const inputsExt = new Map(${generate(Array.from(inputsExt))})`);
1084
- // generate helpers code
1085
- if (options.formats.includes('umd')) {
1086
- imports.set('path', 'path');
1087
- imports.set('lodash/camelCase.js', 'camelCase');
1088
- imports.set('url', 'url'); // for __dirname polyfill
1089
- setup.add(`const pkgName = ${generate(pkgName)}`);
1090
- setup.add(helpers.getGlobalName.toString());
1091
- // polyfill __dirname
1092
- setup.add('const __dirname = url.fileURLToPath(new URL(\'.\', import.meta.url));');
1093
- }
1094
- // imports
1095
- const importsString = Array.from(imports)
1096
- .map((value) => `import ${value[1]} from '${value[0]}';`)
1097
- .join('\n');
1098
- const setupString = Array.from(setup)
1099
- .join('\n');
1100
- const { minify } = await import('terser');
1101
- const result = await minify(`${importsString}\n${setupString}\nexport default ${text};`, {
1102
- module: true,
1103
- compress: {
1104
- booleans: false,
1105
- ecma: 2020,
1106
- module: true,
1107
- passes: 3,
1108
- unsafe: true
1109
- },
1110
- mangle: false,
1111
- output: {
1112
- beautify: true,
1113
- ecma: 2020,
1114
- quote_style: 1
1115
- }
1116
- });
1117
- await fs.writeFile(path.join(path.dirname(pkgPath), 'rollup.config.mjs'), result.code);
1118
- await updatePackageJson(pkg);
1119
- }
1120
- async function updatePackageJson(pkg) {
1121
- if (typeof pkg.devDependencies !== 'object') {
1122
- pkg.devDependencies = {};
1123
- }
1124
- const devDependencies = pkg.devDependencies;
1125
- if ('pkgbld' in devDependencies) {
1126
- devDependencies.pkgbld = undefined;
1127
- }
1128
- devDependencies.rollup = pkgbldPkg.dependencies.rollup;
1129
- const isBuiltin = (await import('is-builtin-module')).default;
1130
- for (const key of imports.keys()) {
1131
- const packageName = getPackageName(key);
1132
- if (!isBuiltin(packageName)) {
1133
- devDependencies[packageName] = pkgbldPkg.dependencies[packageName] ?? '*';
1134
- }
1135
- }
1136
- }
1137
- function getPackageName(key) {
1138
- return key.split('/').slice(0, key.startsWith('@') ? 2 : 1).join('/');
1139
- }
1140
-
1141
- const defaultTsConfig = {
1142
- include: ['src', 'types'],
1143
- compilerOptions: {
1144
- lib: ['dom', 'esnext'],
1145
- target: 'esnext',
1146
- module: 'esnext',
1147
- esModuleInterop: true,
1148
- allowJs: true,
1149
- skipLibCheck: true,
1150
- strict: true,
1151
- sourceMap: true,
1152
- noUncheckedIndexedAccess: true,
1153
- declaration: true,
1154
- moduleResolution: 'node'
1155
- }
1156
- };
1157
- async function checkTsConfig(options, mainLogger, plugins) {
1158
- if (options.noTsConfig) {
1159
- return;
1160
- }
1161
- // biome-ignore lint/style/useSingleVarDeclarator: <explanation>
1162
- let config, needWrite = false;
1163
- try {
1164
- [, config] = await getJson('tsconfig.json');
1165
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1166
- }
1167
- catch (_) { /*ignore*/ }
1168
- try {
1169
- [, config] = await getJson('jsconfig.json');
1170
- if (config && typeof config === 'object' && !Array.isArray(config)) {
1171
- config.allowJs = true;
1172
- }
1173
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1174
- }
1175
- catch (_) { /*ignore*/ }
1176
- if (!config) {
1177
- config = defaultTsConfig;
1178
- needWrite = true;
1179
- }
1180
- const originalConfig = cloneDeep(config);
1181
- for (const plugin of plugins) {
1182
- plugin.processTsConfig?.(config);
1183
- }
1184
- if (!isEqual(originalConfig, config)) {
1185
- needWrite = true;
1186
- }
1187
- if (needWrite) {
1188
- mainLogger('no tsconfig.json or jsconfig.json and --no-ts-config not specified, writing tsconfig...');
1189
- await writeJson(path.resolve('tsconfig.json'), config);
1190
- mainLogger('done');
1191
- }
1192
- return config;
1193
- }
1194
-
1195
- async function loadPlugins(pkg, loaded) {
1196
- try {
1197
- return await Promise.all([...new Set([...Object.keys(pkg.devDependencies || {}), ...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})])]
1198
- .filter(packageName => packageName.startsWith('pkgbld-plugin-') && !loaded.has(packageName))
1199
- .map(packageName => {
1200
- loaded.add(packageName);
1201
- return import(packageName).then((pluginFactory) => pluginFactory.create());
1202
- }));
1203
- }
1204
- catch (e) {
1205
- console.error(e);
1206
- return [];
1207
- }
1208
- }
1209
-
1210
- async function prunePkg(pkg, options, logger) {
1211
- const scriptsToKeep = getScriptsData();
1212
- const keys = scriptsToKeep[options.profile];
1213
- if (!keys) {
1214
- throw new Error(`unknown profile ${options.profile}`);
1215
- }
1216
- pkg.devDependencies = undefined;
1217
- pkg.packageManager = undefined;
1218
- if (pkg.scripts) {
1219
- for (const key of Object.keys(pkg.scripts)) {
1220
- if (!keys.has(key)) {
1221
- delete pkg.scripts[key];
1222
- }
1223
- }
1224
- if (Object.keys(pkg.scripts).length === 0) {
1225
- pkg.scripts = undefined;
1226
- }
1227
- }
1228
- if (options.flatten) {
1229
- await flatten(pkg, options.flatten, logger);
1230
- }
1231
- if (options.removeSourcemaps) {
1232
- const sourceMaps = await walkDir('.', ['node_modules']).then(files => files.filter(file => file.endsWith('.map')));
1233
- for (const sourceMap of sourceMaps) {
1234
- // find corresponding file
1235
- const sourceFile = sourceMap.slice(0, -4);
1236
- // load file
1237
- const sourceFileContent = await readFile(sourceFile, 'utf8');
1238
- // find sourceMappingURL
1239
- const sourceMappingUrl = `\n//# sourceMappingURL=${path.basename(sourceMap)}`;
1240
- // remove sourceMappingURL
1241
- const newContent = sourceFileContent.replace(sourceMappingUrl, '');
1242
- // write file
1243
- await writeFile(sourceFile, newContent, 'utf8');
1244
- // remove sourceMap
1245
- await rm(sourceMap);
1246
- }
1247
- }
1248
- if (pkg.files && Array.isArray(pkg.files) && options.optimizeFiles) {
1249
- const filterFiles = ['package.json'];
1250
- const specialFiles = ['README', 'LICENSE', 'LICENCE'];
1251
- if (pkg.main && typeof pkg.main === 'string') {
1252
- filterFiles.push(normalizePath(pkg.main));
1253
- }
1254
- if (pkg.bin) {
1255
- if (typeof pkg.bin === 'string') {
1256
- filterFiles.push(normalizePath(pkg.bin));
1257
- }
1258
- if (typeof pkg.bin === 'object' && pkg.bin !== null) {
1259
- filterFiles.push(...Object.values(pkg.bin).map(normalizePath));
1260
- }
1261
- }
1262
- const depthToFiles = new Map();
1263
- for (const file of pkg.files.concat(filterFiles)) {
1264
- const dirname = path.dirname(file);
1265
- const depth = dirname.split('/').length;
1266
- if (!depthToFiles.has(depth)) {
1267
- depthToFiles.set(depth, [file]);
1268
- }
1269
- else {
1270
- depthToFiles.get(depth)?.push(file);
1271
- }
1272
- }
1273
- // walk depth keys from the highest to the lowest
1274
- const maxDepth = Math.max(...depthToFiles.keys());
1275
- for (let depth = maxDepth; depth > 0; --depth) {
1276
- const files = depthToFiles.get(depth);
1277
- const mapDirToFiles = new Map();
1278
- for (const file of files) {
1279
- const dirname = path.dirname(file);
1280
- const basename = normalizePath(path.basename(file));
1281
- if (!mapDirToFiles.has(dirname)) {
1282
- mapDirToFiles.set(dirname, [basename]);
1283
- }
1284
- else {
1285
- mapDirToFiles.get(dirname)?.push(basename);
1286
- }
1287
- }
1288
- for (const [dirname, filesInDir] of mapDirToFiles) {
1289
- // find out real content of the directory
1290
- const realFiles = await readdir(dirname);
1291
- // check if all files in the directory are in the filesInDir
1292
- const allFilesInDir = realFiles.every(file => filesInDir.includes(file)) || realFiles.length === 0;
1293
- if (allFilesInDir && dirname !== '.') {
1294
- if (!depthToFiles.has(depth - 1)) {
1295
- depthToFiles.set(depth - 1, [dirname]);
1296
- }
1297
- else {
1298
- depthToFiles.get(depth - 1).push(dirname);
1299
- }
1300
- const thisDepth = depthToFiles.get(depth);
1301
- depthToFiles.set(depth, thisDepth.filter(file => filesInDir.every(fileInDir => path.join(dirname, fileInDir) !== file)));
1302
- }
1303
- }
1304
- }
1305
- pkg.files = [...new Set(Array.from(depthToFiles.values()).flat())];
1306
- pkg.files = pkg.files.filter(file => {
1307
- const fileNormalized = normalizePath(file);
1308
- const dirname = path.dirname(fileNormalized);
1309
- const basenameWithoutExtension = path.basename(fileNormalized, path.extname(fileNormalized)).toUpperCase();
1310
- return !filterFiles.includes(fileNormalized) && (dirname !== '' && dirname !== '.' || !specialFiles.includes(basenameWithoutExtension));
1311
- });
1312
- const ignoreDirs = [];
1313
- for (const fileOrDir of pkg.files) {
1314
- if (await isDirectory(fileOrDir)) {
1315
- const allFiles = await walkDir(fileOrDir);
1316
- if (allFiles.every(file => {
1317
- const fileNormalized = normalizePath(file);
1318
- return filterFiles.includes(fileNormalized);
1319
- })) {
1320
- ignoreDirs.push(fileOrDir);
1321
- }
1322
- }
1323
- }
1324
- pkg.files = pkg.files.filter(dir => !ignoreDirs.includes(dir));
1325
- if (pkg.files.length === 0) {
1326
- pkg.files = undefined;
1327
- }
1328
- }
1329
- }
1330
- async function flatten(pkg, flatten, logger) {
1331
- const { default: jsonata } = await import('jsonata');
1332
- // find out where is the dist folder
1333
- const expression = jsonata('[bin, bin.*, main, module, unpkg, umd, types, typings, exports[].*.*, typesVersions.*.*, directories.bin]');
1334
- const allReferences = (await expression.evaluate(pkg));
1335
- let distDir;
1336
- // at this point we requested directories.bin, but it is the only one that is directory and not a file
1337
- // later when we get dirname we can't flatten directories.bin completely
1338
- // it is easy to fix by checking element is a directory but it is kind of good
1339
- // to have it as a separate directory, but user still can flatten it by specifying the directory
1340
- if (flatten === true) {
1341
- let commonSegments;
1342
- for (const entry of allReferences) {
1343
- if (typeof entry !== 'string') {
1344
- continue;
1345
- }
1346
- const dirname = path.dirname(entry);
1347
- const cleanedSegments = dirname.split('/').filter(path => path && path !== '.');
1348
- if (!commonSegments) {
1349
- commonSegments = cleanedSegments;
1350
- }
1351
- else {
1352
- for (let i = 0; i < commonSegments.length; ++i) {
1353
- if (commonSegments[i] !== cleanedSegments[i]) {
1354
- commonSegments.length = i;
1355
- break;
1356
- }
1357
- }
1358
- }
1359
- }
1360
- distDir = commonSegments?.join('/');
1361
- }
1362
- else {
1363
- distDir = normalizePath(flatten);
1364
- }
1365
- if (!distDir) {
1366
- throw new Error('could not find dist folder');
1367
- }
1368
- logger.update(`flattening ${distDir}...`);
1369
- // check if dist can be flattened
1370
- const relativeDistDir = `./${distDir}`;
1371
- const existsPromises = [];
1372
- const filesInDist = await walkDir(relativeDistDir);
1373
- for (const file of filesInDist) {
1374
- // check file is not in root dir
1375
- const relativePath = path.relative(relativeDistDir, file);
1376
- existsPromises.push(isExists(relativePath));
1377
- }
1378
- const exists = await Promise.all(existsPromises);
1379
- const filesAlreadyExist = exists.filter(Boolean);
1380
- if (filesAlreadyExist.length) {
1381
- throw new Error(`dist folder cannot be flattened because files already exist: ${filesAlreadyExist.join(', ')}`);
1382
- }
1383
- if (typeof flatten === 'string' && 'directories' in pkg && pkg.directories != null
1384
- && typeof pkg.directories === 'object' && 'bin' in pkg.directories
1385
- && typeof pkg.directories.bin === 'string' && normalizePath(pkg.directories.bin) === normalizePath(flatten)) {
1386
- // biome-ignore lint/performance/noDelete: <explanation>
1387
- delete pkg.directories.bin;
1388
- if (Object.keys(pkg.directories).length === 0) {
1389
- pkg.directories = undefined;
1390
- }
1391
- const files = await readdir(flatten);
1392
- if (files.length === 1) {
1393
- pkg.bin = files[0];
1394
- }
1395
- else {
1396
- pkg.bin = {};
1397
- for (const file of files) {
1398
- pkg.bin[path.basename(file, path.extname(file))] = file;
1399
- }
1400
- }
1401
- }
1402
- // create new directory structure
1403
- const mkdirPromises = [];
1404
- for (const file of filesInDist) {
1405
- // check file is not in root dir
1406
- const relativePath = path.relative(relativeDistDir, file);
1407
- mkdirPromises.push(mkdir(path.dirname(relativePath), { recursive: true }));
1408
- }
1409
- await Promise.all(mkdirPromises);
1410
- // move files to root dir (rename)
1411
- const renamePromises = [];
1412
- const newFiles = [];
1413
- for (const file of filesInDist) {
1414
- // check file is not in root dir
1415
- const relativePath = path.relative(relativeDistDir, file);
1416
- newFiles.push(relativePath);
1417
- renamePromises.push(rename(file, relativePath));
1418
- }
1419
- await Promise.all(renamePromises);
1420
- let cleanedDir = relativeDistDir;
1421
- while (await isEmptyDir(cleanedDir)) {
1422
- await rm(cleanedDir, { recursive: true, force: true });
1423
- const parentDir = path.dirname(cleanedDir);
1424
- if (parentDir === '.') {
1425
- break;
1426
- }
1427
- cleanedDir = parentDir;
1428
- }
1429
- const normalizedCleanDir = normalizePath(cleanedDir);
1430
- const allReferencesSet = new Set(allReferences);
1431
- // update package.json
1432
- const stringToReplace = `${distDir}/`; // we append / to remove in from the middle of the string
1433
- const pkgClone = cloneAndUpdate(pkg, value => allReferencesSet.has(value) ? value.replace(stringToReplace, '') : value);
1434
- Object.assign(pkg, pkgClone);
1435
- // update files
1436
- let files = pkg.files;
1437
- if (files) {
1438
- files = files.filter(file => {
1439
- const fileNormalized = normalizePath(file);
1440
- return !isSubDirectory(cleanedDir, fileNormalized) && fileNormalized !== normalizedCleanDir;
1441
- });
1442
- files.push(...newFiles);
1443
- pkg.files = [...files];
1444
- }
1445
- // remove extra directories with package.json
1446
- const exports = pkg.exports ? Object.keys(pkg.exports) : [];
1447
- for (const key of exports) {
1448
- if (key === '.') {
1449
- continue;
1450
- }
1451
- const isDir = await isDirectory(key);
1452
- if (isDir) {
1453
- const pkgPath = path.join(key, 'package.json');
1454
- const pkgExists = await isExists(pkgPath);
1455
- // ensure nothing else is in the directory
1456
- const files = await readdir(key);
1457
- if (files.length === 1 && pkgExists) {
1458
- await rm(key, { recursive: true, force: true });
1459
- }
1460
- }
1461
- }
1462
- }
1463
- function normalizePath(file) {
1464
- let fileNormalized = path.normalize(file);
1465
- if (fileNormalized.endsWith('/') || fileNormalized.endsWith('\\')) {
1466
- // remove trailing slash
1467
- fileNormalized = fileNormalized.slice(0, -1);
1468
- }
1469
- return fileNormalized;
1470
- }
1471
- function cloneAndUpdate(pkg, updater) {
1472
- if (typeof pkg === 'string') {
1473
- return updater(pkg);
1474
- }
1475
- if (Array.isArray(pkg)) {
1476
- return pkg.map(value => cloneAndUpdate(value, updater));
1477
- }
1478
- if (typeof pkg === 'object' && pkg !== null) {
1479
- const clone = {};
1480
- for (const key of Object.keys(pkg)) {
1481
- clone[key] = cloneAndUpdate(pkg[key], updater);
1482
- }
1483
- return clone;
1484
- }
1485
- return pkg;
1486
- }
1487
- function isSubDirectory(parent, child) {
1488
- return path.relative(child, parent).startsWith('..');
1489
- }
1490
- async function isEmptyDir(dir) {
1491
- const entries = await readdir(dir, { withFileTypes: true });
1492
- return entries.filter(entry => !entry.isDirectory()).length === 0;
1493
- }
1494
- async function isDirectory(file) {
1495
- const fileStat = await stat(file);
1496
- return fileStat.isDirectory();
1497
- }
1498
- async function walkDir(dir, ignoreDirs = []) {
1499
- const entries = await readdir(dir, { withFileTypes: true });
1500
- const files = [];
1501
- await Promise.all(entries.map(entry => {
1502
- const childPath = path.join(dir, entry.name);
1503
- if (entry.isDirectory() && !ignoreDirs.includes(entry.name)) {
1504
- return walkDir(childPath)
1505
- .then(childFiles => {
1506
- files.push(...childFiles);
1507
- });
1508
- }
1509
- files.push(childPath);
1510
- }).filter(Boolean));
1511
- return files;
1512
- }
1513
- function getScriptsData() {
1514
- const libraryScripts = new Set([
1515
- 'preinstall',
1516
- 'install',
1517
- 'postinstall',
1518
- 'prepublish',
1519
- 'preprepare',
1520
- 'prepare',
1521
- 'postprepare'
1522
- ]);
1523
- const appScripts = new Set([
1524
- ...libraryScripts,
1525
- 'prestart',
1526
- 'start',
1527
- 'poststart',
1528
- 'prerestart',
1529
- 'restart',
1530
- 'postrestart',
1531
- 'prestop',
1532
- 'stop',
1533
- 'poststop',
1534
- 'pretest',
1535
- 'test',
1536
- 'posttest'
1537
- ]);
1538
- return {
1539
- library: libraryScripts,
1540
- app: appScripts
1541
- };
1542
- }
1543
-
1544
- // eslint-disable-next-line @typescript-eslint/triple-slash-reference
1545
- /// <reference path="./rollup-plugin-preprocess.d.ts" />
1546
- execute();
1547
- async function execute() {
1548
- const time = Date.now();
1549
- const mainLogger = createLogger();
1550
- mainLogger.update('preparing..');
1551
- try {
1552
- let pkg;
1553
- let pkgPath;
1554
- // eslint-disable-next-line prefer-const
1555
- [pkgPath, pkg] = await getJson('package.json');
1556
- const loadedPlugins = new Set;
1557
- const plugins = await loadPlugins(pkg, loadedPlugins);
1558
- const [rootPackagePath, rootPkg] = await getJson(join(await searchForWorkspaceRoot(dirname(pkgPath)), 'package.json'));
1559
- if (rootPackagePath !== pkgPath) {
1560
- plugins.push(...await loadPlugins(rootPkg, loadedPlugins));
1561
- }
1562
- mainLogger.update('');
1563
- process.stdout.moveCursor?.(0, -1);
1564
- const options = getCliOptions(plugins, pkg);
1565
- if (options.kind === 'prune') {
1566
- await prunePkg(pkg, options, mainLogger);
1567
- await writeJson(pkgPath, pkg);
1568
- process.exit(0);
1569
- }
1570
- process.stdout.moveCursor?.(0, 1);
1571
- mainLogger.update('preparing...');
1572
- const tsConfig = await checkTsConfig(options, mainLogger, plugins);
1573
- const [inputs, inputsExt] = await processPackage(pkg, options, plugins, tsConfig);
1574
- if (options.formatPackageJson) {
1575
- pkg = formatPackageJson(pkg);
1576
- }
1577
- const helpers = getHelpers(pkg.name);
1578
- const preimportMap = preimport();
1579
- const provider = options.eject ? await createEjectProvider(preimportMap) : createProvider(preimportMap);
1580
- const rollupConfigs = await getRollupConfigs(provider, inputs, inputsExt, options, helpers, plugins);
1581
- if (options.noBundle) {
1582
- rollupConfigs.length = 0;
1583
- }
1584
- if (options.eject) {
1585
- await ejectConfig(rollupConfigs, pkgPath, options, inputs, inputsExt, helpers, pkg);
1586
- mainLogger.finish(`ejected config in ${getTimeDiff(time)}`);
1587
- if (!options.noUpdatePackageJson) {
1588
- await writeJson(pkgPath, pkg);
1589
- }
1590
- }
1591
- else {
1592
- const updater = mainLoggerText(options.sourceDir, options.dir, rollupConfigs.length, time);
1593
- mainLogger.start(updater());
1594
- await Promise.all(rollupConfigs.map(config => buildConfig(config, updater)));
1595
- if (!options.noUpdatePackageJson) {
1596
- await writeJson(pkgPath, pkg);
1597
- }
1598
- if (!options.noSubpackages) {
1599
- await createSubpackages(inputs, options);
1600
- }
1601
- await Promise.all(plugins
1602
- .filter(plugin => plugin.buildEnd)
1603
- .map(plugin => plugin.buildEnd()));
1604
- mainLogger.finish(updater(true));
1605
- }
1606
- }
1607
- catch (e) {
1608
- mainLogger.finish(String(e), 3 /* LogLevel.error */);
1609
- process.exit(-1);
1610
- }
1611
- async function buildConfig(config, updater) {
1612
- const bundle = await rollup(config);
1613
- await Promise.all(toArray(config.output).map(config => bundle.write(config)));
1614
- await bundle.close();
1615
- mainLogger(`${kleur.green('✓')} ${formatInput(config.input)} [${formatOutput(config.output, 'format')}]`);
1616
- mainLogger.update(updater());
1617
- }
1618
- }
1619
- function preimport() {
1620
- return (process.env.PKGBLD_INTERNAL ? new Map([
1621
- ['@rollup-extras/plugin-binify', import('@rollup-extras/plugin-binify')],
1622
- ['@rollup-extras/plugin-clean', import('@rollup-extras/plugin-clean')],
1623
- ['@rollup-extras/plugin-externals', import('@rollup-extras/plugin-externals')]
1624
- ]) : new Map);
1625
- }
1626
- process.on('exit', () => { });