/* oxlint-disable @typescript-eslint/no-explicit-any */
export function table(name) {
    return new TableBuilder({
        name,
        columns: {},
        primaryKey: [],
    });
}
export function string() {
    return new ColumnBuilder({
        type: 'string',
        optional: false,
        customType: null,
    });
}
export function number() {
    return new ColumnBuilder({
        type: 'number',
        optional: false,
        customType: null,
    });
}
export function boolean() {
    return new ColumnBuilder({
        type: 'boolean',
        optional: false,
        customType: null,
    });
}
export function json() {
    return new ColumnBuilder({
        type: 'json',
        optional: false,
        customType: null,
    });
}
export function enumeration() {
    return new ColumnBuilder({
        type: 'string',
        optional: false,
        customType: null,
    });
}
export const column = {
    string,
    number,
    boolean,
    json,
    enumeration,
};
export class TableBuilder {
    #schema;
    constructor(schema) {
        this.#schema = schema;
    }
    from(serverName) {
        return new TableBuilder({
            ...this.#schema,
            // Strip the "public." schema if specified, as tables in the upstream
            // "public" schema are created without the schema prefix on the replica.
            // See liteTableName() in zero-cache/src/types/names.ts
            serverName: serverName.startsWith('public.')
                ? serverName.substring('public.'.length)
                : serverName,
        });
    }
    columns(columns) {
        const columnSchemas = Object.fromEntries(Object.entries(columns).map(([k, v]) => [k, v.schema]));
        return new TableBuilderWithColumns({
            ...this.#schema,
            columns: columnSchemas,
        });
    }
}
export class TableBuilderWithColumns {
    #schema;
    constructor(schema) {
        this.#schema = schema;
    }
    primaryKey(...pkColumnNames) {
        return new TableBuilderWithColumns({
            ...this.#schema,
            primaryKey: pkColumnNames,
        });
    }
    get schema() {
        return this.#schema;
    }
    build() {
        // We can probably get the type system to throw an error if primaryKey is not called
        // before passing the schema to createSchema
        // Till then --
        if (this.#schema.primaryKey.length === 0) {
            throw new Error(`Table "${this.#schema.name}" is missing a primary key`);
        }
        const names = new Set();
        for (const [col, { serverName }] of Object.entries(this.#schema.columns)) {
            const name = serverName ?? col;
            if (names.has(name)) {
                throw new Error(`Table "${this.#schema.name}" has multiple columns referencing "${name}"`);
            }
            names.add(name);
        }
        return this.#schema;
    }
}
class ColumnBuilder {
    #schema;
    constructor(schema) {
        this.#schema = schema;
    }
    from(serverName) {
        return new ColumnBuilder({
            ...this.#schema,
            serverName,
        });
    }
    optional() {
        return new ColumnBuilder({
            ...this.#schema,
            optional: true,
        });
    }
    get schema() {
        return this.#schema;
    }
}
//# sourceMappingURL=table-builder.js.map