@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.
@@ -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
- const schemaProvider = await tryCreateNodeSchemaProvider();
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.filter((s) => Boolean(s)),
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) {
@@ -11,11 +11,24 @@ export interface DiffResult {
11
11
  changes: UniSpecChange[];
12
12
  }
13
13
  /**
14
- * Compute a structural diff between two UniSpec documents.
14
+ * Compare two UniSpec documents and return detected changes.
15
15
  *
16
- * Current behavior:
17
- * - Tracks added, removed, and changed fields and array items.
18
- * - Uses JSON Pointer-like paths rooted at "" (e.g., "/info/title").
19
- * - Marks all changes with severity "unknown" for now.
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;
@@ -218,12 +218,25 @@ function annotateGraphQLChange(change) {
218
218
  return annotated;
219
219
  }
220
220
  /**
221
- * Compute a structural diff between two UniSpec documents.
221
+ * Compare two UniSpec documents and return detected changes.
222
222
  *
223
- * Current behavior:
224
- * - Tracks added, removed, and changed fields and array items.
225
- * - Uses JSON Pointer-like paths rooted at "" (e.g., "/info/title").
226
- * - Marks all changes with severity "unknown" for now.
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 = [];
@@ -4,10 +4,9 @@ export interface LoadOptions {
4
4
  }
5
5
  /**
6
6
  * Load a UniSpec document from a raw input value.
7
- * Currently supports:
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, _options?: LoadOptions): Promise<UniSpecDocument>;
12
+ export declare function loadUniSpec(input: string | object, options?: LoadOptions): Promise<UniSpecDocument>;
@@ -1,19 +1,41 @@
1
1
  /**
2
2
  * Load a UniSpec document from a raw input value.
3
- * Currently supports:
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, _options = {}) {
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
- // For now we assume JSON; YAML support will be added later.
16
- return JSON.parse(trimmed);
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
- * - Preserves values as-is.
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;
@@ -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
- * - Preserves values as-is.
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);