// utils/Required.ts
/**
 * Marks a property as required and injects runtime validation into `willUpdate()`.
 * Use options to control whether it throws, logs a warning, or checks additional conditions.
 *
 * @example
 * ```ts
 * @Required()
 * foo: string;
 *
 * @Required({
 *   warnOnly: true,
 *   message: 'start must be a valid future date',
 *   condition: v => v instanceof Date && v > new Date()
 * })
 * start: Date;
 * ```
 *
 * @public
 */
export function Required(options) {
    return (proto, propKey) => {
        const key = propKey.toString();
        // Merge default options
        options = {
            warnOnly: false,
            message: undefined,
            condition: undefined,
            ...options
        };
        // Store metadata on prototype
        if (!proto.__requiredProps) {
            proto.__requiredProps = new Map();
        }
        proto.__requiredProps.set(key, options);
        // Patch willUpdate once
        const originalWillUpdate = proto.willUpdate;
        proto.willUpdate = function (changedProps) {
            originalWillUpdate?.call(this, changedProps);
            const props = proto.__requiredProps;
            if (!props) {
                return;
            }
            for (const [name, opt] of props) {
                const value = this[name];
                const isMissing = value == null;
                const failsCondition = typeof opt.condition === 'function' && !opt.condition(value);
                if (isMissing || failsCondition) {
                    const msg = opt.message ??
                        `[${this.constructor.name}] Required property '${name}' is missing or invalid.`;
                    if (opt.warnOnly) {
                        console.warn(msg);
                    }
                    else {
                        throw new Error(msg);
                    }
                }
            }
        };
    };
}
//# sourceMappingURL=RequiredDecorator.js.map