@farmslot/recipe-harness 0.2.2 → 0.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/CHANGELOG.md +33 -0
- package/README.md +6 -1
- package/dist/runtime/decision-types.d.ts +23 -0
- package/dist/runtime/decision-types.d.ts.map +1 -0
- package/dist/runtime/decision-types.js +2 -0
- package/dist/runtime/decision-types.js.map +1 -0
- package/dist/runtime/deps-readiness.d.ts +20 -0
- package/dist/runtime/deps-readiness.d.ts.map +1 -0
- package/dist/runtime/deps-readiness.js +93 -0
- package/dist/runtime/deps-readiness.js.map +1 -0
- package/dist/runtime/log-analysis.d.ts +42 -0
- package/dist/runtime/log-analysis.d.ts.map +1 -0
- package/dist/runtime/log-analysis.js +104 -0
- package/dist/runtime/log-analysis.js.map +1 -0
- package/dist/runtime/metro-probe.d.ts +5 -0
- package/dist/runtime/metro-probe.d.ts.map +1 -0
- package/dist/runtime/metro-probe.js +22 -0
- package/dist/runtime/metro-probe.js.map +1 -0
- package/package.json +22 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@farmslot/recipe-harness` are tracked here.
|
|
4
|
+
|
|
5
|
+
## Unreleased
|
|
6
|
+
|
|
7
|
+
## 0.3.0 - 2026-06-26
|
|
8
|
+
|
|
9
|
+
- Add shared runtime-readiness helpers under `@farmslot/recipe-harness/runtime/*`:
|
|
10
|
+
- `deps-readiness` — install fingerprint, baseline recording, product-marker partial checks, decision state persistence
|
|
11
|
+
- `log-analysis` — Metro/RN bundle log boundaries, unresolved-module scoping, persistent bundle-error detection
|
|
12
|
+
- `metro-probe` — packager `/status` reachability probe
|
|
13
|
+
- `decision-types` — portable `RuntimeDecisionReport` / `RuntimeDecisionAction` shapes
|
|
14
|
+
- Product runners (e.g. MetaMask) should import these modules instead of copying readiness logic locally.
|
|
15
|
+
|
|
16
|
+
## 0.2.2 - 2026-06-10
|
|
17
|
+
|
|
18
|
+
- Publish with npm-resolvable `@farmslot/protocol` dependency metadata instead of workspace-only protocol references.
|
|
19
|
+
|
|
20
|
+
## 0.2.1 - 2026-06-10
|
|
21
|
+
|
|
22
|
+
- Drive CDP text inputs with trusted keyboard insertion instead of direct DOM value assignment so React-controlled inputs receive real input/change handling.
|
|
23
|
+
- Drive CDP clicks with real mouse events and expose `ui.key_press` through the standard UI adapter.
|
|
24
|
+
|
|
25
|
+
## 0.2.0 - 2026-06-02
|
|
26
|
+
|
|
27
|
+
- Define the v0 public harness package surface with explicit core, adapter, node, CLI, and runtime entry points.
|
|
28
|
+
- Publish recipe runner runtime helpers under explicit `runtime/*` subpaths for browser extension, CDP, and React Native bridge clients.
|
|
29
|
+
- Keep CLI and writer implementation details behind explicit subpath exports instead of wildcard package exports.
|
|
30
|
+
|
|
31
|
+
## 0.1.0 - 2026-05-31
|
|
32
|
+
|
|
33
|
+
- Initial public active-development release.
|
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ npm install @farmslot/recipe-harness @farmslot/protocol
|
|
|
39
39
|
| `src/index.ts` | Public package export surface. |
|
|
40
40
|
| `src/core/` | Manifest-aware recipe graph execution, flow calls, predicates, HUD node shaping, and harness-local types. |
|
|
41
41
|
| `src/adapters/` | Standard core and UI adapter factories. |
|
|
42
|
-
| `src/runtime/` | Runtime transports
|
|
42
|
+
| `src/runtime/` | Runtime transports (CDP, browser extensions, RN bridge) and shared readiness helpers (deps, log analysis, Metro probe). |
|
|
43
43
|
| `src/node/` | Node-only artifact, trace, and summary writers. |
|
|
44
44
|
| `src/cli/` | CLI entrypoint, commands, and shared CLI validation helpers. |
|
|
45
45
|
| `test/` | Harness package and export-boundary tests mirroring public behavior. |
|
|
@@ -60,6 +60,10 @@ listed here.
|
|
|
60
60
|
| `@farmslot/recipe-harness/runtime/cdp` | CDP browser transport helpers. |
|
|
61
61
|
| `@farmslot/recipe-harness/runtime/react-native-bridge` | React Native bridge transport helpers. |
|
|
62
62
|
| `@farmslot/recipe-harness/runtime/browser-extension` | Browser-extension target helpers. |
|
|
63
|
+
| `@farmslot/recipe-harness/runtime/deps-readiness` | Install fingerprint, baseline, product-marker partial checks. |
|
|
64
|
+
| `@farmslot/recipe-harness/runtime/log-analysis` | Bundle-log boundaries, unresolved-module scoping, persistent bundle-error state. |
|
|
65
|
+
| `@farmslot/recipe-harness/runtime/metro-probe` | Metro packager `/status` reachability probe. |
|
|
66
|
+
| `@farmslot/recipe-harness/runtime/decision-types` | Portable `RuntimeDecisionReport` / action shapes for product adapters. |
|
|
63
67
|
| `@farmslot/recipe-harness/cli` | Programmatic CLI entrypoint. |
|
|
64
68
|
| `@farmslot/recipe-harness/cli/support` | Shared CLI input validation helpers. |
|
|
65
69
|
| `@farmslot/recipe-harness/writers` | Node-only JSON artifact writers. |
|
|
@@ -68,6 +72,7 @@ listed here.
|
|
|
68
72
|
|
|
69
73
|
The harness owns generic execution mechanics:
|
|
70
74
|
|
|
75
|
+
- runtime-readiness primitives (`runtime/deps-readiness`, `runtime/log-analysis`, `runtime/metro-probe`) — product runners supply adapter-specific markers, log patterns, and shell launch;
|
|
71
76
|
- manifest-aware runner construction;
|
|
72
77
|
- graph execution, `call` flow composition, setup/start-state/proof/teardown ordering;
|
|
73
78
|
- standard core adapters such as `command`, `wait`, `assert_json`, `watch_logs`, and `end`;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { DepsCheck } from './deps-readiness.js';
|
|
2
|
+
/** Stable id a host branches on when executing `actions[]`. */
|
|
3
|
+
export interface RuntimeDecisionAction {
|
|
4
|
+
id: string;
|
|
5
|
+
argv?: string[];
|
|
6
|
+
cwd?: string;
|
|
7
|
+
paths?: string[];
|
|
8
|
+
}
|
|
9
|
+
export type RuntimeReadinessDecision = 'install' | 'build' | 'launch' | 'relaunch' | 'ready' | 'blocked' | 'unknown';
|
|
10
|
+
export interface RuntimeDecisionReport<TChecks extends Record<string, unknown> = Record<string, unknown>> {
|
|
11
|
+
schemaVersion: 1;
|
|
12
|
+
adapter: string;
|
|
13
|
+
target: string;
|
|
14
|
+
decision: RuntimeReadinessDecision;
|
|
15
|
+
reasonCode: string;
|
|
16
|
+
reasons: string[];
|
|
17
|
+
checks: TChecks;
|
|
18
|
+
actions: RuntimeDecisionAction[];
|
|
19
|
+
/** Extension-only: build must clear webpack cache first. */
|
|
20
|
+
clean?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export type { DepsCheck };
|
|
23
|
+
//# sourceMappingURL=decision-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision-types.d.ts","sourceRoot":"","sources":["../../src/runtime/decision-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,+DAA+D;AAC/D,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,MAAM,wBAAwB,GAChC,SAAS,GACT,OAAO,GACP,QAAQ,GACR,UAAU,GACV,OAAO,GACP,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,WAAW,qBAAqB,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACtG,aAAa,EAAE,CAAC,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,wBAAwB,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACjC,4DAA4D;IAC5D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,YAAY,EAAE,SAAS,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision-types.js","sourceRoot":"","sources":["../../src/runtime/decision-types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Lock/manifest inputs hashed for the deps baseline. */
|
|
2
|
+
export declare const DEPS_INPUTS: string[];
|
|
3
|
+
/** Yarn install-state markers. */
|
|
4
|
+
export declare const INSTALL_MARKERS: string[];
|
|
5
|
+
export interface DepsCheck {
|
|
6
|
+
installed: boolean;
|
|
7
|
+
status: 'current' | 'stale' | 'missing' | 'partial';
|
|
8
|
+
hasBaseline: boolean;
|
|
9
|
+
missingProducts?: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare function depsFingerprint(target: string, extraInputs?: string[]): string;
|
|
12
|
+
/** Record the current deps fingerprint as the install baseline (OS temp dir). */
|
|
13
|
+
export declare function recordDepsBaseline(target: string): void;
|
|
14
|
+
export declare function readDecisionState(target: string, name: string): Record<string, unknown> | null;
|
|
15
|
+
export declare function writeDecisionState(target: string, name: string, value: Record<string, unknown>): void;
|
|
16
|
+
export declare function clearDecisionState(target: string, name: string): void;
|
|
17
|
+
export declare function depsCheck(target: string, options?: {
|
|
18
|
+
productMarkers?: string[];
|
|
19
|
+
}): DepsCheck;
|
|
20
|
+
//# sourceMappingURL=deps-readiness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deps-readiness.d.ts","sourceRoot":"","sources":["../../src/runtime/deps-readiness.ts"],"names":[],"mappings":"AAKA,yDAAyD;AACzD,eAAO,MAAM,WAAW,UAAiE,CAAC;AAE1F,kCAAkC;AAClC,eAAO,MAAM,eAAe,UAA6D,CAAC;AAE1F,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IACpD,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAgCD,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,GAAE,MAAM,EAAO,GAAG,MAAM,CAWlF;AAMD,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAEvD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAE9F;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAErG;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAMrE;AAED,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,GAC1C,SAAS,CAwBX"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
/** Lock/manifest inputs hashed for the deps baseline. */
|
|
6
|
+
export const DEPS_INPUTS = ['package.json', 'yarn.lock', '.yarnrc.yml', '.tool-versions'];
|
|
7
|
+
/** Yarn install-state markers. */
|
|
8
|
+
export const INSTALL_MARKERS = ['node_modules/.yarn-state.yml', '.yarn/install-state.gz'];
|
|
9
|
+
const STATE_NAMESPACE = 'farmslot-recipe-runtime-decision';
|
|
10
|
+
function stateDir(target) {
|
|
11
|
+
const key = crypto.createHash('sha1').update(path.resolve(target)).digest('hex').slice(0, 16);
|
|
12
|
+
return path.join(os.tmpdir(), STATE_NAMESPACE, key);
|
|
13
|
+
}
|
|
14
|
+
function readBaseline(target, name) {
|
|
15
|
+
try {
|
|
16
|
+
return JSON.parse(fs.readFileSync(path.join(stateDir(target), name), 'utf8'));
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function writeBaseline(target, name, value) {
|
|
23
|
+
const dir = stateDir(target);
|
|
24
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
25
|
+
fs.writeFileSync(path.join(dir, name), `${JSON.stringify(value, null, 2)}\n`);
|
|
26
|
+
}
|
|
27
|
+
function newestMtime(target, rels) {
|
|
28
|
+
let newest = 0;
|
|
29
|
+
for (const rel of rels) {
|
|
30
|
+
const abs = path.join(target, rel);
|
|
31
|
+
if (fs.existsSync(abs))
|
|
32
|
+
newest = Math.max(newest, fs.statSync(abs).mtimeMs);
|
|
33
|
+
}
|
|
34
|
+
return newest;
|
|
35
|
+
}
|
|
36
|
+
export function depsFingerprint(target, extraInputs = []) {
|
|
37
|
+
const hash = crypto.createHash('sha256');
|
|
38
|
+
for (const rel of [...DEPS_INPUTS, ...extraInputs]) {
|
|
39
|
+
const abs = path.join(target, rel);
|
|
40
|
+
if (!fs.existsSync(abs))
|
|
41
|
+
continue;
|
|
42
|
+
hash.update(rel);
|
|
43
|
+
hash.update('\0');
|
|
44
|
+
hash.update(fs.readFileSync(abs));
|
|
45
|
+
hash.update('\0');
|
|
46
|
+
}
|
|
47
|
+
return hash.digest('hex');
|
|
48
|
+
}
|
|
49
|
+
function missingProductMarkers(target, markers) {
|
|
50
|
+
return markers.filter((rel) => !fs.existsSync(path.join(target, rel)));
|
|
51
|
+
}
|
|
52
|
+
/** Record the current deps fingerprint as the install baseline (OS temp dir). */
|
|
53
|
+
export function recordDepsBaseline(target) {
|
|
54
|
+
writeBaseline(target, 'deps-state.json', { fingerprint: depsFingerprint(target) });
|
|
55
|
+
}
|
|
56
|
+
export function readDecisionState(target, name) {
|
|
57
|
+
return readBaseline(target, name);
|
|
58
|
+
}
|
|
59
|
+
export function writeDecisionState(target, name, value) {
|
|
60
|
+
writeBaseline(target, name, value);
|
|
61
|
+
}
|
|
62
|
+
export function clearDecisionState(target, name) {
|
|
63
|
+
try {
|
|
64
|
+
fs.unlinkSync(path.join(stateDir(target), name));
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// no prior state
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function depsCheck(target, options = {}) {
|
|
71
|
+
const productMarkers = options.productMarkers ?? [];
|
|
72
|
+
const inputs = DEPS_INPUTS.filter((rel) => fs.existsSync(path.join(target, rel)));
|
|
73
|
+
const installed = inputs.length > 0 && INSTALL_MARKERS.some((rel) => fs.existsSync(path.join(target, rel)));
|
|
74
|
+
if (!installed)
|
|
75
|
+
return { installed: false, status: 'missing', hasBaseline: false };
|
|
76
|
+
const missingProducts = missingProductMarkers(target, productMarkers);
|
|
77
|
+
if (missingProducts.length > 0) {
|
|
78
|
+
return {
|
|
79
|
+
installed: true,
|
|
80
|
+
status: 'partial',
|
|
81
|
+
hasBaseline: false,
|
|
82
|
+
missingProducts,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const baseline = readBaseline(target, 'deps-state.json');
|
|
86
|
+
if (!baseline) {
|
|
87
|
+
const drift = newestMtime(target, inputs) > newestMtime(target, INSTALL_MARKERS);
|
|
88
|
+
return { installed: true, status: drift ? 'stale' : 'current', hasBaseline: false };
|
|
89
|
+
}
|
|
90
|
+
const status = baseline.fingerprint === depsFingerprint(target) ? 'current' : 'stale';
|
|
91
|
+
return { installed: true, status, hasBaseline: true };
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=deps-readiness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deps-readiness.js","sourceRoot":"","sources":["../../src/runtime/deps-readiness.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export declare function packageRootsForModule(target: string, moduleName: string): string[];
|
|
2
|
+
/** True when the resolved package root contains package.json (ignores empty dirs). */
|
|
3
|
+
export declare function moduleExistsInNodeModules(target: string, moduleName: string): boolean;
|
|
4
|
+
export declare function unresolvedModulesFromLogSlice(lines: string[], startIndex?: number): string[];
|
|
5
|
+
export declare function bundleErrorExcerptHash(excerpt: string): string;
|
|
6
|
+
export interface LogBoundaryScan {
|
|
7
|
+
lastErr: number;
|
|
8
|
+
lastOk: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function scanLogBoundaries(lines: string[], options: {
|
|
11
|
+
errorPattern: RegExp;
|
|
12
|
+
okPattern: RegExp;
|
|
13
|
+
}): LogBoundaryScan;
|
|
14
|
+
/**
|
|
15
|
+
* Return the last capture group from `errorPattern` when the error is not
|
|
16
|
+
* superseded by a later `okPattern` line (e.g. stale native-module errors).
|
|
17
|
+
*/
|
|
18
|
+
export declare function supersededErrorCapture(logText: string, options: {
|
|
19
|
+
errorPattern: RegExp;
|
|
20
|
+
okPattern: RegExp;
|
|
21
|
+
}): string | null;
|
|
22
|
+
export interface BundleLogAnalysis {
|
|
23
|
+
status: 'ok' | 'errors' | 'bundling' | 'no-log';
|
|
24
|
+
reason?: 'bundle-error' | 'unresolved-module' | 'stale-bundle-error';
|
|
25
|
+
excerpt?: string;
|
|
26
|
+
unresolvedModules?: string[];
|
|
27
|
+
}
|
|
28
|
+
export interface AnalyzeBundleLogOptions {
|
|
29
|
+
target: string;
|
|
30
|
+
logText: string;
|
|
31
|
+
errorPattern: RegExp;
|
|
32
|
+
okPattern: RegExp;
|
|
33
|
+
bundlingPattern?: RegExp;
|
|
34
|
+
}
|
|
35
|
+
export declare function analyzeBundleLog(options: AnalyzeBundleLogOptions): BundleLogAnalysis;
|
|
36
|
+
export interface PersistentBundleErrorDecision {
|
|
37
|
+
blocked: boolean;
|
|
38
|
+
excerptHash: string;
|
|
39
|
+
}
|
|
40
|
+
/** Block when the same bundle-error excerpt was already recorded for this target. */
|
|
41
|
+
export declare function evaluatePersistentBundleError(target: string, excerpt: string, stateFile?: string): PersistentBundleErrorDecision;
|
|
42
|
+
//# sourceMappingURL=log-analysis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-analysis.d.ts","sourceRoot":"","sources":["../../src/runtime/log-analysis.ts"],"names":[],"mappings":"AAMA,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAOlF;AAED,sFAAsF;AACtF,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAMrF;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,SAAI,GAAG,MAAM,EAAE,CAOvF;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,EAAE;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACnD,eAAe,CAQjB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACnD,MAAM,GAAG,IAAI,CASf;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,IAAI,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAC;IAChD,MAAM,CAAC,EAAE,cAAc,GAAG,mBAAmB,GAAG,oBAAoB,CAAC;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,iBAAiB,CA+BpF;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,qFAAqF;AACrF,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,SAAS,SAA4B,GACpC,6BAA6B,CAQ/B"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { readDecisionState, writeDecisionState } from './deps-readiness.js';
|
|
5
|
+
export function packageRootsForModule(target, moduleName) {
|
|
6
|
+
if (moduleName.startsWith('@')) {
|
|
7
|
+
const parts = moduleName.split('/');
|
|
8
|
+
if (parts.length >= 2)
|
|
9
|
+
return [path.join(target, 'node_modules', parts[0], parts[1])];
|
|
10
|
+
return [path.join(target, 'node_modules', parts[0])];
|
|
11
|
+
}
|
|
12
|
+
return [path.join(target, 'node_modules', moduleName.split('/')[0])];
|
|
13
|
+
}
|
|
14
|
+
/** True when the resolved package root contains package.json (ignores empty dirs). */
|
|
15
|
+
export function moduleExistsInNodeModules(target, moduleName) {
|
|
16
|
+
for (const pkgRoot of packageRootsForModule(target, moduleName)) {
|
|
17
|
+
if (!fs.existsSync(pkgRoot))
|
|
18
|
+
continue;
|
|
19
|
+
if (fs.existsSync(path.join(pkgRoot, 'package.json')))
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
export function unresolvedModulesFromLogSlice(lines, startIndex = 0) {
|
|
25
|
+
const found = new Set();
|
|
26
|
+
for (let i = Math.max(0, startIndex); i < lines.length; i += 1) {
|
|
27
|
+
const match = /Unable to resolve "([^"]+)"/u.exec(lines[i]);
|
|
28
|
+
if (match)
|
|
29
|
+
found.add(match[1]);
|
|
30
|
+
}
|
|
31
|
+
return [...found];
|
|
32
|
+
}
|
|
33
|
+
export function bundleErrorExcerptHash(excerpt) {
|
|
34
|
+
return crypto.createHash('sha256').update(excerpt).digest('hex').slice(0, 16);
|
|
35
|
+
}
|
|
36
|
+
export function scanLogBoundaries(lines, options) {
|
|
37
|
+
let lastErr = -1;
|
|
38
|
+
let lastOk = -1;
|
|
39
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
40
|
+
if (options.errorPattern.test(lines[i]))
|
|
41
|
+
lastErr = i;
|
|
42
|
+
if (options.okPattern.test(lines[i]))
|
|
43
|
+
lastOk = i;
|
|
44
|
+
}
|
|
45
|
+
return { lastErr, lastOk };
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Return the last capture group from `errorPattern` when the error is not
|
|
49
|
+
* superseded by a later `okPattern` line (e.g. stale native-module errors).
|
|
50
|
+
*/
|
|
51
|
+
export function supersededErrorCapture(logText, options) {
|
|
52
|
+
const lines = logText.split('\n');
|
|
53
|
+
const { lastErr, lastOk } = scanLogBoundaries(lines, options);
|
|
54
|
+
if (lastOk >= 0 && lastOk > lastErr)
|
|
55
|
+
return null;
|
|
56
|
+
for (let i = lines.length - 1; i >= 0; i -= 1) {
|
|
57
|
+
const match = options.errorPattern.exec(lines[i]);
|
|
58
|
+
if (match?.[1])
|
|
59
|
+
return match[1];
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
export function analyzeBundleLog(options) {
|
|
64
|
+
const lines = options.logText.split('\n');
|
|
65
|
+
const { lastErr, lastOk } = scanLogBoundaries(lines, {
|
|
66
|
+
errorPattern: options.errorPattern,
|
|
67
|
+
okPattern: options.okPattern,
|
|
68
|
+
});
|
|
69
|
+
const sliceStart = lastOk >= 0 ? lastOk + 1 : 0;
|
|
70
|
+
const unresolved = unresolvedModulesFromLogSlice(lines, sliceStart).filter((name) => !moduleExistsInNodeModules(options.target, name));
|
|
71
|
+
if (unresolved.length > 0 && lastErr > lastOk) {
|
|
72
|
+
return {
|
|
73
|
+
status: 'errors',
|
|
74
|
+
reason: 'unresolved-module',
|
|
75
|
+
excerpt: `Missing node_modules entries: ${unresolved.slice(0, 3).join(', ')}`,
|
|
76
|
+
unresolvedModules: unresolved,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
if (lastErr > lastOk) {
|
|
80
|
+
const excerpt = lines.slice(lastErr, lastErr + 3).join(' | ').slice(0, 400);
|
|
81
|
+
const cited = unresolvedModulesFromLogSlice(lines, sliceStart);
|
|
82
|
+
const stillMissing = cited.filter((name) => !moduleExistsInNodeModules(options.target, name));
|
|
83
|
+
if (cited.length > 0 && stillMissing.length === 0) {
|
|
84
|
+
return { status: 'errors', reason: 'stale-bundle-error', excerpt, unresolvedModules: cited };
|
|
85
|
+
}
|
|
86
|
+
return { status: 'errors', reason: 'bundle-error', excerpt };
|
|
87
|
+
}
|
|
88
|
+
if (lastOk >= 0)
|
|
89
|
+
return { status: 'ok' };
|
|
90
|
+
const bundlingPattern = options.bundlingPattern ?? /Bundling|index\.(js|tsx?).*%/u;
|
|
91
|
+
const bundling = lines.some((line) => bundlingPattern.test(line));
|
|
92
|
+
return bundling ? { status: 'bundling' } : { status: 'no-log' };
|
|
93
|
+
}
|
|
94
|
+
/** Block when the same bundle-error excerpt was already recorded for this target. */
|
|
95
|
+
export function evaluatePersistentBundleError(target, excerpt, stateFile = 'bundle-error-state.json') {
|
|
96
|
+
const excerptHash = bundleErrorExcerptHash(excerpt);
|
|
97
|
+
const prev = readDecisionState(target, stateFile);
|
|
98
|
+
if (prev?.excerptHash === excerptHash) {
|
|
99
|
+
return { blocked: true, excerptHash };
|
|
100
|
+
}
|
|
101
|
+
writeDecisionState(target, stateFile, { excerptHash, recordedAt: Date.now() });
|
|
102
|
+
return { blocked: false, excerptHash };
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=log-analysis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-analysis.js","sourceRoot":"","sources":["../../src/runtime/log-analysis.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metro-probe.d.ts","sourceRoot":"","sources":["../../src/runtime/metro-probe.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAmBlG"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
export function probeMetroPackager(port, timeoutMs = 1500) {
|
|
3
|
+
return new Promise((resolve) => {
|
|
4
|
+
const req = http.get(`http://localhost:${port}/status`, { timeout: timeoutMs }, (res) => {
|
|
5
|
+
let body = '';
|
|
6
|
+
res.on('data', (chunk) => {
|
|
7
|
+
body += chunk;
|
|
8
|
+
});
|
|
9
|
+
res.on('end', () => {
|
|
10
|
+
const up = res.statusCode !== undefined && res.statusCode >= 200 && res.statusCode < 300
|
|
11
|
+
&& /packager-status:running/u.test(body);
|
|
12
|
+
resolve({ status: up ? 'up' : 'down' });
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
req.on('timeout', () => {
|
|
16
|
+
req.destroy();
|
|
17
|
+
resolve({ status: 'down' });
|
|
18
|
+
});
|
|
19
|
+
req.on('error', () => resolve({ status: 'down' }));
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=metro-probe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metro-probe.js","sourceRoot":"","sources":["../../src/runtime/metro-probe.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAM7B,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,SAAS,GAAG,IAAI;IAC/D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,oBAAoB,IAAI,SAAS,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE;YACtF,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;gBACvB,IAAI,IAAI,KAAK,CAAC;YAChB,CAAC,CAAC,CAAC;YACH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;gBACjB,MAAM,EAAE,GAAG,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,GAAG,GAAG;uBACnF,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC3C,OAAO,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;YAC1C,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;YACrB,GAAG,CAAC,OAAO,EAAE,CAAC;YACd,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farmslot/recipe-harness",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -62,6 +62,26 @@
|
|
|
62
62
|
"types": "./dist/runtime/react-native-bridge.d.ts",
|
|
63
63
|
"import": "./dist/runtime/react-native-bridge.js",
|
|
64
64
|
"default": "./dist/runtime/react-native-bridge.js"
|
|
65
|
+
},
|
|
66
|
+
"./runtime/deps-readiness": {
|
|
67
|
+
"types": "./dist/runtime/deps-readiness.d.ts",
|
|
68
|
+
"import": "./dist/runtime/deps-readiness.js",
|
|
69
|
+
"default": "./dist/runtime/deps-readiness.js"
|
|
70
|
+
},
|
|
71
|
+
"./runtime/log-analysis": {
|
|
72
|
+
"types": "./dist/runtime/log-analysis.d.ts",
|
|
73
|
+
"import": "./dist/runtime/log-analysis.js",
|
|
74
|
+
"default": "./dist/runtime/log-analysis.js"
|
|
75
|
+
},
|
|
76
|
+
"./runtime/metro-probe": {
|
|
77
|
+
"types": "./dist/runtime/metro-probe.d.ts",
|
|
78
|
+
"import": "./dist/runtime/metro-probe.js",
|
|
79
|
+
"default": "./dist/runtime/metro-probe.js"
|
|
80
|
+
},
|
|
81
|
+
"./runtime/decision-types": {
|
|
82
|
+
"types": "./dist/runtime/decision-types.d.ts",
|
|
83
|
+
"import": "./dist/runtime/decision-types.js",
|
|
84
|
+
"default": "./dist/runtime/decision-types.js"
|
|
65
85
|
}
|
|
66
86
|
},
|
|
67
87
|
"scripts": {
|
|
@@ -118,4 +138,4 @@
|
|
|
118
138
|
"publishConfig": {
|
|
119
139
|
"access": "public"
|
|
120
140
|
}
|
|
121
|
-
}
|
|
141
|
+
}
|