// adapted from https://github.com/AitoDotAI/json-stringify-pretty-compact
// allows { } to be presented as {} to better mirror prettier formatting
function isObject(obj) {
    return typeof obj === 'object' && obj !== null;
}
function forEach(obj, cb) {
    if (Array.isArray(obj)) {
        // oxlint-disable-next-line unicorn/no-array-for-each
        obj.forEach(cb);
    }
    else if (isObject(obj)) {
        for (const key of Object.keys(obj)) {
            const val = obj[key];
            cb(val, key);
        }
    }
}
function getTreeDepth(obj) {
    let depth = 0;
    if (Array.isArray(obj) || isObject(obj)) {
        forEach(obj, (val) => {
            if (Array.isArray(val) || isObject(val)) {
                const tmpDepth = getTreeDepth(val);
                if (tmpDepth > depth) {
                    depth = tmpDepth;
                }
            }
        });
        return depth + 1;
    }
    return depth;
}
function get(options, name, defaultValue) {
    return (name in options ? options[name] : defaultValue);
}
// Note: This regex matches even invalid JSON strings, but since we’re
// working on the output of `JSON.stringify` we know that only valid strings
// are present (unless the user supplied a weird `options.indent` but in
// that case we don’t care since the output would be invalid anyway).
// This regex has been adjusted to allow replacement of { } and [ ] with {} and []
// to better mirror prettier formatting.
const stringOrChar = /("(?:[^\\"]|\\.)*")|[:,]|\{(?!})|(?<!\{)}|\[(?!])|(?<!\[)]/g;
function prettify(str, options = {}) {
    const tokens = {
        '{': '{',
        '}': '}',
        '[': '[',
        ']': ']',
        ',': ', ',
        ':': ': ',
    };
    if (!!options.addMargin || !!options.addObjectMargin) {
        tokens['{'] = '{ ';
        tokens['}'] = ' }';
    }
    if (!!options.addMargin || !!options.addArrayMargin) {
        tokens['['] = '[ ';
        tokens[']'] = ' ]';
    }
    return str.replaceAll(stringOrChar, (match, string) => string ? match : tokens[match]);
}
function stringifyPrettyCompact(rootObj, options = {}) {
    const indent = JSON.stringify([1], null, get(options, 'indent', 2)).slice(2, -3);
    const addMargin = get(options, 'margins', false);
    const addArrayMargin = get(options, 'arrayMargins', false);
    const addObjectMargin = get(options, 'objectMargins', true);
    const maxLength = indent === '' ? Infinity : get(options, 'maxLength', 80);
    const maxNesting = get(options, 'maxNesting', Infinity);
    return (function stringifyRecursive(obj, currentIndent, reserved) {
        if (obj &&
            typeof obj === 'object' &&
            typeof obj.toJSON === 'function') {
            // oxlint-disable-next-line typescript/no-confusing-void-expression
            obj = obj.toJSON();
        }
        const string = JSON.stringify(obj);
        // oxlint-disable-next-line typescript/no-unnecessary-condition
        if (string === undefined) {
            return string;
        }
        const length = maxLength - currentIndent.length - reserved;
        const treeDepth = getTreeDepth(obj);
        if (treeDepth <= maxNesting && string.length <= length) {
            const prettified = prettify(string, {
                addMargin,
                addArrayMargin,
                addObjectMargin,
            });
            if (prettified.length <= length) {
                return prettified;
            }
        }
        if (isObject(obj)) {
            const nextIndent = currentIndent + indent;
            const items = [];
            let delimiters;
            const atEndOfArray = (array, index) => index === array.length - 1 ? 0 : 1;
            if (Array.isArray(obj)) {
                for (let index = 0; index < obj.length; index += 1) {
                    items.push(stringifyRecursive(obj[index], nextIndent, atEndOfArray(obj, index)) || 'null');
                }
                delimiters = '[]';
            }
            else {
                // oxlint-disable-next-line unicorn/no-array-for-each
                Object.keys(obj).forEach((key, index, array) => {
                    const keyPart = `${JSON.stringify(key)}: `;
                    const value = stringifyRecursive(obj[key], nextIndent, keyPart.length + atEndOfArray(array, index));
                    // oxlint-disable-next-line typescript/no-unnecessary-condition
                    if (value !== undefined) {
                        items.push(keyPart + value);
                    }
                });
                delimiters = '{}';
            }
            if (items.length > 0) {
                return [
                    delimiters[0],
                    indent + items.join(`,\n${nextIndent}`),
                    delimiters[1],
                ].join(`\n${currentIndent}`);
            }
        }
        return string;
    })(rootObj, '', 0);
}

function isPlainObject(value) {
	if (typeof value !== 'object' || value === null) {
		return false;
	}

	const prototype = Object.getPrototypeOf(value);
	return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in value) && !(Symbol.iterator in value);
}

function sortKeys(object, options = {}) {
	if (!isPlainObject(object) && !Array.isArray(object)) {
		throw new TypeError('Expected a plain object or array');
	}

	const {deep, compare} = options;
	const cache = new WeakMap();

	const deepSortArray = array => {
		const resultFromCache = cache.get(array);
		if (resultFromCache !== undefined) {
			return resultFromCache;
		}

		const result = [];
		cache.set(array, result);

		result.push(...array.map(item => {
			if (Array.isArray(item)) {
				return deepSortArray(item);
			}

			if (isPlainObject(item)) {
				return _sortKeys(item);
			}

			return item;
		}));

		return result;
	};

	const _sortKeys = object => {
		const resultFromCache = cache.get(object);
		if (resultFromCache !== undefined) {
			return resultFromCache;
		}

		const result = {};
		const keys = Object.keys(object).sort(compare);

		cache.set(object, result);

		for (const key of keys) {
			const value = object[key];
			let newValue;

			if (deep && Array.isArray(value)) {
				newValue = deepSortArray(value);
			} else {
				newValue = deep && isPlainObject(value) ? _sortKeys(value) : value;
			}

			Object.defineProperty(result, key, {
				...Object.getOwnPropertyDescriptor(object, key),
				value: newValue,
			});
		}

		return result;
	};

	if (Array.isArray(object)) {
		return deep ? deepSortArray(object) : [...object];
	}

	return _sortKeys(object);
}

/**
 * Stringifies a value with stable pretty printing.
 *
 * That means the keys are sorted and the value is pretty printed.
 *
 * @param value - The value to stringify.
 * @returns The stringified value.
 */
function stringifyPrettyStable(value) {
    const sortedValue = sortKeys(value, {
        deep: true,
    });
    return `${stringifyPrettyCompact(sortedValue)}\n`;
}

export { stringifyPrettyStable as s };
//# sourceMappingURL=stringify-pretty-stable-CdD-vf_i.js.map
