@0disoft/mensor-contract 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 +201 -0
- package/dist/spec/diagnostic-report-v1.schema.json +735 -0
- package/dist/spec/feature-contract-v1.schema.json +257 -0
- package/dist/spec/project-contract-v1.schema.json +132 -0
- package/dist/spec/route-index-v1.schema.json +78 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/jsonc.d.ts +4 -0
- package/dist/src/jsonc.d.ts.map +1 -0
- package/dist/src/jsonc.js +132 -0
- package/dist/src/jsonc.js.map +1 -0
- package/dist/src/route-index.d.ts +4 -0
- package/dist/src/route-index.d.ts.map +1 -0
- package/dist/src/route-index.js +120 -0
- package/dist/src/route-index.js.map +1 -0
- package/dist/src/schemas.d.ts +8 -0
- package/dist/src/schemas.d.ts.map +1 -0
- package/dist/src/schemas.js +40 -0
- package/dist/src/schemas.js.map +1 -0
- package/dist/src/types.d.ts +385 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/validate.d.ts +5 -0
- package/dist/src/validate.d.ts.map +1 -0
- package/dist/src/validate.js +102 -0
- package/dist/src/validate.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { parseJsonc } from "./jsonc.js";
|
|
2
|
+
import { schemaIssues, validateDiagnosticReport, validateFeatureContract, validateProjectContract, } from "./schemas.js";
|
|
3
|
+
export function parseProjectContract(text) {
|
|
4
|
+
return parseAndValidate(text, validateProjectContract);
|
|
5
|
+
}
|
|
6
|
+
export function parseFeatureContract(text) {
|
|
7
|
+
const result = parseAndValidate(text, validateFeatureContract);
|
|
8
|
+
return result.ok ? applySemanticIssues(result.value, featureSemanticIssues(result.value)) : result;
|
|
9
|
+
}
|
|
10
|
+
export function parseDiagnosticReport(text) {
|
|
11
|
+
const result = parseAndValidate(text, validateDiagnosticReport);
|
|
12
|
+
return result.ok ? applySemanticIssues(result.value, reportSemanticIssues(result.value)) : result;
|
|
13
|
+
}
|
|
14
|
+
function parseAndValidate(text, validate) {
|
|
15
|
+
const parsed = parseJsonc(text);
|
|
16
|
+
if (!parsed.ok) {
|
|
17
|
+
return parsed;
|
|
18
|
+
}
|
|
19
|
+
if (!validate(parsed.value)) {
|
|
20
|
+
return { ok: false, issues: schemaIssues(validate) };
|
|
21
|
+
}
|
|
22
|
+
return { ok: true, value: parsed.value };
|
|
23
|
+
}
|
|
24
|
+
function applySemanticIssues(value, issues) {
|
|
25
|
+
return issues.length === 0 ? { ok: true, value } : { ok: false, issues };
|
|
26
|
+
}
|
|
27
|
+
function featureSemanticIssues(feature) {
|
|
28
|
+
const issues = [];
|
|
29
|
+
feature.actions.forEach((action, actionIndex) => {
|
|
30
|
+
const bindingNames = new Set();
|
|
31
|
+
const bindingPaths = new Set();
|
|
32
|
+
action.input.formCodec.bindings.forEach((binding, bindingIndex) => {
|
|
33
|
+
const base = `/actions/${actionIndex}/input/formCodec/bindings/${bindingIndex}`;
|
|
34
|
+
const pathKey = binding.path.join("\u0000");
|
|
35
|
+
if (binding.path.length !== 1 ||
|
|
36
|
+
!Object.hasOwn(action.input.schema.properties, binding.path[0] ?? "")) {
|
|
37
|
+
issues.push(semanticIssue(`${base}/path`, "Form binding path must identify exactly one declared input schema property."));
|
|
38
|
+
}
|
|
39
|
+
if (bindingNames.has(binding.name)) {
|
|
40
|
+
issues.push(semanticIssue(`${base}/name`, "Form binding names must be unique."));
|
|
41
|
+
}
|
|
42
|
+
if (bindingPaths.has(pathKey)) {
|
|
43
|
+
issues.push(semanticIssue(`${base}/path`, "Form binding paths must be unique."));
|
|
44
|
+
}
|
|
45
|
+
bindingNames.add(binding.name);
|
|
46
|
+
bindingPaths.add(pathKey);
|
|
47
|
+
});
|
|
48
|
+
const ignoredNames = new Set();
|
|
49
|
+
(action.input.formCodec.ignoredFields ?? []).forEach((field, fieldIndex) => {
|
|
50
|
+
const instancePath = `/actions/${actionIndex}/input/formCodec/ignoredFields/${fieldIndex}/name`;
|
|
51
|
+
if (bindingNames.has(field.name)) {
|
|
52
|
+
issues.push(semanticIssue(instancePath, "A form field name cannot be both bound and ignored."));
|
|
53
|
+
}
|
|
54
|
+
if (ignoredNames.has(field.name)) {
|
|
55
|
+
issues.push(semanticIssue(instancePath, "Ignored form field names must be unique."));
|
|
56
|
+
}
|
|
57
|
+
ignoredNames.add(field.name);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
return issues;
|
|
61
|
+
}
|
|
62
|
+
function reportSemanticIssues(report) {
|
|
63
|
+
const issues = [];
|
|
64
|
+
const severities = report.diagnostics.map((item) => item.severity);
|
|
65
|
+
const errorCount = severities.filter((severity) => severity === "error").length;
|
|
66
|
+
const warningCount = severities.filter((severity) => severity === "warning").length;
|
|
67
|
+
const expectedStatus = errorCount === 0 ? "passed" : "failed";
|
|
68
|
+
if (report.status !== expectedStatus) {
|
|
69
|
+
issues.push(semanticIssue("/status", "Diagnostic report status must be derived from errors."));
|
|
70
|
+
}
|
|
71
|
+
if (report.summary.errorCount !== errorCount) {
|
|
72
|
+
issues.push(semanticIssue("/summary/errorCount", "Diagnostic report errorCount must equal the number of error diagnostics."));
|
|
73
|
+
}
|
|
74
|
+
if (report.summary.warningCount !== warningCount) {
|
|
75
|
+
issues.push(semanticIssue("/summary/warningCount", "Diagnostic report warningCount must equal the number of warning diagnostics."));
|
|
76
|
+
}
|
|
77
|
+
report.diagnostics.forEach((diagnostic, diagnosticIndex) => {
|
|
78
|
+
if (!rangeIsOrdered(diagnostic.range)) {
|
|
79
|
+
issues.push(semanticIssue(`/diagnostics/${diagnosticIndex}/range`, "Diagnostic range start must not follow its end."));
|
|
80
|
+
}
|
|
81
|
+
diagnostic.related.forEach((related, relatedIndex) => {
|
|
82
|
+
if (!rangeIsOrdered(related.range)) {
|
|
83
|
+
issues.push(semanticIssue(`/diagnostics/${diagnosticIndex}/related/${relatedIndex}/range`, "Related range start must not follow its end."));
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
return issues;
|
|
88
|
+
}
|
|
89
|
+
function rangeIsOrdered(range) {
|
|
90
|
+
return range.start.line < range.end.line || (range.start.line === range.end.line &&
|
|
91
|
+
range.start.character <= range.end.character);
|
|
92
|
+
}
|
|
93
|
+
function semanticIssue(instancePath, message) {
|
|
94
|
+
return {
|
|
95
|
+
code: "schema.violation",
|
|
96
|
+
message,
|
|
97
|
+
instancePath,
|
|
98
|
+
schemaPath: "#/$semantic",
|
|
99
|
+
keyword: "semantic",
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/validate.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@0disoft/mensor-contract",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Serializable contracts, schemas, and deterministic diagnostics for Mensor.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public",
|
|
8
|
+
"registry": "https://registry.npmjs.org",
|
|
9
|
+
"provenance": true
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/0disoft/mensor.git",
|
|
14
|
+
"directory": "packages/contract"
|
|
15
|
+
},
|
|
16
|
+
"homepage": "https://github.com/0disoft/mensor#readme",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/0disoft/mensor/issues"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"mensor",
|
|
22
|
+
"contracts",
|
|
23
|
+
"diagnostics",
|
|
24
|
+
"json-schema",
|
|
25
|
+
"developer-tools"
|
|
26
|
+
],
|
|
27
|
+
"type": "module",
|
|
28
|
+
"sideEffects": false,
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=22"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"LICENSE",
|
|
34
|
+
"dist/src",
|
|
35
|
+
"dist/spec"
|
|
36
|
+
],
|
|
37
|
+
"exports": {
|
|
38
|
+
".": {
|
|
39
|
+
"types": "./dist/src/index.d.ts",
|
|
40
|
+
"import": "./dist/src/index.js"
|
|
41
|
+
},
|
|
42
|
+
"./schemas/project-contract-v1.schema.json": "./dist/spec/project-contract-v1.schema.json",
|
|
43
|
+
"./schemas/feature-contract-v1.schema.json": "./dist/spec/feature-contract-v1.schema.json",
|
|
44
|
+
"./schemas/diagnostic-report-v1.schema.json": "./dist/spec/diagnostic-report-v1.schema.json",
|
|
45
|
+
"./schemas/route-index-v1.schema.json": "./dist/spec/route-index-v1.schema.json"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"ajv": "8.20.0",
|
|
49
|
+
"jsonc-parser": "3.3.1"
|
|
50
|
+
}
|
|
51
|
+
}
|