presetter 8.2.0 → 8.3.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 CHANGED
@@ -299,6 +299,46 @@ Presetter uses a sophisticated **two-pass resolution system** that makes configu
299
299
  - **Deep Merging**: Sophisticated algorithms handle complex inheritance
300
300
  - **Script Composition**: Local scripts merge with preset scripts intelligently
301
301
 
302
+ ### 🔧 Binary Path Resolution
303
+
304
+ When running tasks via `run`, `run-s`, or `run-p`, Presetter automatically prepends binary paths from preset packages to the PATH environment variable. This makes tools in each preset's `node_modules/.bin` directory available without additional configuration.
305
+
306
+ **How it works:**
307
+
308
+ - Direct preset binaries are checked first
309
+ - Extended preset binaries are checked next
310
+ - Finally, the existing PATH is checked
311
+
312
+ **Benefits:**
313
+
314
+ - No need to install shared dev tools at the repository root
315
+ - No need for pnpm's `shamefullyHoist: true` or `public-hoist-pattern` for every tool
316
+ - Preset dependencies are automatically available to templated scripts
317
+
318
+ **Limitation - Dynamic Imports:**
319
+
320
+ Libraries loaded via dynamic `import()` may fail because dynamic imports are resolved from the project root, not the preset. This affects libraries that are loaded at runtime rather than through direct imports.
321
+
322
+ **Notable example:** `@vitest/coverage-v8` - required by vitest when using v8 as the coverage engine.
323
+
324
+ **Workarounds:**
325
+
326
+ 1. **Install directly:** Add the library to your project's `package.json` (or monorepo root):
327
+
328
+ ```bash
329
+ npm install -D @vitest/coverage-v8
330
+ ```
331
+
332
+ 2. **Use pnpm hoisting:** Add the library to pnpm's `public-hoist-pattern` in `pnpm-workspace.yaml`:
333
+
334
+ ```yaml
335
+ packages:
336
+ - 'packages/*'
337
+ settings:
338
+ public-hoist-pattern:
339
+ - '@vitest/coverage-v8'
340
+ ```
341
+
302
342
  ---
303
343
 
304
344
  ## 🛠️ Advanced Usage
@@ -443,6 +483,10 @@ Absolutely! Presets are just npm packages that export configuration templates. S
443
483
 
444
484
  Yes! Presetter supports monorepo setups and can bootstrap multiple projects with glob patterns. Use [presetter-preset-monorepo](https://github.com/alvis/presetter/blob/master/packages/preset-monorepo) for monorepo-specific configurations.
445
485
 
486
+ ### Why do some dynamically imported libraries fail to resolve?
487
+
488
+ While Presetter makes preset tools available via PATH, libraries loaded through dynamic `import()` (like `@vitest/coverage-v8`) resolve from your project root, not the preset. Install such libraries directly at your project root or add them to pnpm's `public-hoist-pattern` in `pnpm-workspace.yaml`.
489
+
446
490
  ---
447
491
 
448
492
  ## 🤝 Contributing
@@ -0,0 +1,92 @@
1
+ /** represents a parsed call expression from command text */
2
+ export interface ParsedCallExpr {
3
+ /** the command name (e.g., "run") */
4
+ command: string;
5
+ /** positional arguments before "--" */
6
+ args: string[];
7
+ /** extra arguments after "--" */
8
+ extraArgs: string[];
9
+ }
10
+ /** represents a run command match with its position */
11
+ export interface RunMatch {
12
+ /** the matched text */
13
+ match: string;
14
+ /** start offset in source */
15
+ start: number;
16
+ /** end offset in source */
17
+ end: number;
18
+ }
19
+ /** parsed command structure */
20
+ export type ParsedCommand = ParsedSimpleCommand | ParsedBinaryCmd | ParsedSubshell | ParsedBlock;
21
+ /** simple command (e.g., `run build`, `echo test`) */
22
+ export interface ParsedSimpleCommand {
23
+ type: 'CallExpr';
24
+ /** command name (first word) */
25
+ command: string;
26
+ /** arguments after command name */
27
+ args: string[];
28
+ /** extra arguments after "--" */
29
+ extraArgs: string[];
30
+ /** start offset in original source */
31
+ start: number;
32
+ /** end offset in original source */
33
+ end: number;
34
+ }
35
+ /** binary operator type */
36
+ type BinaryOperator = '&&' | '||' | '|';
37
+ /** binary command (e.g., `cmd1 && cmd2`) */
38
+ export interface ParsedBinaryCmd {
39
+ type: 'BinaryCmd';
40
+ /** operator: && || | */
41
+ op: BinaryOperator;
42
+ /** left side command */
43
+ left: ParsedCommand;
44
+ /** right side command */
45
+ right: ParsedCommand;
46
+ /** start offset in original source */
47
+ start: number;
48
+ /** end offset in original source */
49
+ end: number;
50
+ }
51
+ /** subshell (e.g., `(cmd1 && cmd2)`) */
52
+ export interface ParsedSubshell {
53
+ type: 'Subshell';
54
+ /** inner command */
55
+ body: ParsedCommand;
56
+ /** start offset in original source */
57
+ start: number;
58
+ /** end offset in original source */
59
+ end: number;
60
+ }
61
+ /** block (e.g., `{ cmd1; cmd2; }`) */
62
+ export interface ParsedBlock {
63
+ type: 'Block';
64
+ /** inner command */
65
+ body: ParsedCommand;
66
+ /** start offset in original source */
67
+ start: number;
68
+ /** end offset in original source */
69
+ end: number;
70
+ }
71
+ /**
72
+ * parses command text into ParsedCallExpr structure (pure)
73
+ * @param cmdText the command text to parse
74
+ * @returns the parsed call expression
75
+ */
76
+ export declare const parseCommandText: (cmdText: string) => Readonly<ParsedCallExpr>;
77
+ /**
78
+ * parses command text into structured form
79
+ * @param text command text to parse
80
+ * @param baseOffset offset in original source
81
+ * @returns parsed command structure
82
+ */
83
+ export declare const parseCommandStructure: (text: string, baseOffset: number) => ParsedCommand;
84
+ /**
85
+ * finds all run commands in parsed structure
86
+ * @param cmd parsed command to search
87
+ * @param source original source string
88
+ * @returns array of run command matches
89
+ */
90
+ export declare const findRunInParsed: (cmd: ParsedCommand, source: string) => RunMatch[];
91
+ export {};
92
+ //# sourceMappingURL=parsing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsing.d.ts","sourceRoot":"","sources":["../src/parsing.ts"],"names":[],"mappings":"AAEA,4DAA4D;AAC5D,MAAM,WAAW,cAAc;IAC7B,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,iCAAiC;IACjC,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,uDAAuD;AACvD,MAAM,WAAW,QAAQ;IACvB,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,+BAA+B;AAC/B,MAAM,MAAM,aAAa,GACrB,mBAAmB,GACnB,eAAe,GACf,cAAc,GACd,WAAW,CAAC;AAEhB,sDAAsD;AACtD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,UAAU,CAAC;IACjB,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,iCAAiC;IACjC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,2BAA2B;AAC3B,KAAK,cAAc,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,CAAC;AAExC,4CAA4C;AAC5C,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,WAAW,CAAC;IAClB,wBAAwB;IACxB,EAAE,EAAE,cAAc,CAAC;IACnB,wBAAwB;IACxB,IAAI,EAAE,aAAa,CAAC;IACpB,yBAAyB;IACzB,KAAK,EAAE,aAAa,CAAC;IACrB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wCAAwC;AACxC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,UAAU,CAAC;IACjB,oBAAoB;IACpB,IAAI,EAAE,aAAa,CAAC;IACpB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,sCAAsC;AACtC,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,oBAAoB;IACpB,IAAI,EAAE,aAAa,CAAC;IACpB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;CACb;AA2ID;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAS,MAAM,KAAG,QAAQ,CAAC,cAAc,CAWzE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAChC,MAAM,MAAM,EACZ,YAAY,MAAM,KACjB,aA4DF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAC1B,KAAK,aAAa,EAClB,QAAQ,MAAM,KACb,QAAQ,EAkCV,CAAC"}
package/lib/parsing.js ADDED
@@ -0,0 +1,207 @@
1
+ import parseArgs from 'yargs-parser';
2
+ /**
3
+ * updates depth counters based on character
4
+ * @param char the character
5
+ * @param parenDepth current parenthesis depth
6
+ * @param braceDepth current brace depth
7
+ * @returns updated depths
8
+ */
9
+ const updateDepths = (char, parenDepth, braceDepth) => {
10
+ let newParenDepth = parenDepth;
11
+ let newBraceDepth = braceDepth;
12
+ if (char === '(') {
13
+ newParenDepth++;
14
+ }
15
+ else if (char === ')') {
16
+ newParenDepth--;
17
+ }
18
+ else if (char === '{') {
19
+ newBraceDepth++;
20
+ }
21
+ else if (char === '}') {
22
+ newBraceDepth--;
23
+ }
24
+ return [newParenDepth, newBraceDepth];
25
+ };
26
+ /**
27
+ * checks if a character ends a quote
28
+ * @param char the character
29
+ * @param inSingleQuote whether in single quote
30
+ * @param inDoubleQuote whether in double quote
31
+ * @returns updated quote states
32
+ */
33
+ const updateQuotes = (char, inSingleQuote, inDoubleQuote) => {
34
+ let newSingleQuote = inSingleQuote;
35
+ let newDoubleQuote = inDoubleQuote;
36
+ if (char === "'" && !inDoubleQuote) {
37
+ newSingleQuote = !inSingleQuote;
38
+ }
39
+ else if (char === '"' && !inSingleQuote) {
40
+ newDoubleQuote = !inDoubleQuote;
41
+ }
42
+ return [newSingleQuote, newDoubleQuote];
43
+ };
44
+ /**
45
+ * checks for binary operators at current position
46
+ * @param char current character
47
+ * @param nextChar next character
48
+ * @param parenDepth parenthesis depth
49
+ * @param braceDepth brace depth
50
+ * @returns operator match or null
51
+ */
52
+ const checkBinaryOp = (char, nextChar, parenDepth, braceDepth) => {
53
+ if (parenDepth !== 0 || braceDepth !== 0) {
54
+ return null;
55
+ }
56
+ if (char === '&' && nextChar === '&') {
57
+ return { op: '&&' };
58
+ }
59
+ if (char === '|' && nextChar === '|') {
60
+ return { op: '||' };
61
+ }
62
+ if (char === '|' && nextChar !== '|') {
63
+ return { op: '|' };
64
+ }
65
+ return null;
66
+ };
67
+ /**
68
+ * finds the first top-level binary operator in command text
69
+ * @param text command text to search
70
+ * @returns operator match or null if none found
71
+ */
72
+ const findTopLevelOperator = (text) => {
73
+ let parenDepth = 0;
74
+ let braceDepth = 0;
75
+ let inSingleQuote = false;
76
+ let inDoubleQuote = false;
77
+ let escaped = false;
78
+ for (let i = 0; i < text.length; i++) {
79
+ const char = text[i];
80
+ const nextChar = text[i + 1];
81
+ if (escaped) {
82
+ escaped = false;
83
+ continue;
84
+ }
85
+ if (char === '\\' && !inSingleQuote) {
86
+ escaped = true;
87
+ continue;
88
+ }
89
+ [inSingleQuote, inDoubleQuote] = updateQuotes(char, inSingleQuote, inDoubleQuote);
90
+ if (inSingleQuote || inDoubleQuote) {
91
+ continue;
92
+ }
93
+ [parenDepth, braceDepth] = updateDepths(char, parenDepth, braceDepth);
94
+ const opMatch = checkBinaryOp(char, nextChar, parenDepth, braceDepth);
95
+ if (opMatch) {
96
+ return { ...opMatch, index: i };
97
+ }
98
+ }
99
+ return null;
100
+ };
101
+ /**
102
+ * parses command text into ParsedCallExpr structure (pure)
103
+ * @param cmdText the command text to parse
104
+ * @returns the parsed call expression
105
+ */
106
+ export const parseCommandText = (cmdText) => {
107
+ const arg = parseArgs(cmdText, {
108
+ configuration: { 'populate--': true, 'unknown-options-as-args': true },
109
+ });
110
+ const parts = arg._;
111
+ const command = parts[0] ?? '';
112
+ const args = parts.slice(1);
113
+ const extraArgs = (arg['--'] ?? []);
114
+ return { command, args, extraArgs };
115
+ };
116
+ /**
117
+ * parses command text into structured form
118
+ * @param text command text to parse
119
+ * @param baseOffset offset in original source
120
+ * @returns parsed command structure
121
+ */
122
+ export const parseCommandStructure = (text, baseOffset) => {
123
+ const trimmed = text.trim();
124
+ const trimOffset = text.indexOf(trimmed);
125
+ const start = baseOffset + trimOffset;
126
+ const end = start + trimmed.length;
127
+ // check for Subshell: (...)
128
+ if (trimmed.startsWith('(') && trimmed.endsWith(')')) {
129
+ const inner = trimmed.slice(1, -1);
130
+ return {
131
+ type: 'Subshell',
132
+ body: parseCommandStructure(inner, start + 1),
133
+ start,
134
+ end,
135
+ };
136
+ }
137
+ // check for Block: { ... }
138
+ if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
139
+ const inner = trimmed.slice(1, -1);
140
+ return {
141
+ type: 'Block',
142
+ body: parseCommandStructure(inner, start + 1),
143
+ start,
144
+ end,
145
+ };
146
+ }
147
+ // check for BinaryCmd: cmd1 && cmd2
148
+ const opMatch = findTopLevelOperator(trimmed);
149
+ if (opMatch) {
150
+ const leftText = trimmed.slice(0, opMatch.index);
151
+ const rightText = trimmed.slice(opMatch.index + opMatch.op.length);
152
+ return {
153
+ type: 'BinaryCmd',
154
+ op: opMatch.op,
155
+ left: parseCommandStructure(leftText, start),
156
+ right: parseCommandStructure(rightText, start + opMatch.index + opMatch.op.length),
157
+ start,
158
+ end,
159
+ };
160
+ }
161
+ // otherwise it's a CallExpr
162
+ const parsed = parseCommandText(trimmed);
163
+ return {
164
+ type: 'CallExpr',
165
+ command: parsed.command,
166
+ args: parsed.args,
167
+ extraArgs: parsed.extraArgs,
168
+ start,
169
+ end,
170
+ };
171
+ };
172
+ /**
173
+ * finds all run commands in parsed structure
174
+ * @param cmd parsed command to search
175
+ * @param source original source string
176
+ * @returns array of run command matches
177
+ */
178
+ export const findRunInParsed = (cmd, source) => {
179
+ const matches = [];
180
+ const visit = (node) => {
181
+ switch (node.type) {
182
+ case 'CallExpr':
183
+ // check if command is 'run' with at least one task
184
+ if (node.command === 'run' && node.args.length > 0) {
185
+ matches.push({
186
+ match: source.slice(node.start, node.end),
187
+ start: node.start,
188
+ end: node.end,
189
+ });
190
+ }
191
+ break;
192
+ case 'BinaryCmd':
193
+ visit(node.left);
194
+ visit(node.right);
195
+ break;
196
+ case 'Subshell':
197
+ case 'Block':
198
+ visit(node.body);
199
+ break;
200
+ default:
201
+ break;
202
+ }
203
+ };
204
+ visit(cmd);
205
+ return matches;
206
+ };
207
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2luZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9wYXJzaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sU0FBUyxNQUFNLGNBQWMsQ0FBQztBQTRGckM7Ozs7OztHQU1HO0FBQ0gsTUFBTSxZQUFZLEdBQUcsQ0FDbkIsSUFBWSxFQUNaLFVBQWtCLEVBQ2xCLFVBQWtCLEVBQ0EsRUFBRTtJQUNwQixJQUFJLGFBQWEsR0FBRyxVQUFVLENBQUM7SUFDL0IsSUFBSSxhQUFhLEdBQUcsVUFBVSxDQUFDO0lBRS9CLElBQUksSUFBSSxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQ2pCLGFBQWEsRUFBRSxDQUFDO0lBQ2xCLENBQUM7U0FBTSxJQUFJLElBQUksS0FBSyxHQUFHLEVBQUUsQ0FBQztRQUN4QixhQUFhLEVBQUUsQ0FBQztJQUNsQixDQUFDO1NBQU0sSUFBSSxJQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7UUFDeEIsYUFBYSxFQUFFLENBQUM7SUFDbEIsQ0FBQztTQUFNLElBQUksSUFBSSxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQ3hCLGFBQWEsRUFBRSxDQUFDO0lBQ2xCLENBQUM7SUFFRCxPQUFPLENBQUMsYUFBYSxFQUFFLGFBQWEsQ0FBQyxDQUFDO0FBQ3hDLENBQUMsQ0FBQztBQUVGOzs7Ozs7R0FNRztBQUNILE1BQU0sWUFBWSxHQUFHLENBQ25CLElBQVksRUFDWixhQUFzQixFQUN0QixhQUFzQixFQUNGLEVBQUU7SUFDdEIsSUFBSSxjQUFjLEdBQUcsYUFBYSxDQUFDO0lBQ25DLElBQUksY0FBYyxHQUFHLGFBQWEsQ0FBQztJQUVuQyxJQUFJLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUNuQyxjQUFjLEdBQUcsQ0FBQyxhQUFhLENBQUM7SUFDbEMsQ0FBQztTQUFNLElBQUksSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQzFDLGNBQWMsR0FBRyxDQUFDLGFBQWEsQ0FBQztJQUNsQyxDQUFDO0lBRUQsT0FBTyxDQUFDLGNBQWMsRUFBRSxjQUFjLENBQUMsQ0FBQztBQUMxQyxDQUFDLENBQUM7QUFFRjs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxhQUFhLEdBQUcsQ0FDcEIsSUFBWSxFQUNaLFFBQTRCLEVBQzVCLFVBQWtCLEVBQ2xCLFVBQWtCLEVBQ2EsRUFBRTtJQUNqQyxJQUFJLFVBQVUsS0FBSyxDQUFDLElBQUksVUFBVSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3pDLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUNELElBQUksSUFBSSxLQUFLLEdBQUcsSUFBSSxRQUFRLEtBQUssR0FBRyxFQUFFLENBQUM7UUFDckMsT0FBTyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUN0QixDQUFDO0lBQ0QsSUFBSSxJQUFJLEtBQUssR0FBRyxJQUFJLFFBQVEsS0FBSyxHQUFHLEVBQUUsQ0FBQztRQUNyQyxPQUFPLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDO0lBQ3RCLENBQUM7SUFDRCxJQUFJLElBQUksS0FBSyxHQUFHLElBQUksUUFBUSxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQ3JDLE9BQU8sRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLENBQUM7SUFDckIsQ0FBQztJQUVELE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQyxDQUFDO0FBRUY7Ozs7R0FJRztBQUNILE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxJQUFZLEVBQXdCLEVBQUU7SUFDbEUsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO0lBQ25CLElBQUksVUFBVSxHQUFHLENBQUMsQ0FBQztJQUNuQixJQUFJLGFBQWEsR0FBRyxLQUFLLENBQUM7SUFDMUIsSUFBSSxhQUFhLEdBQUcsS0FBSyxDQUFDO0lBQzFCLElBQUksT0FBTyxHQUFHLEtBQUssQ0FBQztJQUVwQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ3JDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNyQixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBRTdCLElBQUksT0FBTyxFQUFFLENBQUM7WUFDWixPQUFPLEdBQUcsS0FBSyxDQUFDO1lBQ2hCLFNBQVM7UUFDWCxDQUFDO1FBRUQsSUFBSSxJQUFJLEtBQUssSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDcEMsT0FBTyxHQUFHLElBQUksQ0FBQztZQUNmLFNBQVM7UUFDWCxDQUFDO1FBRUQsQ0FBQyxhQUFhLEVBQUUsYUFBYSxDQUFDLEdBQUcsWUFBWSxDQUMzQyxJQUFJLEVBQ0osYUFBYSxFQUNiLGFBQWEsQ0FDZCxDQUFDO1FBRUYsSUFBSSxhQUFhLElBQUksYUFBYSxFQUFFLENBQUM7WUFDbkMsU0FBUztRQUNYLENBQUM7UUFFRCxDQUFDLFVBQVUsRUFBRSxVQUFVLENBQUMsR0FBRyxZQUFZLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUV0RSxNQUFNLE9BQU8sR0FBRyxhQUFhLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDdEUsSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUNaLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUM7UUFDbEMsQ0FBQztJQUNILENBQUM7SUFFRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUMsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLE9BQWUsRUFBNEIsRUFBRTtJQUM1RSxNQUFNLEdBQUcsR0FBRyxTQUFTLENBQUMsT0FBTyxFQUFFO1FBQzdCLGFBQWEsRUFBRSxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUseUJBQXlCLEVBQUUsSUFBSSxFQUFFO0tBQ3ZFLENBQUMsQ0FBQztJQUVILE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxDQUFhLENBQUM7SUFDaEMsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUMvQixNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVCLE1BQU0sU0FBUyxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBYSxDQUFDO0lBRWhELE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxDQUFDO0FBQ3RDLENBQUMsQ0FBQztBQUVGOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQUcsQ0FDbkMsSUFBWSxFQUNaLFVBQWtCLEVBQ0gsRUFBRTtJQUNqQixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDNUIsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN6QyxNQUFNLEtBQUssR0FBRyxVQUFVLEdBQUcsVUFBVSxDQUFDO0lBQ3RDLE1BQU0sR0FBRyxHQUFHLEtBQUssR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDO0lBRW5DLDRCQUE0QjtJQUM1QixJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3JELE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFbkMsT0FBTztZQUNMLElBQUksRUFBRSxVQUFVO1lBQ2hCLElBQUksRUFBRSxxQkFBcUIsQ0FBQyxLQUFLLEVBQUUsS0FBSyxHQUFHLENBQUMsQ0FBQztZQUM3QyxLQUFLO1lBQ0wsR0FBRztTQUNKLENBQUM7SUFDSixDQUFDO0lBRUQsMkJBQTJCO0lBQzNCLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDckQsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUVuQyxPQUFPO1lBQ0wsSUFBSSxFQUFFLE9BQU87WUFDYixJQUFJLEVBQUUscUJBQXFCLENBQUMsS0FBSyxFQUFFLEtBQUssR0FBRyxDQUFDLENBQUM7WUFDN0MsS0FBSztZQUNMLEdBQUc7U0FDSixDQUFDO0lBQ0osQ0FBQztJQUVELG9DQUFvQztJQUNwQyxNQUFNLE9BQU8sR0FBRyxvQkFBb0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM5QyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQ1osTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pELE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRW5FLE9BQU87WUFDTCxJQUFJLEVBQUUsV0FBVztZQUNqQixFQUFFLEVBQUUsT0FBTyxDQUFDLEVBQUU7WUFDZCxJQUFJLEVBQUUscUJBQXFCLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQztZQUM1QyxLQUFLLEVBQUUscUJBQXFCLENBQzFCLFNBQVMsRUFDVCxLQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FDMUM7WUFDRCxLQUFLO1lBQ0wsR0FBRztTQUNKLENBQUM7SUFDSixDQUFDO0lBRUQsNEJBQTRCO0lBQzVCLE1BQU0sTUFBTSxHQUFHLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBRXpDLE9BQU87UUFDTCxJQUFJLEVBQUUsVUFBVTtRQUNoQixPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU87UUFDdkIsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJO1FBQ2pCLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUztRQUMzQixLQUFLO1FBQ0wsR0FBRztLQUNKLENBQUM7QUFDSixDQUFDLENBQUM7QUFFRjs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBRyxDQUM3QixHQUFrQixFQUNsQixNQUFjLEVBQ0YsRUFBRTtJQUNkLE1BQU0sT0FBTyxHQUFlLEVBQUUsQ0FBQztJQUUvQixNQUFNLEtBQUssR0FBRyxDQUFDLElBQW1CLEVBQVEsRUFBRTtRQUMxQyxRQUFRLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNsQixLQUFLLFVBQVU7Z0JBQ2IsbURBQW1EO2dCQUNuRCxJQUFJLElBQUksQ0FBQyxPQUFPLEtBQUssS0FBSyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUNuRCxPQUFPLENBQUMsSUFBSSxDQUFDO3dCQUNYLEtBQUssRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQzt3QkFDekMsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLO3dCQUNqQixHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUc7cUJBQ2QsQ0FBQyxDQUFDO2dCQUNMLENBQUM7Z0JBQ0QsTUFBTTtZQUVSLEtBQUssV0FBVztnQkFDZCxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUNqQixLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNsQixNQUFNO1lBRVIsS0FBSyxVQUFVLENBQUM7WUFDaEIsS0FBSyxPQUFPO2dCQUNWLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ2pCLE1BQU07WUFFUjtnQkFDRSxNQUFNO1FBQ1YsQ0FBQztJQUNILENBQUMsQ0FBQztJQUVGLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUVYLE9BQU8sT0FBTyxDQUFDO0FBQ2pCLENBQUMsQ0FBQyJ9
@@ -1,6 +1,7 @@
1
1
  export * from './asset.js';
2
2
  export * from './object.js';
3
3
  export * from './preset.js';
4
+ export * from './roots.js';
4
5
  export * from './script.js';
5
6
  export * from './variable.js';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/preset/resolution/index.ts"],"names":[],"mappings":"AAEA,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/preset/resolution/index.ts"],"names":[],"mappings":"AAEA,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC"}
@@ -2,6 +2,7 @@
2
2
  export * from './asset.js';
3
3
  export * from './object.js';
4
4
  export * from './preset.js';
5
+ export * from './roots.js';
5
6
  export * from './script.js';
6
7
  export * from './variable.js';
7
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcHJlc2V0L3Jlc29sdXRpb24vaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEscUJBQXFCO0FBRXJCLGNBQWMsU0FBUyxDQUFDO0FBQ3hCLGNBQWMsVUFBVSxDQUFDO0FBQ3pCLGNBQWMsVUFBVSxDQUFDO0FBQ3pCLGNBQWMsVUFBVSxDQUFDO0FBQ3pCLGNBQWMsWUFBWSxDQUFDIn0=
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcHJlc2V0L3Jlc29sdXRpb24vaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEscUJBQXFCO0FBRXJCLGNBQWMsU0FBUyxDQUFDO0FBQ3hCLGNBQWMsVUFBVSxDQUFDO0FBQ3pCLGNBQWMsVUFBVSxDQUFDO0FBQ3pCLGNBQWMsU0FBUyxDQUFDO0FBQ3hCLGNBQWMsVUFBVSxDQUFDO0FBQ3pCLGNBQWMsWUFBWSxDQUFDIn0=
@@ -0,0 +1,15 @@
1
+ import type { PresetNode } from 'presetter-types';
2
+ /**
3
+ * recursively extracts all preset root paths from a preset node tree (pure function)
4
+ *
5
+ * Order: closest to consumer first, then child presets
6
+ * Example: consumer -> preset-esm -> preset-essentials
7
+ * Returns: [esm-root, essentials-root]
8
+ *
9
+ * This ensures the direct preset's binaries have highest PATH priority,
10
+ * allowing more specific presets to override base preset binaries.
11
+ * @param node the root preset node to traverse
12
+ * @returns array of unique preset root paths, closest to consumer first
13
+ */
14
+ export declare const extractPresetRoots: (node: PresetNode) => readonly string[];
15
+ //# sourceMappingURL=roots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roots.d.ts","sourceRoot":"","sources":["../../../src/preset/resolution/roots.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kBAAkB,GAAI,MAAM,UAAU,KAAG,SAAS,MAAM,EAYpE,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * recursively extracts all preset root paths from a preset node tree (pure function)
3
+ *
4
+ * Order: closest to consumer first, then child presets
5
+ * Example: consumer -> preset-esm -> preset-essentials
6
+ * Returns: [esm-root, essentials-root]
7
+ *
8
+ * This ensures the direct preset's binaries have highest PATH priority,
9
+ * allowing more specific presets to override base preset binaries.
10
+ * @param node the root preset node to traverse
11
+ * @returns array of unique preset root paths, closest to consumer first
12
+ */
13
+ export const extractPresetRoots = (node) => {
14
+ const collectRoots = (current) => {
15
+ // add THIS node's root first (closer to consumer, higher priority)
16
+ const thisRoot = current.definition.root ? [current.definition.root] : [];
17
+ // then collect extended preset roots (further from consumer, lower priority)
18
+ const childRoots = current.nodes.flatMap(collectRoots);
19
+ return [...thisRoot, ...childRoots];
20
+ };
21
+ // deduplicate while preserving priority order (first occurrence wins)
22
+ return [...new Set(collectRoots(node))];
23
+ };
24
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm9vdHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcHJlc2V0L3Jlc29sdXRpb24vcm9vdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUE7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLElBQWdCLEVBQXFCLEVBQUU7SUFDeEUsTUFBTSxZQUFZLEdBQUcsQ0FBQyxPQUFtQixFQUFxQixFQUFFO1FBQzlELG1FQUFtRTtRQUNuRSxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDMUUsNkVBQTZFO1FBQzdFLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBRXZELE9BQU8sQ0FBQyxHQUFHLFFBQVEsRUFBRSxHQUFHLFVBQVUsQ0FBQyxDQUFDO0lBQ3RDLENBQUMsQ0FBQztJQUVGLHNFQUFzRTtJQUN0RSxPQUFPLENBQUMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQzFDLENBQUMsQ0FBQyJ9
@@ -5,5 +5,8 @@ import type { PresetNode, ProjectContext, Scripts } from 'presetter-types';
5
5
  * @param context the context in which the node is being resolved
6
6
  * @returns a promise that resolves to the RESOLVED scripts
7
7
  */
8
- export declare function resolveScripts(node: PresetNode, context: ProjectContext): Promise<Scripts>;
8
+ export declare function resolveScripts(node: PresetNode, context: ProjectContext): Promise<{
9
+ paths: string[];
10
+ scripts: Scripts;
11
+ }>;
9
12
  //# sourceMappingURL=script.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"script.d.ts","sourceRoot":"","sources":["../../../src/preset/resolution/script.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE3E;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,OAAO,CAAC,CAoClB"}
1
+ {"version":3,"file":"script.d.ts","sourceRoot":"","sources":["../../../src/preset/resolution/script.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE3E;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CA4ChD"}
@@ -1,6 +1,8 @@
1
+ import { resolve } from 'node:path';
1
2
  import { substitute } from '../../template/index.js';
2
3
  import { resolveNodeContent } from './content.js';
3
4
  import Debug from './debugger.js';
5
+ import { extractPresetRoots } from './roots.js';
4
6
  import { resolveVariables } from './variable.js';
5
7
  /**
6
8
  * resolves all scripts for a given preset node
@@ -34,6 +36,9 @@ export async function resolveScripts(node, context) {
34
36
  select: ({ override }) => override?.scripts,
35
37
  })) ?? {};
36
38
  debug('RESOLVED SCRIPTS (FINAL PASS)\n%O', final);
37
- return substitute(final, variables);
39
+ const presetRoots = extractPresetRoots(node);
40
+ const paths = presetRoots.map((path) => resolve(path, 'node_modules', '.bin'));
41
+ debug('RESOLVED PATHS\n%O', paths);
42
+ return { paths, scripts: substitute(final, variables) };
38
43
  }
39
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NyaXB0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3ByZXNldC9yZXNvbHV0aW9uL3NjcmlwdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFNUMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQy9DLE9BQU8sS0FBSyxNQUFNLFlBQVksQ0FBQztBQUMvQixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFJOUM7Ozs7O0dBS0c7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGNBQWMsQ0FDbEMsSUFBZ0IsRUFDaEIsT0FBdUI7SUFFdkIsTUFBTSxJQUFJLEdBQUcsU0FBUyxDQUFDO0lBQ3ZCLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFakMsaUNBQWlDO0lBQ2pDLE1BQU0sU0FBUyxHQUFHLE1BQU0sZ0JBQWdCLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBRXhELEtBQUssQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDO0lBRTFDLDJDQUEyQztJQUMzQyxNQUFNLE9BQU8sR0FBRyxNQUFNLGtCQUFrQixDQUFDO1FBQ3ZDLElBQUk7UUFDSixJQUFJO1FBQ0osT0FBTztRQUNQLFNBQVM7UUFDVCxNQUFNLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsQ0FBQyxPQUFPO0tBQ2pDLENBQUMsQ0FBQztJQUVILEtBQUssQ0FBQyxxQ0FBcUMsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUV0RCxLQUFLLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztJQUV4QyxnRUFBZ0U7SUFDaEUsTUFBTSxLQUFLLEdBQ1QsQ0FBQyxNQUFNLGtCQUFrQixDQUFDO1FBQ3hCLElBQUk7UUFDSixJQUFJO1FBQ0osT0FBTztRQUNQLE9BQU87UUFDUCxTQUFTO1FBQ1QsTUFBTSxFQUFFLENBQUMsRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLENBQUMsUUFBUSxFQUFFLE9BQU87S0FDNUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO0lBRVosS0FBSyxDQUFDLG1DQUFtQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBRWxELE9BQU8sVUFBVSxDQUFDLEtBQUssRUFBRSxTQUFTLENBQUMsQ0FBQztBQUN0QyxDQUFDIn0=
44
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NyaXB0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3ByZXNldC9yZXNvbHV0aW9uL3NjcmlwdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRXBDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUU1QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDL0MsT0FBTyxLQUFLLE1BQU0sWUFBWSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUM3QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFJOUM7Ozs7O0dBS0c7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGNBQWMsQ0FDbEMsSUFBZ0IsRUFDaEIsT0FBdUI7SUFFdkIsTUFBTSxJQUFJLEdBQUcsU0FBUyxDQUFDO0lBQ3ZCLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFakMsaUNBQWlDO0lBQ2pDLE1BQU0sU0FBUyxHQUFHLE1BQU0sZ0JBQWdCLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBRXhELEtBQUssQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDO0lBRTFDLDJDQUEyQztJQUMzQyxNQUFNLE9BQU8sR0FBRyxNQUFNLGtCQUFrQixDQUFDO1FBQ3ZDLElBQUk7UUFDSixJQUFJO1FBQ0osT0FBTztRQUNQLFNBQVM7UUFDVCxNQUFNLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsQ0FBQyxPQUFPO0tBQ2pDLENBQUMsQ0FBQztJQUVILEtBQUssQ0FBQyxxQ0FBcUMsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUV0RCxLQUFLLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztJQUV4QyxnRUFBZ0U7SUFDaEUsTUFBTSxLQUFLLEdBQ1QsQ0FBQyxNQUFNLGtCQUFrQixDQUFDO1FBQ3hCLElBQUk7UUFDSixJQUFJO1FBQ0osT0FBTztRQUNQLE9BQU87UUFDUCxTQUFTO1FBQ1QsTUFBTSxFQUFFLENBQUMsRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLENBQUMsUUFBUSxFQUFFLE9BQU87S0FDNUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO0lBRVosS0FBSyxDQUFDLG1DQUFtQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBRWxELE1BQU0sV0FBVyxHQUFHLGtCQUFrQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBRTdDLE1BQU0sS0FBSyxHQUFHLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUNyQyxPQUFPLENBQUMsSUFBSSxFQUFFLGNBQWMsRUFBRSxNQUFNLENBQUMsQ0FDdEMsQ0FBQztJQUVGLEtBQUssQ0FBQyxvQkFBb0IsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUVuQyxPQUFPLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxVQUFVLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxFQUFFLENBQUM7QUFDMUQsQ0FBQyJ9
@@ -1,6 +1,10 @@
1
+ import type { Script } from '#scripts';
1
2
  /**
2
- * get the merged scripts templates
3
+ * get the merged scripts templates (pure function)
3
4
  * @returns scripts template
4
5
  */
5
- export declare function getScripts(): Promise<Record<string, string>>;
6
+ export declare const getScripts: () => Promise<{
7
+ paths: string[];
8
+ scripts: Script;
9
+ }>;
6
10
  //# sourceMappingURL=scripts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scripts.d.ts","sourceRoot":"","sources":["../../src/preset/scripts.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAOlE"}
1
+ {"version":3,"file":"scripts.d.ts","sourceRoot":"","sources":["../../src/preset/scripts.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC;;;GAGG;AACH,eAAO,MAAM,UAAU,QAAa,OAAO,CAAC;IAC1C,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB,CAKA,CAAC"}
@@ -2,13 +2,12 @@ import { resolveProjectContext } from '#context';
2
2
  import { resolveProjectPreset } from './project.js';
3
3
  import { resolveScripts } from './resolution/index.js';
4
4
  /**
5
- * get the merged scripts templates
5
+ * get the merged scripts templates (pure function)
6
6
  * @returns scripts template
7
7
  */
8
- export async function getScripts() {
8
+ export const getScripts = async () => {
9
9
  const context = await resolveProjectContext();
10
10
  const node = await resolveProjectPreset(context);
11
- const script = await resolveScripts(node, context);
12
- return script;
13
- }
14
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NyaXB0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wcmVzZXQvc2NyaXB0cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFakQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ2pELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFOUM7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxVQUFVO0lBQzlCLE1BQU0sT0FBTyxHQUFHLE1BQU0scUJBQXFCLEVBQUUsQ0FBQztJQUM5QyxNQUFNLElBQUksR0FBRyxNQUFNLG9CQUFvQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBRWpELE1BQU0sTUFBTSxHQUFHLE1BQU0sY0FBYyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztJQUVuRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDIn0=
11
+ return resolveScripts(node, context);
12
+ };
13
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NyaXB0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wcmVzZXQvc2NyaXB0cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFakQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ2pELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFJOUM7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHLEtBQUssSUFHNUIsRUFBRTtJQUNILE1BQU0sT0FBTyxHQUFHLE1BQU0scUJBQXFCLEVBQUUsQ0FBQztJQUM5QyxNQUFNLElBQUksR0FBRyxNQUFNLG9CQUFvQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBRWpELE9BQU8sY0FBYyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztBQUN2QyxDQUFDLENBQUMifQ==
package/lib/run.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AA4JnC;;;;;;GAMG;AACH,wBAAsB,GAAG,CACvB,KAAK,EAAE,IAAI,EAAE,EACb,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GACvD,OAAO,CAAC,IAAI,CAAC,CAmCf"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AA+KnC;;;;;;GAMG;AACH,wBAAsB,GAAG,CACvB,KAAK,EAAE,IAAI,EAAE,EACb,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GACvD,OAAO,CAAC,IAAI,CAAC,CA6Cf"}
package/lib/run.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { delimiter } from 'node:path';
1
2
  import npmRunScript from '@npmcli/run-script';
2
3
  import { Listr } from 'listr2';
3
4
  import parse from 'yargs-parser';
@@ -9,19 +10,20 @@ import { parseGlobalArgs, parseTaskSpec, selectTasks } from './task.js';
9
10
  /**
10
11
  * create an array of Listr tasks based on the provided inputs
11
12
  * @param _ collection of arguments
12
- * @param _.composed composed script object containing script definitions
13
+ * @param _.scripts composed script object containing script definitions
13
14
  * @param _.template template object containing script definitions
14
15
  * @param _.context project context
16
+ * @param _.paths additional binary paths from preset roots
15
17
  * @param _.task task name
16
18
  * @param _.args array of arguments
17
19
  * @returns array of Listr tasks
18
20
  */
19
21
  function createListrTask(_) {
20
- const { composed, template, task, args, context } = _;
22
+ const { scripts, template, task, args, context, paths } = _;
21
23
  return {
22
24
  title: `Running ${task}...`,
23
25
  task: async (_, taskControl) => {
24
- const command = composed[task];
26
+ const command = scripts[task];
25
27
  // parse the command and extract the executable and task specifications
26
28
  const argv = parse(command, {
27
29
  configuration: { 'populate--': true, 'unknown-options-as-args': true },
@@ -31,19 +33,20 @@ function createListrTask(_) {
31
33
  if (['run-s', 'run-p'].includes(executable)) {
32
34
  const globalArgs = [...parseGlobalArgs(argv), ...args];
33
35
  // get subtasks based on the task specifications and global arguments
34
- const subTasks = taskSpecs.flatMap((taskSpec) => getListrTasksBySpec({ template, context, taskSpec, globalArgs }));
36
+ const subTasks = (await Promise.all(taskSpecs.map(async (taskSpec) => getListrTasksBySpec({
37
+ template,
38
+ context,
39
+ paths,
40
+ taskSpec,
41
+ globalArgs,
42
+ })))).flat();
35
43
  const concurrent = executable === 'run-p';
36
44
  return taskControl.newListr(subTasks, { concurrent });
37
45
  }
38
46
  else {
39
- taskControl.output = `${composed[task]} ${args.join(' ')}`;
47
+ taskControl.output = `${scripts[task]} ${args.join(' ')}`;
40
48
  // run the npm script with the provided arguments and package information
41
- return runWithNPM({
42
- task,
43
- args,
44
- context,
45
- composedScript: composed,
46
- });
49
+ return runWithNPM({ task, args, context, paths, scripts });
47
50
  }
48
51
  },
49
52
  };
@@ -53,18 +56,20 @@ function createListrTask(_) {
53
56
  * @param _ collection of arguments
54
57
  * @param _.template template object containing script definitions
55
58
  * @param _.context package context
59
+ * @param _.paths additional binary paths from preset roots
56
60
  * @param _.taskSpec task specification string
57
61
  * @param _.globalArgs array of global arguments
58
- * @returns array of Listr tasks
62
+ * @returns a promise resolving to an array of Listr tasks
59
63
  */
60
- function getListrTasksBySpec(_) {
61
- const { template, context, taskSpec, globalArgs } = _;
64
+ async function getListrTasksBySpec(_) {
65
+ const { template, context, paths, taskSpec, globalArgs } = _;
62
66
  // parse the task specification and remove any quotes
63
67
  const task = parseTaskSpec(taskSpec.toString().replace(/^(['"])([^]*?)\1$/, '$2'), globalArgs);
64
68
  // get Listr tasks based on the provided inputs
65
69
  return getListrTasks({
66
70
  template,
67
71
  context,
72
+ paths,
68
73
  selector: task.selector,
69
74
  args: task.args,
70
75
  });
@@ -74,20 +79,21 @@ function getListrTasksBySpec(_) {
74
79
  * @param _ collection of arguments
75
80
  * @param _.template template object containing script definitions
76
81
  * @param _.context project context
82
+ * @param _.paths additional binary paths from preset roots
77
83
  * @param _.selector task selector string
78
84
  * @param _.args array of arguments
79
- * @returns array of Listr tasks
85
+ * @returns a promise resolving to an array of Listr tasks
80
86
  */
81
- function getListrTasks(_) {
82
- const { template, context, selector, args } = _;
87
+ async function getListrTasks(_) {
88
+ const { paths, template, context, selector, args } = _;
83
89
  // clone the content for immutability
84
90
  const target = { ...context.packageJson.scripts };
85
91
  // compose the script using the provided template and target
86
- const composed = composeScripts({ template, target });
92
+ const scripts = await composeScripts({ template, target });
87
93
  // select tasks based on the composed script and selector
88
- const tasks = selectTasks(Object.keys(composed), selector);
94
+ const tasks = selectTasks(Object.keys(scripts), selector);
89
95
  // create Listr tasks based on the selected tasks
90
- return tasks.map((task) => createListrTask({ composed, template, context, task, args }));
96
+ return tasks.map((task) => createListrTask({ paths, scripts, template, context, task, args }));
91
97
  }
92
98
  /**
93
99
  * run a task defined in the combined script definitions using npm-run-script
@@ -95,16 +101,21 @@ function getListrTasks(_) {
95
101
  * @param _.task task name
96
102
  * @param _.args array of arguments
97
103
  * @param _.context project context
98
- * @param _.composedScript combined script definitions
104
+ * @param _.paths additional binary paths from preset roots
105
+ * @param _.scripts combined script definitions
99
106
  * @returns a promise that will be resolved when the task is completed
100
107
  */
101
108
  async function runWithNPM(_) {
102
- const { task, args, context: { projectRoot }, composedScript, } = _;
103
- debug('RUNNING\n%O', { task, command: composedScript[task] });
109
+ const { task, args, context: { projectRoot }, scripts, } = _;
110
+ const paths = [..._.paths, ...process.env.PATH.split(delimiter)];
111
+ debug('RUNNING\n%O', { task, command: scripts[task], paths });
104
112
  await npmRunScript({
105
113
  event: task,
106
114
  args,
107
- pkg: { scripts: composedScript },
115
+ env: {
116
+ PATH: paths.join(delimiter),
117
+ },
118
+ pkg: { scripts },
108
119
  path: projectRoot,
109
120
  stdio: 'inherit',
110
121
  });
@@ -128,9 +139,15 @@ export async function run(tasks, options) {
128
139
  }
129
140
  : context;
130
141
  // get the merged script definitions
131
- const template = await getScripts();
142
+ const { paths, scripts: template } = await getScripts();
132
143
  // get Listr tasks based on the provided tasks and package information
133
- const listTasks = tasks.flatMap((task) => getListrTasks({ template, context: distilled, ...task }));
144
+ const listTasks = (await Promise.all(tasks.map(async (taskItem) => getListrTasks({
145
+ paths,
146
+ template,
147
+ context: distilled,
148
+ selector: taskItem.selector,
149
+ args: taskItem.args,
150
+ })))).flat();
134
151
  // create a Listr instance with the list of tasks and configuration options
135
152
  const listr = new Listr(listTasks, {
136
153
  concurrent: parallel,
@@ -145,4 +162,4 @@ export async function run(tasks, options) {
145
162
  process.exit(1);
146
163
  }
147
164
  }
148
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3J1bi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLFlBQVksTUFBTSxvQkFBb0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBRS9CLE9BQU8sS0FBSyxNQUFNLGNBQWMsQ0FBQztBQUVqQyxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDbEQsT0FBTyxLQUFLLE1BQU0sWUFBWSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDdEMsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUMzQyxPQUFPLEVBQUUsZUFBZSxFQUFFLGFBQWEsRUFBRSxXQUFXLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFPckU7Ozs7Ozs7OztHQVNHO0FBQ0gsU0FBUyxlQUFlLENBQUMsQ0FNeEI7SUFDQyxNQUFNLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxHQUFHLENBQUMsQ0FBQztJQUV0RCxPQUFPO1FBQ0wsS0FBSyxFQUFFLFdBQVcsSUFBSSxLQUFLO1FBQzNCLElBQUksRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLFdBQVcsRUFBRSxFQUFFO1lBQzdCLE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUUvQix1RUFBdUU7WUFDdkUsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLE9BQU8sRUFBRTtnQkFDMUIsYUFBYSxFQUFFLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSx5QkFBeUIsRUFBRSxJQUFJLEVBQUU7YUFDdkUsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxDQUFDLFVBQVUsRUFBRSxHQUFHLFNBQVMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxF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
165
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3J1bi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRXRDLE9BQU8sWUFBWSxNQUFNLG9CQUFvQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFFL0IsT0FBTyxLQUFLLE1BQU0sY0FBYyxDQUFDO0FBRWpDLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNsRCxPQUFPLEtBQUssTUFBTSxZQUFZLENBQUM7QUFDL0IsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUN0QyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzNDLE9BQU8sRUFBRSxlQUFlLEVBQUUsYUFBYSxFQUFFLFdBQVcsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQU9yRTs7Ozs7Ozs7OztHQVVHO0FBQ0gsU0FBUyxlQUFlLENBQUMsQ0FPeEI7SUFDQyxNQUFNLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFFNUQsT0FBTztRQUNMLEtBQUssRUFBRSxXQUFXLElBQUksS0FBSztRQUMzQixJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxXQUFXLEVBQUUsRUFBRTtZQUM3QixNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7WUFFOUIsdUVBQXVFO1lBQ3ZFLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxPQUFPLEVBQUU7Z0JBQzFCLGFBQWEsRUFBRSxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUseUJBQXlCLEVBQUUsSUFBSSxFQUFFO2FBQ3ZFLENBQUMsQ0FBQztZQUNILE1BQU0sQ0FBQyxVQUFVLEVBQUUsR0FBRyxTQUFT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
package/lib/scripts.d.ts CHANGED
@@ -1,21 +1,19 @@
1
1
  /** pseudo type for representing the name of a script */
2
2
  type ScriptName = string;
3
- /** pseudo type for representing the command */
4
- type Command = string;
5
3
  /** collection of scripts */
6
- export type Script = Record<ScriptName, Command>;
4
+ export type Script = Record<ScriptName, string>;
7
5
  /**
8
6
  * merge the script definitions from the template and the target package.json
9
7
  * @param args template and customized scripts to be merged
10
8
  * @param args.template scripts defined from the template
11
9
  * @param args.target scripts defined from target's package.json
12
- * @returns a dictionary of merged definitions
10
+ * @returns a promise resolving to a dictionary of merged definitions
13
11
  */
14
12
  export declare function composeScripts(args: {
15
13
  /** scripts defined from the template */
16
14
  template: Script;
17
15
  /** scripts defined from target's package.json */
18
16
  target: Script;
19
- }): Script;
17
+ }): Promise<Script>;
20
18
  export {};
21
19
  //# sourceMappingURL=scripts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scripts.d.ts","sourceRoot":"","sources":["../src/scripts.ts"],"names":[],"mappings":"AAUA,wDAAwD;AACxD,KAAK,UAAU,GAAG,MAAM,CAAC;AAEzB,+CAA+C;AAC/C,KAAK,OAAO,GAAG,MAAM,CAAC;AAEtB,4BAA4B;AAC5B,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AAkBjD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE;IACnC,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,MAAM,CA4BT"}
1
+ {"version":3,"file":"scripts.d.ts","sourceRoot":"","sources":["../src/scripts.ts"],"names":[],"mappings":"AAcA,wDAAwD;AACxD,KAAK,UAAU,GAAG,MAAM,CAAC;AAEzB,4BAA4B;AAC5B,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AAwBhD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAuClB"}
package/lib/scripts.js CHANGED
@@ -1,96 +1,123 @@
1
- import { basename } from 'node:path';
2
- import mvdan from 'mvdan-sh';
3
- import parse from 'yargs-parser';
1
+ import { parse, print } from 'sh-syntax';
4
2
  import debug from './debugger.js';
5
- import { mapValues } from './utilities/index.js';
6
- const { syntax } = mvdan;
7
- // shell command parser
8
- const parser = syntax.NewParser();
9
- // shell command generator
10
- const printer = syntax.NewPrinter();
3
+ import { findRunInParsed, parseCommandStructure, parseCommandText, } from './parsing.js';
4
+ import { mapValuesAsync } from './utilities/index.js';
5
+ const MAX_DEPTH = 10;
11
6
  /**
12
7
  * merge the script definitions from the template and the target package.json
13
8
  * @param args template and customized scripts to be merged
14
9
  * @param args.template scripts defined from the template
15
10
  * @param args.target scripts defined from target's package.json
16
- * @returns a dictionary of merged definitions
11
+ * @returns a promise resolving to a dictionary of merged definitions
17
12
  */
18
- export function composeScripts(args) {
13
+ export async function composeScripts(args) {
19
14
  const { template, target } = args;
20
15
  debug('SCRIPT PROVIDED BY PROJECT\n%O', target);
21
- const script = mapValues({ ...template, ...target }, (command) => {
16
+ const script = await mapValuesAsync({ ...template, ...target }, async (command) => {
22
17
  try {
23
- // parse the shell command into its ast
24
- const ast = parser.Parse(command);
25
- // walk through the tree and replace any call to the runner e.g. preset task1 task2 -- --help
26
- syntax.Walk(ast, (node) => replaceRunnerNode(node, { template, target }));
27
- // generate the code from ast
28
- return printer.Print(ast).trim();
18
+ // first validate the shell command syntax
19
+ await parse(command);
20
+ // resolve any 'run' commands in the script
21
+ const context = { template, target };
22
+ const resolvedCommand = await resolveAllRunCommands(command, context);
23
+ // parse and print to normalize formatting
24
+ const ast = await parse(resolvedCommand);
25
+ const printed = await print(ast, { originalText: resolvedCommand });
26
+ return printed.trim();
29
27
  }
30
28
  catch (error) {
31
- if (error instanceof Error) {
29
+ // check if it's a resolution error (our own error)
30
+ if (error instanceof Error &&
31
+ error.message.includes('cannot be resolved')) {
32
32
  throw error;
33
33
  }
34
- else {
35
- // parser.Parse may throw an empty object as an error, catch here
36
- throw new Error(`failed to parse command: ${command}`);
37
- }
34
+ // otherwise it's a parse error
35
+ throw new Error(`failed to parse command: ${command}`);
38
36
  }
39
37
  });
40
38
  debug('SCRIPT RESOLVED FROM PRESET AND PROJECT\n%O', script);
41
39
  return script;
42
40
  }
43
- function isNodeType(node, type) {
44
- return syntax.NodeType(node) === type;
45
- }
46
41
  /**
47
- * resolve a runner command
48
- * @param command the command to be replaced
42
+ * resolves a runner command into its expanded form (pure)
43
+ * @param parsedExpr the parsed call expression
44
+ * @param originalCommand the original full command (for error messages)
49
45
  * @param context resource context
50
- * @returns the resolved command
46
+ * @returns the resolved command string
51
47
  */
52
- function resolveRunner(command, context) {
53
- const arg = parse(command, {
54
- configuration: { 'populate--': true, 'unknown-options-as-args': true },
55
- });
56
- // extract tasks and their arguments
57
- const destinations = arg._.slice(1);
58
- const destinationArgs = arg['--'] ?? [];
48
+ const resolveRunner = (parsedExpr, originalCommand, context) => {
49
+ const { args, extraArgs } = parsedExpr;
50
+ const destinations = args.filter((arg) => !arg.startsWith('--'));
59
51
  // resolve tasks into its full form e.g. task1 task2
60
52
  return destinations
61
53
  .map((destination) => {
62
54
  const expandedCommand = context.template[destination] ||
63
- (context.target[destination] === command
55
+ (context.target[destination] === originalCommand
64
56
  ? undefined
65
57
  : context.target[destination]);
66
58
  if (expandedCommand === undefined) {
67
- throw new Error(`"${destination}" cannot be resolved in "${command}"`);
59
+ throw new Error(`"${destination}" cannot be resolved in "${originalCommand}"`);
68
60
  }
69
- return [expandedCommand, ...destinationArgs].join(' ');
61
+ return [expandedCommand, ...extraArgs].join(' ');
70
62
  })
71
63
  .join(' && ');
72
- }
64
+ };
73
65
  /**
74
- * replace a runner node with the actual command
75
- * @param node an expression node
66
+ * finds all replacements needed for run commands
67
+ * @param command the original source command string
76
68
  * @param context resource context
77
- * @returns boolean true for no error
69
+ * @param ast the parsed AST from sh-syntax
70
+ * @returns array of replacements to apply
78
71
  */
79
- function replaceRunnerNode(node, context) {
80
- // replace only it's a runner call, not anything else
81
- if (isNodeType(node, 'Stmt') && isNodeType(node.Cmd, 'CallExpr')) {
82
- // parse assigned arguments e.g. task1 args --help
83
- const parts = node.Cmd.Args.map((part) => part.Lit());
84
- // only resolve if the `run` cli shipped in this package is invoke
85
- if (parts.length && basename(parts[0]) === 'run') {
86
- // resolve tasks into its full form e.g. task1 task2
87
- const resolvedCommand = resolveRunner(parts.join(' '), context);
88
- // replace the task definition with its expanded statement
89
- node.Cmd = parser.Parse(resolvedCommand).Stmts[0].Cmd;
90
- // recursively replace any runner call in the expanded statement
91
- replaceRunnerNode(node.Cmd, context);
72
+ const findReplacements = (command, context, ast) => {
73
+ const matches = [];
74
+ // iterate over statements from sh-syntax
75
+ for (const stmt of ast.Stmt) {
76
+ if (stmt.Cmd) {
77
+ // extract command text using sh-syntax positions
78
+ const cmdText = command.slice(stmt.Cmd.Pos.Offset, stmt.Cmd.End.Offset);
79
+ // parse structure ourselves
80
+ const parsed = parseCommandStructure(cmdText, stmt.Cmd.Pos.Offset);
81
+ // find run commands
82
+ matches.push(...findRunInParsed(parsed, command));
92
83
  }
93
84
  }
94
- return true;
95
- }
96
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NyaXB0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9zY3JpcHRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFckMsT0FBTyxLQUFLLE1BQU0sVUFBVSxDQUFDO0FBQzdCLE9BQU8sS0FBSyxNQUFNLGNBQWMsQ0FBQztBQUVqQyxPQUFPLEtBQUssTUFBTSxZQUFZLENBQUM7QUFDL0IsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQWF4QyxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDO0FBRXpCLHVCQUF1QjtBQUN2QixNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUM7QUFFbEMsMEJBQTBCO0FBQzFCLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQztBQVVwQzs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsY0FBYyxDQUFDLElBSzlCO0lBQ0MsTUFBTSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUM7SUFFbEMsS0FBSyxDQUFDLGdDQUFnQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBRWhELE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxFQUFFLEdBQUcsUUFBUSxFQUFFLEdBQUcsTUFBTSxFQUFFLEVBQUUsQ0FBQyxPQUFPLEVBQVUsRUFBRTtRQUN2RSxJQUFJLENBQUM7WUFDSCx1Q0FBdUM7WUFDdkMsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUVsQyw2RkFBNkY7WUFDN0YsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLGlCQUFpQixDQUFDLElBQUksRUFBRSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFFMUUsNkJBQTZC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
85
+ return matches.map((runMatch) => {
86
+ const parsedExpr = parseCommandText(runMatch.match);
87
+ const resolved = resolveRunner(parsedExpr, command, context);
88
+ return {
89
+ start: runMatch.start,
90
+ end: runMatch.end,
91
+ text: resolved,
92
+ };
93
+ });
94
+ };
95
+ /**
96
+ * apply replacements to source (pure, processes right-to-left)
97
+ * @param source the original source string
98
+ * @param replacements the replacements to apply
99
+ * @returns the source with all replacements applied
100
+ */
101
+ const applyReplacements = (source, replacements) => [...replacements]
102
+ .sort((a, b) => b.start - a.start) // right to left to preserve positions
103
+ .reduce((text, { start, end, text: replacement }) => text.slice(0, start) + replacement + text.slice(end), source);
104
+ /**
105
+ * recursively resolve all run commands (immutable recursion)
106
+ * @param command the command to process
107
+ * @param context resource context
108
+ * @param depth current recursion depth (for cycle detection)
109
+ * @returns the resolved command with all run patterns replaced
110
+ */
111
+ const resolveAllRunCommands = async (command, context, depth = 0) => {
112
+ if (depth > MAX_DEPTH) {
113
+ throw new Error('Maximum recursion depth exceeded');
114
+ }
115
+ const ast = await parse(command);
116
+ const replacements = findReplacements(command, context, ast);
117
+ if (replacements.length === 0) {
118
+ return command;
119
+ }
120
+ const resolved = applyReplacements(command, replacements);
121
+ return resolveAllRunCommands(resolved, context, depth + 1);
122
+ };
123
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NyaXB0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9zY3JpcHRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRXpDLE9BQU8sS0FBSyxNQUFNLFlBQVksQ0FBQztBQUMvQixPQUFPLEVBQ0wsZUFBZSxFQUNmLHFCQUFxQixFQUNyQixnQkFBZ0IsR0FDakIsTUFBTSxXQUFXLENBQUM7QUFDbkIsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQWdDN0MsTUFBTSxTQUFTLEdBQUcsRUFBRSxDQUFDO0FBRXJCOzs7Ozs7R0FNRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsY0FBYyxDQUFDLElBS3BDO0lBQ0MsTUFBTSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUM7SUFFbEMsS0FBSyxDQUFDLGdDQUFnQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBRWhELE1BQU0sTUFBTSxHQUFHLE1BQU0sY0FBYyxDQUNqQyxFQUFFLEdBQUcsUUFBUSxFQUFFLEdBQUcsTUFBTSxFQUFFLEVBQzFCLEtBQUssRUFBRSxPQUFPLEVBQW1CLEVBQUU7UUFDakMsSUFBSSxDQUFDO1lBQ0gsMENBQTBDO1lBQzFDLE1BQU0sS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBRXJCLDJDQUEyQztZQUMzQyxNQUFNLE9BQU8sR0FBRyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsQ0FBQztZQUNyQyxNQUFNLGVBQWUsR0FBRyxNQUFNLHFCQUFxQixDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztZQUV0RSwwQ0FBMEM7WUFDMUMsTUFBTSxHQUFHLEdBQUcsTUFBTSxLQUFLLENBQUMsZUFBZSxDQUFDLENBQUM7WUFDekMsTUFBTSxPQUFPLEdBQUcsTUFBTSxLQUFLLENBQUMsR0FBRyxFQUFFLEVBQUUsWUFBWSxFQUFFLGVBQWUs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
@@ -5,4 +5,11 @@
5
5
  * @returns the mapped object
6
6
  */
7
7
  export declare function mapValues<T, U>(obj: Record<string, T>, fn: (value: T) => U): Record<string, U>;
8
+ /**
9
+ * map the values of an object asynchronously to a new object with the same keys
10
+ * @param obj the object to be mapped
11
+ * @param fn the async mapping function
12
+ * @returns a promise resolving to the mapped object
13
+ */
14
+ export declare function mapValuesAsync<T, U>(obj: Record<string, T>, fn: (value: T) => Promise<U>): Promise<Record<string, U>>;
8
15
  //# sourceMappingURL=mapping.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../src/utilities/mapping.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,CAAC,EAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EACtB,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAClB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAInB"}
1
+ {"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../src/utilities/mapping.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,CAAC,EAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EACtB,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAClB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAInB;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,CAAC,EAAE,CAAC,EACvC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EACtB,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAM5B"}
@@ -7,4 +7,14 @@
7
7
  export function mapValues(obj, fn) {
8
8
  return Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, fn(value)]));
9
9
  }
10
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFwcGluZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsaXRpZXMvbWFwcGluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxTQUFTLENBQ3ZCLEdBQXNCLEVBQ3RCLEVBQW1CO0lBRW5CLE9BQU8sTUFBTSxDQUFDLFdBQVcsQ0FDdkIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FDNUQsQ0FBQztBQUNKLENBQUMifQ==
10
+ /**
11
+ * map the values of an object asynchronously to a new object with the same keys
12
+ * @param obj the object to be mapped
13
+ * @param fn the async mapping function
14
+ * @returns a promise resolving to the mapped object
15
+ */
16
+ export async function mapValuesAsync(obj, fn) {
17
+ const entries = await Promise.all(Object.entries(obj).map(async ([key, value]) => [key, await fn(value)]));
18
+ return Object.fromEntries(entries);
19
+ }
20
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFwcGluZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsaXRpZXMvbWFwcGluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxTQUFTLENBQ3ZCLEdBQXNCLEVBQ3RCLEVBQW1CO0lBRW5CLE9BQU8sTUFBTSxDQUFDLFdBQVcsQ0FDdkIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FDNUQsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsY0FBYyxDQUNsQyxHQUFzQixFQUN0QixFQUE0QjtJQUU1QixNQUFNLE9BQU8sR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQy9CLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLEVBQUUsTUFBTSxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUN4RSxDQUFDO0lBRUYsT0FBTyxNQUFNLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQ3JDLENBQUMifQ==
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "presetter",
3
- "version": "8.2.0",
3
+ "version": "8.3.0",
4
4
  "description": "Make project configurations clean with presets",
5
5
  "keywords": [
6
6
  "config",
@@ -69,16 +69,16 @@
69
69
  "debug": "^4.3.5",
70
70
  "execa": "^9.3.0",
71
71
  "find-up-simple": "^1.0.0",
72
- "globby": "^15.0.0",
72
+ "globby": "^16.0.0",
73
73
  "jiti": "^2.4.0",
74
74
  "js-yaml": "^4.1.0",
75
75
  "listr2": "^9.0.0",
76
- "mvdan-sh": "^0.10.0",
77
76
  "pupa": "^3.1.0",
77
+ "sh-syntax": "^0.5.0",
78
78
  "source-map-support": "^0.5.0",
79
79
  "yargs": "^18.0.0",
80
80
  "yargs-parser": "^22.0.0",
81
- "presetter-types": "8.2.0"
81
+ "presetter-types": "8.3.0"
82
82
  },
83
83
  "devDependencies": {
84
84
  "@types/debug": "^4.0.0",
@@ -86,9 +86,9 @@
86
86
  "@types/node": "^24.0.0",
87
87
  "@types/yargs": "^17.0.0",
88
88
  "type-fest": "^5.0.0",
89
- "presetter-preset-esm": "8.2.0",
90
- "presetter-preset-essentials": "8.2.0",
91
- "presetter-preset-strict": "8.2.0"
89
+ "presetter-preset-esm": "8.3.0",
90
+ "presetter-preset-strict": "8.3.0",
91
+ "presetter-preset-essentials": "8.3.0"
92
92
  },
93
93
  "engines": {
94
94
  "node": ">=20.0.0"
@@ -101,6 +101,7 @@
101
101
  "script": "tsx --conditions=development --eval \"process.argv = [...process.argv.slice(0, 2), 'run', ...process.argv.slice(2)]; import('./src/executable/index.ts');\" -- run --template",
102
102
  "stage": "npm run script -- stage --",
103
103
  "test": "npm run script -- test --",
104
+ "typecheck": "npm run script -- typecheck --",
104
105
  "watch": "npm run script -- watch --"
105
106
  }
106
107
  }
@@ -8,6 +8,7 @@ declare module '@npmcli/run-script' {
8
8
  event: string;
9
9
  args: string[];
10
10
  pkg: PackageJson;
11
+ env?: Record<string, string>;
11
12
  path?: string;
12
13
  stdio?: T;
13
14
  stdioString?: S;
@@ -1,44 +0,0 @@
1
- declare module 'mvdan-sh' {
2
- export type Node = CallExpr | File | Subshell | Stmt;
3
-
4
- export interface File {
5
- Stmts: Stmt[];
6
- }
7
-
8
- export interface Stmt {
9
- Cmd: Node;
10
- }
11
-
12
- export interface Subshell {
13
- Stmts: Stmt[];
14
- }
15
-
16
- export interface CallExpr {
17
- Args: Word[];
18
- }
19
-
20
- interface Word {
21
- Parts: WordPart[];
22
- Lit(): string;
23
- }
24
-
25
- interface WordPart {
26
- Value: string;
27
- }
28
-
29
- declare class Parser {
30
- Parse(name: string): File;
31
- }
32
-
33
- declare class Printer {
34
- Print(node: Node): string;
35
- }
36
-
37
- export namespace syntax {
38
- declare function DebugPrint(node: Node): void;
39
- declare function NewParser(): Parser;
40
- declare function NewPrinter(): Printer;
41
- declare function Walk(node: Node, callback: (node: Node) => boolean): void;
42
- declare function NodeType(node: Node): string;
43
- }
44
- }