@ifc-lite/sdk 9.2.0 → 9.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/README.md +24 -0
- package/dist/review/capture-budget.d.ts +6 -0
- package/dist/review/capture-budget.d.ts.map +1 -0
- package/dist/review/capture-budget.js +47 -0
- package/dist/review/capture-budget.js.map +1 -0
- package/dist/review/capture-retention.d.ts +47 -0
- package/dist/review/capture-retention.d.ts.map +1 -0
- package/dist/review/capture-retention.js +141 -0
- package/dist/review/capture-retention.js.map +1 -0
- package/dist/review/capture-types.d.ts +57 -0
- package/dist/review/capture-types.d.ts.map +1 -0
- package/dist/review/capture-types.js +5 -0
- package/dist/review/capture-types.js.map +1 -0
- package/dist/review/native-captures.d.ts +21 -0
- package/dist/review/native-captures.d.ts.map +1 -0
- package/dist/review/native-captures.js +325 -0
- package/dist/review/native-captures.js.map +1 -0
- package/dist/review/native-snapshot.d.ts +47 -0
- package/dist/review/native-snapshot.d.ts.map +1 -0
- package/dist/review/native-snapshot.js +98 -0
- package/dist/review/native-snapshot.js.map +1 -0
- package/dist/review/portable-analysis-binding.d.ts +29 -0
- package/dist/review/portable-analysis-binding.d.ts.map +1 -0
- package/dist/review/portable-analysis-binding.js +60 -0
- package/dist/review/portable-analysis-binding.js.map +1 -0
- package/dist/review/portable-analysis.d.ts +103 -0
- package/dist/review/portable-analysis.d.ts.map +1 -0
- package/dist/review/portable-analysis.js +119 -0
- package/dist/review/portable-analysis.js.map +1 -0
- package/dist/review/portable-automation-provenance.d.ts +32 -0
- package/dist/review/portable-automation-provenance.d.ts.map +1 -0
- package/dist/review/portable-automation-provenance.js +68 -0
- package/dist/review/portable-automation-provenance.js.map +1 -0
- package/dist/review/portable-ids-report.d.ts +125 -0
- package/dist/review/portable-ids-report.d.ts.map +1 -0
- package/dist/review/portable-ids-report.js +124 -0
- package/dist/review/portable-ids-report.js.map +1 -0
- package/dist/review/portable-manual-report.d.ts +66 -0
- package/dist/review/portable-manual-report.d.ts.map +1 -0
- package/dist/review/portable-manual-report.js +121 -0
- package/dist/review/portable-manual-report.js.map +1 -0
- package/dist/review/portable-report-metadata.d.ts +42 -0
- package/dist/review/portable-report-metadata.d.ts.map +1 -0
- package/dist/review/portable-report-metadata.js +41 -0
- package/dist/review/portable-report-metadata.js.map +1 -0
- package/dist/review/portable-saved-validation.d.ts +12 -0
- package/dist/review/portable-saved-validation.d.ts.map +1 -0
- package/dist/review/portable-saved-validation.js +32 -0
- package/dist/review/portable-saved-validation.js.map +1 -0
- package/dist/review/portable-validation-evidence.d.ts +53 -0
- package/dist/review/portable-validation-evidence.d.ts.map +1 -0
- package/dist/review/portable-validation-evidence.js +52 -0
- package/dist/review/portable-validation-evidence.js.map +1 -0
- package/dist/review.d.ts +16 -0
- package/dist/review.d.ts.map +1 -1
- package/dist/review.js +11 -0
- package/dist/review.js.map +1 -1
- package/package.json +9 -9
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portable contract for a captured clash or validation run kept for
|
|
3
|
+
* cross-revision reconciliation (#7370). No store or runtime imports: the
|
|
4
|
+
* content library, a backup import and recovery all validate through
|
|
5
|
+
* `decodeSavedAnalysisRun`.
|
|
6
|
+
*
|
|
7
|
+
* A session capture (`CapturedRun`) is the native result object, which names
|
|
8
|
+
* the session's model ids and, for clashes, renderer ids. Neither means
|
|
9
|
+
* anything after a reload. A saved run therefore keeps the native result with
|
|
10
|
+
* every model id replaced by a join key (`SavedRunModel.key`), each model by
|
|
11
|
+
* its name and the source identities the viewer had for it, and each clash
|
|
12
|
+
* element by its local express id instead of the renderer id. An element
|
|
13
|
+
* without a GlobalId has a model-scoped key (`expressid:<model>:<id>`); its
|
|
14
|
+
* model part is the join key too. Everything the
|
|
15
|
+
* reconciler compares (rules, settings, coverage, truncation, specifications,
|
|
16
|
+
* rule content, per-entity results) is kept as the native run recorded it, so
|
|
17
|
+
* the same compatibility checks and refusals apply to a reopened run.
|
|
18
|
+
*/
|
|
19
|
+
import type { Clash, ClashElementRef, ClashResult } from '@ifc-lite/clash';
|
|
20
|
+
import type { ValidationReport } from '@ifc-lite/ids';
|
|
21
|
+
export type SavedTranslation = [number, number, number];
|
|
22
|
+
/** One model the run drew from. `key` joins the rows of this payload; it is never a live model id. */
|
|
23
|
+
export interface SavedRunModel {
|
|
24
|
+
key: string;
|
|
25
|
+
name: string;
|
|
26
|
+
/** Sampled source fingerprint (`FederatedModel.sourceFingerprint`), when the viewer had one. */
|
|
27
|
+
sourceFingerprint?: string;
|
|
28
|
+
/** Full-content source hash (`FederatedModel.sourceContentHash`), when the viewer had one. */
|
|
29
|
+
sourceContentHash?: string;
|
|
30
|
+
/** Placement the run was stamped with; absent when the run recorded none. */
|
|
31
|
+
placement?: {
|
|
32
|
+
translation: SavedTranslation;
|
|
33
|
+
angle: number;
|
|
34
|
+
pivot: SavedTranslation;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** A clash element named by its local express id; the renderer id is rebuilt from the bound model. */
|
|
38
|
+
export type SavedClashRef = Omit<ClashElementRef, 'ref'> & {
|
|
39
|
+
expressId: number;
|
|
40
|
+
};
|
|
41
|
+
/** A non-finite distance survives as its name: JSON would turn it into null. */
|
|
42
|
+
export type SavedDistance = number | 'Infinity' | '-Infinity' | 'NaN';
|
|
43
|
+
export type SavedRunClash = Omit<Clash, 'a' | 'b' | 'distance'> & {
|
|
44
|
+
a: SavedClashRef;
|
|
45
|
+
b: SavedClashRef;
|
|
46
|
+
distance: SavedDistance;
|
|
47
|
+
};
|
|
48
|
+
export type SavedRunClashResult = Omit<ClashResult, 'clashes'> & {
|
|
49
|
+
clashes: SavedRunClash[];
|
|
50
|
+
};
|
|
51
|
+
export type SavedRunValidationReport = Omit<ValidationReport, 'timestamp'> & {
|
|
52
|
+
timestamp: string;
|
|
53
|
+
};
|
|
54
|
+
/** The rule content a rules report ran from (`ReportRuleSetContent`), as rule id/text pairs. */
|
|
55
|
+
export interface SavedRuleSetContent {
|
|
56
|
+
file: string;
|
|
57
|
+
rules: Array<[string, string]>;
|
|
58
|
+
}
|
|
59
|
+
interface SavedAnalysisRunBase {
|
|
60
|
+
version: 1;
|
|
61
|
+
/** The session capture id, kept so a reopened run is the same run to reconciliation and Review. */
|
|
62
|
+
id: string;
|
|
63
|
+
capturedAt: string;
|
|
64
|
+
savedAt: string;
|
|
65
|
+
models: SavedRunModel[];
|
|
66
|
+
/** Keys of the models the run examined; null when the run did not record them. */
|
|
67
|
+
examined: string[] | null;
|
|
68
|
+
/** When saved: the run described the open models, they changed after it, or the run carried no freshness stamp. */
|
|
69
|
+
freshness: 'current' | 'stale' | 'unknown';
|
|
70
|
+
/** A model the run examined had unsaved edits when it ran, so the run does not describe its file; null when unknown. */
|
|
71
|
+
edited: boolean | null;
|
|
72
|
+
/** The run's stamp recorded each model's placement (clash runs do). */
|
|
73
|
+
placementRecorded: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* The placement frame of a placement-stamped run, exactly what makes such a run stale in its session:
|
|
76
|
+
* the committed realignment (`realignedFrameKey`), how many models were open, and each open model the run
|
|
77
|
+
* did not examine (`others`, with its source identity and placement). Null without placement.
|
|
78
|
+
*/
|
|
79
|
+
frame: {
|
|
80
|
+
realignedFrameKey: string | null;
|
|
81
|
+
openModels: number;
|
|
82
|
+
others: SavedRunModel[];
|
|
83
|
+
} | null;
|
|
84
|
+
}
|
|
85
|
+
export type SavedAnalysisRun = SavedAnalysisRunBase & {
|
|
86
|
+
kind: 'clash';
|
|
87
|
+
result: SavedRunClashResult;
|
|
88
|
+
} | SavedAnalysisRunBase & {
|
|
89
|
+
kind: 'validation';
|
|
90
|
+
report: SavedRunValidationReport;
|
|
91
|
+
ruleSet: SavedRuleSetContent | null;
|
|
92
|
+
};
|
|
93
|
+
export declare const SAVED_RUN_LIMITS: {
|
|
94
|
+
readonly models: 1000;
|
|
95
|
+
readonly clashes: 200000;
|
|
96
|
+
readonly rules: 2000;
|
|
97
|
+
readonly specifications: 5000;
|
|
98
|
+
readonly text: 2000;
|
|
99
|
+
};
|
|
100
|
+
/** Strict: one invalid row refuses the whole run rather than reconciling a subset of it as if it were the run. */
|
|
101
|
+
export declare function decodeSavedAnalysisRun(v: unknown): SavedAnalysisRun | null;
|
|
102
|
+
export {};
|
|
103
|
+
//# sourceMappingURL=portable-analysis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portable-analysis.d.ts","sourceRoot":"","sources":["../../src/review/portable-analysis.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
export const SAVED_RUN_LIMITS = { models: 1_000, clashes: 200_000, rules: 2_000, specifications: 5_000, text: 2_000 };
|
|
5
|
+
const record = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
6
|
+
const text = (v, allowEmpty = false, max = SAVED_RUN_LIMITS.text) => typeof v === 'string' && v.length <= max && (allowEmpty || v.length > 0);
|
|
7
|
+
const anyText = (v) => typeof v === 'string';
|
|
8
|
+
const finite = (v) => typeof v === 'number' && Number.isFinite(v);
|
|
9
|
+
const count = (v) => typeof v === 'number' && Number.isSafeInteger(v) && v >= 0;
|
|
10
|
+
const optional = (v, check) => v === undefined || check(v);
|
|
11
|
+
const bool = (v) => typeof v === 'boolean';
|
|
12
|
+
const date = (v) => typeof v === 'string' && Number.isFinite(Date.parse(v));
|
|
13
|
+
const list = (v, max, check) => Array.isArray(v) && v.length <= max && v.every(check);
|
|
14
|
+
const oneOf = (v, values) => typeof v === 'string' && values.includes(v);
|
|
15
|
+
const vector = (v) => Array.isArray(v) && v.length === 3 && v.every(finite);
|
|
16
|
+
function isModel(v) {
|
|
17
|
+
return record(v) && text(v.key) && text(v.name) && optional(v.sourceFingerprint, text) && optional(v.sourceContentHash, text)
|
|
18
|
+
&& optional(v.placement, p => record(p) && vector(p.translation) && finite(p.angle) && vector(p.pivot));
|
|
19
|
+
}
|
|
20
|
+
function isClashRef(v, keys) {
|
|
21
|
+
return record(v) && text(v.key) && text(v.model) && keys.has(v.model) && anyText(v.tag) && optional(v.name, anyText) && count(v.expressId);
|
|
22
|
+
}
|
|
23
|
+
const DISTANCE_NAMES = ['Infinity', '-Infinity', 'NaN'];
|
|
24
|
+
function isClash(v, keys) {
|
|
25
|
+
return record(v) && text(v.id) && text(v.rule) && oneOf(v.status, ['hard', 'clearance', 'touch'])
|
|
26
|
+
&& oneOf(v.severity, ['critical', 'major', 'minor', 'info']) && (finite(v.distance) || oneOf(v.distance, DISTANCE_NAMES))
|
|
27
|
+
&& optional(v.distanceKind, k => oneOf(k, ['mesh', 'estimate'])) && optional(v.depthFloor, finite)
|
|
28
|
+
&& vector(v.point) && record(v.bounds) && vector(v.bounds.min) && vector(v.bounds.max)
|
|
29
|
+
&& isClashRef(v.a, keys) && isClashRef(v.b, keys);
|
|
30
|
+
}
|
|
31
|
+
const keyList = (v) => Array.isArray(v) && v.every(anyText);
|
|
32
|
+
function isCoverage(v) {
|
|
33
|
+
return record(v) && text(v.rule) && count(v.matchedA) && (v.matchedB === null || count(v.matchedB))
|
|
34
|
+
&& optional(v.fromMembersA, bool) && optional(v.fromMembersB, bool) && optional(v.matchedKeysA, keyList)
|
|
35
|
+
&& optional(v.matchedKeysB, k => k === null || keyList(k)) && optional(v.candidatesExamined, count);
|
|
36
|
+
}
|
|
37
|
+
function isRule(v) {
|
|
38
|
+
// Member lists name session renderer ids; a saved run never carries them.
|
|
39
|
+
return record(v) && text(v.id) && anyText(v.name) && anyText(v.a) && optional(v.b, anyText) && oneOf(v.mode, ['hard', 'clearance'])
|
|
40
|
+
&& optional(v.tolerance, finite) && optional(v.clearance, finite)
|
|
41
|
+
&& optional(v.severity, s => oneOf(s, ['critical', 'major', 'minor', 'info'])) && optional(v.reportTouch, bool)
|
|
42
|
+
&& v.membersA === undefined && v.membersB === undefined;
|
|
43
|
+
}
|
|
44
|
+
function isClashResult(v, keys) {
|
|
45
|
+
if (!record(v) || !record(v.settings) || !finite(v.settings.tolerance) || !bool(v.settings.excludeVoidsAndHosts))
|
|
46
|
+
return false;
|
|
47
|
+
if (!record(v.summary) || !list(v.rulesRun, SAVED_RUN_LIMITS.rules, isRule))
|
|
48
|
+
return false;
|
|
49
|
+
if (!optional(v.ruleCoverage, c => list(c, SAVED_RUN_LIMITS.rules, isCoverage)))
|
|
50
|
+
return false;
|
|
51
|
+
if (!optional(v.truncated, t => record(t) && anyText(t.reason) && count(t.droppedPairs)))
|
|
52
|
+
return false;
|
|
53
|
+
return list(v.clashes, SAVED_RUN_LIMITS.clashes, clash => isClash(clash, keys));
|
|
54
|
+
}
|
|
55
|
+
function isEntity(v, keys) {
|
|
56
|
+
return record(v) && count(v.expressId) && text(v.modelId) && keys.has(v.modelId) && anyText(v.entityType)
|
|
57
|
+
&& optional(v.entityName, anyText) && optional(v.globalId, anyText) && bool(v.passed)
|
|
58
|
+
&& Array.isArray(v.requirementResults) && v.requirementResults.every(r => record(r) && record(r.requirement)
|
|
59
|
+
&& anyText(r.requirement.id) && oneOf(r.status, ['pass', 'fail', 'not_applicable']) && optional(r.actualValue, anyText));
|
|
60
|
+
}
|
|
61
|
+
function isSetResult(v, keys) {
|
|
62
|
+
return record(v) && Array.isArray(v.members) && v.members.every(m => record(m) && text(m.modelId) && keys.has(m.modelId) && count(m.expressId));
|
|
63
|
+
}
|
|
64
|
+
function isSpecification(v, keys) {
|
|
65
|
+
return record(v) && record(v.specification) && anyText(v.specification.id) && anyText(v.specification.name)
|
|
66
|
+
&& oneOf(v.status, ['pass', 'fail', 'not_applicable']) && count(v.applicableCount) && count(v.passedCount) && count(v.failedCount)
|
|
67
|
+
&& optional(v.error, anyText) && Array.isArray(v.entityResults) && v.entityResults.every(e => isEntity(e, keys))
|
|
68
|
+
&& optional(v.setResults, s => Array.isArray(s) && s.every(r => isSetResult(r, keys)));
|
|
69
|
+
}
|
|
70
|
+
function isModelInfo(v, keys) {
|
|
71
|
+
return record(v) && text(v.modelId) && keys.has(v.modelId) && anyText(v.schemaVersion) && count(v.entityCount);
|
|
72
|
+
}
|
|
73
|
+
function isValidationReport(v, keys) {
|
|
74
|
+
if (!record(v) || !date(v.timestamp) || !record(v.summary) || !record(v.source))
|
|
75
|
+
return false;
|
|
76
|
+
const source = v.source;
|
|
77
|
+
if (!(source.kind === 'ids' && record(source.document) && Array.isArray(source.document.specifications))
|
|
78
|
+
&& !(source.kind === 'rules' && record(source.ruleSet) && anyText(source.ruleSet.name)))
|
|
79
|
+
return false;
|
|
80
|
+
return list(v.modelInfo, SAVED_RUN_LIMITS.models, info => isModelInfo(info, keys))
|
|
81
|
+
&& list(v.specificationResults, SAVED_RUN_LIMITS.specifications, spec => isSpecification(spec, keys));
|
|
82
|
+
}
|
|
83
|
+
function isRuleSet(v) {
|
|
84
|
+
return record(v) && anyText(v.file) && Array.isArray(v.rules)
|
|
85
|
+
&& v.rules.every(entry => Array.isArray(entry) && entry.length === 2 && anyText(entry[0]) && anyText(entry[1]));
|
|
86
|
+
}
|
|
87
|
+
const isFrame = (v) => record(v)
|
|
88
|
+
&& (v.realignedFrameKey === null || text(v.realignedFrameKey)) && count(v.openModels) && v.openModels > 0
|
|
89
|
+
&& list(v.others, SAVED_RUN_LIMITS.models, other => isModel(other) && other.placement !== undefined);
|
|
90
|
+
/** Strict: one invalid row refuses the whole run rather than reconciling a subset of it as if it were the run. */
|
|
91
|
+
export function decodeSavedAnalysisRun(v) {
|
|
92
|
+
if (!record(v) || v.version !== 1 || !text(v.id, false, 200) || !date(v.capturedAt) || !date(v.savedAt))
|
|
93
|
+
return null;
|
|
94
|
+
if (!oneOf(v.freshness, ['current', 'stale', 'unknown']) || !(v.edited === null || bool(v.edited)) || !bool(v.placementRecorded))
|
|
95
|
+
return null;
|
|
96
|
+
if (v.placementRecorded ? !isFrame(v.frame) : v.frame !== null)
|
|
97
|
+
return null;
|
|
98
|
+
if (!list(v.models, SAVED_RUN_LIMITS.models, isModel))
|
|
99
|
+
return null;
|
|
100
|
+
const keys = new Set(v.models.map(model => model.key));
|
|
101
|
+
if (keys.size !== v.models.length)
|
|
102
|
+
return null;
|
|
103
|
+
// A placement-stamped run recorded where every model sat: one without its placement could never be checked for a move.
|
|
104
|
+
if (v.placementRecorded && v.models.some(model => model.placement === undefined))
|
|
105
|
+
return null;
|
|
106
|
+
// A frame model is one the run did not examine: its key never names a run model, and no two share one.
|
|
107
|
+
const others = isFrame(v.frame) ? v.frame.others : [];
|
|
108
|
+
if (new Set([...keys, ...others.map(other => other.key)]).size !== keys.size + others.length)
|
|
109
|
+
return null;
|
|
110
|
+
if (v.examined !== null && !list(v.examined, SAVED_RUN_LIMITS.models, key => typeof key === 'string' && keys.has(key)))
|
|
111
|
+
return null;
|
|
112
|
+
if (v.kind === 'clash')
|
|
113
|
+
return isClashResult(v.result, keys) ? v : null;
|
|
114
|
+
if (v.kind === 'validation') {
|
|
115
|
+
return isValidationReport(v.report, keys) && (v.ruleSet === null || isRuleSet(v.ruleSet)) ? v : null;
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=portable-analysis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portable-analysis.js","sourceRoot":"","sources":["../../src/review/portable-analysis.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Optional, portable execution context beside immutable native evidence (#6612). */
|
|
2
|
+
export interface AutomationReportProvenance {
|
|
3
|
+
origin: 'flow';
|
|
4
|
+
workflowId: string;
|
|
5
|
+
runId: string;
|
|
6
|
+
jobId: string;
|
|
7
|
+
resultId: string;
|
|
8
|
+
resource?: {
|
|
9
|
+
name: string;
|
|
10
|
+
fingerprint?: string;
|
|
11
|
+
};
|
|
12
|
+
effectiveOptions?: Record<string, AutomationJsonValue>;
|
|
13
|
+
models: Array<{
|
|
14
|
+
id?: string;
|
|
15
|
+
name: string;
|
|
16
|
+
sourceFingerprint?: string;
|
|
17
|
+
mutationRevision?: number;
|
|
18
|
+
}>;
|
|
19
|
+
timestamp: string;
|
|
20
|
+
diagnostics?: Array<{
|
|
21
|
+
severity: 'warning' | 'error';
|
|
22
|
+
message: string;
|
|
23
|
+
code?: string;
|
|
24
|
+
}>;
|
|
25
|
+
}
|
|
26
|
+
export type AutomationJsonValue = null | boolean | number | string | AutomationJsonValue[] | {
|
|
27
|
+
[key: string]: AutomationJsonValue;
|
|
28
|
+
};
|
|
29
|
+
export declare function isAutomationReportProvenance(value: unknown): value is AutomationReportProvenance;
|
|
30
|
+
/** JSON evidence equality ignores object member order; IDs and provenance remain significant. */
|
|
31
|
+
export declare function sameReportEvidence(left: unknown, right: unknown): boolean;
|
|
32
|
+
//# sourceMappingURL=portable-automation-provenance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portable-automation-provenance.d.ts","sourceRoot":"","sources":["../../src/review/portable-automation-provenance.ts"],"names":[],"mappings":"AAIA,qFAAqF;AACrF,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IACvD,MAAM,EAAE,KAAK,CAAC;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpG,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxF;AACD,MAAM,MAAM,mBAAmB,GAAG,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,mBAAmB,EAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB,CAAA;CAAE,CAAC;AAgBpI,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,0BAA0B,CAYhG;AAED,iGAAiG;AACjG,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAczE"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
const record = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
5
|
+
const identifier = (value) => typeof value === 'string' && value.length > 0 && value.length <= 512;
|
|
6
|
+
const optionalString = (value) => value === undefined || identifier(value);
|
|
7
|
+
/** Bound the metadata traversal independently of the native report's entity rows. */
|
|
8
|
+
function portable(value, depth, budget) {
|
|
9
|
+
if (depth > 12 || --budget.left < 0)
|
|
10
|
+
return false;
|
|
11
|
+
if (value === null || typeof value === 'boolean')
|
|
12
|
+
return true;
|
|
13
|
+
if (typeof value === 'number')
|
|
14
|
+
return Number.isFinite(value);
|
|
15
|
+
if (typeof value === 'string')
|
|
16
|
+
return value.length <= 16384;
|
|
17
|
+
if (Array.isArray(value))
|
|
18
|
+
return value.length <= 2048 && value.every((entry) => portable(entry, depth + 1, budget));
|
|
19
|
+
return record(value) && Object.keys(value).length <= 512
|
|
20
|
+
&& Object.entries(value).every(([key, entry]) => key.length <= 512 && portable(entry, depth + 1, budget));
|
|
21
|
+
}
|
|
22
|
+
export function isAutomationReportProvenance(value) {
|
|
23
|
+
if (!record(value) || value.origin !== 'flow' ||
|
|
24
|
+
!['workflowId', 'runId', 'jobId', 'resultId'].every((key) => identifier(value[key])) ||
|
|
25
|
+
typeof value.timestamp !== 'string' || !Number.isFinite(Date.parse(value.timestamp)))
|
|
26
|
+
return false;
|
|
27
|
+
if (value.resource !== undefined && (!record(value.resource) || !identifier(value.resource.name) || !optionalString(value.resource.fingerprint)))
|
|
28
|
+
return false;
|
|
29
|
+
if (value.effectiveOptions !== undefined && (!record(value.effectiveOptions) || !portable(value.effectiveOptions, 0, { left: 10000 })))
|
|
30
|
+
return false;
|
|
31
|
+
if (!Array.isArray(value.models) || value.models.length > 1000 || !value.models.every((model) => record(model)
|
|
32
|
+
&& identifier(model.name) && optionalString(model.id) && optionalString(model.sourceFingerprint)
|
|
33
|
+
&& (model.mutationRevision === undefined || (typeof model.mutationRevision === 'number' && Number.isSafeInteger(model.mutationRevision) && model.mutationRevision >= 0))))
|
|
34
|
+
return false;
|
|
35
|
+
return value.diagnostics === undefined || (Array.isArray(value.diagnostics) && value.diagnostics.length <= 1000 && value.diagnostics.every((diagnostic) => record(diagnostic)
|
|
36
|
+
&& (diagnostic.severity === 'warning' || diagnostic.severity === 'error') && typeof diagnostic.message === 'string'
|
|
37
|
+
&& diagnostic.message.length > 0 && diagnostic.message.length <= 16384 && optionalString(diagnostic.code)));
|
|
38
|
+
}
|
|
39
|
+
/** JSON evidence equality ignores object member order; IDs and provenance remain significant. */
|
|
40
|
+
export function sameReportEvidence(left, right) {
|
|
41
|
+
const normalize = (value, depth, path) => {
|
|
42
|
+
if (depth > 64)
|
|
43
|
+
throw new Error('Evidence nesting exceeds the supported depth');
|
|
44
|
+
if (typeof value !== 'object' || value === null)
|
|
45
|
+
return value;
|
|
46
|
+
if (path.has(value))
|
|
47
|
+
throw new Error('Evidence must not contain cycles');
|
|
48
|
+
path.add(value);
|
|
49
|
+
try {
|
|
50
|
+
if (Array.isArray(value))
|
|
51
|
+
return value.map((entry) => normalize(entry, depth + 1, path));
|
|
52
|
+
if (record(value))
|
|
53
|
+
return Object.fromEntries(Object.keys(value).sort().map((key) => [key, normalize(value[key], depth + 1, path)]));
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
path.delete(value);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
try {
|
|
61
|
+
return JSON.stringify(normalize(left, 0, new WeakSet())) === JSON.stringify(normalize(right, 0, new WeakSet()));
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
console.warn('[Reports] Unable to compare evidence', error);
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=portable-automation-provenance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portable-automation-provenance.js","sourceRoot":"","sources":["../../src/review/portable-automation-provenance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The validation report block's saved shape (#5125, #6372), split out of
|
|
3
|
+
* `types.ts` (which re-exports everything here) to keep that file under its
|
|
4
|
+
* module-size budget.
|
|
5
|
+
*
|
|
6
|
+
* One block kind (`'ids-report'`) serves both validation sources: an IDS run
|
|
7
|
+
* and an information-validation (rule set) run. `sourceKind` says which one
|
|
8
|
+
* produced the snapshot. It is optional and additive (#6372): every block
|
|
9
|
+
* saved before it existed was labelled as IDS, so an absent `sourceKind`
|
|
10
|
+
* reads as `'ids'` and the document format version stays the same.
|
|
11
|
+
*/
|
|
12
|
+
import { type SavedValidationElements } from './portable-validation-evidence.js';
|
|
13
|
+
import { type BlockTitle } from './portable-report-metadata.js';
|
|
14
|
+
import type { PortableReportValidationError as DocumentValidationError } from './portable-report-metadata.js';
|
|
15
|
+
import { type ReportProvenance } from './portable-report-metadata.js';
|
|
16
|
+
/** Which engine produced a report block's snapshot; mirrors `ValidationSource['kind']`. */
|
|
17
|
+
export type ReportSourceKind = 'ids' | 'rules';
|
|
18
|
+
/**
|
|
19
|
+
* One check (IDS specification, or information-validation rule) inside a
|
|
20
|
+
* report block (#5125): the counts and description taken straight off
|
|
21
|
+
* `SpecificationResult` — `shortDescription` is the specification's `name`,
|
|
22
|
+
* `longDescription` its optional `description`, so neither is invented here.
|
|
23
|
+
*
|
|
24
|
+
* The optional fields below are only ever written for an information
|
|
25
|
+
* validation snapshot (#6372); an IDS snapshot keeps its original shape.
|
|
26
|
+
*/
|
|
27
|
+
export interface IdsReportCheckSummary {
|
|
28
|
+
id: string;
|
|
29
|
+
shortDescription: string;
|
|
30
|
+
longDescription?: string;
|
|
31
|
+
checked: number;
|
|
32
|
+
passed: number;
|
|
33
|
+
failed: number;
|
|
34
|
+
/** 0-100, floor-rounded; 100 when `checked` is 0 (no applicable entities) — matches `SpecificationResult.passRate`. */
|
|
35
|
+
passRate: number;
|
|
36
|
+
rules: IdsReportRuleSummary[];
|
|
37
|
+
/** `'warning'`: this check's failures are warnings, counted apart from failures (#6372). Absent means `'error'`. */
|
|
38
|
+
severity?: 'error' | 'warning';
|
|
39
|
+
/** The engine could not evaluate this check (`SpecificationResult.error`); printed instead of counts (#6372). */
|
|
40
|
+
error?: string;
|
|
41
|
+
/** Set-level results of a `unique` / `aggregate` rule (`SpecificationResult.setResults`, #6372). */
|
|
42
|
+
sets?: IdsReportSetRow[];
|
|
43
|
+
/** The engine capped `sets` before every set was evaluated (`setResultsTruncated`). */
|
|
44
|
+
setsTruncated?: boolean;
|
|
45
|
+
/** How many applicable elements the rule found against its declared cardinality (#6372). */
|
|
46
|
+
cardinality?: IdsReportCardinality;
|
|
47
|
+
}
|
|
48
|
+
/** A requirement under one IDS specification. Null metrics mean the source
|
|
49
|
+
* report omitted passing entities, so an exact per-rule count is unavailable. */
|
|
50
|
+
export interface IdsReportRuleSummary {
|
|
51
|
+
id: string;
|
|
52
|
+
/** Bare attribute / property name (#6470), for the compact layout. Absent in older documents. */
|
|
53
|
+
name?: string;
|
|
54
|
+
shortDescription: string;
|
|
55
|
+
longDescription?: string;
|
|
56
|
+
checked: number;
|
|
57
|
+
passed: number | null;
|
|
58
|
+
failed: number | null;
|
|
59
|
+
passRate: number | null;
|
|
60
|
+
}
|
|
61
|
+
/** One uniqueness / aggregate group result, as `SetResult` reports it (without its member list). */
|
|
62
|
+
export interface IdsReportSetRow {
|
|
63
|
+
/** unique: the shared value; aggregate: fn + subject, e.g. `sum(Qto_….NetFloorArea)`. */
|
|
64
|
+
label: string;
|
|
65
|
+
/** The rendered groupBy key (parent name, storey name…), when the rule groups; `''` is a blank grouping value, not "ungrouped". */
|
|
66
|
+
groupKey?: string;
|
|
67
|
+
actual: string;
|
|
68
|
+
expected: string;
|
|
69
|
+
passed: boolean;
|
|
70
|
+
}
|
|
71
|
+
/** `IDSCardinalityResult` reduced to its numbers, so every surface words it in its own language. */
|
|
72
|
+
export interface IdsReportCardinality {
|
|
73
|
+
passed: boolean;
|
|
74
|
+
actual: number;
|
|
75
|
+
min?: number;
|
|
76
|
+
max?: number;
|
|
77
|
+
}
|
|
78
|
+
/** `compact`: one bar row per check / requirement. `long`: full requirement text, never truncated. */
|
|
79
|
+
export type IdsReportVariant = 'compact' | 'long';
|
|
80
|
+
export declare const IDS_REPORT_VARIANTS: readonly IdsReportVariant[];
|
|
81
|
+
/**
|
|
82
|
+
* A frozen snapshot of an IDS / information-validation report (#5125, #6372),
|
|
83
|
+
* taken from the live `ValidationReport` when the block is added or refreshed
|
|
84
|
+
* — like a table block's list copy, it travels with the document instead of
|
|
85
|
+
* reading the store, so a saved document still prints the run that produced it.
|
|
86
|
+
*/
|
|
87
|
+
export interface IdsReportBlock extends ReportProvenance, BlockTitle {
|
|
88
|
+
kind: 'ids-report';
|
|
89
|
+
id: string;
|
|
90
|
+
/** Layout (#6470). Absent in documents saved before it existed, which keep printing the original layout (one truncated line per field) until the author picks one. */
|
|
91
|
+
variant?: IdsReportVariant;
|
|
92
|
+
/**
|
|
93
|
+
* Compact layout only (#6560): print one bar row per specification and leave out its
|
|
94
|
+
* requirement rows. Optional and additive, so the document format version is unchanged;
|
|
95
|
+
* a viewer that supports the document format but predates this field ignores it
|
|
96
|
+
* and prints the full compact report.
|
|
97
|
+
*/
|
|
98
|
+
specificationsOnly?: boolean;
|
|
99
|
+
/** Optional ring benchmark (#6552). Absent retains existing document output. */
|
|
100
|
+
benchmarks?: boolean;
|
|
101
|
+
/** Whole-block size, 0.5-2 (#6548); absent is 1. */
|
|
102
|
+
scale?: number;
|
|
103
|
+
/** Which engine produced the snapshot (#6372). Absent means `'ids'`: every block saved before this field existed was labelled IDS. */
|
|
104
|
+
sourceKind?: ReportSourceKind;
|
|
105
|
+
/** IDS document title, or rule-set name, printed in the block's heading. */
|
|
106
|
+
sourceName: string;
|
|
107
|
+
/** When the snapshotted run finished (`ValidationReport.timestamp`, ISO). */
|
|
108
|
+
generatedAt: string;
|
|
109
|
+
/** `failed` excludes warning-severity failures, which `warnings` counts (#6372; absent on IDS snapshots). */
|
|
110
|
+
summary: {
|
|
111
|
+
checked: number;
|
|
112
|
+
passed: number;
|
|
113
|
+
failed: number;
|
|
114
|
+
passRate: number;
|
|
115
|
+
warnings?: number;
|
|
116
|
+
};
|
|
117
|
+
checks: IdsReportCheckSummary[];
|
|
118
|
+
/** Optional immutable element failures; absent in older count-only snapshots (#7091). */
|
|
119
|
+
elementEvidence?: SavedValidationElements;
|
|
120
|
+
}
|
|
121
|
+
/** The source a report block was snapshotted from; a block saved before #6372 has none and is IDS. */
|
|
122
|
+
export declare function reportBlockSourceKind(block: Pick<IdsReportBlock, 'sourceKind'>): ReportSourceKind;
|
|
123
|
+
/** Structural check of a report block (#5125, #6372): a finite, non-negative count and a 0-100 pass rate at both the block and every check. */
|
|
124
|
+
export declare function validateIdsReportBlock(block: Record<string, unknown>, at: string, errors: DocumentValidationError[]): void;
|
|
125
|
+
//# sourceMappingURL=portable-ids-report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portable-ids-report.d.ts","sourceRoot":"","sources":["../../src/review/portable-ids-report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* The validation report block's saved shape (#5125, #6372), split out of
|
|
6
|
+
* `types.ts` (which re-exports everything here) to keep that file under its
|
|
7
|
+
* module-size budget.
|
|
8
|
+
*
|
|
9
|
+
* One block kind (`'ids-report'`) serves both validation sources: an IDS run
|
|
10
|
+
* and an information-validation (rule set) run. `sourceKind` says which one
|
|
11
|
+
* produced the snapshot. It is optional and additive (#6372): every block
|
|
12
|
+
* saved before it existed was labelled as IDS, so an absent `sourceKind`
|
|
13
|
+
* reads as `'ids'` and the document format version stays the same.
|
|
14
|
+
*/
|
|
15
|
+
import { validateSavedValidationElements } from './portable-validation-evidence.js';
|
|
16
|
+
import { validateBlockTitle } from './portable-report-metadata.js';
|
|
17
|
+
import { validateReportProvenance } from './portable-report-metadata.js';
|
|
18
|
+
export const IDS_REPORT_VARIANTS = ['compact', 'long'];
|
|
19
|
+
/** The source a report block was snapshotted from; a block saved before #6372 has none and is IDS. */
|
|
20
|
+
export function reportBlockSourceKind(block) {
|
|
21
|
+
return block.sourceKind ?? 'ids';
|
|
22
|
+
}
|
|
23
|
+
const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
24
|
+
const isString = (v) => typeof v === 'string';
|
|
25
|
+
const isCount = (v) => typeof v === 'number' && Number.isFinite(v) && v >= 0;
|
|
26
|
+
const isRate = (v) => typeof v === 'number' && Number.isFinite(v) && v >= 0 && v <= 100;
|
|
27
|
+
function validateCheckExtras(check, checkAt, errors) {
|
|
28
|
+
if (check.severity !== undefined && check.severity !== 'error' && check.severity !== 'warning')
|
|
29
|
+
errors.push({ path: `${checkAt}.severity`, message: 'expected error | warning' });
|
|
30
|
+
if (check.error !== undefined && !isString(check.error))
|
|
31
|
+
errors.push({ path: `${checkAt}.error`, message: 'expected a string' });
|
|
32
|
+
if (check.setsTruncated !== undefined && typeof check.setsTruncated !== 'boolean')
|
|
33
|
+
errors.push({ path: `${checkAt}.setsTruncated`, message: 'expected a boolean' });
|
|
34
|
+
if (check.sets !== undefined) {
|
|
35
|
+
if (!Array.isArray(check.sets))
|
|
36
|
+
errors.push({ path: `${checkAt}.sets`, message: 'expected an array' });
|
|
37
|
+
else
|
|
38
|
+
check.sets.forEach((set, k) => {
|
|
39
|
+
const ok = isRecord(set) && isString(set.label) && isString(set.actual) && isString(set.expected) && typeof set.passed === 'boolean'
|
|
40
|
+
&& (set.groupKey === undefined || isString(set.groupKey));
|
|
41
|
+
if (!ok)
|
|
42
|
+
errors.push({ path: `${checkAt}.sets[${k}]`, message: 'expected { label, actual, expected: strings; passed: boolean; groupKey?: string }' });
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
const cardinality = check.cardinality;
|
|
46
|
+
if (cardinality !== undefined) {
|
|
47
|
+
const ok = isRecord(cardinality) && typeof cardinality.passed === 'boolean' && isCount(cardinality.actual)
|
|
48
|
+
&& (cardinality.min === undefined || isCount(cardinality.min)) && (cardinality.max === undefined || isCount(cardinality.max));
|
|
49
|
+
if (!ok)
|
|
50
|
+
errors.push({ path: `${checkAt}.cardinality`, message: 'expected { passed: boolean; actual, min?, max?: non-negative numbers }' });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** Structural check of a report block (#5125, #6372): a finite, non-negative count and a 0-100 pass rate at both the block and every check. */
|
|
54
|
+
export function validateIdsReportBlock(block, at, errors) {
|
|
55
|
+
validateReportProvenance(block, at, errors);
|
|
56
|
+
if (block.elementEvidence !== undefined)
|
|
57
|
+
validateSavedValidationElements(block.elementEvidence, `${at}.elementEvidence`, errors);
|
|
58
|
+
validateBlockTitle(block, at, errors);
|
|
59
|
+
if (block.sourceKind !== undefined && block.sourceKind !== 'ids' && block.sourceKind !== 'rules')
|
|
60
|
+
errors.push({ path: `${at}.sourceKind`, message: 'expected ids | rules' });
|
|
61
|
+
if (!isString(block.sourceName))
|
|
62
|
+
errors.push({ path: `${at}.sourceName`, message: 'expected a string' });
|
|
63
|
+
if (!isString(block.generatedAt))
|
|
64
|
+
errors.push({ path: `${at}.generatedAt`, message: 'expected a string' });
|
|
65
|
+
if (block.variant !== undefined && !IDS_REPORT_VARIANTS.includes(block.variant))
|
|
66
|
+
errors.push({ path: `${at}.variant`, message: `expected ${IDS_REPORT_VARIANTS.join(' | ')}` });
|
|
67
|
+
if (block.benchmarks !== undefined && typeof block.benchmarks !== 'boolean')
|
|
68
|
+
errors.push({ path: `${at}.benchmarks`, message: 'expected a boolean' });
|
|
69
|
+
if (block.specificationsOnly !== undefined && typeof block.specificationsOnly !== 'boolean')
|
|
70
|
+
errors.push({ path: `${at}.specificationsOnly`, message: 'expected a boolean' });
|
|
71
|
+
const summary = block.summary;
|
|
72
|
+
if (!isRecord(summary) || !isCount(summary.checked) || !isCount(summary.passed) || !isCount(summary.failed) || !isRate(summary.passRate)
|
|
73
|
+
|| (summary.warnings !== undefined && !isCount(summary.warnings))) {
|
|
74
|
+
errors.push({ path: `${at}.summary`, message: 'expected { checked, passed, failed, warnings?: non-negative numbers; passRate: 0-100 }' });
|
|
75
|
+
}
|
|
76
|
+
if (!Array.isArray(block.checks)) {
|
|
77
|
+
errors.push({ path: `${at}.checks`, message: 'expected an array' });
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
block.checks.forEach((check, i) => {
|
|
81
|
+
const checkAt = `${at}.checks[${i}]`;
|
|
82
|
+
if (!isRecord(check)) {
|
|
83
|
+
errors.push({ path: checkAt, message: 'expected an object' });
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (!isString(check.id) || check.id.length === 0)
|
|
87
|
+
errors.push({ path: `${checkAt}.id`, message: 'expected a non-empty string' });
|
|
88
|
+
if (!isString(check.shortDescription))
|
|
89
|
+
errors.push({ path: `${checkAt}.shortDescription`, message: 'expected a string' });
|
|
90
|
+
if (check.longDescription !== undefined && !isString(check.longDescription))
|
|
91
|
+
errors.push({ path: `${checkAt}.longDescription`, message: 'expected a string' });
|
|
92
|
+
if (!isCount(check.checked) || !isCount(check.passed) || !isCount(check.failed))
|
|
93
|
+
errors.push({ path: `${checkAt}`, message: 'expected checked/passed/failed: non-negative numbers' });
|
|
94
|
+
if (!isRate(check.passRate))
|
|
95
|
+
errors.push({ path: `${checkAt}.passRate`, message: 'expected a number between 0 and 100' });
|
|
96
|
+
validateCheckExtras(check, checkAt, errors);
|
|
97
|
+
if (!Array.isArray(check.rules)) {
|
|
98
|
+
errors.push({ path: `${checkAt}.rules`, message: 'expected an array' });
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
check.rules.forEach((rule, j) => {
|
|
102
|
+
const ruleAt = `${checkAt}.rules[${j}]`;
|
|
103
|
+
if (!isRecord(rule)) {
|
|
104
|
+
errors.push({ path: ruleAt, message: 'expected an object' });
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (!isString(rule.id) || rule.id.length === 0)
|
|
108
|
+
errors.push({ path: `${ruleAt}.id`, message: 'expected a non-empty string' });
|
|
109
|
+
if (!isString(rule.shortDescription))
|
|
110
|
+
errors.push({ path: `${ruleAt}.shortDescription`, message: 'expected a string' });
|
|
111
|
+
if (rule.name !== undefined && !isString(rule.name))
|
|
112
|
+
errors.push({ path: `${ruleAt}.name`, message: 'expected a string' });
|
|
113
|
+
if (rule.longDescription !== undefined && !isString(rule.longDescription))
|
|
114
|
+
errors.push({ path: `${ruleAt}.longDescription`, message: 'expected a string' });
|
|
115
|
+
if (!isCount(rule.checked))
|
|
116
|
+
errors.push({ path: `${ruleAt}.checked`, message: 'expected a non-negative number' });
|
|
117
|
+
const unavailable = rule.passed === null && rule.failed === null && rule.passRate === null;
|
|
118
|
+
if (!unavailable && (!isCount(rule.passed) || !isCount(rule.failed) || !isRate(rule.passRate))) {
|
|
119
|
+
errors.push({ path: ruleAt, message: 'expected passed/failed: non-negative numbers and passRate: 0-100, or all null' });
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=portable-ids-report.js.map
|