@junejuly-lockstep/reconciler 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +182 -0
- package/dist/boot.d.ts +51 -0
- package/dist/boot.d.ts.map +1 -0
- package/dist/boot.js +162 -0
- package/dist/boot.js.map +1 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +180 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +55 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +140 -0
- package/dist/config.js.map +1 -0
- package/dist/contract.d.ts +61 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +154 -0
- package/dist/contract.js.map +1 -0
- package/dist/determinism.d.ts +23 -0
- package/dist/determinism.d.ts.map +1 -0
- package/dist/determinism.js +102 -0
- package/dist/determinism.js.map +1 -0
- package/dist/errors.d.ts +25 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +35 -0
- package/dist/errors.js.map +1 -0
- package/dist/exitCodes.d.ts +33 -0
- package/dist/exitCodes.d.ts.map +1 -0
- package/dist/exitCodes.js +49 -0
- package/dist/exitCodes.js.map +1 -0
- package/dist/extract.d.ts +30 -0
- package/dist/extract.d.ts.map +1 -0
- package/dist/extract.js +376 -0
- package/dist/extract.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +17 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +55 -0
- package/dist/init.js.map +1 -0
- package/dist/journeys.d.ts +34 -0
- package/dist/journeys.d.ts.map +1 -0
- package/dist/journeys.js +276 -0
- package/dist/journeys.js.map +1 -0
- package/dist/paths.d.ts +26 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +80 -0
- package/dist/paths.js.map +1 -0
- package/dist/reconcile.d.ts +63 -0
- package/dist/reconcile.d.ts.map +1 -0
- package/dist/reconcile.js +316 -0
- package/dist/reconcile.js.map +1 -0
- package/dist/report.d.ts +33 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +97 -0
- package/dist/report.js.map +1 -0
- package/dist/sync.d.ts +46 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +110 -0
- package/dist/sync.js.map +1 -0
- package/dist/upload.d.ts +33 -0
- package/dist/upload.d.ts.map +1 -0
- package/dist/upload.js +86 -0
- package/dist/upload.js.map +1 -0
- package/dist/util.d.ts +24 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +97 -0
- package/dist/util.js.map +1 -0
- package/dist/visual.d.ts +49 -0
- package/dist/visual.d.ts.map +1 -0
- package/dist/visual.js +145 -0
- package/dist/visual.js.map +1 -0
- package/dist/walk.d.ts +147 -0
- package/dist/walk.d.ts.map +1 -0
- package/dist/walk.js +433 -0
- package/dist/walk.js.map +1 -0
- package/package.json +78 -0
- package/templates/example.journey.ts +90 -0
- package/templates/lockstep-reconcile.yml +219 -0
- package/templates/lockstep.config.example.ts +46 -0
- package/templates/msw-handlers.example.ts +113 -0
- package/templates/scenarios.example.ts +32 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACjC,IAAI,CAAS;IACb,KAAK,CAA2C;IAEzD,YAAY,IAAY,EAAE,OAAe,EAAE,OAAiD,EAAE;QAC5F,MAAM,KAAK,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;QAC3C,KAAK,CACH,KAAK,CAAC,MAAM,KAAK,CAAC;YAChB,CAAC,CAAC,uBAAuB,IAAI,MAAM,OAAO,EAAE;YAC5C,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,0BAA0B,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC3G,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,MAAM,CAAC,QAAQ,CAAC,KAA+C;QAC7D,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC;QAC/B,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QAClF,OAAO,IAAI,iBAAiB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAChE,CAAC;CACF;AAED,sGAAsG;AACtG,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACnC,MAAM,CAAU;IAEzB,YAAY,OAAe,EAAE,KAAe;QAC1C,KAAK,CACH,KAAK,YAAY,KAAK,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC;YACxD,CAAC,CAAC,GAAG,OAAO,KAAK,KAAK,CAAC,OAAO,EAAE;YAChC,CAAC,CAAC,OAAO,CACZ,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;CACF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { RunKind } from '@junejuly-lockstep/model';
|
|
2
|
+
/** Exit codes for CI gating (SPEC.md "Reconciler package"). */
|
|
3
|
+
export declare const EXIT: {
|
|
4
|
+
/** Run posted, no verdicts need a human. */
|
|
5
|
+
readonly CLEAN: 0;
|
|
6
|
+
/** The repo does not meet the client contract; nothing was walked or posted. */
|
|
7
|
+
readonly CONTRACT_VIOLATION: 1;
|
|
8
|
+
/** Browser, app boot, upload or platform API failed. */
|
|
9
|
+
readonly INFRASTRUCTURE: 2;
|
|
10
|
+
/** Run posted and the platform attached verdicts that need judgment. */
|
|
11
|
+
readonly VERDICTS: 3;
|
|
12
|
+
};
|
|
13
|
+
export type ExitCode = (typeof EXIT)[keyof typeof EXIT];
|
|
14
|
+
export declare const FAIL_ON_VERDICTS_MODES: readonly ["auto", "always", "never"];
|
|
15
|
+
export type FailOnVerdicts = (typeof FAIL_ON_VERDICTS_MODES)[number];
|
|
16
|
+
export declare function parseFailOnVerdicts(value: string | undefined): FailOnVerdicts;
|
|
17
|
+
/** `auto` = report-only on PR runs, fail on deploy runs. */
|
|
18
|
+
export declare function shouldFailOnVerdicts(kind: RunKind, mode: FailOnVerdicts): boolean;
|
|
19
|
+
/** Map a thrown error to the exit code the CLI should use. */
|
|
20
|
+
export declare function exitCodeForError(err: unknown): ExitCode;
|
|
21
|
+
/**
|
|
22
|
+
* Exit code for a run that completed and was ingested. Exit 3 is always *reported*
|
|
23
|
+
* when judgment verdicts exist; whether it fails the job is the caller's call via
|
|
24
|
+
* `shouldFailOnVerdicts`. We return 3 so the workflow template can decide; when
|
|
25
|
+
* the mode says report-only we still return 0 so plain `npx lockstep reconcile`
|
|
26
|
+
* does not fail PR checks.
|
|
27
|
+
*/
|
|
28
|
+
export declare function exitCodeForResult(args: {
|
|
29
|
+
judgmentCount: number;
|
|
30
|
+
kind: RunKind;
|
|
31
|
+
failOnVerdicts: FailOnVerdicts;
|
|
32
|
+
}): ExitCode;
|
|
33
|
+
//# sourceMappingURL=exitCodes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exitCodes.d.ts","sourceRoot":"","sources":["../src/exitCodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAGxD,+DAA+D;AAC/D,eAAO,MAAM,IAAI;IACf,4CAA4C;;IAE5C,gFAAgF;;IAEhF,wDAAwD;;IAExD,wEAAwE;;CAEhE,CAAC;AACX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,MAAM,OAAO,IAAI,CAAC,CAAC;AAExD,eAAO,MAAM,sBAAsB,sCAAuC,CAAC;AAC3E,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAErE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,CAM7E;AAED,4DAA4D;AAC5D,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAIjF;AAED,8DAA8D;AAC9D,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CAIvD;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,OAAO,CAAC;IACd,cAAc,EAAE,cAAc,CAAC;CAChC,GAAG,QAAQ,CAGX"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ContractViolation, InfrastructureError } from './errors.js';
|
|
2
|
+
/** Exit codes for CI gating (SPEC.md "Reconciler package"). */
|
|
3
|
+
export const EXIT = {
|
|
4
|
+
/** Run posted, no verdicts need a human. */
|
|
5
|
+
CLEAN: 0,
|
|
6
|
+
/** The repo does not meet the client contract; nothing was walked or posted. */
|
|
7
|
+
CONTRACT_VIOLATION: 1,
|
|
8
|
+
/** Browser, app boot, upload or platform API failed. */
|
|
9
|
+
INFRASTRUCTURE: 2,
|
|
10
|
+
/** Run posted and the platform attached verdicts that need judgment. */
|
|
11
|
+
VERDICTS: 3,
|
|
12
|
+
};
|
|
13
|
+
export const FAIL_ON_VERDICTS_MODES = ['auto', 'always', 'never'];
|
|
14
|
+
export function parseFailOnVerdicts(value) {
|
|
15
|
+
if (value === undefined)
|
|
16
|
+
return 'auto';
|
|
17
|
+
if (FAIL_ON_VERDICTS_MODES.includes(value))
|
|
18
|
+
return value;
|
|
19
|
+
throw new Error(`--fail-on-verdicts must be one of ${FAIL_ON_VERDICTS_MODES.join('|')}, got "${value}"`);
|
|
20
|
+
}
|
|
21
|
+
/** `auto` = report-only on PR runs, fail on deploy runs. */
|
|
22
|
+
export function shouldFailOnVerdicts(kind, mode) {
|
|
23
|
+
if (mode === 'always')
|
|
24
|
+
return true;
|
|
25
|
+
if (mode === 'never')
|
|
26
|
+
return false;
|
|
27
|
+
return kind === 'deploy';
|
|
28
|
+
}
|
|
29
|
+
/** Map a thrown error to the exit code the CLI should use. */
|
|
30
|
+
export function exitCodeForError(err) {
|
|
31
|
+
if (err instanceof ContractViolation)
|
|
32
|
+
return EXIT.CONTRACT_VIOLATION;
|
|
33
|
+
if (err instanceof InfrastructureError)
|
|
34
|
+
return EXIT.INFRASTRUCTURE;
|
|
35
|
+
return EXIT.INFRASTRUCTURE;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Exit code for a run that completed and was ingested. Exit 3 is always *reported*
|
|
39
|
+
* when judgment verdicts exist; whether it fails the job is the caller's call via
|
|
40
|
+
* `shouldFailOnVerdicts`. We return 3 so the workflow template can decide; when
|
|
41
|
+
* the mode says report-only we still return 0 so plain `npx lockstep reconcile`
|
|
42
|
+
* does not fail PR checks.
|
|
43
|
+
*/
|
|
44
|
+
export function exitCodeForResult(args) {
|
|
45
|
+
if (args.judgmentCount <= 0)
|
|
46
|
+
return EXIT.CLEAN;
|
|
47
|
+
return shouldFailOnVerdicts(args.kind, args.failOnVerdicts) ? EXIT.VERDICTS : EXIT.CLEAN;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=exitCodes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exitCodes.js","sourceRoot":"","sources":["../src/exitCodes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAErE,+DAA+D;AAC/D,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,4CAA4C;IAC5C,KAAK,EAAE,CAAC;IACR,gFAAgF;IAChF,kBAAkB,EAAE,CAAC;IACrB,wDAAwD;IACxD,cAAc,EAAE,CAAC;IACjB,wEAAwE;IACxE,QAAQ,EAAE,CAAC;CACH,CAAC;AAGX,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAU,CAAC;AAG3E,MAAM,UAAU,mBAAmB,CAAC,KAAyB;IAC3D,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IACvC,IAAK,sBAA4C,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAuB,CAAC;IAClG,MAAM,IAAI,KAAK,CACb,qCAAqC,sBAAsB,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,KAAK,GAAG,CACxF,CAAC;AACJ,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,oBAAoB,CAAC,IAAa,EAAE,IAAoB;IACtE,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC;IACnC,OAAO,IAAI,KAAK,QAAQ,CAAC;AAC3B,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,gBAAgB,CAAC,GAAY;IAC3C,IAAI,GAAG,YAAY,iBAAiB;QAAE,OAAO,IAAI,CAAC,kBAAkB,CAAC;IACrE,IAAI,GAAG,YAAY,mBAAmB;QAAE,OAAO,IAAI,CAAC,cAAc,CAAC;IACnE,OAAO,IAAI,CAAC,cAAc,CAAC;AAC7B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAIjC;IACC,IAAI,IAAI,CAAC,aAAa,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC;IAC/C,OAAO,oBAAoB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;AAC3F,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Node, Project } from 'ts-morph';
|
|
2
|
+
import { ExtractedGraph } from '@junejuly-lockstep/model';
|
|
3
|
+
export interface ExtractOptions {
|
|
4
|
+
/** Repo root (where lockstep.config.ts lives). */
|
|
5
|
+
rootDir: string;
|
|
6
|
+
/** Globs relative to rootDir; default: every ts/tsx/js/jsx file. */
|
|
7
|
+
include?: string[];
|
|
8
|
+
/** Extra ignore globs on top of the defaults (node_modules, .next, dist, tests). */
|
|
9
|
+
exclude?: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare const DEFAULT_INCLUDE: string[];
|
|
12
|
+
export declare const DEFAULT_EXCLUDE: string[];
|
|
13
|
+
/**
|
|
14
|
+
* Map a repo-relative file path to the Next.js route it renders, or null.
|
|
15
|
+
* App router: `app/visits/[id]/page.tsx` -> `/visits/:id`; route groups and slots are dropped.
|
|
16
|
+
* Pages router: `pages/visits/index.tsx` -> `/visits`; `_app`, `_document`, `api/` are skipped.
|
|
17
|
+
*/
|
|
18
|
+
export declare function routeForFile(relFile: string): string | null;
|
|
19
|
+
export declare function listSourceFiles(opts: ExtractOptions): Promise<string[]>;
|
|
20
|
+
/** Walk the app source with ts-morph and produce the extracted navigation graph. */
|
|
21
|
+
export declare function extractGraph(opts: ExtractOptions): Promise<ExtractedGraph>;
|
|
22
|
+
export declare function extractFromProject(project: Project, rootDir: string): ExtractedGraph;
|
|
23
|
+
/** Name of the closest enclosing function: declaration, variable, property, or JSX attribute. */
|
|
24
|
+
export declare function enclosingFunctionName(node: Node): string | null;
|
|
25
|
+
/**
|
|
26
|
+
* Lift the predicates guarding a navigation: `if (c) nav()` -> `c`, else-branch -> `!(c)`,
|
|
27
|
+
* `c ? nav() : x` -> `c`, `c && nav()` -> `c`. Stops at the enclosing function boundary.
|
|
28
|
+
*/
|
|
29
|
+
export declare function liftGuard(node: Node): string | null;
|
|
30
|
+
//# sourceMappingURL=extract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAsD,MAAM,UAAU,CAAC;AAC7F,OAAO,EACL,cAAc,EAGf,MAAM,0BAA0B,CAAC;AAGlC,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,eAAO,MAAM,eAAe,UAA2B,CAAC;AACxD,eAAO,MAAM,eAAe,UAc3B,CAAC;AASF;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAc3D;AAiBD,wBAAsB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQ7E;AAED,oFAAoF;AACpF,wBAAsB,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAchF;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CAoBpF;AA2HD,iGAAiG;AACjG,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAW/D;AA+FD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAwBnD"}
|
package/dist/extract.js
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fg from 'fast-glob';
|
|
3
|
+
import { Node, Project, SyntaxKind, ts } from 'ts-morph';
|
|
4
|
+
import { ExtractedGraph, } from '@junejuly-lockstep/model';
|
|
5
|
+
import { toPosix } from './util.js';
|
|
6
|
+
export const DEFAULT_INCLUDE = ['**/*.{ts,tsx,js,jsx}'];
|
|
7
|
+
export const DEFAULT_EXCLUDE = [
|
|
8
|
+
'**/node_modules/**',
|
|
9
|
+
'**/.next/**',
|
|
10
|
+
'**/dist/**',
|
|
11
|
+
'**/build/**',
|
|
12
|
+
'**/out/**',
|
|
13
|
+
'**/coverage/**',
|
|
14
|
+
'**/.lockstep/**',
|
|
15
|
+
'**/*.d.ts',
|
|
16
|
+
'**/*.test.*',
|
|
17
|
+
'**/*.spec.*',
|
|
18
|
+
'**/__tests__/**',
|
|
19
|
+
'**/*.stories.*',
|
|
20
|
+
'**/*.journey.ts',
|
|
21
|
+
];
|
|
22
|
+
const NAV_KINDS = {
|
|
23
|
+
push: 'router.push',
|
|
24
|
+
replace: 'router.replace',
|
|
25
|
+
redirect: 'redirect',
|
|
26
|
+
permanentRedirect: 'redirect',
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Map a repo-relative file path to the Next.js route it renders, or null.
|
|
30
|
+
* App router: `app/visits/[id]/page.tsx` -> `/visits/:id`; route groups and slots are dropped.
|
|
31
|
+
* Pages router: `pages/visits/index.tsx` -> `/visits`; `_app`, `_document`, `api/` are skipped.
|
|
32
|
+
*/
|
|
33
|
+
export function routeForFile(relFile) {
|
|
34
|
+
const file = toPosix(relFile);
|
|
35
|
+
const app = /^(?:src\/)?app\/(.*?)page\.(?:tsx|jsx|ts|js)$/.exec(file);
|
|
36
|
+
if (app)
|
|
37
|
+
return segmentsToRoute(app[1].split('/').filter(Boolean));
|
|
38
|
+
const pages = /^(?:src\/)?pages\/(.*)\.(?:tsx|jsx|ts|js)$/.exec(file);
|
|
39
|
+
if (pages) {
|
|
40
|
+
const segments = pages[1].split('/').filter(Boolean);
|
|
41
|
+
if (segments[0] === 'api')
|
|
42
|
+
return null;
|
|
43
|
+
const last = segments[segments.length - 1];
|
|
44
|
+
if (!last || last.startsWith('_'))
|
|
45
|
+
return null;
|
|
46
|
+
if (last === 'index')
|
|
47
|
+
segments.pop();
|
|
48
|
+
return segmentsToRoute(segments);
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
function segmentsToRoute(segments) {
|
|
53
|
+
const parts = segments
|
|
54
|
+
.filter((s) => !(s.startsWith('(') && s.endsWith(')')) && !s.startsWith('@'))
|
|
55
|
+
.map((s) => {
|
|
56
|
+
const optionalCatchAll = /^\[\[\.\.\.(.+)\]\]$/.exec(s);
|
|
57
|
+
if (optionalCatchAll)
|
|
58
|
+
return `*${optionalCatchAll[1]}?`;
|
|
59
|
+
const catchAll = /^\[\.\.\.(.+)\]$/.exec(s);
|
|
60
|
+
if (catchAll)
|
|
61
|
+
return `*${catchAll[1]}`;
|
|
62
|
+
const dynamic = /^\[(.+)\]$/.exec(s);
|
|
63
|
+
if (dynamic)
|
|
64
|
+
return `:${dynamic[1]}`;
|
|
65
|
+
return s;
|
|
66
|
+
});
|
|
67
|
+
return `/${parts.join('/')}`.replace(/\/+/g, '/');
|
|
68
|
+
}
|
|
69
|
+
export async function listSourceFiles(opts) {
|
|
70
|
+
const files = await fg(opts.include ?? DEFAULT_INCLUDE, {
|
|
71
|
+
cwd: opts.rootDir,
|
|
72
|
+
ignore: [...DEFAULT_EXCLUDE, ...(opts.exclude ?? [])],
|
|
73
|
+
onlyFiles: true,
|
|
74
|
+
dot: false,
|
|
75
|
+
});
|
|
76
|
+
return files.map(toPosix).sort();
|
|
77
|
+
}
|
|
78
|
+
/** Walk the app source with ts-morph and produce the extracted navigation graph. */
|
|
79
|
+
export async function extractGraph(opts) {
|
|
80
|
+
const files = await listSourceFiles(opts);
|
|
81
|
+
const project = new Project({
|
|
82
|
+
skipAddingFilesFromTsConfig: true,
|
|
83
|
+
skipFileDependencyResolution: true,
|
|
84
|
+
compilerOptions: {
|
|
85
|
+
jsx: ts.JsxEmit.Preserve,
|
|
86
|
+
allowJs: true,
|
|
87
|
+
noResolve: true,
|
|
88
|
+
skipLibCheck: true,
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
for (const f of files)
|
|
92
|
+
project.addSourceFileAtPath(path.join(opts.rootDir, f));
|
|
93
|
+
return extractFromProject(project, opts.rootDir);
|
|
94
|
+
}
|
|
95
|
+
export function extractFromProject(project, rootDir) {
|
|
96
|
+
const routes = [];
|
|
97
|
+
const navigations = [];
|
|
98
|
+
for (const sf of project.getSourceFiles()) {
|
|
99
|
+
const rel = toPosix(path.relative(rootDir, sf.getFilePath()));
|
|
100
|
+
const route = routeForFile(rel);
|
|
101
|
+
if (route !== null)
|
|
102
|
+
routes.push({ route, file: rel, testIds: collectTestIds(sf) });
|
|
103
|
+
navigations.push(...extractNavigations(sf, rel, route));
|
|
104
|
+
}
|
|
105
|
+
routes.sort((a, b) => cmp(a.file, b.file) || cmp(a.route, b.route));
|
|
106
|
+
navigations.sort((a, b) => cmp(a.file, b.file) || a.line - b.line || cmp(a.toRoute ?? '', b.toRoute ?? ''));
|
|
107
|
+
return ExtractedGraph.parse({
|
|
108
|
+
routes,
|
|
109
|
+
navigations,
|
|
110
|
+
unresolvedCount: navigations.filter((n) => n.unresolved).length,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
function cmp(a, b) {
|
|
114
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
115
|
+
}
|
|
116
|
+
function collectTestIds(sf) {
|
|
117
|
+
const ids = new Set();
|
|
118
|
+
for (const attr of sf.getDescendantsOfKind(SyntaxKind.JsxAttribute)) {
|
|
119
|
+
if (attrName(attr) !== 'data-testid')
|
|
120
|
+
continue;
|
|
121
|
+
const v = literalValue(attr.getInitializer());
|
|
122
|
+
if (v !== null)
|
|
123
|
+
ids.add(v);
|
|
124
|
+
}
|
|
125
|
+
return [...ids].sort();
|
|
126
|
+
}
|
|
127
|
+
function attrName(attr) {
|
|
128
|
+
return attr.getNameNode().getText();
|
|
129
|
+
}
|
|
130
|
+
/** Resolve a static string from a literal, template without substitutions, or `{ pathname }` object. */
|
|
131
|
+
function literalValue(node) {
|
|
132
|
+
if (!node)
|
|
133
|
+
return null;
|
|
134
|
+
if (Node.isStringLiteral(node) || Node.isNoSubstitutionTemplateLiteral(node))
|
|
135
|
+
return node.getLiteralText();
|
|
136
|
+
if (Node.isJsxExpression(node))
|
|
137
|
+
return literalValue(node.getExpression());
|
|
138
|
+
if (Node.isParenthesizedExpression(node))
|
|
139
|
+
return literalValue(node.getExpression());
|
|
140
|
+
if (Node.isAsExpression(node) || Node.isSatisfiesExpression(node))
|
|
141
|
+
return literalValue(node.getExpression());
|
|
142
|
+
if (Node.isObjectLiteralExpression(node)) {
|
|
143
|
+
const prop = node.getProperty('pathname');
|
|
144
|
+
if (prop && Node.isPropertyAssignment(prop))
|
|
145
|
+
return literalValue(prop.getInitializer());
|
|
146
|
+
}
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
function extractNavigations(sf, file, fromRoute) {
|
|
150
|
+
const out = [];
|
|
151
|
+
// <Link href="...">
|
|
152
|
+
for (const el of [
|
|
153
|
+
...sf.getDescendantsOfKind(SyntaxKind.JsxOpeningElement),
|
|
154
|
+
...sf.getDescendantsOfKind(SyntaxKind.JsxSelfClosingElement),
|
|
155
|
+
]) {
|
|
156
|
+
const tag = el.getTagNameNode().getText();
|
|
157
|
+
if (tag !== 'Link' && tag !== 'NextLink')
|
|
158
|
+
continue;
|
|
159
|
+
const href = el.getAttribute('href');
|
|
160
|
+
if (!href || !Node.isJsxAttribute(href))
|
|
161
|
+
continue;
|
|
162
|
+
const target = literalValue(href.getInitializer());
|
|
163
|
+
const element = Node.isJsxOpeningElement(el) ? el.getParent() : el;
|
|
164
|
+
out.push({
|
|
165
|
+
fromRoute,
|
|
166
|
+
toRoute: target,
|
|
167
|
+
kind: 'link',
|
|
168
|
+
file,
|
|
169
|
+
line: el.getStartLineNumber(),
|
|
170
|
+
handler: enclosingFunctionName(el),
|
|
171
|
+
triggerText: elementText(element),
|
|
172
|
+
triggerTestId: elementTestId(el),
|
|
173
|
+
guard: liftGuard(el),
|
|
174
|
+
unresolved: target === null,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
// router.push(...), router.replace(...), redirect(...)
|
|
178
|
+
for (const call of sf.getDescendantsOfKind(SyntaxKind.CallExpression)) {
|
|
179
|
+
const kind = navKind(call.getExpression());
|
|
180
|
+
if (!kind)
|
|
181
|
+
continue;
|
|
182
|
+
const arg = call.getArguments()[0];
|
|
183
|
+
const target = literalValue(arg);
|
|
184
|
+
const trigger = triggerElementFor(call, sf);
|
|
185
|
+
out.push({
|
|
186
|
+
fromRoute,
|
|
187
|
+
toRoute: target,
|
|
188
|
+
kind,
|
|
189
|
+
file,
|
|
190
|
+
line: call.getStartLineNumber(),
|
|
191
|
+
handler: enclosingFunctionName(call),
|
|
192
|
+
triggerText: trigger ? elementText(trigger.element) : null,
|
|
193
|
+
triggerTestId: trigger ? elementTestId(trigger.opening) : null,
|
|
194
|
+
guard: liftGuard(call),
|
|
195
|
+
unresolved: target === null,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
return out;
|
|
199
|
+
}
|
|
200
|
+
function navKind(expr) {
|
|
201
|
+
if (Node.isIdentifier(expr)) {
|
|
202
|
+
const name = expr.getText();
|
|
203
|
+
if (name === 'redirect' || name === 'permanentRedirect')
|
|
204
|
+
return NAV_KINDS[name];
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
if (Node.isPropertyAccessExpression(expr)) {
|
|
208
|
+
const method = expr.getName();
|
|
209
|
+
if (method !== 'push' && method !== 'replace')
|
|
210
|
+
return null;
|
|
211
|
+
const objText = expr.getExpression().getText();
|
|
212
|
+
if (/router$/i.test(objText) ||
|
|
213
|
+
/useRouter\(\)$/.test(objText) ||
|
|
214
|
+
/^(navigation|history)$/.test(objText)) {
|
|
215
|
+
return NAV_KINDS[method];
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
function isFunctionLike(node) {
|
|
221
|
+
return (Node.isFunctionDeclaration(node) ||
|
|
222
|
+
Node.isFunctionExpression(node) ||
|
|
223
|
+
Node.isArrowFunction(node) ||
|
|
224
|
+
Node.isMethodDeclaration(node));
|
|
225
|
+
}
|
|
226
|
+
/** Name of the closest enclosing function: declaration, variable, property, or JSX attribute. */
|
|
227
|
+
export function enclosingFunctionName(node) {
|
|
228
|
+
let cur = node.getParent();
|
|
229
|
+
while (cur) {
|
|
230
|
+
if (isFunctionLike(cur)) {
|
|
231
|
+
const name = functionName(cur);
|
|
232
|
+
if (name)
|
|
233
|
+
return name;
|
|
234
|
+
// Anonymous: keep climbing (e.g. useCallback(() => ...) assigned to a const).
|
|
235
|
+
}
|
|
236
|
+
cur = cur.getParent();
|
|
237
|
+
}
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
function functionName(fn) {
|
|
241
|
+
if (Node.isFunctionDeclaration(fn) || Node.isMethodDeclaration(fn))
|
|
242
|
+
return fn.getName() ?? null;
|
|
243
|
+
if (Node.isFunctionExpression(fn) && fn.getName())
|
|
244
|
+
return fn.getName() ?? null;
|
|
245
|
+
let cur = fn.getParent();
|
|
246
|
+
while (cur) {
|
|
247
|
+
if (Node.isVariableDeclaration(cur))
|
|
248
|
+
return cur.getName();
|
|
249
|
+
if (Node.isPropertyAssignment(cur))
|
|
250
|
+
return cur.getName();
|
|
251
|
+
if (Node.isJsxAttribute(cur))
|
|
252
|
+
return attrName(cur);
|
|
253
|
+
if (Node.isCallExpression(cur) ||
|
|
254
|
+
Node.isParenthesizedExpression(cur) ||
|
|
255
|
+
Node.isAsExpression(cur)) {
|
|
256
|
+
cur = cur.getParent();
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
if (Node.isJsxExpression(cur)) {
|
|
260
|
+
cur = cur.getParent();
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* The JSX element whose handler prop runs this call: either the call sits inside an inline
|
|
269
|
+
* arrow in a JSX attribute, or its enclosing named handler is referenced by a JSX attribute.
|
|
270
|
+
*/
|
|
271
|
+
function triggerElementFor(call, sf) {
|
|
272
|
+
const attr = call.getFirstAncestorByKind(SyntaxKind.JsxAttribute);
|
|
273
|
+
if (attr)
|
|
274
|
+
return triggerFromAttribute(attr);
|
|
275
|
+
const handler = enclosingFunctionName(call);
|
|
276
|
+
if (!handler)
|
|
277
|
+
return null;
|
|
278
|
+
for (const candidate of sf.getDescendantsOfKind(SyntaxKind.JsxAttribute)) {
|
|
279
|
+
const init = candidate.getInitializer();
|
|
280
|
+
if (!init || !Node.isJsxExpression(init))
|
|
281
|
+
continue;
|
|
282
|
+
const expr = init.getExpression();
|
|
283
|
+
if (!expr)
|
|
284
|
+
continue;
|
|
285
|
+
const text = expr.getText().replace(/\s+/g, '');
|
|
286
|
+
if (text === handler ||
|
|
287
|
+
text.endsWith(`=>${handler}()`) ||
|
|
288
|
+
text.endsWith(`=>${handler}(e)`) ||
|
|
289
|
+
text.endsWith(`=>${handler}(event)`)) {
|
|
290
|
+
return triggerFromAttribute(candidate);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
function triggerFromAttribute(attr) {
|
|
296
|
+
// JsxAttribute -> JsxAttributes -> JsxOpeningElement | JsxSelfClosingElement
|
|
297
|
+
let opening = attr.getParent();
|
|
298
|
+
if (opening && opening.getKind() === SyntaxKind.JsxAttributes)
|
|
299
|
+
opening = opening.getParent();
|
|
300
|
+
if (!opening)
|
|
301
|
+
return null;
|
|
302
|
+
if (Node.isJsxOpeningElement(opening))
|
|
303
|
+
return { element: opening.getParent() ?? opening, opening };
|
|
304
|
+
if (Node.isJsxSelfClosingElement(opening))
|
|
305
|
+
return { element: opening, opening };
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
308
|
+
function elementTestId(opening) {
|
|
309
|
+
if (!Node.isJsxOpeningElement(opening) && !Node.isJsxSelfClosingElement(opening))
|
|
310
|
+
return null;
|
|
311
|
+
const attr = opening.getAttribute('data-testid');
|
|
312
|
+
if (!attr || !Node.isJsxAttribute(attr))
|
|
313
|
+
return null;
|
|
314
|
+
return literalValue(attr.getInitializer());
|
|
315
|
+
}
|
|
316
|
+
/** Visible text of a JSX element: its text children (recursively), whitespace collapsed. */
|
|
317
|
+
function elementText(element) {
|
|
318
|
+
if (!Node.isJsxElement(element))
|
|
319
|
+
return null;
|
|
320
|
+
const parts = [];
|
|
321
|
+
for (const text of element.getDescendantsOfKind(SyntaxKind.JsxText)) {
|
|
322
|
+
const t = text.getText().replace(/\s+/g, ' ').trim();
|
|
323
|
+
if (t)
|
|
324
|
+
parts.push(t);
|
|
325
|
+
}
|
|
326
|
+
for (const expr of element.getDescendantsOfKind(SyntaxKind.JsxExpression)) {
|
|
327
|
+
const inner = expr.getExpression();
|
|
328
|
+
if (inner && (Node.isStringLiteral(inner) || Node.isNoSubstitutionTemplateLiteral(inner))) {
|
|
329
|
+
parts.push(inner.getLiteralText().trim());
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
const joined = parts.join(' ').replace(/\s+/g, ' ').trim();
|
|
333
|
+
return joined || null;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Lift the predicates guarding a navigation: `if (c) nav()` -> `c`, else-branch -> `!(c)`,
|
|
337
|
+
* `c ? nav() : x` -> `c`, `c && nav()` -> `c`. Stops at the enclosing function boundary.
|
|
338
|
+
*/
|
|
339
|
+
export function liftGuard(node) {
|
|
340
|
+
const guards = [];
|
|
341
|
+
let child = node;
|
|
342
|
+
let parent = node.getParent();
|
|
343
|
+
while (parent && !isFunctionLike(parent) && !Node.isSourceFile(parent)) {
|
|
344
|
+
if (Node.isIfStatement(parent)) {
|
|
345
|
+
const cond = squash(parent.getExpression().getText());
|
|
346
|
+
if (parent.getThenStatement() === child)
|
|
347
|
+
guards.push(cond);
|
|
348
|
+
else if (parent.getElseStatement() === child)
|
|
349
|
+
guards.push(`!(${cond})`);
|
|
350
|
+
}
|
|
351
|
+
else if (Node.isConditionalExpression(parent)) {
|
|
352
|
+
const cond = squash(parent.getCondition().getText());
|
|
353
|
+
if (parent.getWhenTrue() === child)
|
|
354
|
+
guards.push(cond);
|
|
355
|
+
else if (parent.getWhenFalse() === child)
|
|
356
|
+
guards.push(`!(${cond})`);
|
|
357
|
+
}
|
|
358
|
+
else if (Node.isBinaryExpression(parent) && parent.getRight() === child) {
|
|
359
|
+
const op = parent.getOperatorToken().getKind();
|
|
360
|
+
const left = squash(parent.getLeft().getText());
|
|
361
|
+
if (op === SyntaxKind.AmpersandAmpersandToken)
|
|
362
|
+
guards.push(left);
|
|
363
|
+
else if (op === SyntaxKind.BarBarToken)
|
|
364
|
+
guards.push(`!(${left})`);
|
|
365
|
+
}
|
|
366
|
+
child = parent;
|
|
367
|
+
parent = parent.getParent();
|
|
368
|
+
}
|
|
369
|
+
if (guards.length === 0)
|
|
370
|
+
return null;
|
|
371
|
+
return guards.reverse().join(' && ');
|
|
372
|
+
}
|
|
373
|
+
function squash(text) {
|
|
374
|
+
return text.replace(/\s+/g, ' ').trim();
|
|
375
|
+
}
|
|
376
|
+
//# sourceMappingURL=extract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type { JourneyMeta, LockstepConfig, MachineJson, Scenario, StateMeta, TriggerBinding, } from '@junejuly-lockstep/model';
|
|
2
|
+
export { defineConfig, loadConfig, checkContract, checkMockApiBase, assertContract, loadAndCheck, WORKFLOW_PATH, API_KEY_ENV, } from './config.js';
|
|
3
|
+
export type { LoadedConfig, ContractReport, ContractCheckOptions } from './config.js';
|
|
4
|
+
export { ContractViolation, InfrastructureError } from './errors.js';
|
|
5
|
+
export { EXIT, FAIL_ON_VERDICTS_MODES, exitCodeForError, exitCodeForResult, parseFailOnVerdicts, shouldFailOnVerdicts, } from './exitCodes.js';
|
|
6
|
+
export type { ExitCode, FailOnVerdicts } from './exitCodes.js';
|
|
7
|
+
export { loadJourneys, loadScenarios, journeyFromModule, toMachineJson, stripFunctions, journeyKeyFromFile, } from './journeys.js';
|
|
8
|
+
export type { JourneyModule, LoadedJourney } from './journeys.js';
|
|
9
|
+
export { enumeratePaths, machineFromJson, uncoveredTransitions } from './paths.js';
|
|
10
|
+
export type { EnumeratedPath, PathStep } from './paths.js';
|
|
11
|
+
export { extractGraph, extractFromProject, routeForFile, liftGuard, enclosingFunctionName, DEFAULT_EXCLUDE, DEFAULT_INCLUDE, } from './extract.js';
|
|
12
|
+
export type { ExtractOptions } from './extract.js';
|
|
13
|
+
export { hashSdl, canonicalSdl, hashOperationShapes, normalizeShape, hashLockfile, diffSdl, formatSdlChanges, snapshotContract, NO_HASH, } from './contract.js';
|
|
14
|
+
export type { SdlChange, SnapshotOptions, SnapshotResult } from './contract.js';
|
|
15
|
+
export { bootApp, waitForPort, waitForPortClosed, isPortOpen, killTree } from './boot.js';
|
|
16
|
+
export type { BootOptions, BootedApp } from './boot.js';
|
|
17
|
+
export { walk, defaultWalkDeps, operationNamesOf, summarizeError, screenshotPath, tracePath, triggerTestId, testIdSelector, FROZEN_EPOCH_MS, VIEWPORT, DEVICE_SCALE_FACTOR, DISABLE_MOTION_CSS, CHROMIUM_ARGS, } from './walk.js';
|
|
18
|
+
export type { WalkOptions, WalkDeps, BrowserLike, ContextLike, PageLike, LocatorLike, RequestLike, } from './walk.js';
|
|
19
|
+
export { comparePng, compareWalk, downloadBaselines, baselineId, PIXEL_THRESHOLD, } from './visual.js';
|
|
20
|
+
export type { CompareResult, CompareWalkOptions } from './visual.js';
|
|
21
|
+
export { uploadArtifacts, collectArtifacts, PRESIGN_BATCH } from './upload.js';
|
|
22
|
+
export type { UploadFile, UploadOptions, UploadResult } from './upload.js';
|
|
23
|
+
export { assembleRunPayload, summarize } from './report.js';
|
|
24
|
+
export type { RunParts, SummaryOptions } from './report.js';
|
|
25
|
+
export { DETERMINISM_RULES, hashPngs, compareHashMaps, formatDeterminismReport, } from './determinism.js';
|
|
26
|
+
export type { HashComparison, HashMap } from './determinism.js';
|
|
27
|
+
export { init, INIT_FILES, templatesDir } from './init.js';
|
|
28
|
+
export type { InitResult } from './init.js';
|
|
29
|
+
export { reconcile, validate, resolveCommitSha, resolveApiBaseUrl, gitShowFile, gitExec, API_BASE_URL_ENV, } from './reconcile.js';
|
|
30
|
+
export type { ReconcileOptions, ReconcileResult } from './reconcile.js';
|
|
31
|
+
export { syncModels, resolveBranch, resolvePushedAt } from './sync.js';
|
|
32
|
+
export type { SyncModelsOptions, SyncModelsResult } from './sync.js';
|
|
33
|
+
export { buildProgram } from './cli.js';
|
|
34
|
+
export { reconcilerVersion, sha256 } from './util.js';
|
|
35
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export { defineConfig, loadConfig, checkContract, checkMockApiBase, assertContract, loadAndCheck, WORKFLOW_PATH, API_KEY_ENV, } from './config.js';
|
|
2
|
+
export { ContractViolation, InfrastructureError } from './errors.js';
|
|
3
|
+
export { EXIT, FAIL_ON_VERDICTS_MODES, exitCodeForError, exitCodeForResult, parseFailOnVerdicts, shouldFailOnVerdicts, } from './exitCodes.js';
|
|
4
|
+
export { loadJourneys, loadScenarios, journeyFromModule, toMachineJson, stripFunctions, journeyKeyFromFile, } from './journeys.js';
|
|
5
|
+
export { enumeratePaths, machineFromJson, uncoveredTransitions } from './paths.js';
|
|
6
|
+
export { extractGraph, extractFromProject, routeForFile, liftGuard, enclosingFunctionName, DEFAULT_EXCLUDE, DEFAULT_INCLUDE, } from './extract.js';
|
|
7
|
+
export { hashSdl, canonicalSdl, hashOperationShapes, normalizeShape, hashLockfile, diffSdl, formatSdlChanges, snapshotContract, NO_HASH, } from './contract.js';
|
|
8
|
+
export { bootApp, waitForPort, waitForPortClosed, isPortOpen, killTree } from './boot.js';
|
|
9
|
+
export { walk, defaultWalkDeps, operationNamesOf, summarizeError, screenshotPath, tracePath, triggerTestId, testIdSelector, FROZEN_EPOCH_MS, VIEWPORT, DEVICE_SCALE_FACTOR, DISABLE_MOTION_CSS, CHROMIUM_ARGS, } from './walk.js';
|
|
10
|
+
export { comparePng, compareWalk, downloadBaselines, baselineId, PIXEL_THRESHOLD, } from './visual.js';
|
|
11
|
+
export { uploadArtifacts, collectArtifacts, PRESIGN_BATCH } from './upload.js';
|
|
12
|
+
export { assembleRunPayload, summarize } from './report.js';
|
|
13
|
+
export { DETERMINISM_RULES, hashPngs, compareHashMaps, formatDeterminismReport, } from './determinism.js';
|
|
14
|
+
export { init, INIT_FILES, templatesDir } from './init.js';
|
|
15
|
+
export { reconcile, validate, resolveCommitSha, resolveApiBaseUrl, gitShowFile, gitExec, API_BASE_URL_ENV, } from './reconcile.js';
|
|
16
|
+
export { syncModels, resolveBranch, resolvePushedAt } from './sync.js';
|
|
17
|
+
export { buildProgram } from './cli.js';
|
|
18
|
+
export { reconcilerVersion, sha256 } from './util.js';
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,OAAO,EACL,YAAY,EACZ,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,aAAa,EACb,WAAW,GACZ,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EACL,IAAI,EACJ,sBAAsB,EACtB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,kBAAkB,GACnB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEnF,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,qBAAqB,EACrB,eAAe,EACf,eAAe,GAChB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,OAAO,EACP,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,OAAO,EACP,gBAAgB,EAChB,gBAAgB,EAChB,OAAO,GACR,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1F,OAAO,EACL,IAAI,EACJ,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,SAAS,EACT,aAAa,EACb,cAAc,EACd,eAAe,EACf,QAAQ,EACR,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,GACd,MAAM,WAAW,CAAC;AAUnB,OAAO,EACL,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,UAAU,EACV,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE/E,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE5D,OAAO,EACL,iBAAiB,EACjB,QAAQ,EACR,eAAe,EACf,uBAAuB,GACxB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE3D,OAAO,EACL,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,OAAO,EACP,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEvE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/init.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Template file -> destination in the client repo. */
|
|
2
|
+
export declare const INIT_FILES: ReadonlyArray<{
|
|
3
|
+
template: string;
|
|
4
|
+
dest: string;
|
|
5
|
+
purpose: string;
|
|
6
|
+
}>;
|
|
7
|
+
export declare function templatesDir(): string;
|
|
8
|
+
export declare function listTemplates(): string[];
|
|
9
|
+
export interface InitResult {
|
|
10
|
+
written: string[];
|
|
11
|
+
skipped: string[];
|
|
12
|
+
}
|
|
13
|
+
/** Copy the templates into `cwd`; existing files are kept unless `force`. */
|
|
14
|
+
export declare function init(cwd: string, opts?: {
|
|
15
|
+
force?: boolean;
|
|
16
|
+
}): InitResult;
|
|
17
|
+
//# sourceMappingURL=init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAIA,uDAAuD;AACvD,eAAO,MAAM,UAAU,EAAE,aAAa,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA0BzF,CAAC;AAEF,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAExC;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,6EAA6E;AAC7E,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,UAAU,CAe5E"}
|