{"version":3,"file":"array-validator.mjs","names":[],"sources":["../../../../../../../@warlock.js/seal/src/validators/array-validator.ts"],"sourcesContent":["import { setKeyPath } from \"../helpers\";\r\nimport { flipArrayMutator, sortArrayMutator, uniqueArrayMutator } from \"../mutators\";\r\nimport {\r\n  arrayRule,\r\n  betweenLengthRule,\r\n  lengthRule,\r\n  maxLengthRule,\r\n  minLengthRule,\r\n  sortedArrayRule,\r\n  uniqueArrayRule,\r\n} from \"../rules\";\r\nimport type { SchemaContext, ValidationResult } from \"../types\";\r\nimport { BaseValidator } from \"./base-validator\";\r\nimport { applyNullable, getRuleOptions } from \"../standard-schema/json-schema\";\r\nimport type { JsonSchemaResult, JsonSchemaTarget } from \"../standard-schema/json-schema\";\r\n\r\n/**\r\n * Array validator class\r\n */\r\nexport class ArrayValidator extends BaseValidator {\r\n  public constructor(\r\n    public validator: BaseValidator,\r\n    errorMessage?: string,\r\n  ) {\r\n    super();\r\n    this.addMutableRule(arrayRule, errorMessage);\r\n  }\r\n\r\n  /**\r\n   * Check if value is an array type\r\n   */\r\n  public matchesType(value: any): boolean {\r\n    return Array.isArray(value);\r\n  }\r\n\r\n  /**\r\n   * Clone the validator\r\n   */\r\n  public override clone(): this {\r\n    const cloned = super.clone();\r\n\r\n    cloned.validator = this.validator.clone();\r\n\r\n    return cloned;\r\n  }\r\n\r\n  /** Reverse array order */\r\n  public flip() {\r\n    return this.addMutator(flipArrayMutator);\r\n  }\r\n\r\n  /** Reverse array order (alias) */\r\n  public reverse() {\r\n    return this.addMutator(flipArrayMutator);\r\n  }\r\n\r\n  /** Make it has only unique values */\r\n  public onlyUnique() {\r\n    return this.addMutator(uniqueArrayMutator);\r\n  }\r\n\r\n  /** Sort array */\r\n  public sort(direction: \"asc\" | \"desc\" = \"asc\", key?: string) {\r\n    return this.addMutator(sortArrayMutator, { direction, key });\r\n  }\r\n\r\n  /** Array length must be greater than the given length */\r\n  public minLength(length: number, errorMessage?: string) {\r\n    return this.addRule(minLengthRule, errorMessage, { minLength: length });\r\n  }\r\n\r\n  /** Array length must be less than the given length */\r\n  public maxLength(length: number, errorMessage?: string) {\r\n    return this.addRule(maxLengthRule, errorMessage, { maxLength: length });\r\n  }\r\n\r\n  /** Array length must be of the given length */\r\n  public length(length: number, errorMessage?: string) {\r\n    return this.addRule(lengthRule, errorMessage, { length });\r\n  }\r\n\r\n  /**\r\n   * Array length must be between min and max (inclusive)\r\n   *\r\n   * @param min - Minimum length (inclusive)\r\n   * @param max - Maximum length (inclusive)\r\n   *\r\n   * @example\r\n   * ```ts\r\n   * v.array(v.string()).between(1, 10)  // Array must have 1 to 10 items\r\n   * v.array(v.number()).lengthBetween(5, 20)  // Same using alias\r\n   * ```\r\n   *\r\n   * @category Validation Rule\r\n   */\r\n  public between(min: number, max: number, errorMessage?: string) {\r\n    return this.addRule(betweenLengthRule, errorMessage, {\r\n      minLength: min,\r\n      maxLength: max,\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Alias for between() - array length between min and max\r\n   */\r\n  public lengthBetween(min: number, max: number, errorMessage?: string) {\r\n    return this.between(min, max, errorMessage);\r\n  }\r\n\r\n  /** Array must have unique values */\r\n  public unique(errorMessage?: string) {\r\n    return this.addRule(uniqueArrayRule, errorMessage);\r\n  }\r\n\r\n  /** Array must be sorted */\r\n  public sorted(direction: \"asc\" | \"desc\" = \"asc\", errorMessage?: string) {\r\n    return this.addRule(sortedArrayRule, errorMessage, { direction });\r\n  }\r\n\r\n  /** Mutate the data */\r\n  public mutate(data: any, context: SchemaContext) {\r\n    if (!Array.isArray(data)) return data;\r\n    return super.mutate([...data], context);\r\n  }\r\n\r\n  /** Validate array\r\n   *\r\n   * Absent input (and absent without `.default()`) propagates as `data: undefined`\r\n   * so the parent ObjectValidator can omit the key. Without this, optional array\r\n   * fields would silently materialise as `[]` in the validated output.\r\n   */\r\n  public async validate(data: any, context: SchemaContext): Promise<ValidationResult> {\r\n    // Apply default when absent, then mutate. Mirrors BaseValidator's\r\n    // `valueForRules = data ?? this.getDefaultValue()` so `.default([...])`\r\n    // works on arrays too.\r\n    const valueForRules = data ?? this.getDefaultValue();\r\n    const mutatedData = await this.mutate(valueForRules, context);\r\n\r\n    const result = await super.validate(data, context);\r\n\r\n    if (result.isValid === false) return result;\r\n\r\n    // Nothing to iterate for absent (no default) or null (nullable) inputs —\r\n    // propagate so the parent ObjectValidator can omit the key.\r\n    if (mutatedData === undefined || mutatedData === null) return result;\r\n\r\n    // Defensive: type rule (arrayRule) should have failed for non-arrays.\r\n    if (!Array.isArray(mutatedData)) return result;\r\n\r\n    const errors: ValidationResult[\"errors\"] = [];\r\n\r\n    // Validate all items in parallel (consistent with ObjectValidator)\r\n    const validationPromises = mutatedData.map(async (value: any, index: number) => {\r\n      const childContext: SchemaContext = {\r\n        ...context,\r\n        parent: mutatedData,\r\n        value,\r\n        key: index.toString(),\r\n        path: setKeyPath(context.path, index.toString()),\r\n      };\r\n\r\n      const childResult = await this.validator.validate(value, childContext);\r\n\r\n      // Update mutated data with validated result\r\n      mutatedData[index] = childResult.data;\r\n\r\n      // Collect errors from this element\r\n      if (childResult.isValid === false) {\r\n        errors.push(...childResult.errors);\r\n      }\r\n    });\r\n\r\n    await Promise.all(validationPromises);\r\n\r\n    return {\r\n      isValid: errors.length === 0,\r\n      errors,\r\n      data: await this.startTransformationPipeline(mutatedData, context),\r\n    };\r\n  }\r\n\r\n  /**\r\n   * @inheritdoc\r\n   *\r\n   * Recursively generates JSON Schema for the array items.\r\n   *\r\n   * @example\r\n   * ```ts\r\n   * v.array(v.string().min(1)).minLength(1).toJsonSchema(\"draft-2020-12\")\r\n   * // → { type: \"array\", items: { type: \"string\", minLength: 1 }, minItems: 1 }\r\n   * ```\r\n   */\r\n  public override toJsonSchema(target: JsonSchemaTarget = \"draft-2020-12\"): JsonSchemaResult {\r\n    const schema: JsonSchemaResult = {\r\n      type: \"array\",\r\n      items: this.validator.toJsonSchema(target),\r\n    };\r\n\r\n    const minOpts = getRuleOptions(this.rules, \"minLength\");\r\n    if (minOpts?.minLength !== undefined) schema.minItems = minOpts.minLength;\r\n\r\n    const maxOpts = getRuleOptions(this.rules, \"maxLength\");\r\n    if (maxOpts?.maxLength !== undefined) schema.maxItems = maxOpts.maxLength;\r\n\r\n    const betweenOpts = getRuleOptions(this.rules, \"betweenLength\");\r\n    if (betweenOpts) {\r\n      if (betweenOpts.minLength !== undefined) schema.minItems = betweenOpts.minLength;\r\n      if (betweenOpts.maxLength !== undefined) schema.maxItems = betweenOpts.maxLength;\r\n    }\r\n\r\n    const lengthOpts = getRuleOptions(this.rules, \"length\");\r\n    if (lengthOpts?.length !== undefined) {\r\n      schema.minItems = lengthOpts.length;\r\n      schema.maxItems = lengthOpts.length;\r\n    }\r\n\r\n    if (this.isNullable) applyNullable(schema, target);\r\n\r\n    return schema;\r\n  }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;AAmBA,IAAa,iBAAb,cAAoC,cAAc;CAChD,AAAO,YACL,AAAO,WACP,cACA;EACA,MAAM;EAHC;EAIP,KAAK,eAAe,WAAW,YAAY;CAC7C;;;;CAKA,AAAO,YAAY,OAAqB;EACtC,OAAO,MAAM,QAAQ,KAAK;CAC5B;;;;CAKA,AAAgB,QAAc;EAC5B,MAAM,SAAS,MAAM,MAAM;EAE3B,OAAO,YAAY,KAAK,UAAU,MAAM;EAExC,OAAO;CACT;;CAGA,AAAO,OAAO;EACZ,OAAO,KAAK,WAAW,gBAAgB;CACzC;;CAGA,AAAO,UAAU;EACf,OAAO,KAAK,WAAW,gBAAgB;CACzC;;CAGA,AAAO,aAAa;EAClB,OAAO,KAAK,WAAW,kBAAkB;CAC3C;;CAGA,AAAO,KAAK,YAA4B,OAAO,KAAc;EAC3D,OAAO,KAAK,WAAW,kBAAkB;GAAE;GAAW;EAAI,CAAC;CAC7D;;CAGA,AAAO,UAAU,QAAgB,cAAuB;EACtD,OAAO,KAAK,QAAQ,eAAe,cAAc,EAAE,WAAW,OAAO,CAAC;CACxE;;CAGA,AAAO,UAAU,QAAgB,cAAuB;EACtD,OAAO,KAAK,QAAQ,eAAe,cAAc,EAAE,WAAW,OAAO,CAAC;CACxE;;CAGA,AAAO,OAAO,QAAgB,cAAuB;EACnD,OAAO,KAAK,QAAQ,YAAY,cAAc,EAAE,OAAO,CAAC;CAC1D;;;;;;;;;;;;;;;CAgBA,AAAO,QAAQ,KAAa,KAAa,cAAuB;EAC9D,OAAO,KAAK,QAAQ,mBAAmB,cAAc;GACnD,WAAW;GACX,WAAW;EACb,CAAC;CACH;;;;CAKA,AAAO,cAAc,KAAa,KAAa,cAAuB;EACpE,OAAO,KAAK,QAAQ,KAAK,KAAK,YAAY;CAC5C;;CAGA,AAAO,OAAO,cAAuB;EACnC,OAAO,KAAK,QAAQ,iBAAiB,YAAY;CACnD;;CAGA,AAAO,OAAO,YAA4B,OAAO,cAAuB;EACtE,OAAO,KAAK,QAAQ,iBAAiB,cAAc,EAAE,UAAU,CAAC;CAClE;;CAGA,AAAO,OAAO,MAAW,SAAwB;EAC/C,IAAI,CAAC,MAAM,QAAQ,IAAI,GAAG,OAAO;EACjC,OAAO,MAAM,OAAO,CAAC,GAAG,IAAI,GAAG,OAAO;CACxC;;;;;;;CAQA,MAAa,SAAS,MAAW,SAAmD;EAIlF,MAAM,gBAAgB,QAAQ,KAAK,gBAAgB;EACnD,MAAM,cAAc,MAAM,KAAK,OAAO,eAAe,OAAO;EAE5D,MAAM,SAAS,MAAM,MAAM,SAAS,MAAM,OAAO;EAEjD,IAAI,OAAO,YAAY,OAAO,OAAO;EAIrC,IAAI,gBAAgB,UAAa,gBAAgB,MAAM,OAAO;EAG9D,IAAI,CAAC,MAAM,QAAQ,WAAW,GAAG,OAAO;EAExC,MAAM,SAAqC,CAAC;EAG5C,MAAM,qBAAqB,YAAY,IAAI,OAAO,OAAY,UAAkB;GAC9E,MAAM,eAA8B;IAClC,GAAG;IACH,QAAQ;IACR;IACA,KAAK,MAAM,SAAS;IACpB,MAAM,WAAW,QAAQ,MAAM,MAAM,SAAS,CAAC;GACjD;GAEA,MAAM,cAAc,MAAM,KAAK,UAAU,SAAS,OAAO,YAAY;GAGrE,YAAY,SAAS,YAAY;GAGjC,IAAI,YAAY,YAAY,OAC1B,OAAO,KAAK,GAAG,YAAY,MAAM;EAErC,CAAC;EAED,MAAM,QAAQ,IAAI,kBAAkB;EAEpC,OAAO;GACL,SAAS,OAAO,WAAW;GAC3B;GACA,MAAM,MAAM,KAAK,4BAA4B,aAAa,OAAO;EACnE;CACF;;;;;;;;;;;;CAaA,AAAgB,aAAa,SAA2B,iBAAmC;EACzF,MAAM,SAA2B;GAC/B,MAAM;GACN,OAAO,KAAK,UAAU,aAAa,MAAM;EAC3C;EAEA,MAAM,UAAU,eAAe,KAAK,OAAO,WAAW;EACtD,IAAI,SAAS,cAAc,QAAW,OAAO,WAAW,QAAQ;EAEhE,MAAM,UAAU,eAAe,KAAK,OAAO,WAAW;EACtD,IAAI,SAAS,cAAc,QAAW,OAAO,WAAW,QAAQ;EAEhE,MAAM,cAAc,eAAe,KAAK,OAAO,eAAe;EAC9D,IAAI,aAAa;GACf,IAAI,YAAY,cAAc,QAAW,OAAO,WAAW,YAAY;GACvE,IAAI,YAAY,cAAc,QAAW,OAAO,WAAW,YAAY;EACzE;EAEA,MAAM,aAAa,eAAe,KAAK,OAAO,QAAQ;EACtD,IAAI,YAAY,WAAW,QAAW;GACpC,OAAO,WAAW,WAAW;GAC7B,OAAO,WAAW,WAAW;EAC/B;EAEA,IAAI,KAAK,YAAY,cAAc,QAAQ,MAAM;EAEjD,OAAO;CACT;AACF"}