pipework 0.269.0 → 0.271.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 +9 -0
- package/REFERENCE.md +44 -0
- package/dist/cli/commands/check-steps.d.ts +34 -0
- package/dist/cli/commands/check-steps.d.ts.map +1 -0
- package/dist/cli/commands/check-steps.js +60 -0
- package/dist/cli/commands/check-steps.js.map +1 -0
- package/dist/cli/commands/check.d.ts +43 -1
- package/dist/cli/commands/check.d.ts.map +1 -1
- package/dist/cli/commands/check.js +232 -133
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/lint.js +36 -1
- package/dist/cli/commands/lint.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +55 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/lint/config.d.ts +4 -0
- package/dist/lint/config.d.ts.map +1 -1
- package/dist/lint/config.js +6 -0
- package/dist/lint/config.js.map +1 -1
- package/dist/lint/doctrine.d.ts +4 -0
- package/dist/lint/doctrine.d.ts.map +1 -1
- package/dist/lint/doctrine.js +14 -7
- package/dist/lint/doctrine.js.map +1 -1
- package/dist/lint/rules/doctrine.d.ts +3 -0
- package/dist/lint/rules/doctrine.d.ts.map +1 -0
- package/dist/lint/rules/doctrine.js +28 -0
- package/dist/lint/rules/doctrine.js.map +1 -0
- package/dist/trace/cardinality/check.d.ts +5 -1
- package/dist/trace/cardinality/check.d.ts.map +1 -1
- package/dist/trace/cardinality/check.js +3 -1
- package/dist/trace/cardinality/check.js.map +1 -1
- package/dist/trace/check/coverage-check.d.ts +2 -0
- package/dist/trace/check/coverage-check.d.ts.map +1 -1
- package/dist/trace/check/coverage-check.js +3 -1
- package/dist/trace/check/coverage-check.js.map +1 -1
- package/dist/trace/check/flow-check.d.ts +2 -0
- package/dist/trace/check/flow-check.d.ts.map +1 -1
- package/dist/trace/check/flow-check.js +3 -1
- package/dist/trace/check/flow-check.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/commands/check-steps.ts +98 -0
- package/src/cli/commands/check.ts +283 -147
- package/src/cli/commands/lint.ts +34 -1
- package/src/cli/index.ts +56 -2
- package/src/lint/config.ts +6 -0
- package/src/lint/doctrine.ts +17 -8
- package/src/lint/rules/doctrine.ts +31 -0
- package/src/trace/cardinality/check.ts +9 -2
- package/src/trace/check/coverage-check.ts +5 -1
- package/src/trace/check/flow-check.ts +5 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { basename } from 'node:path';
|
|
2
|
+
import { doctrineViolations, isSourceFileName } from '../doctrine.js';
|
|
3
|
+
const RULES = ['prefer-pipe-define', 'no-raw-pgTable', 'brand-primary-key', 'use-traits'];
|
|
4
|
+
function doctrineRule(name) {
|
|
5
|
+
const id = `define/${name}`;
|
|
6
|
+
return {
|
|
7
|
+
meta: {
|
|
8
|
+
type: 'problem',
|
|
9
|
+
docs: { description: `Doctrine rule ${id}; same scan as the doctrine step of pipework check.` },
|
|
10
|
+
schema: [],
|
|
11
|
+
},
|
|
12
|
+
create(context) {
|
|
13
|
+
return {
|
|
14
|
+
'Program:exit'() {
|
|
15
|
+
if (!isSourceFileName(basename(context.filename)))
|
|
16
|
+
return;
|
|
17
|
+
for (const v of doctrineViolations(context.filename, context.sourceCode.text)) {
|
|
18
|
+
if (v.rule !== id)
|
|
19
|
+
continue;
|
|
20
|
+
context.report({ loc: { line: v.line, column: 0 }, message: v.message });
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export const doctrineRules = Object.fromEntries(RULES.map(name => [name, doctrineRule(name)]));
|
|
28
|
+
//# sourceMappingURL=doctrine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctrine.js","sourceRoot":"","sources":["../../../src/lint/rules/doctrine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEpC,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAErE,MAAM,KAAK,GAAG,CAAC,oBAAoB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,YAAY,CAAU,CAAA;AAElG,SAAS,YAAY,CAAC,IAAY;IAChC,MAAM,EAAE,GAAG,UAAU,IAAI,EAAE,CAAA;IAC3B,OAAO;QACL,IAAI,EAAE;YACJ,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,EAAE,WAAW,EAAE,iBAAiB,EAAE,qDAAqD,EAAE;YAC/F,MAAM,EAAE,EAAE;SACX;QACD,MAAM,CAAC,OAAO;YACZ,OAAO;gBACL,cAAc;oBACZ,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;wBAAE,OAAM;oBACzD,KAAK,MAAM,CAAC,IAAI,kBAAkB,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;wBAC9E,IAAI,CAAC,CAAC,IAAI,KAAK,EAAE;4BAAE,SAAQ;wBAC3B,OAAO,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA;oBAC1E,CAAC;gBACH,CAAC;aACF,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAoC,MAAM,CAAC,WAAW,CAC9E,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAC9C,CAAA"}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { type CardinalityResult } from './analyze.js';
|
|
2
|
+
export interface CardinalityCheckResult extends CardinalityResult {
|
|
3
|
+
/** Every file parsed, in input order; a clean one has no violation. */
|
|
4
|
+
readonly scannedFiles: readonly string[];
|
|
5
|
+
}
|
|
2
6
|
/** Analyzes `@downstream` cardinality across `sourceFiles` (paths relative to `cwd`). */
|
|
3
|
-
export declare function checkCardinality(cwd: string, sourceFiles: readonly string[]):
|
|
7
|
+
export declare function checkCardinality(cwd: string, sourceFiles: readonly string[]): CardinalityCheckResult;
|
|
4
8
|
//# sourceMappingURL=check.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../src/trace/cardinality/check.ts"],"names":[],"mappings":"AAQA,OAAO,EAA0C,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAE7F,yFAAyF;AACzF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../src/trace/cardinality/check.ts"],"names":[],"mappings":"AAQA,OAAO,EAA0C,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAE7F,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB;IAC/D,uEAAuE;IACvE,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;CACzC;AAED,yFAAyF;AACzF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,sBAAsB,CAuBpG"}
|
|
@@ -9,6 +9,7 @@ import { analyzeCardinality } from './analyze.js';
|
|
|
9
9
|
/** Analyzes `@downstream` cardinality across `sourceFiles` (paths relative to `cwd`). */
|
|
10
10
|
export function checkCardinality(cwd, sourceFiles) {
|
|
11
11
|
const entries = [];
|
|
12
|
+
const scannedFiles = [];
|
|
12
13
|
for (const file of sourceFiles) {
|
|
13
14
|
const abs = join(cwd, file);
|
|
14
15
|
let sites;
|
|
@@ -20,10 +21,11 @@ export function checkCardinality(cwd, sourceFiles) {
|
|
|
20
21
|
// the type checker's diagnostic, not this check's.
|
|
21
22
|
continue;
|
|
22
23
|
}
|
|
24
|
+
scannedFiles.push(file);
|
|
23
25
|
for (const site of sites) {
|
|
24
26
|
entries.push({ file, site });
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
|
-
return analyzeCardinality(entries);
|
|
29
|
+
return { ...analyzeCardinality(entries), scannedFiles };
|
|
28
30
|
}
|
|
29
31
|
//# sourceMappingURL=check.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/trace/cardinality/check.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,4EAA4E;AAC5E,6EAA6E;AAC7E,8EAA8E;AAE9E,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AACjE,OAAO,EAAE,kBAAkB,EAA8C,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/trace/cardinality/check.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,4EAA4E;AAC5E,6EAA6E;AAC7E,8EAA8E;AAE9E,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AACjE,OAAO,EAAE,kBAAkB,EAA8C,MAAM,cAAc,CAAA;AAO7F,yFAAyF;AACzF,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,WAA8B;IAC1E,MAAM,OAAO,GAAoB,EAAE,CAAA;IACnC,MAAM,YAAY,GAAa,EAAE,CAAA;IAEjC,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;QAE3B,IAAI,KAAK,CAAA;QACT,IAAI,CAAC;YACH,KAAK,GAAG,oBAAoB,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,CAAA;QAChE,CAAC;QAAC,MAAM,CAAC;YACP,sEAAsE;YACtE,mDAAmD;YACnD,SAAQ;QACV,CAAC;QACD,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAEvB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QAC9B,CAAC;IACH,CAAC;IAED,OAAO,EAAE,GAAG,kBAAkB,CAAC,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;AACzD,CAAC"}
|
|
@@ -8,6 +8,8 @@ export interface CoverageViolation {
|
|
|
8
8
|
export interface CoverageCheckResult {
|
|
9
9
|
readonly violations: readonly CoverageViolation[];
|
|
10
10
|
readonly scanned: number;
|
|
11
|
+
/** Every file parsed, in input order; a clean one has no violation. */
|
|
12
|
+
readonly scannedFiles: readonly string[];
|
|
11
13
|
}
|
|
12
14
|
/**
|
|
13
15
|
* Tier-2 coverage check across `sourceFiles` (paths relative to `cwd`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coverage-check.d.ts","sourceRoot":"","sources":["../../../src/trace/check/coverage-check.ts"],"names":[],"mappings":"AA2BA,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAEzD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,SAAS,iBAAiB,EAAE,CAAA;IACjD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"coverage-check.d.ts","sourceRoot":"","sources":["../../../src/trace/check/coverage-check.ts"],"names":[],"mappings":"AA2BA,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAEzD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,SAAS,iBAAiB,EAAE,CAAA;IACjD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,uEAAuE;IACvE,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;CACzC;AAUD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,MAAM,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,GAC5C,mBAAmB,CAqErB"}
|
|
@@ -35,6 +35,7 @@ import { classifyIo } from './io-pattern.js';
|
|
|
35
35
|
export function checkCoverage(cwd, sourceFiles, extras = {}) {
|
|
36
36
|
const violations = [];
|
|
37
37
|
let scanned = 0;
|
|
38
|
+
const scannedFiles = [];
|
|
38
39
|
for (const file of sourceFiles) {
|
|
39
40
|
const abs = join(cwd, file);
|
|
40
41
|
if (!existsSync(abs))
|
|
@@ -52,6 +53,7 @@ export function checkCoverage(cwd, sourceFiles, extras = {}) {
|
|
|
52
53
|
continue;
|
|
53
54
|
}
|
|
54
55
|
scanned++;
|
|
56
|
+
scannedFiles.push(file);
|
|
55
57
|
const ioSites = collectIoSites(program, extras);
|
|
56
58
|
const flowStepRanges = collectFlowStepRanges(sites);
|
|
57
59
|
for (const io of ioSites) {
|
|
@@ -90,7 +92,7 @@ export function checkCoverage(cwd, sourceFiles, extras = {}) {
|
|
|
90
92
|
});
|
|
91
93
|
}
|
|
92
94
|
}
|
|
93
|
-
return { violations, scanned };
|
|
95
|
+
return { violations, scanned, scannedFiles };
|
|
94
96
|
}
|
|
95
97
|
function collectFlowStepRanges(sites) {
|
|
96
98
|
const ranges = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coverage-check.js","sourceRoot":"","sources":["../../../src/trace/check/coverage-check.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,+EAA+E;AAC/E,+EAA+E;AAC/E,6DAA6D;AAC7D,EAAE;AACF,uEAAuE;AACvE,yEAAyE;AACzE,wBAAwB;AACxB,EAAE;AACF,aAAa;AACb,4EAA4E;AAC5E,wEAAwE;AACxE,4EAA4E;AAC5E,4EAA4E;AAC5E,6DAA6D;AAC7D,0EAA0E;AAC1E,oCAAoC;AACpC,EAAE;AACF,4EAA4E;AAC5E,0EAA0E;AAC1E,0EAA0E;AAC1E,0CAA0C;AAE1C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAA;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,EAAmC,MAAM,qBAAqB,CAAA;AACnG,OAAO,EAAE,UAAU,EAAe,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"coverage-check.js","sourceRoot":"","sources":["../../../src/trace/check/coverage-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,8 @@ export interface FlowViolation {
|
|
|
7
7
|
export interface FlowCheckResult {
|
|
8
8
|
readonly violations: readonly FlowViolation[];
|
|
9
9
|
readonly scanned: number;
|
|
10
|
+
/** Every file parsed, in input order; a clean one has no violation. */
|
|
11
|
+
readonly scannedFiles: readonly string[];
|
|
10
12
|
}
|
|
11
13
|
/** Validates every `@flow_step` annotation in `sourceFiles` (paths relative to `cwd`). */
|
|
12
14
|
export declare function checkFlowAnnotations(cwd: string, sourceFiles: readonly string[]): FlowCheckResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-check.d.ts","sourceRoot":"","sources":["../../../src/trace/check/flow-check.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,UAAU,EAAE,SAAS,aAAa,EAAE,CAAA;IAC7C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"flow-check.d.ts","sourceRoot":"","sources":["../../../src/trace/check/flow-check.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,UAAU,EAAE,SAAS,aAAa,EAAE,CAAA;IAC7C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,uEAAuE;IACvE,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;CACzC;AAED,0FAA0F;AAC1F,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,eAAe,CAyBjG"}
|
|
@@ -15,6 +15,7 @@ import { collectFlowStepSites } from './flow-step-site.js';
|
|
|
15
15
|
export function checkFlowAnnotations(cwd, sourceFiles) {
|
|
16
16
|
const violations = [];
|
|
17
17
|
let scanned = 0;
|
|
18
|
+
const scannedFiles = [];
|
|
18
19
|
for (const file of sourceFiles) {
|
|
19
20
|
const abs = join(cwd, file);
|
|
20
21
|
if (!existsSync(abs))
|
|
@@ -28,11 +29,12 @@ export function checkFlowAnnotations(cwd, sourceFiles) {
|
|
|
28
29
|
continue;
|
|
29
30
|
}
|
|
30
31
|
scanned++;
|
|
32
|
+
scannedFiles.push(file);
|
|
31
33
|
for (const site of sites) {
|
|
32
34
|
collectSiteViolations(file, site, violations);
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
|
-
return { violations, scanned };
|
|
37
|
+
return { violations, scanned, scannedFiles };
|
|
36
38
|
}
|
|
37
39
|
function collectSiteViolations(file, site, out) {
|
|
38
40
|
const { subject, annotation, commentLine } = site;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-check.js","sourceRoot":"","sources":["../../../src/trace/check/flow-check.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,gFAAgF;AAChF,6DAA6D;AAC7D,EAAE;AACF,8EAA8E;AAC9E,4EAA4E;AAC5E,iCAAiC;AACjC,EAAE;AACF,yEAAyE;AACzE,8EAA8E;AAE9E,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,oBAAoB,EAAqB,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"flow-check.js","sourceRoot":"","sources":["../../../src/trace/check/flow-check.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// The vocabulary of `check`'s steps: names, the structured record each step
|
|
2
|
+
// yields, the --only/--skip selection, and the JSON writer.
|
|
3
|
+
|
|
4
|
+
import { writeFileSync } from 'node:fs'
|
|
5
|
+
|
|
6
|
+
export const STEP_NAMES = [
|
|
7
|
+
'checksums', 'vitest-config', 'eslint-config', 'config-load', 'doctrine', 'flow',
|
|
8
|
+
'cardinality', 'coverage', 'lint', 'typecheck', 'startup', 'boundaries', 'dependencies', 'install',
|
|
9
|
+
] as const
|
|
10
|
+
|
|
11
|
+
export type StepName = typeof STEP_NAMES[number]
|
|
12
|
+
|
|
13
|
+
export interface StepViolation {
|
|
14
|
+
readonly rule: string
|
|
15
|
+
readonly file: string
|
|
16
|
+
/** 1-based; 0 when the violation is not at a line (a config value, a whole-project fault). */
|
|
17
|
+
readonly line: number
|
|
18
|
+
readonly message: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface FileVerdict {
|
|
22
|
+
readonly file: string
|
|
23
|
+
readonly violations: readonly StepViolation[]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface StepRecord {
|
|
27
|
+
readonly step: StepName
|
|
28
|
+
readonly status: 'passed' | 'failed' | 'skipped'
|
|
29
|
+
readonly pipeworkVersion: string
|
|
30
|
+
/** What the verdict depends on. */
|
|
31
|
+
readonly reads: string
|
|
32
|
+
/** Only on a skipped step: why it did not run. */
|
|
33
|
+
readonly reason?: string
|
|
34
|
+
/** Every scanned file, clean ones with an empty list. Only doctrine, flow, cardinality and coverage. */
|
|
35
|
+
readonly files?: readonly FileVerdict[]
|
|
36
|
+
readonly violations: readonly StepViolation[]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** What each step's verdict depends on, for a gate that keys cached verdicts. */
|
|
40
|
+
export const STEP_READS: Readonly<Record<StepName, string>> = {
|
|
41
|
+
'checksums': 'package.json (its _generated and _checksum fields).',
|
|
42
|
+
'vitest-config': 'vitest.config.ts, any stale vitest configs under the workspace, and the vitest section of pipework.config.ts (loaded, with everything it imports).',
|
|
43
|
+
'eslint-config': 'eslint.config.js and the pipework version.',
|
|
44
|
+
'config-load': 'pipework.config.ts and everything it imports (it is evaluated).',
|
|
45
|
+
'doctrine': "Each file's verdict depends only on that file's bytes and the pipework version; no other file is read.",
|
|
46
|
+
'flow': "Each file's verdict depends only on that file's bytes and the pipework version; no other file is read. A file that does not parse is not judged and is absent from files.",
|
|
47
|
+
'cardinality': "cardinality/mismatch and cardinality/unannotated-ambiguity depend only on the file's own bytes. cardinality/step-cycle depends on ALL scanned source files (the call graph spans files), and the cardinality/structural-max-* verdicts depend on all scanned source files and trace.structuralMax in pipework.config.ts (loaded, with everything it imports). With explicit file arguments only those files form the graph, so cycles and the derived cap reflect that subset. A file that does not parse is absent from files.",
|
|
48
|
+
'coverage': "Each file's verdict depends on that file's bytes, the pipework version and trace.io in pipework.config.ts (loaded, with everything it imports). Violations are warnings: the step never fails.",
|
|
49
|
+
'lint': 'The files the lint include globs name, eslint.config.js, the tsconfig chain and lint.* in pipework.config.ts; type-aware rules also read the files a linted file imports. Not per-file independent.',
|
|
50
|
+
'typecheck': "Every module's tsconfig and the whole program it names. Not per-file independent.",
|
|
51
|
+
'startup': 'pipework.config.ts loaded, and everything that config imports (it is evaluated, so every define() and registration it reaches counts). Needs no database and opens no connection.',
|
|
52
|
+
'boundaries': 'scripts/check-boundaries.js and the repository files it scans.',
|
|
53
|
+
'dependencies': 'package.json of each workspace package.',
|
|
54
|
+
'install': "The pipework copies under node_modules (pnpm's virtual-store lockfile and each copy's package.json).",
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function record(
|
|
58
|
+
step: StepName,
|
|
59
|
+
version: string,
|
|
60
|
+
status: StepRecord['status'],
|
|
61
|
+
violations: readonly StepViolation[] = [],
|
|
62
|
+
scannedFiles?: readonly string[],
|
|
63
|
+
reason?: string,
|
|
64
|
+
): StepRecord {
|
|
65
|
+
const base = { step, status, pipeworkVersion: version, reads: STEP_READS[step] }
|
|
66
|
+
const withReason = reason === undefined ? base : { ...base, reason }
|
|
67
|
+
if (scannedFiles === undefined) return { ...withReason, violations }
|
|
68
|
+
const files = scannedFiles.map(file => ({ file, violations: violations.filter(v => v.file === file) }))
|
|
69
|
+
return { ...withReason, files, violations }
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export type StepSelection = (step: StepName) => boolean
|
|
73
|
+
|
|
74
|
+
/** --only and --skip take comma-separated step names; either alone, never both. */
|
|
75
|
+
export function parseStepSelection(only: string | undefined, skip: string | undefined): StepSelection {
|
|
76
|
+
const valid = `Valid steps: ${STEP_NAMES.join(', ')}.`
|
|
77
|
+
if (only !== undefined && skip !== undefined) {
|
|
78
|
+
throw new Error(`--only and --skip cannot be combined. ${valid}`)
|
|
79
|
+
}
|
|
80
|
+
const raw = only ?? skip
|
|
81
|
+
if (raw === undefined) return () => true
|
|
82
|
+
const flag = only !== undefined ? '--only' : '--skip'
|
|
83
|
+
const names = raw.split(',').map(n => n.trim())
|
|
84
|
+
for (const name of names) {
|
|
85
|
+
if (!(STEP_NAMES as readonly string[]).includes(name)) {
|
|
86
|
+
throw new Error(`${flag} names an unknown step "${name}". ${valid}`)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const set = new Set<string>(names)
|
|
90
|
+
return only !== undefined ? step => set.has(step) : step => !set.has(step)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** The JSON to stdout, or to `outputFile` when given. */
|
|
94
|
+
export function emitJson(value: unknown, outputFile: string | undefined): void {
|
|
95
|
+
const text = JSON.stringify(value, null, 2) + '\n'
|
|
96
|
+
if (outputFile === undefined) process.stdout.write(text)
|
|
97
|
+
else writeFileSync(outputFile, text, 'utf-8')
|
|
98
|
+
}
|