import { assert } from "../../../shared/src/asserts.js";
import { Internal } from "../../../zero-protocol/src/error-kind-enum.js";
import { MeasurePushOperator } from "../../../zql/src/query/measure-push-operator.js";
import { QueryDelegateBase } from "../../../zql/src/query/query-delegate-base.js";
import "../../../shared/src/config.js";
import "../../../replicache/src/hash.js";
import "../../../replicache/src/btree/node.js";
import "compare-utf8";
import "../../../shared/src/iterables.js";
import "../../../shared/src/btree-set.js";
import "../../../zero-protocol/src/ast.js";
import "js-xxhash";
import "../../../shared/src/valita.js";
import "../../../zero-protocol/src/primary-key.js";
class ZeroContext extends QueryDelegateBase {
  #lc;
  // It is a bummer to have to maintain separate MemorySources here and copy the
  // data in from the Replicache db. But we want the data to be accessible via
  // pipelines *synchronously* and the core Replicache infra is all async. So
  // that needs to be fixed.
  #mainSources;
  addServerQuery;
  addCustomQuery;
  updateServerQuery;
  updateCustomQuery;
  flushQueryChanges;
  #batchViewUpdates;
  #commitListeners = /* @__PURE__ */ new Set();
  assertValidRunOptions;
  /**
   * Client-side queries start out as "unknown" and are then updated to
   * "complete" once the server has sent back the query result.
   */
  defaultQueryComplete = false;
  addMetric;
  constructor(lc, mainSources, addQuery, addCustomQuery, updateQuery, updateCustomQuery, flushQueryChanges, batchViewUpdates, addMetric, assertValidRunOptions) {
    super();
    this.#lc = lc;
    this.#mainSources = mainSources;
    this.addServerQuery = addQuery;
    this.updateServerQuery = updateQuery;
    this.updateCustomQuery = updateCustomQuery;
    this.#batchViewUpdates = batchViewUpdates;
    this.assertValidRunOptions = assertValidRunOptions;
    this.addCustomQuery = addCustomQuery;
    this.flushQueryChanges = flushQueryChanges;
    this.addMetric = addMetric;
  }
  applyFiltersAnyway;
  debug;
  getSource(name) {
    return this.#mainSources.getSource(name);
  }
  mapAst(ast) {
    return ast;
  }
  decorateSourceInput(input, queryID) {
    return new MeasurePushOperator(input, queryID, this, "query-update-client");
  }
  onTransactionCommit(cb) {
    this.#commitListeners.add(cb);
    return () => {
      this.#commitListeners.delete(cb);
    };
  }
  batchViewUpdates(applyViewUpdates) {
    let result;
    let viewChangesPerformed = false;
    this.#batchViewUpdates(() => {
      result = applyViewUpdates();
      viewChangesPerformed = true;
    });
    assert(
      viewChangesPerformed,
      "batchViewUpdates must call applyViewUpdates synchronously."
    );
    return result;
  }
  processChanges(expectedHead, newHead, changes) {
    this.batchViewUpdates(() => {
      try {
        this.#mainSources.advance(expectedHead, newHead, changes);
      } finally {
        this.#endTransaction();
      }
    });
  }
  #endTransaction() {
    for (const listener of this.#commitListeners) {
      try {
        listener();
      } catch (e) {
        this.#lc.error?.(
          Internal,
          "Failed notifying a commit listener of IVM updates",
          e
        );
      }
    }
  }
}
export {
  ZeroContext
};
//# sourceMappingURL=context.js.map
