presetter 9.0.0 → 9.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/lib/executable/entry.d.ts +7 -2
- package/lib/executable/entry.d.ts.map +1 -1
- package/lib/executable/entry.js +99 -23
- package/lib/executable/error.d.ts.map +1 -1
- package/lib/executable/error.js +55 -13
- package/lib/executable/index.js +6 -2
- package/lib/preset/config/resolve.d.ts.map +1 -1
- package/lib/preset/config/resolve.js +51 -4
- package/package.json +5 -5
|
@@ -7,11 +7,16 @@ interface ResolveProjectRootsOptions {
|
|
|
7
7
|
* @param args command line arguments
|
|
8
8
|
*/
|
|
9
9
|
export declare function entry(args: string[]): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* bootstrap every given project root, carrying on past any failure
|
|
12
|
+
* @param roots the project roots to be bootstrapped
|
|
13
|
+
*/
|
|
14
|
+
export declare function bootstrapProjects(roots: readonly string[]): Promise<void>;
|
|
10
15
|
/**
|
|
11
16
|
* resolve target project roots from path globs and package-name globs
|
|
12
17
|
* @param options resolution inputs
|
|
13
|
-
* @param options.projects path globs (e.g. `presets/next`, `packages
|
|
14
|
-
* @param options.packages package-name globs (e.g. `@presetter/preset
|
|
18
|
+
* @param options.projects path globs (e.g. `presets/next`, `packages/*`, `!presets/node`)
|
|
19
|
+
* @param options.packages package-name globs (e.g. `@presetter/preset-*`, `!@presetter/preset-node`)
|
|
15
20
|
* @returns deduped absolute project root paths
|
|
16
21
|
*/
|
|
17
22
|
export declare function resolveProjectRoots(options: ResolveProjectRootsOptions): Promise<string[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../../src/executable/entry.ts"],"names":[],"mappings":"AAmBA,UAAU,0BAA0B;IAClC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;
|
|
1
|
+
{"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../../src/executable/entry.ts"],"names":[],"mappings":"AAmBA,UAAU,0BAA0B;IAClC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAqHD;;;GAGG;AACH,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAezD;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,OAAO,CAAC,IAAI,CAAC,CAyBf;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,MAAM,EAAE,CAAC,CAgCnB;AAyED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,SAAS,GAAE,MAA+B,GACzC,MAAM,EAAE,CAOV"}
|
package/lib/executable/entry.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
-
import { dirname, posix, resolve } from 'node:path';
|
|
2
|
+
import { dirname, posix, relative, resolve } from 'node:path';
|
|
3
3
|
import { globby } from 'globby';
|
|
4
4
|
import yargs from 'yargs';
|
|
5
5
|
import { bootstrap } from '../preset/index.js';
|
|
6
6
|
import { run } from '../run.js';
|
|
7
7
|
import { parseGlobalArgs, parseTaskSpec } from '../task.js';
|
|
8
8
|
const DEFAULT_LIST_DELIMITER = ',';
|
|
9
|
+
const NEGATION_PREFIX = '!';
|
|
9
10
|
const WORKSPACE_GLOB_OPTIONS = {
|
|
10
11
|
gitignore: true,
|
|
11
12
|
ignore: ['**/node_modules/**'],
|
|
@@ -24,7 +25,7 @@ const bootstrapCommand = {
|
|
|
24
25
|
array: true,
|
|
25
26
|
default: ['.'],
|
|
26
27
|
coerce: (values) => expandDelimitedValues(values),
|
|
27
|
-
description: 'a glob pattern matching any target project folders containing package.json (comma-separated values supported)',
|
|
28
|
+
description: 'a glob pattern matching any target project folders containing package.json (comma-separated values supported; prefix a pattern with ! to exclude its matches)',
|
|
28
29
|
})
|
|
29
30
|
.option('packages', {
|
|
30
31
|
type: 'string',
|
|
@@ -32,7 +33,7 @@ const bootstrapCommand = {
|
|
|
32
33
|
array: true,
|
|
33
34
|
default: [],
|
|
34
35
|
coerce: (values) => expandDelimitedValues(values),
|
|
35
|
-
description: 'a glob pattern matching any target package names (e.g. @presetter/preset-*; comma-separated values supported)',
|
|
36
|
+
description: 'a glob pattern matching any target package names (e.g. @presetter/preset-*; comma-separated values supported; prefix a pattern with ! to exclude its matches)',
|
|
36
37
|
})
|
|
37
38
|
.help(),
|
|
38
39
|
handler: async (argv) => {
|
|
@@ -41,9 +42,7 @@ const bootstrapCommand = {
|
|
|
41
42
|
return;
|
|
42
43
|
}
|
|
43
44
|
const projectRoots = await resolveProjectRoots({ projects, packages });
|
|
44
|
-
|
|
45
|
-
await bootstrap(root);
|
|
46
|
-
}
|
|
45
|
+
await bootstrapProjects(projectRoots);
|
|
47
46
|
},
|
|
48
47
|
};
|
|
49
48
|
const runCommand = {
|
|
@@ -104,34 +103,111 @@ export async function entry(args) {
|
|
|
104
103
|
.demandCommand()
|
|
105
104
|
.parse(args);
|
|
106
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* bootstrap every given project root, carrying on past any failure
|
|
108
|
+
* @param roots the project roots to be bootstrapped
|
|
109
|
+
*/
|
|
110
|
+
export async function bootstrapProjects(roots) {
|
|
111
|
+
const failures = [];
|
|
112
|
+
// NOTE: run sequentially so that the progress printed by bootstrap stays in a deterministic order
|
|
113
|
+
for (const root of roots) {
|
|
114
|
+
try {
|
|
115
|
+
await bootstrap(root);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
failures.push({ root, error: error });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (failures.length > 0) {
|
|
122
|
+
// NOTE: report everything at the end so that a single broken project doesn't hide the rest of the run
|
|
123
|
+
throw new AggregateError(failures.map(({ root, error }) => new Error(`failed to bootstrap ${relative(process.cwd(), root) || '.'}`, { cause: error })), `failed to bootstrap ${failures.length} of ${roots.length} projects`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
107
126
|
/**
|
|
108
127
|
* resolve target project roots from path globs and package-name globs
|
|
109
128
|
* @param options resolution inputs
|
|
110
|
-
* @param options.projects path globs (e.g. `presets/next`, `packages
|
|
111
|
-
* @param options.packages package-name globs (e.g. `@presetter/preset
|
|
129
|
+
* @param options.projects path globs (e.g. `presets/next`, `packages/*`, `!presets/node`)
|
|
130
|
+
* @param options.packages package-name globs (e.g. `@presetter/preset-*`, `!@presetter/preset-node`)
|
|
112
131
|
* @returns deduped absolute project root paths
|
|
113
132
|
*/
|
|
114
133
|
export async function resolveProjectRoots(options) {
|
|
115
134
|
const { projects, packages } = options;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
135
|
+
// NOTE: name patterns are rewritten into path patterns so that both flags contribute to
|
|
136
|
+
// a single pattern list, which is what lets an exclusion given on either flag subtract a
|
|
137
|
+
// root selected by either flag
|
|
138
|
+
const patterns = [...projects, ...(await resolveNamePatterns(packages))];
|
|
139
|
+
const selecting = [];
|
|
140
|
+
const subtracting = [];
|
|
141
|
+
for (const pattern of patterns) {
|
|
142
|
+
const [prefix, directory] = splitNegation(pattern);
|
|
143
|
+
// NOTE: a pattern carrying nothing but `!` would otherwise become `package.json` and
|
|
144
|
+
// silently subtract the repo root
|
|
145
|
+
if (directory) {
|
|
146
|
+
const manifest = posix.join(directory, 'package.json');
|
|
147
|
+
(prefix === NEGATION_PREFIX ? subtracting : selecting).push(manifest);
|
|
121
148
|
}
|
|
122
149
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
roots.add(resolve(dirname(path)));
|
|
130
|
-
}
|
|
131
|
-
}));
|
|
150
|
+
const roots = new Set(await resolveRoots(selecting));
|
|
151
|
+
// NOTE: both sides are compared as resolved absolute paths rather than handed to globby
|
|
152
|
+
// as `!` patterns, whose matching is positional and stays blind to a pattern written
|
|
153
|
+
// relative to the working directory when its counterpart is absolute
|
|
154
|
+
for (const root of await resolveRoots(subtracting)) {
|
|
155
|
+
roots.delete(root);
|
|
132
156
|
}
|
|
133
157
|
return [...roots];
|
|
134
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* resolve the project roots behind a list of manifest patterns
|
|
161
|
+
* @param patterns manifest globs carrying no negation prefix
|
|
162
|
+
* @returns absolute project root paths
|
|
163
|
+
*/
|
|
164
|
+
async function resolveRoots(patterns) {
|
|
165
|
+
if (patterns.length === 0) {
|
|
166
|
+
return [];
|
|
167
|
+
}
|
|
168
|
+
const files = await globby(patterns, WORKSPACE_GLOB_OPTIONS);
|
|
169
|
+
return files.map((file) => resolve(dirname(file)));
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* rewrite package-name globs into path globs, keeping any `!` prefix
|
|
173
|
+
* @param patterns package-name globs, each optionally prefixed with `!`
|
|
174
|
+
* @returns path globs pointing at the project roots declaring a matching name
|
|
175
|
+
*/
|
|
176
|
+
async function resolveNamePatterns(patterns) {
|
|
177
|
+
if (patterns.length === 0) {
|
|
178
|
+
return [];
|
|
179
|
+
}
|
|
180
|
+
const manifests = await globby('**/package.json', WORKSPACE_GLOB_OPTIONS);
|
|
181
|
+
const names = new Map(manifests.map((path) => [posix.dirname(path), readPackageName(path)]));
|
|
182
|
+
return patterns.flatMap((pattern) => {
|
|
183
|
+
const [prefix, name] = splitNegation(pattern);
|
|
184
|
+
const isMatchingName = compileNameMatcher([name]);
|
|
185
|
+
return [...names]
|
|
186
|
+
.filter(([, declared]) => declared !== undefined && isMatchingName(declared))
|
|
187
|
+
.map(([directory]) => `${prefix}${directory}`);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* split a pattern into its negation prefix and the pattern it negates
|
|
192
|
+
* @param pattern a raw pattern, optionally prefixed with `!`
|
|
193
|
+
* @returns the `!` prefix (empty when the pattern selects) and the trimmed remainder
|
|
194
|
+
*/
|
|
195
|
+
function splitNegation(pattern) {
|
|
196
|
+
const isNegated = pattern.startsWith(NEGATION_PREFIX);
|
|
197
|
+
return [
|
|
198
|
+
isNegated ? NEGATION_PREFIX : '',
|
|
199
|
+
(isNegated ? pattern.slice(NEGATION_PREFIX.length) : pattern).trim(),
|
|
200
|
+
];
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* read the package name declared by a manifest
|
|
204
|
+
* @param path path to a package.json file
|
|
205
|
+
* @returns the declared name, or undefined when the manifest declares none
|
|
206
|
+
*/
|
|
207
|
+
function readPackageName(path) {
|
|
208
|
+
const { name } = JSON.parse(readFileSync(path, { encoding: 'utf8' }));
|
|
209
|
+
return name;
|
|
210
|
+
}
|
|
135
211
|
/**
|
|
136
212
|
* expand each entry by splitting on a delimiter and trimming the parts
|
|
137
213
|
* @param values raw flag values, each possibly containing the delimiter
|
|
@@ -158,4 +234,4 @@ function compileNameMatcher(patterns) {
|
|
|
158
234
|
});
|
|
159
235
|
return (name) => expressions.some((expression) => expression.test(name));
|
|
160
236
|
}
|
|
161
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
237
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50cnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZXhlY3V0YWJsZS9lbnRyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUNuRCxPQUFPLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRTlELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDaEMsT0FBTyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBRTFCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDdEMsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUM3QixPQUFPLEVBQUUsZUFBZSxFQUFFLGFBQWEsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQXVCekQsTUFBTSxzQkFBc0IsR0FBRyxHQUFHLENBQUM7QUFDbkMsTUFBTSxlQUFlLEdBQUcsR0FBRyxDQUFDO0FBQzVCLE1BQU0sc0JBQXNCLEdBQUc7SUFDN0IsU0FBUyxFQUFFLElBQUk7SUFDZixNQUFNLEVBQUUsQ0FBQyxvQkFBb0IsQ0FBQztDQUMvQixDQUFDO0FBRUYsTUFBTSxnQkFBZ0IsR0FHbEI7SUFDRixPQUFPLEVBQUUsV0FBVztJQUNwQixRQUFRLEVBQUUscURBQXFEO0lBQy9ELE9BQU8sRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQ2pCLEtBQUs7U0FDRixNQUFNLENBQUMsTUFBTSxFQUFFO1FBQ2QsSUFBSSxFQUFFLFFBQVE7UUFDZCxXQUFXLEVBQUUsMkNBQTJDO0tBQ3pELENBQUM7U0FDRCxNQUFNLENBQUMsVUFBVSxFQUFFO1FBQ2xCLElBQUksRUFBRSxRQUFRO1FBQ2QsS0FBSyxFQUFFLEdBQUc7UUFDVixLQUFLLEVBQUUsSUFBSTtRQUNYLE9BQU8sRUFBRSxDQUFDLEdBQUcsQ0FBQztR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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/executable/error.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/executable/error.ts"],"names":[],"mappings":"AASA;;;GAGG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ7D"}
|
package/lib/executable/error.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { warn } from 'node:console';
|
|
2
2
|
import createCallsiteRecord from 'callsite-record';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
|
+
const INDENT = ' ';
|
|
4
5
|
/**
|
|
5
6
|
* print error nicely on console
|
|
6
7
|
* @param error the error to be reported
|
|
@@ -8,21 +9,62 @@ import chalk from 'chalk';
|
|
|
8
9
|
export async function handleError(error) {
|
|
9
10
|
if (!process.stdout.isTTY) {
|
|
10
11
|
// don't print formatted error message if the process is not run on TTY
|
|
12
|
+
// NOTE: node already inspects both `cause` and `errors` when logging an error directly
|
|
11
13
|
warn(error);
|
|
12
14
|
}
|
|
13
15
|
else {
|
|
14
|
-
|
|
15
|
-
const type = chalk.red.bold(`[${error.name}]`);
|
|
16
|
-
const message = chalk.white.bold(error.message.trim());
|
|
17
|
-
warn(`${type} ${message}`);
|
|
18
|
-
// print the callsite record
|
|
19
|
-
const record = createCallsiteRecord({
|
|
20
|
-
forError: error,
|
|
21
|
-
});
|
|
22
|
-
if (record) {
|
|
23
|
-
warn();
|
|
24
|
-
warn(await record.render({}));
|
|
25
|
-
}
|
|
16
|
+
await printError(error, 0);
|
|
26
17
|
}
|
|
27
18
|
}
|
|
28
|
-
|
|
19
|
+
/**
|
|
20
|
+
* print an error together with every aggregated member and nested cause
|
|
21
|
+
* @param error the error to be reported
|
|
22
|
+
* @param depth the nesting level of the error, used for indentation
|
|
23
|
+
*/
|
|
24
|
+
async function printError(error, depth) {
|
|
25
|
+
const type = chalk.red.bold(`[${error.name}]`);
|
|
26
|
+
const message = chalk.white.bold(error.message.trim());
|
|
27
|
+
warn(`${INDENT.repeat(depth)}${type} ${message}`);
|
|
28
|
+
const children = error instanceof AggregateError
|
|
29
|
+
? error.errors
|
|
30
|
+
: error.cause instanceof Error
|
|
31
|
+
? [error.cause]
|
|
32
|
+
: [];
|
|
33
|
+
// NOTE: only a leaf carries the callsite the user cares about, as any wrapper points at presetter itself
|
|
34
|
+
if (children.length === 0) {
|
|
35
|
+
await printCallsiteRecord(error);
|
|
36
|
+
}
|
|
37
|
+
for (const child of children) {
|
|
38
|
+
await printError(child, depth + 1);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* print the source excerpt behind the error, if it can be rendered
|
|
43
|
+
* @param error the error to be reported
|
|
44
|
+
*/
|
|
45
|
+
async function printCallsiteRecord(error) {
|
|
46
|
+
const record = createCallsiteRecord({ forError: error });
|
|
47
|
+
if (!record) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const rendered = await renderCallsiteRecord(record);
|
|
51
|
+
if (rendered !== undefined) {
|
|
52
|
+
warn();
|
|
53
|
+
warn(rendered);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* render a callsite record, tolerating a source file the renderer cannot read
|
|
58
|
+
* @param record the callsite record to be rendered
|
|
59
|
+
* @returns the rendered excerpt, or undefined when it cannot be produced
|
|
60
|
+
*/
|
|
61
|
+
async function renderCallsiteRecord(record) {
|
|
62
|
+
try {
|
|
63
|
+
return await record.render({});
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// NOTE: the renderer must read the source behind the callsite, which isn't always possible (e.g. a jiti-transpiled path), and a missing excerpt must never mask the message
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZXhlY3V0YWJsZS9lcnJvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRXBDLE9BQU8sb0JBQW9CLE1BQU0saUJBQWlCLENBQUM7QUFDbkQsT0FBTyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBSTFCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQztBQUVwQjs7O0dBR0c7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLFdBQVcsQ0FBQyxLQUFZO0lBQzVDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzFCLHVFQUF1RTtRQUN2RSx1RkFBdUY7UUFDdkYsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2QsQ0FBQztTQUFNLENBQUM7UUFDTixNQUFNLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDN0IsQ0FBQztBQUNILENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsS0FBSyxVQUFVLFVBQVUsQ0FBQyxLQUFZLEVBQUUsS0FBYTtJQUNuRCxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDO0lBQy9DLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN2RCxJQUFJLENBQUMsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUksSUFBSSxPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBRWxELE1BQU0sUUFBUSxHQUNaLEtBQUssWUFBWSxjQUFjO1FBQzdCLENBQUMsQ0FBRSxLQUFLLENBQUMsTUFBa0I7UUFDM0IsQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLFlBQVksS0FBSztZQUM1QixDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDO1lBQ2YsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUVYLHlHQUF5RztJQUN6RyxJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDMUIsTUFBTSxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNuQyxDQUFDO0lBRUQsS0FBSyxNQUFNLEtBQUssSUFBSSxRQUFRLEVBQUUsQ0FBQztRQUM3QixNQUFNLFVBQVUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3JDLENBQUM7QUFDSCxDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsS0FBSyxVQUFVLG1CQUFtQixDQUFDLEtBQVk7SUFDN0MsTUFBTSxNQUFNLEdBQUcsb0JBQW9CLENBQUMsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztJQUV6RCxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDWixPQUFPO0lBQ1QsQ0FBQztJQUVELE1BQU0sUUFBUSxHQUFHLE1BQU0sb0JBQW9CLENBQUMsTUFBTSxDQUFDLENBQUM7SUFFcEQsSUFBSSxRQUFRLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDM0IsSUFBSSxFQUFFLENBQUM7UUFDUCxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDakIsQ0FBQztBQUNILENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsS0FBSyxVQUFVLG9CQUFvQixDQUNqQyxNQUFzQjtJQUV0QixJQUFJLENBQUM7UUFDSCxPQUFPLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsNEtBQTRLO1FBQzVLLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7QUFDSCxDQUFDIn0=
|
package/lib/executable/index.js
CHANGED
|
@@ -2,5 +2,9 @@
|
|
|
2
2
|
import { entry } from './entry.js';
|
|
3
3
|
import { handleError } from './error.js';
|
|
4
4
|
const [, , ...args] = process.argv;
|
|
5
|
-
entry(args).catch(
|
|
6
|
-
|
|
5
|
+
entry(args).catch(async (error) => {
|
|
6
|
+
await handleError(error);
|
|
7
|
+
// NOTE: report the failure to the shell, otherwise a broken bootstrap passes CI silently
|
|
8
|
+
process.exitCode = 1;
|
|
9
|
+
});
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZXhlY3V0YWJsZS9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxxQkFBcUI7QUFFckIsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUNoQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBRXRDLE1BQU0sQ0FBQyxFQUFFLEFBQUQsRUFBRyxHQUFHLElBQUksQ0FBQyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUM7QUFFbkMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsS0FBWSxFQUFFLEVBQUU7SUFDdkMsTUFBTSxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFekIseUZBQXlGO0lBQ3pGLE9BQU8sQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDO0FBQ3ZCLENBQUMsQ0FBQyxDQUFDIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/preset/config/resolve.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/preset/config/resolve.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAW/C;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAqB1E"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { basename } from 'node:path';
|
|
1
2
|
import { createJiti } from 'jiti';
|
|
2
|
-
import debug from '
|
|
3
|
+
import debug from '#debugger';
|
|
4
|
+
import { display } from '#utilities/display';
|
|
3
5
|
import { searchPresetterConfigs } from './search.js';
|
|
4
6
|
const jiti = createJiti(import.meta.url, {
|
|
5
7
|
moduleCache: false, // NOTE: disable module cache to fix a bug in jiti that importing the same file multiple times simtaneously would result in some of the imports resolved as undefined
|
|
@@ -16,12 +18,57 @@ const configs = {};
|
|
|
16
18
|
export async function resolvePresetterConfig(root) {
|
|
17
19
|
const configPaths = await searchPresetterConfigs(root);
|
|
18
20
|
if (configPaths.length === 0) {
|
|
19
|
-
throw new Error(
|
|
21
|
+
throw new Error(`no presetter configuration file found for ${root}`);
|
|
20
22
|
}
|
|
21
23
|
// NOTE: the priority is given to the configuration file closest to the project root, from mts, ts, mjs then js
|
|
22
24
|
const closestConfigPath = configPaths[0];
|
|
23
25
|
debug(`loading presetter configuration from ${closestConfigPath}`);
|
|
24
26
|
// NOTE: load the preset with import cache as a fix to a bug in jiti that importing the same file multiple times simtaneously would result in some of the imports resolved as undefined
|
|
25
|
-
return (configs[closestConfigPath] ??=
|
|
27
|
+
return (configs[closestConfigPath] ??= loadPresetterConfig(closestConfigPath).catch((error) => {
|
|
28
|
+
// NOTE: a rejection must never be memoized, otherwise every project sharing the configuration inherits a stale failure
|
|
29
|
+
delete configs[closestConfigPath];
|
|
30
|
+
throw error;
|
|
31
|
+
}));
|
|
26
32
|
}
|
|
27
|
-
|
|
33
|
+
/**
|
|
34
|
+
* load a presetter configuration file and verify that it exports a preset
|
|
35
|
+
* @param path the path to the presetter configuration file
|
|
36
|
+
* @returns the preset exported by the configuration file
|
|
37
|
+
*/
|
|
38
|
+
async function loadPresetterConfig(path) {
|
|
39
|
+
const content = await importDefault(path);
|
|
40
|
+
if (!isPreset(content)) {
|
|
41
|
+
throw new Error(`${basename(path)} at ${path} does not default-export a preset ` +
|
|
42
|
+
`(expected an object or function with an "id", received ${display(content)})`);
|
|
43
|
+
}
|
|
44
|
+
return content;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* import the default export of a configuration file, naming the file on failure
|
|
48
|
+
* @param path the path to the presetter configuration file
|
|
49
|
+
* @returns whatever the configuration file exports
|
|
50
|
+
*/
|
|
51
|
+
async function importDefault(path) {
|
|
52
|
+
try {
|
|
53
|
+
// NOTE: jiti falls back to the module namespace when the file has no default export, hence the validation in loadPresetterConfig
|
|
54
|
+
return await jiti.import(path, { default: true });
|
|
55
|
+
}
|
|
56
|
+
catch (cause) {
|
|
57
|
+
throw new Error(`failed to load the presetter configuration at ${path}`, {
|
|
58
|
+
cause,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* check whether a value loaded from a configuration file is a preset
|
|
64
|
+
* @param content the value exported by the configuration file
|
|
65
|
+
* @returns true if the value is an object or function carrying a string id
|
|
66
|
+
*/
|
|
67
|
+
function isPreset(content) {
|
|
68
|
+
if ((typeof content !== 'object' || content === null) &&
|
|
69
|
+
typeof content !== 'function') {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
return 'id' in content && typeof content.id === 'string';
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb2x2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wcmVzZXQvY29uZmlnL3Jlc29sdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUVyQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRWxDLE9BQU8sS0FBSyxNQUFNLFdBQVcsQ0FBQztBQUM5QixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFN0MsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sVUFBVSxDQUFDO0FBSWxELE1BQU0sSUFBSSxHQUFHLFVBQVUsQ0FBQyxPQUFPLElBQUksQ0FBQyxHQUFHLEVBQUU7SUFDdkMsV0FBVyxFQUFFLEtBQUssRUFBRSxxS0FBcUs7SUFDekwscUJBQXFCO0lBQ3JCLEtBQUssRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLFdBQVcsQ0FBQztJQUNqRCxtQkFBbUI7Q0FDcEIsQ0FBQyxDQUFDO0FBRUgsTUFBTSxPQUFPLEdBQW9DLEVBQUUsQ0FBQztBQUVwRDs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxzQkFBc0IsQ0FBQyxJQUFZO0lBQ3ZELE1BQU0sV0FBVyxHQUFHLE1BQU0sc0JBQXNCLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFdkQsSUFBSSxXQUFXLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQzdCLE1BQU0sSUFBSSxLQUFLLENBQUMsNkNBQTZDLElBQUksRUFBRSxDQUFDLENBQUM7SUFDdkUsQ0FBQztJQUVELCtHQUErRztJQUMvRyxNQUFNLGlCQUFpQixHQUFHLFdBQVcsQ0FBQyxDQUFDLENBQUUsQ0FBQztJQUUxQyxLQUFLLENBQUMsd0NBQXdDLGlCQUFpQixFQUFFLENBQUMsQ0FBQztJQUVuRSx1TEFBdUw7SUFDdkwsT0FBTyxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLG1CQUFtQixDQUN4RCxpQkFBaUIsQ0FDbEIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFZLEVBQUUsRUFBRTtRQUN2Qix1SEFBdUg7UUFDdkgsT0FBTyxPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUVsQyxNQUFNLEtBQUssQ0FBQztJQUNkLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDTixDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILEtBQUssVUFBVSxtQkFBbUIsQ0FBQyxJQUFZO0lBQzdDLE1BQU0sT0FBTyxHQUFHLE1BQU0sYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRTFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUN2QixNQUFNLElBQUksS0FBSyxDQUNiLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLElBQUksb0NBQW9DO1lBQzlELDBEQUEwRCxPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FDaEYsQ0FBQztJQUNKLENBQUM7SUFFRCxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILEtBQUssVUFBVSxhQUFhLENBQUMsSUFBWTtJQUN2QyxJQUFJLENBQUM7UUFDSCxpSUFBaUk7UUFDakksT0FBTyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQVUsSUFBSSxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7SUFDN0QsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixNQUFNLElBQUksS0FBSyxDQUFDLGlEQUFpRCxJQUFJLEVBQUUsRUFBRTtZQUN2RSxLQUFLO1NBQ04sQ0FBQyxDQUFDO0lBQ0wsQ0FBQztBQUNILENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxRQUFRLENBQUMsT0FBZ0I7SUFDaEMsSUFDRSxDQUFDLE9BQU8sT0FBTyxLQUFLLFFBQVEsSUFBSSxPQUFPLEtBQUssSUFBSSxDQUFDO1FBQ2pELE9BQU8sT0FBTyxLQUFLLFVBQVUsRUFDN0IsQ0FBQztRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELE9BQU8sSUFBSSxJQUFJLE9BQU8sSUFBSSxPQUFPLE9BQU8sQ0FBQyxFQUFFLEtBQUssUUFBUSxDQUFDO0FBQzNELENBQUMifQ==
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "presetter",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.1.0",
|
|
4
4
|
"description": "Make project configurations clean with presets",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"config",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"source-map-support": "^0.5.0",
|
|
58
58
|
"yargs": "^18.0.0",
|
|
59
59
|
"yargs-parser": "^22.0.0",
|
|
60
|
-
"@presetter/types": "9.
|
|
60
|
+
"@presetter/types": "9.1.0"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@types/debug": "^4.0.0",
|
|
@@ -65,9 +65,9 @@
|
|
|
65
65
|
"@types/node": "^24.0.0",
|
|
66
66
|
"@types/yargs": "^17.0.0",
|
|
67
67
|
"type-fest": "^5.0.0",
|
|
68
|
-
"@presetter/preset-
|
|
69
|
-
"@presetter/preset-
|
|
70
|
-
"@presetter/preset-
|
|
68
|
+
"@presetter/preset-essentials": "9.1.0",
|
|
69
|
+
"@presetter/preset-esm": "9.1.0",
|
|
70
|
+
"@presetter/preset-strict": "9.1.0"
|
|
71
71
|
},
|
|
72
72
|
"engines": {
|
|
73
73
|
"node": ">=20.0.0"
|