@contractual/differs.core 0.1.0-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/assemble.d.ts +10 -0
- package/dist/assemble.d.ts.map +1 -0
- package/dist/assemble.js +42 -0
- package/dist/assemble.js.map +1 -0
- package/dist/classifiers.d.ts +87 -0
- package/dist/classifiers.d.ts.map +1 -0
- package/dist/classifiers.js +375 -0
- package/dist/classifiers.js.map +1 -0
- package/dist/format.d.ts +12 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +127 -0
- package/dist/format.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/ref-resolver.d.ts +73 -0
- package/dist/ref-resolver.d.ts.map +1 -0
- package/dist/ref-resolver.js +345 -0
- package/dist/ref-resolver.js.map +1 -0
- package/dist/types.d.ts +170 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +151 -0
- package/dist/types.js.map +1 -0
- package/dist/walker.d.ts +17 -0
- package/dist/walker.d.ts.map +1 -0
- package/dist/walker.js +1195 -0
- package/dist/walker.js.map +1 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (C) 2025 Omer Morad
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result assembly — classify, format, summarize, and compute suggestedBump
|
|
3
|
+
*/
|
|
4
|
+
import type { RawChange, ChangeSeverity, DiffResult } from '@contractual/types';
|
|
5
|
+
export interface AssembleOptions {
|
|
6
|
+
contract?: string;
|
|
7
|
+
classifyFn?: (change: RawChange, newSchema: unknown) => ChangeSeverity;
|
|
8
|
+
}
|
|
9
|
+
export declare function assembleResult(rawChanges: RawChange[], resolvedNewSchema: unknown, options?: AssembleOptions): DiffResult;
|
|
10
|
+
//# sourceMappingURL=assemble.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assemble.d.ts","sourceRoot":"","sources":["../src/assemble.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAU,cAAc,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAIxF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,KAAK,cAAc,CAAC;CACxE;AAED,wBAAgB,cAAc,CAC5B,UAAU,EAAE,SAAS,EAAE,EACvB,iBAAiB,EAAE,OAAO,EAC1B,OAAO,CAAC,EAAE,eAAe,GACxB,UAAU,CAkCZ"}
|
package/dist/assemble.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result assembly — classify, format, summarize, and compute suggestedBump
|
|
3
|
+
*/
|
|
4
|
+
import { classify, classifyPropertyAdded } from './classifiers.js';
|
|
5
|
+
import { formatChangeMessage } from './format.js';
|
|
6
|
+
export function assembleResult(rawChanges, resolvedNewSchema, options) {
|
|
7
|
+
const classifyChange = options?.classifyFn ?? defaultClassify;
|
|
8
|
+
const changes = rawChanges.map((raw) => ({
|
|
9
|
+
path: raw.path,
|
|
10
|
+
severity: classifyChange(raw, resolvedNewSchema),
|
|
11
|
+
category: raw.type,
|
|
12
|
+
message: formatChangeMessage(raw),
|
|
13
|
+
oldValue: raw.oldValue,
|
|
14
|
+
newValue: raw.newValue,
|
|
15
|
+
}));
|
|
16
|
+
const summary = {
|
|
17
|
+
breaking: changes.filter((c) => c.severity === 'breaking').length,
|
|
18
|
+
nonBreaking: changes.filter((c) => c.severity === 'non-breaking').length,
|
|
19
|
+
patch: changes.filter((c) => c.severity === 'patch').length,
|
|
20
|
+
unknown: changes.filter((c) => c.severity === 'unknown').length,
|
|
21
|
+
};
|
|
22
|
+
const suggestedBump = summary.breaking > 0
|
|
23
|
+
? 'major'
|
|
24
|
+
: summary.nonBreaking > 0
|
|
25
|
+
? 'minor'
|
|
26
|
+
: summary.patch > 0
|
|
27
|
+
? 'patch'
|
|
28
|
+
: 'none';
|
|
29
|
+
return {
|
|
30
|
+
contract: options?.contract ?? '',
|
|
31
|
+
changes,
|
|
32
|
+
summary,
|
|
33
|
+
suggestedBump,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function defaultClassify(change, newSchema) {
|
|
37
|
+
if (change.type === 'property-added') {
|
|
38
|
+
return classifyPropertyAdded(change, newSchema);
|
|
39
|
+
}
|
|
40
|
+
return classify(change);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=assemble.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assemble.js","sourceRoot":"","sources":["../src/assemble.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAOlD,MAAM,UAAU,cAAc,CAC5B,UAAuB,EACvB,iBAA0B,EAC1B,OAAyB;IAEzB,MAAM,cAAc,GAAG,OAAO,EAAE,UAAU,IAAI,eAAe,CAAC;IAE9D,MAAM,OAAO,GAAa,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACjD,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,QAAQ,EAAE,cAAc,CAAC,GAAG,EAAE,iBAAiB,CAAC;QAChD,QAAQ,EAAE,GAAG,CAAC,IAAI;QAClB,OAAO,EAAE,mBAAmB,CAAC,GAAG,CAAC;QACjC,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,QAAQ,EAAE,GAAG,CAAC,QAAQ;KACvB,CAAC,CAAC,CAAC;IAEJ,MAAM,OAAO,GAAG;QACd,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,MAAM;QACjE,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,cAAc,CAAC,CAAC,MAAM;QACxE,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,MAAM;QAC3D,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,MAAM;KAChE,CAAC;IAEF,MAAM,aAAa,GACjB,OAAO,CAAC,QAAQ,GAAG,CAAC;QAClB,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,OAAO,CAAC,WAAW,GAAG,CAAC;YACvB,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC;gBACjB,CAAC,CAAC,OAAO;gBACT,CAAC,CAAC,MAAM,CAAC;IAEjB,OAAO;QACL,QAAQ,EAAE,OAAO,EAAE,QAAQ,IAAI,EAAE;QACjC,OAAO;QACP,OAAO;QACP,aAAa;KACd,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,MAAiB,EAAE,SAAkB;IAC5D,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;QACrC,OAAO,qBAAqB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Schema Change Classifiers
|
|
3
|
+
*
|
|
4
|
+
* Classifies raw structural changes into severity levels for semantic versioning.
|
|
5
|
+
* Follows API compatibility principles where breaking changes require major bumps,
|
|
6
|
+
* additive changes require minor bumps, and metadata changes are patches.
|
|
7
|
+
*/
|
|
8
|
+
import type { RawChange, ChangeType, ChangeSeverity } from '@contractual/types';
|
|
9
|
+
/**
|
|
10
|
+
* Export classification sets for external analysis
|
|
11
|
+
*/
|
|
12
|
+
export declare const CLASSIFICATION_SETS: {
|
|
13
|
+
readonly breaking: ReadonlySet<ChangeType>;
|
|
14
|
+
readonly nonBreaking: ReadonlySet<ChangeType>;
|
|
15
|
+
readonly patch: ReadonlySet<ChangeType>;
|
|
16
|
+
readonly unknown: ReadonlySet<ChangeType>;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Classify a raw change into a severity level
|
|
20
|
+
*
|
|
21
|
+
* Uses the Strands API classification rules where:
|
|
22
|
+
* - Breaking changes require major version bump
|
|
23
|
+
* - Non-breaking changes require minor version bump
|
|
24
|
+
* - Patch changes are metadata/annotation only
|
|
25
|
+
* - Unknown changes require manual review
|
|
26
|
+
*
|
|
27
|
+
* @param change - The raw change to classify
|
|
28
|
+
* @returns The severity classification
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* const change: RawChange = {
|
|
33
|
+
* path: '/properties/name',
|
|
34
|
+
* type: 'property-removed',
|
|
35
|
+
* oldValue: { type: 'string' },
|
|
36
|
+
* };
|
|
37
|
+
* const severity = classify(change);
|
|
38
|
+
* // severity === 'breaking'
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function classify(change: RawChange): ChangeSeverity;
|
|
42
|
+
/**
|
|
43
|
+
* Classify a property-added change with schema context
|
|
44
|
+
*
|
|
45
|
+
* Property additions are breaking if the property is required,
|
|
46
|
+
* otherwise they are non-breaking (additive).
|
|
47
|
+
*
|
|
48
|
+
* @param change - The property-added change
|
|
49
|
+
* @param newSchema - The new schema for context (to check required array)
|
|
50
|
+
* @returns The severity classification
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* const change: RawChange = {
|
|
55
|
+
* path: '/properties/email',
|
|
56
|
+
* type: 'property-added',
|
|
57
|
+
* newValue: { type: 'string', format: 'email' },
|
|
58
|
+
* };
|
|
59
|
+
*
|
|
60
|
+
* const schema = {
|
|
61
|
+
* type: 'object',
|
|
62
|
+
* properties: { email: { type: 'string', format: 'email' } },
|
|
63
|
+
* required: ['email'], // email is required!
|
|
64
|
+
* };
|
|
65
|
+
*
|
|
66
|
+
* const severity = classifyPropertyAdded(change, schema);
|
|
67
|
+
* // severity === 'breaking' (because email is in required[])
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare function classifyPropertyAdded(change: RawChange, newSchema: unknown): ChangeSeverity;
|
|
71
|
+
/**
|
|
72
|
+
* Batch classify multiple changes
|
|
73
|
+
*
|
|
74
|
+
* @param changes - Array of raw changes
|
|
75
|
+
* @param newSchema - Optional schema for context-aware classification
|
|
76
|
+
* @returns Map of change to severity
|
|
77
|
+
*/
|
|
78
|
+
export declare function classifyAll(changes: readonly RawChange[], newSchema?: unknown): Map<RawChange, ChangeSeverity>;
|
|
79
|
+
/**
|
|
80
|
+
* Get a human-readable message for a classified change
|
|
81
|
+
*
|
|
82
|
+
* @param change - The raw change
|
|
83
|
+
* @param severity - The classified severity
|
|
84
|
+
* @returns Human-readable description
|
|
85
|
+
*/
|
|
86
|
+
export declare function getChangeMessage(change: RawChange, severity: ChangeSeverity): string;
|
|
87
|
+
//# sourceMappingURL=classifiers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classifiers.d.ts","sourceRoot":"","sources":["../src/classifiers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AA+IhF;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;CAKtB,CAAC;AAEX;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,cAAc,CAsB1D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,GAAG,cAAc,CA6B3F;AAgGD;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,SAAS,SAAS,EAAE,EAC7B,SAAS,CAAC,EAAE,OAAO,GAClB,GAAG,CAAC,SAAS,EAAE,cAAc,CAAC,CAYhC;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,GAAG,MAAM,CAapF"}
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Schema Change Classifiers
|
|
3
|
+
*
|
|
4
|
+
* Classifies raw structural changes into severity levels for semantic versioning.
|
|
5
|
+
* Follows API compatibility principles where breaking changes require major bumps,
|
|
6
|
+
* additive changes require minor bumps, and metadata changes are patches.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Change types that are always breaking (require major version bump)
|
|
10
|
+
*
|
|
11
|
+
* These changes can break existing consumers:
|
|
12
|
+
* - Removing properties removes data they may depend on
|
|
13
|
+
* - Adding required fields forces consumers to provide new data
|
|
14
|
+
* - Type changes can break parsing/validation
|
|
15
|
+
* - Enum removals can invalidate existing data
|
|
16
|
+
* - Tightened constraints can reject previously valid data
|
|
17
|
+
* - Composition option additions can change validation semantics
|
|
18
|
+
*
|
|
19
|
+
* Aligned with Strands API classification rules.
|
|
20
|
+
*/
|
|
21
|
+
const BREAKING_CHANGES = new Set([
|
|
22
|
+
'property-removed',
|
|
23
|
+
'required-added',
|
|
24
|
+
'type-changed',
|
|
25
|
+
'type-narrowed',
|
|
26
|
+
'enum-value-removed',
|
|
27
|
+
'enum-added',
|
|
28
|
+
'constraint-tightened',
|
|
29
|
+
'additional-properties-denied',
|
|
30
|
+
'items-changed',
|
|
31
|
+
'min-items-increased',
|
|
32
|
+
'max-items-decreased',
|
|
33
|
+
'ref-target-changed',
|
|
34
|
+
'dependent-required-added',
|
|
35
|
+
// Composition breaking changes (per Strands API)
|
|
36
|
+
'anyof-option-added',
|
|
37
|
+
'oneof-option-added',
|
|
38
|
+
'allof-member-added',
|
|
39
|
+
'not-schema-changed',
|
|
40
|
+
// OpenAPI structural breaking changes
|
|
41
|
+
'path-removed',
|
|
42
|
+
'operation-removed',
|
|
43
|
+
'parameter-added',
|
|
44
|
+
'parameter-removed',
|
|
45
|
+
'parameter-required-changed',
|
|
46
|
+
'request-body-added',
|
|
47
|
+
'response-removed',
|
|
48
|
+
'security-changed',
|
|
49
|
+
]);
|
|
50
|
+
/**
|
|
51
|
+
* Change types that are non-breaking (require minor version bump)
|
|
52
|
+
*
|
|
53
|
+
* These changes are backward compatible additions/relaxations:
|
|
54
|
+
* - Adding optional properties extends the schema without breaking
|
|
55
|
+
* - Removing required constraints makes the schema more permissive
|
|
56
|
+
* - Type widening accepts more values
|
|
57
|
+
* - Loosened constraints accept more values
|
|
58
|
+
* - Composition option removals make schema less restrictive
|
|
59
|
+
*
|
|
60
|
+
* Aligned with Strands API classification rules.
|
|
61
|
+
*/
|
|
62
|
+
const NON_BREAKING_CHANGES = new Set([
|
|
63
|
+
'property-added',
|
|
64
|
+
'required-removed',
|
|
65
|
+
'type-widened',
|
|
66
|
+
'enum-value-added',
|
|
67
|
+
'enum-removed',
|
|
68
|
+
'constraint-loosened',
|
|
69
|
+
'additional-properties-allowed',
|
|
70
|
+
'additional-properties-changed',
|
|
71
|
+
'dependent-required-removed',
|
|
72
|
+
// Composition non-breaking changes (per Strands API)
|
|
73
|
+
'anyof-option-removed',
|
|
74
|
+
'oneof-option-removed',
|
|
75
|
+
'allof-member-removed',
|
|
76
|
+
// OpenAPI structural non-breaking changes
|
|
77
|
+
'path-added',
|
|
78
|
+
'operation-added',
|
|
79
|
+
'request-body-removed',
|
|
80
|
+
'response-added',
|
|
81
|
+
'server-changed',
|
|
82
|
+
]);
|
|
83
|
+
/**
|
|
84
|
+
* Change types that are patches (documentation/metadata only)
|
|
85
|
+
*
|
|
86
|
+
* These changes don't affect validation behavior:
|
|
87
|
+
* - Description changes are documentation only
|
|
88
|
+
* - Title changes are display metadata
|
|
89
|
+
* - Default/example changes don't affect validation
|
|
90
|
+
* - Format is an annotation (per Strands API) - doesn't affect validation
|
|
91
|
+
* - Annotation keywords (deprecated, readOnly, writeOnly)
|
|
92
|
+
* - Content keywords (contentEncoding, contentMediaType, contentSchema)
|
|
93
|
+
*
|
|
94
|
+
* Aligned with Strands API classification rules.
|
|
95
|
+
*/
|
|
96
|
+
const PATCH_CHANGES = new Set([
|
|
97
|
+
// Metadata changes
|
|
98
|
+
'description-changed',
|
|
99
|
+
'title-changed',
|
|
100
|
+
'default-changed',
|
|
101
|
+
'examples-changed',
|
|
102
|
+
// Format is annotation (patch per Strands API)
|
|
103
|
+
'format-added',
|
|
104
|
+
'format-removed',
|
|
105
|
+
'format-changed',
|
|
106
|
+
// Annotation keywords (Draft 2019-09+)
|
|
107
|
+
'deprecated-changed',
|
|
108
|
+
'read-only-changed',
|
|
109
|
+
'write-only-changed',
|
|
110
|
+
// Content keywords
|
|
111
|
+
'content-encoding-changed',
|
|
112
|
+
'content-media-type-changed',
|
|
113
|
+
'content-schema-changed',
|
|
114
|
+
]);
|
|
115
|
+
/**
|
|
116
|
+
* Change types that require manual review
|
|
117
|
+
*
|
|
118
|
+
* These changes are too complex to classify automatically:
|
|
119
|
+
* - Generic composition changes require semantic analysis
|
|
120
|
+
* - Complex keywords (propertyNames, dependentSchemas, unevaluated*)
|
|
121
|
+
* - Conditional schema changes (if/then/else)
|
|
122
|
+
* - Unknown changes need human evaluation
|
|
123
|
+
*
|
|
124
|
+
* Aligned with Strands API classification rules.
|
|
125
|
+
*/
|
|
126
|
+
const UNKNOWN_CHANGES = new Set([
|
|
127
|
+
// Complex object keywords
|
|
128
|
+
'property-names-changed',
|
|
129
|
+
'dependent-schemas-changed',
|
|
130
|
+
'unevaluated-properties-changed',
|
|
131
|
+
// Complex array keywords
|
|
132
|
+
'unevaluated-items-changed',
|
|
133
|
+
'min-contains-changed',
|
|
134
|
+
'max-contains-changed',
|
|
135
|
+
// Conditional schema
|
|
136
|
+
'if-then-else-changed',
|
|
137
|
+
// Legacy/generic composition
|
|
138
|
+
'composition-changed',
|
|
139
|
+
// OpenAPI context-dependent (schema-level changes handled by walker)
|
|
140
|
+
'parameter-schema-changed',
|
|
141
|
+
'response-schema-changed',
|
|
142
|
+
// Catch-all
|
|
143
|
+
'unknown-change',
|
|
144
|
+
]);
|
|
145
|
+
/**
|
|
146
|
+
* Export classification sets for external analysis
|
|
147
|
+
*/
|
|
148
|
+
export const CLASSIFICATION_SETS = {
|
|
149
|
+
breaking: BREAKING_CHANGES,
|
|
150
|
+
nonBreaking: NON_BREAKING_CHANGES,
|
|
151
|
+
patch: PATCH_CHANGES,
|
|
152
|
+
unknown: UNKNOWN_CHANGES,
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* Classify a raw change into a severity level
|
|
156
|
+
*
|
|
157
|
+
* Uses the Strands API classification rules where:
|
|
158
|
+
* - Breaking changes require major version bump
|
|
159
|
+
* - Non-breaking changes require minor version bump
|
|
160
|
+
* - Patch changes are metadata/annotation only
|
|
161
|
+
* - Unknown changes require manual review
|
|
162
|
+
*
|
|
163
|
+
* @param change - The raw change to classify
|
|
164
|
+
* @returns The severity classification
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```typescript
|
|
168
|
+
* const change: RawChange = {
|
|
169
|
+
* path: '/properties/name',
|
|
170
|
+
* type: 'property-removed',
|
|
171
|
+
* oldValue: { type: 'string' },
|
|
172
|
+
* };
|
|
173
|
+
* const severity = classify(change);
|
|
174
|
+
* // severity === 'breaking'
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
export function classify(change) {
|
|
178
|
+
const { type } = change;
|
|
179
|
+
// Check each category in order of specificity
|
|
180
|
+
if (BREAKING_CHANGES.has(type)) {
|
|
181
|
+
return 'breaking';
|
|
182
|
+
}
|
|
183
|
+
if (NON_BREAKING_CHANGES.has(type)) {
|
|
184
|
+
return 'non-breaking';
|
|
185
|
+
}
|
|
186
|
+
if (PATCH_CHANGES.has(type)) {
|
|
187
|
+
return 'patch';
|
|
188
|
+
}
|
|
189
|
+
if (UNKNOWN_CHANGES.has(type)) {
|
|
190
|
+
return 'unknown';
|
|
191
|
+
}
|
|
192
|
+
// Defensive: any unhandled type is unknown
|
|
193
|
+
return 'unknown';
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Classify a property-added change with schema context
|
|
197
|
+
*
|
|
198
|
+
* Property additions are breaking if the property is required,
|
|
199
|
+
* otherwise they are non-breaking (additive).
|
|
200
|
+
*
|
|
201
|
+
* @param change - The property-added change
|
|
202
|
+
* @param newSchema - The new schema for context (to check required array)
|
|
203
|
+
* @returns The severity classification
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```typescript
|
|
207
|
+
* const change: RawChange = {
|
|
208
|
+
* path: '/properties/email',
|
|
209
|
+
* type: 'property-added',
|
|
210
|
+
* newValue: { type: 'string', format: 'email' },
|
|
211
|
+
* };
|
|
212
|
+
*
|
|
213
|
+
* const schema = {
|
|
214
|
+
* type: 'object',
|
|
215
|
+
* properties: { email: { type: 'string', format: 'email' } },
|
|
216
|
+
* required: ['email'], // email is required!
|
|
217
|
+
* };
|
|
218
|
+
*
|
|
219
|
+
* const severity = classifyPropertyAdded(change, schema);
|
|
220
|
+
* // severity === 'breaking' (because email is in required[])
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
export function classifyPropertyAdded(change, newSchema) {
|
|
224
|
+
// Validate change type
|
|
225
|
+
if (change.type !== 'property-added') {
|
|
226
|
+
return classify(change);
|
|
227
|
+
}
|
|
228
|
+
// Extract property name from path
|
|
229
|
+
const propertyName = extractPropertyName(change.path);
|
|
230
|
+
if (!propertyName) {
|
|
231
|
+
// Cannot determine property name, fall back to non-breaking
|
|
232
|
+
return 'non-breaking';
|
|
233
|
+
}
|
|
234
|
+
// Find the parent schema containing this property
|
|
235
|
+
const parentSchema = findParentSchema(change.path, newSchema);
|
|
236
|
+
if (!parentSchema) {
|
|
237
|
+
// Cannot find parent schema, fall back to non-breaking
|
|
238
|
+
return 'non-breaking';
|
|
239
|
+
}
|
|
240
|
+
// Check if property is in the required array
|
|
241
|
+
const required = getRequiredArray(parentSchema);
|
|
242
|
+
if (required.includes(propertyName)) {
|
|
243
|
+
// Adding a required property is breaking
|
|
244
|
+
return 'breaking';
|
|
245
|
+
}
|
|
246
|
+
// Adding an optional property is non-breaking
|
|
247
|
+
return 'non-breaking';
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Extract the property name from a JSON Pointer path
|
|
251
|
+
*
|
|
252
|
+
* @param path - JSON Pointer path (e.g., '/properties/name' or '/properties/user/properties/email')
|
|
253
|
+
* @returns The property name or null if not found
|
|
254
|
+
*/
|
|
255
|
+
function extractPropertyName(path) {
|
|
256
|
+
// Match the last /properties/NAME segment
|
|
257
|
+
const match = path.match(/\/properties\/([^/]+)$/);
|
|
258
|
+
if (match?.[1] !== undefined) {
|
|
259
|
+
return decodeJsonPointerSegment(match[1]);
|
|
260
|
+
}
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Decode a JSON Pointer segment (handles ~0 and ~1 escapes)
|
|
265
|
+
*
|
|
266
|
+
* @param segment - The encoded segment
|
|
267
|
+
* @returns The decoded segment
|
|
268
|
+
*/
|
|
269
|
+
function decodeJsonPointerSegment(segment) {
|
|
270
|
+
return segment.replace(/~1/g, '/').replace(/~0/g, '~');
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Find the parent schema containing a property
|
|
274
|
+
*
|
|
275
|
+
* @param path - JSON Pointer path to the property
|
|
276
|
+
* @param schema - The root schema
|
|
277
|
+
* @returns The parent schema or null if not found
|
|
278
|
+
*/
|
|
279
|
+
function findParentSchema(path, schema) {
|
|
280
|
+
if (!isObject(schema)) {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
// Remove the last segment to get parent path
|
|
284
|
+
// e.g., '/properties/name' -> '' (root)
|
|
285
|
+
// e.g., '/properties/user/properties/email' -> '/properties/user'
|
|
286
|
+
const segments = path.split('/').filter(Boolean);
|
|
287
|
+
// We need to navigate to the schema containing /properties/NAME
|
|
288
|
+
// So we remove 'properties' and 'NAME' from the end
|
|
289
|
+
if (segments.length < 2) {
|
|
290
|
+
// Path is too short, parent is root
|
|
291
|
+
return schema;
|
|
292
|
+
}
|
|
293
|
+
// Remove 'NAME' and 'properties' from the end
|
|
294
|
+
const parentSegments = segments.slice(0, -2);
|
|
295
|
+
// Navigate to parent
|
|
296
|
+
let current = schema;
|
|
297
|
+
for (const segment of parentSegments) {
|
|
298
|
+
if (!isObject(current)) {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
const decoded = decodeJsonPointerSegment(segment);
|
|
302
|
+
current = current[decoded];
|
|
303
|
+
}
|
|
304
|
+
return current;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Get the required array from a schema object
|
|
308
|
+
*
|
|
309
|
+
* @param schema - The schema object
|
|
310
|
+
* @returns Array of required property names
|
|
311
|
+
*/
|
|
312
|
+
function getRequiredArray(schema) {
|
|
313
|
+
if (!isObject(schema)) {
|
|
314
|
+
return [];
|
|
315
|
+
}
|
|
316
|
+
const obj = schema;
|
|
317
|
+
const required = obj['required'];
|
|
318
|
+
if (!Array.isArray(required)) {
|
|
319
|
+
return [];
|
|
320
|
+
}
|
|
321
|
+
return required.filter((item) => typeof item === 'string');
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Type guard for objects
|
|
325
|
+
*/
|
|
326
|
+
function isObject(value) {
|
|
327
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Batch classify multiple changes
|
|
331
|
+
*
|
|
332
|
+
* @param changes - Array of raw changes
|
|
333
|
+
* @param newSchema - Optional schema for context-aware classification
|
|
334
|
+
* @returns Map of change to severity
|
|
335
|
+
*/
|
|
336
|
+
export function classifyAll(changes, newSchema) {
|
|
337
|
+
const results = new Map();
|
|
338
|
+
for (const change of changes) {
|
|
339
|
+
if (change.type === 'property-added' && newSchema !== undefined) {
|
|
340
|
+
results.set(change, classifyPropertyAdded(change, newSchema));
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
results.set(change, classify(change));
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return results;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Get a human-readable message for a classified change
|
|
350
|
+
*
|
|
351
|
+
* @param change - The raw change
|
|
352
|
+
* @param severity - The classified severity
|
|
353
|
+
* @returns Human-readable description
|
|
354
|
+
*/
|
|
355
|
+
export function getChangeMessage(change, severity) {
|
|
356
|
+
const severityLabel = severity === 'breaking'
|
|
357
|
+
? 'BREAKING'
|
|
358
|
+
: severity === 'non-breaking'
|
|
359
|
+
? 'Non-breaking'
|
|
360
|
+
: severity === 'patch'
|
|
361
|
+
? 'Patch'
|
|
362
|
+
: 'Unknown';
|
|
363
|
+
const typeLabel = formatChangeType(change.type);
|
|
364
|
+
return `[${severityLabel}] ${typeLabel} at ${change.path}`;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Format a change type into a human-readable label
|
|
368
|
+
*/
|
|
369
|
+
function formatChangeType(type) {
|
|
370
|
+
return type
|
|
371
|
+
.split('-')
|
|
372
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
373
|
+
.join(' ');
|
|
374
|
+
}
|
|
375
|
+
//# sourceMappingURL=classifiers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classifiers.js","sourceRoot":"","sources":["../src/classifiers.ts"],"names":[],"mappings":"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"}
|
package/dist/format.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Human-readable message formatting for raw changes
|
|
3
|
+
*/
|
|
4
|
+
import type { RawChange } from '@contractual/types';
|
|
5
|
+
/**
|
|
6
|
+
* Format a human-readable message for a change
|
|
7
|
+
*
|
|
8
|
+
* @param change - The raw change to format
|
|
9
|
+
* @returns Human-readable message describing the change
|
|
10
|
+
*/
|
|
11
|
+
export declare function formatChangeMessage(change: RawChange): string;
|
|
12
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CA4F7D"}
|