burgee 0.11.0 → 0.12.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 +19 -4
- package/dist/cli.d.ts +2 -90
- package/dist/cli.js +4 -151
- package/dist/commander/command.d.ts +33 -1
- package/dist/commander/command.js +49 -11
- package/dist/compat.d.ts +39 -2
- package/dist/compat.js +90 -2
- package/dist/complete-dynamic.d.ts +18 -0
- package/dist/complete-dynamic.js +19 -0
- package/dist/completions.js +33 -15
- package/dist/config-explain.d.ts +22 -0
- package/dist/config-explain.js +33 -0
- package/dist/define-error.d.ts +29 -0
- package/dist/define-error.js +29 -0
- package/dist/errors.d.ts +29 -0
- package/dist/errors.js +17 -0
- package/dist/execute.d.ts +6 -0
- package/dist/execute.js +74 -16
- package/dist/facade-failure.d.ts +17 -0
- package/dist/facade-failure.js +12 -0
- package/dist/fields.d.ts +32 -0
- package/dist/fields.js +45 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/manifest.d.ts +42 -5
- package/dist/manifest.js +6 -0
- package/dist/mcp.d.ts +5 -1
- package/dist/mcp.js +77 -11
- package/dist/migrate.d.ts +57 -7
- package/dist/migrate.js +413 -34
- package/dist/parse-hooks.d.ts +7 -0
- package/dist/parse-hooks.js +17 -0
- package/dist/plugin.d.ts +2 -6
- package/dist/plugin.js +1 -1
- package/dist/program-schema.json +1 -0
- package/dist/program.d.ts +90 -0
- package/dist/program.js +151 -0
- package/dist/runtime.d.ts +3 -1
- package/dist/runtime.js +3 -0
- package/dist/schema.d.ts +7 -0
- package/dist/schema.js +6 -11
- package/dist/schema.json +1 -1
- package/dist/stdin-dash.d.ts +15 -0
- package/dist/stdin-dash.js +12 -0
- package/dist/validate.d.ts +1 -27
- package/dist/validate.js +2 -17
- package/dist/yargs/factory.js +39 -13
- package/dist/yargs-parser.d.ts +8 -1
- package/dist/yargs-parser.js +1 -1
- package/dist/yargs.d.ts +1 -0
- package/dist/yargs.js +1 -0
- package/package.json +7 -6
package/dist/manifest.d.ts
CHANGED
|
@@ -36,6 +36,13 @@ export type StandardResult<Output> = {
|
|
|
36
36
|
export interface OptionSpec {
|
|
37
37
|
/** `boolean` never consumes a value (S7); `number` rejects NaN and Infinity (S3). */
|
|
38
38
|
type: 'string' | 'boolean' | 'number';
|
|
39
|
+
/**
|
|
40
|
+
* D3 / D-119 — values computed when a person presses TAB: the generated script calls the
|
|
41
|
+
* program back (`<program> __complete <command> --<option> <partial>`) for this option and
|
|
42
|
+
* no other. Declaring it is the opt-in; an option without one completes from `choices`, or
|
|
43
|
+
* not at all, and never runs the program.
|
|
44
|
+
*/
|
|
45
|
+
complete?: (partial: string) => Iterable<string> | Promise<Iterable<string>>;
|
|
39
46
|
description?: string;
|
|
40
47
|
required?: boolean;
|
|
41
48
|
short?: string;
|
|
@@ -78,6 +85,13 @@ export interface OptionSpec {
|
|
|
78
85
|
/** `true` renders `(deprecated)`; a string names the replacement: `(deprecated: use --force)` (yargs #2248). */
|
|
79
86
|
deprecated?: boolean | string;
|
|
80
87
|
hidden?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* `boolean` only: whether `--no-<name>` is accepted. Every boolean is negatable unless this
|
|
90
|
+
* says `false`. burgee's own parser negates every boolean (see `toParseConfig`); the
|
|
91
|
+
* commander façade sets `false` where commander would refuse the negation, so completions
|
|
92
|
+
* and `--mcp` never offer or send a flag the parser behind them rejects.
|
|
93
|
+
*/
|
|
94
|
+
negatable?: boolean;
|
|
81
95
|
/** The shared set this option was copied from (M4); `--schema` carries it, help lists the option like any other. */
|
|
82
96
|
sharedFrom?: string;
|
|
83
97
|
}
|
|
@@ -150,6 +164,8 @@ export interface ArgumentSpec {
|
|
|
150
164
|
required?: boolean;
|
|
151
165
|
variadic?: boolean;
|
|
152
166
|
default?: string;
|
|
167
|
+
/** `'file'`: a path, where `-` means standard input — handed to the handler as `ctx.stdin` (S4). */
|
|
168
|
+
type?: 'file';
|
|
153
169
|
}
|
|
154
170
|
/** One example: a single copy-pasteable command line, the description below it (H2). */
|
|
155
171
|
export interface Example {
|
|
@@ -173,6 +189,11 @@ export interface RunContext {
|
|
|
173
189
|
options: Record<string, unknown>;
|
|
174
190
|
positionals: string[];
|
|
175
191
|
passthrough: string[];
|
|
192
|
+
/**
|
|
193
|
+
* Standard input, present only when a `type: 'file'` argument was given `-` (S4). The
|
|
194
|
+
* positional still reads `-`, so a handler checks it the same way it checks a path.
|
|
195
|
+
*/
|
|
196
|
+
stdin?: NodeJS.ReadableStream;
|
|
176
197
|
env: Record<string, string | undefined>;
|
|
177
198
|
/** Exit with an E1 code. Unwinds cleanly: the code is honoured and nothing is printed. */
|
|
178
199
|
exit: (code: number) => never;
|
|
@@ -219,6 +240,8 @@ export interface CommandNode {
|
|
|
219
240
|
* none, so a façade's command is withheld in fact and cannot be made to say so.
|
|
220
241
|
*/
|
|
221
242
|
effects?: DeclaredEffects;
|
|
243
|
+
/** The result's top-level fields, as declared (N14); what `--json=` lists. */
|
|
244
|
+
fields?: readonly string[];
|
|
222
245
|
run?: (ctx: RunContext) => unknown;
|
|
223
246
|
/**
|
|
224
247
|
* The handler's module, imported on dispatch only (M2): the manifest — help, schema,
|
|
@@ -235,13 +258,19 @@ export declare function lazyRun(load: () => Promise<LazyModule>): (ctx: RunConte
|
|
|
235
258
|
export interface HookFilter {
|
|
236
259
|
command?: RegExp;
|
|
237
260
|
}
|
|
261
|
+
/** What a hook is handed. `argv` on `parse` only; `options` is empty on `parse` and `shutdown`. */
|
|
262
|
+
export interface HookContext {
|
|
263
|
+
command: string;
|
|
264
|
+
options: Record<string, unknown>;
|
|
265
|
+
argv?: string[];
|
|
266
|
+
}
|
|
238
267
|
export interface Hook {
|
|
239
268
|
filter?: HookFilter;
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
options: Record<string, unknown>;
|
|
243
|
-
}) => void | Promise<void>;
|
|
269
|
+
/** `parse` may return the argv to use instead; every other stage's return is ignored. */
|
|
270
|
+
handler: (ctx: HookContext) => unknown;
|
|
244
271
|
}
|
|
272
|
+
/** The stages a plugin hook fires at. `parse` and `shutdown` bracket the run (D-122). */
|
|
273
|
+
export type HookStage = 'parse' | 'preRun' | 'postRun' | 'onError' | 'shutdown';
|
|
245
274
|
/** Rolldown's lesson: evaluate the filter before crossing the boundary. */
|
|
246
275
|
export declare function hookApplies(hook: Hook | undefined, command: string): hook is Hook;
|
|
247
276
|
export declare class Manifest {
|
|
@@ -270,7 +299,15 @@ export declare class Manifest {
|
|
|
270
299
|
use(plugin: Plugin): void;
|
|
271
300
|
/** `enforce: 'pre'` first, then unordered, then `'post'` — the Vite/Rolldown convention. */
|
|
272
301
|
private ordered;
|
|
273
|
-
|
|
302
|
+
/** Whether any registered plugin declares a hook at `stage` — so a run without one pays nothing. */
|
|
303
|
+
declares(stage: HookStage): boolean;
|
|
304
|
+
/**
|
|
305
|
+
* `parse` (D-122): argv in, argv out, before the command is resolved. Each plugin, in
|
|
306
|
+
* `enforce` order, is handed what the previous one returned; returning nothing keeps it.
|
|
307
|
+
* A filter is matched against the typed argv, since no command has been resolved yet.
|
|
308
|
+
*/
|
|
309
|
+
parse(argv: string[]): Promise<string[]>;
|
|
310
|
+
fire(stage: Exclude<HookStage, 'parse'>, command: string, options: Record<string, unknown>): Promise<void>;
|
|
274
311
|
find(path: string[]): CommandNode | undefined;
|
|
275
312
|
/**
|
|
276
313
|
* Longest-prefix match of argv against declared command paths. The root's own
|
package/dist/manifest.js
CHANGED
|
@@ -49,6 +49,12 @@ export class Manifest {
|
|
|
49
49
|
ordered() {
|
|
50
50
|
return [...this.plugins].sort((a, b) => (a.enforce === undefined ? 1 : ORDER[a.enforce]) - (b.enforce === undefined ? 1 : ORDER[b.enforce]));
|
|
51
51
|
}
|
|
52
|
+
declares(stage) {
|
|
53
|
+
return this.plugins.some((p) => p.hooks?.[stage] !== undefined);
|
|
54
|
+
}
|
|
55
|
+
async parse(argv) {
|
|
56
|
+
return (await import('./parse-hooks.js')).runParseHooks(this.ordered(), argv);
|
|
57
|
+
}
|
|
52
58
|
async fire(stage, command, options) {
|
|
53
59
|
for (const plugin of this.ordered()) {
|
|
54
60
|
const hook = plugin.hooks?.[stage];
|
package/dist/mcp.d.ts
CHANGED
|
@@ -34,7 +34,11 @@ export type Invoke = (argv: string[]) => Promise<{
|
|
|
34
34
|
* this command is not a `read_only` one, and it is not a `withheld` one either — nobody said.
|
|
35
35
|
*/
|
|
36
36
|
export declare function annotationsOf(effects?: Effects): ToolAnnotations;
|
|
37
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* `config get` → `config_get`: MCP tool names are `[a-zA-Z0-9_-]`, one character or more. A
|
|
39
|
+
* program whose root runs — a single `run(defineCommand(…))`, a commander program with a root
|
|
40
|
+
* `.action()` — has no typed name at all, so its tool is named after the program.
|
|
41
|
+
*/
|
|
38
42
|
export declare const toolName: (node: CommandNode, root: string[]) => string;
|
|
39
43
|
/**
|
|
40
44
|
* The tool list: every runnable, visible command an author has not withheld.
|
package/dist/mcp.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import { Console } from 'node:console';
|
|
1
2
|
import { createInterface } from 'node:readline';
|
|
3
|
+
import { Writable } from 'node:stream';
|
|
2
4
|
import { WITHHELD } from './definition.js';
|
|
5
|
+
import { kebab } from './names.js';
|
|
6
|
+
import { host } from './runtime.js';
|
|
3
7
|
import { inputSchemaOf, runnable, typedName } from './schema.js';
|
|
4
8
|
export const MCP_PROTOCOL_VERSION = '2025-06-18';
|
|
5
9
|
const JSON_RPC_INVALID_REQUEST = -32600;
|
|
@@ -14,7 +18,7 @@ export function annotationsOf(effects) {
|
|
|
14
18
|
destructiveHint: effects === 'non_idempotent',
|
|
15
19
|
};
|
|
16
20
|
}
|
|
17
|
-
export const toolName = (node, root) => typedName(node, root).replaceAll(' ', '_');
|
|
21
|
+
export const toolName = (node, root) => (typedName(node, root) || root.join(' ')).replaceAll(' ', '_');
|
|
18
22
|
function describe(node) {
|
|
19
23
|
const parts = [node.description ?? node.summary ?? ''];
|
|
20
24
|
for (const e of node.examples ?? [])
|
|
@@ -32,12 +36,13 @@ function optionArgs(node, args) {
|
|
|
32
36
|
const value = args[name];
|
|
33
37
|
if (value === undefined || value === null)
|
|
34
38
|
continue;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
const flag = `--${kebab(name)}`;
|
|
40
|
+
if (spec.type !== 'boolean')
|
|
41
|
+
out.push(flag, String(value));
|
|
42
|
+
else if (value === true)
|
|
43
|
+
out.push(flag);
|
|
44
|
+
else if (value === false && spec.negatable !== false && (spec.default === true || spec.env !== undefined))
|
|
45
|
+
out.push(`--no-${kebab(name)}`);
|
|
41
46
|
}
|
|
42
47
|
return out;
|
|
43
48
|
}
|
|
@@ -55,6 +60,46 @@ export function argvOf(node, root, args) {
|
|
|
55
60
|
const command = typedName(node, root).split(' ').filter((s) => s !== '');
|
|
56
61
|
return [...command, ...optionArgs(node, args), '--json', ...positionalArgs(node, args)];
|
|
57
62
|
}
|
|
63
|
+
const STDOUT_CONSOLE = ['log', 'info', 'debug', 'dir', 'dirxml', 'table', 'group', 'groupCollapsed', 'groupEnd', 'count', 'countReset', 'time', 'timeLog', 'timeEnd'];
|
|
64
|
+
let framing = false;
|
|
65
|
+
async function printedBy(run) {
|
|
66
|
+
const chunks = [];
|
|
67
|
+
const decoder = new TextDecoder();
|
|
68
|
+
const take = (chunk) => void chunks.push(typeof chunk === 'string' ? chunk : decoder.decode(chunk));
|
|
69
|
+
const sink = new Writable({
|
|
70
|
+
decodeStrings: false,
|
|
71
|
+
write(chunk, _encoding, done) {
|
|
72
|
+
take(chunk);
|
|
73
|
+
done();
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
const stdout = host.stdout;
|
|
77
|
+
const write = stdout.write;
|
|
78
|
+
stdout.write = function (chunk, ...rest) {
|
|
79
|
+
if (framing)
|
|
80
|
+
return Reflect.apply(write, stdout, [chunk, ...rest]);
|
|
81
|
+
take(chunk);
|
|
82
|
+
const done = rest.find((r) => typeof r === 'function');
|
|
83
|
+
if (done !== undefined)
|
|
84
|
+
queueMicrotask(done);
|
|
85
|
+
return true;
|
|
86
|
+
};
|
|
87
|
+
const printer = new Console({ stdout: sink, stderr: host.stderr });
|
|
88
|
+
const saved = STDOUT_CONSOLE.map((m) => [m, console[m]]);
|
|
89
|
+
for (const m of STDOUT_CONSOLE)
|
|
90
|
+
Reflect.set(console, m, printer[m].bind(printer));
|
|
91
|
+
try {
|
|
92
|
+
return { settled: { status: 'fulfilled', value: await run() }, printed: chunks.join('') };
|
|
93
|
+
}
|
|
94
|
+
catch (reason) {
|
|
95
|
+
return { settled: { status: 'rejected', reason }, printed: chunks.join('') };
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
for (const [m, fn] of saved)
|
|
99
|
+
Reflect.set(console, m, fn);
|
|
100
|
+
stdout.write = write;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
58
103
|
async function callTool(session, params) {
|
|
59
104
|
const { manifest, invoke } = session;
|
|
60
105
|
const root = manifest.rootPath;
|
|
@@ -65,9 +110,22 @@ async function callTool(session, params) {
|
|
|
65
110
|
if (node === undefined)
|
|
66
111
|
return { error: { code: JSON_RPC_INVALID_PARAMS, message: `unknown tool "${name}"` } };
|
|
67
112
|
const args = (given['arguments'] ?? {});
|
|
68
|
-
const {
|
|
69
|
-
|
|
70
|
-
|
|
113
|
+
const { settled, printed } = await printedBy(async () => await invoke(argvOf(node, root, args)));
|
|
114
|
+
let text;
|
|
115
|
+
let isError;
|
|
116
|
+
if (settled.status === 'fulfilled') {
|
|
117
|
+
const { stdout, stderr, code } = settled.value;
|
|
118
|
+
text = stdout.trim() !== '' ? stdout.trim() : stderr.trim();
|
|
119
|
+
isError = code !== 0;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
text = settled.reason instanceof Error ? settled.reason.message : String(settled.reason);
|
|
123
|
+
isError = true;
|
|
124
|
+
}
|
|
125
|
+
const content = [{ type: 'text', text }];
|
|
126
|
+
if (printed.trim() !== '')
|
|
127
|
+
content.push({ type: 'text', text: printed.trimEnd() });
|
|
128
|
+
return { result: { content, isError } };
|
|
71
129
|
}
|
|
72
130
|
async function handle(session, request) {
|
|
73
131
|
switch (request.method) {
|
|
@@ -89,7 +147,15 @@ export function startMcp(manifest, opts) {
|
|
|
89
147
|
invoke: opts.invoke,
|
|
90
148
|
serverInfo: { name: manifest.rootPath.join(' ') || 'burgee', version: manifest.version ?? '0.0.0' },
|
|
91
149
|
};
|
|
92
|
-
const reply = (body) =>
|
|
150
|
+
const reply = (body) => {
|
|
151
|
+
framing = true;
|
|
152
|
+
try {
|
|
153
|
+
opts.output.write(`${JSON.stringify({ jsonrpc: '2.0', ...body })}\n`);
|
|
154
|
+
}
|
|
155
|
+
finally {
|
|
156
|
+
framing = false;
|
|
157
|
+
}
|
|
158
|
+
};
|
|
93
159
|
const swap = (next, invoke) => {
|
|
94
160
|
session.manifest = next;
|
|
95
161
|
if (invoke !== undefined)
|
package/dist/migrate.d.ts
CHANGED
|
@@ -1,13 +1,25 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type Row } from './compat.js';
|
|
2
|
+
/** The npm package a specifier names: `@scope/name/x` → `@scope/name`, `name/x` → `name`. */
|
|
3
|
+
export declare function packageOf(specifier: string): string;
|
|
2
4
|
/**
|
|
3
|
-
* A2 — the whole mapping, as data.
|
|
5
|
+
* A2, A12 — the whole mapping, as data, and none of it typed here.
|
|
6
|
+
*
|
|
7
|
+
* Every drop-in the oracle grades **level** with its incumbent (D-137): the incumbent's own
|
|
8
|
+
* suite passes as many cases against the family's replacement as against the incumbent
|
|
9
|
+
* itself, in the same harness. That is commander and yargs, and chalk, ora, string-width,
|
|
10
|
+
* cross-spawn, signal-exit and the rest — `compat.ts` holds the list and a lock re-derives it
|
|
11
|
+
* from `compat-oracle`. A drop-in that is not level yet is reported, never rewritten.
|
|
4
12
|
*
|
|
5
13
|
* Whole specifiers only. `burgee/commander` is not a key, which is what makes a second run
|
|
6
14
|
* over an already-migrated tree a no-op and lets the command declare `effects: 'idempotent'`.
|
|
15
|
+
* `yargs/yargs` is the one key the oracle does not name: yargs documents it as an entry,
|
|
16
|
+
* and it is the same module as `yargs`.
|
|
7
17
|
*/
|
|
8
18
|
export declare const MAPPING: Readonly<Record<string, string>>;
|
|
9
|
-
/** The packages a project depends on that this command
|
|
10
|
-
export declare const HOSTS: readonly [
|
|
19
|
+
/** The packages a project depends on that this command rewrites (A1). */
|
|
20
|
+
export declare const HOSTS: readonly string[];
|
|
21
|
+
/** The leading number of a version or a range — `^3.0.7` is 3, `>=18` is 18; `undefined` for `*` or a tag. */
|
|
22
|
+
export declare function majorOf(version: string): number | undefined;
|
|
11
23
|
/**
|
|
12
24
|
* Every name each target exports — values and types alike — so a rewrite that moves
|
|
13
25
|
* `import { Argv } from 'yargs'` can first ask whether `burgee/yargs` has an `Argv`.
|
|
@@ -24,8 +36,24 @@ export declare const FACADE_EXPORTS: Readonly<Record<string, readonly string[]>>
|
|
|
24
36
|
*
|
|
25
37
|
* `unknown-export` is a named import the target does not export — rewriting it would turn a
|
|
26
38
|
* working import into TS2305 or a `SyntaxError` at load, so the file stays as it was.
|
|
39
|
+
*
|
|
40
|
+
* `require-of-default` is a `require()` whose two sides hand back different kinds of value.
|
|
41
|
+
* `require()` of an ES module returns its namespace, so `require('cross-spawn')` — a function —
|
|
42
|
+
* rewritten to a target with a default and no `'module.exports'` would make `spawn(...)` throw.
|
|
43
|
+
* A `require('chalk')` of chalk 6, which is ESM only, already returns a namespace, and moves to
|
|
44
|
+
* a target that does too ({@link REQUIRE_NAMESPACE}, A29). Where the shapes differ, the file
|
|
45
|
+
* stays on the incumbent, where it works.
|
|
27
46
|
*/
|
|
28
|
-
export type RefusalReason = 'deep-import' | 'non-literal-specifier' | 'unknown-export';
|
|
47
|
+
export type RefusalReason = 'deep-import' | 'non-literal-specifier' | 'unknown-export' | 'require-of-default';
|
|
48
|
+
/**
|
|
49
|
+
* Incumbents whose own `require()` already returns an ES namespace — they ship ESM only and
|
|
50
|
+
* export no `'module.exports'`, so `require('chalk').default` is how a CommonJS caller of
|
|
51
|
+
* chalk 6 reaches it. Moving that line to a target that also hands back its namespace is
|
|
52
|
+
* exact (A29). Derived, not typed: `migrate-require.test.ts` holds this list equal to what
|
|
53
|
+
* Node's own `require()` returns for every installed incumbent in `MAPPING`, so a name here
|
|
54
|
+
* is a measurement and an incumbent that is not installed is left out, and refused as before.
|
|
55
|
+
*/
|
|
56
|
+
export declare const REQUIRE_NAMESPACE: readonly string[];
|
|
29
57
|
export interface Refusal {
|
|
30
58
|
/** Relative to the directory being migrated, with forward slashes on every platform. */
|
|
31
59
|
file: string;
|
|
@@ -64,6 +92,18 @@ export interface Detection {
|
|
|
64
92
|
/** Hosts a source file actually imports — used. These two disagree more often than not. */
|
|
65
93
|
imported: string[];
|
|
66
94
|
}
|
|
95
|
+
/** An incumbent the project has on a different major from the one graded — left alone (A12). */
|
|
96
|
+
export interface OffMajor {
|
|
97
|
+
from: string;
|
|
98
|
+
/** The installed version, or the declared range when nothing is installed here. */
|
|
99
|
+
found: string;
|
|
100
|
+
graded: string;
|
|
101
|
+
}
|
|
102
|
+
/** A declared incumbent with a graded drop-in that is not level yet (A12). */
|
|
103
|
+
export interface NotLevel extends Row {
|
|
104
|
+
from: string;
|
|
105
|
+
to: string;
|
|
106
|
+
}
|
|
67
107
|
export interface MigrationReport {
|
|
68
108
|
files: number;
|
|
69
109
|
imports: number;
|
|
@@ -72,14 +112,22 @@ export interface MigrationReport {
|
|
|
72
112
|
/** Type-only imports left pointing at the incumbent, each with the note that says why. */
|
|
73
113
|
kept: Kept[];
|
|
74
114
|
detected: Detection;
|
|
115
|
+
/** `add`: the family packages the rewritten imports now name, which the project must depend on. */
|
|
75
116
|
dependencies: {
|
|
76
117
|
before: string[];
|
|
77
118
|
removable: string[];
|
|
78
119
|
after: number;
|
|
120
|
+
add: string[];
|
|
79
121
|
};
|
|
80
|
-
graded: (
|
|
122
|
+
graded: (Row & {
|
|
81
123
|
host: string;
|
|
82
124
|
})[];
|
|
125
|
+
/** Declared incumbents whose drop-in is graded but not level — left alone, with the grade that says why. */
|
|
126
|
+
partial: NotLevel[];
|
|
127
|
+
/** Incumbents on a major the oracle did not grade — left alone, never rewritten onto an API they do not use. */
|
|
128
|
+
offMajor: OffMajor[];
|
|
129
|
+
/** The install and uninstall to run next, for the package manager the lockfile names; `''` when there is none. */
|
|
130
|
+
next: string;
|
|
83
131
|
dryRun: boolean;
|
|
84
132
|
/** N7 — an idempotent command says whether it changed anything; silence is what an agent misreads. */
|
|
85
133
|
changed: boolean;
|
|
@@ -97,6 +145,8 @@ interface Site {
|
|
|
97
145
|
* — the import clause, which is all `bindingsOf` needs. Absent for the other three positions.
|
|
98
146
|
*/
|
|
99
147
|
clause?: string[];
|
|
148
|
+
/** `require('x')`: CommonJS receives the target's whole namespace, not its default export. */
|
|
149
|
+
require?: true;
|
|
100
150
|
}
|
|
101
151
|
interface Scan {
|
|
102
152
|
sites: Site[];
|
|
@@ -154,7 +204,7 @@ export declare function bindingsOf(clause: readonly string[]): {
|
|
|
154
204
|
* source is returned unchanged the moment there is a refusal in it: the unit of success is
|
|
155
205
|
* the file, so the worst case is *nothing changed here, and here is why* (D-051).
|
|
156
206
|
*/
|
|
157
|
-
export declare function rewriteSource(source: string): Rewrite;
|
|
207
|
+
export declare function rewriteSource(source: string, skip?: ReadonlySet<string>): Rewrite;
|
|
158
208
|
/** Every source file under `dir`, relative and slash-separated so a report reads the same everywhere. */
|
|
159
209
|
export declare function sourceFiles(dir: string, at?: string, found?: string[]): string[];
|
|
160
210
|
/**
|