/**
 * Default codec implementation for domain services.
 *
 * Provides canonical CBOR encoding/decoding using cbor-x directly,
 * avoiding concrete adapter imports from the infrastructure layer.
 *
 * Keys are recursively sorted before encoding for deterministic output,
 * which is critical for content-addressed storage (Git SHA matching).
 *
 * @module domain/utils/defaultCodec
 */
import { Encoder, decode as cborDecode } from 'cbor-x';
import CodecPort from "../../ports/CodecPort.js";
const encoder = new Encoder({
    useRecords: false,
    mapsAsObjects: true,
});
const CBOR_NATIVE = [Uint8Array, Date, RegExp, Set];
/**
 * Returns true if the value is a built-in type with its own CBOR encoding.
 */
function isCborNative(value) {
    return CBOR_NATIVE.some((T) => value instanceof T);
}
/**
 * Recursively sorts object keys for deterministic CBOR encoding.
 */
function sortKeys(value) {
    if (value === null || value === undefined) {
        return value;
    }
    if (typeof value !== 'object') {
        return value;
    }
    return sortObjectLike(value);
}
function sortObjectLike(value) {
    if (Array.isArray(value)) {
        return sortArray(value);
    }
    if (value instanceof Map) {
        return sortMapKeys(value);
    }
    if (isCborNative(value)) {
        return value;
    }
    return sortObjectKeys(value);
}
function sortArray(value) {
    return value.map(sortKeys);
}
/**
 * Sorts keys of a Map and recursively sorts nested values. Maps
 * flatten to plain records so the sorted form is a CodecValue.
 */
function sortMapKeys(map) {
    const sorted = {};
    for (const key of Array.from(map.keys()).sort()) {
        const value = map.get(key);
        if (value !== undefined) {
            sorted[String(key)] = sortKeys(value);
        }
    }
    return sorted;
}
/**
 * Sorts keys of any object and recursively sorts nested values.
 * Skips built-in types that have their own CBOR representation.
 */
function sortObjectKeys(obj) {
    if (isCborNative(obj)) {
        return obj;
    }
    const sorted = {};
    for (const key of Object.keys(obj).sort()) {
        const value = obj[key];
        if (value !== undefined) {
            sorted[key] = sortKeys(value);
        }
    }
    return sorted;
}
/**
 * Default CBOR codec used by domain services that receive no codec
 * override. Delegates encoding to cbor-x with canonical key ordering.
 */
class DefaultCodec extends CodecPort {
    encode(data) {
        return encoder.encode(sortKeys(data));
    }
    decode(buffer) {
        return cborDecode(buffer);
    }
}
const defaultCodec = new DefaultCodec();
Object.freeze(defaultCodec);
export default defaultCodec;
