pkgbld 1.36.0 → 2.0.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/README.md +26 -88
- package/index.js +2 -2
- package/package.json +31 -27
- package/src/build-configuration.js +395 -0
- package/src/build-entries.js +214 -0
- package/src/build-plugin-lifecycle.js +100 -0
- package/src/builtin-plugins/binify.js +31 -0
- package/src/builtin-plugins/clean.js +30 -0
- package/src/builtin-plugins/commonjs.js +14 -0
- package/src/builtin-plugins/externals.js +107 -0
- package/src/builtin-plugins/json.js +14 -0
- package/src/builtin-plugins/preprocess.js +37 -0
- package/src/builtin-plugins/resolve.js +14 -0
- package/src/builtin-plugins/terser.js +50 -0
- package/src/eject.js +151 -0
- package/src/get-json.js +16 -0
- package/src/get-plugins.js +43 -0
- package/src/get-rollup-configs.js +224 -0
- package/src/helpers.js +229 -0
- package/src/index.js +133 -0
- package/src/load-plugins.js +37 -0
- package/src/messages.js +13 -0
- package/src/options/index.js +266 -0
- package/src/options/types.js +24 -0
- package/src/plugin-name.js +6 -0
- package/src/priorities.js +10 -0
- package/src/process-pkg.js +237 -0
- package/src/process-ts-config.js +80 -0
- package/src/rollup-plugin-preprocess.d.ts +1 -0
- package/src/types.js +170 -0
- package/src/write-json.js +21 -0
- package/types/index.d.ts +298 -0
- package/dist/index.d.ts +0 -79
- package/dist/index.mjs +0 -1626
package/src/eject.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
import pkgbldPkg from '../package.json' with { type: 'json' };
|
|
5
|
+
import { camelCase } from './helpers.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {import('rollup').RollupOptions} RollupOptions
|
|
9
|
+
* @typedef {import('type-fest').PackageJson} PackageJson
|
|
10
|
+
* @typedef {import('./types.js').BuildConfiguration} BuildConfiguration
|
|
11
|
+
* @typedef {import('./types.js').PackageProcessingResult} PackageProcessingResult
|
|
12
|
+
* @typedef {import('./types.js').PkgbldRollupPlugin} PkgbldRollupPlugin
|
|
13
|
+
* @typedef {import('./types.js').Provider} Provider
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const imports = new Map();
|
|
17
|
+
const setup = new Set();
|
|
18
|
+
|
|
19
|
+
/** @type {<T extends object>(object: T) => string | boolean | RegExp | null | undefined} */
|
|
20
|
+
let generate;
|
|
21
|
+
/** @type {() => string} */
|
|
22
|
+
let generateGlobals;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @returns {Promise<[Provider, PkgbldRollupPlugin[]]>}
|
|
26
|
+
*/
|
|
27
|
+
export async function createEjectProvider() {
|
|
28
|
+
const createMockProvider = (await import('@slimlib/smart-mock')).default;
|
|
29
|
+
const provider = createMockProvider();
|
|
30
|
+
const createMock = provider.createMock;
|
|
31
|
+
generate = provider.generate;
|
|
32
|
+
generateGlobals = provider.generateGlobals;
|
|
33
|
+
/** @type {PkgbldRollupPlugin[]} */
|
|
34
|
+
const plugins = [];
|
|
35
|
+
return [
|
|
36
|
+
{
|
|
37
|
+
provide: (
|
|
38
|
+
/** @type {PkgbldRollupPlugin['plugin']} */ plugin,
|
|
39
|
+
/** @type {PkgbldRollupPlugin['priority']} */ priority,
|
|
40
|
+
/** @type {Omit<PkgbldRollupPlugin, 'plugin' | 'priority'>=} */ options
|
|
41
|
+
) => {
|
|
42
|
+
plugins.push({ priority, plugin, format: options?.format, inputs: options?.inputs, outputPlugin: options?.outputPlugin });
|
|
43
|
+
},
|
|
44
|
+
import: async (/** @type {string} */ name, /** @type {string=} */ exportName) => {
|
|
45
|
+
const result = await import(name);
|
|
46
|
+
const exports = result[exportName ?? 'default'];
|
|
47
|
+
const mangledName = camelCase(name);
|
|
48
|
+
imports.set(name, mangledName);
|
|
49
|
+
return createMock(exports, mangledName);
|
|
50
|
+
},
|
|
51
|
+
globalImport: (/** @type {string} */ module, /** @type {string | string[]=} */ exportName) => {
|
|
52
|
+
imports.set(module, exportName ?? 'default');
|
|
53
|
+
},
|
|
54
|
+
globalSetup: (/** @type {((...args: any[]) => any) | string} */ code) => {
|
|
55
|
+
if (typeof code === 'function') {
|
|
56
|
+
setup.add(code.toString());
|
|
57
|
+
return createMock(code, code.name);
|
|
58
|
+
}
|
|
59
|
+
setup.add(String(code));
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
plugins,
|
|
63
|
+
];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @param {RollupOptions[]} config
|
|
68
|
+
* @param {string} pkgPath
|
|
69
|
+
* @param {BuildConfiguration} configuration
|
|
70
|
+
* @param {PackageProcessingResult} packageResult
|
|
71
|
+
* @param {ReturnType<import('./helpers.js').getHelpers>} helpers
|
|
72
|
+
* @param {PackageJson} pkg
|
|
73
|
+
*/
|
|
74
|
+
export async function ejectConfig(config, pkgPath, configuration, packageResult, helpers, pkg) {
|
|
75
|
+
const pkgName = /** @type {{ name: string }} */ (pkg).name;
|
|
76
|
+
|
|
77
|
+
const text = generate(config);
|
|
78
|
+
setup.add(generateGlobals());
|
|
79
|
+
|
|
80
|
+
setup.add(`const configuration = ${generate(configuration)}`);
|
|
81
|
+
setup.add(`const packageResult = { executableOutputs: ${generate(packageResult.executableOutputs)} }`);
|
|
82
|
+
setup.add(`const inputs = ${generate(packageResult.entries.values.map(entry => entry.sourcePath))}`);
|
|
83
|
+
|
|
84
|
+
if (configuration.outputs.formats.includes('umd')) {
|
|
85
|
+
imports.set('path', 'path');
|
|
86
|
+
imports.set('url', 'url');
|
|
87
|
+
setup.add(`const pkgName = ${generate(/** @type {never} */ (pkgName))}`);
|
|
88
|
+
setup.add(camelCase.toString());
|
|
89
|
+
setup.add(helpers.getGlobalName.toString());
|
|
90
|
+
setup.add("const __dirname = url.fileURLToPath(new URL('.', import.meta.url));");
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const importsString = Array.from(imports)
|
|
94
|
+
.map(value => `import ${value[1]} from '${value[0]}';`)
|
|
95
|
+
.join('\n');
|
|
96
|
+
const setupString = Array.from(setup).join('\n');
|
|
97
|
+
|
|
98
|
+
const { minify } = await import('terser');
|
|
99
|
+
|
|
100
|
+
const result = await minify(`${importsString}\n${setupString}\nexport default ${text};`, {
|
|
101
|
+
module: true,
|
|
102
|
+
compress: {
|
|
103
|
+
booleans: false,
|
|
104
|
+
ecma: 2020,
|
|
105
|
+
module: true,
|
|
106
|
+
passes: 3,
|
|
107
|
+
unsafe: true,
|
|
108
|
+
},
|
|
109
|
+
mangle: false,
|
|
110
|
+
output: {
|
|
111
|
+
beautify: true,
|
|
112
|
+
ecma: 2020,
|
|
113
|
+
quote_style: 1,
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
await fs.writeFile(path.join(path.dirname(pkgPath), 'rollup.config.mjs'), /** @type {string} */ (result.code));
|
|
117
|
+
|
|
118
|
+
await updatePackageJson(pkg);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @param {PackageJson} pkg
|
|
123
|
+
*/
|
|
124
|
+
async function updatePackageJson(pkg) {
|
|
125
|
+
if (typeof pkg.devDependencies !== 'object') {
|
|
126
|
+
pkg.devDependencies = {};
|
|
127
|
+
}
|
|
128
|
+
const devDependencies = pkg.devDependencies;
|
|
129
|
+
if ('pkgbld' in devDependencies) {
|
|
130
|
+
devDependencies.pkgbld = undefined;
|
|
131
|
+
}
|
|
132
|
+
devDependencies.rollup = /** @type {Record<string, string>} */ (pkgbldPkg.dependencies).rollup ?? '*';
|
|
133
|
+
const isBuiltin = (await import('is-builtin-module')).default;
|
|
134
|
+
for (const key of imports.keys()) {
|
|
135
|
+
const packageName = getPackageName(key);
|
|
136
|
+
if (!isBuiltin(packageName)) {
|
|
137
|
+
devDependencies[packageName] = /** @type {Record<string, string>} */ (pkgbldPkg.dependencies)[packageName] ?? '*';
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* @param {string} key
|
|
144
|
+
* @returns {string}
|
|
145
|
+
*/
|
|
146
|
+
function getPackageName(key) {
|
|
147
|
+
return key
|
|
148
|
+
.split('/')
|
|
149
|
+
.slice(0, key.startsWith('@') ? 2 : 1)
|
|
150
|
+
.join('/');
|
|
151
|
+
}
|
package/src/get-json.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {import('type-fest').JsonObject} JsonObject
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {string} fileName
|
|
10
|
+
* @returns {Promise<[string, JsonObject]>}
|
|
11
|
+
*/
|
|
12
|
+
export async function getJson(fileName) {
|
|
13
|
+
const pkgPath = path.resolve(fileName);
|
|
14
|
+
const buffer = await fs.readFile(pkgPath);
|
|
15
|
+
return [pkgPath, /** @type {JsonObject} */ (JSON.parse(buffer.toString()))];
|
|
16
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import binify from './builtin-plugins/binify.js';
|
|
2
|
+
import clean from './builtin-plugins/clean.js';
|
|
3
|
+
import commonjs from './builtin-plugins/commonjs.js';
|
|
4
|
+
import externals from './builtin-plugins/externals.js';
|
|
5
|
+
import json from './builtin-plugins/json.js';
|
|
6
|
+
import preprocess from './builtin-plugins/preprocess.js';
|
|
7
|
+
import resolve from './builtin-plugins/resolve.js';
|
|
8
|
+
import terser from './builtin-plugins/terser.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {import('./types.js').PkgbldRollupPlugin} PkgbldRollupPlugin
|
|
12
|
+
* @typedef {import('./types.js').Provider} Provider
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export const plugins = [clean, commonjs, externals, preprocess, resolve, terser, binify, json];
|
|
16
|
+
|
|
17
|
+
const noop = () => undefined;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @returns {[Provider, PkgbldRollupPlugin[]]}
|
|
21
|
+
*/
|
|
22
|
+
export function createProvider() {
|
|
23
|
+
/** @type {PkgbldRollupPlugin[]} */
|
|
24
|
+
const plugins = [];
|
|
25
|
+
return [
|
|
26
|
+
{
|
|
27
|
+
provide: (
|
|
28
|
+
/** @type {PkgbldRollupPlugin['plugin']} */ plugin,
|
|
29
|
+
/** @type {PkgbldRollupPlugin['priority']} */ priority,
|
|
30
|
+
/** @type {Omit<PkgbldRollupPlugin, 'plugin' | 'priority'>=} */ options
|
|
31
|
+
) => {
|
|
32
|
+
plugins.push({ priority, plugin, format: options?.format, inputs: options?.inputs, outputPlugin: options?.outputPlugin });
|
|
33
|
+
},
|
|
34
|
+
import: async (/** @type {string} */ name, /** @type {string=} */ exportName) => {
|
|
35
|
+
const result = await import(name);
|
|
36
|
+
return result[exportName ?? 'default'];
|
|
37
|
+
},
|
|
38
|
+
globalImport: noop,
|
|
39
|
+
globalSetup: code => (typeof code === 'function' ? code : undefined),
|
|
40
|
+
},
|
|
41
|
+
plugins,
|
|
42
|
+
];
|
|
43
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import refiner from '@slimlib/refine-partition';
|
|
2
|
+
|
|
3
|
+
import { plugins as pluginFactories } from './get-plugins.js';
|
|
4
|
+
import { areSetsEqual, toArray } from './helpers.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {import('rollup').InternalModuleFormat} InternalModuleFormat
|
|
8
|
+
* @typedef {import('rollup').OutputOptions} OutputOptions
|
|
9
|
+
* @typedef {import('./types.js').BuildConfiguration} BuildConfiguration
|
|
10
|
+
* @typedef {import('./types.js').PackageProcessingResult} PackageProcessingResult
|
|
11
|
+
* @typedef {import('./types.js').PkgbldRollupPlugin} PkgbldRollupPlugin
|
|
12
|
+
* @typedef {import('./types.js').Provider} Provider
|
|
13
|
+
* @typedef {ReturnType<typeof import('./build-plugin-lifecycle.js').createBuildPluginLifecycle>} BuildPluginLifecycle
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {[Provider, PkgbldRollupPlugin[]]} providerAndPlugins
|
|
18
|
+
* @param {PackageProcessingResult} packageResult
|
|
19
|
+
* @param {BuildConfiguration} configuration
|
|
20
|
+
* @param {ReturnType<import('./helpers.js').getHelpers>} helpers
|
|
21
|
+
* @param {BuildPluginLifecycle} pluginLifecycle
|
|
22
|
+
*/
|
|
23
|
+
export async function getRollupConfigs([provider, plugins], packageResult, configuration, helpers, pluginLifecycle) {
|
|
24
|
+
const inputs = packageResult.entries.values.map(entry => entry.sourcePath);
|
|
25
|
+
const entriesBySourcePath = new Map(packageResult.entries.values.map(entry => [entry.sourcePath, entry]));
|
|
26
|
+
const factoryInProgress = [];
|
|
27
|
+
|
|
28
|
+
const fileNamePatterns = /** @type {{ [key in InternalModuleFormat]: string }} */ ({
|
|
29
|
+
es: configuration.outputs.patterns.es,
|
|
30
|
+
cjs: configuration.outputs.patterns.cjs,
|
|
31
|
+
umd: configuration.outputs.patterns.umd,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
for (const factory of pluginFactories) {
|
|
35
|
+
factoryInProgress.push(factory(provider, configuration, packageResult));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
factoryInProgress.push(pluginLifecycle.provideRollupPlugins(provider, configuration, packageResult));
|
|
39
|
+
|
|
40
|
+
await Promise.all(factoryInProgress);
|
|
41
|
+
|
|
42
|
+
/** @type {Set<string>} */
|
|
43
|
+
const expandInputs = new Set();
|
|
44
|
+
|
|
45
|
+
for (const plugin of plugins) {
|
|
46
|
+
if (plugin.format && plugin.inputs?.length && !plugin.outputPlugin) {
|
|
47
|
+
for (const format of toArray(plugin.format)) {
|
|
48
|
+
expandInputs.add(format);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const refineNext = refiner();
|
|
54
|
+
|
|
55
|
+
refineNext(doExpandInputs(/** @type {InternalModuleFormat[]} */ ([...configuration.outputs.formats])));
|
|
56
|
+
|
|
57
|
+
for (const plugin of plugins) {
|
|
58
|
+
if (plugin.format && !plugin.outputPlugin) {
|
|
59
|
+
const formats = toArray(plugin.format);
|
|
60
|
+
if (!plugin.inputs || plugin.inputs.length === 0) {
|
|
61
|
+
refineNext(doExpandInputs(formats));
|
|
62
|
+
} else if (inputs.length === 1) {
|
|
63
|
+
refineNext(formats);
|
|
64
|
+
} else {
|
|
65
|
+
const expanded = [];
|
|
66
|
+
for (const format of formats) {
|
|
67
|
+
for (const input of plugin.inputs) {
|
|
68
|
+
expanded.push(`${format}.${input}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
refineNext(expanded);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const refined = refineNext();
|
|
77
|
+
/** @type {{ formats: InternalModuleFormat[]; inputs: string[] }[]} */
|
|
78
|
+
const partitions = [];
|
|
79
|
+
|
|
80
|
+
for (const partition of refined) {
|
|
81
|
+
/** @type {{ format: InternalModuleFormat; input?: string }[]} */
|
|
82
|
+
const result = [];
|
|
83
|
+
for (const format of partition) {
|
|
84
|
+
if (format.includes('.')) {
|
|
85
|
+
const [, realFormat, input] = format.split(/(.*?)\.(.*)/gm);
|
|
86
|
+
result.push({ format: /** @type {InternalModuleFormat} */ (realFormat), input });
|
|
87
|
+
} else {
|
|
88
|
+
result.push({ format: /** @type {InternalModuleFormat} */ (format) });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/** @type {Map<InternalModuleFormat, Set<string>>} */
|
|
92
|
+
const mapFormatInputs = new Map();
|
|
93
|
+
/** @type {Set<InternalModuleFormat>} */
|
|
94
|
+
const formatsWithoutInputs = new Set();
|
|
95
|
+
for (const { format, input } of result) {
|
|
96
|
+
if (input) {
|
|
97
|
+
if (mapFormatInputs.has(format)) {
|
|
98
|
+
/** @type {Set<string>} */ (mapFormatInputs.get(format)).add(input);
|
|
99
|
+
} else {
|
|
100
|
+
mapFormatInputs.set(format, new Set([input]));
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
formatsWithoutInputs.add(format);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
for (const format of formatsWithoutInputs) {
|
|
107
|
+
if (mapFormatInputs.has(format)) {
|
|
108
|
+
throw new Error(
|
|
109
|
+
`${format} is both used with inputs and without in plugins configuration and was not expanded / handled correctly. Please file an issue for pkgbld.`
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
mapFormatInputs.set(format, new Set(inputs));
|
|
113
|
+
}
|
|
114
|
+
/** @type {Set<string> | undefined} */
|
|
115
|
+
let prevInputs;
|
|
116
|
+
for (const inputs of mapFormatInputs.values()) {
|
|
117
|
+
if (prevInputs) {
|
|
118
|
+
if (!areSetsEqual(inputs, prevInputs)) {
|
|
119
|
+
throw new Error(`unbalanced inputs for partition: ${JSON.stringify(partition)}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
prevInputs = inputs;
|
|
123
|
+
}
|
|
124
|
+
partitions.push({ formats: [...mapFormatInputs.keys()], inputs: [.../** @type {Set<string>} */ (prevInputs)] });
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return partitions.map(({ formats, inputs }) => {
|
|
128
|
+
return {
|
|
129
|
+
input: Object.fromEntries(
|
|
130
|
+
inputs.map(input => [/** @type {import('./types.js').BuildEntry} */ (entriesBySourcePath.get(input)).name, input])
|
|
131
|
+
),
|
|
132
|
+
|
|
133
|
+
output: formats.map(format => ({
|
|
134
|
+
format,
|
|
135
|
+
dir: configuration.paths.outputDir,
|
|
136
|
+
entryFileNames: fileNamePatterns[format],
|
|
137
|
+
plugins: getPlugins([format], inputs, true),
|
|
138
|
+
sourcemap: configuration.outputs.sourcemaps.some(value => value === format),
|
|
139
|
+
...getExtraOutputSettings(format, inputs),
|
|
140
|
+
})),
|
|
141
|
+
|
|
142
|
+
plugins: getPlugins(formats, inputs, false),
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @param {InternalModuleFormat} format
|
|
148
|
+
* @param {string[]} inputs
|
|
149
|
+
* @returns {Partial<OutputOptions>}
|
|
150
|
+
*/
|
|
151
|
+
function getExtraOutputSettings(format, inputs) {
|
|
152
|
+
let result = {};
|
|
153
|
+
switch (format) {
|
|
154
|
+
case 'cjs':
|
|
155
|
+
case 'es':
|
|
156
|
+
result = { chunkFileNames: fileNamePatterns[format] };
|
|
157
|
+
break;
|
|
158
|
+
case 'umd':
|
|
159
|
+
if (inputs.length <= 0) {
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
if (inputs.length > 1) {
|
|
163
|
+
throw new Error(`Cannot produce global name for multiple umd inputs in one output: ${inputs}`);
|
|
164
|
+
}
|
|
165
|
+
result = {
|
|
166
|
+
name: helpers.getGlobalName(inputs.join('_')),
|
|
167
|
+
globals: helpers.getExternalGlobalName,
|
|
168
|
+
};
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
pluginLifecycle.extendOutputSettings(result, format, inputs, configuration);
|
|
172
|
+
return result;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* @param {InternalModuleFormat[]} formats
|
|
177
|
+
* @param {string[]} inputs
|
|
178
|
+
* @param {boolean} outputPlugin
|
|
179
|
+
*/
|
|
180
|
+
function getPlugins(formats, inputs, outputPlugin) {
|
|
181
|
+
const filteredPlugins = [];
|
|
182
|
+
for (const plugin of plugins) {
|
|
183
|
+
if (!!plugin.outputPlugin === outputPlugin) {
|
|
184
|
+
if (
|
|
185
|
+
(!plugin.format || toArray(plugin.format).some(format => formats.includes(format))) &&
|
|
186
|
+
(!plugin.inputs || plugin.inputs.every(input => inputs.includes(input)))
|
|
187
|
+
) {
|
|
188
|
+
filteredPlugins.push({
|
|
189
|
+
instance: plugin.plugin(),
|
|
190
|
+
priority: plugin.priority,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
filteredPlugins.sort((a, b) => a.priority - b.priority);
|
|
196
|
+
return filteredPlugins.map(plugin => plugin.instance);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* @param {InternalModuleFormat[]} formats
|
|
201
|
+
*/
|
|
202
|
+
function doExpandInputs(formats) {
|
|
203
|
+
if (inputs.length === 1) {
|
|
204
|
+
return formats;
|
|
205
|
+
}
|
|
206
|
+
const expanded = [];
|
|
207
|
+
for (const format of formats) {
|
|
208
|
+
if (expandInputs.has(format)) {
|
|
209
|
+
if (format !== 'umd') {
|
|
210
|
+
for (const input of inputs) {
|
|
211
|
+
expanded.push(`${format}.${input}`);
|
|
212
|
+
}
|
|
213
|
+
} else {
|
|
214
|
+
for (const entryName of configuration.outputs.umdEntries) {
|
|
215
|
+
expanded.push(`${format}.${packageResult.entries.require(entryName).sourcePath}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
expanded.push(format);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return expanded;
|
|
223
|
+
}
|
|
224
|
+
}
|
package/src/helpers.js
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { access, constants, readFile } from 'node:fs/promises';
|
|
2
|
+
import path, { dirname, join } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
import { cyan, magenta } from '@niceties/ansi';
|
|
6
|
+
|
|
7
|
+
import { processPackageJson } from './options/index.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {import('rollup').OutputOptions} OutputOptions
|
|
11
|
+
* @typedef {import('type-fest').PackageJson} PackageJson
|
|
12
|
+
* @typedef {import('./options/index.js').PackageJson} PackageJsonO
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {unknown} value
|
|
19
|
+
* @returns {string}
|
|
20
|
+
*/
|
|
21
|
+
export function camelCase(value) {
|
|
22
|
+
const words = String(value)
|
|
23
|
+
.normalize('NFKD')
|
|
24
|
+
.replaceAll(/\p{Mark}/gu, '')
|
|
25
|
+
.replaceAll(/([\p{Ll}\d])(\p{Lu})/gu, '$1 $2')
|
|
26
|
+
.replaceAll(/(\p{Lu}+)(\p{Lu}\p{Ll})/gu, '$1 $2')
|
|
27
|
+
.match(/[\p{L}\d]+/gu);
|
|
28
|
+
|
|
29
|
+
return (words ?? [])
|
|
30
|
+
.map((word, index) => {
|
|
31
|
+
const lowerCaseWord = word.toLowerCase();
|
|
32
|
+
return index === 0 ? lowerCaseWord : lowerCaseWord[0].toUpperCase() + lowerCaseWord.slice(1);
|
|
33
|
+
})
|
|
34
|
+
.join('');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {string} pkgName
|
|
39
|
+
*/
|
|
40
|
+
export function getHelpers(pkgName) {
|
|
41
|
+
/**
|
|
42
|
+
* @param {string} anInput
|
|
43
|
+
*/
|
|
44
|
+
function getGlobalName(anInput) {
|
|
45
|
+
return camelCase(
|
|
46
|
+
path.join(
|
|
47
|
+
pkgName,
|
|
48
|
+
path.basename(anInput, path.extname(anInput)) !== 'index' ? path.basename(anInput, path.extname(anInput)) : ''
|
|
49
|
+
)
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @param {string} id
|
|
55
|
+
*/
|
|
56
|
+
function getExternalGlobalName(id) {
|
|
57
|
+
if (path.isAbsolute(id)) {
|
|
58
|
+
return getGlobalName(path.relative(__dirname, id));
|
|
59
|
+
}
|
|
60
|
+
return camelCase(id);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
getGlobalName,
|
|
65
|
+
getExternalGlobalName,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @template T
|
|
71
|
+
* @param {T | T[] | undefined} object
|
|
72
|
+
* @returns {T[]}
|
|
73
|
+
*/
|
|
74
|
+
export function toArray(object) {
|
|
75
|
+
if (Array.isArray(object)) {
|
|
76
|
+
return object;
|
|
77
|
+
}
|
|
78
|
+
if (object == null) {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
return [object];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @param {string[] | string} input
|
|
86
|
+
* @returns {string}
|
|
87
|
+
*/
|
|
88
|
+
export function formatInput(input) {
|
|
89
|
+
return (Array.isArray(input) ? input : [input ?? '']).map(item => magenta(path.basename(item, path.extname(item)))).join(', ');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @param {OutputOptions | OutputOptions[] | undefined} output
|
|
94
|
+
* @param {'dir' | 'format'} field
|
|
95
|
+
* @returns {string}
|
|
96
|
+
*/
|
|
97
|
+
export function formatOutput(output, field) {
|
|
98
|
+
if (output == null) {
|
|
99
|
+
return '';
|
|
100
|
+
}
|
|
101
|
+
return (Array.isArray(output) ? output : [output ?? '']).map(item => cyan(/** @type {string} */ (item[field]))).join(', ');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @param {number} starting
|
|
106
|
+
* @returns {string}
|
|
107
|
+
*/
|
|
108
|
+
export function getTimeDiff(starting) {
|
|
109
|
+
const diff = Date.now() - starting;
|
|
110
|
+
return diff >= 1000 ? `${(diff / 1000).toFixed(1)}s` : `${diff}ms`;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @template T
|
|
115
|
+
* @param {Set<T>} a
|
|
116
|
+
* @param {Set<T>} b
|
|
117
|
+
* @returns {boolean}
|
|
118
|
+
*/
|
|
119
|
+
export const areSetsEqual = (a, b) => (a.size === b.size ? [...a].every(value => b.has(value)) : false);
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @param {PackageJson} pkg
|
|
123
|
+
* @returns {PackageJson}
|
|
124
|
+
*/
|
|
125
|
+
export function formatPackageJson(pkg) {
|
|
126
|
+
return /** @type {PackageJson} */ (
|
|
127
|
+
processPackageJson(
|
|
128
|
+
/** @type {PackageJsonO} */ (pkg),
|
|
129
|
+
key => key in pkg,
|
|
130
|
+
key => /** @type {Record<string, unknown>} */ (pkg)[key]
|
|
131
|
+
)
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* @param {string} file
|
|
137
|
+
* @returns {Promise<string | false>}
|
|
138
|
+
*/
|
|
139
|
+
export async function isExists(file) {
|
|
140
|
+
try {
|
|
141
|
+
await access(file);
|
|
142
|
+
} catch (e) {
|
|
143
|
+
if (typeof e === 'object' && e != null && 'code' in e && e.code === 'ENOENT') {
|
|
144
|
+
return /** @type {const} */ (false);
|
|
145
|
+
}
|
|
146
|
+
throw e;
|
|
147
|
+
}
|
|
148
|
+
return file;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* @param {string} file
|
|
153
|
+
* @returns {Promise<boolean>}
|
|
154
|
+
*/
|
|
155
|
+
export async function isReadable(file) {
|
|
156
|
+
try {
|
|
157
|
+
await access(file, constants.R_OK);
|
|
158
|
+
return true;
|
|
159
|
+
} catch {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* @param {string} root
|
|
166
|
+
* @param {string} file
|
|
167
|
+
*/
|
|
168
|
+
function hasFile(root, file) {
|
|
169
|
+
const path = join(root, file);
|
|
170
|
+
return isExists(path);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* @param {string} root
|
|
175
|
+
* @returns {Promise<boolean>}
|
|
176
|
+
*/
|
|
177
|
+
async function hasWorkspacePackageJson(root) {
|
|
178
|
+
const path = join(root, 'package.json');
|
|
179
|
+
if (!(await isReadable(path))) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
try {
|
|
183
|
+
const content = /** @type {PackageJson} */ (JSON.parse(await readFile(path, 'utf-8')) || {});
|
|
184
|
+
return !!content.workspaces;
|
|
185
|
+
} catch {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* @param {string} current
|
|
192
|
+
* @returns {Promise<string>}
|
|
193
|
+
*/
|
|
194
|
+
export async function searchForPackageRoot(current) {
|
|
195
|
+
const root = current;
|
|
196
|
+
let dir = current;
|
|
197
|
+
|
|
198
|
+
while (dir) {
|
|
199
|
+
if (await hasFile(dir, 'package.json')) return dir;
|
|
200
|
+
|
|
201
|
+
const parentDir = dirname(dir);
|
|
202
|
+
if (parentDir === dir) break;
|
|
203
|
+
|
|
204
|
+
dir = parentDir;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return root;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @param {string} current
|
|
212
|
+
* @returns {Promise<string>}
|
|
213
|
+
*/
|
|
214
|
+
export async function searchForWorkspaceRoot(current) {
|
|
215
|
+
const root = await searchForPackageRoot(current);
|
|
216
|
+
let dir = current;
|
|
217
|
+
|
|
218
|
+
while (dir) {
|
|
219
|
+
if (await hasFile(dir, 'pnpm-workspace.yaml')) return dir;
|
|
220
|
+
if (await hasWorkspacePackageJson(dir)) return dir;
|
|
221
|
+
|
|
222
|
+
const parentDir = dirname(dir);
|
|
223
|
+
if (parentDir === dir) break;
|
|
224
|
+
|
|
225
|
+
dir = parentDir;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return root;
|
|
229
|
+
}
|