@cleocode/contracts 2026.5.111 → 2026.5.113
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/dist/__tests__/cli-meta-suggested-next.test.d.ts +21 -0
- package/dist/__tests__/cli-meta-suggested-next.test.d.ts.map +1 -0
- package/dist/__tests__/cli-meta-suggested-next.test.js +70 -0
- package/dist/__tests__/cli-meta-suggested-next.test.js.map +1 -0
- package/dist/__tests__/evidence-atom-schema.test.d.ts +16 -0
- package/dist/__tests__/evidence-atom-schema.test.d.ts.map +1 -0
- package/dist/__tests__/evidence-atom-schema.test.js +394 -0
- package/dist/__tests__/evidence-atom-schema.test.js.map +1 -0
- package/dist/config/__tests__/manifest.test.d.ts +13 -0
- package/dist/config/__tests__/manifest.test.d.ts.map +1 -0
- package/dist/config/__tests__/manifest.test.js +143 -0
- package/dist/config/__tests__/manifest.test.js.map +1 -0
- package/dist/config/manifest.d.ts +158 -0
- package/dist/config/manifest.d.ts.map +1 -0
- package/dist/config/manifest.js +123 -0
- package/dist/config/manifest.js.map +1 -0
- package/dist/docs/__tests__/provenance.test.d.ts +14 -0
- package/dist/docs/__tests__/provenance.test.d.ts.map +1 -0
- package/dist/docs/__tests__/provenance.test.js +579 -0
- package/dist/docs/__tests__/provenance.test.js.map +1 -0
- package/dist/docs/provenance.d.ts +731 -0
- package/dist/docs/provenance.d.ts.map +1 -0
- package/dist/docs/provenance.js +258 -0
- package/dist/docs/provenance.js.map +1 -0
- package/dist/docs-taxonomy.d.ts +24 -0
- package/dist/docs-taxonomy.d.ts.map +1 -1
- package/dist/docs-taxonomy.js +27 -0
- package/dist/docs-taxonomy.js.map +1 -1
- package/dist/doctor.d.ts +101 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/errors.d.ts +4 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +4 -0
- package/dist/errors.js.map +1 -1
- package/dist/evidence-atom-schema.d.ts +407 -0
- package/dist/evidence-atom-schema.d.ts.map +1 -0
- package/dist/evidence-atom-schema.js +505 -0
- package/dist/evidence-atom-schema.js.map +1 -0
- package/dist/exit-codes.d.ts +37 -0
- package/dist/exit-codes.d.ts.map +1 -1
- package/dist/exit-codes.js +37 -0
- package/dist/exit-codes.js.map +1 -1
- package/dist/index.d.ts +13 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/invariants/__tests__/adr-056-release.test.d.ts +16 -0
- package/dist/invariants/__tests__/adr-056-release.test.d.ts.map +1 -0
- package/dist/invariants/__tests__/adr-056-release.test.js +88 -0
- package/dist/invariants/__tests__/adr-056-release.test.js.map +1 -0
- package/dist/invariants/__tests__/adr-070-orchestration.test.d.ts +22 -0
- package/dist/invariants/__tests__/adr-070-orchestration.test.d.ts.map +1 -0
- package/dist/invariants/__tests__/adr-070-orchestration.test.js +151 -0
- package/dist/invariants/__tests__/adr-070-orchestration.test.js.map +1 -0
- package/dist/invariants/__tests__/registry.test.d.ts +14 -0
- package/dist/invariants/__tests__/registry.test.d.ts.map +1 -0
- package/dist/invariants/__tests__/registry.test.js +113 -0
- package/dist/invariants/__tests__/registry.test.js.map +1 -0
- package/dist/invariants/adr-056-release.d.ts +42 -0
- package/dist/invariants/adr-056-release.d.ts.map +1 -0
- package/dist/invariants/adr-056-release.js +143 -0
- package/dist/invariants/adr-056-release.js.map +1 -0
- package/dist/invariants/adr-070-orchestration.d.ts +73 -0
- package/dist/invariants/adr-070-orchestration.d.ts.map +1 -0
- package/dist/invariants/adr-070-orchestration.js +290 -0
- package/dist/invariants/adr-070-orchestration.js.map +1 -0
- package/dist/invariants/adr-073-saga.d.ts +32 -0
- package/dist/invariants/adr-073-saga.d.ts.map +1 -0
- package/dist/invariants/adr-073-saga.js +155 -0
- package/dist/invariants/adr-073-saga.js.map +1 -0
- package/dist/invariants/index.d.ts +162 -0
- package/dist/invariants/index.d.ts.map +1 -0
- package/dist/invariants/index.js +118 -0
- package/dist/invariants/index.js.map +1 -0
- package/dist/operations/__tests__/input-contract.test.d.ts +20 -0
- package/dist/operations/__tests__/input-contract.test.d.ts.map +1 -0
- package/dist/operations/__tests__/input-contract.test.js +158 -0
- package/dist/operations/__tests__/input-contract.test.js.map +1 -0
- package/dist/operations/docs.d.ts +16 -0
- package/dist/operations/docs.d.ts.map +1 -1
- package/dist/operations/input-contract.d.ts +267 -0
- package/dist/operations/input-contract.d.ts.map +1 -0
- package/dist/operations/input-contract.js +29 -0
- package/dist/operations/input-contract.js.map +1 -0
- package/dist/templates/__tests__/manifest.test.d.ts +18 -0
- package/dist/templates/__tests__/manifest.test.d.ts.map +1 -0
- package/dist/templates/__tests__/manifest.test.js +123 -0
- package/dist/templates/__tests__/manifest.test.js.map +1 -0
- package/dist/templates/manifest.d.ts +186 -0
- package/dist/templates/manifest.d.ts.map +1 -0
- package/dist/templates/manifest.js +165 -0
- package/dist/templates/manifest.js.map +1 -0
- package/package.json +2 -2
- package/src/__tests__/cli-meta-suggested-next.test.ts +76 -0
- package/src/__tests__/evidence-atom-schema.test.ts +499 -0
- package/src/config/__tests__/manifest.test.ts +176 -0
- package/src/config/manifest.ts +218 -0
- package/src/docs/__tests__/__snapshots__/provenance.test.ts.snap +252 -0
- package/src/docs/__tests__/provenance.test.ts +648 -0
- package/src/docs/provenance.ts +601 -0
- package/src/docs-taxonomy.ts +55 -0
- package/src/doctor.ts +111 -0
- package/src/errors.ts +4 -0
- package/src/evidence-atom-schema.ts +628 -0
- package/src/exit-codes.ts +39 -0
- package/src/index.ts +129 -0
- package/src/invariants/__tests__/adr-056-release.test.ts +102 -0
- package/src/invariants/__tests__/adr-070-orchestration.test.ts +186 -0
- package/src/invariants/__tests__/registry.test.ts +136 -0
- package/src/invariants/adr-056-release.ts +154 -0
- package/src/invariants/adr-070-orchestration.ts +317 -0
- package/src/invariants/adr-073-saga.ts +167 -0
- package/src/invariants/index.ts +222 -0
- package/src/operations/__tests__/input-contract.test.ts +188 -0
- package/src/operations/docs.ts +16 -0
- package/src/operations/input-contract.ts +301 -0
- package/src/templates/__tests__/manifest.test.ts +140 -0
- package/src/templates/manifest.ts +208 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Central invariants registry — SSoT for system-wide invariants surfaced via
|
|
3
|
+
* the SaGa T10326 SG-SUBSTRATE-RECONCILIATION programme (Epic T10327
|
|
4
|
+
* E-INVARIANT-REGISTRY-SSOT, Task T10335 R1).
|
|
5
|
+
*
|
|
6
|
+
* Every registered invariant carries the metadata needed to:
|
|
7
|
+
* 1. Reference its source ADR (e.g. `ADR-073` §1.2 for I1-I8).
|
|
8
|
+
* 2. Locate the runtime guard that enforces it (when one exists).
|
|
9
|
+
* 3. Bind the CI lint rule that protects it (when one exists).
|
|
10
|
+
* 4. Cross-reference test files that exercise it.
|
|
11
|
+
* 5. Render documentation via the downstream R8 auto-render pipeline.
|
|
12
|
+
*
|
|
13
|
+
* Downstream consumers:
|
|
14
|
+
* - R2 (T10336, SHIPPED): registers ADR-070 ORC-001..ORC-014 codes into
|
|
15
|
+
* this same registry via `./adr-070-orchestration.ts`.
|
|
16
|
+
* - R4 (T10338): CI gate validates that every `severity:'error'` entry has
|
|
17
|
+
* a non-null `runtimeGate` AND a matching error-code in `errors.ts`.
|
|
18
|
+
* - R5 (T10339): refactor `packages/core/src/release/invariants/registry.ts`
|
|
19
|
+
* to consume the central registry instead of carrying its own list.
|
|
20
|
+
* - R6 (T10340): `cleo doctor --audit-invariants` walks the registry to
|
|
21
|
+
* produce a per-invariant audit report.
|
|
22
|
+
* - R8 (T10342): auto-render docs page from the registry.
|
|
23
|
+
*
|
|
24
|
+
* @epic T10327 — E-INVARIANT-REGISTRY-SSOT
|
|
25
|
+
* @saga T10326 — SG-SUBSTRATE-RECONCILIATION
|
|
26
|
+
* @task T10335 — R1: registry + ADR-073 I1-I8
|
|
27
|
+
* @see ADR-073-above-epic-naming.md §1.2
|
|
28
|
+
*/
|
|
29
|
+
import { ADR_056_INVARIANTS } from './adr-056-release.js';
|
|
30
|
+
import { ADR_070_INVARIANTS } from './adr-070-orchestration.js';
|
|
31
|
+
import { ADR_073_INVARIANTS } from './adr-073-saga.js';
|
|
32
|
+
// Re-exported so consumers can import either the per-ADR list or the merged
|
|
33
|
+
// registry from one place.
|
|
34
|
+
export { ADR_056_INVARIANTS } from './adr-056-release.js';
|
|
35
|
+
export { ADR_070_INVARIANTS } from './adr-070-orchestration.js';
|
|
36
|
+
export { ADR_073_INVARIANTS } from './adr-073-saga.js';
|
|
37
|
+
/**
|
|
38
|
+
* Compute the canonical registry key for an invariant.
|
|
39
|
+
*
|
|
40
|
+
* @internal
|
|
41
|
+
*/
|
|
42
|
+
function buildKey(invariant) {
|
|
43
|
+
return `${invariant.adr}.${invariant.code}`;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Build the merged registry record from all per-ADR invariant modules.
|
|
47
|
+
*
|
|
48
|
+
* Future ADR modules (ADR-070 ORC codes via R2 T10336, etc.) append to
|
|
49
|
+
* the spread list below. Each module exports a `readonly RegisteredInvariant[]`
|
|
50
|
+
* — this index assembles them into a keyed record at module load time.
|
|
51
|
+
*
|
|
52
|
+
* @internal
|
|
53
|
+
*/
|
|
54
|
+
function buildRegistry() {
|
|
55
|
+
const entries = [
|
|
56
|
+
...ADR_073_INVARIANTS,
|
|
57
|
+
...ADR_056_INVARIANTS,
|
|
58
|
+
...ADR_070_INVARIANTS,
|
|
59
|
+
];
|
|
60
|
+
const record = {};
|
|
61
|
+
for (const entry of entries) {
|
|
62
|
+
const key = buildKey(entry);
|
|
63
|
+
if (record[key] !== undefined) {
|
|
64
|
+
throw new Error(`Duplicate invariant key registered: ${key}`);
|
|
65
|
+
}
|
|
66
|
+
record[key] = entry;
|
|
67
|
+
}
|
|
68
|
+
return Object.freeze(record);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Central invariants registry — keyed by `${adr}.${code}`.
|
|
72
|
+
*
|
|
73
|
+
* Treat as read-only at runtime. Mutating this record is a contract
|
|
74
|
+
* violation; downstream consumers (R5 release-registry refactor, R6
|
|
75
|
+
* doctor audit, R8 docs renderer) assume immutability.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* import { INVARIANTS_REGISTRY } from '@cleocode/contracts';
|
|
80
|
+
* const i3 = INVARIANTS_REGISTRY['ADR-073.I3'];
|
|
81
|
+
* if (i3?.runtimeGate) {
|
|
82
|
+
* console.log(`Guard: ${i3.runtimeGate.functionName}`);
|
|
83
|
+
* }
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export const INVARIANTS_REGISTRY = buildRegistry();
|
|
87
|
+
/**
|
|
88
|
+
* Look up a single invariant by its `${adr}.${code}` key.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* const i3 = getInvariant('ADR-073.I3');
|
|
93
|
+
* // → RegisteredInvariant for ADR-073 invariant I3
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export function getInvariant(adrCode) {
|
|
97
|
+
return INVARIANTS_REGISTRY[adrCode];
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Return every invariant registered against a given ADR, in declaration order.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* const adr073 = getInvariantsByAdr('ADR-073');
|
|
105
|
+
* // → array of I1..I8 entries
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export function getInvariantsByAdr(adr) {
|
|
109
|
+
const result = [];
|
|
110
|
+
for (const key of Object.keys(INVARIANTS_REGISTRY)) {
|
|
111
|
+
const entry = INVARIANTS_REGISTRY[key];
|
|
112
|
+
if (entry !== undefined && entry.adr === adr) {
|
|
113
|
+
result.push(entry);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/invariants/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,4EAA4E;AAC5E,2BAA2B;AAC3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAoGvD;;;;GAIG;AACH,SAAS,QAAQ,CAAC,SAA8B;IAC9C,OAAO,GAAG,SAAS,CAAC,GAAG,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC;AAC9C,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,aAAa;IACpB,MAAM,OAAO,GAA0B;QACrC,GAAG,kBAAkB;QACrB,GAAG,kBAAkB;QACrB,GAAG,kBAAkB;KACtB,CAAC;IACF,MAAM,MAAM,GAAwC,EAAE,CAAC;IACvD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC5B,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,uCAAuC,GAAG,EAAE,CAAC,CAAC;QAChE,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACtB,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAkD,aAAa,EAAE,CAAC;AAElG;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,OAAO,mBAAmB,CAAC,OAAO,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,MAAM,MAAM,GAA0B,EAAE,CAAC;IACzC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACnD,MAAM,KAAK,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;YAC7C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type + construction tests for OperationInputContract, ValidationResult,
|
|
3
|
+
* and ValidationError.
|
|
4
|
+
*
|
|
5
|
+
* These tests are intentionally minimal — the contracts package is a leaf
|
|
6
|
+
* with zero runtime dependencies, so there is no validator to exercise
|
|
7
|
+
* here. Instead, we assert:
|
|
8
|
+
*
|
|
9
|
+
* 1. ValidationResult narrows correctly via the `ok` discriminator.
|
|
10
|
+
* 2. A typed OperationInputContract<T> can be constructed and its
|
|
11
|
+
* examples[0].value satisfies the generic.
|
|
12
|
+
* 3. ValidationError can be constructed with all 6 required fields.
|
|
13
|
+
*
|
|
14
|
+
* The runtime validator that consumes these types ships under T9915.
|
|
15
|
+
*
|
|
16
|
+
* @epic T9855
|
|
17
|
+
* @task T9914
|
|
18
|
+
*/
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=input-contract.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-contract.test.d.ts","sourceRoot":"","sources":["../../../src/operations/__tests__/input-contract.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type + construction tests for OperationInputContract, ValidationResult,
|
|
3
|
+
* and ValidationError.
|
|
4
|
+
*
|
|
5
|
+
* These tests are intentionally minimal — the contracts package is a leaf
|
|
6
|
+
* with zero runtime dependencies, so there is no validator to exercise
|
|
7
|
+
* here. Instead, we assert:
|
|
8
|
+
*
|
|
9
|
+
* 1. ValidationResult narrows correctly via the `ok` discriminator.
|
|
10
|
+
* 2. A typed OperationInputContract<T> can be constructed and its
|
|
11
|
+
* examples[0].value satisfies the generic.
|
|
12
|
+
* 3. ValidationError can be constructed with all 6 required fields.
|
|
13
|
+
*
|
|
14
|
+
* The runtime validator that consumes these types ships under T9915.
|
|
15
|
+
*
|
|
16
|
+
* @epic T9855
|
|
17
|
+
* @task T9914
|
|
18
|
+
*/
|
|
19
|
+
import { describe, expect, it } from 'vitest';
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// ValidationResult discriminated-union narrowing
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
describe('ValidationResult<T>', () => {
|
|
24
|
+
it('narrows to the success branch when ok is true', () => {
|
|
25
|
+
// Constructor return type is widened so TS keeps both branches reachable
|
|
26
|
+
// at the call site — that's the whole point of the discriminated union.
|
|
27
|
+
const makeResult = () => ({
|
|
28
|
+
ok: true,
|
|
29
|
+
value: { title: 'Ship E7' },
|
|
30
|
+
});
|
|
31
|
+
const result = makeResult();
|
|
32
|
+
if (result.ok) {
|
|
33
|
+
// Type-level: TypeScript narrows result.value to { title: string }.
|
|
34
|
+
// Runtime: the value is exactly what we constructed.
|
|
35
|
+
expect(result.value.title).toBe('Ship E7');
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
// Type-level: result.errors is ValidationError[].
|
|
39
|
+
expect(result.errors).toEqual([]);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
it('narrows to the failure branch when ok is false', () => {
|
|
43
|
+
const makeResult = () => ({
|
|
44
|
+
ok: false,
|
|
45
|
+
errors: [
|
|
46
|
+
{
|
|
47
|
+
path: '/title',
|
|
48
|
+
expected: 'string with minLength 1',
|
|
49
|
+
received: 'empty string',
|
|
50
|
+
fix: 'Provide a non-empty title.',
|
|
51
|
+
errorCode: 'E_INPUT_MIN_LENGTH',
|
|
52
|
+
schemaPath: '#/properties/title/minLength',
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
});
|
|
56
|
+
const result = makeResult();
|
|
57
|
+
if (result.ok) {
|
|
58
|
+
expect(result.value).toBeDefined();
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
expect(result.errors).toHaveLength(1);
|
|
62
|
+
expect(result.errors[0]?.errorCode).toBe('E_INPUT_MIN_LENGTH');
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// OperationInputContract<T> construction
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
describe('OperationInputContract<T>', () => {
|
|
70
|
+
it('builds a typed contract whose examples match the generic', () => {
|
|
71
|
+
const schema = {
|
|
72
|
+
type: 'object',
|
|
73
|
+
required: ['title', 'acceptance'],
|
|
74
|
+
properties: {
|
|
75
|
+
title: { type: 'string', minLength: 1, maxLength: 200 },
|
|
76
|
+
acceptance: { type: 'string', minLength: 1 },
|
|
77
|
+
},
|
|
78
|
+
additionalProperties: false,
|
|
79
|
+
};
|
|
80
|
+
const contract = {
|
|
81
|
+
operation: 'tasks.create',
|
|
82
|
+
schema,
|
|
83
|
+
examples: [
|
|
84
|
+
{
|
|
85
|
+
name: 'minimal',
|
|
86
|
+
value: { title: 'Ship E7', acceptance: 'PR merged' },
|
|
87
|
+
description: 'Smallest valid payload.',
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
};
|
|
91
|
+
expect(contract.operation).toBe('tasks.create');
|
|
92
|
+
expect(contract.schema).toBe(schema);
|
|
93
|
+
expect(contract.examples).toHaveLength(1);
|
|
94
|
+
const first = contract.examples[0];
|
|
95
|
+
expect(first).toBeDefined();
|
|
96
|
+
// Type-level: first.value is CreateTaskInput. Runtime sanity:
|
|
97
|
+
expect(first?.value.title).toBe('Ship E7');
|
|
98
|
+
expect(first?.value.acceptance).toBe('PR merged');
|
|
99
|
+
expect(first?.name).toBe('minimal');
|
|
100
|
+
expect(first?.description).toBe('Smallest valid payload.');
|
|
101
|
+
});
|
|
102
|
+
it('accepts a contract with an example that omits the optional description', () => {
|
|
103
|
+
const contract = {
|
|
104
|
+
operation: 'docs.fetch',
|
|
105
|
+
schema: { type: 'object', required: ['id'], properties: { id: { type: 'string' } } },
|
|
106
|
+
examples: [{ name: 'minimal', value: { id: 'adr-076' } }],
|
|
107
|
+
};
|
|
108
|
+
expect(contract.examples[0]?.description).toBeUndefined();
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
// ValidationError shape
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
describe('ValidationError', () => {
|
|
115
|
+
it('constructs with all 6 required fields', () => {
|
|
116
|
+
const err = {
|
|
117
|
+
path: '/owners/0/email',
|
|
118
|
+
expected: 'string matching email format',
|
|
119
|
+
received: 'string',
|
|
120
|
+
fix: 'Use a valid email address (e.g. user@example.com).',
|
|
121
|
+
errorCode: 'E_INPUT_FORMAT_EMAIL',
|
|
122
|
+
schemaPath: '#/properties/owners/items/properties/email/format',
|
|
123
|
+
};
|
|
124
|
+
expect(err.path).toBe('/owners/0/email');
|
|
125
|
+
expect(err.expected).toBe('string matching email format');
|
|
126
|
+
expect(err.received).toBe('string');
|
|
127
|
+
expect(err.fix).toBe('Use a valid email address (e.g. user@example.com).');
|
|
128
|
+
expect(err.errorCode).toBe('E_INPUT_FORMAT_EMAIL');
|
|
129
|
+
expect(err.schemaPath).toBe('#/properties/owners/items/properties/email/format');
|
|
130
|
+
// All 6 fields present — no extras.
|
|
131
|
+
expect(Object.keys(err).sort()).toEqual([
|
|
132
|
+
'errorCode',
|
|
133
|
+
'expected',
|
|
134
|
+
'fix',
|
|
135
|
+
'path',
|
|
136
|
+
'received',
|
|
137
|
+
'schemaPath',
|
|
138
|
+
]);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
// ---------------------------------------------------------------------------
|
|
142
|
+
// Registry shape
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
144
|
+
describe('OperationInputContractRegistry', () => {
|
|
145
|
+
it('keys contracts by their operation identifier', () => {
|
|
146
|
+
const createTask = {
|
|
147
|
+
operation: 'tasks.create',
|
|
148
|
+
schema: { type: 'object', required: ['title'], properties: { title: { type: 'string' } } },
|
|
149
|
+
examples: [{ name: 'minimal', value: { title: 'a' } }],
|
|
150
|
+
};
|
|
151
|
+
const registry = {
|
|
152
|
+
'tasks.create': createTask,
|
|
153
|
+
};
|
|
154
|
+
expect(registry['tasks.create']?.operation).toBe('tasks.create');
|
|
155
|
+
expect(registry['unknown.op']).toBeUndefined();
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
//# sourceMappingURL=input-contract.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-contract.test.js","sourceRoot":"","sources":["../../../src/operations/__tests__/input-contract.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -351,6 +351,22 @@ export interface DocsAddParams {
|
|
|
351
351
|
* @task T9637 (T-DOCS-SLUG-2)
|
|
352
352
|
*/
|
|
353
353
|
type?: DocsType;
|
|
354
|
+
/**
|
|
355
|
+
* When `true`, body-schema validation against
|
|
356
|
+
* {@link DocKindMetadata.requiredSections} is enforced — a missing
|
|
357
|
+
* required H2 section returns `E_DOC_SCHEMA_MISMATCH` with the
|
|
358
|
+
* missing-sections list in `details.missing`. When omitted or `false`,
|
|
359
|
+
* the validator runs in advisory mode: the write proceeds and any
|
|
360
|
+
* missing sections surface as a warning in the envelope's `meta`.
|
|
361
|
+
*
|
|
362
|
+
* Only meaningful when `file` is set; URL attachments skip body
|
|
363
|
+
* validation (no local bytes to scan).
|
|
364
|
+
*
|
|
365
|
+
* @task T10160 (E12.C3 · absorbs T10154)
|
|
366
|
+
* @epic T10157
|
|
367
|
+
* @saga T9855
|
|
368
|
+
*/
|
|
369
|
+
strict?: boolean;
|
|
354
370
|
}
|
|
355
371
|
/**
|
|
356
372
|
* Result of `docs.add`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/operations/docs.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/operations/docs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OperationInputContract — schema-first input contract for CLEO operations.
|
|
3
|
+
*
|
|
4
|
+
* This module is the SINGLE SOURCE OF TRUTH for the schema-first input
|
|
5
|
+
* validation surface that powers the `mutate(operation, input)` DX
|
|
6
|
+
* (Saga T9855 / E7). Every CLEO operation that accepts structured input
|
|
7
|
+
* MUST be describable as an {@link OperationInputContract}: a JSON Schema
|
|
8
|
+
* draft-07 document, a stable operation identifier, and at least one
|
|
9
|
+
* worked example payload.
|
|
10
|
+
*
|
|
11
|
+
* Validators consume an {@link OperationInputContract} and produce a
|
|
12
|
+
* {@link ValidationResult} discriminated union — either the typed value
|
|
13
|
+
* (`ok: true`) or an array of {@link ValidationError} entries with
|
|
14
|
+
* actionable, JSON-Pointer-anchored remediation hints (`ok: false`).
|
|
15
|
+
*
|
|
16
|
+
* ZERO runtime dependencies: `contracts` is a leaf package. JSON Schema
|
|
17
|
+
* documents are modeled as the loose alias {@link JsonSchema} so this
|
|
18
|
+
* module does not pull in a JSON Schema typings package.
|
|
19
|
+
*
|
|
20
|
+
* @packageDocumentation
|
|
21
|
+
* @module @cleocode/contracts/operations/input-contract
|
|
22
|
+
*
|
|
23
|
+
* @see {@link https://json-schema.org/draft-07/schema}
|
|
24
|
+
*
|
|
25
|
+
* @epic T9855
|
|
26
|
+
* @task T9914
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* Loose alias for a JSON Schema draft-07 document.
|
|
30
|
+
*
|
|
31
|
+
* Intentionally typed as `Record<string, unknown>` to keep the contracts
|
|
32
|
+
* package free of any JSON Schema typings runtime/type dependency. The
|
|
33
|
+
* actual draft-07 shape is enforced by the validator implementation
|
|
34
|
+
* (T9915) at the point of use, not by the type system here.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* const titleSchema: JsonSchema = {
|
|
39
|
+
* type: 'object',
|
|
40
|
+
* required: ['title'],
|
|
41
|
+
* properties: {
|
|
42
|
+
* title: { type: 'string', minLength: 1 },
|
|
43
|
+
* },
|
|
44
|
+
* };
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export type JsonSchema = Record<string, unknown>;
|
|
48
|
+
/**
|
|
49
|
+
* A single worked example payload for an {@link OperationInputContract}.
|
|
50
|
+
*
|
|
51
|
+
* Examples are MANDATORY (the contract requires at least one) — they
|
|
52
|
+
* double as documentation for human readers AND as conformance fixtures
|
|
53
|
+
* for the validator self-test that ships with every CLEO release.
|
|
54
|
+
*
|
|
55
|
+
* @typeParam T - The validated, typed input shape produced by the contract.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* const example: OperationInputExample<{ title: string }> = {
|
|
60
|
+
* name: 'minimal',
|
|
61
|
+
* value: { title: 'Ship saga T9855' },
|
|
62
|
+
* description: 'Smallest valid input — title is the only required field.',
|
|
63
|
+
* };
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export interface OperationInputExample<T> {
|
|
67
|
+
/**
|
|
68
|
+
* Short, human-readable identifier for the example. Conventionally
|
|
69
|
+
* kebab-case (`'minimal'`, `'with-all-fields'`, `'edge-empty-array'`).
|
|
70
|
+
*/
|
|
71
|
+
name: string;
|
|
72
|
+
/**
|
|
73
|
+
* A concrete value that validates successfully against the contract's
|
|
74
|
+
* {@link OperationInputContract.schema | schema}. Strongly typed via
|
|
75
|
+
* the `T` generic so example tables stay in sync with the operation
|
|
76
|
+
* payload shape at compile time.
|
|
77
|
+
*/
|
|
78
|
+
value: T;
|
|
79
|
+
/**
|
|
80
|
+
* Optional prose explaining why this example matters — what edge case
|
|
81
|
+
* it covers, what default it exercises, etc. Surfaced in generated docs.
|
|
82
|
+
*/
|
|
83
|
+
description?: string;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Schema-first input contract for a single CLEO operation.
|
|
87
|
+
*
|
|
88
|
+
* Pairs a stable operation identifier with the JSON Schema draft-07
|
|
89
|
+
* document that describes the operation's accepted input shape, plus a
|
|
90
|
+
* non-empty (by convention) catalogue of worked examples. The validator
|
|
91
|
+
* implementation (T9915) ingests an {@link OperationInputContract} and a
|
|
92
|
+
* raw payload, returning a {@link ValidationResult}.
|
|
93
|
+
*
|
|
94
|
+
* Together with the {@link OperationInputContractRegistry}, this type is
|
|
95
|
+
* the foundation of the schema-first `mutate(operation, input)` DX
|
|
96
|
+
* surface (Saga T9855 / E7).
|
|
97
|
+
*
|
|
98
|
+
* @typeParam T - The validated, typed input shape produced when the
|
|
99
|
+
* raw payload passes validation. The generic propagates through
|
|
100
|
+
* {@link ValidationResult} so callers receive a strongly-typed `value`
|
|
101
|
+
* in the success branch.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```ts
|
|
105
|
+
* interface CreateTaskInput {
|
|
106
|
+
* title: string;
|
|
107
|
+
* acceptance: string;
|
|
108
|
+
* }
|
|
109
|
+
*
|
|
110
|
+
* const createTaskContract: OperationInputContract<CreateTaskInput> = {
|
|
111
|
+
* operation: 'tasks.create',
|
|
112
|
+
* schema: {
|
|
113
|
+
* type: 'object',
|
|
114
|
+
* required: ['title', 'acceptance'],
|
|
115
|
+
* properties: {
|
|
116
|
+
* title: { type: 'string', minLength: 1, maxLength: 200 },
|
|
117
|
+
* acceptance: { type: 'string', minLength: 1 },
|
|
118
|
+
* },
|
|
119
|
+
* additionalProperties: false,
|
|
120
|
+
* },
|
|
121
|
+
* examples: [
|
|
122
|
+
* {
|
|
123
|
+
* name: 'minimal',
|
|
124
|
+
* value: { title: 'Ship E7', acceptance: 'PR merged' },
|
|
125
|
+
* },
|
|
126
|
+
* ],
|
|
127
|
+
* };
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
export interface OperationInputContract<T> {
|
|
131
|
+
/**
|
|
132
|
+
* Stable, fully-qualified operation identifier in
|
|
133
|
+
* `<domain>.<verb>` form (e.g. `'tasks.create'`, `'docs.publish'`).
|
|
134
|
+
* Used as the registry key in {@link OperationInputContractRegistry}.
|
|
135
|
+
*/
|
|
136
|
+
operation: string;
|
|
137
|
+
/**
|
|
138
|
+
* JSON Schema draft-07 document describing the accepted input shape.
|
|
139
|
+
* The validator MUST treat absent properties as not-present (it does
|
|
140
|
+
* NOT inject `default` values) so callers can distinguish "user
|
|
141
|
+
* omitted" from "user supplied default".
|
|
142
|
+
*/
|
|
143
|
+
schema: JsonSchema;
|
|
144
|
+
/**
|
|
145
|
+
* Catalogue of worked example payloads. Conventionally non-empty so
|
|
146
|
+
* generated docs always have at least one runnable sample. Each
|
|
147
|
+
* example's {@link OperationInputExample.value | value} is statically
|
|
148
|
+
* typed to the contract's `T` parameter.
|
|
149
|
+
*/
|
|
150
|
+
examples: ReadonlyArray<OperationInputExample<T>>;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* A single validation failure produced by the input validator.
|
|
154
|
+
*
|
|
155
|
+
* Every field is REQUIRED — there are no optional remediation hints.
|
|
156
|
+
* This shape is the wire format the `mutate` DX surface returns to
|
|
157
|
+
* callers, so it MUST be stable, machine-parseable, AND human-readable.
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* ```ts
|
|
161
|
+
* const err: ValidationError = {
|
|
162
|
+
* path: '/title',
|
|
163
|
+
* expected: 'string with minLength 1',
|
|
164
|
+
* received: 'empty string',
|
|
165
|
+
* fix: 'Provide a non-empty title (1-200 chars).',
|
|
166
|
+
* errorCode: 'E_INPUT_MIN_LENGTH',
|
|
167
|
+
* schemaPath: '#/properties/title/minLength',
|
|
168
|
+
* };
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
export interface ValidationError {
|
|
172
|
+
/**
|
|
173
|
+
* RFC 6901 JSON Pointer to the failing input location, anchored at
|
|
174
|
+
* the root of the payload (e.g. `'/title'`, `'/owners/0/email'`).
|
|
175
|
+
* An empty string `''` denotes the root document itself.
|
|
176
|
+
*/
|
|
177
|
+
path: string;
|
|
178
|
+
/**
|
|
179
|
+
* Human-readable description of what the validator expected at
|
|
180
|
+
* {@link ValidationError.path | path} (e.g. `'string'`,
|
|
181
|
+
* `'integer >= 0'`, `'one of: pending | active | done'`).
|
|
182
|
+
*/
|
|
183
|
+
expected: string;
|
|
184
|
+
/**
|
|
185
|
+
* Human-readable description of what was actually received at
|
|
186
|
+
* {@link ValidationError.path | path}. NEVER includes the raw value
|
|
187
|
+
* itself — describes type/cardinality only — so logs of errors do
|
|
188
|
+
* not accidentally leak user payloads.
|
|
189
|
+
*/
|
|
190
|
+
received: string;
|
|
191
|
+
/**
|
|
192
|
+
* Actionable, imperative remediation hint targeted at the caller
|
|
193
|
+
* (e.g. `'Provide a non-empty title (1-200 chars).'`). Surfaced
|
|
194
|
+
* directly in CLI output and validator return envelopes.
|
|
195
|
+
*/
|
|
196
|
+
fix: string;
|
|
197
|
+
/**
|
|
198
|
+
* Stable, screaming-snake-case error code (e.g.
|
|
199
|
+
* `'E_INPUT_MIN_LENGTH'`, `'E_INPUT_REQUIRED'`). Stable across
|
|
200
|
+
* releases so callers can branch on it programmatically.
|
|
201
|
+
*/
|
|
202
|
+
errorCode: string;
|
|
203
|
+
/**
|
|
204
|
+
* RFC 6901 JSON Pointer into the contract's
|
|
205
|
+
* {@link OperationInputContract.schema | schema} that produced the
|
|
206
|
+
* failure (e.g. `'#/properties/title/minLength'`). Lets tooling jump
|
|
207
|
+
* straight to the offending schema clause.
|
|
208
|
+
*/
|
|
209
|
+
schemaPath: string;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Discriminated union returned by the input validator.
|
|
213
|
+
*
|
|
214
|
+
* Narrows on the `ok` boolean: when `ok === true`, the strongly-typed
|
|
215
|
+
* `value` is present; when `ok === false`, a non-empty `errors` array
|
|
216
|
+
* lists every failure (validators are encouraged to surface ALL errors
|
|
217
|
+
* in one pass, not bail on the first).
|
|
218
|
+
*
|
|
219
|
+
* @typeParam T - The validated, typed input shape produced on success.
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* ```ts
|
|
223
|
+
* function handle(result: ValidationResult<{ title: string }>) {
|
|
224
|
+
* if (result.ok) {
|
|
225
|
+
* // result.value is { title: string }
|
|
226
|
+
* return createTask(result.value);
|
|
227
|
+
* }
|
|
228
|
+
* // result.errors is ValidationError[]
|
|
229
|
+
* for (const e of result.errors) {
|
|
230
|
+
* console.error(`${e.path}: ${e.fix}`);
|
|
231
|
+
* }
|
|
232
|
+
* }
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
export type ValidationResult<T> = {
|
|
236
|
+
readonly ok: true;
|
|
237
|
+
readonly value: T;
|
|
238
|
+
} | {
|
|
239
|
+
readonly ok: false;
|
|
240
|
+
readonly errors: ValidationError[];
|
|
241
|
+
};
|
|
242
|
+
/**
|
|
243
|
+
* Registry of every {@link OperationInputContract} known to the CLEO
|
|
244
|
+
* runtime, keyed by the contract's `operation` identifier (e.g.
|
|
245
|
+
* `'tasks.create'`).
|
|
246
|
+
*
|
|
247
|
+
* The value type uses `unknown` for the contract's generic so registry
|
|
248
|
+
* lookups stay assignable across operations with different input
|
|
249
|
+
* shapes. Callers that need the concrete `T` MUST narrow via an
|
|
250
|
+
* operation-specific accessor — direct `registry[op]` reads are
|
|
251
|
+
* intentionally not type-narrowed by operation name.
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```ts
|
|
255
|
+
* const registry: OperationInputContractRegistry = {
|
|
256
|
+
* 'tasks.create': createTaskContract,
|
|
257
|
+
* 'docs.publish': publishDocsContract,
|
|
258
|
+
* };
|
|
259
|
+
*
|
|
260
|
+
* const contract = registry['tasks.create'];
|
|
261
|
+
* if (contract) {
|
|
262
|
+
* // validate(contract, payload) → ValidationResult<unknown>
|
|
263
|
+
* }
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
export type OperationInputContractRegistry = Record<string, OperationInputContract<unknown>>;
|
|
267
|
+
//# sourceMappingURL=input-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-contract.d.ts","sourceRoot":"","sources":["../../src/operations/input-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAMH;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAMjD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACtC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;OAKG;IACH,KAAK,EAAE,CAAC,CAAC;IAET;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,MAAM,WAAW,sBAAsB,CAAC,CAAC;IACvC;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;;;;OAKG;IACH,MAAM,EAAE,UAAU,CAAC;IAEnB;;;;;OAKG;IACH,QAAQ,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC;CACnD;AAMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;;;;OAKG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAMD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAC1B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GACxC;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,eAAe,EAAE,CAAA;CAAE,CAAC;AAM/D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,MAAM,8BAA8B,GAAG,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OperationInputContract — schema-first input contract for CLEO operations.
|
|
3
|
+
*
|
|
4
|
+
* This module is the SINGLE SOURCE OF TRUTH for the schema-first input
|
|
5
|
+
* validation surface that powers the `mutate(operation, input)` DX
|
|
6
|
+
* (Saga T9855 / E7). Every CLEO operation that accepts structured input
|
|
7
|
+
* MUST be describable as an {@link OperationInputContract}: a JSON Schema
|
|
8
|
+
* draft-07 document, a stable operation identifier, and at least one
|
|
9
|
+
* worked example payload.
|
|
10
|
+
*
|
|
11
|
+
* Validators consume an {@link OperationInputContract} and produce a
|
|
12
|
+
* {@link ValidationResult} discriminated union — either the typed value
|
|
13
|
+
* (`ok: true`) or an array of {@link ValidationError} entries with
|
|
14
|
+
* actionable, JSON-Pointer-anchored remediation hints (`ok: false`).
|
|
15
|
+
*
|
|
16
|
+
* ZERO runtime dependencies: `contracts` is a leaf package. JSON Schema
|
|
17
|
+
* documents are modeled as the loose alias {@link JsonSchema} so this
|
|
18
|
+
* module does not pull in a JSON Schema typings package.
|
|
19
|
+
*
|
|
20
|
+
* @packageDocumentation
|
|
21
|
+
* @module @cleocode/contracts/operations/input-contract
|
|
22
|
+
*
|
|
23
|
+
* @see {@link https://json-schema.org/draft-07/schema}
|
|
24
|
+
*
|
|
25
|
+
* @epic T9855
|
|
26
|
+
* @task T9914
|
|
27
|
+
*/
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=input-contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-contract.js","sourceRoot":"","sources":["../../src/operations/input-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG"}
|