0
# Schema Management
1
2
Schema compilation, caching, and remote reference resolution capabilities for handling complex schema relationships and dependencies. z-schema provides comprehensive tools for managing schemas with remote references and inter-schema dependencies.
3
4
## Capabilities
5
6
### Remote Reference Management
7
8
Set and manage remote schema references for resolving `$ref` properties.
9
10
```javascript { .api }
11
/**
12
* Register a remote schema reference
13
* @param uri - URI identifier for the schema
14
* @param schema - Schema object or JSON string
15
* @param validationOptions - Optional validation options for this schema
16
*/
17
setRemoteReference(
18
uri: string,
19
schema: any | string,
20
validationOptions?: ZSchema.Options
21
): void;
22
```
23
24
**Usage Examples:**
25
26
```javascript
27
const ZSchema = require("z-schema");
28
const validator = new ZSchema();
29
30
// Set remote reference from object
31
const personSchema = {
32
type: "object",
33
properties: {
34
name: { type: "string" },
35
age: { type: "number" }
36
},
37
required: ["name", "age"]
38
};
39
40
validator.setRemoteReference("http://example.com/person", personSchema);
41
42
// Set remote reference from JSON string
43
const addressSchemaJson = JSON.stringify({
44
type: "object",
45
properties: {
46
street: { type: "string" },
47
city: { type: "string" },
48
zipCode: { type: "string", pattern: "^\\d{5}$" }
49
},
50
required: ["street", "city"]
51
});
52
53
validator.setRemoteReference("http://example.com/address", addressSchemaJson);
54
55
// Use schemas with references
56
const mainSchema = {
57
type: "object",
58
properties: {
59
person: { $ref: "http://example.com/person" },
60
address: { $ref: "http://example.com/address" }
61
}
62
};
63
64
// Set with custom validation options
65
validator.setRemoteReference(
66
"http://example.com/strict-schema",
67
strictSchema,
68
{ strictMode: true, noEmptyStrings: true }
69
);
70
71
const data = {
72
person: { name: "John Doe", age: 30 },
73
address: { street: "123 Main St", city: "Anytown", zipCode: "12345" }
74
};
75
76
const valid = validator.validate(data, mainSchema);
77
```
78
79
### Global Schema Reader
80
81
Set a global function to read schemas synchronously when references are encountered.
82
83
```javascript { .api }
84
/**
85
* Set global schema reader function (static method)
86
* @param schemaReader - Function that reads schemas by URI
87
*/
88
static setSchemaReader(schemaReader: (uri: string) => any): void;
89
90
/**
91
* Set schema reader function (instance method)
92
* @param schemaReader - Function that reads schemas by URI
93
*/
94
setSchemaReader(schemaReader: (uri: string) => any): void;
95
96
/**
97
* Get current schema reader function
98
* @returns Current schema reader function or undefined
99
*/
100
getSchemaReader(): ((uri: string) => any) | undefined;
101
```
102
103
**Usage Examples:**
104
105
```javascript
106
const fs = require("fs");
107
const path = require("path");
108
109
// Set global schema reader
110
ZSchema.setSchemaReader(function(uri) {
111
const filename = path.resolve(__dirname, "schemas", uri + ".json");
112
try {
113
return JSON.parse(fs.readFileSync(filename, "utf8"));
114
} catch (error) {
115
throw new Error(`Could not read schema: ${uri}`);
116
}
117
});
118
119
// Now schemas will be automatically loaded when referenced
120
const schema = {
121
type: "object",
122
properties: {
123
user: { $ref: "user" }, // Will load from schemas/user.json
124
profile: { $ref: "profile" } // Will load from schemas/profile.json
125
}
126
};
127
128
const validator = new ZSchema();
129
const valid = validator.validate(data, schema);
130
131
// Instance-specific schema reader
132
const validator2 = new ZSchema();
133
validator2.setSchemaReader(function(uri) {
134
// Custom loading logic for this validator instance
135
return loadSchemaFromDatabase(uri);
136
});
137
```
138
139
### Schema Resolution
140
141
Get fully resolved schemas with all references expanded.
142
143
```javascript { .api }
144
/**
145
* Get schema with all references resolved
146
* @param schema - Schema to resolve
147
* @returns Resolved schema with expanded references
148
* @throws Error if resolution fails
149
*/
150
getResolvedSchema(schema: any): any;
151
```
152
153
**Usage Examples:**
154
155
```javascript
156
const validator = new ZSchema();
157
158
// Set up remote references
159
validator.setRemoteReference("http://example.com/address", {
160
type: "object",
161
properties: {
162
street: { type: "string" },
163
city: { type: "string" }
164
}
165
});
166
167
// Schema with references
168
const schema = {
169
type: "object",
170
properties: {
171
name: { type: "string" },
172
address: { $ref: "http://example.com/address" }
173
}
174
};
175
176
try {
177
const resolvedSchema = validator.getResolvedSchema(schema);
178
console.log(JSON.stringify(resolvedSchema, null, 2));
179
/* Output:
180
{
181
"type": "object",
182
"properties": {
183
"name": { "type": "string" },
184
"address": {
185
"type": "object",
186
"properties": {
187
"street": { "type": "string" },
188
"city": { "type": "string" }
189
}
190
}
191
}
192
}
193
*/
194
} catch (error) {
195
console.error("Schema resolution failed:", error.message);
196
}
197
```
198
199
### Missing Reference Detection
200
201
Identify missing remote references that need to be resolved.
202
203
```javascript { .api }
204
/**
205
* Get array of missing references from validation errors
206
* @param arr - Optional array of errors to check (defaults to last errors)
207
* @returns Array of missing reference URIs
208
*/
209
getMissingReferences(arr?: any[]): string[];
210
211
/**
212
* Get array of missing remote references (URLs only)
213
* @returns Array of missing remote reference URLs
214
*/
215
getMissingRemoteReferences(): string[];
216
```
217
218
**Usage Examples:**
219
220
```javascript
221
const validator = new ZSchema();
222
223
const schema = {
224
type: "object",
225
properties: {
226
profile: { $ref: "http://example.com/profile" },
227
settings: { $ref: "http://example.com/settings" },
228
localRef: { $ref: "#/definitions/local" }
229
},
230
definitions: {
231
local: { type: "string" }
232
}
233
};
234
235
const valid = validator.validate({}, schema);
236
237
if (!valid) {
238
// Get all missing references
239
const missingRefs = validator.getMissingReferences();
240
console.log("Missing references:", missingRefs);
241
// Output: ["http://example.com/profile", "http://example.com/settings"]
242
243
// Get only remote (URL) references
244
const missingRemote = validator.getMissingRemoteReferences();
245
console.log("Missing remote references:", missingRemote);
246
// Output: ["http://example.com/profile", "http://example.com/settings"]
247
248
// Load missing schemas
249
missingRemote.forEach(url => {
250
const schema = loadSchemaFromSomewhere(url);
251
validator.setRemoteReference(url, schema);
252
});
253
254
// Retry validation
255
const validAfterLoad = validator.validate({}, schema);
256
}
257
```
258
259
### Automatic Schema Loading
260
261
Example implementation of automatic remote schema loading.
262
263
```javascript { .api }
264
// Example helper function for automatic schema loading
265
function validateWithAutomaticLoading(validator, data, schema, callback) {
266
function attemptValidation() {
267
const valid = validator.validate(data, schema);
268
const missingRefs = validator.getMissingRemoteReferences();
269
270
if (missingRefs.length > 0) {
271
let loaded = 0;
272
const errors = [];
273
274
missingRefs.forEach(url => {
275
// Load remote schema (example using fetch or http)
276
loadRemoteSchema(url)
277
.then(remoteSchema => {
278
validator.setRemoteReference(url, remoteSchema);
279
loaded++;
280
281
if (loaded === missingRefs.length) {
282
if (errors.length === 0) {
283
attemptValidation(); // Retry
284
} else {
285
callback(errors[0], false);
286
}
287
}
288
})
289
.catch(error => {
290
errors.push(error);
291
loaded++;
292
293
if (loaded === missingRefs.length) {
294
callback(errors[0], false);
295
}
296
});
297
});
298
} else {
299
callback(null, valid);
300
}
301
}
302
303
attemptValidation();
304
}
305
```
306
307
**Usage Examples:**
308
309
```javascript
310
const https = require("https");
311
312
function loadRemoteSchema(url) {
313
return new Promise((resolve, reject) => {
314
https.get(url, (response) => {
315
let data = "";
316
response.on("data", chunk => data += chunk);
317
response.on("end", () => {
318
try {
319
resolve(JSON.parse(data));
320
} catch (error) {
321
reject(error);
322
}
323
});
324
}).on("error", reject);
325
});
326
}
327
328
const validator = new ZSchema();
329
const schema = {
330
$ref: "https://json-schema.org/draft-04/schema#"
331
};
332
333
validateWithAutomaticLoading(validator, {type: "string"}, schema, (error, valid) => {
334
if (error) {
335
console.error("Loading failed:", error);
336
} else if (valid) {
337
console.log("Validation passed");
338
} else {
339
console.log("Validation failed:", validator.getLastErrors());
340
}
341
});
342
```
343
344
## Configuration Options
345
346
### Reference Resolution Options
347
348
```javascript { .api }
349
interface ReferenceOptions {
350
/** Don't fail on unresolvable remote references (default: false) */
351
ignoreUnresolvableReferences?: boolean;
352
}
353
```
354
355
**Usage Examples:**
356
357
```javascript
358
// Ignore unresolvable references (for testing)
359
const lenientValidator = new ZSchema({
360
ignoreUnresolvableReferences: true
361
});
362
363
const schema = {
364
type: "object",
365
properties: {
366
data: { $ref: "http://unreachable.example.com/schema" }
367
}
368
};
369
370
// This will not fail even though the reference cannot be resolved
371
const valid = lenientValidator.validate({ data: "test" }, schema);
372
```
373
374
## Schema Compilation Process
375
376
Understanding the internal schema compilation process for advanced usage.
377
378
```javascript { .api }
379
/**
380
* Compile schema without meta-schema validation
381
* @param schema - Schema to compile
382
* @returns boolean indicating compilation success
383
*/
384
compileSchema(schema: any): boolean;
385
```
386
387
**Usage Examples:**
388
389
```javascript
390
const validator = new ZSchema();
391
392
// Compile schema array with inter-references
393
const schemas = [
394
{
395
id: "base",
396
type: "object",
397
properties: {
398
id: { type: "number" }
399
}
400
},
401
{
402
id: "extended",
403
allOf: [
404
{ $ref: "base" },
405
{
406
properties: {
407
name: { type: "string" }
408
}
409
}
410
]
411
}
412
];
413
414
// Compile all schemas
415
const compiled = validator.compileSchema(schemas);
416
if (compiled) {
417
// Use compiled schema for validation
418
const valid = validator.validate(
419
{ id: 1, name: "test" },
420
schemas.find(s => s.id === "extended")
421
);
422
}
423
```
424
425
## Error Handling for Schema Management
426
427
Schema management operations can fail in various ways. Handle errors appropriately.
428
429
```javascript { .api }
430
interface SchemaManagementErrors {
431
"UNRESOLVABLE_REFERENCE": "Reference could not be resolved: {0}";
432
"SCHEMA_NOT_REACHABLE": "Validator was not able to read schema with uri: {0}";
433
"REF_UNRESOLVED": "Reference has not been resolved during compilation: {0}";
434
"REMOTE_NOT_VALID": "Remote reference didn't compile successfully: {0}";
435
}
436
```
437
438
**Usage Examples:**
439
440
```javascript
441
const validator = new ZSchema();
442
443
try {
444
const resolvedSchema = validator.getResolvedSchema(schemaWithBadRefs);
445
} catch (error) {
446
if (error.name === "z-schema validation error") {
447
error.details.forEach(detail => {
448
switch (detail.code) {
449
case "UNRESOLVABLE_REFERENCE":
450
console.log(`Cannot resolve reference: ${detail.params[0]}`);
451
break;
452
case "SCHEMA_NOT_REACHABLE":
453
console.log(`Schema not reachable: ${detail.params[0]}`);
454
break;
455
default:
456
console.log(`Schema error: ${detail.message}`);
457
}
458
});
459
}
460
}
461
```