"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.sanitizeFilename = exports.hexColor = exports.JsonParsed = exports.stringToBool = exports.longitudeSchema = exports.latitudeSchema = exports.isoDateToDate = exports.isoDatetimeToDate = exports.toEmail = exports.FilenameParamDto = exports.UUIDAssetIDParamDto = exports.UUIDv7ParamDto = exports.UUIDParamDto = exports.FileNotEmptyValidator = exports.ParseMeUUIDPipe = void 0;
exports.IsIPRange = IsIPRange;
exports.nonEmptyPartial = nonEmptyPartial;
exports.IsNotSiblingOf = IsNotSiblingOf;
const common_1 = require("@nestjs/common");
const luxon_1 = require("luxon");
const nestjs_zod_1 = require("nestjs-zod");
const sanitize_filename_1 = __importDefault(require("sanitize-filename"));
const validator_1 = require("validator");
const zod_1 = __importDefault(require("zod"));
function isIPOrRange(value, options) {
    const { requireCIDR = true } = options ?? {};
    if ((0, validator_1.isIPRange)(value)) {
        return true;
    }
    if (!requireCIDR && (0, validator_1.isIP)(value)) {
        return true;
    }
    return false;
}
function IsIPRange(options) {
    return zod_1.default
        .array(zod_1.default.string())
        .refine((arr) => arr.every((item) => isIPOrRange(item, options)), 'Must be an ip address or ip address range');
}
function nonEmptyPartial(shape) {
    return zod_1.default
        .object(shape)
        .partial()
        .refine((data) => Object.values(data).some((value) => value !== undefined), {
        message: 'At least one field must be provided',
    });
}
function IsNotSiblingOf(_schema, property, siblings) {
    const message = `${String(property)} cannot exist alongside ${siblings.join(' or ')}`;
    return zod_1.default.custom().refine((data) => {
        if (data[property] === undefined) {
            return true;
        }
        return siblings.every((sibling) => data[sibling] === undefined);
    }, { message });
}
let ParseMeUUIDPipe = class ParseMeUUIDPipe extends common_1.ParseUUIDPipe {
    async transform(value, metadata) {
        if (value == 'me') {
            return value;
        }
        return super.transform(value, metadata);
    }
};
exports.ParseMeUUIDPipe = ParseMeUUIDPipe;
exports.ParseMeUUIDPipe = ParseMeUUIDPipe = __decorate([
    (0, common_1.Injectable)()
], ParseMeUUIDPipe);
let FileNotEmptyValidator = class FileNotEmptyValidator extends common_1.FileValidator {
    requiredFields;
    constructor(requiredFields) {
        super({});
        this.requiredFields = requiredFields;
        this.requiredFields = requiredFields;
    }
    isValid(files) {
        if (!files) {
            return false;
        }
        return this.requiredFields.every((field) => files[field]);
    }
    buildErrorMessage() {
        return `Field(s) ${this.requiredFields.join(', ')} should not be empty`;
    }
};
exports.FileNotEmptyValidator = FileNotEmptyValidator;
exports.FileNotEmptyValidator = FileNotEmptyValidator = __decorate([
    (0, common_1.Injectable)(),
    __metadata("design:paramtypes", [Array])
], FileNotEmptyValidator);
const UUIDParamSchema = zod_1.default.object({
    id: zod_1.default.uuidv4(),
});
class UUIDParamDto extends (0, nestjs_zod_1.createZodDto)(UUIDParamSchema) {
}
exports.UUIDParamDto = UUIDParamDto;
const UUIDv7ParamSchema = zod_1.default.object({
    id: zod_1.default.uuidv7(),
});
class UUIDv7ParamDto extends (0, nestjs_zod_1.createZodDto)(UUIDv7ParamSchema) {
}
exports.UUIDv7ParamDto = UUIDv7ParamDto;
const UUIDAssetIDParamSchema = zod_1.default.object({
    id: zod_1.default.uuidv4(),
    assetId: zod_1.default.uuidv4(),
});
class UUIDAssetIDParamDto extends (0, nestjs_zod_1.createZodDto)(UUIDAssetIDParamSchema) {
}
exports.UUIDAssetIDParamDto = UUIDAssetIDParamDto;
const FilenameParamSchema = zod_1.default.object({
    filename: zod_1.default.string().regex(/^[a-zA-Z0-9_\-.]+$/, {
        error: 'Filename contains invalid characters',
    }),
});
class FilenameParamDto extends (0, nestjs_zod_1.createZodDto)(FilenameParamSchema) {
}
exports.FilenameParamDto = FilenameParamDto;
exports.toEmail = zod_1.default
    .email({
    pattern: zod_1.default.regexes.html5Email,
    error: (iss) => `Invalid input: expected email, received ${typeof iss.input}`,
})
    .transform((val) => val.toLowerCase());
exports.isoDatetimeToDate = zod_1.default
    .codec(zod_1.default.iso.datetime({
    error: (iss) => `Invalid input: expected ISO 8601 datetime string, received ${typeof iss.input}`,
    offset: true,
}), zod_1.default.date(), {
    decode: (isoString) => new Date(isoString),
    encode: (date) => date.toISOString(),
})
    .meta({ example: '2024-01-01T00:00:00.000Z' });
exports.isoDateToDate = zod_1.default
    .codec(zod_1.default.iso.date({
    error: (iss) => `Invalid input: expected ISO date string (YYYY-MM-DD), received ${typeof iss.input}`,
}), zod_1.default.date(), {
    decode: (isoString) => new Date(isoString),
    encode: (date) => luxon_1.DateTime.fromJSDate(date).toFormat('yyyy-MM-dd'),
})
    .meta({ example: '2024-01-01' });
exports.latitudeSchema = zod_1.default.number().min(-90).max(90);
exports.longitudeSchema = zod_1.default.number().min(-180).max(180);
exports.stringToBool = zod_1.default
    .stringbool({ truthy: ['true'], falsy: ['false'], case: 'sensitive' })
    .meta({ type: 'boolean' });
exports.JsonParsed = zod_1.default.transform((val, ctx) => {
    if (typeof val === 'string') {
        try {
            return JSON.parse(val);
        }
        catch {
            ctx.issues.push({
                code: 'custom',
                message: `Invalid input: expected JSON string, received ${typeof val}`,
                input: val,
            });
            return zod_1.default.NEVER;
        }
    }
    return val;
});
const hexColorRegex = /^#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/;
exports.hexColor = zod_1.default
    .string()
    .regex(hexColorRegex)
    .transform((val) => (val.startsWith('#') ? val : `#${val}`));
exports.sanitizeFilename = zod_1.default.string().transform((val) => (0, sanitize_filename_1.default)(val.replaceAll('.', '')));
//# sourceMappingURL=validation.js.map