@unispechq/unispec-core 0.2.8 → 0.2.9
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/validator/index.js +134 -34
- package/dist/validator/index.d.ts +14 -2
- package/dist/validator/index.js +101 -34
- package/package.json +1 -1
|
@@ -1,4 +1,37 @@
|
|
|
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
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
@@ -6,32 +39,91 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
39
|
exports.validateUniSpec = validateUniSpec;
|
|
7
40
|
exports.validateUniSpecTests = validateUniSpecTests;
|
|
8
41
|
const _2020_js_1 = __importDefault(require("ajv/dist/2020.js"));
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
42
|
+
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
|
+
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 ?? {};
|
|
22
74
|
const typeSchemaPaths = Object.values(types).map((rel) => String(rel));
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
unispec: unispec,
|
|
92
|
+
unispecTests,
|
|
93
|
+
subschemas: subschemas.filter((s) => Boolean(s)),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function createAjv(options) {
|
|
97
|
+
const ajv = new _2020_js_1.default({
|
|
98
|
+
allErrors: true,
|
|
99
|
+
strict: true,
|
|
100
|
+
...(options.ajvOptions ?? {}),
|
|
101
|
+
});
|
|
102
|
+
ajv.addFormat("uri", true);
|
|
103
|
+
return ajv;
|
|
28
104
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
105
|
+
async function getValidator(options = {}) {
|
|
106
|
+
if (cached && !options.schemas && !options.schemaProvider && !options.ajvOptions)
|
|
107
|
+
return cached;
|
|
108
|
+
const schemas = options.schemas ?? (await loadDefaultSchemas());
|
|
109
|
+
const ajv = createAjv(options);
|
|
110
|
+
if (schemas.subschemas?.length) {
|
|
111
|
+
ajv.addSchema(schemas.subschemas);
|
|
112
|
+
}
|
|
113
|
+
const validateUniSpecFn = ajv.compile(schemas.unispec);
|
|
114
|
+
let validateUniSpecTestsFn;
|
|
115
|
+
if (schemas.unispecTests) {
|
|
116
|
+
validateUniSpecTestsFn = ajv.compile(schemas.unispecTests);
|
|
117
|
+
}
|
|
118
|
+
const result = {
|
|
119
|
+
validateUniSpecFn,
|
|
120
|
+
validateUniSpecTestsFn,
|
|
121
|
+
};
|
|
122
|
+
if (!options.schemas && !options.schemaProvider && !options.ajvOptions) {
|
|
123
|
+
cached = result;
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
32
126
|
}
|
|
33
|
-
const validateFn = ajv.compile(unispec_schema_1.unispec);
|
|
34
|
-
let validateTestsFn;
|
|
35
127
|
function mapAjvErrors(errors) {
|
|
36
128
|
if (!errors)
|
|
37
129
|
return [];
|
|
@@ -44,7 +136,8 @@ function mapAjvErrors(errors) {
|
|
|
44
136
|
/**
|
|
45
137
|
* Validate a UniSpec document against the UniSpec JSON Schema.
|
|
46
138
|
*/
|
|
47
|
-
async function validateUniSpec(doc,
|
|
139
|
+
async function validateUniSpec(doc, options = {}) {
|
|
140
|
+
const { validateUniSpecFn } = await getValidator(options);
|
|
48
141
|
const docForValidation = {
|
|
49
142
|
unispecVersion: "0.0.0",
|
|
50
143
|
service: {
|
|
@@ -56,7 +149,7 @@ async function validateUniSpec(doc, _options = {}) {
|
|
|
56
149
|
},
|
|
57
150
|
extensions: doc.extensions,
|
|
58
151
|
};
|
|
59
|
-
const valid =
|
|
152
|
+
const valid = validateUniSpecFn(docForValidation);
|
|
60
153
|
if (valid) {
|
|
61
154
|
return {
|
|
62
155
|
valid: true,
|
|
@@ -65,20 +158,27 @@ async function validateUniSpec(doc, _options = {}) {
|
|
|
65
158
|
}
|
|
66
159
|
return {
|
|
67
160
|
valid: false,
|
|
68
|
-
errors: mapAjvErrors(
|
|
161
|
+
errors: mapAjvErrors(validateUniSpecFn.errors),
|
|
69
162
|
};
|
|
70
163
|
}
|
|
71
164
|
/**
|
|
72
165
|
* Validate a UniSpec Tests document against the UniSpec Tests JSON Schema.
|
|
73
166
|
*/
|
|
74
|
-
async function validateUniSpecTests(doc,
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
167
|
+
async function validateUniSpecTests(doc, options = {}) {
|
|
168
|
+
const { validateUniSpecTestsFn } = await getValidator(options);
|
|
169
|
+
if (!validateUniSpecTestsFn) {
|
|
170
|
+
return {
|
|
171
|
+
valid: false,
|
|
172
|
+
errors: [
|
|
173
|
+
{
|
|
174
|
+
message: "UniSpec tests validation schema is not available. Provide ValidateOptions.schemas.unispecTests or a schemaProvider that can load it.",
|
|
175
|
+
path: "",
|
|
176
|
+
code: "schema_missing",
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
};
|
|
80
180
|
}
|
|
81
|
-
const valid =
|
|
181
|
+
const valid = validateUniSpecTestsFn(doc);
|
|
82
182
|
if (valid) {
|
|
83
183
|
return {
|
|
84
184
|
valid: true,
|
|
@@ -87,6 +187,6 @@ async function validateUniSpecTests(doc, _options = {}) {
|
|
|
87
187
|
}
|
|
88
188
|
return {
|
|
89
189
|
valid: false,
|
|
90
|
-
errors: mapAjvErrors(
|
|
190
|
+
errors: mapAjvErrors(validateUniSpecTestsFn.errors),
|
|
91
191
|
};
|
|
92
192
|
}
|
|
@@ -1,11 +1,23 @@
|
|
|
1
|
+
import Ajv2020 from "ajv/dist/2020.js";
|
|
1
2
|
import { UniSpecDocument, UniSpecTestsDocument, ValidationResult } from "../types";
|
|
3
|
+
export interface SchemaProvider {
|
|
4
|
+
getSchema: (schemaPath: string) => Promise<object>;
|
|
5
|
+
}
|
|
6
|
+
export interface ValidatorSchemas {
|
|
7
|
+
unispec: object;
|
|
8
|
+
unispecTests?: object;
|
|
9
|
+
subschemas?: object[];
|
|
10
|
+
}
|
|
2
11
|
export interface ValidateOptions {
|
|
12
|
+
schemas?: ValidatorSchemas;
|
|
13
|
+
schemaProvider?: SchemaProvider;
|
|
14
|
+
ajvOptions?: ConstructorParameters<typeof Ajv2020>[0];
|
|
3
15
|
}
|
|
4
16
|
/**
|
|
5
17
|
* Validate a UniSpec document against the UniSpec JSON Schema.
|
|
6
18
|
*/
|
|
7
|
-
export declare function validateUniSpec(doc: UniSpecDocument,
|
|
19
|
+
export declare function validateUniSpec(doc: UniSpecDocument, options?: ValidateOptions): Promise<ValidationResult>;
|
|
8
20
|
/**
|
|
9
21
|
* Validate a UniSpec Tests document against the UniSpec Tests JSON Schema.
|
|
10
22
|
*/
|
|
11
|
-
export declare function validateUniSpecTests(doc: UniSpecTestsDocument,
|
|
23
|
+
export declare function validateUniSpecTests(doc: UniSpecTestsDocument, options?: ValidateOptions): Promise<ValidationResult>;
|
package/dist/validator/index.js
CHANGED
|
@@ -1,30 +1,89 @@
|
|
|
1
1
|
import Ajv2020 from "ajv/dist/2020.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
2
|
+
let cached = null;
|
|
3
|
+
async function tryCreateNodeSchemaProvider() {
|
|
4
|
+
try {
|
|
5
|
+
const fs = await import("node:fs/promises");
|
|
6
|
+
const path = await import("node:path");
|
|
7
|
+
const module = await import("node:module");
|
|
8
|
+
const requireBasePath = typeof __filename === "string" && __filename.length > 0
|
|
9
|
+
? __filename
|
|
10
|
+
: path.join(process.cwd(), "__unispec_core_require__.js");
|
|
11
|
+
const require = module.createRequire(requireBasePath);
|
|
12
|
+
const schemaIndexPath = require.resolve("@unispechq/unispec-schema/schema");
|
|
13
|
+
const schemaRoot = path.dirname(schemaIndexPath);
|
|
14
|
+
return {
|
|
15
|
+
getSchema: async (schemaPath) => {
|
|
16
|
+
const fullPath = path.join(schemaRoot, schemaPath);
|
|
17
|
+
const json = await fs.readFile(fullPath, "utf8");
|
|
18
|
+
return JSON.parse(json);
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async function loadDefaultSchemas() {
|
|
27
|
+
const schemaProvider = await tryCreateNodeSchemaProvider();
|
|
28
|
+
if (!schemaProvider) {
|
|
29
|
+
throw new Error("UniSpec validator: default schema loading is not available in this environment. " +
|
|
30
|
+
"Provide ValidateOptions.schemas (recommended for browsers/edge runtimes) or ValidateOptions.schemaProvider.");
|
|
31
|
+
}
|
|
32
|
+
const { manifest, unispec } = (await import("@unispechq/unispec-schema"));
|
|
33
|
+
const types = manifest?.types ?? {};
|
|
15
34
|
const typeSchemaPaths = Object.values(types).map((rel) => String(rel));
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
35
|
+
const subschemas = await Promise.all(typeSchemaPaths.map(async (relPath) => {
|
|
36
|
+
try {
|
|
37
|
+
return await schemaProvider.getSchema(relPath);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}));
|
|
43
|
+
let unispecTests;
|
|
44
|
+
try {
|
|
45
|
+
unispecTests = await schemaProvider.getSchema("unispec-tests.schema.json");
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
unispecTests = undefined;
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
unispec: unispec,
|
|
52
|
+
unispecTests,
|
|
53
|
+
subschemas: subschemas.filter((s) => Boolean(s)),
|
|
54
|
+
};
|
|
21
55
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
56
|
+
function createAjv(options) {
|
|
57
|
+
const ajv = new Ajv2020({
|
|
58
|
+
allErrors: true,
|
|
59
|
+
strict: true,
|
|
60
|
+
...(options.ajvOptions ?? {}),
|
|
61
|
+
});
|
|
62
|
+
ajv.addFormat("uri", true);
|
|
63
|
+
return ajv;
|
|
64
|
+
}
|
|
65
|
+
async function getValidator(options = {}) {
|
|
66
|
+
if (cached && !options.schemas && !options.schemaProvider && !options.ajvOptions)
|
|
67
|
+
return cached;
|
|
68
|
+
const schemas = options.schemas ?? (await loadDefaultSchemas());
|
|
69
|
+
const ajv = createAjv(options);
|
|
70
|
+
if (schemas.subschemas?.length) {
|
|
71
|
+
ajv.addSchema(schemas.subschemas);
|
|
72
|
+
}
|
|
73
|
+
const validateUniSpecFn = ajv.compile(schemas.unispec);
|
|
74
|
+
let validateUniSpecTestsFn;
|
|
75
|
+
if (schemas.unispecTests) {
|
|
76
|
+
validateUniSpecTestsFn = ajv.compile(schemas.unispecTests);
|
|
77
|
+
}
|
|
78
|
+
const result = {
|
|
79
|
+
validateUniSpecFn,
|
|
80
|
+
validateUniSpecTestsFn,
|
|
81
|
+
};
|
|
82
|
+
if (!options.schemas && !options.schemaProvider && !options.ajvOptions) {
|
|
83
|
+
cached = result;
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
25
86
|
}
|
|
26
|
-
const validateFn = ajv.compile(unispecSchema);
|
|
27
|
-
let validateTestsFn;
|
|
28
87
|
function mapAjvErrors(errors) {
|
|
29
88
|
if (!errors)
|
|
30
89
|
return [];
|
|
@@ -37,7 +96,8 @@ function mapAjvErrors(errors) {
|
|
|
37
96
|
/**
|
|
38
97
|
* Validate a UniSpec document against the UniSpec JSON Schema.
|
|
39
98
|
*/
|
|
40
|
-
export async function validateUniSpec(doc,
|
|
99
|
+
export async function validateUniSpec(doc, options = {}) {
|
|
100
|
+
const { validateUniSpecFn } = await getValidator(options);
|
|
41
101
|
const docForValidation = {
|
|
42
102
|
unispecVersion: "0.0.0",
|
|
43
103
|
service: {
|
|
@@ -49,7 +109,7 @@ export async function validateUniSpec(doc, _options = {}) {
|
|
|
49
109
|
},
|
|
50
110
|
extensions: doc.extensions,
|
|
51
111
|
};
|
|
52
|
-
const valid =
|
|
112
|
+
const valid = validateUniSpecFn(docForValidation);
|
|
53
113
|
if (valid) {
|
|
54
114
|
return {
|
|
55
115
|
valid: true,
|
|
@@ -58,20 +118,27 @@ export async function validateUniSpec(doc, _options = {}) {
|
|
|
58
118
|
}
|
|
59
119
|
return {
|
|
60
120
|
valid: false,
|
|
61
|
-
errors: mapAjvErrors(
|
|
121
|
+
errors: mapAjvErrors(validateUniSpecFn.errors),
|
|
62
122
|
};
|
|
63
123
|
}
|
|
64
124
|
/**
|
|
65
125
|
* Validate a UniSpec Tests document against the UniSpec Tests JSON Schema.
|
|
66
126
|
*/
|
|
67
|
-
export async function validateUniSpecTests(doc,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
127
|
+
export async function validateUniSpecTests(doc, options = {}) {
|
|
128
|
+
const { validateUniSpecTestsFn } = await getValidator(options);
|
|
129
|
+
if (!validateUniSpecTestsFn) {
|
|
130
|
+
return {
|
|
131
|
+
valid: false,
|
|
132
|
+
errors: [
|
|
133
|
+
{
|
|
134
|
+
message: "UniSpec tests validation schema is not available. Provide ValidateOptions.schemas.unispecTests or a schemaProvider that can load it.",
|
|
135
|
+
path: "",
|
|
136
|
+
code: "schema_missing",
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
};
|
|
73
140
|
}
|
|
74
|
-
const valid =
|
|
141
|
+
const valid = validateUniSpecTestsFn(doc);
|
|
75
142
|
if (valid) {
|
|
76
143
|
return {
|
|
77
144
|
valid: true,
|
|
@@ -80,6 +147,6 @@ export async function validateUniSpecTests(doc, _options = {}) {
|
|
|
80
147
|
}
|
|
81
148
|
return {
|
|
82
149
|
valid: false,
|
|
83
|
-
errors: mapAjvErrors(
|
|
150
|
+
errors: mapAjvErrors(validateUniSpecTestsFn.errors),
|
|
84
151
|
};
|
|
85
152
|
}
|
package/package.json
CHANGED