import { deepMerge, isPlainObject } from "../../../shared/src/deep-merge.js";
import { getValueAtPath, iterateLeaves } from "../../../shared/src/object-traversal.js";
import { validateInput } from "../query/validate-input.js";
import { isMutatorDefinition, isMutator } from "./mutator.js";
function defineMutators(definitionsOrBase, maybeOverrides) {
  function processDefinitions(definitions, path) {
    const result = {
      ["~"]: "MutatorRegistry"
    };
    for (const [key, value] of Object.entries(definitions)) {
      path.push(key);
      const name = path.join(".");
      if (isMutatorDefinition(value)) {
        result[key] = createMutator(name, value);
      } else {
        result[key] = processDefinitions(value, path);
      }
      path.pop();
    }
    return result;
  }
  if (maybeOverrides !== void 0) {
    let base;
    if (!isMutatorRegistry(definitionsOrBase)) {
      base = processDefinitions(definitionsOrBase, []);
    } else {
      base = definitionsOrBase;
    }
    const processed = processDefinitions(maybeOverrides, []);
    const merged = deepMerge(base, processed, isMutatorLeaf);
    merged["~"] = "MutatorRegistry";
    return merged;
  }
  return processDefinitions(
    definitionsOrBase,
    []
  );
}
const isMutatorLeaf = (value) => !isPlainObject(value) || isMutator(value);
function defineMutatorsWithType() {
  return defineMutators;
}
function isMutatorRegistry(value) {
  return typeof value === "object" && value !== null && value["~"] === "MutatorRegistry";
}
function createMutator(name, definition) {
  const { validator } = definition;
  const fn = async (options) => {
    const validatedArgs = validator ? validateInput(name, options.args, validator, "mutator") : options.args;
    await definition.fn({
      args: validatedArgs,
      ctx: options.ctx,
      tx: options.tx
    });
  };
  const mutator = (args) => ({
    args,
    "~": "MutateRequest",
    "mutator": mutator
  });
  mutator.mutatorName = name;
  mutator.fn = fn;
  mutator["~"] = "Mutator";
  return mutator;
}
function* iterateMutators(registry) {
  yield* iterateLeaves(registry, isMutator);
}
function getMutator(registry, name) {
  const m = getValueAtPath(registry, name, ".");
  return m;
}
function mustGetMutator(registry, name) {
  const mutator = getMutator(registry, name);
  if (mutator === void 0) {
    throw new Error(`Mutator not found: ${name}`);
  }
  return mutator;
}
export {
  defineMutators,
  defineMutatorsWithType,
  getMutator,
  isMutatorRegistry,
  iterateMutators,
  mustGetMutator
};
//# sourceMappingURL=mutator-registry.js.map
