diff --git a/package-lock.json b/package-lock.json index fac1e3f..e34d160 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,6 @@ "uid": "^2.0.2" }, "devDependencies": { - "@hyperjump/json-schema": "^1.10.0", "@types/cors": "^2.8.17", "@types/express": "^5.0.0", "@types/node": "^22.9.3", @@ -664,87 +663,6 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@hyperjump/browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@hyperjump/browser/-/browser-1.2.0.tgz", - "integrity": "sha512-xv7u4Ddbhnd9a4yi8V0bNYQrimL0SuBW2T+l4eSEKedxhIBVqxuZ6Vulm6+rPtcvg79LyhWxH4fB/J056qaSMQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@hyperjump/json-pointer": "^1.1.0", - "@hyperjump/uri": "^1.2.0", - "content-type": "^1.0.5", - "just-curry-it": "^5.3.0", - "type-is": "^1.6.18" - }, - "engines": { - "node": ">=18.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jdesrosiers" - } - }, - "node_modules/@hyperjump/json-pointer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@hyperjump/json-pointer/-/json-pointer-1.1.0.tgz", - "integrity": "sha512-tFCKxMKDKK3VEdtUA3EBOS9GmSOS4mbrTjh9v3RnK10BphDMOb6+bxTh++/ae1AyfHyWb6R54O/iaoAtPMZPCg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jdesrosiers" - } - }, - "node_modules/@hyperjump/json-schema": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@hyperjump/json-schema/-/json-schema-1.10.0.tgz", - "integrity": "sha512-OhtHN025zzbBrRm12LEmE1WBni0phS5wXakJtKLEAhc65abuaIiDHyqjpr4JqjoyiMXCc15Ozfiepj8sk+SleQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@hyperjump/json-pointer": "^1.1.0", - "@hyperjump/pact": "^1.2.0", - "@hyperjump/uri": "^1.2.0", - "content-type": "^1.0.4", - "json-stringify-deterministic": "^1.0.12", - "just-curry-it": "^5.3.0", - "uuid": "^9.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jdesrosiers" - }, - "peerDependencies": { - "@hyperjump/browser": "^1.1.0" - } - }, - "node_modules/@hyperjump/pact": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@hyperjump/pact/-/pact-1.3.0.tgz", - "integrity": "sha512-/UIKatOtyZ3kN4A7AQmqZKzg/6es9jKyeWbfrenb2rDb3I9W4ZrVZT8q1zDrI/G+849I6Eq0ybzV1mmEC9zoDg==", - "dev": true, - "license": "MIT", - "dependencies": { - "just-curry-it": "^5.3.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jdesrosiers" - } - }, - "node_modules/@hyperjump/uri": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@hyperjump/uri/-/uri-1.2.2.tgz", - "integrity": "sha512-Zn8AZb/j54KKUCckmcOzKCSCKpIpMVBc60zYaajD8Dq/1g4UN6TfAFi+uDa5o/6rf+I+5xDZjZpdzwfuhlC0xQ==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jdesrosiers" - } - }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -4106,16 +4024,6 @@ "dev": true, "license": "MIT" }, - "node_modules/json-stringify-deterministic": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/json-stringify-deterministic/-/json-stringify-deterministic-1.0.12.tgz", - "integrity": "sha512-q3PN0lbUdv0pmurkBNdJH3pfFvOTL/Zp0lquqpvcjfKzt6Y0j49EPHAmVHCAS4Ceq/Y+PejWTzyiVpoY71+D6g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -4129,13 +4037,6 @@ "node": ">=6" } }, - "node_modules/just-curry-it": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/just-curry-it/-/just-curry-it-5.3.0.tgz", - "integrity": "sha512-silMIRiFjUWlfaDhkgSzpuAyQ6EX/o09Eu8ZBfmFwQMbax7+LQzeIU2CBrICT6Ne4l86ITCGvUCBpCubWYy0Yw==", - "dev": true, - "license": "MIT" - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -6397,20 +6298,6 @@ "node": ">= 0.4.0" } }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index 165452a..05a0afe 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "uid": "^2.0.2" }, "devDependencies": { - "@hyperjump/json-schema": "^1.10.0", "@types/cors": "^2.8.17", "@types/express": "^5.0.0", "@types/node": "^22.9.3", diff --git a/schema/IndexResponse.schema.json b/schema/IndexResponse.schema.json index 73fce61..fa2096f 100644 --- a/schema/IndexResponse.schema.json +++ b/schema/IndexResponse.schema.json @@ -1,19 +1,12 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://example.com/grout-index", - "$defs": { - "index-data": { - "$dynamicAnchor": "TData", - "type": "object", - "properties": { - "versionx": { - "type": "string", - "pattern": "^[0-9]+.[0-9]+.[0-9]+$" - } - }, - "additionalProperties": false, - "required": ["versionx"] + "type": "object", + "properties": { + "version": { + "type": "string", + "pattern": "^[0-9]+.[0-9]+.[0-9]+$" } }, - "$ref": "https://example.com/grout-response" + "additionalProperties": false, + "required": ["version"] } \ No newline at end of file diff --git a/schema/MetadataResponse.schema.json b/schema/MetadataResponse.schema.json index 54c48fa..0e42f42 100644 --- a/schema/MetadataResponse.schema.json +++ b/schema/MetadataResponse.schema.json @@ -1,34 +1,28 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "data": { - "$dynamicAnchor": "TData", + "type": "object", + "properties": { + "datasets": { "type": "object", "properties": { - "datasets": { + "tile": { "type": "object", - "properties": { - "tile": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "levelsx": { - "type": "array", - "items": { "type": "string" } - } - }, - "required": ["levelsx"] + "additionalProperties": { + "type": "object", + "properties": { + "levels": { + "type": "array", + "items": { "type": "string" } } - } - }, - "additionalProperties": false, - "required": ["tile"] + }, + "required": ["levels"] + } } }, "additionalProperties": false, - "required": ["datasets"] + "required": ["tile"] } }, - "$ref": "grout-response" + "additionalProperties": false, + "required": ["datasets"] } \ No newline at end of file diff --git a/schema/Response.schema.json b/schema/Response.schema.json index e799a75..37d94e5 100644 --- a/schema/Response.schema.json +++ b/schema/Response.schema.json @@ -1,12 +1,5 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://example.com/grout-response", - "$defs": { - "content": { - "$dynamicAnchor": "TData", - "not": true - } - }, "type": "object", "properties": { "status": { @@ -42,7 +35,10 @@ } }, "data": { - "$dynamicRef": "#TData" + "oneOf": [ + { "type": "null" }, + { "type": "object" } + ] } }, "additionalProperties": false, diff --git a/tests/integration/integrationTest.ts b/tests/integration/integrationTest.ts index dfb4a28..d63e698 100644 --- a/tests/integration/integrationTest.ts +++ b/tests/integration/integrationTest.ts @@ -1,6 +1,5 @@ import request from "supertest"; import Ajv from "ajv/dist/2020" -import { registerSchema, validate } from "@hyperjump/json-schema/draft-2020-12"; import { expect } from "vitest"; export const grout = request("http://localhost:5000"); @@ -16,26 +15,22 @@ export const getData = async (url: string, schemaName: string) => { const ajv = new Ajv(); - const schema = await getSchema(schemaName); - ajv.addSchema(schema); + const responseSchema = await getSchema("Response"); // outer Response schema + //ajv.addSchema(responseSchema); - const responseSchema = await getSchema("Response"); // We always need the outer Response schema - ajv.addSchema(responseSchema); + const dataSchema = await getSchema(schemaName); + //ajv.addSchema(dataSchema); - registerSchema(responseSchema, "https://example.com/grout-response"); - registerSchema(schema, "https://example.com/grout-index"); + // First validate that the entire response conforms to the Response schema... + const responseValidate = ajv.compile(responseSchema); + expect(responseValidate(response.body), `Response schema errors: \n ${ajv.errorsText(responseValidate.errors)} \nfor response: \n${JSON.stringify(response.body, null, 2)}`).toBe(true); - const output = await validate("https://example.com/grout-index", response.body); - - - const valid = ajv.validate(schema, response.body); - //const validate = ajv.compile(schema); - //const valid = validate(response.body); - expect(valid, `Schema errors: \n ${JSON.stringify(ajv.errors)} \nfor response: \n${JSON.stringify(response.body, null, 2)}`).toBe(true); - - expect(output.valid, `Schema errors: ${JSON.stringify(output)}`).toBe(true); + // ...then that the data part matches the expected data schema + const dataValidate = ajv.compile(dataSchema); + const data = response.body.data; + expect(dataValidate(data), `Data schema errors: \n${ajv.errorsText(dataValidate.errors)} \nfor data: \n${JSON.stringify(data, null, 2)}`).toBe(true) expect(response.body.status).toBe("success"); expect(response.body.errors).toBe(null); - return response.body.data; + return data; };