@farmslot/recipe-harness 0.3.2 → 0.4.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/CHANGELOG.md +15 -0
- package/README.md +46 -0
- package/dist/adapters/app-lifecycle.d.ts +41 -0
- package/dist/adapters/app-lifecycle.d.ts.map +1 -0
- package/dist/adapters/app-lifecycle.js +203 -0
- package/dist/adapters/app-lifecycle.js.map +1 -0
- package/dist/cli/flows-command.d.ts +3 -0
- package/dist/cli/flows-command.d.ts.map +1 -0
- package/dist/cli/flows-command.js +145 -0
- package/dist/cli/flows-command.js.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/run-command.d.ts.map +1 -1
- package/dist/cli/run-command.js +7 -0
- package/dist/cli/run-command.js.map +1 -1
- package/dist/cli/support.d.ts +4 -2
- package/dist/cli/support.d.ts.map +1 -1
- package/dist/cli/support.js +7 -3
- package/dist/cli/support.js.map +1 -1
- package/dist/cli/validate-command.d.ts.map +1 -1
- package/dist/cli/validate-command.js +7 -0
- package/dist/cli/validate-command.js.map +1 -1
- package/dist/core/flows.d.ts +6 -0
- package/dist/core/flows.d.ts.map +1 -1
- package/dist/core/flows.js +12 -6
- package/dist/core/flows.js.map +1 -1
- package/dist/core/library.d.ts +72 -0
- package/dist/core/library.d.ts.map +1 -0
- package/dist/core/library.js +240 -0
- package/dist/core/library.js.map +1 -0
- package/dist/core/promote.d.ts +41 -0
- package/dist/core/promote.d.ts.map +1 -0
- package/dist/core/promote.js +249 -0
- package/dist/core/promote.js.map +1 -0
- package/dist/core/runner.d.ts.map +1 -1
- package/dist/core/runner.js +62 -3
- package/dist/core/runner.js.map +1 -1
- package/dist/core/types.d.ts +46 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/validation.d.ts +2 -2
- package/dist/core/validation.d.ts.map +1 -1
- package/dist/core/validation.js +2 -2
- package/dist/core/validation.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/package.json +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@ All notable changes to `@farmslot/recipe-harness` are tracked here.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
- Active-development baseline; add user-facing changes here before release or package publication.
|
|
8
|
+
|
|
9
|
+
## 0.4.0 - 2026-07-07
|
|
10
|
+
|
|
11
|
+
- Add a standard outer `app.lifecycle` adapter for Android and iOS simulator launch/foreground/terminate/restart lifecycle control, with Android background support for performance recipes. Exported as `@farmslot/recipe-harness/adapters/app-lifecycle`.
|
|
12
|
+
|
|
13
|
+
## 0.3.3 - 2026-07-03
|
|
14
|
+
|
|
15
|
+
- `resolved-flows.json` is emitted whenever a run had any library resolution activity (used, overridden, or shadowed flows) — previously a run that overrode every library flow with recipe-local declarations produced no artifact even though `summary.json` recorded the overrides
|
|
16
|
+
- `flows promote` fails loudly, naming every offending catalog file, when the target library already declares the ref in more than one catalog (pre-existing corruption); `--force` no longer overwrites just one of the duplicates and leaves the library unloadable
|
|
17
|
+
- Multi-source recipe library resolution: `call` refs can resolve from ordered, named library sources (`--library name=path`, `RECIPE_LIBRARY_PATH`, or the personal library at `<farmslot home>/recipe-library`). First source wins; recipe-local flows always win. Nothing resolves silently for any consumer: cross-source shadowing and recipe-local overrides are recorded in `summary.json` `flowResolution` (`shadowed`, `overrides`) and in the `resolved-flows.json` artifact alongside the used definitions, in addition to logging
|
|
18
|
+
- `farmslot-recipe flows list` — list library flows with source, description, required params, and last-verified date across configured sources; exits non-zero when no source is configured
|
|
19
|
+
- `farmslot-recipe validate --library` — validate accepts library-resolved `call` refs with the same source resolution as run
|
|
20
|
+
- `farmslot-recipe flows promote` — promote an inline flow from a per-change recipe into a recipe library (default: the personal library, created on first promote). Enforces the catalog contract (description required, postcondition required for `ensure_*`), stamps `provenance.promotedFrom`/`promotedAt`, and stamps `lastVerified` only from a passing run's artifacts (`--run <dir>`)
|
|
21
|
+
|
|
7
22
|
## 0.3.2 - 2026-06-30
|
|
8
23
|
|
|
9
24
|
- Document `orchestrateRuntimeUp` `build` decision as terminal — hosts must call again after native build finishes.
|
package/README.md
CHANGED
|
@@ -140,6 +140,52 @@ yarn workspace @farmslot/recipe-harness build
|
|
|
140
140
|
yarn workspace @farmslot/recipe-harness farmslot-recipe --help
|
|
141
141
|
```
|
|
142
142
|
|
|
143
|
+
## Recipe libraries
|
|
144
|
+
|
|
145
|
+
A recipe library is a directory (or repo) of reusable flow catalogs a `call`
|
|
146
|
+
node can resolve without the recipe declaring a `uses` path:
|
|
147
|
+
|
|
148
|
+
```text
|
|
149
|
+
<library-root>/
|
|
150
|
+
library.json { "kind": "recipe-library", "schema_version": 1, "name": "personal" }
|
|
151
|
+
flows/*.flows.json standard recipe-flow-catalog documents
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Sources are named and ordered; the first source that declares a flow ref wins.
|
|
155
|
+
Configure them per run with repeatable `--library name=path` flags or the
|
|
156
|
+
`RECIPE_LIBRARY_PATH` environment variable (colon-separated, same entry
|
|
157
|
+
format). When neither is set, the harness uses the personal library at
|
|
158
|
+
`<farmslot home>/recipe-library` (`FARMSLOT_HOME`, default `~/.farmslot`) if it
|
|
159
|
+
exists. Recipe-local declarations (inline `flows` and explicit `uses`
|
|
160
|
+
catalogs) always win over library sources.
|
|
161
|
+
|
|
162
|
+
Resolution is never silent: shadowed declarations are logged, `summary.json`
|
|
163
|
+
gains a `flowResolution` block naming each used library flow's source, and the
|
|
164
|
+
artifact package includes `resolved-flows.json` with the exact definitions the
|
|
165
|
+
run executed, so evidence stays reviewable without access to the libraries.
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
farmslot-recipe flows list --library personal=~/.farmslot/recipe-library
|
|
169
|
+
farmslot-recipe run recipe.json --artifacts-dir artifacts \
|
|
170
|
+
--action-manifest action-manifest.json \
|
|
171
|
+
--library personal=~/.farmslot/recipe-library --library team=../team-recipes
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Per-change recipes stay throwaway; `flows promote` is the explicit keep step
|
|
175
|
+
that moves a proven inline flow into a library as a durable contract:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
farmslot-recipe flows promote --from recipe.json --flow demo.write-marker \
|
|
179
|
+
--run artifacts # stamps provenance.lastVerified from the passing run
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Promotion requires a `description`, requires a `postcondition` for `ensure_*`
|
|
183
|
+
flows, and stamps provenance (origin recipe, promotion date, last-verified
|
|
184
|
+
evidence). The default target is the personal library (created on first
|
|
185
|
+
promote); promote into a team library by configuring it as a source and
|
|
186
|
+
passing `--to <name>` — sharing personal flows with a team is just a PR to the
|
|
187
|
+
team's library repo.
|
|
188
|
+
|
|
143
189
|
## Custom adapter
|
|
144
190
|
|
|
145
191
|
```ts
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { ActionAdapter, ActionExecutionContext } from '../core/types.js';
|
|
2
|
+
export type AppLifecyclePlatform = 'android' | 'ios-simulator';
|
|
3
|
+
export type AppLifecycleCommand = 'launch' | 'foreground' | 'background' | 'terminate' | 'restart';
|
|
4
|
+
export interface AppLifecycleTarget {
|
|
5
|
+
platform: AppLifecyclePlatform;
|
|
6
|
+
/** Android adb serial or iOS simulator UDID/name. */
|
|
7
|
+
deviceId?: string;
|
|
8
|
+
/** Android package name or iOS bundle id. */
|
|
9
|
+
appId: string;
|
|
10
|
+
/** Optional deep link used for Expo/dev-client launch and foreground. */
|
|
11
|
+
launchUrl?: string;
|
|
12
|
+
/** Optional Metro port to reverse on Android before opening Expo/dev-client. */
|
|
13
|
+
metroPort?: string | number;
|
|
14
|
+
/** Optional host-side calls to run immediately before launch/foreground. */
|
|
15
|
+
prelaunchCalls?: AppLifecycleCall[];
|
|
16
|
+
}
|
|
17
|
+
export interface AppLifecycleExecResult {
|
|
18
|
+
stdout?: string;
|
|
19
|
+
stderr?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface AppLifecycleCommandRunner {
|
|
22
|
+
execFile(file: string, args: string[], options?: {
|
|
23
|
+
timeoutMs?: number;
|
|
24
|
+
}): Promise<AppLifecycleExecResult>;
|
|
25
|
+
}
|
|
26
|
+
export interface AppLifecycleCall {
|
|
27
|
+
file: string;
|
|
28
|
+
args: string[];
|
|
29
|
+
ignoreFailureWhenOutputIncludes?: string[];
|
|
30
|
+
}
|
|
31
|
+
export interface AppLifecycleTargetProvider {
|
|
32
|
+
resolveTarget(node: Record<string, unknown>, context: ActionExecutionContext): Promise<AppLifecycleTarget> | AppLifecycleTarget;
|
|
33
|
+
}
|
|
34
|
+
export interface CreateAppLifecycleAdapterOptions {
|
|
35
|
+
actions?: Iterable<string>;
|
|
36
|
+
targetProvider: AppLifecycleTargetProvider;
|
|
37
|
+
commandRunner?: AppLifecycleCommandRunner;
|
|
38
|
+
}
|
|
39
|
+
export declare function createAppLifecycleAdapters(options: CreateAppLifecycleAdapterOptions): ActionAdapter[];
|
|
40
|
+
export declare function createAppLifecycleAdapter(options: CreateAppLifecycleAdapterOptions): ActionAdapter;
|
|
41
|
+
//# sourceMappingURL=app-lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-lifecycle.d.ts","sourceRoot":"","sources":["../../src/adapters/app-lifecycle.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAI9E,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,eAAe,CAAC;AAE/D,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,YAAY,GAAG,YAAY,GAAG,WAAW,GAAG,SAAS,CAAC;AAEnG,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,4EAA4E;IAC5E,cAAc,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CACN,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAC/B,OAAO,CAAC,sBAAsB,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,+BAA+B,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,0BAA0B;IACzC,aAAa,CACX,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,kBAAkB,CAAC,GAAG,kBAAkB,CAAC;CACrD;AAED,MAAM,WAAW,gCAAgC;IAC/C,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3B,cAAc,EAAE,0BAA0B,CAAC;IAC3C,aAAa,CAAC,EAAE,yBAAyB,CAAC;CAC3C;AAED,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,gCAAgC,GACxC,aAAa,EAAE,CAGjB;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,gCAAgC,GACxC,aAAa,CA4Cf"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import { asNumber, asOptionalString } from '../core/json.js';
|
|
4
|
+
const execFileAsync = promisify(execFile);
|
|
5
|
+
export function createAppLifecycleAdapters(options) {
|
|
6
|
+
if (options.actions && !new Set(options.actions).has('app.lifecycle'))
|
|
7
|
+
return [];
|
|
8
|
+
return [createAppLifecycleAdapter(options)];
|
|
9
|
+
}
|
|
10
|
+
export function createAppLifecycleAdapter(options) {
|
|
11
|
+
const commandRunner = options.commandRunner ?? defaultCommandRunner();
|
|
12
|
+
return {
|
|
13
|
+
action: 'app.lifecycle',
|
|
14
|
+
async execute(node, context) {
|
|
15
|
+
// Validate every node input before resolving the target or running any
|
|
16
|
+
// command, so a bad knob can never fail the action after side effects.
|
|
17
|
+
const command = parseLifecycleCommand(node);
|
|
18
|
+
const timeoutMs = optionalIntegerInRange(node.timeout_ms, 'app.lifecycle.timeout_ms', 0, Number.MAX_SAFE_INTEGER);
|
|
19
|
+
const settleMs = optionalIntegerInRange(node.settle_ms, 'app.lifecycle.settle_ms', 0, 60_000);
|
|
20
|
+
const target = await options.targetProvider.resolveTarget(node, context);
|
|
21
|
+
const calls = lifecycleCalls(command, target);
|
|
22
|
+
const results = [];
|
|
23
|
+
for (const call of calls) {
|
|
24
|
+
const result = await execLifecycleCall(commandRunner, call, timeoutMs);
|
|
25
|
+
results.push({
|
|
26
|
+
file: call.file,
|
|
27
|
+
args: call.args,
|
|
28
|
+
stdout: result.stdout ?? '',
|
|
29
|
+
stderr: result.stderr ?? '',
|
|
30
|
+
ignoredFailure: result.ignoredFailure ?? false,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (settleMs !== undefined) {
|
|
34
|
+
await new Promise((resolve) => setTimeout(resolve, settleMs));
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
output: {
|
|
38
|
+
command,
|
|
39
|
+
platform: target.platform,
|
|
40
|
+
deviceId: target.deviceId ?? null,
|
|
41
|
+
appId: target.appId,
|
|
42
|
+
launchUrl: target.launchUrl ?? null,
|
|
43
|
+
calls: results,
|
|
44
|
+
settleMs: settleMs ?? 0,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function parseLifecycleCommand(node) {
|
|
51
|
+
// `event` and `state` are accepted as aliases for `command` so recipes can use
|
|
52
|
+
// the field name that reads best for their flow (e.g. state: background).
|
|
53
|
+
const raw = asOptionalString(node.command, 'app.lifecycle.command') ??
|
|
54
|
+
asOptionalString(node.event, 'app.lifecycle.event') ??
|
|
55
|
+
asOptionalString(node.state, 'app.lifecycle.state');
|
|
56
|
+
if (!raw) {
|
|
57
|
+
throw new Error('app.lifecycle.command must be explicit (aliases: event, state). Supported commands: launch, foreground, background, terminate, restart.');
|
|
58
|
+
}
|
|
59
|
+
const command = raw;
|
|
60
|
+
if (command === 'launch' ||
|
|
61
|
+
command === 'foreground' ||
|
|
62
|
+
command === 'background' ||
|
|
63
|
+
command === 'terminate' ||
|
|
64
|
+
command === 'restart') {
|
|
65
|
+
return command;
|
|
66
|
+
}
|
|
67
|
+
throw new Error(`Unsupported app.lifecycle command: ${command}. Supported commands: launch, foreground, background, terminate, restart.`);
|
|
68
|
+
}
|
|
69
|
+
function lifecycleCalls(command, target) {
|
|
70
|
+
if (!target.appId || !target.appId.trim()) {
|
|
71
|
+
throw new Error('app.lifecycle target requires appId.');
|
|
72
|
+
}
|
|
73
|
+
if (command === 'restart') {
|
|
74
|
+
return [
|
|
75
|
+
...lifecycleCalls('terminate', target),
|
|
76
|
+
...(target.prelaunchCalls ?? []),
|
|
77
|
+
...lifecycleCalls('launch', target),
|
|
78
|
+
];
|
|
79
|
+
}
|
|
80
|
+
if (command === 'launch' || command === 'foreground') {
|
|
81
|
+
return [...(target.prelaunchCalls ?? []), ...lifecyclePlatformCalls(command, target)];
|
|
82
|
+
}
|
|
83
|
+
return lifecyclePlatformCalls(command, target);
|
|
84
|
+
}
|
|
85
|
+
function lifecyclePlatformCalls(command, target) {
|
|
86
|
+
if (target.platform === 'android')
|
|
87
|
+
return androidLifecycleCalls(command, target);
|
|
88
|
+
if (target.platform === 'ios-simulator')
|
|
89
|
+
return iosSimulatorLifecycleCalls(command, target);
|
|
90
|
+
throw new Error(`Unsupported app.lifecycle platform: ${String(target.platform)}`);
|
|
91
|
+
}
|
|
92
|
+
function androidLifecycleCalls(command, target) {
|
|
93
|
+
const adb = 'adb';
|
|
94
|
+
const serialArgs = target.deviceId ? ['-s', target.deviceId] : [];
|
|
95
|
+
if (command === 'background') {
|
|
96
|
+
return [{ file: adb, args: [...serialArgs, 'shell', 'input', 'keyevent', 'HOME'] }];
|
|
97
|
+
}
|
|
98
|
+
if (command === 'terminate') {
|
|
99
|
+
return [{ file: adb, args: [...serialArgs, 'shell', 'am', 'force-stop', target.appId] }];
|
|
100
|
+
}
|
|
101
|
+
if (target.launchUrl) {
|
|
102
|
+
const calls = [];
|
|
103
|
+
if (target.metroPort !== undefined && target.metroPort !== '') {
|
|
104
|
+
const port = String(target.metroPort);
|
|
105
|
+
calls.push({
|
|
106
|
+
file: adb,
|
|
107
|
+
args: [...serialArgs, 'reverse', `tcp:${port}`, `tcp:${port}`],
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
calls.push({
|
|
111
|
+
file: adb,
|
|
112
|
+
args: [
|
|
113
|
+
...serialArgs,
|
|
114
|
+
'shell',
|
|
115
|
+
'am',
|
|
116
|
+
'start',
|
|
117
|
+
'-a',
|
|
118
|
+
'android.intent.action.VIEW',
|
|
119
|
+
'-d',
|
|
120
|
+
target.launchUrl,
|
|
121
|
+
],
|
|
122
|
+
});
|
|
123
|
+
return calls;
|
|
124
|
+
}
|
|
125
|
+
return [
|
|
126
|
+
{
|
|
127
|
+
file: adb,
|
|
128
|
+
args: [
|
|
129
|
+
...serialArgs,
|
|
130
|
+
'shell',
|
|
131
|
+
'monkey',
|
|
132
|
+
'-p',
|
|
133
|
+
target.appId,
|
|
134
|
+
'-c',
|
|
135
|
+
'android.intent.category.LAUNCHER',
|
|
136
|
+
'1',
|
|
137
|
+
],
|
|
138
|
+
},
|
|
139
|
+
];
|
|
140
|
+
}
|
|
141
|
+
function iosSimulatorLifecycleCalls(command, target) {
|
|
142
|
+
const device = target.deviceId ?? 'booted';
|
|
143
|
+
if (command === 'background') {
|
|
144
|
+
// iOS Simulator has no direct HOME equivalent; foreground Settings to background the app under test.
|
|
145
|
+
return [{ file: 'xcrun', args: ['simctl', 'launch', device, 'com.apple.Preferences'] }];
|
|
146
|
+
}
|
|
147
|
+
if (command === 'terminate') {
|
|
148
|
+
return [
|
|
149
|
+
{
|
|
150
|
+
file: 'xcrun',
|
|
151
|
+
args: ['simctl', 'terminate', device, target.appId],
|
|
152
|
+
// simctl terminate exits non-zero when the app is already stopped; restart should remain idempotent.
|
|
153
|
+
ignoreFailureWhenOutputIncludes: ['not running'],
|
|
154
|
+
},
|
|
155
|
+
];
|
|
156
|
+
}
|
|
157
|
+
if (target.launchUrl) {
|
|
158
|
+
return [{ file: 'xcrun', args: ['simctl', 'openurl', device, target.launchUrl] }];
|
|
159
|
+
}
|
|
160
|
+
return [{ file: 'xcrun', args: ['simctl', 'launch', device, target.appId] }];
|
|
161
|
+
}
|
|
162
|
+
async function execLifecycleCall(commandRunner, call, timeoutMs) {
|
|
163
|
+
try {
|
|
164
|
+
return await commandRunner.execFile(call.file, call.args, { timeoutMs });
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
const text = error instanceof Error ? error.message : String(error);
|
|
168
|
+
if (call.ignoreFailureWhenOutputIncludes?.some((needle) => text.includes(needle))) {
|
|
169
|
+
return { stderr: text, ignoredFailure: true };
|
|
170
|
+
}
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
function optionalIntegerInRange(value, label, min, max) {
|
|
175
|
+
if (value == null)
|
|
176
|
+
return undefined;
|
|
177
|
+
const number = asNumber(value, label);
|
|
178
|
+
if (!Number.isInteger(number) || number < min || number > max) {
|
|
179
|
+
throw new Error(`${label} must be an integer from ${min} through ${max}.`);
|
|
180
|
+
}
|
|
181
|
+
return number;
|
|
182
|
+
}
|
|
183
|
+
function defaultCommandRunner() {
|
|
184
|
+
return {
|
|
185
|
+
async execFile(file, args, options) {
|
|
186
|
+
try {
|
|
187
|
+
return await execFileAsync(file, args, {
|
|
188
|
+
timeout: options?.timeoutMs,
|
|
189
|
+
encoding: 'utf8',
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
if (error instanceof Error) {
|
|
194
|
+
const output = error;
|
|
195
|
+
const details = [output.message, output.stderr, output.stdout].filter(Boolean).join('\n');
|
|
196
|
+
throw new Error(`${file} ${args.join(' ')} failed: ${details}`);
|
|
197
|
+
}
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=app-lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-lifecycle.js","sourceRoot":"","sources":["../../src/adapters/app-lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flows-command.d.ts","sourceRoot":"","sources":["../../src/cli/flows-command.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AA6BzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgF3D"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { isRecord, readJsonFile } from '../core/json.js';
|
|
3
|
+
import { loadRecipeLibraries, personalRecipeLibraryRoot, resolveRecipeLibrarySources, } from '../core/library.js';
|
|
4
|
+
import { promoteRecipeFlow } from '../core/promote.js';
|
|
5
|
+
import { resolveRecipeCliPath } from './support.js';
|
|
6
|
+
export function registerFlowsCommand(program) {
|
|
7
|
+
const flows = program
|
|
8
|
+
.command('flows')
|
|
9
|
+
.description('Inspect flows available from configured recipe library sources');
|
|
10
|
+
flows
|
|
11
|
+
.command('list')
|
|
12
|
+
.description('List every library flow with its source, in precedence order')
|
|
13
|
+
.option('--library <entry>', 'Recipe library source as name=path or path (repeatable; order is precedence, first wins). Defaults to RECIPE_LIBRARY_PATH, then the personal library under the farmslot home.', collectRepeatable, [])
|
|
14
|
+
.option('--json', 'Print the flow list as JSON')
|
|
15
|
+
.action(async (options) => {
|
|
16
|
+
const sources = await resolveRecipeLibrarySources({ cliEntries: options.library });
|
|
17
|
+
if (sources.length === 0) {
|
|
18
|
+
const message = 'No recipe library sources configured. Pass --library name=path, set RECIPE_LIBRARY_PATH, or create a personal library under the farmslot home (recipe-library/library.json).';
|
|
19
|
+
if (options.json) {
|
|
20
|
+
console.log(JSON.stringify({ sources: [], flows: [] }, null, 2));
|
|
21
|
+
}
|
|
22
|
+
console.error(message);
|
|
23
|
+
process.exitCode = 1;
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const resolution = await loadRecipeLibraries(sources, options.json ? undefined : console);
|
|
27
|
+
if (options.json) {
|
|
28
|
+
console.log(JSON.stringify(flowsListDocument(resolution), null, 2));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
printFlowsList(resolution);
|
|
32
|
+
});
|
|
33
|
+
flows
|
|
34
|
+
.command('promote')
|
|
35
|
+
.description('Promote an inline flow from a per-change recipe into a recipe library (the durable keep behind throwaway proofs)')
|
|
36
|
+
.requiredOption('--from <recipe>', 'Per-change recipe declaring the flow inline')
|
|
37
|
+
.requiredOption('--flow <ref>', 'Flow ref to promote')
|
|
38
|
+
.option('--to <name>', 'Target library source name', 'personal')
|
|
39
|
+
.option('--library <entry>', 'Recipe library source as name=path or path (repeatable; order is precedence, first wins). Defaults to RECIPE_LIBRARY_PATH, then the personal library under the farmslot home.', collectRepeatable, [])
|
|
40
|
+
.option('--domain <stem>', 'Catalog file stem (defaults to the ref minus its last segment)')
|
|
41
|
+
.option('--run <artifactsDir>', 'Artifacts directory of a passing run that exercised the flow; stamps provenance.lastVerified')
|
|
42
|
+
.option('--force', 'Overwrite an existing declaration of the same ref')
|
|
43
|
+
.action(async (options) => {
|
|
44
|
+
const target = await resolvePromoteTarget(options.to, options.library);
|
|
45
|
+
const result = await promoteRecipeFlow({
|
|
46
|
+
recipePath: resolveRecipeCliPath(options.from),
|
|
47
|
+
flowRef: options.flow,
|
|
48
|
+
targetRoot: target.root,
|
|
49
|
+
targetName: target.name ?? options.to,
|
|
50
|
+
domain: options.domain,
|
|
51
|
+
runArtifactsDir: options.run ? resolveRecipeCliPath(options.run) : undefined,
|
|
52
|
+
force: options.force,
|
|
53
|
+
logger: console,
|
|
54
|
+
});
|
|
55
|
+
if (result.createdLibrary) {
|
|
56
|
+
console.log(`Created recipe library ${options.to} at ${target.root}`);
|
|
57
|
+
}
|
|
58
|
+
console.log(`Promoted ${result.ref} to ${result.catalogPath}`);
|
|
59
|
+
console.log(result.lastVerified
|
|
60
|
+
? `lastVerified stamped from run evidence: ${result.lastVerified}`
|
|
61
|
+
: 'No run evidence provided (--run); the flow carries no lastVerified stamp.');
|
|
62
|
+
if (options.to === 'personal') {
|
|
63
|
+
console.log('Share it with your team by opening a PR to the team recipe library.');
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
async function resolvePromoteTarget(to, cliEntries) {
|
|
68
|
+
const sources = await resolveRecipeLibrarySources({ cliEntries });
|
|
69
|
+
const resolved = await Promise.all(sources.map(async (source) => ({
|
|
70
|
+
...source,
|
|
71
|
+
name: source.name ?? (await libraryManifestName(source.root)),
|
|
72
|
+
})));
|
|
73
|
+
const named = resolved.find((source) => source.name === to);
|
|
74
|
+
if (named)
|
|
75
|
+
return named;
|
|
76
|
+
if (to === 'personal')
|
|
77
|
+
return { name: 'personal', root: personalRecipeLibraryRoot() };
|
|
78
|
+
const available = resolved.map((source) => source.name ?? source.root).join(', ') || 'none';
|
|
79
|
+
throw new Error(`No recipe library source named ${to} is configured (available: ${available}). Pass --library ${to}=path or set RECIPE_LIBRARY_PATH.`);
|
|
80
|
+
}
|
|
81
|
+
// Bare-path sources get their name from library.json, matching how run
|
|
82
|
+
// resolution names them.
|
|
83
|
+
async function libraryManifestName(root) {
|
|
84
|
+
try {
|
|
85
|
+
const manifest = await readJsonFile(path.join(root, 'library.json'));
|
|
86
|
+
if (isRecord(manifest) && typeof manifest.name === 'string' && manifest.name) {
|
|
87
|
+
return manifest.name;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// not a readable library; leave the source unnamed
|
|
92
|
+
}
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
function flowsListDocument(resolution) {
|
|
96
|
+
return {
|
|
97
|
+
sources: resolution.sources,
|
|
98
|
+
flows: [...resolution.flows.values()]
|
|
99
|
+
.sort((a, b) => a.ref.localeCompare(b.ref))
|
|
100
|
+
.map((flow) => ({
|
|
101
|
+
ref: flow.ref,
|
|
102
|
+
source: flow.source,
|
|
103
|
+
file: flow.file,
|
|
104
|
+
...(flowDescription(flow.raw) ? { description: flowDescription(flow.raw) } : {}),
|
|
105
|
+
...(requiredParams(flow.raw).length > 0
|
|
106
|
+
? { requiredParams: requiredParams(flow.raw) }
|
|
107
|
+
: {}),
|
|
108
|
+
...(flow.shadows.length > 0 ? { shadows: flow.shadows } : {}),
|
|
109
|
+
...(flow.lastVerified ? { lastVerified: flow.lastVerified } : {}),
|
|
110
|
+
})),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function printFlowsList(resolution) {
|
|
114
|
+
if (resolution.flows.size === 0) {
|
|
115
|
+
console.log('No flows found in the configured recipe libraries.');
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
for (const flow of [...resolution.flows.values()].sort((a, b) => a.ref.localeCompare(b.ref))) {
|
|
119
|
+
const details = [
|
|
120
|
+
`source=${flow.source}`,
|
|
121
|
+
`file=${flow.file}`,
|
|
122
|
+
...(flow.lastVerified ? [`lastVerified=${flow.lastVerified}`] : []),
|
|
123
|
+
...(flow.shadows.length > 0 ? [`shadows=${flow.shadows.join(',')}`] : []),
|
|
124
|
+
];
|
|
125
|
+
console.log(`${flow.ref} ${details.join(' ')}`);
|
|
126
|
+
const description = flowDescription(flow.raw);
|
|
127
|
+
if (description)
|
|
128
|
+
console.log(` ${description}`);
|
|
129
|
+
const params = requiredParams(flow.raw);
|
|
130
|
+
if (params.length > 0)
|
|
131
|
+
console.log(` params: ${params.join(', ')}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function flowDescription(raw) {
|
|
135
|
+
return typeof raw.description === 'string' && raw.description ? raw.description : undefined;
|
|
136
|
+
}
|
|
137
|
+
function requiredParams(raw) {
|
|
138
|
+
if (!isRecord(raw.paramsSchema) || !Array.isArray(raw.paramsSchema.required))
|
|
139
|
+
return [];
|
|
140
|
+
return raw.paramsSchema.required.filter((entry) => typeof entry === 'string');
|
|
141
|
+
}
|
|
142
|
+
function collectRepeatable(value, previous) {
|
|
143
|
+
return [...previous, value];
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=flows-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flows-command.js","sourceRoot":"","sources":["../../src/cli/flows-command.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,wBAAgB,0BAA0B,IAAI,OAAO,CAYpD;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvE"}
|
package/dist/cli/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { pathToFileURL } from 'node:url';
|
|
2
2
|
import { Command } from 'commander';
|
|
3
|
+
import { registerFlowsCommand } from './flows-command.js';
|
|
3
4
|
import { registerRunCommand } from './run-command.js';
|
|
4
5
|
import { registerValidateCommand } from './validate-command.js';
|
|
5
6
|
const CLI_VERSION = '0.1.0';
|
|
@@ -11,6 +12,7 @@ export function createRecipeHarnessProgram() {
|
|
|
11
12
|
.version(CLI_VERSION);
|
|
12
13
|
registerValidateCommand(program);
|
|
13
14
|
registerRunCommand(program);
|
|
15
|
+
registerFlowsCommand(program);
|
|
14
16
|
return program;
|
|
15
17
|
}
|
|
16
18
|
export async function runRecipeHarnessCli(argv) {
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,MAAM,WAAW,GAAG,OAAO,CAAC;AAE5B,MAAM,UAAU,0BAA0B;IACxC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAC9B,OAAO;SACJ,IAAI,CAAC,iBAAiB,CAAC;SACvB,WAAW,CAAC,gCAAgC,CAAC;SAC7C,OAAO,CAAC,WAAW,CAAC,CAAC;IAExB,uBAAuB,CAAC,OAAO,CAAC,CAAC;IACjC,kBAAkB,CAAC,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,MAAM,WAAW,GAAG,OAAO,CAAC;AAE5B,MAAM,UAAU,0BAA0B;IACxC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAC9B,OAAO;SACJ,IAAI,CAAC,iBAAiB,CAAC;SACvB,WAAW,CAAC,gCAAgC,CAAC;SAC7C,OAAO,CAAC,WAAW,CAAC,CAAC;IAExB,uBAAuB,CAAC,OAAO,CAAC,CAAC;IACjC,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC5B,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAE9B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAc;IACtD,MAAM,0BAA0B,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/E,IAAI,CAAC;QACH,MAAM,mBAAmB,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-command.d.ts","sourceRoot":"","sources":["../../src/cli/run-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"run-command.d.ts","sourceRoot":"","sources":["../../src/cli/run-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAkCzC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiDzD"}
|
package/dist/cli/run-command.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getRecipeActionManifestActionNames, } from '@farmslot/protocol';
|
|
2
2
|
import { createStandardCoreAdapters } from '../adapters/core.js';
|
|
3
|
+
import { resolveRecipeLibrarySources } from '../core/library.js';
|
|
3
4
|
import { createRecipeRunner } from '../core/runner.js';
|
|
4
5
|
import { parsePositiveInteger, parseRecordingTarget, readRecipeCliJsonFile, resolveRecipeCliPath, } from './support.js';
|
|
5
6
|
export function registerRunCommand(program) {
|
|
@@ -10,6 +11,7 @@ export function registerRunCommand(program) {
|
|
|
10
11
|
.requiredOption('--artifacts-dir <dir>', 'Directory where artifacts are written')
|
|
11
12
|
.requiredOption('--action-manifest <manifest>', 'Runner action manifest JSON')
|
|
12
13
|
.option('--project-root <dir>', 'Project root used by command/artifact adapters')
|
|
14
|
+
.option('--library <entry>', 'Recipe library source as name=path or path (repeatable; order is precedence, first wins). Defaults to RECIPE_LIBRARY_PATH, then the personal library under the farmslot home.', collectRepeatable, [])
|
|
13
15
|
.option('--record-video [mode]', 'Record one whole-recipe MP4 when visual motion proof helps')
|
|
14
16
|
.option('--record-max-fps <fps>', 'Maximum video frame rate')
|
|
15
17
|
.option('--record-max-size <px>', 'Maximum recorded video dimension')
|
|
@@ -27,6 +29,7 @@ export function registerRunCommand(program) {
|
|
|
27
29
|
}),
|
|
28
30
|
logger: console,
|
|
29
31
|
});
|
|
32
|
+
const librarySources = await resolveRecipeLibrarySources({ cliEntries: options.library });
|
|
30
33
|
const result = await runner.run({
|
|
31
34
|
recipePath: resolveRecipeCliPath(recipePath),
|
|
32
35
|
artifactsDir: resolveRecipeCliPath(options.artifactsDir),
|
|
@@ -34,6 +37,7 @@ export function registerRunCommand(program) {
|
|
|
34
37
|
? resolveRecipeCliPath(options.projectRoot)
|
|
35
38
|
: resolveRecipeCliPath('.'),
|
|
36
39
|
recordVideo: parseRecordVideoOptions(options),
|
|
40
|
+
...(librarySources.length > 0 ? { librarySources } : {}),
|
|
37
41
|
});
|
|
38
42
|
if (options.json) {
|
|
39
43
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -46,6 +50,9 @@ export function registerRunCommand(program) {
|
|
|
46
50
|
process.exit(1);
|
|
47
51
|
});
|
|
48
52
|
}
|
|
53
|
+
function collectRepeatable(value, previous) {
|
|
54
|
+
return [...previous, value];
|
|
55
|
+
}
|
|
49
56
|
function parseRecordVideoOptions(options) {
|
|
50
57
|
if (!options.recordVideo)
|
|
51
58
|
return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-command.js","sourceRoot":"","sources":["../../src/cli/run-command.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,kCAAkC,GAEnC,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAGvD,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"run-command.js","sourceRoot":"","sources":["../../src/cli/run-command.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/support.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { type RecipeValidationResult } from '@farmslot/protocol';
|
|
2
|
-
import type { RecordingTarget } from '../core/types.js';
|
|
2
|
+
import type { RecipeLibrarySource, RecordingTarget } from '../core/types.js';
|
|
3
3
|
interface RecipeValidationInputOptions {
|
|
4
4
|
recipePath: string;
|
|
5
5
|
actionManifestPath?: string;
|
|
6
6
|
artifactManifestPath?: string;
|
|
7
7
|
artifactDir?: string;
|
|
8
8
|
baseDir?: string;
|
|
9
|
+
/** Library sources whose flow refs count as resolvable, mirroring run resolution. */
|
|
10
|
+
librarySources?: RecipeLibrarySource[];
|
|
9
11
|
}
|
|
10
12
|
interface RecipeCliRecordingTargetOptions {
|
|
11
13
|
recordAppName?: string;
|
|
@@ -18,6 +20,6 @@ export declare function resolveRecipeCliPath(filePath: string, baseDir?: string)
|
|
|
18
20
|
export declare function parsePositiveInteger(value: string): number;
|
|
19
21
|
export declare function parseRecordingTarget(options: RecipeCliRecordingTargetOptions): RecordingTarget | undefined;
|
|
20
22
|
export declare function readRecipeCliJsonFile(filePath: string, baseDir?: string): Promise<unknown>;
|
|
21
|
-
export declare function validateRecipeCliInput({ recipePath, actionManifestPath, artifactManifestPath, artifactDir, baseDir, }: RecipeValidationInputOptions): Promise<RecipeValidationResult>;
|
|
23
|
+
export declare function validateRecipeCliInput({ recipePath, actionManifestPath, artifactManifestPath, artifactDir, baseDir, librarySources, }: RecipeValidationInputOptions): Promise<RecipeValidationResult>;
|
|
22
24
|
export {};
|
|
23
25
|
//# sourceMappingURL=support.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"support.d.ts","sourceRoot":"","sources":["../../src/cli/support.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,sBAAsB,EAK5B,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"support.d.ts","sourceRoot":"","sources":["../../src/cli/support.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,sBAAsB,EAK5B,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAE7E,UAAU,4BAA4B;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,cAAc,CAAC,EAAE,mBAAmB,EAAE,CAAC;CACxC;AAED,UAAU,+BAA+B;IACvC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,SAAqB,GAAG,MAAM,CAE3F;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM1D;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,+BAA+B,GACvC,eAAe,GAAG,SAAS,CAc7B;AAED,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAChB,OAAO,SAAqB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAUlB;AA2BD,wBAAsB,sBAAsB,CAAC,EAC3C,UAAU,EACV,kBAAkB,EAClB,oBAAoB,EACpB,WAAW,EACX,OAA4B,EAC5B,cAAc,GACf,EAAE,4BAA4B,GAAG,OAAO,CAAC,sBAAsB,CAAC,CA0ChE"}
|