@twin.org/tools-core 0.0.3-next.20 → 0.0.3-next.21

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.
@@ -1,6 +1,6 @@
1
1
  // Copyright 2026 IOTA Stiftung.
2
2
  // SPDX-License-Identifier: Apache-2.0.
3
- import { GeneralError, Is, JsonHelper, ObjectHelper, StringHelper } from "@twin.org/core";
3
+ import { ArrayHelper, GeneralError, Is, JsonHelper, ObjectHelper, StringHelper } from "@twin.org/core";
4
4
  import { JsonSchemaTagNames } from "@twin.org/tools-models";
5
5
  import * as ts from "typescript";
6
6
  import { Constants } from "./constants.js";
@@ -261,10 +261,92 @@ export class JsonSchemaBuilder {
261
261
  schemaKey
262
262
  });
263
263
  }
264
+ JsonSchemaBuilder.validateJsonSchemaTagConstraint(schemaKey, schema.type, rawValue);
264
265
  const parsedValue = JsDoc.parseTagValue(rawValue);
265
266
  ObjectHelper.propertySet(schema, schemaKey, parsedValue);
266
267
  }
267
268
  }
269
+ /**
270
+ * Validate that a @json-schema constraint key is compatible with the given schema type,
271
+ * and that the raw value is valid for the constraint.
272
+ * @param schemaKey The mapped schema key being applied.
273
+ * @param schemaType The type already set on the schema, if any.
274
+ * @param rawValue The raw string value from the JSDoc tag.
275
+ * @throws GeneralError Thrown when the constraint is not valid for the schema type.
276
+ * @throws GeneralError Thrown when the format value is not a recognised JSON Schema format.
277
+ */
278
+ static validateJsonSchemaTagConstraint(schemaKey, schemaType, rawValue) {
279
+ if (schemaType !== undefined) {
280
+ const types = ArrayHelper.fromObjectOrArray(schemaType);
281
+ const numericConstraints = [
282
+ "minimum",
283
+ "maximum",
284
+ "multipleOf",
285
+ "exclusiveMinimum",
286
+ "exclusiveMaximum"
287
+ ];
288
+ const stringConstraints = ["minLength", "maxLength", "pattern", "format"];
289
+ const objectConstraints = ["minProperties", "maxProperties"];
290
+ const arrayConstraints = ["minItems", "maxItems", "uniqueItems"];
291
+ let requiredType;
292
+ if (numericConstraints.includes(schemaKey)) {
293
+ if (!types.includes("number") && !types.includes("integer")) {
294
+ requiredType = "number|integer";
295
+ }
296
+ }
297
+ else if (stringConstraints.includes(schemaKey)) {
298
+ if (!types.includes("string")) {
299
+ requiredType = "string";
300
+ }
301
+ }
302
+ else if (objectConstraints.includes(schemaKey)) {
303
+ if (!types.includes("object")) {
304
+ requiredType = "object";
305
+ }
306
+ }
307
+ else if (arrayConstraints.includes(schemaKey)) {
308
+ if (!types.includes("array")) {
309
+ requiredType = "array";
310
+ }
311
+ }
312
+ if (requiredType !== undefined) {
313
+ throw new GeneralError(JsonSchemaBuilder.CLASS_NAME, "constraintOnIncompatibleType", {
314
+ schemaKey,
315
+ requiredType,
316
+ schemaType: Is.array(schemaType) ? schemaType.join("|") : schemaType
317
+ });
318
+ }
319
+ }
320
+ if (schemaKey === "format") {
321
+ const validFormats = [
322
+ "date-time",
323
+ "date",
324
+ "time",
325
+ "duration",
326
+ "email",
327
+ "idn-email",
328
+ "hostname",
329
+ "idn-hostname",
330
+ "ipv4",
331
+ "ipv6",
332
+ "uri",
333
+ "uri-reference",
334
+ "iri",
335
+ "iri-reference",
336
+ "uuid",
337
+ "uri-template",
338
+ "json-pointer",
339
+ "relative-json-pointer",
340
+ "regex"
341
+ ];
342
+ if (!validFormats.includes(rawValue)) {
343
+ throw new GeneralError(JsonSchemaBuilder.CLASS_NAME, "invalidFormatValue", {
344
+ formatValue: rawValue,
345
+ validFormats: validFormats.join(", ")
346
+ });
347
+ }
348
+ }
349
+ }
268
350
  /**
269
351
  * Determine whether a mapped @json-schema tag key is supported.
270
352
  * @param key The mapped schema key.