@unispechq/unispec-core 0.2.10 → 0.2.11
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/cjs/diff/index.js +18 -5
- package/dist/cjs/loader/index.js +61 -6
- package/dist/cjs/normalizer/index.js +16 -2
- package/dist/cjs/validator/generated-schemas.js +819 -0
- package/dist/cjs/validator/index.js +5 -82
- package/dist/diff/index.d.ts +18 -5
- package/dist/diff/index.js +18 -5
- package/dist/loader/index.d.ts +3 -4
- package/dist/loader/index.js +28 -6
- package/dist/normalizer/index.d.ts +16 -2
- package/dist/normalizer/index.js +16 -2
- package/dist/validator/generated-schemas.d.ts +832 -0
- package/dist/validator/generated-schemas.js +816 -0
- package/dist/validator/index.js +5 -49
- package/package.json +7 -2
|
@@ -1,37 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
4
|
};
|
|
@@ -39,58 +6,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
39
6
|
exports.validateUniSpec = validateUniSpec;
|
|
40
7
|
exports.validateUniSpecTests = validateUniSpecTests;
|
|
41
8
|
const _2020_js_1 = __importDefault(require("ajv/dist/2020.js"));
|
|
9
|
+
const generated_schemas_js_1 = require("./generated-schemas.js");
|
|
42
10
|
let cached = null;
|
|
43
|
-
async function tryCreateNodeSchemaProvider() {
|
|
44
|
-
try {
|
|
45
|
-
const fs = await Promise.resolve().then(() => __importStar(require("node:fs/promises")));
|
|
46
|
-
const path = await Promise.resolve().then(() => __importStar(require("node:path")));
|
|
47
|
-
const module = await Promise.resolve().then(() => __importStar(require("node:module")));
|
|
48
|
-
const requireBasePath = typeof __filename === "string" && __filename.length > 0
|
|
49
|
-
? __filename
|
|
50
|
-
: path.join(process.cwd(), "__unispec_core_require__.js");
|
|
51
|
-
const require = module.createRequire(requireBasePath);
|
|
52
|
-
const schemaIndexPath = require.resolve("@unispechq/unispec-schema/schema");
|
|
53
|
-
const schemaRoot = path.dirname(schemaIndexPath);
|
|
54
|
-
return {
|
|
55
|
-
getSchema: async (schemaPath) => {
|
|
56
|
-
const fullPath = path.join(schemaRoot, schemaPath);
|
|
57
|
-
const json = await fs.readFile(fullPath, "utf8");
|
|
58
|
-
return JSON.parse(json);
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
catch {
|
|
63
|
-
return undefined;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
11
|
async function loadDefaultSchemas() {
|
|
67
|
-
|
|
68
|
-
if (!schemaProvider) {
|
|
69
|
-
throw new Error("UniSpec validator: default schema loading is not available in this environment. " +
|
|
70
|
-
"Provide ValidateOptions.schemas (recommended for browsers/edge runtimes) or ValidateOptions.schemaProvider.");
|
|
71
|
-
}
|
|
72
|
-
const { manifest, unispec } = (await Promise.resolve().then(() => __importStar(require("@unispechq/unispec-schema"))));
|
|
73
|
-
const types = manifest?.types ?? {};
|
|
74
|
-
const typeSchemaPaths = Object.values(types).map((rel) => String(rel));
|
|
75
|
-
const subschemas = await Promise.all(typeSchemaPaths.map(async (relPath) => {
|
|
76
|
-
try {
|
|
77
|
-
return await schemaProvider.getSchema(relPath);
|
|
78
|
-
}
|
|
79
|
-
catch {
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
}));
|
|
83
|
-
let unispecTests;
|
|
84
|
-
try {
|
|
85
|
-
unispecTests = await schemaProvider.getSchema("unispec-tests.schema.json");
|
|
86
|
-
}
|
|
87
|
-
catch {
|
|
88
|
-
unispecTests = undefined;
|
|
89
|
-
}
|
|
12
|
+
// Always use generated schemas - they work in all environments
|
|
90
13
|
return {
|
|
91
|
-
unispec: unispec,
|
|
92
|
-
unispecTests,
|
|
93
|
-
subschemas: subschemas
|
|
14
|
+
unispec: generated_schemas_js_1.GENERATED_SCHEMAS.unispec,
|
|
15
|
+
unispecTests: generated_schemas_js_1.GENERATED_SCHEMAS.unispecTests,
|
|
16
|
+
subschemas: generated_schemas_js_1.GENERATED_SCHEMAS.subschemas,
|
|
94
17
|
};
|
|
95
18
|
}
|
|
96
19
|
function createAjv(options) {
|
package/dist/diff/index.d.ts
CHANGED
|
@@ -11,11 +11,24 @@ export interface DiffResult {
|
|
|
11
11
|
changes: UniSpecChange[];
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
14
|
+
* Compare two UniSpec documents and return detected changes.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* -
|
|
19
|
-
* -
|
|
16
|
+
* This function performs a deep comparison between two UniSpec documents
|
|
17
|
+
* and categorizes changes by severity and protocol. Useful for:
|
|
18
|
+
* - API change detection in CI/CD pipelines
|
|
19
|
+
* - Breaking change analysis
|
|
20
|
+
* - Version compatibility checks
|
|
21
|
+
* - Audit trails for API evolution
|
|
22
|
+
*
|
|
23
|
+
* Features:
|
|
24
|
+
* - Detects added/removed fields at any depth
|
|
25
|
+
* - Special handling for named collections (routes, operations, channels)
|
|
26
|
+
* - Severity classification: "breaking" | "non-breaking" | "unknown"
|
|
27
|
+
* - Protocol categorization: "rest" | "graphql" | "websocket"
|
|
28
|
+
* - Detailed change descriptions with JSON paths
|
|
29
|
+
*
|
|
30
|
+
* @param oldDoc - The previous version of the UniSpec document
|
|
31
|
+
* @param newDoc - The current version of the UniSpec document
|
|
32
|
+
* @returns Object containing all detected changes
|
|
20
33
|
*/
|
|
21
34
|
export declare function diffUniSpec(oldDoc: UniSpecDocument, newDoc: UniSpecDocument): DiffResult;
|
package/dist/diff/index.js
CHANGED
|
@@ -218,12 +218,25 @@ function annotateGraphQLChange(change) {
|
|
|
218
218
|
return annotated;
|
|
219
219
|
}
|
|
220
220
|
/**
|
|
221
|
-
*
|
|
221
|
+
* Compare two UniSpec documents and return detected changes.
|
|
222
222
|
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
* -
|
|
226
|
-
* -
|
|
223
|
+
* This function performs a deep comparison between two UniSpec documents
|
|
224
|
+
* and categorizes changes by severity and protocol. Useful for:
|
|
225
|
+
* - API change detection in CI/CD pipelines
|
|
226
|
+
* - Breaking change analysis
|
|
227
|
+
* - Version compatibility checks
|
|
228
|
+
* - Audit trails for API evolution
|
|
229
|
+
*
|
|
230
|
+
* Features:
|
|
231
|
+
* - Detects added/removed fields at any depth
|
|
232
|
+
* - Special handling for named collections (routes, operations, channels)
|
|
233
|
+
* - Severity classification: "breaking" | "non-breaking" | "unknown"
|
|
234
|
+
* - Protocol categorization: "rest" | "graphql" | "websocket"
|
|
235
|
+
* - Detailed change descriptions with JSON paths
|
|
236
|
+
*
|
|
237
|
+
* @param oldDoc - The previous version of the UniSpec document
|
|
238
|
+
* @param newDoc - The current version of the UniSpec document
|
|
239
|
+
* @returns Object containing all detected changes
|
|
227
240
|
*/
|
|
228
241
|
export function diffUniSpec(oldDoc, newDoc) {
|
|
229
242
|
const changes = [];
|
package/dist/loader/index.d.ts
CHANGED
|
@@ -4,10 +4,9 @@ export interface LoadOptions {
|
|
|
4
4
|
}
|
|
5
5
|
/**
|
|
6
6
|
* Load a UniSpec document from a raw input value.
|
|
7
|
-
*
|
|
7
|
+
* Supports:
|
|
8
8
|
* - JavaScript objects (treated as already parsed UniSpec)
|
|
9
9
|
* - JSON strings
|
|
10
|
-
*
|
|
11
|
-
* YAML and filesystem helpers will be added later, keeping this API stable.
|
|
10
|
+
* - YAML strings
|
|
12
11
|
*/
|
|
13
|
-
export declare function loadUniSpec(input: string | object,
|
|
12
|
+
export declare function loadUniSpec(input: string | object, options?: LoadOptions): Promise<UniSpecDocument>;
|
package/dist/loader/index.js
CHANGED
|
@@ -1,19 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Load a UniSpec document from a raw input value.
|
|
3
|
-
*
|
|
3
|
+
* Supports:
|
|
4
4
|
* - JavaScript objects (treated as already parsed UniSpec)
|
|
5
5
|
* - JSON strings
|
|
6
|
-
*
|
|
7
|
-
* YAML and filesystem helpers will be added later, keeping this API stable.
|
|
6
|
+
* - YAML strings
|
|
8
7
|
*/
|
|
9
|
-
export async function loadUniSpec(input,
|
|
8
|
+
export async function loadUniSpec(input, options = {}) {
|
|
10
9
|
if (typeof input === "string") {
|
|
11
10
|
const trimmed = input.trim();
|
|
12
11
|
if (!trimmed) {
|
|
13
12
|
throw new Error("Cannot load UniSpec: input string is empty");
|
|
14
13
|
}
|
|
15
|
-
//
|
|
16
|
-
|
|
14
|
+
// Try JSON first (faster and more common)
|
|
15
|
+
try {
|
|
16
|
+
return JSON.parse(trimmed);
|
|
17
|
+
}
|
|
18
|
+
catch (jsonError) {
|
|
19
|
+
// If JSON fails, try YAML
|
|
20
|
+
try {
|
|
21
|
+
// Dynamic import to avoid bundling yaml parser if not needed
|
|
22
|
+
const yamlModule = await import("js-yaml");
|
|
23
|
+
if (!yamlModule.load) {
|
|
24
|
+
throw new Error("js-yaml module not available");
|
|
25
|
+
}
|
|
26
|
+
const doc = yamlModule.load(trimmed, {
|
|
27
|
+
filename: options.filename,
|
|
28
|
+
// Basic security options
|
|
29
|
+
schema: yamlModule.FAILSAFE_SCHEMA
|
|
30
|
+
});
|
|
31
|
+
return doc;
|
|
32
|
+
}
|
|
33
|
+
catch (yamlError) {
|
|
34
|
+
const jsonMsg = jsonError instanceof Error ? jsonError.message : String(jsonError);
|
|
35
|
+
const yamlMsg = yamlError instanceof Error ? yamlError.message : String(yamlError);
|
|
36
|
+
throw new Error(`Failed to parse input as JSON or YAML. JSON error: ${jsonMsg}. YAML error: ${yamlMsg}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
17
39
|
}
|
|
18
40
|
return input;
|
|
19
41
|
}
|
|
@@ -4,8 +4,22 @@ export interface NormalizeOptions {
|
|
|
4
4
|
/**
|
|
5
5
|
* Normalize a UniSpec document into a canonical, deterministic form.
|
|
6
6
|
*
|
|
7
|
+
* This function ensures consistent representation of UniSpec documents
|
|
8
|
+
* by sorting object keys and protocol-specific structures in a predictable order.
|
|
9
|
+
* Useful for:
|
|
10
|
+
* - Generating stable diffs between documents
|
|
11
|
+
* - Creating consistent output for caching
|
|
12
|
+
* - Ensuring reproducible builds
|
|
13
|
+
*
|
|
7
14
|
* Current behavior:
|
|
8
|
-
* - Recursively sorts object keys lexicographically
|
|
9
|
-
* -
|
|
15
|
+
* - Recursively sorts object keys lexicographically
|
|
16
|
+
* - Sorts REST routes by name or path+method
|
|
17
|
+
* - Sorts GraphQL operations by name within each operation type
|
|
18
|
+
* - Sorts WebSocket channels and messages by name
|
|
19
|
+
* - Preserves all values as-is
|
|
20
|
+
*
|
|
21
|
+
* @param doc - The UniSpec document to normalize
|
|
22
|
+
* @param options - Normalization options (currently unused, reserved for future)
|
|
23
|
+
* @returns The normalized UniSpec document
|
|
10
24
|
*/
|
|
11
25
|
export declare function normalizeUniSpec(doc: UniSpecDocument, _options?: NormalizeOptions): UniSpecDocument;
|
package/dist/normalizer/index.js
CHANGED
|
@@ -94,9 +94,23 @@ function normalizeGraphqlOperations(doc) {
|
|
|
94
94
|
/**
|
|
95
95
|
* Normalize a UniSpec document into a canonical, deterministic form.
|
|
96
96
|
*
|
|
97
|
+
* This function ensures consistent representation of UniSpec documents
|
|
98
|
+
* by sorting object keys and protocol-specific structures in a predictable order.
|
|
99
|
+
* Useful for:
|
|
100
|
+
* - Generating stable diffs between documents
|
|
101
|
+
* - Creating consistent output for caching
|
|
102
|
+
* - Ensuring reproducible builds
|
|
103
|
+
*
|
|
97
104
|
* Current behavior:
|
|
98
|
-
* - Recursively sorts object keys lexicographically
|
|
99
|
-
* -
|
|
105
|
+
* - Recursively sorts object keys lexicographically
|
|
106
|
+
* - Sorts REST routes by name or path+method
|
|
107
|
+
* - Sorts GraphQL operations by name within each operation type
|
|
108
|
+
* - Sorts WebSocket channels and messages by name
|
|
109
|
+
* - Preserves all values as-is
|
|
110
|
+
*
|
|
111
|
+
* @param doc - The UniSpec document to normalize
|
|
112
|
+
* @param options - Normalization options (currently unused, reserved for future)
|
|
113
|
+
* @returns The normalized UniSpec document
|
|
100
114
|
*/
|
|
101
115
|
export function normalizeUniSpec(doc, _options = {}) {
|
|
102
116
|
const normalized = normalizeValue(doc);
|