Skip to content

Commit 099c14a

Browse files
authored
Improve schema for Time object to generate better TS types (#35)
* improve schema for Time object to generate better TS types * improve tests to report validation errors * fix small issue with test script * remove top-level additionalProperties: false from time type to avoid issues with oneOf * add test for comparing version strings in schema/package files * bump version in schema.json
1 parent a86786f commit 099c14a

File tree

4 files changed

+70
-32
lines changed

4 files changed

+70
-32
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@nasa-jpl/seq-json-schema",
3-
"version": "1.3.0",
3+
"version": "1.3.1",
44
"license": "MIT",
55
"type": "module",
66
"repository": {

schema.json

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"$id": "https://github.com/NASA-AMMOS/seq-json-schema/tree/v1.3.0",
2+
"$id": "https://github.com/NASA-AMMOS/seq-json-schema/tree/v1.3.1",
33
"$schema": "https://json-schema.org/draft/2020-12/schema",
44
"$defs": {
55
"immediate_activate": {
@@ -475,32 +475,33 @@
475475
"type": "object"
476476
},
477477
"time": {
478-
"additionalProperties": false,
479478
"description": "Time object",
480-
"properties": {
481-
"tag": {
482-
"description": "Relative or absolute time. Required for ABSOLUTE, BLOCK_RELATIVE, COMMAND_RELATIVE, and EPOCH_RELATIVE time types but not COMMAND_COMPLETE.",
483-
"type": "string"
479+
"oneOf": [
480+
{
481+
"additionalProperties": false,
482+
"properties": {
483+
"type": {
484+
"description": "Allowed time types without a tag: COMMAND_COMPLETE",
485+
"enum": ["COMMAND_COMPLETE"],
486+
"type": "string"
487+
}
488+
},
489+
"required": ["type"]
484490
},
485-
"type": {
486-
"description": "Allowed time types: ABSOLUTE, BLOCK_RELATIVE, COMMAND_RELATIVE, EPOCH_RELATIVE, or COMMAND_COMPLETE.",
487-
"enum": ["ABSOLUTE", "BLOCK_RELATIVE", "COMMAND_RELATIVE", "EPOCH_RELATIVE", "COMMAND_COMPLETE"],
488-
"type": "string"
489-
}
490-
},
491-
"required": ["type"],
492-
"allOf": [
493491
{
494-
"if": {
495-
"properties": {
496-
"type": {
497-
"enum": ["ABSOLUTE", "BLOCK_RELATIVE", "COMMAND_RELATIVE", "EPOCH_RELATIVE"]
498-
}
492+
"additionalProperties": false,
493+
"properties": {
494+
"type": {
495+
"description": "Allowed time types with a tag: ABSOLUTE, BLOCK_RELATIVE, COMMAND_RELATIVE, EPOCH_RELATIVE.",
496+
"enum": ["ABSOLUTE", "BLOCK_RELATIVE", "COMMAND_RELATIVE", "EPOCH_RELATIVE"],
497+
"type": "string"
498+
},
499+
"tag": {
500+
"description": "Relative or absolute time. Required for ABSOLUTE, BLOCK_RELATIVE, COMMAND_RELATIVE, and EPOCH_RELATIVE time types but not COMMAND_COMPLETE.",
501+
"type": "string"
499502
}
500503
},
501-
"then": {
502-
"required": ["tag"]
503-
}
504+
"required": ["type", "tag"]
504505
}
505506
],
506507
"type": "object"

test/test.js

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,69 @@ import Ajv from 'ajv/dist/2020.js';
22
import schema from '../schema.json' assert { type: 'json' };
33
import { readdirSync, readFileSync } from 'fs';
44
import { exit } from 'process';
5+
import packageJson from '../package.json' assert { type: 'json' };
6+
import lockfileJson from '../package-lock.json' assert { type: 'json' };
7+
8+
function testVersions(failures) {
9+
// Make sure version strings match
10+
const schemaId = schema.$id;
11+
const versionMatch = schemaId.match(/\/v(\d+\.\d+\.\d+)$/);
12+
if(!versionMatch) throw "Cannot find version in schema.json $id field";
13+
const schemaVersion = versionMatch ? versionMatch[1] : null;
14+
15+
const packageVersion = packageJson.version;
16+
const lockfileVersion = lockfileJson.version;
17+
18+
if(schemaVersion !== packageVersion || schemaVersion !== lockfileVersion) {
19+
const msg = "Versions in schema.json, package.json and package-lock.json must match";
20+
failures.push(msg);
21+
console.error(`❌ ${msg}`);
22+
console.log(`schema version in schema.$id: ${schemaVersion}`);
23+
console.log(`package.json version: ${packageVersion}`);
24+
console.log(`package-lock.json version: ${lockfileVersion}`);
25+
}
26+
}
527

628
function test() {
7-
const validate = new Ajv({ strict: false }).compile(schema);
29+
const ajv = new Ajv({
30+
strict: false,
31+
verbose: true,
32+
});
33+
const validate = ajv.compile(schema);
834
const validSeqJsonPath = './test/valid-seq-json';
935
const validSeqJsonFiles = readdirSync(validSeqJsonPath);
1036
const invalidSeqJsonPath = './test/invalid-seq-json';
1137
const invalidSeqJsonFiles = readdirSync(invalidSeqJsonPath);
12-
const errors = [];
38+
const failures = [];
39+
40+
testVersions(failures);
1341

1442
// Valid Seq JSON.
1543
for (const validSeqJsonFile of validSeqJsonFiles) {
1644
const validSeqJson = readFileSync(`${validSeqJsonPath}/${validSeqJsonFile}`).toString();
1745
const valid = validate(JSON.parse(validSeqJson));
18-
if (!valid) errors.push(`${validSeqJsonFile} should be valid`);
46+
if (!valid) {
47+
// most relevant errors tend to be at the bottom - reverse list
48+
const errors = validate.errors.slice().reverse();
49+
console.error(`❌ Failed to validate ${validSeqJsonFile} - ${errors.length} errors:`);
50+
console.log(errors);
51+
failures.push(`${validSeqJsonFile} should be valid`);
52+
}
1953
}
2054

2155
// Invalid Seq JSON.
2256
for (const invalidSeqJsonFile of invalidSeqJsonFiles) {
2357
const invalidSeqJson = readFileSync(`${invalidSeqJsonPath}/${invalidSeqJsonFile}`).toString();
2458
const valid = validate(JSON.parse(invalidSeqJson));
25-
if (valid) errors.push(`${invalidSeqJsonFile} should be invalid`);
59+
if (valid) {
60+
console.error(`❌ Failed to invalidate ${invalidSeqJsonFile} - expected errors`);
61+
failures.push(`${invalidSeqJsonFile} should be invalid`);
62+
}
2663
}
2764

28-
if (errors.length) {
29-
console.log('❌ Some tests failed...');
30-
console.error(errors);
65+
if (failures.length) {
66+
console.log(`❌ ${failures.length} tests failed...`);
67+
console.error(failures);
3168
exit(1);
3269
} else {
3370
console.log('✅ All tests passed!');

0 commit comments

Comments
 (0)