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.
@@ -0,0 +1,37 @@
1
+ import { createRequire } from 'node:module';
2
+ import { pathToFileURL } from 'node:url';
3
+
4
+ /**
5
+ * @typedef {import('type-fest').PackageJson} PackageJson
6
+ */
7
+
8
+ import { isPluginPackageName } from './plugin-name.js';
9
+
10
+ /**
11
+ * @param {PackageJson} pkg
12
+ * @param {Set<string>} loaded
13
+ * @param {string} packageJsonPath
14
+ */
15
+ export async function loadPlugins(pkg, loaded, packageJsonPath) {
16
+ const resolveFromPackage = createRequire(packageJsonPath).resolve;
17
+ return await Promise.all(
18
+ [
19
+ ...new Set([
20
+ ...Object.keys(pkg.devDependencies || {}),
21
+ ...Object.keys(pkg.dependencies || {}),
22
+ ...Object.keys(pkg.peerDependencies || {}),
23
+ ]),
24
+ ]
25
+ .filter(packageName => isPluginPackageName(packageName) && !loaded.has(packageName))
26
+ .map(async packageName => {
27
+ loaded.add(packageName);
28
+ try {
29
+ const pluginPath = resolveFromPackage(packageName);
30
+ const pluginFactory = await import(pathToFileURL(pluginPath).href);
31
+ return await pluginFactory.create();
32
+ } catch (cause) {
33
+ throw new Error(`Failed to load Build plugin ${JSON.stringify(packageName)} from ${packageJsonPath}`, { cause });
34
+ }
35
+ })
36
+ );
37
+ }
@@ -0,0 +1,13 @@
1
+ import { getTimeDiff } from './helpers.js';
2
+
3
+ /**
4
+ * @param {string} sourceDir
5
+ * @param {string} dir
6
+ * @param {number} configsCount
7
+ * @param {number} startingTime
8
+ * @param {number} [finishedCount]
9
+ */
10
+ export const mainLoggerText =
11
+ (sourceDir, dir, configsCount, startingTime, finishedCount = 0) =>
12
+ (final = false) =>
13
+ `${sourceDir} → ${dir} ${final ? configsCount : finishedCount++} / ${configsCount}${final ? ` in ${getTimeDiff(startingTime)}` : ''}`;
@@ -0,0 +1,277 @@
1
+ /** @typedef {import('./types.js').PackageJson} PackageJson */
2
+
3
+ /**
4
+ * @param {unknown} value
5
+ * @returns {value is PackageJson}
6
+ */
7
+ export function isPackageJson(value) {
8
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
9
+ return false;
10
+ }
11
+ const obj = /** @type {Record<string, unknown>} */ (value);
12
+ if (obj.private !== undefined && typeof obj.private !== 'boolean') return false;
13
+ if (obj.version !== undefined && typeof obj.version !== 'string') return false;
14
+ if (obj.name !== undefined && typeof obj.name !== 'string') return false;
15
+ if (obj.main !== undefined && typeof obj.main !== 'string') return false;
16
+ if (obj.license !== undefined && typeof obj.license !== 'string') return false;
17
+ if (obj.readme !== undefined && typeof obj.readme !== 'string') return false;
18
+ if (obj.description !== undefined && typeof obj.description !== 'string') return false;
19
+ if (obj.bugs !== undefined && typeof obj.bugs !== 'string') return false;
20
+ if (obj.homepage !== undefined && typeof obj.homepage !== 'string') return false;
21
+ if (obj.bin !== undefined && typeof obj.bin !== 'string' && (typeof obj.bin !== 'object' || obj.bin === null || Array.isArray(obj.bin)))
22
+ return false;
23
+ if (
24
+ obj.author !== undefined &&
25
+ typeof obj.author !== 'string' &&
26
+ (typeof obj.author !== 'object' || obj.author === null || Array.isArray(obj.author))
27
+ )
28
+ return false;
29
+ return true;
30
+ }
31
+
32
+ /**
33
+ * @param {string} value
34
+ * @returns {string[]}
35
+ */
36
+ function CommaSeparatedString(value) {
37
+ if (value === '') return [];
38
+ return value.split(',').map((/** @type {string} */ arg) => arg.trim());
39
+ }
40
+
41
+ /**
42
+ * @param {string} value
43
+ * @returns {true | string[]}
44
+ */
45
+ function CommaSeparatedStringOrBoolean(value) {
46
+ if (value === '') {
47
+ return true;
48
+ }
49
+ return CommaSeparatedString(value);
50
+ }
51
+
52
+ export const cliFlagsDefaults = {
53
+ formats: /** @type {string[]} */ (['es', 'cjs']),
54
+ umd: /** @type {string[]} */ ([]),
55
+ compress: /** @type {string[]} */ (['umd']),
56
+ sourcemaps: /** @type {string[]} */ (['umd']),
57
+ preprocess: /** @type {string[]} */ ([]),
58
+ dest: 'dist',
59
+ src: 'src',
60
+ bin: /** @type {string[] | undefined} */ (undefined),
61
+ includeExternals: /** @type {boolean | string[]} */ (false),
62
+ imports: false,
63
+ conditions: /** @type {string[]} */ ([]),
64
+ eject: false,
65
+ tsConfig: false,
66
+ updatePackageJson: true,
67
+ commonjsPattern: '[name].cjs',
68
+ esmPattern: '[name].mjs',
69
+ umdPattern: '[name].umd.js',
70
+ formatPackageJson: false,
71
+ };
72
+
73
+ /**
74
+ * @typedef {{
75
+ * type: 'string' | 'boolean' | ((value: string) => unknown);
76
+ * description: string;
77
+ * default?: string | boolean | string[] | boolean[];
78
+ * optionalValue?: boolean;
79
+ * }} CliFlag
80
+ */
81
+
82
+ /** @type {Record<string, CliFlag>} */
83
+ export const cliFlags = {
84
+ umd: {
85
+ type: /** @type {(value: string) => string[]} */ (CommaSeparatedString),
86
+ description: 'Package subpath exports in UMD format',
87
+ },
88
+ compress: {
89
+ type: /** @type {(value: string) => string[]} */ (CommaSeparatedString),
90
+ description: 'Compress formats using terser',
91
+ },
92
+ sourcemaps: {
93
+ type: /** @type {(value: string) => string[]} */ (CommaSeparatedString),
94
+ description: 'Emit sourcemaps for the specified formats',
95
+ },
96
+ formats: {
97
+ type: /** @type {(value: string) => string[]} */ (CommaSeparatedString),
98
+ description: 'Formats to emit',
99
+ },
100
+ preprocess: {
101
+ type: /** @type {(value: string) => string[]} */ (CommaSeparatedString),
102
+ description: 'Preprocess entry points / subpath exports',
103
+ },
104
+ dest: {
105
+ type: /** @type {'string'} */ ('string'),
106
+ description: 'Output directory',
107
+ default: cliFlagsDefaults.dest,
108
+ },
109
+ src: {
110
+ type: /** @type {'string'} */ ('string'),
111
+ description: 'Source directory',
112
+ default: cliFlagsDefaults.src,
113
+ },
114
+ bin: {
115
+ type: /** @type {(value: string) => string[]} */ (CommaSeparatedString),
116
+ description: 'Executable files',
117
+ },
118
+ includeExternals: {
119
+ type: /** @type {(value: string) => true | string[]} */ (CommaSeparatedStringOrBoolean),
120
+ description: 'Include all/specified externals into the result bundle(s)',
121
+ optionalValue: true,
122
+ },
123
+ imports: {
124
+ type: /** @type {'boolean'} */ ('boolean'),
125
+ description: 'Build and preserve package imports',
126
+ default: cliFlagsDefaults.imports,
127
+ },
128
+ conditions: {
129
+ type: /** @type {(value: string) => string[]} */ (CommaSeparatedString),
130
+ description: 'Additional conditions for resolving bundled dependencies',
131
+ },
132
+ eject: {
133
+ type: /** @type {'boolean'} */ ('boolean'),
134
+ description: 'Eject config',
135
+ default: cliFlagsDefaults.eject,
136
+ },
137
+ tsConfig: {
138
+ type: /** @type {'boolean'} */ ('boolean'),
139
+ description: 'Create / update tsconfig.json',
140
+ default: cliFlagsDefaults.tsConfig,
141
+ },
142
+ updatePackageJson: {
143
+ type: /** @type {'boolean'} */ ('boolean'),
144
+ description: 'Create / update package.json',
145
+ default: cliFlagsDefaults.updatePackageJson,
146
+ },
147
+ commonjsPattern: {
148
+ type: /** @type {'string'} */ ('string'),
149
+ description: 'CommonJS output file name pattern',
150
+ default: cliFlagsDefaults.commonjsPattern,
151
+ },
152
+ esmPattern: {
153
+ type: /** @type {'string'} */ ('string'),
154
+ description: 'ES output file name pattern',
155
+ default: cliFlagsDefaults.esmPattern,
156
+ },
157
+ umdPattern: {
158
+ type: /** @type {'string'} */ ('string'),
159
+ description: 'UMD output file name pattern',
160
+ default: cliFlagsDefaults.umdPattern,
161
+ },
162
+ formatPackageJson: {
163
+ type: /** @type {'boolean'} */ ('boolean'),
164
+ description: 'Format package.json',
165
+ default: cliFlagsDefaults.formatPackageJson,
166
+ },
167
+ pack: {
168
+ type: /** @type {'boolean'} */ ('boolean'),
169
+ description: 'Pack',
170
+ default: true,
171
+ },
172
+ exports: {
173
+ type: /** @type {'boolean'} */ ('boolean'),
174
+ description: 'Add exports field to package.json',
175
+ default: true,
176
+ },
177
+ clean: {
178
+ type: /** @type {'boolean'} */ ('boolean'),
179
+ description: 'Clean the output directory',
180
+ default: true,
181
+ },
182
+ bundle: {
183
+ type: /** @type {'boolean'} */ ('boolean'),
184
+ description: 'Bundle',
185
+ default: true,
186
+ },
187
+ removeLegalComments: {
188
+ type: /** @type {'boolean'} */ ('boolean'),
189
+ description: 'Remove legal comments',
190
+ default: false,
191
+ },
192
+ };
193
+
194
+ export const packageJsonFieldsOrder = new Set([
195
+ 'private',
196
+ 'type',
197
+ 'version',
198
+ 'name',
199
+ 'scope', // custom
200
+ 'description',
201
+ 'license',
202
+ 'author',
203
+ 'contributors',
204
+ 'funding',
205
+ 'bin',
206
+ 'main',
207
+ 'browser',
208
+ 'unpkg',
209
+ 'module',
210
+ 'svelte',
211
+ 'exports',
212
+ 'imports',
213
+ 'types',
214
+ 'typings',
215
+ 'typesVersions', // non standard but required for typescript with resolution other than nodenext
216
+ 'files',
217
+ 'packageManager',
218
+ 'sideEffects',
219
+ 'engines',
220
+ 'os',
221
+ 'cpu',
222
+ 'man',
223
+ 'directories',
224
+ 'repository',
225
+ 'bugs',
226
+ 'homepage',
227
+ 'readme',
228
+ 'keywords',
229
+ 'scripts',
230
+ 'config',
231
+ 'dependencies',
232
+ 'devDependencies',
233
+ 'peerDependencies',
234
+ 'peerDependenciesMeta',
235
+ 'bundleDependencies',
236
+ 'bundledDependencies',
237
+ 'optionalDependencies',
238
+ 'overrides',
239
+ 'publishConfig',
240
+ 'workspaces',
241
+ ]);
242
+
243
+ /**
244
+ * @param {PackageJson} pkg
245
+ * @param {(key: string) => boolean} needTreatment
246
+ * @param {(key: string) => unknown} treatKey
247
+ * @returns {PackageJson}
248
+ */
249
+ export function processPackageJson(pkg, needTreatment, treatKey) {
250
+ /** @type {PackageJson} */
251
+ const newPkg = {};
252
+
253
+ for (const key of packageJsonFieldsOrder) {
254
+ if (needTreatment(key)) {
255
+ /** @type {Record<string, unknown>} */ (newPkg)[key] = treatKey(key);
256
+ }
257
+ }
258
+
259
+ for (const key in pkg) {
260
+ if (!packageJsonFieldsOrder.has(key)) {
261
+ /** @type {Record<string, unknown>} */ (newPkg)[key] = /** @type {Record<string, unknown>} */ (pkg)[key];
262
+ }
263
+ }
264
+
265
+ return newPkg;
266
+ }
267
+
268
+ /**
269
+ * @template {object | null | number | string | boolean} T
270
+ * @param {T} json
271
+ * @param {string | null} [current] Existing file contents used to detect indentation.
272
+ * @returns {string}
273
+ */
274
+ export function toFormattedJson(json, current) {
275
+ const indent = current?.match(/^[ \t]+(?=\S)/m)?.[0] ?? 2;
276
+ return `${JSON.stringify(json, null, indent)}\n`;
277
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @typedef {{
3
+ * private?: boolean;
4
+ * version?: string;
5
+ * name?: string;
6
+ * bin?: string | Record<string, string>;
7
+ * main?: string;
8
+ * license?: string;
9
+ * readme?: string;
10
+ * author?: string | { name?: string; email?: string; url?: string; };
11
+ * description?: string;
12
+ * scripts?: { [key: string]: string; };
13
+ * repository?: { type?: string; url?: string; };
14
+ * files?: string[];
15
+ * bugs?: string;
16
+ * homepage?: string;
17
+ * dependencies?: Record<string, string>;
18
+ * devDependencies?: Record<string, string>;
19
+ * peerDependencies?: Record<string, string>;
20
+ * exports?: Record<string, string | Record<string, string>>;
21
+ * }} PackageJson
22
+ */
23
+
24
+ export {};
@@ -0,0 +1,240 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { fileURLToPath, pathToFileURL } from 'node:url';
4
+
5
+ import { BuildEntryError, sourceFileExtensions } from './build-entries.js';
6
+
7
+ /**
8
+ * @typedef {import('./types.js').BuildConfiguration} BuildConfiguration
9
+ * @typedef {import('./types.js').BuildEntryIssue} BuildEntryIssue
10
+ * @typedef {import('./types.js').ImportTarget} ImportTarget
11
+ * @typedef {import('./types.js').BuildFormat} BuildFormat
12
+ */
13
+
14
+ const javascriptExtensions = new Set(['.js', '.mjs', '.cjs']);
15
+
16
+ /**
17
+ * Find every local JavaScript leaf of an authored package imports map.
18
+ * Non-JavaScript and package-specifier leaves remain the responsibility of
19
+ * their runtime resolver or producer.
20
+ *
21
+ * @param {unknown} imports
22
+ * @param {BuildConfiguration} configuration
23
+ * @param {unknown} packageType
24
+ * @returns {Promise<ImportTarget[]>}
25
+ */
26
+ export async function collectPackageImportTargets(imports, configuration, packageType) {
27
+ if (imports === undefined || !configuration.resolution.imports) return [];
28
+
29
+ /** @type {BuildEntryIssue[]} */
30
+ const issues = [];
31
+ /** @type {Map<string, ImportTarget>} */
32
+ const targets = new Map();
33
+ const leaves = parseImportMap(imports, issues);
34
+ for (const leaf of leaves) {
35
+ for (const target of await expandLocalTarget(leaf, configuration, packageType, issues)) {
36
+ if (!targets.has(target.outputPath)) targets.set(target.outputPath, target);
37
+ }
38
+ }
39
+
40
+ if (issues.length > 0) throw new BuildEntryError(issues);
41
+ return [...targets.values()];
42
+ }
43
+
44
+ /**
45
+ * Walk the authored map without selecting runtime conditions. Every local
46
+ * branch may need its own output, while package specifiers remain mappings.
47
+ * @param {unknown} imports
48
+ * @param {BuildEntryIssue[]} issues
49
+ */
50
+ function parseImportMap(imports, issues) {
51
+ /** @type {{ value: string; issuePath: string; wildcardKey: boolean }[]} */
52
+ const leaves = [];
53
+ if (!isRecord(imports)) {
54
+ issues.push({ code: 'INVALID_IMPORT_MAP', path: 'package.imports', message: 'must be an object' });
55
+ return leaves;
56
+ }
57
+
58
+ for (const [key, value] of Object.entries(imports)) {
59
+ const issuePath = `package.imports[${JSON.stringify(key)}]`;
60
+ const stars = key.match(/\*/g)?.length ?? 0;
61
+ if (!key.startsWith('#') || key === '#' || key.endsWith('/') || stars > 1) {
62
+ issues.push({ code: 'INVALID_IMPORT_KEY', path: issuePath, message: `Invalid package import key ${JSON.stringify(key)}` });
63
+ continue;
64
+ }
65
+ visit(value, issuePath, stars > 0);
66
+ }
67
+ return leaves;
68
+
69
+ /** @param {unknown} value @param {string} issuePath @param {boolean} wildcardKey */
70
+ function visit(value, issuePath, wildcardKey) {
71
+ if (value === null) return;
72
+ if (Array.isArray(value)) {
73
+ for (const [index, leaf] of value.entries()) visit(leaf, `${issuePath}[${index}]`, wildcardKey);
74
+ return;
75
+ }
76
+ if (isRecord(value)) {
77
+ for (const [condition, leaf] of Object.entries(value)) {
78
+ if (isArrayIndex(condition)) {
79
+ issues.push({
80
+ code: 'INVALID_IMPORT_CONDITION',
81
+ path: `${issuePath}.${condition}`,
82
+ message: `Integer condition key ${JSON.stringify(condition)} is invalid in a package imports map`,
83
+ });
84
+ } else {
85
+ visit(leaf, `${issuePath}.${condition}`, wildcardKey);
86
+ }
87
+ }
88
+ return;
89
+ }
90
+ if (typeof value !== 'string') {
91
+ issues.push({ code: 'INVALID_IMPORT_TARGET', path: issuePath, message: 'must be a string, null, array, or condition object' });
92
+ return;
93
+ }
94
+ if (!value.startsWith('./')) {
95
+ if (value.startsWith('.') || value.startsWith('/') || value.includes('\\') || value.length === 0 || URL.canParse(value)) {
96
+ issues.push({
97
+ code: 'INVALID_IMPORT_TARGET',
98
+ path: issuePath,
99
+ message: `Invalid package import target ${JSON.stringify(value)}`,
100
+ });
101
+ }
102
+ return;
103
+ }
104
+ leaves.push({ value, issuePath, wildcardKey });
105
+ }
106
+ }
107
+
108
+ /** @param {string} key */
109
+ function isArrayIndex(key) {
110
+ return /^(0|[1-9]\d*)$/.test(key) && Number(key) < 2 ** 32 - 1;
111
+ }
112
+
113
+ /**
114
+ * Validate a local URL target, then expand its output pattern against source
115
+ * names. Final source-extension selection happens in resolveBuildEntries.
116
+ * @param {{ value: string; issuePath: string; wildcardKey: boolean }} leaf
117
+ * @param {BuildConfiguration} configuration
118
+ * @param {unknown} packageType
119
+ * @param {BuildEntryIssue[]} issues
120
+ * @returns {Promise<ImportTarget[]>}
121
+ */
122
+ async function expandLocalTarget({ value, issuePath, wildcardKey }, configuration, packageType, issues) {
123
+ const pathPart = value.split(/[?#]/, 1)[0];
124
+ const rawSegments = pathPart.slice(2).split('/');
125
+ let outputPath;
126
+ try {
127
+ if (
128
+ pathPart.includes('\\') ||
129
+ rawSegments.some(segment => {
130
+ const decoded = decodeURIComponent(segment);
131
+ return (
132
+ decoded === '' ||
133
+ decoded === '.' ||
134
+ decoded === '..' ||
135
+ decoded.toLowerCase() === 'node_modules' ||
136
+ decoded.includes('/') ||
137
+ decoded.includes('\\')
138
+ );
139
+ })
140
+ ) {
141
+ throw new Error('invalid path segment');
142
+ }
143
+ outputPath = fileURLToPath(new URL(value, pathToFileURL(path.join(process.cwd(), 'package.json'))));
144
+ } catch {
145
+ issues.push({
146
+ code: 'INVALID_IMPORT_TARGET',
147
+ path: issuePath,
148
+ message: `Invalid local package import target ${JSON.stringify(value)}`,
149
+ });
150
+ return [];
151
+ }
152
+
153
+ const extension = path.extname(outputPath);
154
+ if (!javascriptExtensions.has(extension)) return [];
155
+
156
+ const outputDir = path.resolve(configuration.paths.outputDir);
157
+ if (!outputPath.startsWith(`${outputDir}${path.sep}`) || (pathPart.includes('*') && !wildcardKey)) {
158
+ issues.push({
159
+ code: 'INVALID_IMPORT_TARGET',
160
+ path: issuePath,
161
+ message: `Local JavaScript target ${JSON.stringify(value)} must be a safe path beneath ${configuration.paths.outputDir}`,
162
+ });
163
+ return [];
164
+ }
165
+
166
+ const format = /** @type {BuildFormat} */ (
167
+ extension === '.mjs' ? 'es' : extension === '.cjs' ? 'cjs' : packageType === 'module' ? 'es' : 'cjs'
168
+ );
169
+ if (!configuration.outputs.formats.includes(format)) {
170
+ issues.push({
171
+ code: 'EXCLUDED_IMPORT_FORMAT',
172
+ path: issuePath,
173
+ message: `Local target ${JSON.stringify(value)} requires ${format}, which is excluded by outputs.formats`,
174
+ });
175
+ return [];
176
+ }
177
+
178
+ const relativeOutput = path.relative(outputDir, outputPath).replaceAll('\\', '/');
179
+ const sourceName = relativeOutput.slice(0, -extension.length);
180
+ if (pathPart.includes('*')) {
181
+ const sourceNames = await findMatchingSourceNames(configuration.paths.sourceDir, sourceName);
182
+ if (sourceNames.length === 0) {
183
+ issues.push({
184
+ code: 'SOURCE_NOT_FOUND',
185
+ path: issuePath,
186
+ message: `Import target ${JSON.stringify(value)} has no supported source file`,
187
+ });
188
+ }
189
+ return sourceNames.map(matchedName => ({
190
+ sourceName: matchedName,
191
+ outputPath: `./${configuration.paths.outputDir}/${matchedName}${extension}`,
192
+ format,
193
+ issuePath,
194
+ }));
195
+ }
196
+ return [{ sourceName, outputPath: `./${configuration.paths.outputDir}/${relativeOutput}`, format, issuePath }];
197
+ }
198
+
199
+ /** @param {unknown} value @returns {value is Record<string, unknown>} */
200
+ function isRecord(value) {
201
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
202
+ }
203
+
204
+ /** @param {string} sourceDir @param {string} pattern */
205
+ async function findMatchingSourceNames(sourceDir, pattern) {
206
+ const parts = pattern.split('*').map(part => part.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
207
+ const matcher = new RegExp(
208
+ `^${parts[0]}(.+?)${parts[1]}${parts
209
+ .slice(2)
210
+ .map(part => `\\1${part}`)
211
+ .join('')}$`
212
+ );
213
+ /** @type {Set<string>} */
214
+ const names = new Set();
215
+ await walk(sourceDir, '');
216
+ return [...names].sort();
217
+
218
+ /** @param {string} directory @param {string} relative */
219
+ async function walk(directory, relative) {
220
+ let entries;
221
+ try {
222
+ entries = await fs.readdir(directory, { withFileTypes: true });
223
+ } catch (error) {
224
+ if (/** @type {NodeJS.ErrnoException} */ (error).code === 'ENOENT') return;
225
+ throw error;
226
+ }
227
+ for (const entry of entries) {
228
+ const nextRelative = relative ? `${relative}/${entry.name}` : entry.name;
229
+ if (entry.isDirectory()) {
230
+ await walk(path.join(directory, entry.name), nextRelative);
231
+ } else if (entry.isFile()) {
232
+ const extension = path.posix.extname(nextRelative).slice(1);
233
+ if (sourceFileExtensions.includes(/** @type {typeof sourceFileExtensions[number]} */ (extension))) {
234
+ const name = nextRelative.slice(0, -(extension.length + 1));
235
+ if (matcher.test(name)) names.add(name);
236
+ }
237
+ }
238
+ }
239
+ }
240
+ }
@@ -0,0 +1,6 @@
1
+ const PLUGIN_PACKAGE_RE = /^(?:@[^/]+\/)?pkgbld-plugin-/;
2
+
3
+ /** @param {string} packageName */
4
+ export function isPluginPackageName(packageName) {
5
+ return PLUGIN_PACKAGE_RE.test(packageName);
6
+ }
@@ -0,0 +1,11 @@
1
+ export const Priority = /** @type {const} */ ({
2
+ preprocess: 1000,
3
+ cleanup: 1000,
4
+ packageImports: 1500,
5
+ externals: 2000,
6
+ resolve: 3000,
7
+ commonjs: 4000,
8
+ transpile: 6000,
9
+ compress: 10000,
10
+ finalize: 20000,
11
+ });