@twin.org/data-core 0.0.1-next.35 → 0.0.1-next.36
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/index.cjs +111 -36
- package/dist/esm/index.mjs +111 -36
- package/dist/types/index.d.ts +2 -1
- package/dist/types/models/IDataTypeHandler.d.ts +2 -2
- package/dist/types/models/IJsonSchema.d.ts +5 -0
- package/dist/types/models/ISchemaValidationErrors.d.ts +7 -0
- package/dist/types/models/ISchemaValidationResult.d.ts +2 -2
- package/dist/types/utils/jsonSchemaHelper.d.ts +15 -5
- package/docs/changelog.md +7 -0
- package/docs/reference/classes/JsonSchemaHelper.md +38 -4
- package/docs/reference/index.md +2 -1
- package/docs/reference/interfaces/IDataTypeHandler.md +2 -2
- package/docs/reference/interfaces/ISchemaValidationResult.md +2 -2
- package/docs/reference/type-aliases/IJsonSchema.md +5 -0
- package/docs/reference/type-aliases/ISchemaValidationErrors.md +5 -0
- package/package.json +4 -5
- package/dist/types/models/ISchemaValidationError.d.ts +0 -5
- package/docs/reference/type-aliases/ISchemaValidationError.md +0 -5
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var core = require('@twin.org/core');
|
|
4
|
+
var browser = require('@hyperjump/browser');
|
|
5
|
+
var draft202012 = require('@hyperjump/json-schema/draft-2020-12');
|
|
4
6
|
var web = require('@twin.org/web');
|
|
5
|
-
var Ajv = require('ajv');
|
|
6
|
-
var addFormats = require('ajv-formats');
|
|
7
7
|
|
|
8
8
|
// Copyright 2024 IOTA Stiftung.
|
|
9
9
|
// SPDX-License-Identifier: Apache-2.0.
|
|
@@ -66,6 +66,16 @@ class JsonSchemaHelper {
|
|
|
66
66
|
* The schema version.
|
|
67
67
|
*/
|
|
68
68
|
static SCHEMA_VERSION = "https://json-schema.org/draft/2020-12/schema";
|
|
69
|
+
/**
|
|
70
|
+
* The private prefix for the type.
|
|
71
|
+
* @internal
|
|
72
|
+
*/
|
|
73
|
+
static _PRIVATE_PREFIX = "https://twindev.org/private/";
|
|
74
|
+
/**
|
|
75
|
+
* The private type.
|
|
76
|
+
* @internal
|
|
77
|
+
*/
|
|
78
|
+
static _PRIVATE_TYPE = "https://twindev.org/private/ValidationType";
|
|
69
79
|
/**
|
|
70
80
|
* The class name.
|
|
71
81
|
* @internal
|
|
@@ -79,50 +89,77 @@ class JsonSchemaHelper {
|
|
|
79
89
|
* @returns Result containing errors if there are any.
|
|
80
90
|
*/
|
|
81
91
|
static async validate(schema, data, additionalTypes) {
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
// you have an array with fixed elements e.g. myType: [string, ...string[]]
|
|
86
|
-
// https://github.com/ajv-validator/ajv/issues/1417
|
|
87
|
-
strictTuples: false,
|
|
88
|
-
loadSchema: async (uri) => {
|
|
92
|
+
const httpSchemePlugin = {
|
|
93
|
+
retrieve: async (uri) => {
|
|
94
|
+
let loadedSchema;
|
|
89
95
|
const subTypeHandler = DataTypeHandlerFactory.getIfExists(uri);
|
|
90
96
|
if (core.Is.function(subTypeHandler?.jsonSchema)) {
|
|
91
97
|
const subSchema = await subTypeHandler.jsonSchema();
|
|
92
98
|
if (core.Is.object(subSchema)) {
|
|
93
|
-
|
|
99
|
+
loadedSchema = subSchema;
|
|
94
100
|
}
|
|
95
101
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
if (!core.Is.object(loadedSchema)) {
|
|
103
|
+
try {
|
|
104
|
+
// We don't have the type in our local data types, so we try to fetch it from the web
|
|
105
|
+
schema = await web.FetchHelper.fetchJson(JsonSchemaHelper._CLASS_NAME, uri, web.HttpMethod.GET, undefined, {
|
|
106
|
+
headers: {
|
|
107
|
+
Accept: browser.acceptableMediaTypes()
|
|
108
|
+
},
|
|
109
|
+
// Cache for an hour
|
|
110
|
+
cacheTtlMs: 3600000
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
catch { }
|
|
107
114
|
}
|
|
115
|
+
// Failed to load remotely so return an empty object
|
|
116
|
+
// so the schema validation doesn't completely fail
|
|
117
|
+
loadedSchema ??= {};
|
|
118
|
+
return {
|
|
119
|
+
status: 200,
|
|
120
|
+
statusText: "OK",
|
|
121
|
+
ok: true,
|
|
122
|
+
url: uri,
|
|
123
|
+
headers: new Headers({
|
|
124
|
+
"Content-Type": "application/schema+json"
|
|
125
|
+
}),
|
|
126
|
+
json: Promise.resolve(loadedSchema)
|
|
127
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
128
|
+
};
|
|
108
129
|
}
|
|
109
|
-
}
|
|
110
|
-
|
|
130
|
+
};
|
|
131
|
+
browser.addUriSchemePlugin("https", httpSchemePlugin);
|
|
132
|
+
browser.addUriSchemePlugin("http", httpSchemePlugin);
|
|
111
133
|
// Add the additional types provided by the user
|
|
112
134
|
if (core.Is.objectValue(additionalTypes)) {
|
|
113
135
|
for (const key in additionalTypes) {
|
|
114
|
-
|
|
136
|
+
additionalTypes[key].$schema =
|
|
137
|
+
additionalTypes[key].$schema ?? JsonSchemaHelper.SCHEMA_VERSION;
|
|
138
|
+
const additionalType = key.startsWith("http")
|
|
139
|
+
? key
|
|
140
|
+
: `${JsonSchemaHelper._PRIVATE_PREFIX}${key}`;
|
|
141
|
+
draft202012.registerSchema(additionalTypes[key], additionalType);
|
|
115
142
|
}
|
|
116
143
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const output =
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
144
|
+
schema.$schema = schema.$schema ?? JsonSchemaHelper.SCHEMA_VERSION;
|
|
145
|
+
draft202012.registerSchema(schema, JsonSchemaHelper._PRIVATE_TYPE);
|
|
146
|
+
const output = await draft202012.validate(JsonSchemaHelper._PRIVATE_TYPE, data, "DETAILED");
|
|
147
|
+
await this.cleanupOutput(output);
|
|
148
|
+
await this.formatErrors(output, data);
|
|
149
|
+
draft202012.unregisterSchema(JsonSchemaHelper._PRIVATE_TYPE);
|
|
150
|
+
// Remove the additional types provided by the user
|
|
151
|
+
if (core.Is.objectValue(additionalTypes)) {
|
|
152
|
+
for (const key in additionalTypes) {
|
|
153
|
+
const additionalType = key.startsWith("http")
|
|
154
|
+
? key
|
|
155
|
+
: `${JsonSchemaHelper._PRIVATE_PREFIX}${key}`;
|
|
156
|
+
draft202012.unregisterSchema(additionalType);
|
|
157
|
+
}
|
|
124
158
|
}
|
|
125
|
-
return
|
|
159
|
+
return {
|
|
160
|
+
result: output.valid,
|
|
161
|
+
errors: output.errors
|
|
162
|
+
};
|
|
126
163
|
}
|
|
127
164
|
/**
|
|
128
165
|
* Get the property type from a schema.
|
|
@@ -131,9 +168,12 @@ class JsonSchemaHelper {
|
|
|
131
168
|
* @returns The types of the property.
|
|
132
169
|
*/
|
|
133
170
|
static getPropertyType(schema, propertyName) {
|
|
171
|
+
if (core.Is.boolean(schema)) {
|
|
172
|
+
return undefined;
|
|
173
|
+
}
|
|
134
174
|
if (schema.type === "object" && core.Is.objectValue(schema.properties)) {
|
|
135
175
|
const propertySchema = schema.properties[propertyName];
|
|
136
|
-
if (core.Is.
|
|
176
|
+
if (!core.Is.boolean(propertySchema) && !core.Is.empty(propertySchema)) {
|
|
137
177
|
if (core.Is.stringValue(propertySchema.$ref)) {
|
|
138
178
|
return propertySchema.$ref;
|
|
139
179
|
}
|
|
@@ -199,6 +239,41 @@ class JsonSchemaHelper {
|
|
|
199
239
|
additionalProperties: false
|
|
200
240
|
};
|
|
201
241
|
}
|
|
242
|
+
/**
|
|
243
|
+
* Cleanup the errors from the schema validation.
|
|
244
|
+
* @param outputUnit The errors to format.
|
|
245
|
+
* @param data The data that was validated.
|
|
246
|
+
* @returns The formatted errors.
|
|
247
|
+
*/
|
|
248
|
+
static async formatErrors(outputUnit, data) {
|
|
249
|
+
if (outputUnit.keyword === "https://json-schema.org/keyword/required") {
|
|
250
|
+
outputUnit.message = `The property '${outputUnit.instanceLocation}' is required but was not found.`;
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
outputUnit.message = `"${outputUnit.instanceLocation}" fails schema constraint ${outputUnit.absoluteKeywordLocation}`;
|
|
254
|
+
}
|
|
255
|
+
if (core.Is.arrayValue(outputUnit.errors)) {
|
|
256
|
+
for (const subError of outputUnit.errors) {
|
|
257
|
+
await this.formatErrors(subError, data);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Cleanup the errors from the schema validation.
|
|
263
|
+
* @param outputUnit The errors to format.
|
|
264
|
+
* @returns The formatted errors.
|
|
265
|
+
* @internal
|
|
266
|
+
*/
|
|
267
|
+
static async cleanupOutput(outputUnit) {
|
|
268
|
+
if (outputUnit.absoluteKeywordLocation?.startsWith(JsonSchemaHelper._PRIVATE_TYPE)) {
|
|
269
|
+
outputUnit.absoluteKeywordLocation = outputUnit.absoluteKeywordLocation.replace(JsonSchemaHelper._PRIVATE_TYPE, "");
|
|
270
|
+
}
|
|
271
|
+
if (core.Is.arrayValue(outputUnit.errors)) {
|
|
272
|
+
for (const subError of outputUnit.errors) {
|
|
273
|
+
await this.cleanupOutput(subError);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
202
277
|
}
|
|
203
278
|
|
|
204
279
|
// Copyright 2024 IOTA Stiftung.
|
|
@@ -242,14 +317,14 @@ class DataTypeHelper {
|
|
|
242
317
|
const schema = await handler.jsonSchema();
|
|
243
318
|
if (core.Is.object(schema)) {
|
|
244
319
|
const validationResult = await JsonSchemaHelper.validate(schema, data);
|
|
245
|
-
if (core.Is.arrayValue(validationResult.
|
|
320
|
+
if (core.Is.arrayValue(validationResult.errors)) {
|
|
246
321
|
validationFailures.push({
|
|
247
322
|
property: propertyName,
|
|
248
323
|
reason: "validation.schema.failedValidation",
|
|
249
324
|
properties: {
|
|
250
325
|
value: data,
|
|
251
|
-
schemaErrors: validationResult.
|
|
252
|
-
message: validationResult.
|
|
326
|
+
schemaErrors: validationResult.errors,
|
|
327
|
+
message: validationResult.errors.map(e => e.message).join("\n")
|
|
253
328
|
}
|
|
254
329
|
});
|
|
255
330
|
}
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Factory, Urn, Is, StringHelper } from '@twin.org/core';
|
|
2
|
+
import { addUriSchemePlugin, acceptableMediaTypes } from '@hyperjump/browser';
|
|
3
|
+
import { registerSchema, validate, unregisterSchema } from '@hyperjump/json-schema/draft-2020-12';
|
|
2
4
|
import { FetchHelper, HttpMethod } from '@twin.org/web';
|
|
3
|
-
import Ajv from 'ajv';
|
|
4
|
-
import addFormats from 'ajv-formats';
|
|
5
5
|
|
|
6
6
|
// Copyright 2024 IOTA Stiftung.
|
|
7
7
|
// SPDX-License-Identifier: Apache-2.0.
|
|
@@ -64,6 +64,16 @@ class JsonSchemaHelper {
|
|
|
64
64
|
* The schema version.
|
|
65
65
|
*/
|
|
66
66
|
static SCHEMA_VERSION = "https://json-schema.org/draft/2020-12/schema";
|
|
67
|
+
/**
|
|
68
|
+
* The private prefix for the type.
|
|
69
|
+
* @internal
|
|
70
|
+
*/
|
|
71
|
+
static _PRIVATE_PREFIX = "https://twindev.org/private/";
|
|
72
|
+
/**
|
|
73
|
+
* The private type.
|
|
74
|
+
* @internal
|
|
75
|
+
*/
|
|
76
|
+
static _PRIVATE_TYPE = "https://twindev.org/private/ValidationType";
|
|
67
77
|
/**
|
|
68
78
|
* The class name.
|
|
69
79
|
* @internal
|
|
@@ -77,50 +87,77 @@ class JsonSchemaHelper {
|
|
|
77
87
|
* @returns Result containing errors if there are any.
|
|
78
88
|
*/
|
|
79
89
|
static async validate(schema, data, additionalTypes) {
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// you have an array with fixed elements e.g. myType: [string, ...string[]]
|
|
84
|
-
// https://github.com/ajv-validator/ajv/issues/1417
|
|
85
|
-
strictTuples: false,
|
|
86
|
-
loadSchema: async (uri) => {
|
|
90
|
+
const httpSchemePlugin = {
|
|
91
|
+
retrieve: async (uri) => {
|
|
92
|
+
let loadedSchema;
|
|
87
93
|
const subTypeHandler = DataTypeHandlerFactory.getIfExists(uri);
|
|
88
94
|
if (Is.function(subTypeHandler?.jsonSchema)) {
|
|
89
95
|
const subSchema = await subTypeHandler.jsonSchema();
|
|
90
96
|
if (Is.object(subSchema)) {
|
|
91
|
-
|
|
97
|
+
loadedSchema = subSchema;
|
|
92
98
|
}
|
|
93
99
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
100
|
+
if (!Is.object(loadedSchema)) {
|
|
101
|
+
try {
|
|
102
|
+
// We don't have the type in our local data types, so we try to fetch it from the web
|
|
103
|
+
schema = await FetchHelper.fetchJson(JsonSchemaHelper._CLASS_NAME, uri, HttpMethod.GET, undefined, {
|
|
104
|
+
headers: {
|
|
105
|
+
Accept: acceptableMediaTypes()
|
|
106
|
+
},
|
|
107
|
+
// Cache for an hour
|
|
108
|
+
cacheTtlMs: 3600000
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
catch { }
|
|
105
112
|
}
|
|
113
|
+
// Failed to load remotely so return an empty object
|
|
114
|
+
// so the schema validation doesn't completely fail
|
|
115
|
+
loadedSchema ??= {};
|
|
116
|
+
return {
|
|
117
|
+
status: 200,
|
|
118
|
+
statusText: "OK",
|
|
119
|
+
ok: true,
|
|
120
|
+
url: uri,
|
|
121
|
+
headers: new Headers({
|
|
122
|
+
"Content-Type": "application/schema+json"
|
|
123
|
+
}),
|
|
124
|
+
json: Promise.resolve(loadedSchema)
|
|
125
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
126
|
+
};
|
|
106
127
|
}
|
|
107
|
-
}
|
|
108
|
-
|
|
128
|
+
};
|
|
129
|
+
addUriSchemePlugin("https", httpSchemePlugin);
|
|
130
|
+
addUriSchemePlugin("http", httpSchemePlugin);
|
|
109
131
|
// Add the additional types provided by the user
|
|
110
132
|
if (Is.objectValue(additionalTypes)) {
|
|
111
133
|
for (const key in additionalTypes) {
|
|
112
|
-
|
|
134
|
+
additionalTypes[key].$schema =
|
|
135
|
+
additionalTypes[key].$schema ?? JsonSchemaHelper.SCHEMA_VERSION;
|
|
136
|
+
const additionalType = key.startsWith("http")
|
|
137
|
+
? key
|
|
138
|
+
: `${JsonSchemaHelper._PRIVATE_PREFIX}${key}`;
|
|
139
|
+
registerSchema(additionalTypes[key], additionalType);
|
|
113
140
|
}
|
|
114
141
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
const output =
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
142
|
+
schema.$schema = schema.$schema ?? JsonSchemaHelper.SCHEMA_VERSION;
|
|
143
|
+
registerSchema(schema, JsonSchemaHelper._PRIVATE_TYPE);
|
|
144
|
+
const output = await validate(JsonSchemaHelper._PRIVATE_TYPE, data, "DETAILED");
|
|
145
|
+
await this.cleanupOutput(output);
|
|
146
|
+
await this.formatErrors(output, data);
|
|
147
|
+
unregisterSchema(JsonSchemaHelper._PRIVATE_TYPE);
|
|
148
|
+
// Remove the additional types provided by the user
|
|
149
|
+
if (Is.objectValue(additionalTypes)) {
|
|
150
|
+
for (const key in additionalTypes) {
|
|
151
|
+
const additionalType = key.startsWith("http")
|
|
152
|
+
? key
|
|
153
|
+
: `${JsonSchemaHelper._PRIVATE_PREFIX}${key}`;
|
|
154
|
+
unregisterSchema(additionalType);
|
|
155
|
+
}
|
|
122
156
|
}
|
|
123
|
-
return
|
|
157
|
+
return {
|
|
158
|
+
result: output.valid,
|
|
159
|
+
errors: output.errors
|
|
160
|
+
};
|
|
124
161
|
}
|
|
125
162
|
/**
|
|
126
163
|
* Get the property type from a schema.
|
|
@@ -129,9 +166,12 @@ class JsonSchemaHelper {
|
|
|
129
166
|
* @returns The types of the property.
|
|
130
167
|
*/
|
|
131
168
|
static getPropertyType(schema, propertyName) {
|
|
169
|
+
if (Is.boolean(schema)) {
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
132
172
|
if (schema.type === "object" && Is.objectValue(schema.properties)) {
|
|
133
173
|
const propertySchema = schema.properties[propertyName];
|
|
134
|
-
if (Is.
|
|
174
|
+
if (!Is.boolean(propertySchema) && !Is.empty(propertySchema)) {
|
|
135
175
|
if (Is.stringValue(propertySchema.$ref)) {
|
|
136
176
|
return propertySchema.$ref;
|
|
137
177
|
}
|
|
@@ -197,6 +237,41 @@ class JsonSchemaHelper {
|
|
|
197
237
|
additionalProperties: false
|
|
198
238
|
};
|
|
199
239
|
}
|
|
240
|
+
/**
|
|
241
|
+
* Cleanup the errors from the schema validation.
|
|
242
|
+
* @param outputUnit The errors to format.
|
|
243
|
+
* @param data The data that was validated.
|
|
244
|
+
* @returns The formatted errors.
|
|
245
|
+
*/
|
|
246
|
+
static async formatErrors(outputUnit, data) {
|
|
247
|
+
if (outputUnit.keyword === "https://json-schema.org/keyword/required") {
|
|
248
|
+
outputUnit.message = `The property '${outputUnit.instanceLocation}' is required but was not found.`;
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
outputUnit.message = `"${outputUnit.instanceLocation}" fails schema constraint ${outputUnit.absoluteKeywordLocation}`;
|
|
252
|
+
}
|
|
253
|
+
if (Is.arrayValue(outputUnit.errors)) {
|
|
254
|
+
for (const subError of outputUnit.errors) {
|
|
255
|
+
await this.formatErrors(subError, data);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Cleanup the errors from the schema validation.
|
|
261
|
+
* @param outputUnit The errors to format.
|
|
262
|
+
* @returns The formatted errors.
|
|
263
|
+
* @internal
|
|
264
|
+
*/
|
|
265
|
+
static async cleanupOutput(outputUnit) {
|
|
266
|
+
if (outputUnit.absoluteKeywordLocation?.startsWith(JsonSchemaHelper._PRIVATE_TYPE)) {
|
|
267
|
+
outputUnit.absoluteKeywordLocation = outputUnit.absoluteKeywordLocation.replace(JsonSchemaHelper._PRIVATE_TYPE, "");
|
|
268
|
+
}
|
|
269
|
+
if (Is.arrayValue(outputUnit.errors)) {
|
|
270
|
+
for (const subError of outputUnit.errors) {
|
|
271
|
+
await this.cleanupOutput(subError);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
200
275
|
}
|
|
201
276
|
|
|
202
277
|
// Copyright 2024 IOTA Stiftung.
|
|
@@ -240,14 +315,14 @@ class DataTypeHelper {
|
|
|
240
315
|
const schema = await handler.jsonSchema();
|
|
241
316
|
if (Is.object(schema)) {
|
|
242
317
|
const validationResult = await JsonSchemaHelper.validate(schema, data);
|
|
243
|
-
if (Is.arrayValue(validationResult.
|
|
318
|
+
if (Is.arrayValue(validationResult.errors)) {
|
|
244
319
|
validationFailures.push({
|
|
245
320
|
property: propertyName,
|
|
246
321
|
reason: "validation.schema.failedValidation",
|
|
247
322
|
properties: {
|
|
248
323
|
value: data,
|
|
249
|
-
schemaErrors: validationResult.
|
|
250
|
-
message: validationResult.
|
|
324
|
+
schemaErrors: validationResult.errors,
|
|
325
|
+
message: validationResult.errors.map(e => e.message).join("\n")
|
|
251
326
|
}
|
|
252
327
|
});
|
|
253
328
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,7 +2,8 @@ export * from "./factories/dataTypeHandlerFactory";
|
|
|
2
2
|
export * from "./factories/identifierHandlerFactory";
|
|
3
3
|
export * from "./models/IDataTypeHandler";
|
|
4
4
|
export * from "./models/IIdentifierHandler";
|
|
5
|
-
export * from "./models/
|
|
5
|
+
export * from "./models/IJsonSchema";
|
|
6
|
+
export * from "./models/ISchemaValidationErrors";
|
|
6
7
|
export * from "./models/ISchemaValidationResult";
|
|
7
8
|
export * from "./models/validationMode";
|
|
8
9
|
export * from "./utils/dataTypeHelper";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IValidationFailure } from "@twin.org/core";
|
|
2
|
-
import type {
|
|
2
|
+
import type { IJsonSchema } from "./IJsonSchema";
|
|
3
3
|
/**
|
|
4
4
|
* Interface describing a type which can handle a specific data type.
|
|
5
5
|
*/
|
|
@@ -20,7 +20,7 @@ export interface IDataTypeHandler {
|
|
|
20
20
|
* Get the JSON schema for the data type.
|
|
21
21
|
* @returns The JSON schema for the data type.
|
|
22
22
|
*/
|
|
23
|
-
jsonSchema?(): Promise<
|
|
23
|
+
jsonSchema?(): Promise<IJsonSchema | undefined>;
|
|
24
24
|
/**
|
|
25
25
|
* A method for validating the data type.
|
|
26
26
|
* @param propertyName The name of the property being validated.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ISchemaValidationErrors } from "./ISchemaValidationErrors";
|
|
2
2
|
/**
|
|
3
3
|
* Validation result.
|
|
4
4
|
*/
|
|
@@ -10,5 +10,5 @@ export interface ISchemaValidationResult {
|
|
|
10
10
|
/**
|
|
11
11
|
* The error.
|
|
12
12
|
*/
|
|
13
|
-
|
|
13
|
+
errors?: ISchemaValidationErrors;
|
|
14
14
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { type OutputUnit } from "@hyperjump/json-schema/draft-2020-12";
|
|
1
2
|
import type { IEntitySchema } from "@twin.org/entity";
|
|
2
|
-
import type {
|
|
3
|
+
import type { IJsonSchema } from "../models/IJsonSchema";
|
|
3
4
|
import type { ISchemaValidationResult } from "../models/ISchemaValidationResult";
|
|
4
5
|
/**
|
|
5
6
|
* A helper for JSON schemas.
|
|
@@ -16,8 +17,8 @@ export declare class JsonSchemaHelper {
|
|
|
16
17
|
* @param additionalTypes Additional types to add for reference, not already in DataTypeHandlerFactory.
|
|
17
18
|
* @returns Result containing errors if there are any.
|
|
18
19
|
*/
|
|
19
|
-
static validate<T = unknown>(schema:
|
|
20
|
-
[id: string]:
|
|
20
|
+
static validate<T = unknown>(schema: IJsonSchema, data: T, additionalTypes?: {
|
|
21
|
+
[id: string]: IJsonSchema;
|
|
21
22
|
}): Promise<ISchemaValidationResult>;
|
|
22
23
|
/**
|
|
23
24
|
* Get the property type from a schema.
|
|
@@ -25,12 +26,21 @@ export declare class JsonSchemaHelper {
|
|
|
25
26
|
* @param propertyName The name of the property to get the type for.
|
|
26
27
|
* @returns The types of the property.
|
|
27
28
|
*/
|
|
28
|
-
static getPropertyType(schema:
|
|
29
|
+
static getPropertyType(schema: IJsonSchema, propertyName: string): string | undefined;
|
|
29
30
|
/**
|
|
30
31
|
* Convert an entity schema to JSON schema e.g https://example.com/schemas/.
|
|
31
32
|
* @param entitySchema The entity schema to convert.
|
|
32
33
|
* @param baseDomain The base domain for local schemas e.g. https://example.com/
|
|
33
34
|
* @returns The JSON schema for the entity.
|
|
34
35
|
*/
|
|
35
|
-
static entitySchemaToJsonSchema(entitySchema: IEntitySchema | undefined, baseDomain?: string):
|
|
36
|
+
static entitySchemaToJsonSchema(entitySchema: IEntitySchema | undefined, baseDomain?: string): IJsonSchema;
|
|
37
|
+
/**
|
|
38
|
+
* Cleanup the errors from the schema validation.
|
|
39
|
+
* @param outputUnit The errors to format.
|
|
40
|
+
* @param data The data that was validated.
|
|
41
|
+
* @returns The formatted errors.
|
|
42
|
+
*/
|
|
43
|
+
static formatErrors<T>(outputUnit: OutputUnit & {
|
|
44
|
+
message?: string;
|
|
45
|
+
}, data: T): Promise<void>;
|
|
36
46
|
}
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# @twin.org/data-core - Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.1-next.36](https://github.com/twinfoundation/data/compare/data-core-v0.0.1-next.35...data-core-v0.0.1-next.36) (2025-06-10)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* expand Json LD Keyword ([70632d1](https://github.com/twinfoundation/data/commit/70632d1e11ad85cf3c57e118476b125a673f1681))
|
|
9
|
+
|
|
3
10
|
## [0.0.1-next.35](https://github.com/twinfoundation/data/compare/data-core-v0.0.1-next.34...data-core-v0.0.1-next.35) (2025-06-03)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -38,7 +38,7 @@ Validates data against the schema.
|
|
|
38
38
|
|
|
39
39
|
##### schema
|
|
40
40
|
|
|
41
|
-
`
|
|
41
|
+
`JsonSchemaDraft202012Object`
|
|
42
42
|
|
|
43
43
|
The schema to validate the data with.
|
|
44
44
|
|
|
@@ -70,7 +70,7 @@ Get the property type from a schema.
|
|
|
70
70
|
|
|
71
71
|
##### schema
|
|
72
72
|
|
|
73
|
-
`
|
|
73
|
+
`JsonSchemaDraft202012Object`
|
|
74
74
|
|
|
75
75
|
The schema to extract the types from.
|
|
76
76
|
|
|
@@ -90,7 +90,7 @@ The types of the property.
|
|
|
90
90
|
|
|
91
91
|
### entitySchemaToJsonSchema()
|
|
92
92
|
|
|
93
|
-
> `static` **entitySchemaToJsonSchema**(`entitySchema`, `baseDomain?`): `
|
|
93
|
+
> `static` **entitySchemaToJsonSchema**(`entitySchema`, `baseDomain?`): `JsonSchemaDraft202012Object`
|
|
94
94
|
|
|
95
95
|
Convert an entity schema to JSON schema e.g https://example.com/schemas/.
|
|
96
96
|
|
|
@@ -110,6 +110,40 @@ The base domain for local schemas e.g. https://example.com/
|
|
|
110
110
|
|
|
111
111
|
#### Returns
|
|
112
112
|
|
|
113
|
-
`
|
|
113
|
+
`JsonSchemaDraft202012Object`
|
|
114
114
|
|
|
115
115
|
The JSON schema for the entity.
|
|
116
|
+
|
|
117
|
+
***
|
|
118
|
+
|
|
119
|
+
### formatErrors()
|
|
120
|
+
|
|
121
|
+
> `static` **formatErrors**\<`T`\>(`outputUnit`, `data`): `Promise`\<`void`\>
|
|
122
|
+
|
|
123
|
+
Cleanup the errors from the schema validation.
|
|
124
|
+
|
|
125
|
+
#### Type Parameters
|
|
126
|
+
|
|
127
|
+
##### T
|
|
128
|
+
|
|
129
|
+
`T`
|
|
130
|
+
|
|
131
|
+
#### Parameters
|
|
132
|
+
|
|
133
|
+
##### outputUnit
|
|
134
|
+
|
|
135
|
+
`OutputUnit` & `object`
|
|
136
|
+
|
|
137
|
+
The errors to format.
|
|
138
|
+
|
|
139
|
+
##### data
|
|
140
|
+
|
|
141
|
+
`T`
|
|
142
|
+
|
|
143
|
+
The data that was validated.
|
|
144
|
+
|
|
145
|
+
#### Returns
|
|
146
|
+
|
|
147
|
+
`Promise`\<`void`\>
|
|
148
|
+
|
|
149
|
+
The formatted errors.
|
package/docs/reference/index.md
CHANGED
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
## Type Aliases
|
|
15
15
|
|
|
16
|
-
- [
|
|
16
|
+
- [IJsonSchema](type-aliases/IJsonSchema.md)
|
|
17
|
+
- [ISchemaValidationErrors](type-aliases/ISchemaValidationErrors.md)
|
|
17
18
|
- [ValidationMode](type-aliases/ValidationMode.md)
|
|
18
19
|
|
|
19
20
|
## Variables
|
|
@@ -30,13 +30,13 @@ The default value for the item to use when constructing a new object.
|
|
|
30
30
|
|
|
31
31
|
### jsonSchema()?
|
|
32
32
|
|
|
33
|
-
> `optional` **jsonSchema**(): `Promise`\<`undefined` \| `
|
|
33
|
+
> `optional` **jsonSchema**(): `Promise`\<`undefined` \| `JsonSchemaDraft202012Object`\>
|
|
34
34
|
|
|
35
35
|
Get the JSON schema for the data type.
|
|
36
36
|
|
|
37
37
|
#### Returns
|
|
38
38
|
|
|
39
|
-
`Promise`\<`undefined` \| `
|
|
39
|
+
`Promise`\<`undefined` \| `JsonSchemaDraft202012Object`\>
|
|
40
40
|
|
|
41
41
|
The JSON schema for the data type.
|
|
42
42
|
|
|
@@ -12,8 +12,8 @@ The result.
|
|
|
12
12
|
|
|
13
13
|
***
|
|
14
14
|
|
|
15
|
-
###
|
|
15
|
+
### errors?
|
|
16
16
|
|
|
17
|
-
> `optional` **
|
|
17
|
+
> `optional` **errors**: [`ISchemaValidationErrors`](../type-aliases/ISchemaValidationErrors.md)
|
|
18
18
|
|
|
19
19
|
The error.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/data-core",
|
|
3
|
-
"version": "0.0.1-next.
|
|
3
|
+
"version": "0.0.1-next.36",
|
|
4
4
|
"description": "Definitions and helpers for using with data and schemas",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -14,13 +14,12 @@
|
|
|
14
14
|
"node": ">=20.0.0"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
+
"@hyperjump/browser": "1.3.0",
|
|
18
|
+
"@hyperjump/json-schema": "1.15.0",
|
|
17
19
|
"@twin.org/core": "next",
|
|
18
20
|
"@twin.org/entity": "next",
|
|
19
21
|
"@twin.org/nameof": "next",
|
|
20
|
-
"@twin.org/web": "next"
|
|
21
|
-
"@types/json-schema": "7.0.15",
|
|
22
|
-
"ajv": "8.17.1",
|
|
23
|
-
"ajv-formats": "3.0.1"
|
|
22
|
+
"@twin.org/web": "next"
|
|
24
23
|
},
|
|
25
24
|
"main": "./dist/cjs/index.cjs",
|
|
26
25
|
"module": "./dist/esm/index.mjs",
|