skir-codemirror-plugin 1.0.3 → 1.0.5

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.
@@ -168,7 +168,8 @@ class SchemaValidator {
168
168
  // Enum
169
169
  const nameToVariantDef = {};
170
170
  recordDef.variants.forEach((variant) => {
171
- nameToVariantDef[variant.name] = variant;
171
+ nameToVariantDef[variant.name.toLowerCase()] = variant;
172
+ nameToVariantDef[variant.name.toUpperCase()] = variant;
172
173
  });
173
174
  if (value.kind === "object") {
174
175
  pushTypeHint();
@@ -182,10 +183,10 @@ class SchemaValidator {
182
183
  this.errors.push({
183
184
  kind: "error",
184
185
  segment: value.segment,
185
- message: "Expected: uppercase variant name",
186
+ message: "Expected: constant variant",
186
187
  });
187
188
  }
188
- else if (name === "UNKNOWN" || fieldDef) {
189
+ else if (name === "unknown" || name === "UNKNOWN" || fieldDef) {
189
190
  pushTypeHint({ enumDefinition: recordDef });
190
191
  typeHintStack.pop();
191
192
  }
@@ -232,22 +233,21 @@ class SchemaValidator {
232
233
  return;
233
234
  }
234
235
  const kind = JSON.parse(kindKv.value.jsonCode);
235
- if (kind !== kind.toLowerCase()) {
236
+ const variantDef = nameToVariantDef[kind];
237
+ if (!variantDef) {
236
238
  this.errors.push({
237
239
  kind: "error",
238
240
  segment: kindKv.value.segment,
239
- message: "Expected: lowercase variant name",
241
+ message: "Unknown variant",
240
242
  });
241
243
  return;
242
244
  }
243
- const variantDef = nameToVariantDef[kind];
244
- if (!variantDef) {
245
+ else if (variantDef.type === undefined) {
245
246
  this.errors.push({
246
247
  kind: "error",
247
248
  segment: kindKv.value.segment,
248
- message: "Unknown variant",
249
+ message: "Expected: wrapper variant",
249
250
  });
250
- return;
251
251
  }
252
252
  const valueKv = object.keyValues["value"];
253
253
  if (!valueKv) {
@@ -1 +1 @@
1
- {"version":3,"file":"schema_validator.js","sourceRoot":"","sources":["../../src/json/schema_validator.ts"],"names":[],"mappings":"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","sourcesContent":["import { primitiveSerializer } from \"skir-client\";\nimport { toJson } from \"./to_json\";\nimport type {\n EnumDefinition,\n FieldDefinition,\n Hint,\n JsonError,\n JsonObject,\n JsonValue,\n MutableTypeHint,\n Path,\n PrimitiveType,\n RecordDefinition,\n TypeDefinition,\n TypeHint,\n TypeSignature,\n ValidationResult,\n VariantDefinition,\n} from \"./types\";\n\nexport function validateSchema(\n value: JsonValue,\n schema: TypeDefinition,\n): ValidationResult {\n const idToRecordDef: { [id: string]: RecordDefinition } = {};\n for (const record of schema.records) {\n idToRecordDef[record.id] = record;\n }\n\n const validator = new SchemaValidator(idToRecordDef);\n const root: Path = { kind: \"root\" };\n validator.validate(value, root, schema.type);\n const pathToTypeHint = new Map<Path, TypeHint>();\n for (const hint of validator.hints) {\n const { valueContext } = hint;\n if (valueContext) {\n pathToTypeHint.set(valueContext.path, hint);\n }\n }\n return {\n errors: validator.errors,\n hints: validator.hints,\n rootTypeHint: validator.rootTypeHint,\n pathToTypeHint: pathToTypeHint,\n };\n}\n\nclass SchemaValidator {\n constructor(readonly idToRecordDef: { [id: string]: RecordDefinition }) {}\n readonly errors: JsonError[] = [];\n readonly hints: Hint[] = [];\n private readonly typeHintStack: MutableTypeHint[] = [];\n rootTypeHint: TypeHint | undefined;\n\n validate(\n value: JsonValue,\n path: Path,\n schema: TypeSignature,\n optionalSchema?: TypeSignature,\n ): void {\n const { idToRecordDef, typeHintStack } = this;\n value.expectedType = schema;\n // For every call to pushTypeHint() there emust be one call to typeHintStack.pop()\n const pushTypeHint = (options?: {\n enumDefinition?: EnumDefinition;\n }): void => {\n const typeDesc = getTypeDesc(optionalSchema ?? schema);\n const typeDoc = getTypeDoc(schema, idToRecordDef);\n const message = [typeDesc];\n if (typeDoc) {\n message.push(typeDoc);\n }\n if (value.kind === \"array\") {\n const { length } = value.values;\n if (length) {\n message.push(`Length: ${length}`);\n }\n }\n const hint: MutableTypeHint = {\n segment: value.firstToken,\n message: message.length === 1 ? message[0] : message,\n valueContext: { value, path },\n childHints: [],\n enumDefinition: options?.enumDefinition,\n };\n if (typeHintStack.length) {\n const topOfStack = typeHintStack[typeHintStack.length - 1];\n topOfStack.childHints.push(hint);\n } else {\n this.rootTypeHint = hint;\n }\n this.hints.push(hint);\n typeHintStack.push(hint);\n };\n switch (schema.kind) {\n case \"array\": {\n if (value.kind === \"array\") {\n pushTypeHint();\n for (const [index, item] of value.values.entries()) {\n const { key_extractor: keyExtractor, item: itemSchema } =\n schema.value;\n const itemKey = extractItemKey(item, keyExtractor);\n const itemPath: Path = {\n kind: \"array-item\",\n index: index,\n key: itemKey,\n arrayPath: path,\n };\n this.validate(item, itemPath, itemSchema);\n }\n typeHintStack.pop();\n } else {\n this.errors.push({\n kind: \"error\",\n segment: value.segment,\n message: \"Expected: array\",\n });\n }\n break;\n }\n case \"optional\": {\n if (value.kind === \"literal\" && value.jsonCode === \"null\") {\n pushTypeHint();\n typeHintStack.pop();\n } else {\n this.validate(value, path, schema.value, schema);\n }\n break;\n }\n case \"primitive\": {\n const primitiveType = schema.value;\n if (primitiveType === \"timestamp\") {\n if (this.validateTimestamp(value)) {\n pushTypeHint();\n typeHintStack.pop();\n }\n } else if (hasPrimitiveType(value, primitiveType)) {\n pushTypeHint();\n typeHintStack.pop();\n } else {\n this.errors.push({\n kind: \"error\",\n segment: value.firstToken,\n message: `Expected: ${primitiveType}`,\n });\n }\n break;\n }\n case \"record\": {\n const recordDef = idToRecordDef[schema.value];\n if (recordDef.kind === \"struct\") {\n const nameToFieldDef: { [name: string]: FieldDefinition } = {};\n recordDef.fields.forEach((field) => {\n nameToFieldDef[field.name] = field;\n });\n if (value.kind === \"object\") {\n pushTypeHint();\n for (const keyValue of Object.values(value.keyValues)) {\n const { key, value } = keyValue;\n const fieldDef = nameToFieldDef[key];\n if (fieldDef) {\n if (fieldDef.doc) {\n this.hints.push({\n segment: keyValue.keySegment,\n message: fieldDef.doc,\n });\n }\n const valuePath: Path = {\n kind: \"field-value\",\n fieldName: key,\n structPath: path,\n };\n this.validate(value, valuePath, fieldDef.type!);\n } else {\n this.errors.push({\n kind: \"error\",\n segment: keyValue.keySegment,\n message: \"Unknown field\",\n });\n }\n }\n typeHintStack.pop();\n } else {\n this.errors.push({\n kind: \"error\",\n segment: value.firstToken,\n message: \"Expected: object\",\n });\n }\n } else {\n // Enum\n const nameToVariantDef: { [name: string]: VariantDefinition } = {};\n recordDef.variants.forEach((variant) => {\n nameToVariantDef[variant.name] = variant;\n });\n if (value.kind === \"object\") {\n pushTypeHint();\n this.validateEnumObject(value, path, nameToVariantDef);\n typeHintStack.pop();\n } else if (value.kind === \"literal\" && value.type === \"string\") {\n const name = JSON.parse(value.jsonCode);\n const fieldDef = nameToVariantDef[name];\n if (fieldDef && fieldDef.type) {\n this.errors.push({\n kind: \"error\",\n segment: value.segment,\n message: \"Expected: uppercase variant name\",\n });\n } else if (name === \"UNKNOWN\" || fieldDef) {\n pushTypeHint({ enumDefinition: recordDef });\n typeHintStack.pop();\n } else {\n this.errors.push({\n kind: \"error\",\n segment: value.segment,\n message: \"Unknown variant\",\n });\n }\n } else {\n this.errors.push({\n kind: \"error\",\n segment: value.firstToken,\n message: \"Expected: object or string\",\n });\n }\n }\n break;\n }\n default: {\n const _: never = schema;\n throw new Error(_);\n }\n }\n }\n\n validateEnumObject(\n object: JsonObject,\n enumPath: Path,\n nameToVariantDef: { [name: string]: VariantDefinition },\n ): void {\n const kindKv = object.keyValues[\"kind\"];\n if (!kindKv) {\n this.errors.push({\n kind: \"error\",\n segment: object.segment,\n message: \"Missing: 'kind'\",\n });\n return;\n }\n if (kindKv.value.kind !== \"literal\" || kindKv.value.type !== \"string\") {\n this.errors.push({\n kind: \"error\",\n segment: kindKv.value.firstToken,\n message: \"Expected: string\",\n });\n return;\n }\n const kind: string = JSON.parse(kindKv.value.jsonCode);\n if (kind !== kind.toLowerCase()) {\n this.errors.push({\n kind: \"error\",\n segment: kindKv.value.segment,\n message: \"Expected: lowercase variant name\",\n });\n return;\n }\n const variantDef = nameToVariantDef[kind];\n if (!variantDef) {\n this.errors.push({\n kind: \"error\",\n segment: kindKv.value.segment,\n message: \"Unknown variant\",\n });\n return;\n }\n const valueKv = object.keyValues[\"value\"];\n if (!valueKv) {\n this.errors.push({\n kind: \"error\",\n segment: object.segment,\n message: \"Missing: 'value'\",\n });\n return;\n }\n for (const key of object.allKeys) {\n if (key.key !== \"kind\" && key.key !== \"value\") {\n this.errors.push({\n kind: \"error\",\n segment: key.keySegment,\n message: \"Unexpected entry\",\n });\n }\n }\n const path: Path = {\n kind: \"variant-value\",\n variantName: variantDef.name,\n enumPath: enumPath,\n };\n this.validate(valueKv.value, path, variantDef.type!);\n }\n\n private validateTimestamp(value: JsonValue): boolean {\n if (value.kind !== \"object\") {\n this.errors.push({\n kind: \"error\",\n segment: value.firstToken,\n message: \"Expected: timestamp\",\n });\n return false;\n }\n const unixMillisKv = value.keyValues[\"unix_millis\"];\n if (!unixMillisKv) {\n this.errors.push({\n kind: \"error\",\n segment: value.firstToken,\n message: \"Missing: 'unix_millis'\",\n });\n return true;\n }\n if (\n unixMillisKv.value.kind !== \"literal\" ||\n unixMillisKv.value.type !== \"number\"\n ) {\n this.errors.push({\n kind: \"error\",\n segment: unixMillisKv.value.firstToken,\n message: \"Expected: number\",\n });\n return true;\n }\n const unixMillis = toJson(unixMillisKv.value) as number;\n if (unixMillis < -8640000000000000 || 8640000000000000 < unixMillis) {\n this.errors.push({\n kind: \"error\",\n segment: unixMillisKv.value.firstToken,\n message: \"Timestamp out of range\",\n });\n return true;\n }\n // At this point: the timestamp is technically valid.\n const formatted = value.keyValues[\"formatted\"];\n if (!formatted) {\n return true;\n }\n if (\n formatted.value.kind !== \"literal\" ||\n formatted.value.type !== \"string\"\n ) {\n this.errors.push({\n kind: \"error\",\n segment: formatted.value.firstToken,\n message: \"Expected: string\",\n });\n return true;\n }\n const formattedStr = toJson(formatted.value) as string;\n if (formattedStr === \"n/a\") {\n return true;\n }\n const parsedMillis = Date.parse(formattedStr);\n if (Number.isNaN(parsedMillis)) {\n this.errors.push({\n kind: \"error\",\n segment: formatted.value.firstToken,\n message: \"Invalid ISO 8601 date string\",\n });\n return true;\n }\n if (parsedMillis !== unixMillis) {\n this.errors.push({\n kind: \"error\",\n segment: formatted.value.firstToken,\n message: \"Does not match 'unix_millis'\",\n });\n }\n for (const key of value.allKeys) {\n if (key.key !== \"unix_millis\" && key.key !== \"formatted\") {\n this.errors.push({\n kind: \"error\",\n segment: key.keySegment,\n message: \"Unexpected entry\",\n });\n }\n }\n return true;\n }\n}\n\nfunction extractItemKey(\n item: JsonValue,\n keyExtractor: string | undefined,\n): string | null {\n if (keyExtractor === undefined) {\n return null;\n }\n const pieces = keyExtractor.split(\".\");\n let value = item;\n for (const piece of pieces) {\n if (value.kind !== \"object\") {\n // Error\n return null;\n }\n const kv = value.keyValues[piece];\n if (!kv) {\n // Error\n return null;\n }\n value = kv.value;\n }\n switch (value.kind) {\n case \"literal\": {\n switch (value.type) {\n case \"string\":\n case \"number\":\n case \"boolean\":\n return value.jsonCode;\n }\n // Error\n return null;\n }\n case \"object\": {\n const kv = value.keyValues[\"unix_millis\"];\n if (kv && kv.value.kind === \"literal\" && kv.value.type === \"number\") {\n return kv.value.jsonCode;\n } else {\n // Error\n return null;\n }\n }\n case \"array\": {\n // Error\n return null;\n }\n }\n}\n\nfunction hasPrimitiveType(\n value: JsonValue,\n expectedType: PrimitiveType,\n): boolean {\n switch (expectedType) {\n case \"bool\":\n return value.kind === \"literal\" && value.type === \"boolean\";\n case \"int32\": {\n return isInteger(value, -2147483648n, 2147483647n);\n }\n case \"int64\": {\n return isInteger(value, -9223372036854775808n, 9223372036854775807n);\n }\n case \"hash64\": {\n return isInteger(value, 0n, 18446744073709551615n);\n }\n case \"float32\":\n case \"float64\": {\n return isFloat(value);\n }\n case \"string\": {\n return value.kind === \"literal\" && value.type === \"string\";\n }\n case \"bytes\": {\n if (value.kind !== \"literal\") {\n return false;\n }\n try {\n primitiveSerializer(\"bytes\").fromJsonCode(value.jsonCode);\n return true;\n } catch {\n return false;\n }\n }\n case \"timestamp\": {\n // Case handled separately in validate()\n throw new Error();\n }\n }\n}\n\nfunction isInteger(value: JsonValue, min: bigint, max: bigint): boolean {\n if (value.kind !== \"literal\") {\n return false;\n }\n let decimalRep: string;\n if (value.type === \"string\") {\n decimalRep = JSON.parse(value.jsonCode);\n } else if (value.type === \"number\") {\n decimalRep = value.jsonCode;\n } else {\n return false;\n }\n let int: bigint;\n try {\n int = BigInt(decimalRep);\n } catch {\n return false;\n }\n return min <= int && int <= max;\n}\n\nfunction isFloat(value: JsonValue): boolean {\n if (value.kind !== \"literal\") {\n return false;\n }\n if (value.type === \"number\") {\n return true;\n } else if (\n value.type === \"string\" &&\n (value.jsonCode === '\"NaN\"' ||\n value.jsonCode === '\"Infinity\"' ||\n value.jsonCode === '\"-Infinity\"')\n ) {\n return true;\n } else {\n return false;\n }\n}\n\nfunction getTypeDesc(type: TypeSignature): string {\n function getTypePart(type: TypeSignature): string {\n switch (type.kind) {\n case \"primitive\":\n return type.value;\n case \"array\":\n return `[${getTypePart(type.value.item)}]`;\n case \"optional\":\n return `${getTypePart(type.value)}?`;\n case \"record\": {\n const recordId = type.value;\n return recordId.split(\":\")[1];\n }\n }\n }\n function getModulePart(type: TypeSignature): string | null {\n switch (type.kind) {\n case \"primitive\":\n return null;\n case \"array\":\n return getModulePart(type.value.item);\n case \"optional\":\n return getModulePart(type.value);\n case \"record\": {\n const recordId = type.value;\n return recordId.split(\":\")[0];\n }\n }\n }\n const typePart = getTypePart(type);\n const modulePart = getModulePart(type);\n return modulePart ? `${typePart} (${modulePart})` : typePart;\n}\n\nfunction getTypeDoc(\n type: TypeSignature,\n idToRecordDef: Readonly<{ [id: string]: RecordDefinition }>,\n): string | undefined {\n switch (type.kind) {\n case \"primitive\":\n return undefined;\n case \"array\":\n return getTypeDoc(type.value.item, idToRecordDef);\n case \"optional\":\n return getTypeDoc(type.value, idToRecordDef);\n case \"record\": {\n const recordId = type.value;\n const recordDef = idToRecordDef[recordId]!;\n return recordDef.doc;\n }\n }\n}\n"]}
1
+ {"version":3,"file":"schema_validator.js","sourceRoot":"","sources":["../../src/json/schema_validator.ts"],"names":[],"mappings":"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","sourcesContent":["import { primitiveSerializer } from \"skir-client\";\nimport { toJson } from \"./to_json\";\nimport type {\n EnumDefinition,\n FieldDefinition,\n Hint,\n JsonError,\n JsonObject,\n JsonValue,\n MutableTypeHint,\n Path,\n PrimitiveType,\n RecordDefinition,\n TypeDefinition,\n TypeHint,\n TypeSignature,\n ValidationResult,\n VariantDefinition,\n} from \"./types\";\n\nexport function validateSchema(\n value: JsonValue,\n schema: TypeDefinition,\n): ValidationResult {\n const idToRecordDef: { [id: string]: RecordDefinition } = {};\n for (const record of schema.records) {\n idToRecordDef[record.id] = record;\n }\n\n const validator = new SchemaValidator(idToRecordDef);\n const root: Path = { kind: \"root\" };\n validator.validate(value, root, schema.type);\n const pathToTypeHint = new Map<Path, TypeHint>();\n for (const hint of validator.hints) {\n const { valueContext } = hint;\n if (valueContext) {\n pathToTypeHint.set(valueContext.path, hint);\n }\n }\n return {\n errors: validator.errors,\n hints: validator.hints,\n rootTypeHint: validator.rootTypeHint,\n pathToTypeHint: pathToTypeHint,\n };\n}\n\nclass SchemaValidator {\n constructor(readonly idToRecordDef: { [id: string]: RecordDefinition }) {}\n readonly errors: JsonError[] = [];\n readonly hints: Hint[] = [];\n private readonly typeHintStack: MutableTypeHint[] = [];\n rootTypeHint: TypeHint | undefined;\n\n validate(\n value: JsonValue,\n path: Path,\n schema: TypeSignature,\n optionalSchema?: TypeSignature,\n ): void {\n const { idToRecordDef, typeHintStack } = this;\n value.expectedType = schema;\n // For every call to pushTypeHint() there emust be one call to typeHintStack.pop()\n const pushTypeHint = (options?: {\n enumDefinition?: EnumDefinition;\n }): void => {\n const typeDesc = getTypeDesc(optionalSchema ?? schema);\n const typeDoc = getTypeDoc(schema, idToRecordDef);\n const message = [typeDesc];\n if (typeDoc) {\n message.push(typeDoc);\n }\n if (value.kind === \"array\") {\n const { length } = value.values;\n if (length) {\n message.push(`Length: ${length}`);\n }\n }\n const hint: MutableTypeHint = {\n segment: value.firstToken,\n message: message.length === 1 ? message[0] : message,\n valueContext: { value, path },\n childHints: [],\n enumDefinition: options?.enumDefinition,\n };\n if (typeHintStack.length) {\n const topOfStack = typeHintStack[typeHintStack.length - 1];\n topOfStack.childHints.push(hint);\n } else {\n this.rootTypeHint = hint;\n }\n this.hints.push(hint);\n typeHintStack.push(hint);\n };\n switch (schema.kind) {\n case \"array\": {\n if (value.kind === \"array\") {\n pushTypeHint();\n for (const [index, item] of value.values.entries()) {\n const { key_extractor: keyExtractor, item: itemSchema } =\n schema.value;\n const itemKey = extractItemKey(item, keyExtractor);\n const itemPath: Path = {\n kind: \"array-item\",\n index: index,\n key: itemKey,\n arrayPath: path,\n };\n this.validate(item, itemPath, itemSchema);\n }\n typeHintStack.pop();\n } else {\n this.errors.push({\n kind: \"error\",\n segment: value.segment,\n message: \"Expected: array\",\n });\n }\n break;\n }\n case \"optional\": {\n if (value.kind === \"literal\" && value.jsonCode === \"null\") {\n pushTypeHint();\n typeHintStack.pop();\n } else {\n this.validate(value, path, schema.value, schema);\n }\n break;\n }\n case \"primitive\": {\n const primitiveType = schema.value;\n if (primitiveType === \"timestamp\") {\n if (this.validateTimestamp(value)) {\n pushTypeHint();\n typeHintStack.pop();\n }\n } else if (hasPrimitiveType(value, primitiveType)) {\n pushTypeHint();\n typeHintStack.pop();\n } else {\n this.errors.push({\n kind: \"error\",\n segment: value.firstToken,\n message: `Expected: ${primitiveType}`,\n });\n }\n break;\n }\n case \"record\": {\n const recordDef = idToRecordDef[schema.value];\n if (recordDef.kind === \"struct\") {\n const nameToFieldDef: { [name: string]: FieldDefinition } = {};\n recordDef.fields.forEach((field) => {\n nameToFieldDef[field.name] = field;\n });\n if (value.kind === \"object\") {\n pushTypeHint();\n for (const keyValue of Object.values(value.keyValues)) {\n const { key, value } = keyValue;\n const fieldDef = nameToFieldDef[key];\n if (fieldDef) {\n if (fieldDef.doc) {\n this.hints.push({\n segment: keyValue.keySegment,\n message: fieldDef.doc,\n });\n }\n const valuePath: Path = {\n kind: \"field-value\",\n fieldName: key,\n structPath: path,\n };\n this.validate(value, valuePath, fieldDef.type!);\n } else {\n this.errors.push({\n kind: \"error\",\n segment: keyValue.keySegment,\n message: \"Unknown field\",\n });\n }\n }\n typeHintStack.pop();\n } else {\n this.errors.push({\n kind: \"error\",\n segment: value.firstToken,\n message: \"Expected: object\",\n });\n }\n } else {\n // Enum\n const nameToVariantDef: { [name: string]: VariantDefinition } = {};\n recordDef.variants.forEach((variant) => {\n nameToVariantDef[variant.name.toLowerCase()] = variant;\n nameToVariantDef[variant.name.toUpperCase()] = variant;\n });\n if (value.kind === \"object\") {\n pushTypeHint();\n this.validateEnumObject(value, path, nameToVariantDef);\n typeHintStack.pop();\n } else if (value.kind === \"literal\" && value.type === \"string\") {\n const name = JSON.parse(value.jsonCode);\n const fieldDef = nameToVariantDef[name];\n if (fieldDef && fieldDef.type) {\n this.errors.push({\n kind: \"error\",\n segment: value.segment,\n message: \"Expected: constant variant\",\n });\n } else if (name === \"unknown\" || name === \"UNKNOWN\" || fieldDef) {\n pushTypeHint({ enumDefinition: recordDef });\n typeHintStack.pop();\n } else {\n this.errors.push({\n kind: \"error\",\n segment: value.segment,\n message: \"Unknown variant\",\n });\n }\n } else {\n this.errors.push({\n kind: \"error\",\n segment: value.firstToken,\n message: \"Expected: object or string\",\n });\n }\n }\n break;\n }\n default: {\n const _: never = schema;\n throw new Error(_);\n }\n }\n }\n\n validateEnumObject(\n object: JsonObject,\n enumPath: Path,\n nameToVariantDef: { [name: string]: VariantDefinition },\n ): void {\n const kindKv = object.keyValues[\"kind\"];\n if (!kindKv) {\n this.errors.push({\n kind: \"error\",\n segment: object.segment,\n message: \"Missing: 'kind'\",\n });\n return;\n }\n if (kindKv.value.kind !== \"literal\" || kindKv.value.type !== \"string\") {\n this.errors.push({\n kind: \"error\",\n segment: kindKv.value.firstToken,\n message: \"Expected: string\",\n });\n return;\n }\n const kind: string = JSON.parse(kindKv.value.jsonCode);\n const variantDef = nameToVariantDef[kind];\n if (!variantDef) {\n this.errors.push({\n kind: \"error\",\n segment: kindKv.value.segment,\n message: \"Unknown variant\",\n });\n return;\n } else if (variantDef.type === undefined) {\n this.errors.push({\n kind: \"error\",\n segment: kindKv.value.segment,\n message: \"Expected: wrapper variant\",\n });\n }\n const valueKv = object.keyValues[\"value\"];\n if (!valueKv) {\n this.errors.push({\n kind: \"error\",\n segment: object.segment,\n message: \"Missing: 'value'\",\n });\n return;\n }\n for (const key of object.allKeys) {\n if (key.key !== \"kind\" && key.key !== \"value\") {\n this.errors.push({\n kind: \"error\",\n segment: key.keySegment,\n message: \"Unexpected entry\",\n });\n }\n }\n const path: Path = {\n kind: \"variant-value\",\n variantName: variantDef.name,\n enumPath: enumPath,\n };\n this.validate(valueKv.value, path, variantDef.type!);\n }\n\n private validateTimestamp(value: JsonValue): boolean {\n if (value.kind !== \"object\") {\n this.errors.push({\n kind: \"error\",\n segment: value.firstToken,\n message: \"Expected: timestamp\",\n });\n return false;\n }\n const unixMillisKv = value.keyValues[\"unix_millis\"];\n if (!unixMillisKv) {\n this.errors.push({\n kind: \"error\",\n segment: value.firstToken,\n message: \"Missing: 'unix_millis'\",\n });\n return true;\n }\n if (\n unixMillisKv.value.kind !== \"literal\" ||\n unixMillisKv.value.type !== \"number\"\n ) {\n this.errors.push({\n kind: \"error\",\n segment: unixMillisKv.value.firstToken,\n message: \"Expected: number\",\n });\n return true;\n }\n const unixMillis = toJson(unixMillisKv.value) as number;\n if (unixMillis < -8640000000000000 || 8640000000000000 < unixMillis) {\n this.errors.push({\n kind: \"error\",\n segment: unixMillisKv.value.firstToken,\n message: \"Timestamp out of range\",\n });\n return true;\n }\n // At this point: the timestamp is technically valid.\n const formatted = value.keyValues[\"formatted\"];\n if (!formatted) {\n return true;\n }\n if (\n formatted.value.kind !== \"literal\" ||\n formatted.value.type !== \"string\"\n ) {\n this.errors.push({\n kind: \"error\",\n segment: formatted.value.firstToken,\n message: \"Expected: string\",\n });\n return true;\n }\n const formattedStr = toJson(formatted.value) as string;\n if (formattedStr === \"n/a\") {\n return true;\n }\n const parsedMillis = Date.parse(formattedStr);\n if (Number.isNaN(parsedMillis)) {\n this.errors.push({\n kind: \"error\",\n segment: formatted.value.firstToken,\n message: \"Invalid ISO 8601 date string\",\n });\n return true;\n }\n if (parsedMillis !== unixMillis) {\n this.errors.push({\n kind: \"error\",\n segment: formatted.value.firstToken,\n message: \"Does not match 'unix_millis'\",\n });\n }\n for (const key of value.allKeys) {\n if (key.key !== \"unix_millis\" && key.key !== \"formatted\") {\n this.errors.push({\n kind: \"error\",\n segment: key.keySegment,\n message: \"Unexpected entry\",\n });\n }\n }\n return true;\n }\n}\n\nfunction extractItemKey(\n item: JsonValue,\n keyExtractor: string | undefined,\n): string | null {\n if (keyExtractor === undefined) {\n return null;\n }\n const pieces = keyExtractor.split(\".\");\n let value = item;\n for (const piece of pieces) {\n if (value.kind !== \"object\") {\n // Error\n return null;\n }\n const kv = value.keyValues[piece];\n if (!kv) {\n // Error\n return null;\n }\n value = kv.value;\n }\n switch (value.kind) {\n case \"literal\": {\n switch (value.type) {\n case \"string\":\n case \"number\":\n case \"boolean\":\n return value.jsonCode;\n }\n // Error\n return null;\n }\n case \"object\": {\n const kv = value.keyValues[\"unix_millis\"];\n if (kv && kv.value.kind === \"literal\" && kv.value.type === \"number\") {\n return kv.value.jsonCode;\n } else {\n // Error\n return null;\n }\n }\n case \"array\": {\n // Error\n return null;\n }\n }\n}\n\nfunction hasPrimitiveType(\n value: JsonValue,\n expectedType: PrimitiveType,\n): boolean {\n switch (expectedType) {\n case \"bool\":\n return value.kind === \"literal\" && value.type === \"boolean\";\n case \"int32\": {\n return isInteger(value, -2147483648n, 2147483647n);\n }\n case \"int64\": {\n return isInteger(value, -9223372036854775808n, 9223372036854775807n);\n }\n case \"hash64\": {\n return isInteger(value, 0n, 18446744073709551615n);\n }\n case \"float32\":\n case \"float64\": {\n return isFloat(value);\n }\n case \"string\": {\n return value.kind === \"literal\" && value.type === \"string\";\n }\n case \"bytes\": {\n if (value.kind !== \"literal\") {\n return false;\n }\n try {\n primitiveSerializer(\"bytes\").fromJsonCode(value.jsonCode);\n return true;\n } catch {\n return false;\n }\n }\n case \"timestamp\": {\n // Case handled separately in validate()\n throw new Error();\n }\n }\n}\n\nfunction isInteger(value: JsonValue, min: bigint, max: bigint): boolean {\n if (value.kind !== \"literal\") {\n return false;\n }\n let decimalRep: string;\n if (value.type === \"string\") {\n decimalRep = JSON.parse(value.jsonCode);\n } else if (value.type === \"number\") {\n decimalRep = value.jsonCode;\n } else {\n return false;\n }\n let int: bigint;\n try {\n int = BigInt(decimalRep);\n } catch {\n return false;\n }\n return min <= int && int <= max;\n}\n\nfunction isFloat(value: JsonValue): boolean {\n if (value.kind !== \"literal\") {\n return false;\n }\n if (value.type === \"number\") {\n return true;\n } else if (\n value.type === \"string\" &&\n (value.jsonCode === '\"NaN\"' ||\n value.jsonCode === '\"Infinity\"' ||\n value.jsonCode === '\"-Infinity\"')\n ) {\n return true;\n } else {\n return false;\n }\n}\n\nfunction getTypeDesc(type: TypeSignature): string {\n function getTypePart(type: TypeSignature): string {\n switch (type.kind) {\n case \"primitive\":\n return type.value;\n case \"array\":\n return `[${getTypePart(type.value.item)}]`;\n case \"optional\":\n return `${getTypePart(type.value)}?`;\n case \"record\": {\n const recordId = type.value;\n return recordId.split(\":\")[1];\n }\n }\n }\n function getModulePart(type: TypeSignature): string | null {\n switch (type.kind) {\n case \"primitive\":\n return null;\n case \"array\":\n return getModulePart(type.value.item);\n case \"optional\":\n return getModulePart(type.value);\n case \"record\": {\n const recordId = type.value;\n return recordId.split(\":\")[0];\n }\n }\n }\n const typePart = getTypePart(type);\n const modulePart = getModulePart(type);\n return modulePart ? `${typePart} (${modulePart})` : typePart;\n}\n\nfunction getTypeDoc(\n type: TypeSignature,\n idToRecordDef: Readonly<{ [id: string]: RecordDefinition }>,\n): string | undefined {\n switch (type.kind) {\n case \"primitive\":\n return undefined;\n case \"array\":\n return getTypeDoc(type.value.item, idToRecordDef);\n case \"optional\":\n return getTypeDoc(type.value, idToRecordDef);\n case \"record\": {\n const recordId = type.value;\n const recordDef = idToRecordDef[recordId]!;\n return recordDef.doc;\n }\n }\n}\n"]}
@@ -140,7 +140,7 @@ describe("schema_validator", () => {
140
140
  },
141
141
  ]);
142
142
  });
143
- it("validates enum (string literal)", () => {
143
+ it("validates enum (string literal accepts lower and upper)", () => {
144
144
  const schema = {
145
145
  type: { kind: "record", value: "MyEnum" },
146
146
  records: [
@@ -148,14 +148,84 @@ describe("schema_validator", () => {
148
148
  kind: "enum",
149
149
  id: "MyEnum",
150
150
  variants: [
151
- { name: "First", number: 1 },
152
- { name: "Second", number: 2 },
151
+ { name: "FOO", number: 1 },
152
+ { name: "BAR", number: 2 },
153
153
  ],
154
154
  },
155
155
  ],
156
156
  };
157
- const result = validateSchema(parse('"First"'), schema);
158
- expect(result).toMatch({ errors: [] });
157
+ const lowerResult = validateSchema(parse('"foo"'), schema);
158
+ expect(lowerResult).toMatch({ errors: [] });
159
+ const upperResult = validateSchema(parse('"FOO"'), schema);
160
+ expect(upperResult).toMatch({ errors: [] });
161
+ });
162
+ it("rejects mixed-case enum string literal", () => {
163
+ const schema = {
164
+ type: { kind: "record", value: "MyEnum" },
165
+ records: [
166
+ {
167
+ kind: "enum",
168
+ id: "MyEnum",
169
+ variants: [{ name: "FOO", number: 1 }],
170
+ },
171
+ ],
172
+ };
173
+ const result = validateSchema(parse('"Foo"'), schema);
174
+ expect(result.errors).toMatch([
175
+ {
176
+ message: "Unknown variant",
177
+ },
178
+ ]);
179
+ });
180
+ it("accepts UNKNOWN and unknown enum literals", () => {
181
+ const schema = {
182
+ type: { kind: "record", value: "MyEnum" },
183
+ records: [
184
+ {
185
+ kind: "enum",
186
+ id: "MyEnum",
187
+ variants: [{ name: "FOO", number: 1 }],
188
+ },
189
+ ],
190
+ };
191
+ expect(validateSchema(parse('"UNKNOWN"'), schema)).toMatch({ errors: [] });
192
+ expect(validateSchema(parse('"unknown"'), schema)).toMatch({ errors: [] });
193
+ const mixedCaseResult = validateSchema(parse('"Unknown"'), schema);
194
+ expect(mixedCaseResult.errors).toMatch([
195
+ {
196
+ message: "Unknown variant",
197
+ },
198
+ ]);
199
+ });
200
+ it("validates enum object kind in lower and upper", () => {
201
+ const schema = {
202
+ type: { kind: "record", value: "MyEnum" },
203
+ records: [
204
+ {
205
+ kind: "enum",
206
+ id: "MyEnum",
207
+ variants: [
208
+ {
209
+ name: "COMPLEX",
210
+ number: 1,
211
+ type: { kind: "primitive", value: "int32" },
212
+ },
213
+ ],
214
+ },
215
+ ],
216
+ };
217
+ expect(validateSchema(parse('{"kind": "complex", "value": 123}'), schema)).toMatch({
218
+ errors: [],
219
+ });
220
+ expect(validateSchema(parse('{"kind": "COMPLEX", "value": 123}'), schema)).toMatch({
221
+ errors: [],
222
+ });
223
+ const mixedCaseResult = validateSchema(parse('{"kind": "Complex", "value": 123}'), schema);
224
+ expect(mixedCaseResult.errors).toMatch([
225
+ {
226
+ message: "Unknown variant",
227
+ },
228
+ ]);
159
229
  });
160
230
  it("reports unknown enum variant", () => {
161
231
  const schema = {
@@ -175,6 +245,51 @@ describe("schema_validator", () => {
175
245
  },
176
246
  ]);
177
247
  });
248
+ it("reports error when typed enum variant is provided as string", () => {
249
+ const schema = {
250
+ type: { kind: "record", value: "MyEnum" },
251
+ records: [
252
+ {
253
+ kind: "enum",
254
+ id: "MyEnum",
255
+ variants: [
256
+ {
257
+ name: "COMPLEX",
258
+ number: 1,
259
+ type: { kind: "primitive", value: "int32" },
260
+ },
261
+ ],
262
+ },
263
+ ],
264
+ };
265
+ const result = validateSchema(parse('"COMPLEX"'), schema);
266
+ expect(result.errors).toMatch([
267
+ {
268
+ message: "Expected: constant variant",
269
+ },
270
+ ]);
271
+ });
272
+ it("reports error when constant enum variant is provided as object", () => {
273
+ const schema = {
274
+ type: { kind: "record", value: "MyEnum" },
275
+ records: [
276
+ {
277
+ kind: "enum",
278
+ id: "MyEnum",
279
+ variants: [{ name: "SIMPLE", number: 1 }],
280
+ },
281
+ ],
282
+ };
283
+ const result = validateSchema(parse('{"kind": "SIMPLE"}'), schema);
284
+ expect(result.errors).toMatch([
285
+ {
286
+ message: "Expected: wrapper variant",
287
+ },
288
+ {
289
+ message: "Missing: 'value'",
290
+ },
291
+ ]);
292
+ });
178
293
  it("stores enum definition in type hint for UNKNOWN enum literal", () => {
179
294
  const schema = {
180
295
  type: { kind: "record", value: "MyEnum" },
@@ -1 +1 @@
1
- {"version":3,"file":"schema_validator.test.js","sourceRoot":"","sources":["../../src/json/schema_validator.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from \"buckwheat\";\nimport { describe, it } from \"mocha\";\nimport { parseJsonValue } from \"./json_parser.js\";\nimport { validateSchema } from \"./schema_validator.js\";\nimport { JsonValue, TypeDefinition } from \"./types.js\";\n\nfunction parse(json: string): JsonValue {\n const result = parseJsonValue(json);\n if (!result.value) {\n throw new Error(`JSON parse error: ${JSON.stringify(result.errors)}`);\n }\n return result.value;\n}\n\ndescribe(\"schema_validator\", () => {\n it(\"validates primitive int32\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"primitive\", value: \"int32\" },\n records: [],\n };\n const result = validateSchema(parse(\"123\"), schema);\n expect(result).toMatch({ errors: [] });\n if (result.hints.length === 0) {\n throw new Error(\"Expected type hints\");\n }\n });\n\n it(\"validates primitive string\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"primitive\", value: \"string\" },\n records: [],\n };\n const result = validateSchema(parse('\"hello\"'), schema);\n expect(result).toMatch({ errors: [] });\n });\n\n it(\"reports error for type mismatch (int32 vs string)\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"primitive\", value: \"int32\" },\n records: [],\n };\n const result = validateSchema(parse('\"hello\"'), schema);\n expect(result.errors).toMatch([\n {\n message: \"Expected: int32\",\n },\n ]);\n });\n\n it(\"validates array of primitives\", () => {\n const schema: TypeDefinition = {\n type: {\n kind: \"array\",\n value: { item: { kind: \"primitive\", value: \"int32\" } },\n },\n records: [],\n };\n const result = validateSchema(parse(\"[1, 2, 3]\"), schema);\n expect(result).toMatch({ errors: [] });\n });\n\n it(\"reports error for invalid array item\", () => {\n const schema: TypeDefinition = {\n type: {\n kind: \"array\",\n value: { item: { kind: \"primitive\", value: \"int32\" } },\n },\n records: [],\n };\n const result = validateSchema(parse('[1, \"bad\", 3]'), schema);\n expect(result.errors).toMatch([\n {\n message: \"Expected: int32\",\n segment: {\n start: 4,\n end: 9,\n },\n },\n ]);\n });\n\n it(\"validates optional field (present)\", () => {\n const schema: TypeDefinition = {\n type: {\n kind: \"optional\",\n value: { kind: \"primitive\", value: \"int32\" },\n },\n records: [],\n };\n const result = validateSchema(parse(\"123\"), schema);\n expect(result).toMatch({ errors: [] });\n });\n\n it(\"validates optional field (null)\", () => {\n const schema: TypeDefinition = {\n type: {\n kind: \"optional\",\n value: { kind: \"primitive\", value: \"int32\" },\n },\n records: [],\n };\n const result = validateSchema(parse(\"null\"), schema);\n expect(result).toMatch({ errors: [] });\n });\n\n it(\"validates struct\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyStruct\" },\n records: [\n {\n kind: \"struct\",\n id: \"MyStruct\",\n fields: [\n {\n name: \"foo\",\n number: 1,\n type: { kind: \"primitive\", value: \"string\" },\n },\n {\n name: \"bar\",\n number: 2,\n type: { kind: \"primitive\", value: \"int32\" },\n },\n ],\n },\n ],\n };\n const result = validateSchema(parse('{\"foo\": \"hi\", \"bar\": 123}'), schema);\n expect(result).toMatch({ errors: [] });\n });\n\n it(\"reports unknown field in struct\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyStruct\" },\n records: [\n {\n kind: \"struct\",\n id: \"MyStruct\",\n fields: [],\n },\n ],\n };\n const result = validateSchema(parse('{\"unknown\": 1}'), schema);\n expect(result.errors).toMatch([\n {\n message: \"Unknown field\",\n segment: {\n start: 1,\n end: 10,\n },\n },\n ]);\n });\n\n it(\"validates enum (string literal)\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyEnum\" },\n records: [\n {\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [\n { name: \"First\", number: 1 },\n { name: \"Second\", number: 2 },\n ],\n },\n ],\n };\n const result = validateSchema(parse('\"First\"'), schema);\n expect(result).toMatch({ errors: [] });\n });\n\n it(\"reports unknown enum variant\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyEnum\" },\n records: [\n {\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [{ name: \"First\", number: 1 }],\n },\n ],\n };\n const result = validateSchema(parse('\"Unknown\"'), schema);\n expect(result.errors).toMatch([\n {\n message: \"Unknown variant\",\n },\n ]);\n });\n\n it(\"stores enum definition in type hint for UNKNOWN enum literal\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyEnum\" },\n records: [\n {\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [\n { name: \"First\", number: 1 },\n { name: \"Second\", number: 2 },\n ],\n },\n ],\n };\n\n const result = validateSchema(parse('\"UNKNOWN\"'), schema);\n expect(result.errors).toMatch([]);\n if (!result.rootTypeHint) {\n throw new Error(\"Expected root type hint\");\n }\n expect(result.rootTypeHint.enumDefinition).toMatch({\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [\n { name: \"First\", number: 1 },\n { name: \"Second\", number: 2 },\n ],\n });\n });\n\n it(\"stores enum definition in nested UNKNOWN enum field hint\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyStruct\" },\n records: [\n {\n kind: \"struct\",\n id: \"MyStruct\",\n fields: [\n {\n name: \"status\",\n number: 1,\n type: { kind: \"record\", value: \"MyEnum\" },\n },\n ],\n },\n {\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [\n { name: \"First\", number: 1 },\n { name: \"Second\", number: 2 },\n ],\n },\n ],\n };\n\n const result = validateSchema(parse('{\"status\": \"UNKNOWN\"}'), schema);\n expect(result.errors).toMatch([]);\n if (!result.rootTypeHint) {\n throw new Error(\"Expected root type hint\");\n }\n if (result.rootTypeHint.childHints.length !== 1) {\n throw new Error(\"Expected one child type hint\");\n }\n const statusHint = result.rootTypeHint.childHints[0];\n expect(statusHint.enumDefinition).toMatch({\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [\n { name: \"First\", number: 1 },\n { name: \"Second\", number: 2 },\n ],\n });\n });\n\n it(\"validates enum (object with kind)\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyEnum\" },\n records: [\n {\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [\n {\n name: \"complex\",\n number: 1,\n type: { kind: \"primitive\", value: \"int32\" },\n },\n ],\n },\n ],\n };\n\n expect(\n validateSchema(parse('{\"kind\": \"complex\", \"value\": 123}'), schema),\n ).toMatch({ errors: [] });\n expect(\n validateSchema(parse('{\"kind\": \"complex\", \"value\": \"foo\"}'), schema),\n ).toMatch({\n errors: [\n {\n message: \"Expected: int32\",\n },\n ],\n });\n expect(validateSchema(parse('{\"kind\": \"complex\"}'), schema)).toMatch({\n errors: [\n {\n message: \"Missing: 'value'\",\n },\n ],\n });\n });\n});\n"]}
1
+ {"version":3,"file":"schema_validator.test.js","sourceRoot":"","sources":["../../src/json/schema_validator.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from \"buckwheat\";\nimport { describe, it } from \"mocha\";\nimport { parseJsonValue } from \"./json_parser.js\";\nimport { validateSchema } from \"./schema_validator.js\";\nimport { JsonValue, TypeDefinition } from \"./types.js\";\n\nfunction parse(json: string): JsonValue {\n const result = parseJsonValue(json);\n if (!result.value) {\n throw new Error(`JSON parse error: ${JSON.stringify(result.errors)}`);\n }\n return result.value;\n}\n\ndescribe(\"schema_validator\", () => {\n it(\"validates primitive int32\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"primitive\", value: \"int32\" },\n records: [],\n };\n const result = validateSchema(parse(\"123\"), schema);\n expect(result).toMatch({ errors: [] });\n if (result.hints.length === 0) {\n throw new Error(\"Expected type hints\");\n }\n });\n\n it(\"validates primitive string\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"primitive\", value: \"string\" },\n records: [],\n };\n const result = validateSchema(parse('\"hello\"'), schema);\n expect(result).toMatch({ errors: [] });\n });\n\n it(\"reports error for type mismatch (int32 vs string)\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"primitive\", value: \"int32\" },\n records: [],\n };\n const result = validateSchema(parse('\"hello\"'), schema);\n expect(result.errors).toMatch([\n {\n message: \"Expected: int32\",\n },\n ]);\n });\n\n it(\"validates array of primitives\", () => {\n const schema: TypeDefinition = {\n type: {\n kind: \"array\",\n value: { item: { kind: \"primitive\", value: \"int32\" } },\n },\n records: [],\n };\n const result = validateSchema(parse(\"[1, 2, 3]\"), schema);\n expect(result).toMatch({ errors: [] });\n });\n\n it(\"reports error for invalid array item\", () => {\n const schema: TypeDefinition = {\n type: {\n kind: \"array\",\n value: { item: { kind: \"primitive\", value: \"int32\" } },\n },\n records: [],\n };\n const result = validateSchema(parse('[1, \"bad\", 3]'), schema);\n expect(result.errors).toMatch([\n {\n message: \"Expected: int32\",\n segment: {\n start: 4,\n end: 9,\n },\n },\n ]);\n });\n\n it(\"validates optional field (present)\", () => {\n const schema: TypeDefinition = {\n type: {\n kind: \"optional\",\n value: { kind: \"primitive\", value: \"int32\" },\n },\n records: [],\n };\n const result = validateSchema(parse(\"123\"), schema);\n expect(result).toMatch({ errors: [] });\n });\n\n it(\"validates optional field (null)\", () => {\n const schema: TypeDefinition = {\n type: {\n kind: \"optional\",\n value: { kind: \"primitive\", value: \"int32\" },\n },\n records: [],\n };\n const result = validateSchema(parse(\"null\"), schema);\n expect(result).toMatch({ errors: [] });\n });\n\n it(\"validates struct\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyStruct\" },\n records: [\n {\n kind: \"struct\",\n id: \"MyStruct\",\n fields: [\n {\n name: \"foo\",\n number: 1,\n type: { kind: \"primitive\", value: \"string\" },\n },\n {\n name: \"bar\",\n number: 2,\n type: { kind: \"primitive\", value: \"int32\" },\n },\n ],\n },\n ],\n };\n const result = validateSchema(parse('{\"foo\": \"hi\", \"bar\": 123}'), schema);\n expect(result).toMatch({ errors: [] });\n });\n\n it(\"reports unknown field in struct\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyStruct\" },\n records: [\n {\n kind: \"struct\",\n id: \"MyStruct\",\n fields: [],\n },\n ],\n };\n const result = validateSchema(parse('{\"unknown\": 1}'), schema);\n expect(result.errors).toMatch([\n {\n message: \"Unknown field\",\n segment: {\n start: 1,\n end: 10,\n },\n },\n ]);\n });\n\n it(\"validates enum (string literal accepts lower and upper)\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyEnum\" },\n records: [\n {\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [\n { name: \"FOO\", number: 1 },\n { name: \"BAR\", number: 2 },\n ],\n },\n ],\n };\n const lowerResult = validateSchema(parse('\"foo\"'), schema);\n expect(lowerResult).toMatch({ errors: [] });\n\n const upperResult = validateSchema(parse('\"FOO\"'), schema);\n expect(upperResult).toMatch({ errors: [] });\n });\n\n it(\"rejects mixed-case enum string literal\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyEnum\" },\n records: [\n {\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [{ name: \"FOO\", number: 1 }],\n },\n ],\n };\n\n const result = validateSchema(parse('\"Foo\"'), schema);\n expect(result.errors).toMatch([\n {\n message: \"Unknown variant\",\n },\n ]);\n });\n\n it(\"accepts UNKNOWN and unknown enum literals\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyEnum\" },\n records: [\n {\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [{ name: \"FOO\", number: 1 }],\n },\n ],\n };\n\n expect(validateSchema(parse('\"UNKNOWN\"'), schema)).toMatch({ errors: [] });\n expect(validateSchema(parse('\"unknown\"'), schema)).toMatch({ errors: [] });\n\n const mixedCaseResult = validateSchema(parse('\"Unknown\"'), schema);\n expect(mixedCaseResult.errors).toMatch([\n {\n message: \"Unknown variant\",\n },\n ]);\n });\n\n it(\"validates enum object kind in lower and upper\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyEnum\" },\n records: [\n {\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [\n {\n name: \"COMPLEX\",\n number: 1,\n type: { kind: \"primitive\", value: \"int32\" },\n },\n ],\n },\n ],\n };\n\n expect(\n validateSchema(parse('{\"kind\": \"complex\", \"value\": 123}'), schema),\n ).toMatch({\n errors: [],\n });\n expect(\n validateSchema(parse('{\"kind\": \"COMPLEX\", \"value\": 123}'), schema),\n ).toMatch({\n errors: [],\n });\n\n const mixedCaseResult = validateSchema(\n parse('{\"kind\": \"Complex\", \"value\": 123}'),\n schema,\n );\n expect(mixedCaseResult.errors).toMatch([\n {\n message: \"Unknown variant\",\n },\n ]);\n });\n\n it(\"reports unknown enum variant\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyEnum\" },\n records: [\n {\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [{ name: \"First\", number: 1 }],\n },\n ],\n };\n const result = validateSchema(parse('\"Unknown\"'), schema);\n expect(result.errors).toMatch([\n {\n message: \"Unknown variant\",\n },\n ]);\n });\n\n it(\"reports error when typed enum variant is provided as string\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyEnum\" },\n records: [\n {\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [\n {\n name: \"COMPLEX\",\n number: 1,\n type: { kind: \"primitive\", value: \"int32\" },\n },\n ],\n },\n ],\n };\n\n const result = validateSchema(parse('\"COMPLEX\"'), schema);\n expect(result.errors).toMatch([\n {\n message: \"Expected: constant variant\",\n },\n ]);\n });\n\n it(\"reports error when constant enum variant is provided as object\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyEnum\" },\n records: [\n {\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [{ name: \"SIMPLE\", number: 1 }],\n },\n ],\n };\n\n const result = validateSchema(parse('{\"kind\": \"SIMPLE\"}'), schema);\n expect(result.errors).toMatch([\n {\n message: \"Expected: wrapper variant\",\n },\n {\n message: \"Missing: 'value'\",\n },\n ]);\n });\n\n it(\"stores enum definition in type hint for UNKNOWN enum literal\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyEnum\" },\n records: [\n {\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [\n { name: \"First\", number: 1 },\n { name: \"Second\", number: 2 },\n ],\n },\n ],\n };\n\n const result = validateSchema(parse('\"UNKNOWN\"'), schema);\n expect(result.errors).toMatch([]);\n if (!result.rootTypeHint) {\n throw new Error(\"Expected root type hint\");\n }\n expect(result.rootTypeHint.enumDefinition).toMatch({\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [\n { name: \"First\", number: 1 },\n { name: \"Second\", number: 2 },\n ],\n });\n });\n\n it(\"stores enum definition in nested UNKNOWN enum field hint\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyStruct\" },\n records: [\n {\n kind: \"struct\",\n id: \"MyStruct\",\n fields: [\n {\n name: \"status\",\n number: 1,\n type: { kind: \"record\", value: \"MyEnum\" },\n },\n ],\n },\n {\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [\n { name: \"First\", number: 1 },\n { name: \"Second\", number: 2 },\n ],\n },\n ],\n };\n\n const result = validateSchema(parse('{\"status\": \"UNKNOWN\"}'), schema);\n expect(result.errors).toMatch([]);\n if (!result.rootTypeHint) {\n throw new Error(\"Expected root type hint\");\n }\n if (result.rootTypeHint.childHints.length !== 1) {\n throw new Error(\"Expected one child type hint\");\n }\n const statusHint = result.rootTypeHint.childHints[0];\n expect(statusHint.enumDefinition).toMatch({\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [\n { name: \"First\", number: 1 },\n { name: \"Second\", number: 2 },\n ],\n });\n });\n\n it(\"validates enum (object with kind)\", () => {\n const schema: TypeDefinition = {\n type: { kind: \"record\", value: \"MyEnum\" },\n records: [\n {\n kind: \"enum\",\n id: \"MyEnum\",\n variants: [\n {\n name: \"complex\",\n number: 1,\n type: { kind: \"primitive\", value: \"int32\" },\n },\n ],\n },\n ],\n };\n\n expect(\n validateSchema(parse('{\"kind\": \"complex\", \"value\": 123}'), schema),\n ).toMatch({ errors: [] });\n expect(\n validateSchema(parse('{\"kind\": \"complex\", \"value\": \"foo\"}'), schema),\n ).toMatch({\n errors: [\n {\n message: \"Expected: int32\",\n },\n ],\n });\n expect(validateSchema(parse('{\"kind\": \"complex\"}'), schema)).toMatch({\n errors: [\n {\n message: \"Missing: 'value'\",\n },\n ],\n });\n });\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skir-codemirror-plugin",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "",
5
5
  "homepage": "https://github.com/gepheum/skir-codemirror-plugin#readme",
6
6
  "bugs": {
@@ -48,7 +48,7 @@
48
48
  "@codemirror/lang-json": "^6.0.2",
49
49
  "@uiw/codemirror-themes-all": "^4.25.9",
50
50
  "codemirror": "^6.0.2",
51
- "skir-client": "^1.0.11"
51
+ "skir-client": "^1.0.18"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@custom-elements-manifest/analyzer": "^0.6.3",
@@ -73,6 +73,5 @@
73
73
  "diff": "^8.0.3",
74
74
  "minimatch": "^10.2.1",
75
75
  "serialize-javascript": "^7.0.4"
76
- },
77
- "customElements": "custom-elements.json"
76
+ }
78
77
  }
@@ -152,7 +152,7 @@ describe("schema_validator", () => {
152
152
  ]);
153
153
  });
154
154
 
155
- it("validates enum (string literal)", () => {
155
+ it("validates enum (string literal accepts lower and upper)", () => {
156
156
  const schema: TypeDefinition = {
157
157
  type: { kind: "record", value: "MyEnum" },
158
158
  records: [
@@ -160,14 +160,100 @@ describe("schema_validator", () => {
160
160
  kind: "enum",
161
161
  id: "MyEnum",
162
162
  variants: [
163
- { name: "First", number: 1 },
164
- { name: "Second", number: 2 },
163
+ { name: "FOO", number: 1 },
164
+ { name: "BAR", number: 2 },
165
165
  ],
166
166
  },
167
167
  ],
168
168
  };
169
- const result = validateSchema(parse('"First"'), schema);
170
- expect(result).toMatch({ errors: [] });
169
+ const lowerResult = validateSchema(parse('"foo"'), schema);
170
+ expect(lowerResult).toMatch({ errors: [] });
171
+
172
+ const upperResult = validateSchema(parse('"FOO"'), schema);
173
+ expect(upperResult).toMatch({ errors: [] });
174
+ });
175
+
176
+ it("rejects mixed-case enum string literal", () => {
177
+ const schema: TypeDefinition = {
178
+ type: { kind: "record", value: "MyEnum" },
179
+ records: [
180
+ {
181
+ kind: "enum",
182
+ id: "MyEnum",
183
+ variants: [{ name: "FOO", number: 1 }],
184
+ },
185
+ ],
186
+ };
187
+
188
+ const result = validateSchema(parse('"Foo"'), schema);
189
+ expect(result.errors).toMatch([
190
+ {
191
+ message: "Unknown variant",
192
+ },
193
+ ]);
194
+ });
195
+
196
+ it("accepts UNKNOWN and unknown enum literals", () => {
197
+ const schema: TypeDefinition = {
198
+ type: { kind: "record", value: "MyEnum" },
199
+ records: [
200
+ {
201
+ kind: "enum",
202
+ id: "MyEnum",
203
+ variants: [{ name: "FOO", number: 1 }],
204
+ },
205
+ ],
206
+ };
207
+
208
+ expect(validateSchema(parse('"UNKNOWN"'), schema)).toMatch({ errors: [] });
209
+ expect(validateSchema(parse('"unknown"'), schema)).toMatch({ errors: [] });
210
+
211
+ const mixedCaseResult = validateSchema(parse('"Unknown"'), schema);
212
+ expect(mixedCaseResult.errors).toMatch([
213
+ {
214
+ message: "Unknown variant",
215
+ },
216
+ ]);
217
+ });
218
+
219
+ it("validates enum object kind in lower and upper", () => {
220
+ const schema: TypeDefinition = {
221
+ type: { kind: "record", value: "MyEnum" },
222
+ records: [
223
+ {
224
+ kind: "enum",
225
+ id: "MyEnum",
226
+ variants: [
227
+ {
228
+ name: "COMPLEX",
229
+ number: 1,
230
+ type: { kind: "primitive", value: "int32" },
231
+ },
232
+ ],
233
+ },
234
+ ],
235
+ };
236
+
237
+ expect(
238
+ validateSchema(parse('{"kind": "complex", "value": 123}'), schema),
239
+ ).toMatch({
240
+ errors: [],
241
+ });
242
+ expect(
243
+ validateSchema(parse('{"kind": "COMPLEX", "value": 123}'), schema),
244
+ ).toMatch({
245
+ errors: [],
246
+ });
247
+
248
+ const mixedCaseResult = validateSchema(
249
+ parse('{"kind": "Complex", "value": 123}'),
250
+ schema,
251
+ );
252
+ expect(mixedCaseResult.errors).toMatch([
253
+ {
254
+ message: "Unknown variant",
255
+ },
256
+ ]);
171
257
  });
172
258
 
173
259
  it("reports unknown enum variant", () => {
@@ -189,6 +275,55 @@ describe("schema_validator", () => {
189
275
  ]);
190
276
  });
191
277
 
278
+ it("reports error when typed enum variant is provided as string", () => {
279
+ const schema: TypeDefinition = {
280
+ type: { kind: "record", value: "MyEnum" },
281
+ records: [
282
+ {
283
+ kind: "enum",
284
+ id: "MyEnum",
285
+ variants: [
286
+ {
287
+ name: "COMPLEX",
288
+ number: 1,
289
+ type: { kind: "primitive", value: "int32" },
290
+ },
291
+ ],
292
+ },
293
+ ],
294
+ };
295
+
296
+ const result = validateSchema(parse('"COMPLEX"'), schema);
297
+ expect(result.errors).toMatch([
298
+ {
299
+ message: "Expected: constant variant",
300
+ },
301
+ ]);
302
+ });
303
+
304
+ it("reports error when constant enum variant is provided as object", () => {
305
+ const schema: TypeDefinition = {
306
+ type: { kind: "record", value: "MyEnum" },
307
+ records: [
308
+ {
309
+ kind: "enum",
310
+ id: "MyEnum",
311
+ variants: [{ name: "SIMPLE", number: 1 }],
312
+ },
313
+ ],
314
+ };
315
+
316
+ const result = validateSchema(parse('{"kind": "SIMPLE"}'), schema);
317
+ expect(result.errors).toMatch([
318
+ {
319
+ message: "Expected: wrapper variant",
320
+ },
321
+ {
322
+ message: "Missing: 'value'",
323
+ },
324
+ ]);
325
+ });
326
+
192
327
  it("stores enum definition in type hint for UNKNOWN enum literal", () => {
193
328
  const schema: TypeDefinition = {
194
329
  type: { kind: "record", value: "MyEnum" },
@@ -191,7 +191,8 @@ class SchemaValidator {
191
191
  // Enum
192
192
  const nameToVariantDef: { [name: string]: VariantDefinition } = {};
193
193
  recordDef.variants.forEach((variant) => {
194
- nameToVariantDef[variant.name] = variant;
194
+ nameToVariantDef[variant.name.toLowerCase()] = variant;
195
+ nameToVariantDef[variant.name.toUpperCase()] = variant;
195
196
  });
196
197
  if (value.kind === "object") {
197
198
  pushTypeHint();
@@ -204,9 +205,9 @@ class SchemaValidator {
204
205
  this.errors.push({
205
206
  kind: "error",
206
207
  segment: value.segment,
207
- message: "Expected: uppercase variant name",
208
+ message: "Expected: constant variant",
208
209
  });
209
- } else if (name === "UNKNOWN" || fieldDef) {
210
+ } else if (name === "unknown" || name === "UNKNOWN" || fieldDef) {
210
211
  pushTypeHint({ enumDefinition: recordDef });
211
212
  typeHintStack.pop();
212
213
  } else {
@@ -256,22 +257,20 @@ class SchemaValidator {
256
257
  return;
257
258
  }
258
259
  const kind: string = JSON.parse(kindKv.value.jsonCode);
259
- if (kind !== kind.toLowerCase()) {
260
+ const variantDef = nameToVariantDef[kind];
261
+ if (!variantDef) {
260
262
  this.errors.push({
261
263
  kind: "error",
262
264
  segment: kindKv.value.segment,
263
- message: "Expected: lowercase variant name",
265
+ message: "Unknown variant",
264
266
  });
265
267
  return;
266
- }
267
- const variantDef = nameToVariantDef[kind];
268
- if (!variantDef) {
268
+ } else if (variantDef.type === undefined) {
269
269
  this.errors.push({
270
270
  kind: "error",
271
271
  segment: kindKv.value.segment,
272
- message: "Unknown variant",
272
+ message: "Expected: wrapper variant",
273
273
  });
274
- return;
275
274
  }
276
275
  const valueKv = object.keyValues["value"];
277
276
  if (!valueKv) {