@unispechq/unispec-core 0.2.13 → 0.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 +85 -160
- package/dist/cache/cache-factory.d.ts +31 -0
- package/dist/cache/cache-factory.js +65 -0
- package/dist/cache/cache-manager.d.ts +62 -0
- package/dist/cache/cache-manager.js +122 -0
- package/dist/cache/constants.d.ts +21 -0
- package/dist/cache/constants.js +22 -0
- package/dist/cache/hash-utils.d.ts +21 -0
- package/dist/cache/hash-utils.js +35 -0
- package/dist/cache/hashing.d.ts +19 -0
- package/dist/cache/hashing.js +197 -0
- package/dist/cache/index.d.ts +6 -0
- package/dist/cache/index.js +10 -0
- package/dist/cache/lru-cache.d.ts +56 -0
- package/dist/cache/lru-cache.js +161 -0
- package/dist/cache/types.d.ts +24 -0
- package/dist/cache/types.js +4 -0
- package/dist/cjs/cache/cache-factory.js +72 -0
- package/dist/cjs/cache/cache-manager.js +126 -0
- package/dist/cjs/cache/constants.js +25 -0
- package/dist/cjs/cache/hash-utils.js +41 -0
- package/dist/cjs/cache/hashing.js +236 -0
- package/dist/cjs/cache/index.js +26 -0
- package/dist/cjs/cache/lru-cache.js +165 -0
- package/dist/cjs/cache/types.js +5 -0
- package/dist/cjs/diff/annotators.js +132 -0
- package/dist/cjs/diff/change-reports.js +369 -0
- package/dist/cjs/diff/core.js +158 -0
- package/dist/cjs/diff/enhanced-diff.js +79 -0
- package/dist/cjs/diff/impact-strategies-refactored.js +230 -0
- package/dist/cjs/diff/impact-strategies.js +219 -0
- package/dist/cjs/diff/index.js +25 -247
- package/dist/cjs/diff/metrics-calculator.js +69 -0
- package/dist/cjs/diff/risk-calculator.js +58 -0
- package/dist/cjs/diff/suggestion-generator.js +78 -0
- package/dist/cjs/diff/types.js +11 -0
- package/dist/cjs/errors/base-error.js +33 -0
- package/dist/cjs/errors/config-error.js +11 -0
- package/dist/cjs/errors/error-factory.js +48 -0
- package/dist/cjs/errors/index.js +19 -0
- package/dist/cjs/errors/loader-error.js +11 -0
- package/dist/cjs/errors/reference-error.js +11 -0
- package/dist/cjs/errors/schema-error.js +11 -0
- package/dist/cjs/errors/security-error.js +11 -0
- package/dist/cjs/errors/semantic-error.js +11 -0
- package/dist/cjs/generated-schemas.js +2100 -0
- package/dist/cjs/index.js +41 -5
- package/dist/cjs/loader/index.js +11 -75
- package/dist/cjs/loader/security-validator.js +53 -0
- package/dist/cjs/loader/types.js +11 -0
- package/dist/cjs/loader/unispec-loader.js +84 -0
- package/dist/cjs/loader/yaml-loader.js +76 -0
- package/dist/cjs/normalizer/core.js +32 -0
- package/dist/cjs/normalizer/graphql-normalizer.js +67 -0
- package/dist/cjs/normalizer/index.js +5 -119
- package/dist/cjs/normalizer/rest-normalizer.js +51 -0
- package/dist/cjs/normalizer/types.js +2 -0
- package/dist/cjs/normalizer/utils.js +33 -0
- package/dist/cjs/normalizer/websocket-normalizer.js +81 -0
- package/dist/cjs/optimizer/core.js +115 -0
- package/dist/cjs/optimizer/index.js +17 -0
- package/dist/cjs/optimizer/optimization-functions.js +185 -0
- package/dist/cjs/optimizer/types.js +2 -0
- package/dist/cjs/optimizer/utils.js +32 -0
- package/dist/cjs/schemas/dedupe.js +100 -0
- package/dist/cjs/schemas/index.js +12 -132
- package/dist/cjs/schemas/resolver.js +41 -0
- package/dist/cjs/schemas/utils.js +53 -0
- package/dist/cjs/types/index.js +0 -1
- package/dist/cjs/validator/ajv-validator.js +82 -0
- package/dist/cjs/validator/config-validator-main.js +34 -0
- package/dist/cjs/validator/config-validator.js +17 -0
- package/dist/cjs/validator/index.js +21 -108
- package/dist/cjs/validator/object-traversal.js +112 -0
- package/dist/cjs/validator/reference-validator.js +233 -0
- package/dist/cjs/validator/schema-references.js +116 -0
- package/dist/cjs/validator/semantic-validator.js +328 -0
- package/dist/cjs/validator/tests-validator.js +16 -0
- package/dist/cjs/validator/types.js +2 -0
- package/dist/cjs/validator/unispec-validator.js +84 -0
- package/dist/cjs/validator/validator-factory.js +77 -0
- package/dist/cjs/versions.js +147 -0
- package/dist/diff/annotators.d.ts +4 -0
- package/dist/diff/annotators.js +127 -0
- package/dist/diff/change-reports.d.ts +37 -0
- package/dist/diff/change-reports.js +366 -0
- package/dist/diff/core.d.ts +26 -0
- package/dist/diff/core.js +155 -0
- package/dist/diff/enhanced-diff.d.ts +51 -0
- package/dist/diff/enhanced-diff.js +76 -0
- package/dist/diff/impact-strategies-refactored.d.ts +69 -0
- package/dist/diff/impact-strategies-refactored.js +223 -0
- package/dist/diff/impact-strategies.d.ts +41 -0
- package/dist/diff/impact-strategies.js +212 -0
- package/dist/diff/index.d.ts +8 -34
- package/dist/diff/index.js +11 -246
- package/dist/diff/metrics-calculator.d.ts +23 -0
- package/dist/diff/metrics-calculator.js +65 -0
- package/dist/diff/risk-calculator.d.ts +23 -0
- package/dist/diff/risk-calculator.js +55 -0
- package/dist/diff/suggestion-generator.d.ts +18 -0
- package/dist/diff/suggestion-generator.js +74 -0
- package/dist/diff/types.d.ts +24 -0
- package/dist/diff/types.js +8 -0
- package/dist/errors/base-error.d.ts +20 -0
- package/dist/errors/base-error.js +29 -0
- package/dist/errors/config-error.d.ts +4 -0
- package/dist/errors/config-error.js +7 -0
- package/dist/errors/error-factory.d.ts +22 -0
- package/dist/errors/error-factory.js +45 -0
- package/dist/errors/index.d.ts +8 -0
- package/dist/errors/index.js +8 -0
- package/dist/errors/loader-error.d.ts +4 -0
- package/dist/errors/loader-error.js +7 -0
- package/dist/errors/reference-error.d.ts +4 -0
- package/dist/errors/reference-error.js +7 -0
- package/dist/errors/schema-error.d.ts +4 -0
- package/dist/errors/schema-error.js +7 -0
- package/dist/errors/security-error.d.ts +4 -0
- package/dist/errors/security-error.js +7 -0
- package/dist/errors/semantic-error.d.ts +4 -0
- package/dist/errors/semantic-error.js +7 -0
- package/dist/generated-schemas.d.ts +2073 -0
- package/dist/generated-schemas.js +2097 -0
- package/dist/index.cjs +41 -5
- package/dist/index.d.ts +11 -5
- package/dist/index.js +41 -5
- package/dist/loader/index.d.ts +5 -12
- package/dist/loader/index.js +5 -41
- package/dist/loader/security-validator.d.ts +5 -0
- package/dist/loader/security-validator.js +50 -0
- package/dist/loader/types.d.ts +30 -0
- package/dist/loader/types.js +8 -0
- package/dist/loader/unispec-loader.d.ts +10 -0
- package/dist/loader/unispec-loader.js +81 -0
- package/dist/loader/yaml-loader.d.ts +10 -0
- package/dist/loader/yaml-loader.js +39 -0
- package/dist/normalizer/core.d.ts +24 -0
- package/dist/normalizer/core.js +29 -0
- package/dist/normalizer/graphql-normalizer.d.ts +8 -0
- package/dist/normalizer/graphql-normalizer.js +64 -0
- package/dist/normalizer/index.d.ts +2 -25
- package/dist/normalizer/index.js +3 -118
- package/dist/normalizer/rest-normalizer.d.ts +8 -0
- package/dist/normalizer/rest-normalizer.js +48 -0
- package/dist/normalizer/types.d.ts +7 -0
- package/dist/normalizer/types.js +1 -0
- package/dist/normalizer/utils.d.ts +14 -0
- package/dist/normalizer/utils.js +29 -0
- package/dist/normalizer/websocket-normalizer.d.ts +8 -0
- package/dist/normalizer/websocket-normalizer.js +78 -0
- package/dist/optimizer/core.d.ts +17 -0
- package/dist/optimizer/core.js +111 -0
- package/dist/optimizer/index.d.ts +4 -0
- package/dist/optimizer/index.js +7 -0
- package/dist/optimizer/optimization-functions.d.ts +32 -0
- package/dist/optimizer/optimization-functions.js +179 -0
- package/dist/optimizer/types.d.ts +28 -0
- package/dist/optimizer/types.js +1 -0
- package/dist/optimizer/utils.d.ts +7 -0
- package/dist/optimizer/utils.js +29 -0
- package/dist/schemas/dedupe.d.ts +9 -0
- package/dist/schemas/dedupe.js +97 -0
- package/dist/schemas/index.d.ts +3 -4
- package/dist/schemas/index.js +6 -129
- package/dist/schemas/resolver.d.ts +19 -0
- package/dist/schemas/resolver.js +37 -0
- package/dist/schemas/utils.d.ts +20 -0
- package/dist/schemas/utils.js +49 -0
- package/dist/types/index.d.ts +279 -41
- package/dist/types/index.js +0 -1
- package/dist/validator/ajv-validator.d.ts +15 -0
- package/dist/validator/ajv-validator.js +75 -0
- package/dist/validator/config-validator-main.d.ts +10 -0
- package/dist/validator/config-validator-main.js +31 -0
- package/dist/validator/config-validator.d.ts +5 -0
- package/dist/validator/config-validator.js +14 -0
- package/dist/validator/index.d.ts +10 -23
- package/dist/validator/index.js +11 -103
- package/dist/validator/object-traversal.d.ts +52 -0
- package/dist/validator/object-traversal.js +104 -0
- package/dist/validator/reference-validator.d.ts +31 -0
- package/dist/validator/reference-validator.js +230 -0
- package/dist/validator/schema-references.d.ts +23 -0
- package/dist/validator/schema-references.js +111 -0
- package/dist/validator/semantic-validator.d.ts +26 -0
- package/dist/validator/semantic-validator.js +325 -0
- package/dist/validator/tests-validator.d.ts +9 -0
- package/dist/validator/tests-validator.js +13 -0
- package/dist/validator/types.d.ts +29 -0
- package/dist/validator/types.js +1 -0
- package/dist/validator/unispec-validator.d.ts +15 -0
- package/dist/validator/unispec-validator.js +81 -0
- package/dist/validator/validator-factory.d.ts +10 -0
- package/dist/validator/validator-factory.js +73 -0
- package/dist/versions.d.ts +10 -0
- package/dist/versions.js +143 -0
- package/package.json +11 -9
- package/dist/cjs/converters/index.js +0 -204
- package/dist/cjs/validator/generated-schemas.js +0 -827
- package/dist/converters/index.d.ts +0 -14
- package/dist/converters/index.js +0 -199
- package/dist/validator/generated-schemas.d.ts +0 -842
- package/dist/validator/generated-schemas.js +0 -824
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateUniSpec = validateUniSpec;
|
|
4
|
+
const errors_1 = require("../errors/index.js");
|
|
5
|
+
const ajv_validator_1 = require("./ajv-validator.js");
|
|
6
|
+
const reference_validator_1 = require("./reference-validator.js");
|
|
7
|
+
const semantic_validator_1 = require("./semantic-validator.js");
|
|
8
|
+
const validator_factory_1 = require("./validator-factory.js");
|
|
9
|
+
/**
|
|
10
|
+
* Validate a UniSpec document with optional extended validation.
|
|
11
|
+
*
|
|
12
|
+
* This function performs:
|
|
13
|
+
* - JSON Schema validation (always)
|
|
14
|
+
* - Semantic validation (optional, when enableExtendedValidation is true)
|
|
15
|
+
* - Reference validation (optional, when enableExtendedValidation is true)
|
|
16
|
+
*
|
|
17
|
+
* @param doc - The UniSpec document to validate
|
|
18
|
+
* @param options - Validation options
|
|
19
|
+
* @returns Validation result with optional extended results
|
|
20
|
+
*/
|
|
21
|
+
async function validateUniSpec(doc, options = {}) {
|
|
22
|
+
// Always perform basic JSON Schema validation
|
|
23
|
+
const basicResult = await validateUniSpecBase(doc, options);
|
|
24
|
+
// If extended validation is disabled, return basic result
|
|
25
|
+
if (!options.enableExtendedValidation) {
|
|
26
|
+
return basicResult;
|
|
27
|
+
}
|
|
28
|
+
// Perform extended validation
|
|
29
|
+
const result = {
|
|
30
|
+
valid: basicResult.valid,
|
|
31
|
+
errors: [...basicResult.errors],
|
|
32
|
+
};
|
|
33
|
+
// Perform semantic validation
|
|
34
|
+
if (options.semanticValidation) {
|
|
35
|
+
const semanticResult = (0, semantic_validator_1.validateSemantic)(doc, options.semanticValidation);
|
|
36
|
+
result.semantic = semanticResult;
|
|
37
|
+
if (!semanticResult.valid) {
|
|
38
|
+
result.valid = false;
|
|
39
|
+
result.errors.push(...semanticResult.errors);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Perform reference validation
|
|
43
|
+
if (options.referenceValidation) {
|
|
44
|
+
const referenceResult = (0, reference_validator_1.validateReferences)(doc, options.referenceValidation);
|
|
45
|
+
result.references = referenceResult;
|
|
46
|
+
if (!referenceResult.valid) {
|
|
47
|
+
result.valid = false;
|
|
48
|
+
result.errors.push(...referenceResult.errors);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Internal function for basic JSON Schema validation.
|
|
55
|
+
*/
|
|
56
|
+
async function validateUniSpecBase(doc, options = {}) {
|
|
57
|
+
try {
|
|
58
|
+
const { validateUniSpecFn } = await (0, ajv_validator_1.getValidator)(options);
|
|
59
|
+
// Ensure the document has required fields for validation
|
|
60
|
+
const docForValidation = {
|
|
61
|
+
unispecVersion: doc.unispecVersion || "1.0.0",
|
|
62
|
+
service: doc.service,
|
|
63
|
+
};
|
|
64
|
+
const valid = validateUniSpecFn(docForValidation);
|
|
65
|
+
const schemaErrors = (0, validator_factory_1.mapAjvErrors)(validateUniSpecFn.errors);
|
|
66
|
+
if (valid) {
|
|
67
|
+
return {
|
|
68
|
+
valid: true,
|
|
69
|
+
errors: [],
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
valid: false,
|
|
74
|
+
errors: schemaErrors,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
const validationError = errors_1.ErrorFactory.fromError(error, "validation_error");
|
|
79
|
+
return {
|
|
80
|
+
valid: false,
|
|
81
|
+
errors: [validationError.toJSON()],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createValidator = createValidator;
|
|
4
|
+
exports.mapAjvErrors = mapAjvErrors;
|
|
5
|
+
const errors_1 = require("../errors/index.js");
|
|
6
|
+
/**
|
|
7
|
+
* Generic validator factory to reduce code duplication.
|
|
8
|
+
*/
|
|
9
|
+
function createValidator(documentType, getValidatorFn, customValidation) {
|
|
10
|
+
return async function validate(doc, options = {}) {
|
|
11
|
+
try {
|
|
12
|
+
const validateFn = await getValidatorFn(options);
|
|
13
|
+
if (!validateFn) {
|
|
14
|
+
return {
|
|
15
|
+
valid: false,
|
|
16
|
+
errors: [
|
|
17
|
+
{
|
|
18
|
+
message: `${documentType} validation schema is not available. Provide appropriate schema in ValidateOptions.`,
|
|
19
|
+
path: "",
|
|
20
|
+
code: "schema_missing",
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const valid = validateFn(doc);
|
|
26
|
+
// Run custom validation if provided
|
|
27
|
+
const customErrors = customValidation ? customValidation(doc) : [];
|
|
28
|
+
const schemaErrors = valid ? [] : mapAjvErrors(validateFn.errors);
|
|
29
|
+
const allErrors = [...schemaErrors, ...customErrors];
|
|
30
|
+
if (valid && customErrors.length === 0) {
|
|
31
|
+
return {
|
|
32
|
+
valid: true,
|
|
33
|
+
errors: [],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
valid: false,
|
|
38
|
+
errors: allErrors,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
const validationError = errors_1.ErrorFactory.fromError(error, `${documentType}_validation_error`);
|
|
43
|
+
return {
|
|
44
|
+
valid: false,
|
|
45
|
+
errors: [validationError.toJSON()],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Map AJV errors to specific UniSpec validation errors.
|
|
52
|
+
*/
|
|
53
|
+
function mapAjvErrors(errors) {
|
|
54
|
+
if (!errors)
|
|
55
|
+
return [];
|
|
56
|
+
return errors.map((error) => {
|
|
57
|
+
const message = error.message || "UniSpec validation error";
|
|
58
|
+
const path = error.instancePath || error.schemaPath;
|
|
59
|
+
const _code = error.keyword;
|
|
60
|
+
// Create specific error types based on keyword
|
|
61
|
+
switch (error.keyword) {
|
|
62
|
+
case "required":
|
|
63
|
+
return errors_1.ErrorFactory.createSchemaError(`Missing required property: ${message}`, path, { keyword: error.keyword, params: error.params });
|
|
64
|
+
case "type":
|
|
65
|
+
return errors_1.ErrorFactory.createSchemaError(`Invalid type: ${message}`, path, { keyword: error.keyword, params: error.params });
|
|
66
|
+
case "format":
|
|
67
|
+
return errors_1.ErrorFactory.createSchemaError(`Invalid format: ${message}`, path, { keyword: error.keyword, params: error.params });
|
|
68
|
+
case "additionalProperties":
|
|
69
|
+
return errors_1.ErrorFactory.createSchemaError(`Additional property not allowed: ${message}`, path, { keyword: error.keyword, params: error.params });
|
|
70
|
+
default:
|
|
71
|
+
return errors_1.ErrorFactory.createSchemaError(message, path, {
|
|
72
|
+
keyword: error.keyword,
|
|
73
|
+
params: error.params,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getLatestUniSpecVersion = getLatestUniSpecVersion;
|
|
4
|
+
exports.clearVersionCache = clearVersionCache;
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const node_path_1 = require("node:path");
|
|
7
|
+
const node_url_1 = require("node:url");
|
|
8
|
+
let cachedUniSpecVersion = null;
|
|
9
|
+
let cachedSchemaPackagePath = null;
|
|
10
|
+
/**
|
|
11
|
+
* Validate package.json content to ensure it's the correct @unispechq/unispec-schema package
|
|
12
|
+
* @param content Package.json content as string
|
|
13
|
+
* @returns Package info object if valid, null otherwise
|
|
14
|
+
*/
|
|
15
|
+
function validatePackageJson(content) {
|
|
16
|
+
try {
|
|
17
|
+
const packageInfo = JSON.parse(content);
|
|
18
|
+
if (packageInfo.name === "@unispechq/unispec-schema" &&
|
|
19
|
+
packageInfo.version) {
|
|
20
|
+
return packageInfo;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Invalid JSON
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get current module directory (supports both ESM and CJS)
|
|
30
|
+
* @returns Current directory path
|
|
31
|
+
*/
|
|
32
|
+
function getCurrentDirectory() {
|
|
33
|
+
if (typeof __dirname !== "undefined") {
|
|
34
|
+
return __dirname;
|
|
35
|
+
}
|
|
36
|
+
// Try ESM import.meta.url
|
|
37
|
+
try {
|
|
38
|
+
if (typeof globalThis !== "undefined" &&
|
|
39
|
+
globalThis.import
|
|
40
|
+
?.meta?.url) {
|
|
41
|
+
return (0, node_path_1.dirname)((0, node_url_1.fileURLToPath)(globalThis
|
|
42
|
+
.import.meta.url));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// Fallback to current working directory
|
|
47
|
+
}
|
|
48
|
+
return process.cwd();
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Find the package.json path for @unispechq/unispec-schema
|
|
52
|
+
* Works in both ESM and CJS contexts with improved reliability
|
|
53
|
+
* @returns Path to package.json file
|
|
54
|
+
*/
|
|
55
|
+
function findSchemaPackagePath() {
|
|
56
|
+
// Return cached path if available
|
|
57
|
+
if (cachedSchemaPackagePath) {
|
|
58
|
+
return cachedSchemaPackagePath;
|
|
59
|
+
}
|
|
60
|
+
const currentDir = getCurrentDirectory();
|
|
61
|
+
// Define all possible paths to check
|
|
62
|
+
const candidatePaths = [
|
|
63
|
+
// Try direct package.json resolution first (most reliable for CJS)
|
|
64
|
+
() => {
|
|
65
|
+
if (typeof require !== "undefined") {
|
|
66
|
+
try {
|
|
67
|
+
return require.resolve("@unispechq/unispec-schema/package.json");
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
},
|
|
75
|
+
// Try require.resolve for main entry point
|
|
76
|
+
() => {
|
|
77
|
+
if (typeof require !== "undefined") {
|
|
78
|
+
try {
|
|
79
|
+
const packageMainPath = require.resolve("@unispechq/unispec-schema");
|
|
80
|
+
return (0, node_path_1.join)((0, node_path_1.dirname)(packageMainPath), "package.json");
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
},
|
|
88
|
+
// Fallback paths
|
|
89
|
+
() => (0, node_path_1.join)(process.cwd(), "node_modules", "@unispechq", "unispec-schema", "package.json"),
|
|
90
|
+
() => (0, node_path_1.join)(currentDir, "..", "node_modules", "@unispechq", "unispec-schema", "package.json"),
|
|
91
|
+
() => (0, node_path_1.join)(currentDir, "..", "..", "node_modules", "@unispechq", "unispec-schema", "package.json"),
|
|
92
|
+
() => (0, node_path_1.join)(currentDir, "..", "..", "..", "node_modules", "@unispechq", "unispec-schema", "package.json"),
|
|
93
|
+
];
|
|
94
|
+
// Try each candidate path
|
|
95
|
+
for (const getPath of candidatePaths) {
|
|
96
|
+
try {
|
|
97
|
+
const path = getPath();
|
|
98
|
+
if (!path)
|
|
99
|
+
continue;
|
|
100
|
+
const content = (0, node_fs_1.readFileSync)(path, "utf-8");
|
|
101
|
+
const packageInfo = validatePackageJson(content);
|
|
102
|
+
if (packageInfo) {
|
|
103
|
+
cachedSchemaPackagePath = path;
|
|
104
|
+
return path;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
// Continue to next path
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
throw new Error(`Could not find @unispechq/unispec-schema package.json. Searched in multiple node_modules locations.`);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Get the latest supported UniSpec version from @unispechq/unispec-schema package
|
|
115
|
+
* The version is derived from the package.json version (major.minor.0 format)
|
|
116
|
+
* @returns The latest UniSpec format version (SemVer)
|
|
117
|
+
*/
|
|
118
|
+
function getLatestUniSpecVersion() {
|
|
119
|
+
if (cachedUniSpecVersion) {
|
|
120
|
+
return cachedUniSpecVersion;
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
// Find and read package.json from @unispechq/unispec-schema
|
|
124
|
+
const schemaPackagePath = findSchemaPackagePath();
|
|
125
|
+
const packageJson = (0, node_fs_1.readFileSync)(schemaPackagePath, "utf-8");
|
|
126
|
+
const packageInfo = JSON.parse(packageJson);
|
|
127
|
+
// Extract version and convert to major.minor.0 format
|
|
128
|
+
const version = packageInfo.version;
|
|
129
|
+
const [major, minor] = version.split(".");
|
|
130
|
+
// Create UniSpec version in major.minor.0 format
|
|
131
|
+
const unispecVersion = `${major}.${minor}.0`;
|
|
132
|
+
cachedUniSpecVersion = unispecVersion;
|
|
133
|
+
return unispecVersion;
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
// Fallback to default version if package.json is not available
|
|
137
|
+
cachedUniSpecVersion = "1.0.0";
|
|
138
|
+
return cachedUniSpecVersion;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Clear the version cache (useful for testing or dynamic updates)
|
|
143
|
+
*/
|
|
144
|
+
function clearVersionCache() {
|
|
145
|
+
cachedUniSpecVersion = null;
|
|
146
|
+
cachedSchemaPackagePath = null;
|
|
147
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { UniSpecChange } from "./types.js";
|
|
2
|
+
export declare function annotateRestChange(change: UniSpecChange): UniSpecChange;
|
|
3
|
+
export declare function annotateWebSocketChange(change: UniSpecChange): UniSpecChange;
|
|
4
|
+
export declare function annotateGraphQLChange(change: UniSpecChange): UniSpecChange;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
export function annotateRestChange(change) {
|
|
2
|
+
if (!change.path.startsWith("/service/protocols/rest/routes/")) {
|
|
3
|
+
return change;
|
|
4
|
+
}
|
|
5
|
+
const segments = change.path.split("/").filter(Boolean);
|
|
6
|
+
// Expected shape: ["service", "protocols", "rest", "routes", routeName, ...]
|
|
7
|
+
if (segments[0] !== "service" ||
|
|
8
|
+
segments[1] !== "protocols" ||
|
|
9
|
+
segments[2] !== "rest" ||
|
|
10
|
+
segments[3] !== "routes") {
|
|
11
|
+
return change;
|
|
12
|
+
}
|
|
13
|
+
const routeName = segments[4];
|
|
14
|
+
if (typeof routeName === "undefined") {
|
|
15
|
+
return change;
|
|
16
|
+
}
|
|
17
|
+
const annotated = {
|
|
18
|
+
...change,
|
|
19
|
+
protocol: "rest",
|
|
20
|
+
};
|
|
21
|
+
if (change.description === "Item removed") {
|
|
22
|
+
annotated.kind = "rest.route.removed";
|
|
23
|
+
annotated.severity = "breaking";
|
|
24
|
+
}
|
|
25
|
+
else if (change.description === "Item added") {
|
|
26
|
+
annotated.kind = "rest.route.added";
|
|
27
|
+
annotated.severity = "non-breaking";
|
|
28
|
+
}
|
|
29
|
+
else if (change.path.includes("/required") &&
|
|
30
|
+
change.description === "Value changed") {
|
|
31
|
+
// Changing required field from false to true is breaking
|
|
32
|
+
annotated.kind = "rest.parameter.required_changed";
|
|
33
|
+
annotated.severity = "breaking";
|
|
34
|
+
}
|
|
35
|
+
return annotated;
|
|
36
|
+
}
|
|
37
|
+
export function annotateWebSocketChange(change) {
|
|
38
|
+
if (!change.path.startsWith("/service/protocols/websocket/channels/")) {
|
|
39
|
+
return change;
|
|
40
|
+
}
|
|
41
|
+
const segments = change.path.split("/").filter(Boolean);
|
|
42
|
+
// Expected base: ["service","protocols","websocket","channels", channelName, ...]
|
|
43
|
+
if (segments[0] !== "service" ||
|
|
44
|
+
segments[1] !== "protocols" ||
|
|
45
|
+
segments[2] !== "websocket" ||
|
|
46
|
+
segments[3] !== "channels") {
|
|
47
|
+
return change;
|
|
48
|
+
}
|
|
49
|
+
const channelName = segments[4];
|
|
50
|
+
const next = segments[5];
|
|
51
|
+
const annotated = {
|
|
52
|
+
...change,
|
|
53
|
+
protocol: "websocket",
|
|
54
|
+
};
|
|
55
|
+
if (typeof channelName === "undefined") {
|
|
56
|
+
return annotated;
|
|
57
|
+
}
|
|
58
|
+
// Channel-level changes: /service/protocols/websocket/channels/{channelName}
|
|
59
|
+
if (!next) {
|
|
60
|
+
if (change.description === "Item removed") {
|
|
61
|
+
annotated.kind = "websocket.channel.removed";
|
|
62
|
+
annotated.severity = "breaking";
|
|
63
|
+
}
|
|
64
|
+
else if (change.description === "Item added") {
|
|
65
|
+
annotated.kind = "websocket.channel.added";
|
|
66
|
+
annotated.severity = "non-breaking";
|
|
67
|
+
}
|
|
68
|
+
return annotated;
|
|
69
|
+
}
|
|
70
|
+
// Message-level changes: /service/protocols/websocket/channels/{channelName}/messages/{messageName}
|
|
71
|
+
if (next === "messages") {
|
|
72
|
+
const messageName = segments[6];
|
|
73
|
+
if (typeof messageName === "undefined") {
|
|
74
|
+
return annotated;
|
|
75
|
+
}
|
|
76
|
+
if (change.description === "Item removed") {
|
|
77
|
+
annotated.kind = "websocket.message.removed";
|
|
78
|
+
annotated.severity = "breaking";
|
|
79
|
+
}
|
|
80
|
+
else if (change.description === "Item added") {
|
|
81
|
+
annotated.kind = "websocket.message.added";
|
|
82
|
+
annotated.severity = "non-breaking";
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return annotated;
|
|
86
|
+
}
|
|
87
|
+
export function annotateGraphQLChange(change) {
|
|
88
|
+
if (!change.path.startsWith("/service/protocols/graphql/")) {
|
|
89
|
+
return change;
|
|
90
|
+
}
|
|
91
|
+
const segments = change.path.split("/").filter(Boolean);
|
|
92
|
+
// Expected: ["service","protocols","graphql", operationType, operationName, ...]
|
|
93
|
+
if (segments[0] !== "service" ||
|
|
94
|
+
segments[1] !== "protocols" ||
|
|
95
|
+
segments[2] !== "graphql") {
|
|
96
|
+
return change;
|
|
97
|
+
}
|
|
98
|
+
const operationType = segments[3];
|
|
99
|
+
const operationName = segments[4];
|
|
100
|
+
if (!operationType || typeof operationName === "undefined") {
|
|
101
|
+
return change;
|
|
102
|
+
}
|
|
103
|
+
if (operationType !== "queries" &&
|
|
104
|
+
operationType !== "mutations" &&
|
|
105
|
+
operationType !== "subscriptions") {
|
|
106
|
+
return change;
|
|
107
|
+
}
|
|
108
|
+
const annotated = {
|
|
109
|
+
...change,
|
|
110
|
+
protocol: "graphql",
|
|
111
|
+
};
|
|
112
|
+
if (change.description === "Item removed") {
|
|
113
|
+
annotated.kind = "graphql.operation.removed";
|
|
114
|
+
annotated.severity = "breaking";
|
|
115
|
+
}
|
|
116
|
+
else if (change.description === "Item added") {
|
|
117
|
+
annotated.kind = "graphql.operation.added";
|
|
118
|
+
annotated.severity = "non-breaking";
|
|
119
|
+
}
|
|
120
|
+
else if (change.path.includes("/returnType") &&
|
|
121
|
+
change.description === "Value changed") {
|
|
122
|
+
// Changing return type is breaking
|
|
123
|
+
annotated.kind = "graphql.operation.return_type_changed";
|
|
124
|
+
annotated.severity = "breaking";
|
|
125
|
+
}
|
|
126
|
+
return annotated;
|
|
127
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { EnhancedDiffResult, EnhancedUniSpecChange } from "./enhanced-diff.js";
|
|
2
|
+
export interface ReportOptions {
|
|
3
|
+
format: "markdown" | "html" | "json";
|
|
4
|
+
includeSuggestions?: boolean;
|
|
5
|
+
includeExamples?: boolean;
|
|
6
|
+
groupByRisk?: boolean;
|
|
7
|
+
groupByProtocol?: boolean;
|
|
8
|
+
title?: string;
|
|
9
|
+
versionInfo?: {
|
|
10
|
+
oldVersion?: string;
|
|
11
|
+
newVersion?: string;
|
|
12
|
+
comparisonDate?: string;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export interface ChangeReport {
|
|
16
|
+
title: string;
|
|
17
|
+
summary: {
|
|
18
|
+
totalChanges: number;
|
|
19
|
+
breakingChanges: number;
|
|
20
|
+
compatibilityScore: number;
|
|
21
|
+
migrationEffort: string;
|
|
22
|
+
};
|
|
23
|
+
sections: ReportSection[];
|
|
24
|
+
}
|
|
25
|
+
export interface ReportSection {
|
|
26
|
+
title: string;
|
|
27
|
+
changes: EnhancedUniSpecChange[];
|
|
28
|
+
summary: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Generate a comprehensive change report.
|
|
32
|
+
*
|
|
33
|
+
* @param diff - Enhanced diff result
|
|
34
|
+
* @param options - Report generation options
|
|
35
|
+
* @returns Formatted report in the specified format
|
|
36
|
+
*/
|
|
37
|
+
export declare function generateChangeReport(diff: EnhancedDiffResult, options: ReportOptions): string;
|