#!/usr/bin/env node
import { mkdirSync, existsSync, readFileSync, writeFileSync } from 'fs';
import { resolve, dirname } from 'path';

/*!
 * Copyright (c) Squirrel Chat et al., All rights reserved.
 * SPDX-License-Identifier: BSD-3-Clause
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
function getLineColFromPtr(string, ptr) {
    let lines = string.slice(0, ptr).split(/\r\n|\n|\r/g);
    return [lines.length, lines.pop().length + 1];
}
function makeCodeBlock(string, line, column) {
    let lines = string.split(/\r\n|\n|\r/g);
    let codeblock = '';
    let numberLen = (Math.log10(line + 1) | 0) + 1;
    for (let i = line - 1; i <= line + 1; i++) {
        let l = lines[i - 1];
        if (!l)
            continue;
        codeblock += i.toString().padEnd(numberLen, ' ');
        codeblock += ':  ';
        codeblock += l;
        codeblock += '\n';
        if (i === line) {
            codeblock += ' '.repeat(numberLen + column + 2);
            codeblock += '^\n';
        }
    }
    return codeblock;
}
class TomlError extends Error {
    line;
    column;
    codeblock;
    constructor(message, options) {
        const [line, column] = getLineColFromPtr(options.toml, options.ptr);
        const codeblock = makeCodeBlock(options.toml, line, column);
        super(`Invalid TOML document: ${message}\n\n${codeblock}`, options);
        this.line = line;
        this.column = column;
        this.codeblock = codeblock;
    }
}

/*!
 * Copyright (c) Squirrel Chat et al., All rights reserved.
 * SPDX-License-Identifier: BSD-3-Clause
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
function isEscaped(str, ptr) {
    let i = 0;
    while (str[ptr - ++i] === '\\')
        ;
    return --i && (i % 2);
}
function indexOfNewline(str, start = 0, end = str.length) {
    let idx = str.indexOf('\n', start);
    if (str[idx - 1] === '\r')
        idx--;
    return idx <= end ? idx : -1;
}
function skipComment(str, ptr) {
    for (let i = ptr; i < str.length; i++) {
        let c = str[i];
        if (c === '\n')
            return i;
        if (c === '\r' && str[i + 1] === '\n')
            return i + 1;
        if ((c < '\x20' && c !== '\t') || c === '\x7f') {
            throw new TomlError('control characters are not allowed in comments', {
                toml: str,
                ptr: ptr,
            });
        }
    }
    return str.length;
}
function skipVoid(str, ptr, banNewLines, banComments) {
    let c;
    while ((c = str[ptr]) === ' ' || c === '\t' || (!banNewLines && (c === '\n' || c === '\r' && str[ptr + 1] === '\n')))
        ptr++;
    return banComments || c !== '#'
        ? ptr
        : skipVoid(str, skipComment(str, ptr), banNewLines);
}
function skipUntil(str, ptr, sep, end, banNewLines = false) {
    if (!end) {
        ptr = indexOfNewline(str, ptr);
        return ptr < 0 ? str.length : ptr;
    }
    for (let i = ptr; i < str.length; i++) {
        let c = str[i];
        if (c === '#') {
            i = indexOfNewline(str, i);
        }
        else if (c === sep) {
            return i + 1;
        }
        else if (c === end || (banNewLines && (c === '\n' || (c === '\r' && str[i + 1] === '\n')))) {
            return i;
        }
    }
    throw new TomlError('cannot find end of structure', {
        toml: str,
        ptr: ptr
    });
}
function getStringEnd(str, seek) {
    let first = str[seek];
    let target = first === str[seek + 1] && str[seek + 1] === str[seek + 2]
        ? str.slice(seek, seek + 3)
        : first;
    seek += target.length - 1;
    do
        seek = str.indexOf(target, ++seek);
    while (seek > -1 && first !== "'" && isEscaped(str, seek));
    if (seek > -1) {
        seek += target.length;
        if (target.length > 1) {
            if (str[seek] === first)
                seek++;
            if (str[seek] === first)
                seek++;
        }
    }
    return seek;
}

/*!
 * Copyright (c) Squirrel Chat et al., All rights reserved.
 * SPDX-License-Identifier: BSD-3-Clause
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
let DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;
class TomlDate extends Date {
    #hasDate = false;
    #hasTime = false;
    #offset = null;
    constructor(date) {
        let hasDate = true;
        let hasTime = true;
        let offset = 'Z';
        if (typeof date === 'string') {
            let match = date.match(DATE_TIME_RE);
            if (match) {
                if (!match[1]) {
                    hasDate = false;
                    date = `0000-01-01T${date}`;
                }
                hasTime = !!match[2];
                // Make sure to use T instead of a space. Breaks in case of extreme values otherwise.
                hasTime && date[10] === ' ' && (date = date.replace(' ', 'T'));
                // Do not allow rollover hours.
                if (match[2] && +match[2] > 23) {
                    date = '';
                }
                else {
                    offset = match[3] || null;
                    date = date.toUpperCase();
                    if (!offset && hasTime)
                        date += 'Z';
                }
            }
            else {
                date = '';
            }
        }
        super(date);
        if (!isNaN(this.getTime())) {
            this.#hasDate = hasDate;
            this.#hasTime = hasTime;
            this.#offset = offset;
        }
    }
    isDateTime() {
        return this.#hasDate && this.#hasTime;
    }
    isLocal() {
        return !this.#hasDate || !this.#hasTime || !this.#offset;
    }
    isDate() {
        return this.#hasDate && !this.#hasTime;
    }
    isTime() {
        return this.#hasTime && !this.#hasDate;
    }
    isValid() {
        return this.#hasDate || this.#hasTime;
    }
    toISOString() {
        let iso = super.toISOString();
        // Local Date
        if (this.isDate())
            return iso.slice(0, 10);
        // Local Time
        if (this.isTime())
            return iso.slice(11, 23);
        // Local DateTime
        if (this.#offset === null)
            return iso.slice(0, -1);
        // Offset DateTime
        if (this.#offset === 'Z')
            return iso;
        // This part is quite annoying: JS strips the original timezone from the ISO string representation
        // Instead of using a "modified" date and "Z", we restore the representation "as authored"
        let offset = (+(this.#offset.slice(1, 3)) * 60) + +(this.#offset.slice(4, 6));
        offset = this.#offset[0] === '-' ? offset : -offset;
        let offsetDate = new Date(this.getTime() - (offset * 60e3));
        return offsetDate.toISOString().slice(0, -1) + this.#offset;
    }
    static wrapAsOffsetDateTime(jsDate, offset = 'Z') {
        let date = new TomlDate(jsDate);
        date.#offset = offset;
        return date;
    }
    static wrapAsLocalDateTime(jsDate) {
        let date = new TomlDate(jsDate);
        date.#offset = null;
        return date;
    }
    static wrapAsLocalDate(jsDate) {
        let date = new TomlDate(jsDate);
        date.#hasTime = false;
        date.#offset = null;
        return date;
    }
    static wrapAsLocalTime(jsDate) {
        let date = new TomlDate(jsDate);
        date.#hasDate = false;
        date.#offset = null;
        return date;
    }
}

/*!
 * Copyright (c) Squirrel Chat et al., All rights reserved.
 * SPDX-License-Identifier: BSD-3-Clause
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
let INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/;
let FLOAT_REGEX = /^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/;
let LEADING_ZERO = /^[+-]?0[0-9_]/;
let ESCAPE_REGEX = /^[0-9a-f]{2,8}$/i;
let ESC_MAP = {
    b: '\b',
    t: '\t',
    n: '\n',
    f: '\f',
    r: '\r',
    e: '\x1b',
    '"': '"',
    '\\': '\\',
};
function parseString(str, ptr = 0, endPtr = str.length) {
    let isLiteral = str[ptr] === '\'';
    let isMultiline = str[ptr++] === str[ptr] && str[ptr] === str[ptr + 1];
    if (isMultiline) {
        endPtr -= 2;
        if (str[ptr += 2] === '\r')
            ptr++;
        if (str[ptr] === '\n')
            ptr++;
    }
    let tmp = 0;
    let isEscape;
    let parsed = '';
    let sliceStart = ptr;
    while (ptr < endPtr - 1) {
        let c = str[ptr++];
        if (c === '\n' || (c === '\r' && str[ptr] === '\n')) {
            if (!isMultiline) {
                throw new TomlError('newlines are not allowed in strings', {
                    toml: str,
                    ptr: ptr - 1,
                });
            }
        }
        else if ((c < '\x20' && c !== '\t') || c === '\x7f') {
            throw new TomlError('control characters are not allowed in strings', {
                toml: str,
                ptr: ptr - 1,
            });
        }
        if (isEscape) {
            isEscape = false;
            if (c === 'x' || c === 'u' || c === 'U') {
                // Unicode escape
                let code = str.slice(ptr, (ptr += (c === 'x' ? 2 : c === 'u' ? 4 : 8)));
                if (!ESCAPE_REGEX.test(code)) {
                    throw new TomlError('invalid unicode escape', {
                        toml: str,
                        ptr: tmp,
                    });
                }
                try {
                    parsed += String.fromCodePoint(parseInt(code, 16));
                }
                catch {
                    throw new TomlError('invalid unicode escape', {
                        toml: str,
                        ptr: tmp,
                    });
                }
            }
            else if (isMultiline && (c === '\n' || c === ' ' || c === '\t' || c === '\r')) {
                // Multiline escape
                ptr = skipVoid(str, ptr - 1, true);
                if (str[ptr] !== '\n' && str[ptr] !== '\r') {
                    throw new TomlError('invalid escape: only line-ending whitespace may be escaped', {
                        toml: str,
                        ptr: tmp,
                    });
                }
                ptr = skipVoid(str, ptr);
            }
            else if (c in ESC_MAP) {
                // Classic escape
                parsed += ESC_MAP[c];
            }
            else {
                throw new TomlError('unrecognized escape sequence', {
                    toml: str,
                    ptr: tmp,
                });
            }
            sliceStart = ptr;
        }
        else if (!isLiteral && c === '\\') {
            tmp = ptr - 1;
            isEscape = true;
            parsed += str.slice(sliceStart, tmp);
        }
    }
    return parsed + str.slice(sliceStart, endPtr - 1);
}
function parseValue(value, toml, ptr, integersAsBigInt) {
    // Constant values
    if (value === 'true')
        return true;
    if (value === 'false')
        return false;
    if (value === '-inf')
        return -Infinity;
    if (value === 'inf' || value === '+inf')
        return Infinity;
    if (value === 'nan' || value === '+nan' || value === '-nan')
        return NaN;
    // Avoid FP representation of -0
    if (value === '-0')
        return integersAsBigInt ? 0n : 0;
    // Numbers
    let isInt = INT_REGEX.test(value);
    if (isInt || FLOAT_REGEX.test(value)) {
        if (LEADING_ZERO.test(value)) {
            throw new TomlError('leading zeroes are not allowed', {
                toml: toml,
                ptr: ptr,
            });
        }
        value = value.replace(/_/g, '');
        let numeric = +value;
        if (isNaN(numeric)) {
            throw new TomlError('invalid number', {
                toml: toml,
                ptr: ptr,
            });
        }
        if (isInt) {
            if ((isInt = !Number.isSafeInteger(numeric)) && !integersAsBigInt) {
                throw new TomlError('integer value cannot be represented losslessly', {
                    toml: toml,
                    ptr: ptr,
                });
            }
            if (isInt || integersAsBigInt === true)
                numeric = BigInt(value);
        }
        return numeric;
    }
    const date = new TomlDate(value);
    if (!date.isValid()) {
        throw new TomlError('invalid value', {
            toml: toml,
            ptr: ptr,
        });
    }
    return date;
}

/*!
 * Copyright (c) Squirrel Chat et al., All rights reserved.
 * SPDX-License-Identifier: BSD-3-Clause
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
function sliceAndTrimEndOf(str, startPtr, endPtr) {
    let value = str.slice(startPtr, endPtr);
    let commentIdx = value.indexOf('#');
    if (commentIdx > -1) {
        // The call to skipComment allows to "validate" the comment
        // (absence of control characters)
        skipComment(str, commentIdx);
        value = value.slice(0, commentIdx);
    }
    return [value.trimEnd(), commentIdx];
}
function extractValue(str, ptr, end, depth, integersAsBigInt) {
    if (depth === 0) {
        throw new TomlError('document contains excessively nested structures. aborting.', {
            toml: str,
            ptr: ptr
        });
    }
    let c = str[ptr];
    if (c === '[' || c === '{') {
        let [value, endPtr] = c === '['
            ? parseArray(str, ptr, depth, integersAsBigInt)
            : parseInlineTable(str, ptr, depth, integersAsBigInt);
        if (end) {
            endPtr = skipVoid(str, endPtr);
            if (str[endPtr] === ',')
                endPtr++;
            else if (str[endPtr] !== end) {
                throw new TomlError('expected comma or end of structure', {
                    toml: str,
                    ptr: endPtr,
                });
            }
        }
        return [value, endPtr];
    }
    let endPtr;
    if (c === '"' || c === "'") {
        endPtr = getStringEnd(str, ptr);
        let parsed = parseString(str, ptr, endPtr);
        if (end) {
            endPtr = skipVoid(str, endPtr);
            if (str[endPtr] && str[endPtr] !== ',' && str[endPtr] !== end && str[endPtr] !== '\n' && str[endPtr] !== '\r') {
                throw new TomlError('unexpected character encountered', {
                    toml: str,
                    ptr: endPtr,
                });
            }
            endPtr += (+(str[endPtr] === ','));
        }
        return [parsed, endPtr];
    }
    endPtr = skipUntil(str, ptr, ',', end);
    let slice = sliceAndTrimEndOf(str, ptr, endPtr - (+(str[endPtr - 1] === ',')));
    if (!slice[0]) {
        throw new TomlError('incomplete key-value declaration: no value specified', {
            toml: str,
            ptr: ptr
        });
    }
    if (end && slice[1] > -1) {
        endPtr = skipVoid(str, ptr + slice[1]);
        endPtr += +(str[endPtr] === ',');
    }
    return [
        parseValue(slice[0], str, ptr, integersAsBigInt),
        endPtr,
    ];
}

/*!
 * Copyright (c) Squirrel Chat et al., All rights reserved.
 * SPDX-License-Identifier: BSD-3-Clause
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
let KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/;
function parseKey(str, ptr, end = '=') {
    let dot = ptr - 1;
    let parsed = [];
    let endPtr = str.indexOf(end, ptr);
    if (endPtr < 0) {
        throw new TomlError('incomplete key-value: cannot find end of key', {
            toml: str,
            ptr: ptr,
        });
    }
    do {
        let c = str[ptr = ++dot];
        // If it's whitespace, ignore
        if (c !== ' ' && c !== '\t') {
            // If it's a string
            if (c === '"' || c === '\'') {
                if (c === str[ptr + 1] && c === str[ptr + 2]) {
                    throw new TomlError('multiline strings are not allowed in keys', {
                        toml: str,
                        ptr: ptr,
                    });
                }
                let eos = getStringEnd(str, ptr);
                if (eos < 0) {
                    throw new TomlError('unfinished string encountered', {
                        toml: str,
                        ptr: ptr,
                    });
                }
                dot = str.indexOf('.', eos);
                let strEnd = str.slice(eos, dot < 0 || dot > endPtr ? endPtr : dot);
                let newLine = indexOfNewline(strEnd);
                if (newLine > -1) {
                    throw new TomlError('newlines are not allowed in keys', {
                        toml: str,
                        ptr: ptr + dot + newLine,
                    });
                }
                if (strEnd.trimStart()) {
                    throw new TomlError('found extra tokens after the string part', {
                        toml: str,
                        ptr: eos,
                    });
                }
                if (endPtr < eos) {
                    endPtr = str.indexOf(end, eos);
                    if (endPtr < 0) {
                        throw new TomlError('incomplete key-value: cannot find end of key', {
                            toml: str,
                            ptr: ptr,
                        });
                    }
                }
                parsed.push(parseString(str, ptr, eos));
            }
            else {
                // Normal raw key part consumption and validation
                dot = str.indexOf('.', ptr);
                let part = str.slice(ptr, dot < 0 || dot > endPtr ? endPtr : dot);
                if (!KEY_PART_RE.test(part)) {
                    throw new TomlError('only letter, numbers, dashes and underscores are allowed in keys', {
                        toml: str,
                        ptr: ptr,
                    });
                }
                parsed.push(part.trimEnd());
            }
        }
        // Until there's no more dot
    } while (dot + 1 && dot < endPtr);
    return [parsed, skipVoid(str, endPtr + 1, true, true)];
}
function parseInlineTable(str, ptr, depth, integersAsBigInt) {
    let res = {};
    let seen = new Set();
    let c;
    ptr++;
    while ((c = str[ptr++]) !== '}' && c) {
        if (c === ',') {
            throw new TomlError('expected value, found comma', {
                toml: str,
                ptr: ptr - 1,
            });
        }
        else if (c === '#')
            ptr = skipComment(str, ptr);
        else if (c !== ' ' && c !== '\t' && c !== '\n' && c !== '\r') {
            let k;
            let t = res;
            let hasOwn = false;
            let [key, keyEndPtr] = parseKey(str, ptr - 1);
            for (let i = 0; i < key.length; i++) {
                if (i)
                    t = hasOwn ? t[k] : (t[k] = {});
                k = key[i];
                if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== 'object' || seen.has(t[k]))) {
                    throw new TomlError('trying to redefine an already defined value', {
                        toml: str,
                        ptr: ptr,
                    });
                }
                if (!hasOwn && k === '__proto__') {
                    Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
                }
            }
            if (hasOwn) {
                throw new TomlError('trying to redefine an already defined value', {
                    toml: str,
                    ptr: ptr,
                });
            }
            let [value, valueEndPtr] = extractValue(str, keyEndPtr, '}', depth - 1, integersAsBigInt);
            seen.add(value);
            t[k] = value;
            ptr = valueEndPtr;
        }
    }
    if (!c) {
        throw new TomlError('unfinished table encountered', {
            toml: str,
            ptr: ptr,
        });
    }
    return [res, ptr];
}
function parseArray(str, ptr, depth, integersAsBigInt) {
    let res = [];
    let c;
    ptr++;
    while ((c = str[ptr++]) !== ']' && c) {
        if (c === ',') {
            throw new TomlError('expected value, found comma', {
                toml: str,
                ptr: ptr - 1,
            });
        }
        else if (c === '#')
            ptr = skipComment(str, ptr);
        else if (c !== ' ' && c !== '\t' && c !== '\n' && c !== '\r') {
            let e = extractValue(str, ptr - 1, ']', depth - 1, integersAsBigInt);
            res.push(e[0]);
            ptr = e[1];
        }
    }
    if (!c) {
        throw new TomlError('unfinished array encountered', {
            toml: str,
            ptr: ptr,
        });
    }
    return [res, ptr];
}

/*!
 * Copyright (c) Squirrel Chat et al., All rights reserved.
 * SPDX-License-Identifier: BSD-3-Clause
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
function peekTable(key, table, meta, type) {
    let t = table;
    let m = meta;
    let k;
    let hasOwn = false;
    let state;
    for (let i = 0; i < key.length; i++) {
        if (i) {
            t = hasOwn ? t[k] : (t[k] = {});
            m = (state = m[k]).c;
            if (type === 0 /* Type.DOTTED */ && (state.t === 1 /* Type.EXPLICIT */ || state.t === 2 /* Type.ARRAY */)) {
                return null;
            }
            if (state.t === 2 /* Type.ARRAY */) {
                let l = t.length - 1;
                t = t[l];
                m = m[l].c;
            }
        }
        k = key[i];
        if ((hasOwn = Object.hasOwn(t, k)) && m[k]?.t === 0 /* Type.DOTTED */ && m[k]?.d) {
            return null;
        }
        if (!hasOwn) {
            if (k === '__proto__') {
                Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
                Object.defineProperty(m, k, { enumerable: true, configurable: true, writable: true });
            }
            m[k] = {
                t: i < key.length - 1 && type === 2 /* Type.ARRAY */
                    ? 3 /* Type.ARRAY_DOTTED */
                    : type,
                d: false,
                i: 0,
                c: {},
            };
        }
    }
    state = m[k];
    if (state.t !== type && !(type === 1 /* Type.EXPLICIT */ && state.t === 3 /* Type.ARRAY_DOTTED */)) {
        // Bad key type!
        return null;
    }
    if (type === 2 /* Type.ARRAY */) {
        if (!state.d) {
            state.d = true;
            t[k] = [];
        }
        t[k].push(t = {});
        state.c[state.i++] = (state = { t: 1 /* Type.EXPLICIT */, d: false, i: 0, c: {} });
    }
    if (state.d) {
        // Redefining a table!
        return null;
    }
    state.d = true;
    if (type === 1 /* Type.EXPLICIT */) {
        t = hasOwn ? t[k] : (t[k] = {});
    }
    else if (type === 0 /* Type.DOTTED */ && hasOwn) {
        return null;
    }
    return [k, t, state.c];
}
function parse(toml, { maxDepth = 1000, integersAsBigInt } = {}) {
    let res = {};
    let meta = {};
    let tbl = res;
    let m = meta;
    for (let ptr = skipVoid(toml, 0); ptr < toml.length;) {
        if (toml[ptr] === '[') {
            let isTableArray = toml[++ptr] === '[';
            let k = parseKey(toml, ptr += +isTableArray, ']');
            if (isTableArray) {
                if (toml[k[1] - 1] !== ']') {
                    throw new TomlError('expected end of table declaration', {
                        toml: toml,
                        ptr: k[1] - 1,
                    });
                }
                k[1]++;
            }
            let p = peekTable(k[0], res, meta, isTableArray ? 2 /* Type.ARRAY */ : 1 /* Type.EXPLICIT */);
            if (!p) {
                throw new TomlError('trying to redefine an already defined table or value', {
                    toml: toml,
                    ptr: ptr,
                });
            }
            m = p[2];
            tbl = p[1];
            ptr = k[1];
        }
        else {
            let k = parseKey(toml, ptr);
            let p = peekTable(k[0], tbl, m, 0 /* Type.DOTTED */);
            if (!p) {
                throw new TomlError('trying to redefine an already defined table or value', {
                    toml: toml,
                    ptr: ptr,
                });
            }
            let v = extractValue(toml, k[1], void 0, maxDepth, integersAsBigInt);
            p[1][p[0]] = v[0];
            ptr = v[1];
        }
        ptr = skipVoid(toml, ptr, true);
        if (toml[ptr] && toml[ptr] !== '\n' && toml[ptr] !== '\r') {
            throw new TomlError('each key-value declaration must be followed by an end-of-line', {
                toml: toml,
                ptr: ptr
            });
        }
        ptr = skipVoid(toml, ptr);
    }
    return res;
}

/*!
 * Copyright (c) Squirrel Chat et al., All rights reserved.
 * SPDX-License-Identifier: BSD-3-Clause
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
let BARE_KEY = /^[a-z0-9-_]+$/i;
function extendedTypeOf(obj) {
    let type = typeof obj;
    if (type === 'object') {
        if (Array.isArray(obj))
            return 'array';
        if (obj instanceof Date)
            return 'date';
    }
    return type;
}
function isArrayOfTables(obj) {
    for (let i = 0; i < obj.length; i++) {
        if (extendedTypeOf(obj[i]) !== 'object')
            return false;
    }
    return obj.length != 0;
}
function formatString(s) {
    return JSON.stringify(s).replace(/\x7f/g, '\\u007f');
}
function stringifyValue(val, type, depth, numberAsFloat) {
    if (depth === 0) {
        throw new Error('Could not stringify the object: maximum object depth exceeded');
    }
    if (type === 'number') {
        if (isNaN(val))
            return 'nan';
        if (val === Infinity)
            return 'inf';
        if (val === -Infinity)
            return '-inf';
        if (numberAsFloat && Number.isInteger(val))
            return val.toFixed(1);
        return val.toString();
    }
    if (type === 'bigint' || type === 'boolean') {
        return val.toString();
    }
    if (type === 'string') {
        return formatString(val);
    }
    if (type === 'date') {
        if (isNaN(val.getTime())) {
            throw new TypeError('cannot serialize invalid date');
        }
        return val.toISOString();
    }
    if (type === 'object') {
        return stringifyInlineTable(val, depth, numberAsFloat);
    }
    if (type === 'array') {
        return stringifyArray(val, depth, numberAsFloat);
    }
}
function stringifyInlineTable(obj, depth, numberAsFloat) {
    let keys = Object.keys(obj);
    if (keys.length === 0)
        return '{}';
    let res = '{ ';
    for (let i = 0; i < keys.length; i++) {
        let k = keys[i];
        if (i)
            res += ', ';
        res += BARE_KEY.test(k) ? k : formatString(k);
        res += ' = ';
        res += stringifyValue(obj[k], extendedTypeOf(obj[k]), depth - 1, numberAsFloat);
    }
    return res + ' }';
}
function stringifyArray(array, depth, numberAsFloat) {
    if (array.length === 0)
        return '[]';
    let res = '[ ';
    for (let i = 0; i < array.length; i++) {
        if (i)
            res += ', ';
        if (array[i] === null || array[i] === void 0) {
            throw new TypeError('arrays cannot contain null or undefined values');
        }
        res += stringifyValue(array[i], extendedTypeOf(array[i]), depth - 1, numberAsFloat);
    }
    return res + ' ]';
}
function stringifyArrayTable(array, key, depth, numberAsFloat) {
    if (depth === 0) {
        throw new Error('Could not stringify the object: maximum object depth exceeded');
    }
    let res = '';
    for (let i = 0; i < array.length; i++) {
        res += `${res && '\n'}[[${key}]]\n`;
        res += stringifyTable(0, array[i], key, depth, numberAsFloat);
    }
    return res;
}
function stringifyTable(tableKey, obj, prefix, depth, numberAsFloat) {
    if (depth === 0) {
        throw new Error('Could not stringify the object: maximum object depth exceeded');
    }
    let preamble = '';
    let tables = '';
    let keys = Object.keys(obj);
    for (let i = 0; i < keys.length; i++) {
        let k = keys[i];
        if (obj[k] !== null && obj[k] !== void 0) {
            let type = extendedTypeOf(obj[k]);
            if (type === 'symbol' || type === 'function') {
                throw new TypeError(`cannot serialize values of type '${type}'`);
            }
            let key = BARE_KEY.test(k) ? k : formatString(k);
            if (type === 'array' && isArrayOfTables(obj[k])) {
                tables += (tables && '\n') + stringifyArrayTable(obj[k], prefix ? `${prefix}.${key}` : key, depth - 1, numberAsFloat);
            }
            else if (type === 'object') {
                let tblKey = prefix ? `${prefix}.${key}` : key;
                tables += (tables && '\n') + stringifyTable(tblKey, obj[k], tblKey, depth - 1, numberAsFloat);
            }
            else {
                preamble += key;
                preamble += ' = ';
                preamble += stringifyValue(obj[k], type, depth, numberAsFloat);
                preamble += '\n';
            }
        }
    }
    if (tableKey && (preamble || !tables)) // Create table only if necessary
        preamble = preamble ? `[${tableKey}]\n${preamble}` : `[${tableKey}]`;
    return preamble && tables
        ? `${preamble}\n${tables}`
        : preamble || tables;
}
function stringify(obj, { maxDepth = 1000, numbersAsFloat = false } = {}) {
    if (extendedTypeOf(obj) !== 'object') {
        throw new TypeError('stringify can only be called with an object');
    }
    let str = stringifyTable(0, obj, '', maxDepth, numbersAsFloat);
    if (str[str.length - 1] !== '\n')
        return str + '\n';
    return str;
}

/**
 * corva-ui-mcp-setup CLI
 *
 * Creates/updates MCP config files so AI coding agents can discover the @corva/ui MCP server.
 * Run from any project root: npx -p @corva/ui corva-ui-mcp-setup
 */
const SERVER_CONFIG = {
    command: 'npx',
    args: ['-p', '@corva/ui', 'corva-ui-mcp'],
};
const JSON_FORMAT = {
    formatName: 'JSON',
    serversKey: 'mcpServers',
    serverName: 'corva-ui',
    parse: raw => JSON.parse(raw),
    serialize: data => JSON.stringify(data, null, 2),
};
const TOML_FORMAT = {
    formatName: 'TOML',
    serversKey: 'mcp_servers',
    serverName: 'corva_ui',
    parse: raw => parse(raw),
    serialize: data => stringify(data),
};
const TARGETS = [
    { path: '.cursor/mcp.json', format: JSON_FORMAT },
    { path: '.mcp.json', format: JSON_FORMAT },
    { path: '.codex/config.toml', format: TOML_FORMAT },
];
const ACTION_SYMBOLS = {
    created: '+',
    updated: '~',
    skipped: '=',
};
const isRecord = (value) => typeof value === 'object' && value !== null;
const writeConfig = ({ path: filePath, format }) => {
    const absolutePath = resolve(filePath);
    mkdirSync(dirname(absolutePath), { recursive: true });
    let existing = {};
    let action = 'created';
    if (existsSync(absolutePath)) {
        action = 'updated';
        const raw = readFileSync(absolutePath, 'utf-8');
        try {
            existing = format.parse(raw);
        }
        catch {
            console.warn(`  Warning: ${filePath} contained invalid ${format.formatName} and will be overwritten.`);
            existing = {};
            action = 'created';
        }
    }
    const servers = isRecord(existing[format.serversKey])
        ? existing[format.serversKey]
        : {};
    if (JSON.stringify(servers[format.serverName]) === JSON.stringify(SERVER_CONFIG)) {
        return { file: filePath, action: 'skipped' };
    }
    const merged = {
        ...existing,
        [format.serversKey]: {
            ...servers,
            [format.serverName]: SERVER_CONFIG,
        },
    };
    writeFileSync(absolutePath, `${format.serialize(merged)}\n`);
    return { file: filePath, action };
};
const main = () => {
    console.log('Setting up @corva/ui MCP server configs...\n');
    const results = [];
    for (const target of TARGETS) {
        try {
            results.push(writeConfig(target));
        }
        catch (error) {
            const message = error instanceof Error ? error.message : String(error);
            console.error(`  Error writing ${target.path}: ${message}`);
        }
    }
    console.log('');
    for (const { file, action } of results) {
        console.log(`  ${ACTION_SYMBOLS[action]} ${file} (${action})`);
    }
    console.log('\nDone! The corva-ui MCP server is now configured for this project.');
};
main();
