From a8a8129e76401811a97f7ecbfa0458f171d7795b Mon Sep 17 00:00:00 2001 From: Jeremy Scheff Date: Thu, 23 Nov 2023 00:47:21 -0500 Subject: [PATCH] Warning if no version in league file --- src/worker/api/leagueFileUpload.ts | 36 ++++++++++++++++++++++++++---- tools/lib/generateJSONSchema.js | 2 ++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/worker/api/leagueFileUpload.ts b/src/worker/api/leagueFileUpload.ts index 6a66f6d1d9..fb5a27e4c2 100644 --- a/src/worker/api/leagueFileUpload.ts +++ b/src/worker/api/leagueFileUpload.ts @@ -10,7 +10,7 @@ import { helpers, toUI } from "../util"; import { highWaterMark } from "../core/league/createStream"; import type { Conditions } from "../../common/types"; import { toPolyfillReadable, toPolyfillTransform } from "bbgm-polyfills"; // eslint-disable-line -import { DEFAULT_TEAM_COLORS } from "../../common"; +import { DEFAULT_TEAM_COLORS, LEAGUE_DATABASE_VERSION } from "../../common"; // These objects (at the root of a league file) should be emitted as a complete object, rather than individual rows from an array export const CUMULATIVE_OBJECTS = new Set([ @@ -87,7 +87,13 @@ const makeValidators = () => { verbose: true, }); - const validators: Record = {}; + const validators: Record< + string, + { + required: boolean; + validate: ValidateFunction; + } + > = {}; const baseSchema = { $schema: schema.$schema, @@ -115,7 +121,10 @@ const makeValidators = () => { $id: `${baseSchema.$id}#${part}`, ...subset, }; - validators[part] = ajv.compile(partSchema); + validators[part] = { + required: schema.required.includes(part), + validate: ajv.compile(partSchema), + }; } return validators; @@ -166,6 +175,13 @@ const getBasicInfo = async ({ const reader = await stream.pipeThrough(parseJSON()).getReader(); + const requiredPartsNotYetSeen = new Set(); + for (const [key, { required }] of Object.entries(validators)) { + if (required) { + requiredPartsNotYetSeen.add(key); + } + } + while (true) { const { value, done } = (await reader.read()) as any; if (done) { @@ -191,11 +207,15 @@ const getBasicInfo = async ({ } if (validators[value.key]) { - const validate = validators[value.key]; + const { validate, required } = validators[value.key]; validate(value.value); if (validate.errors) { schemaErrors.push(...validate.errors); } + + if (required) { + requiredPartsNotYetSeen.delete(value.key); + } } if (value.key === "meta" && value.value.name) { @@ -245,6 +265,14 @@ const getBasicInfo = async ({ } } + for (const key of requiredPartsNotYetSeen) { + let message = `"${key}" is required in the root of a JSON file, but is missing.`; + if (key === "version") { + message += ` The latest version is ${LEAGUE_DATABASE_VERSION}, that's probably what you want if this is a new file you're making.`; + } + schemaErrors.push(message); + } + toUI( "updateLocal", [ diff --git a/tools/lib/generateJSONSchema.js b/tools/lib/generateJSONSchema.js index b7b2f74a6d..88ddb95bc7 100644 --- a/tools/lib/generateJSONSchema.js +++ b/tools/lib/generateJSONSchema.js @@ -506,6 +506,8 @@ const generateJSONSchema = (sport /*: string*/) => { type: "object", + required: ["version"], + properties: { version: { type: "integer",