import { formatPg, sql } from "../../z2s/src/sql.js";
import { makeSchemaQuery } from "./query.js";
import { makeSchemaCRUD, TransactionImpl } from "./custom.js";
import { makeServerTransaction } from "./custom.js";
/**
 * Implements a Database for use with PushProcessor that is backed by Postgres.
 *
 * This implementation also implements the same ZQL interfaces for reading and
 * writing data that the Zero client does, so that mutator functions can be
 * shared across client and server.
 */
export class ZQLDatabase {
    connection;
    #mutate;
    #query;
    #schema;
    constructor(connection, schema) {
        this.connection = connection;
        this.#mutate = makeSchemaCRUD(schema);
        this.#query = makeSchemaQuery(schema);
        this.#schema = schema;
    }
    transaction(callback, transactionInput) {
        if (!transactionInput) {
            // Icky hack. This is just here to have user not have to do this.
            // These interfaces need to be factored better.
            transactionInput = {
                upstreamSchema: undefined,
                clientGroupID: undefined,
                clientID: undefined,
                mutationID: undefined,
            };
        }
        return this.connection.transaction(async (dbTx) => {
            const zeroTx = await makeServerTransaction(dbTx, transactionInput.clientID, transactionInput.mutationID, this.#schema, this.#mutate, this.#query);
            return callback(zeroTx, {
                async updateClientMutationID() {
                    const formatted = formatPg(sql `INSERT INTO ${sql.ident(transactionInput.upstreamSchema)}.clients 
                    as current ("clientGroupID", "clientID", "lastMutationID")
                        VALUES (${transactionInput.clientGroupID}, ${transactionInput.clientID}, ${1})
                    ON CONFLICT ("clientGroupID", "clientID")
                    DO UPDATE SET "lastMutationID" = current."lastMutationID" + 1
                    RETURNING "lastMutationID"`);
                    const [{ lastMutationID }] = (await dbTx.query(formatted.text, formatted.values));
                    return { lastMutationID };
                },
                async writeMutationResult(result) {
                    const formatted = formatPg(sql `INSERT INTO ${sql.ident(transactionInput.upstreamSchema)}.mutations
                    ("clientGroupID", "clientID", "mutationID", "result")
                VALUES (${transactionInput.clientGroupID}, ${result.id.clientID}, ${result.id.id}, ${JSON.stringify(result.result)}::text::json)`);
                    await dbTx.query(formatted.text, formatted.values);
                },
            });
        });
    }
}
//# sourceMappingURL=zql-database.js.map