(function() {
  "use strict";
  function createDataFrame(opts) {
    const fields = opts.fields.map((f) => ({
      name: f.name,
      type: f.type ?? inferType(f.values),
      config: f.config ?? {},
      values: f.values,
      labels: f.labels
    }));
    const length = fields.reduce((max, f) => Math.max(max, f.values.length), 0);
    return {
      refId: opts.refId,
      name: opts.name,
      fields,
      length,
      meta: opts.meta
    };
  }
  function inferType(values) {
    const sample = values.find((v) => v != null);
    if (typeof sample === "number") return "number";
    if (typeof sample === "boolean") return "boolean";
    if (sample instanceof Date) return "time";
    if (typeof sample === "string" && !Number.isNaN(Date.parse(sample)) && /\d{4}-\d{2}-\d{2}/.test(sample)) {
      return "time";
    }
    return typeof sample === "string" ? "string" : "other";
  }
  const TIME_SERIES_VALUE_FIELD_NAME = "Value";
  const TIME_SERIES_TIME_FIELD_NAME = "Time";
  function formatLabels(labels) {
    if (!labels) return "";
    return Object.entries(labels).filter(([, v]) => v != null && v !== "").map(([k, v]) => `${k}=${v}`).join(", ");
  }
  function getFieldDisplayName(field, frame, allFrames) {
    const name = calculateFieldDisplayName(field, frame, allFrames);
    if (field.state?.displayName !== name) {
      field.state = { ...field.state || {}, displayName: name };
    }
    return name;
  }
  function isGenericValueName(s) {
    const t = s.trim();
    if (!t || t === TIME_SERIES_VALUE_FIELD_NAME) return true;
    if (/^Value\s*\{/.test(t)) return true;
    return false;
  }
  function calculateFieldDisplayName(field, frame, allFrames) {
    const cfg = field.config ?? {};
    if (cfg.displayName && String(cfg.displayName).length && !isGenericValueName(String(cfg.displayName))) {
      return String(cfg.displayName);
    }
    if (cfg.displayNameFromDS && String(cfg.displayNameFromDS).length && !isGenericValueName(String(cfg.displayNameFromDS))) {
      return String(cfg.displayNameFromDS);
    }
    if (field.type === "time" && !field.labels) {
      return field.name || TIME_SERIES_TIME_FIELD_NAME;
    }
    const frames = allFrames?.length ? allFrames : frame ? [frame] : [];
    let frameNamesDiffer = false;
    if (frames.length > 1) {
      for (let i = 1; i < frames.length; i++) {
        if (frames[i].name !== frames[i - 1].name) {
          frameNamesDiffer = true;
          break;
        }
      }
    }
    const parts = [];
    let frameNameAdded = false;
    let labelsAdded = false;
    if (frameNamesDiffer && frame?.name) {
      parts.push(frame.name);
      frameNameAdded = true;
    }
    if (field.name && !isGenericValueName(field.name)) {
      parts.push(field.name);
    }
    if (field.labels && Object.keys(field.labels).length) {
      const singleLabel = getSingleLabelName(frames.length ? frames : frame ? [frame] : []);
      if (singleLabel && field.labels[singleLabel] != null && field.labels[singleLabel] !== "") {
        parts.push(String(field.labels[singleLabel]));
        labelsAdded = true;
      } else {
        const allLabels = formatLabels(field.labels);
        if (allLabels) {
          parts.push(allLabels);
          labelsAdded = true;
        }
      }
    }
    if (frame && !frameNameAdded && !labelsAdded && isGenericValueName(field.name || "")) {
      if (frame.name) {
        parts.push(frame.name);
        frameNameAdded = true;
      }
    }
    if (parts.length) return parts.join(" ");
    if (field.name) return field.name;
    if (frame?.name) return frame.name;
    return TIME_SERIES_VALUE_FIELD_NAME;
  }
  function getSingleLabelName(frames) {
    const keys = /* @__PURE__ */ new Set();
    for (const fr of frames) {
      for (const f of fr.fields) {
        if (!f.labels) continue;
        for (const k of Object.keys(f.labels)) keys.add(k);
        if (keys.size > 1) return null;
      }
    }
    if (keys.size === 1) return [...keys][0];
    return null;
  }
  function getFrameDisplayName(frame, index2) {
    if (frame.name) return String(frame.name);
    const valueFieldNames = [];
    for (const field of frame.fields) {
      if (field.type === "time") continue;
      valueFieldNames.push(getFieldDisplayName(field, frame));
      if (valueFieldNames.length > 1) break;
    }
    if (valueFieldNames.length === 1) return valueFieldNames[0];
    if (index2 === void 0 && frame.fields.length > 0) {
      return frame.fields.filter((f) => f.type !== "time").map((f) => getFieldDisplayName(f, frame)).join(", ");
    }
    if (typeof index2 === "number") return `Series (${index2})`;
    return "Series";
  }
  function fieldMatchesName(field, name, frame, allFrames) {
    if (!name) return false;
    if (field.name === name) return true;
    return getFieldDisplayName(field, frame, allFrames) === name;
  }
  function findField(frame, name, allFrames) {
    if (name == null || name === "") return void 0;
    const n = String(name);
    return frame.fields.find((f) => f.name === n) ?? frame.fields.find((f) => getFieldDisplayName(f, frame, allFrames) === n);
  }
  const registry = /* @__PURE__ */ new Map();
  function registerTransformer(id, fn) {
    registry.set(id, fn);
  }
  function getTransformer(id) {
    return registry.get(id);
  }
  function listTransformerIds$1() {
    return [...registry.keys()];
  }
  const ALIASES = {
    // filterFieldsByName is first-class; filterByName is internal alias
    filterByName: "filterFieldsByName",
    filterFramesByRefId: "filterByRefId",
    seriesToColumns: "joinByField"
  };
  const DEFAULT_OPTIONS$1 = {
    limit: { limitField: 10 },
    sortBy: { sort: [] },
    reduce: { reducers: ["sum"] },
    histogram: { bucketCount: 10 },
    smoothing: { windowSize: 3 },
    filterByValue: { type: "include", filters: [] },
    prepareTimeSeries: { format: "multi" }
  };
  function resolveTransformerId(id) {
    return ALIASES[id] ?? id;
  }
  function deepCloneFrames(frames) {
    return frames.map((frame) => {
      const fields = frame.fields.map((f) => ({
        name: f.name,
        type: f.type,
        config: f.config ? { ...f.config } : {},
        values: f.values.slice(),
        labels: f.labels ? { ...f.labels } : void 0,
        state: f.state ? { ...f.state } : void 0
      }));
      return {
        refId: frame.refId,
        name: frame.name,
        meta: frame.meta ? { ...frame.meta } : void 0,
        fields,
        length: frame.length ?? fields[0]?.values.length ?? 0
      };
    });
  }
  function interpolateOptions(value, interpolate) {
    return value;
  }
  function patternFromFilterOptions(options) {
    if (options == null) return "";
    if (typeof options === "string" || typeof options === "number") return String(options);
    if (typeof options === "object") {
      const o = options;
      if (o.pattern != null) return String(o.pattern);
      if (o.refId != null) return String(o.refId);
      if (o.value != null) return String(o.value);
      if (Array.isArray(o.names)) return o.names.map(String).join("|");
    }
    return String(options);
  }
  function compileMatcher(raw) {
    const s = raw.trim();
    if (!s) return () => true;
    const m = s.match(/^\/(.+)\/([gimsuy]*)$/);
    if (m) {
      try {
        const re = new RegExp(m[1], m[2]);
        return (v) => re.test(v);
      } catch {
        return (v) => v === s;
      }
    }
    try {
      const re = new RegExp(`^(?:${s})$`);
      return (v) => re.test(v);
    } catch {
      return (v) => v === s;
    }
  }
  function matchFrameFilter(frame, filter) {
    if (filter == null || filter === "") return true;
    if (typeof filter === "string") {
      const hit2 = compileMatcher(filter);
      return hit2(String(frame.refId ?? "")) || hit2(String(frame.name ?? ""));
    }
    const id = String(filter.id || "byRefId");
    const pattern = patternFromFilterOptions(filter.options);
    const hit = compileMatcher(pattern);
    if (id === "byName" || id === "byFrameName") {
      return hit(String(frame.name ?? ""));
    }
    if (id === "byRefId" || id === "byFrameRefID" || id === "byFrameRefId") {
      return hit(String(frame.refId ?? ""));
    }
    return hit(String(frame.refId ?? "")) || hit(String(frame.name ?? ""));
  }
  function applyWithFrameFilter(frames, filter, fn, options) {
    if (filter == null || filter === "") {
      return fn(frames, options);
    }
    const matched = [];
    const passthrough = /* @__PURE__ */ new Map();
    frames.forEach((f, i) => {
      if (matchFrameFilter(f, filter)) {
        matched.push(f);
      } else {
        passthrough.set(i, f);
      }
    });
    if (!matched.length) return frames;
    const transformed = fn(matched, options);
    const out = [];
    let inserted = false;
    for (let i = 0; i < frames.length; i++) {
      if (passthrough.has(i)) {
        out.push(passthrough.get(i));
      } else if (!inserted) {
        out.push(...transformed);
        inserted = true;
        transformed.length;
      }
    }
    if (!inserted) out.push(...transformed);
    return out;
  }
  function readLimitOption$1(options) {
    if (!options) return void 0;
    const raw = options.limit ?? options.limitField ?? options.limitValue;
    if (raw == null) return void 0;
    const n = Math.floor(Number(raw));
    return Number.isFinite(n) && n >= 0 ? n : void 0;
  }
  function tryFuseSortLimit$1(transformations, index2) {
    const cur = transformations[index2];
    const next = transformations[index2 + 1];
    if (!cur || !next) return null;
    if (cur.disabled || next.disabled) return null;
    const curId = resolveTransformerId(cur.id);
    const nextId = resolveTransformerId(next.id);
    if (curId !== "sortBy" || nextId !== "limit") return null;
    const f1 = cur.filter ?? null;
    const f2 = next.filter ?? null;
    if (JSON.stringify(f1) !== JSON.stringify(f2)) return null;
    const lim = readLimitOption$1(next.options);
    if (lim == null) return null;
    return {
      fusedOptions: {
        ...cur.options || {},
        limit: lim,
        limitField: lim,
        limitValue: lim
      },
      skipNext: true
    };
  }
  function applyTransformations(frames, transformations = [], diagnostics, context) {
    let acc = deepCloneFrames(frames);
    if (!transformations.length) return acc;
    const localDiag = [];
    for (let i = 0; i < transformations.length; i++) {
      const t = transformations[i];
      if (t.disabled) continue;
      const resolvedId = resolveTransformerId(t.id);
      const fn = getTransformer(resolvedId) ?? getTransformer(t.id);
      if (!fn) {
        localDiag.push({
          id: t.id,
          level: "warn",
          message: `Unknown transformation: ${t.id}`
        });
        continue;
      }
      const defaults = DEFAULT_OPTIONS$1[resolvedId] ?? DEFAULT_OPTIONS$1[t.id] ?? {};
      const fuse = tryFuseSortLimit$1(transformations, i);
      const stepOptions = fuse ? { ...defaults, ...fuse.fusedOptions } : { ...defaults, ...t.options || {} };
      const merged = interpolateOptions(stepOptions);
      try {
        acc = applyWithFrameFilter(
          acc,
          t.filter,
          fn,
          merged
        );
        if (fuse?.skipNext) i += 1;
      } catch (error) {
        const msg = error instanceof Error ? error.message : String(error);
        localDiag.push({ id: t.id, level: "error", message: msg });
        throw error;
      }
    }
    return acc;
  }
  function listTransformerIds() {
    return listTransformerIds$1();
  }
  function namesFromVariable(raw) {
    if (raw == null || raw === "") return null;
    let s = String(raw).trim();
    if (/^\{.*\}$/.test(s)) s = s.slice(1, -1);
    const names = s.split(",").map((x) => x.trim()).filter(Boolean);
    return names.length ? names : null;
  }
  function matcherFrom(opts, byVariable) {
    if (opts == null || opts === "") return null;
    if (typeof opts === "string") {
      if (byVariable || opts.includes(",") || /^\{.*\}$/.test(opts)) {
        const names = namesFromVariable(opts);
        if (names) {
          const set = new Set(names);
          return (name) => set.has(name);
        }
      }
      try {
        const re = new RegExp(opts);
        return (name) => re.test(name);
      } catch {
        return (name) => name === opts;
      }
    }
    if (typeof opts === "object") {
      const fromVar = (byVariable || opts.variable != null) && opts.variable != null ? namesFromVariable(opts.variable) : null;
      if (fromVar) {
        const set = new Set(fromVar);
        return (name) => set.has(name);
      }
      const names = opts.names;
      const pattern = opts.pattern;
      if (Array.isArray(names) && names.length) {
        const set = new Set(names.map(String));
        if (pattern) {
          try {
            const re = new RegExp(pattern);
            return (name) => set.has(name) || re.test(name);
          } catch {
            return (name) => set.has(name);
          }
        }
        return (name) => set.has(name);
      }
      if (pattern) {
        try {
          const re = new RegExp(pattern);
          return (name) => re.test(name);
        } catch {
          return (name) => name === pattern;
        }
      }
    }
    return null;
  }
  function fieldMatchesPred(field, frame, frames, pred) {
    if (pred(field.name)) return true;
    try {
      const display = getFieldDisplayName(field, frame, frames);
      if (display && display !== field.name && pred(display)) return true;
    } catch {
    }
    const cfgDn = field.config?.displayName;
    if (typeof cfgDn === "string" && cfgDn && pred(cfgDn)) return true;
    return false;
  }
  registerTransformer("filterByName", (frames, options = {}) => {
    const byVariable = options.byVariable === true;
    const includePred = matcherFrom(options.include, byVariable) ?? matcherFrom(options.pattern != null ? String(options.pattern) : void 0, byVariable);
    const excludePred = matcherFrom(options.exclude, byVariable);
    if (!includePred && !excludePred) return frames;
    return frames.map((frame) => {
      let fields = frame.fields;
      if (includePred) {
        fields = fields.filter((f) => fieldMatchesPred(f, frame, frames, includePred));
      }
      if (excludePred) {
        fields = fields.filter((f) => !fieldMatchesPred(f, frame, frames, excludePred));
      }
      return createDataFrame({
        refId: frame.refId,
        name: frame.name,
        fields
      });
    });
  });
  function stringStartsAsRegEx(str) {
    return Boolean(str) && str[0] === "/";
  }
  function stringToJsRegex(str) {
    if (!stringStartsAsRegEx(str)) {
      return new RegExp(`^${str}$`);
    }
    const match = str.match(/^\/(.*?)\/(g?i?m?y?s?)$/);
    if (!match) {
      throw new Error(`'${str}' is not a valid regular expression.`);
    }
    return new RegExp(match[1], match[2]);
  }
  function stringToJsRegexSafe(str) {
    try {
      const s = String(str ?? "");
      if (!s) return null;
      return stringToJsRegex(s);
    } catch {
      return null;
    }
  }
  function compileRefIdMatcher(pattern) {
    const p = String(pattern ?? "").trim();
    if (!p) return () => false;
    if (p.startsWith("/")) {
      const re = stringToJsRegexSafe(p);
      if (re) return (refId) => re.test(refId);
    }
    if (p.includes("|") && !p.startsWith("^") && !p.includes(".*") && !p.includes("(")) {
      const set = new Set(
        p.split("|").map((s) => s.trim()).filter(Boolean)
      );
      return (refId) => set.has(refId);
    }
    try {
      if (/[.*+?^${}()[\]\\]/.test(p)) {
        const re = new RegExp(p);
        return (refId) => re.test(refId);
      }
    } catch {
    }
    return (refId) => refId === p;
  }
  registerTransformer("filterByRefId", (frames, options = {}) => {
    const includeRaw = options.include != null && String(options.include).trim() !== "" ? String(options.include) : void 0;
    const excludeRaw = options.exclude != null && String(options.exclude).trim() !== "" ? String(options.exclude) : void 0;
    if (!includeRaw && !excludeRaw) return frames;
    const include = includeRaw ? compileRefIdMatcher(includeRaw) : null;
    const exclude = excludeRaw ? compileRefIdMatcher(excludeRaw) : null;
    return frames.filter((f) => {
      const refId = f.refId ?? "";
      if (exclude && exclude(refId)) return false;
      if (include) return include(refId);
      return true;
    });
  });
  function isTrueMap(raw) {
    return !!raw && typeof raw === "object" && !Array.isArray(raw);
  }
  function isStringMap(raw) {
    return !!raw && typeof raw === "object" && !Array.isArray(raw);
  }
  function isNumberMap(raw) {
    return !!raw && typeof raw === "object" && !Array.isArray(raw);
  }
  function fieldKey(f, frame) {
    try {
      return getFieldDisplayName(f, frame) || f.name;
    } catch {
      return f.name;
    }
  }
  function indexOfName(name, indexByName) {
    if (Object.prototype.hasOwnProperty.call(indexByName, name)) {
      const v = Number(indexByName[name]);
      return Number.isFinite(v) ? v : Number.MAX_SAFE_INTEGER;
    }
    return Number.MAX_SAFE_INTEGER;
  }
  function organizeFrame(frame, options) {
    const excludeByName = isTrueMap(options.excludeByName) ? options.excludeByName : {};
    const includeByName = isTrueMap(options.includeByName) ? options.includeByName : void 0;
    const indexByName = isNumberMap(options.indexByName) ? options.indexByName : {};
    const renameByName = isStringMap(options.renameByName) ? options.renameByName : {};
    let fields = [...frame.fields];
    if (includeByName) {
      const includeKeys = Object.keys(includeByName).filter((k) => includeByName[k]);
      if (includeKeys.length) {
        const allow = new Set(includeKeys);
        fields = fields.filter((f) => allow.has(f.name) || allow.has(fieldKey(f, frame)));
      }
    }
    fields = fields.filter((f) => {
      if (excludeByName[f.name]) return false;
      const disp = fieldKey(f, frame);
      if (disp !== f.name && excludeByName[disp]) return false;
      return true;
    });
    if (Object.keys(indexByName).length) {
      fields = [...fields].sort((a, b) => {
        const ai = Math.min(
          indexOfName(a.name, indexByName),
          indexOfName(fieldKey(a, frame), indexByName)
        );
        const bi = Math.min(
          indexOfName(b.name, indexByName),
          indexOfName(fieldKey(b, frame), indexByName)
        );
        return ai - bi;
      });
    }
    fields = fields.map((f) => {
      const key = fieldKey(f, frame);
      const next = renameByName[key] ?? renameByName[f.name];
      if (typeof next !== "string" || !next.length) return f;
      return {
        ...f,
        config: {
          ...f.config || {},
          displayName: next
        },
        state: {
          ...f.state || {},
          displayName: next
        }
      };
    });
    return createDataFrame({
      refId: frame.refId,
      name: frame.name,
      fields
    });
  }
  registerTransformer("organize", (frames, options = {}) => {
    const opts = options;
    return frames.map((frame) => organizeFrame(frame, opts));
  });
  function compareValues(av, bv, desc) {
    if (av == null && bv == null) return 0;
    if (av == null) return 1;
    if (bv == null) return -1;
    if (typeof av === "number" && typeof bv === "number") {
      if (av === bv) return 0;
      const c = av < bv ? -1 : 1;
      return desc ? -c : c;
    }
    if (av < bv) return desc ? 1 : -1;
    if (av > bv) return desc ? -1 : 1;
    return 0;
  }
  function reorderFrame(frame, indices) {
    const n = indices.length;
    const fields = frame.fields.map((f) => {
      const src = f.values;
      const values = new Array(n);
      for (let i = 0; i < n; i++) values[i] = src[indices[i]];
      return {
        name: f.name,
        type: f.type,
        config: f.config ? { ...f.config } : {},
        values,
        labels: f.labels ? { ...f.labels } : void 0,
        state: f.state ? { ...f.state } : void 0
      };
    });
    return {
      refId: frame.refId,
      name: frame.name,
      meta: frame.meta ? { ...frame.meta } : void 0,
      fields,
      length: n
    };
  }
  function topKIndices(keyValues, k, desc) {
    const n = keyValues.length;
    if (k <= 0) return [];
    if (k >= n) {
      const indices = new Array(n);
      for (let i = 0; i < n; i++) indices[i] = i;
      indices.sort((a, b) => compareValues(keyValues[a], keyValues[b], desc));
      return indices;
    }
    const heap = [];
    const better = (a, b) => (
      // a is "better" (more preferred in final order) than b
      compareValues(keyValues[a], keyValues[b], desc) < 0
    );
    const worseThan = (a, b) => compareValues(keyValues[a], keyValues[b], desc) > 0;
    const siftUp = (i) => {
      while (i > 0) {
        const p = i - 1 >> 1;
        if (!worseThan(heap[i], heap[p])) break;
        const tmp = heap[i];
        heap[i] = heap[p];
        heap[p] = tmp;
        i = p;
      }
    };
    const siftDown = (i) => {
      for (; ; ) {
        let w = i;
        const l = i * 2 + 1;
        const r = l + 1;
        if (l < heap.length && worseThan(heap[l], heap[w])) w = l;
        if (r < heap.length && worseThan(heap[r], heap[w])) w = r;
        if (w === i) break;
        const tmp = heap[i];
        heap[i] = heap[w];
        heap[w] = tmp;
        i = w;
      }
    };
    for (let i = 0; i < n; i++) {
      if (heap.length < k) {
        heap.push(i);
        siftUp(heap.length - 1);
        continue;
      }
      if (better(i, heap[0])) {
        heap[0] = i;
        siftDown(0);
      }
    }
    heap.sort((a, b) => compareValues(keyValues[a], keyValues[b], desc));
    return heap;
  }
  registerTransformer("sortBy", (frames, options = {}) => {
    const sortSpecs = options.sort ?? [];
    const sort = sortSpecs[0];
    if (!sort?.field) return frames;
    const desc = !!sort.desc;
    const limitRaw = options.limit ?? options.limitField ?? options.limitValue;
    const limit = limitRaw == null ? void 0 : Math.floor(Number(limitRaw));
    return frames.map((frame) => {
      const idx = frame.fields.findIndex(
        (f) => f.name === sort.field || getFieldDisplayName(f, frame, frames) === sort.field
      );
      if (idx < 0) return frame;
      const keyValues = frame.fields[idx].values;
      const n = keyValues.length;
      if (n <= 1) return frame;
      if (limit != null && Number.isFinite(limit) && limit >= 0 && limit < n) {
        const indices2 = topKIndices(keyValues, limit, desc);
        return reorderFrame(frame, indices2);
      }
      const indices = new Array(n);
      for (let i = 0; i < n; i++) indices[i] = i;
      indices.sort((a, b) => compareValues(keyValues[a], keyValues[b], desc));
      return reorderFrame(frame, indices);
    });
  });
  registerTransformer("limit", (frames, options = {}) => {
    const limit = Number(options.limit ?? options.limitField ?? 10);
    if (!Number.isFinite(limit) || limit < 0) return frames;
    const n = Math.floor(limit);
    return frames.map((frame) => {
      const len = frame.length ?? frame.fields[0]?.values?.length ?? 0;
      if (len <= n) return frame;
      return {
        refId: frame.refId,
        name: frame.name,
        meta: frame.meta ? { ...frame.meta } : void 0,
        length: n,
        fields: frame.fields.map((f) => ({
          name: f.name,
          type: f.type,
          config: f.config ? { ...f.config } : {},
          values: f.values.slice(0, n),
          labels: f.labels ? { ...f.labels } : void 0,
          state: f.state ? { ...f.state } : void 0
        }))
      };
    });
  });
  registerTransformer("reduce", (frames, options = {}) => {
    const labelsToFields = options.labelsToFields === true;
    const reducers = (options.reducers ?? ["lastNotNull"]).map(String);
    const mode = String(options.mode ?? "seriesToRows");
    const reducerTitle = (r) => {
      const map = {
        sum: "Sum",
        max: "Max",
        min: "Min",
        mean: "Mean",
        last: "Last",
        lastNotNull: "Last *",
        first: "First",
        firstNotNull: "First *",
        count: "Count",
        range: "Range"
      };
      return map[r] || r;
    };
    const applyReducer = (raw, r) => {
      const finite = () => raw.map((v) => v == null || v === "" ? Number.NaN : Number(v)).filter((n) => Number.isFinite(n));
      if (r === "last") {
        if (!raw.length) return Number.NaN;
        const v = raw[raw.length - 1];
        if (v == null || v === "") return Number.NaN;
        const n = Number(v);
        return Number.isFinite(n) ? n : Number.NaN;
      }
      if (r === "first") {
        if (!raw.length) return Number.NaN;
        const v = raw[0];
        if (v == null || v === "") return Number.NaN;
        const n = Number(v);
        return Number.isFinite(n) ? n : Number.NaN;
      }
      if (r === "lastNotNull") {
        for (let i = raw.length - 1; i >= 0; i--) {
          const v = raw[i];
          if (v == null || v === "") continue;
          const n = Number(v);
          if (Number.isFinite(n)) return n;
        }
        return Number.NaN;
      }
      if (r === "firstNotNull") {
        for (const v of raw) {
          if (v == null || v === "") continue;
          const n = Number(v);
          if (Number.isFinite(n)) return n;
        }
        return Number.NaN;
      }
      const nums = finite();
      if (!nums.length) return Number.NaN;
      if (r === "min") return Math.min(...nums);
      if (r === "max") return Math.max(...nums);
      if (r === "mean") return nums.reduce((a, b) => a + b, 0) / nums.length;
      if (r === "sum") return nums.reduce((a, b) => a + b, 0);
      if (r === "count") return nums.length;
      if (r === "range") return Math.max(...nums) - Math.min(...nums);
      return nums[nums.length - 1];
    };
    const fieldNames = [];
    const labelCols = /* @__PURE__ */ new Map();
    const reducerCols = {};
    for (const r of reducers) reducerCols[reducerTitle(r)] = [];
    if (reducers.includes("sum") && !reducerCols.Total) reducerCols.Total = [];
    if (labelsToFields) {
      for (const frame of frames) {
        for (const field of frame.fields) {
          if (field.type !== "number") continue;
          for (const k of Object.keys(field.labels ?? {})) {
            if (!labelCols.has(k)) labelCols.set(k, []);
          }
        }
      }
    }
    for (const frame of frames) {
      const numFields = frame.fields.filter((f) => f.type === "number");
      for (const field of numFields) {
        const rawVals = field.values;
        const display = labelsToFields ? field.name : getFieldDisplayName(field, frame, frames) || frame.name || field.name;
        fieldNames.push(String(display));
        if (labelsToFields) {
          const labels = field.labels || {};
          for (const k of labelCols.keys()) {
            labelCols.get(k).push(String(labels[k] ?? ""));
          }
        }
        for (const r of reducers) {
          const title = reducerTitle(r);
          reducerCols[title].push(applyReducer(rawVals, r));
        }
        if (reducers.includes("sum")) {
          reducerCols.Total.push(applyReducer(rawVals, "sum"));
        }
      }
    }
    if (!fieldNames.length) {
      return [
        createDataFrame({
          refId: frames[0]?.refId,
          name: "reduce",
          fields: [
            { name: "Field", type: "string", values: [] },
            { name: "Value", type: "number", values: [] }
          ]
        })
      ];
    }
    for (const arr of labelCols.values()) {
      while (arr.length < fieldNames.length) arr.push("");
    }
    const includeTimeField = options.includeTimeField === true;
    if (mode === "reduceFields") {
      return frames.map((frame) => {
        const fields = frame.fields.filter((f) => {
          if (f.type === "time") return includeTimeField;
          return f.type === "number" || f.type === "string" || f.type === "boolean";
        }).map((f) => {
          if (f.type === "time") {
            const r2 = reducers[0] || "lastNotNull";
            return { ...f, values: [applyReducer(f.values, r2)] };
          }
          if (f.type !== "number") return { ...f, values: f.values.slice(0, 1) };
          const r = reducers[0] || "lastNotNull";
          return { ...f, values: [applyReducer(f.values, r)] };
        });
        return createDataFrame({ refId: frame.refId, name: frame.name, fields });
      });
    }
    return [
      createDataFrame({
        refId: frames[0]?.refId,
        name: "reduce",
        meta: { preferredVisualisationType: "table" },
        fields: [
          { name: "Field", type: "string", values: fieldNames },
          ...labelsToFields ? [...labelCols.entries()].map(([k, vals]) => ({
            name: k,
            type: "string",
            values: vals
          })) : [],
          ...Object.entries(reducerCols).map(([k, vals]) => ({
            name: k,
            type: "number",
            values: vals
          }))
        ]
      })
    ];
  });
  var ReducerID = /* @__PURE__ */ ((ReducerID2) => {
    ReducerID2["sum"] = "sum";
    ReducerID2["max"] = "max";
    ReducerID2["min"] = "min";
    ReducerID2["mean"] = "mean";
    ReducerID2["last"] = "last";
    ReducerID2["first"] = "first";
    ReducerID2["count"] = "count";
    ReducerID2["lastNotNull"] = "lastNotNull";
    ReducerID2["firstNotNull"] = "firstNotNull";
    ReducerID2["range"] = "range";
    ReducerID2["diff"] = "diff";
    ReducerID2["diffperc"] = "diffperc";
    ReducerID2["delta"] = "delta";
    ReducerID2["step"] = "step";
    ReducerID2["variance"] = "variance";
    ReducerID2["stdDev"] = "stdDev";
    ReducerID2["median"] = "median";
    ReducerID2["allIsZero"] = "allIsZero";
    ReducerID2["allIsNull"] = "allIsNull";
    ReducerID2["changeCount"] = "changeCount";
    ReducerID2["distinctCount"] = "distinctCount";
    ReducerID2["logmin"] = "logmin";
    return ReducerID2;
  })(ReducerID || {});
  function numericValues(field) {
    return field.values.map((v) => v == null || v === "" ? null : Number(v)).filter((v) => v != null && !Number.isNaN(v));
  }
  function reduceField$1(field, reducers = [
    "lastNotNull"
    /* lastNotNull */
  ]) {
    const nums = numericValues(field);
    const out = {};
    for (const r of reducers) {
      if (r === "count") {
        out[r] = nums.length;
        continue;
      }
      if (r === "allIsNull") {
        out[r] = field.values.every((v) => v == null || v === "");
        continue;
      }
      if (r === "allIsZero") {
        out[r] = nums.length > 0 && nums.every((n) => n === 0);
        continue;
      }
      if (r === "distinctCount") {
        out[r] = new Set(nums).size;
        continue;
      }
      if (r === "changeCount") {
        let c = 0;
        for (let i = 1; i < nums.length; i++) if (nums[i] !== nums[i - 1]) c++;
        out[r] = c;
        continue;
      }
      if (!nums.length) {
        out[r] = null;
        continue;
      }
      switch (r) {
        case "last":
          out[r] = Number(field.values[field.values.length - 1]);
          break;
        case "lastNotNull":
          out[r] = nums[nums.length - 1];
          break;
        case "first":
          out[r] = Number(field.values[0]);
          break;
        case "firstNotNull":
          out[r] = nums[0];
          break;
        case "min":
          out[r] = Math.min(...nums);
          break;
        case "max":
          out[r] = Math.max(...nums);
          break;
        case "mean":
          out[r] = nums.reduce((a, b) => a + b, 0) / nums.length;
          break;
        case "sum":
          out[r] = nums.reduce((a, b) => a + b, 0);
          break;
        case "range":
          out[r] = Math.max(...nums) - Math.min(...nums);
          break;
        case "diff":
          out[r] = nums[nums.length - 1] - nums[0];
          break;
        case "diffperc": {
          const a = nums[0];
          out[r] = a === 0 ? null : (nums[nums.length - 1] - a) / Math.abs(a) * 100;
          break;
        }
        case "delta": {
          let d = 0;
          for (let i = 1; i < nums.length; i++) {
            const step = nums[i] - nums[i - 1];
            if (step > 0) d += step;
          }
          out[r] = d;
          break;
        }
        case "step": {
          let maxStep = 0;
          for (let i = 1; i < nums.length; i++)
            maxStep = Math.max(maxStep, Math.abs(nums[i] - nums[i - 1]));
          out[r] = maxStep;
          break;
        }
        case "variance": {
          const mean = nums.reduce((a, b) => a + b, 0) / nums.length;
          out[r] = nums.reduce((a, b) => a + (b - mean) ** 2, 0) / nums.length;
          break;
        }
        case "stdDev": {
          const mean = nums.reduce((a, b) => a + b, 0) / nums.length;
          const v = nums.reduce((a, b) => a + (b - mean) ** 2, 0) / nums.length;
          out[r] = Math.sqrt(v);
          break;
        }
        case "median": {
          const s = [...nums].sort((a, b) => a - b);
          const mid = Math.floor(s.length / 2);
          out[r] = s.length % 2 ? s[mid] : (s[mid - 1] + s[mid]) / 2;
          break;
        }
        case "logmin": {
          const pos = nums.filter((n) => n > 0);
          out[r] = pos.length ? Math.min(...pos) : null;
          break;
        }
        default:
          out[r] = nums[nums.length - 1];
      }
    }
    return out;
  }
  function isFieldsMap$1(raw) {
    return !!raw && typeof raw === "object" && !Array.isArray(raw);
  }
  function findFrameField$1(frame, name) {
    return frame.fields.find((f) => f.name === name) ?? frame.fields.find((f) => getFieldDisplayName(f, frame) === name);
  }
  function groupByFrame(frame, fieldConfig, legacyMode) {
    const groupByNames = Object.entries(fieldConfig).filter(([, cfg]) => String(cfg?.operation ?? "") === "groupby").map(([n]) => n);
    let aggregateSpecs = Object.entries(fieldConfig).filter(
      ([, cfg]) => String(cfg?.operation ?? "") === "aggregate" && Array.isArray(cfg.aggregations) && (cfg.aggregations?.length ?? 0) > 0
    ).map(([n, cfg]) => ({
      name: n,
      aggregations: (cfg.aggregations ?? []).map(String)
    }));
    if (legacyMode && groupByNames.length) {
      aggregateSpecs = frame.fields.filter((f) => {
        if (f.type !== "number") return false;
        const display = getFieldDisplayName(f, frame);
        return !groupByNames.includes(f.name) && !groupByNames.includes(display);
      }).map((f) => ({ name: f.name, aggregations: ["sum"] }));
    }
    if (!groupByNames.length) return frame;
    const groupByFields = groupByNames.map((n) => findFrameField$1(frame, n)).filter((f) => !!f);
    if (!groupByFields.length) return frame;
    const buckets = /* @__PURE__ */ new Map();
    const len = frame.length || frame.fields[0]?.values.length || 0;
    for (let row = 0; row < len; row++) {
      const keyParts = groupByFields.map((f) => f.values[row]);
      const key = keyParts.map((v) => String(v)).join("");
      let bucket = buckets.get(key);
      if (!bucket) {
        bucket = { keys: keyParts, valuesByField: {} };
        buckets.set(key, bucket);
      }
      for (const field of frame.fields) {
        if (!bucket.valuesByField[field.name]) {
          bucket.valuesByField[field.name] = [];
        }
        bucket.valuesByField[field.name].push(field.values[row]);
      }
    }
    const groupKeys = [...buckets.keys()];
    const outFields = [];
    for (const [gi, src] of groupByFields.entries()) {
      outFields.push({
        name: src.name,
        type: src.type,
        config: { ...src.config ?? {} },
        values: groupKeys.map((k) => buckets.get(k).keys[gi])
      });
    }
    for (const spec of aggregateSpecs) {
      const src = findFrameField$1(frame, spec.name);
      if (!src) continue;
      for (const agg of spec.aggregations) {
        const values = groupKeys.map((k) => {
          const vals = buckets.get(k).valuesByField[src.name] ?? [];
          const fakeField = {
            name: src.name,
            type: src.type,
            config: src.config ?? {},
            values: vals
          };
          const calcs = reduceField$1(fakeField, [agg]);
          const v = calcs[agg];
          if (typeof v === "number") return v;
          if (v == null || typeof v === "boolean") return null;
          if (Array.isArray(v)) return v.length;
          return Number(v);
        });
        const outName = legacyMode && spec.aggregations.length === 1 && agg === "sum" ? spec.name : `${spec.name} (${agg})`;
        outFields.push({
          name: outName,
          type: "number",
          config: {},
          values
        });
      }
    }
    if (outFields.length <= groupByFields.length && !aggregateSpecs.length) ;
    if (!outFields.length) return frame;
    return createDataFrame({
      refId: frame.refId,
      name: frame.name,
      fields: outFields
    });
  }
  registerTransformer("groupBy", (frames, options = {}) => {
    const raw = options.fields;
    const by = options.by;
    let fieldConfig = {};
    let legacyMode = false;
    if (isFieldsMap$1(raw)) {
      fieldConfig = raw;
    } else {
      const legacyKeys = Array.isArray(raw) ? raw.map(String).filter(Boolean) : by ? [String(by)] : [];
      if (!legacyKeys.length) return frames;
      legacyMode = true;
      for (const k of legacyKeys) {
        fieldConfig[k] = { operation: "groupby" };
      }
    }
    if (!Object.keys(fieldConfig).length) return frames;
    return frames.map((frame) => groupByFrame(frame, fieldConfig, legacyMode));
  });
  registerTransformer("labelsToFields", (frames, options = {}) => {
    const mode = String(options.mode ?? "columns");
    const keepRaw = options.keepLabels;
    const keepSet = Array.isArray(keepRaw) && keepRaw.length ? new Set(keepRaw.map(String)) : void 0;
    const valueLabel = options.valueLabel != null && String(options.valueLabel) !== "" ? String(options.valueLabel) : void 0;
    if (mode === "rows") {
      const result = [];
      for (const frame of frames) {
        for (const field of frame.fields) {
          if (!field.labels || !Object.keys(field.labels).length) continue;
          const keys = [];
          const vals = [];
          if (keepSet) {
            for (const key of keepSet) {
              keys.push(key);
              vals.push(String(field.labels[key] ?? ""));
            }
          } else {
            for (const [key, val] of Object.entries(field.labels)) {
              keys.push(key);
              vals.push(String(val ?? ""));
            }
          }
          if (!vals.length) continue;
          result.push(
            createDataFrame({
              refId: frame.refId,
              // Grafana convertLabelsToRows: frame.name = getFieldDisplayName(field, frame, data)
              name: getFieldDisplayName(field, frame, frames),
              fields: [
                { name: "label", type: "string", values: keys, config: {} },
                { name: "value", type: "string", values: vals, config: {} }
              ]
            })
          );
        }
      }
      return result.length ? result : frames;
    }
    return frames.map((frame) => {
      const newFields = [];
      const uniqueLabels = {};
      for (const field of frame.fields) {
        if (!field.labels) {
          newFields.push(field);
          continue;
        }
        const sansLabels = {
          ...field,
          labels: void 0,
          config: {
            ...field.config ?? {},
            displayName: void 0,
            displayNameFromDS: void 0
          }
        };
        for (const labelName of Object.keys(field.labels)) {
          if (keepSet && !keepSet.has(labelName)) continue;
          if (valueLabel && valueLabel === labelName) {
            sansLabels.name = String(field.labels[labelName] ?? sansLabels.name);
            continue;
          }
          const set = uniqueLabels[labelName] ?? (uniqueLabels[labelName] = /* @__PURE__ */ new Set());
          set.add(String(field.labels[labelName] ?? ""));
        }
        newFields.push(sansLabels);
      }
      for (const name of Object.keys(uniqueLabels)) {
        for (const value of uniqueLabels[name]) {
          newFields.push({
            name,
            type: "string",
            values: Array.from({ length: frame.length || 0 }, () => value),
            config: {}
          });
        }
      }
      return createDataFrame({
        refId: frame.refId,
        name: frame.name,
        fields: newFields
      });
    });
  });
  registerTransformer("merge", (frames) => {
    if (frames.length <= 1) return frames;
    const base = frames[0];
    const fields = base.fields.map((f) => ({ ...f, values: [...f.values] }));
    for (const frame of frames.slice(1)) {
      for (const f of frame.fields) {
        const target = fields.find((x) => x.name === f.name && x.type === f.type);
        if (target) target.values.push(...f.values);
        else fields.push({ ...f, values: [...f.values] });
      }
    }
    return [createDataFrame({ refId: base.refId, name: base.name, fields })];
  });
  registerTransformer("concatenate", (frames, options = {}) => {
    if (!frames.length) return frames;
    if (frames.length < 2) return frames;
    const mode = String(options.frameNameMode ?? "field");
    const frameNameLabel = String(options.frameNameLabel ?? "frame");
    const outName = options.frameName != null ? String(options.frameName) : void 0;
    let maxLength = frames[0]?.length ?? frames[0]?.fields[0]?.values.length ?? 0;
    let sameLength = true;
    const fields = [];
    for (const frame of frames) {
      const len = frame.length ?? frame.fields[0]?.values.length ?? 0;
      if (len !== maxLength) {
        sameLength = false;
        maxLength = Math.max(maxLength, len);
      }
      const frameLabel = String(frame.name ?? frame.refId ?? "");
      for (const f of frame.fields) {
        const copy = {
          ...f,
          values: [...f.values],
          config: { ...f.config ?? {} },
          labels: f.labels ? { ...f.labels } : void 0
        };
        if (frameLabel) {
          if (mode === "drop") ;
          else if (mode === "label") {
            copy.labels = {
              ...copy.labels ?? {},
              [frameNameLabel]: frameLabel
            };
          } else {
            if (!copy.name || copy.name === "Value") {
              copy.name = frameLabel;
            } else {
              copy.name = `${frameLabel} · ${f.name}`;
            }
          }
        }
        fields.push(copy);
      }
    }
    if (!sameLength) {
      for (const f of fields) {
        if (f.values.length < maxLength) {
          const pad = new Array(maxLength - f.values.length).fill(void 0);
          f.values = [...f.values, ...pad];
        }
      }
    }
    return [
      {
        name: outName,
        fields,
        length: maxLength,
        refId: frames[0]?.refId
      }
    ];
  });
  function resolveBinaryValues(frame, allFrames, side, numericFields) {
    const len = frame.length || numericFields[0]?.values.length || 0;
    if (side == null) return null;
    if (typeof side === "number") {
      return Array.from({ length: len }, () => side);
    }
    if (typeof side === "string") {
      const byName = numericFields.find((f) => f.name === side) ?? frame.fields.find(
        (f) => f.name === side || getFieldDisplayName(f, frame, allFrames) === side
      );
      if (byName) {
        return byName.values.map((v) => byName.type === "boolean" ? v ? 1 : 0 : Number(v ?? 0));
      }
      const n = Number(side);
      if (Number.isFinite(n)) return Array.from({ length: len }, () => n);
      return null;
    }
    if (typeof side === "object") {
      const matcher = side.matcher;
      if (matcher?.id === "byName") {
        const name = String(matcher.options ?? "");
        const field = frame.fields.find(
          (f) => f.name === name || getFieldDisplayName(f, frame, allFrames) === name
        ) ?? numericFields.find((f) => f.name === name);
        if (field) {
          return field.values.map((v) => field.type === "boolean" ? v ? 1 : 0 : Number(v ?? 0));
        }
      }
      if (matcher?.id === "byType") {
        const t = String(matcher.options ?? "number");
        const field = frame.fields.find((f) => String(f.type) === t);
        if (field) {
          return field.values.map((v) => field.type === "boolean" ? v ? 1 : 0 : Number(v ?? 0));
        }
      }
      const fixed = side.fixed;
      if (fixed != null && fixed !== "") {
        const n = Number(fixed);
        if (Number.isFinite(n)) return Array.from({ length: len }, () => n);
      }
      if (matcher?.options != null) {
        const n = Number(matcher.options);
        if (Number.isFinite(n) && matcher.id !== "byName" && matcher.id !== "byType") {
          return Array.from({ length: len }, () => n);
        }
      }
    }
    return null;
  }
  registerTransformer("calculateField", (frames, options = {}) => {
    const alias = String(options.alias ?? options.outputName ?? "Total");
    let mode = String(options.mode ?? "reduceRow");
    if (mode === "cumulativeFunctions") mode = "cumulative";
    if (mode === "windowFunctions") mode = "window";
    return frames.map((frame) => {
      const nums = frame.fields.filter((f) => f.type === "number");
      if (!nums.length && mode !== "index") return frame;
      const len = frame.length || nums[0]?.values.length || 0;
      const values = [];
      if (mode === "index") {
        const asPercentile = options.index?.asPercentile === true || options.asPercentile === true;
        for (let i = 0; i < len; i++) {
          values.push(asPercentile && len > 0 ? i / len : i);
        }
      } else if (mode === "binary") {
        const binary = options.binary ?? {};
        const op = String(binary.operator ?? "+");
        const applyOp = (a, b) => op === "-" ? a - b : op === "*" ? a * b : op === "/" ? b ? a / b : 0 : op === "**" || op === "^" ? a ** b : a + b;
        const leftSide = binary.left;
        const isByType = leftSide && typeof leftSide === "object" && leftSide.matcher?.id === "byType";
        if (isByType) {
          const t = String(leftSide.matcher?.options ?? "number");
          const rightVals2 = resolveBinaryValues(frame, frames, binary.right, nums) ?? Array.from({ length: len }, () => 0);
          const rightLabel = (() => {
            const r = binary.right;
            if (r && typeof r === "object") {
              return String(r.matcher?.options ?? r.fixed ?? "");
            }
            return String(r ?? "");
          })();
          const extras = [];
          for (const field of frame.fields.filter((f) => String(f.type) === t)) {
            const outVals = [];
            for (let i = 0; i < len; i++) {
              const a = field.type === "boolean" ? field.values[i] ? 1 : 0 : Number(field.values[i] ?? 0);
              outVals.push(applyOp(a, Number(rightVals2[i] ?? 0)));
            }
            extras.push({
              name: `${field.name} ${op} ${rightLabel}`.trim(),
              type: "number",
              values: outVals,
              config: {}
            });
          }
          if (extras.length) {
            let outFields = [...frame.fields, ...extras];
            if (options.replaceFields === true) {
              const time = frame.fields.filter((f) => f.type === "time");
              outFields = [...time, ...extras];
            }
            return createDataFrame({
              refId: frame.refId,
              name: frame.name,
              fields: outFields
            });
          }
        }
        const leftVals = resolveBinaryValues(frame, frames, binary.left, nums) ?? nums[0]?.values.map((v) => Number(v ?? 0)) ?? [];
        const rightVals = resolveBinaryValues(frame, frames, binary.right, nums) ?? Array.from({ length: len }, () => 0);
        for (let i = 0; i < len; i++) {
          values.push(applyOp(Number(leftVals[i] ?? 0), Number(rightVals[i] ?? 0)));
        }
      } else if (mode === "unary") {
        const unary = options.unary ?? {};
        const field = (unary.fieldName ? nums.find(
          (f) => f.name === unary.fieldName || getFieldDisplayName(f, frame, frames) === unary.fieldName
        ) : void 0) ?? nums[0];
        const op = String(unary.operator ?? "abs");
        for (let i = 0; i < len; i++) {
          const a = Number(field.values[i] ?? 0);
          if (op === "abs") values.push(Math.abs(a));
          else if (op === "log" || op === "ln") values.push(a > 0 ? Math.log(a) : Number.NaN);
          else if (op === "log2") values.push(a > 0 ? Math.log2(a) : Number.NaN);
          else if (op === "log10") values.push(a > 0 ? Math.log10(a) : Number.NaN);
          else if (op === "sqrt") values.push(a >= 0 ? Math.sqrt(a) : Number.NaN);
          else if (op === "square") values.push(a * a);
          else if (op === "ceil") values.push(Math.ceil(a));
          else if (op === "floor") values.push(Math.floor(a));
          else values.push(a);
        }
      } else if (mode === "cumulative") {
        const cum = options.cumulative ?? {};
        const fieldKey2 = cum.fieldName ?? cum.field ?? options.fieldName ?? "";
        const field = (fieldKey2 ? nums.find(
          (f) => f.name === fieldKey2 || getFieldDisplayName(f, frame, frames) === fieldKey2
        ) : void 0) ?? nums[0];
        const reducer = String(cum.reducer ?? "sum");
        let acc = 0;
        let count = 0;
        for (let i = 0; i < len; i++) {
          const n = Number(field.values[i]);
          if (Number.isFinite(n)) {
            acc += n;
            count += 1;
          }
          if (reducer === "mean") values.push(count ? acc / count : Number.NaN);
          else if (reducer === "max") {
            const slice = field.values.slice(0, i + 1).map(Number).filter((x) => Number.isFinite(x));
            values.push(slice.length ? Math.max(...slice) : Number.NaN);
          } else if (reducer === "min") {
            const slice = field.values.slice(0, i + 1).map(Number).filter((x) => Number.isFinite(x));
            values.push(slice.length ? Math.min(...slice) : Number.NaN);
          } else {
            values.push(acc);
          }
        }
      } else if (mode === "window") {
        const winOpts = options.window ?? {};
        const fieldKey2 = winOpts.fieldName ?? winOpts.field ?? options.fieldName ?? "";
        const field = (fieldKey2 ? nums.find(
          (f) => f.name === fieldKey2 || getFieldDisplayName(f, frame, frames) === fieldKey2
        ) : void 0) ?? nums[0];
        const sizeMode = String(winOpts.windowSizeMode ?? "fixed");
        const rawSize = Number(
          winOpts.windowSize ?? options.windowSize ?? (sizeMode === "percentage" ? 0.1 : 3)
        );
        const win = Math.max(
          1,
          Math.ceil(sizeMode === "percentage" || sizeMode === "Percentage" ? rawSize * len : rawSize)
        );
        const alignment = String(winOpts.windowAlignment ?? "trailing");
        const reducer = String(winOpts.reducer ?? "mean");
        const reduceSlice = (slice) => {
          if (!slice.length) return Number.NaN;
          if (reducer === "sum") return slice.reduce((a, b) => a + b, 0);
          if (reducer === "min") return Math.min(...slice);
          if (reducer === "max") return Math.max(...slice);
          return slice.reduce((a, b) => a + b, 0) / slice.length;
        };
        for (let i = 0; i < len; i++) {
          let from;
          let to;
          if (alignment === "centered" || alignment === "Centered") {
            const leading = Math.ceil(win / 2) - 1;
            const trailing = Math.floor(win / 2);
            from = Math.max(0, i - trailing);
            to = Math.min(len, i + leading + 1);
          } else {
            from = Math.max(0, i - win + 1);
            to = i + 1;
          }
          const slice = field.values.slice(from, to).map(Number).filter((n) => Number.isFinite(n));
          values.push(reduceSlice(slice));
        }
      } else {
        const reduceOpts = options.reduce ?? {};
        const reducer = String(reduceOpts.reducer ?? "sum");
        const include = Array.isArray(reduceOpts.include) ? reduceOpts.include.map(String) : [];
        const nullMode = String(
          reduceOpts.nullValueMode ?? options.nullValueMode ?? "nullAsZero"
        ).toLowerCase();
        const ignoreNulls = nullMode === "ignore" || nullMode === "nullvaluemode.ignore";
        const nullAsZero = nullMode === "aszero" || nullMode === "nullaszero" || nullMode === "nullvaluemode.aszero" || !ignoreNulls && nullMode !== "preserve";
        const cols = include.length ? frame.fields.filter(
          (f) => include.includes(f.name) || include.includes(String(f.config?.displayName ?? ""))
        ) : nums;
        for (let i = 0; i < len; i++) {
          const row = [];
          for (const f of cols) {
            const raw = f.values[i];
            if (raw == null || raw === "") {
              if (ignoreNulls) continue;
              if (nullAsZero) row.push(0);
              continue;
            }
            const n = f.type === "boolean" ? raw ? 1 : 0 : Number(raw);
            if (!Number.isFinite(n)) {
              if (ignoreNulls) continue;
              if (nullAsZero) row.push(0);
              continue;
            }
            row.push(n);
          }
          let v = 0;
          if (reducer === "mean") v = row.length ? row.reduce((a, b) => a + b, 0) / row.length : 0;
          else if (reducer === "min") v = row.length ? Math.min(...row) : 0;
          else if (reducer === "max") v = row.length ? Math.max(...row) : 0;
          else if (reducer === "count") v = row.length;
          else v = row.reduce((a, b) => a + b, 0);
          values.push(v);
        }
      }
      const indexAsPercentile = mode === "index" && (options.index?.asPercentile === true || options.asPercentile === true);
      const calculated = {
        name: alias,
        type: "number",
        values,
        config: indexAsPercentile ? { unit: "percentunit" } : {}
      };
      if (options.replaceFields === true) {
        const timeFields = frame.fields.filter((f) => f.type === "time");
        return createDataFrame({
          refId: frame.refId,
          name: frame.name,
          fields: [...timeFields, calculated]
        });
      }
      return createDataFrame({
        refId: frame.refId,
        name: frame.name,
        fields: [...frame.fields, calculated]
      });
    });
  });
  function findFrameField(frame, name, allFrames) {
    return findField(frame, name, allFrames);
  }
  function formatTimeToken(date, format, utc) {
    const y = utc ? date.getUTCFullYear() : date.getFullYear();
    const M = (utc ? date.getUTCMonth() : date.getMonth()) + 1;
    const d = utc ? date.getUTCDate() : date.getDate();
    const H = utc ? date.getUTCHours() : date.getHours();
    const m = utc ? date.getUTCMinutes() : date.getMinutes();
    const s = utc ? date.getUTCSeconds() : date.getSeconds();
    const pad = (n, w = 2) => String(n).padStart(w, "0");
    const h12 = H % 12 || 12;
    const ampm = H < 12 ? "am" : "pm";
    return format.replaceAll("YYYY", String(y)).replaceAll("YY", String(y).slice(-2)).replaceAll("MM", pad(M)).replaceAll("M", String(M)).replaceAll("DD", pad(d)).replaceAll("D", String(d)).replaceAll("HH", pad(H)).replaceAll("H", String(H)).replaceAll("hh", pad(h12)).replaceAll("h", String(h12)).replaceAll("mm", pad(m)).replaceAll("ss", pad(s)).replaceAll("a", ampm).replaceAll("A", ampm.toUpperCase());
  }
  const GAZETTEER_COUNTRIES = {
    US: { name: "United States", lat: 37.09, lon: -95.71 },
    NL: { name: "Netherlands", lat: 52.13, lon: 5.29 },
    DE: { name: "Germany", lat: 51.16, lon: 10.45 },
    JP: { name: "Japan", lat: 36.2, lon: 138.25 },
    BR: { name: "Brazil", lat: -14.23, lon: -51.92 },
    CN: { name: "China", lat: 35.86, lon: 104.19 },
    GB: { name: "United Kingdom", lat: 55.37, lon: -3.43 },
    FR: { name: "France", lat: 46.22, lon: 2.21 }
  };
  const GRAFANA_FORMATS = {
    "Upper Case": "upper",
    "Lower Case": "lower",
    "Sentence Case": "sentence",
    "Title Case": "title",
    "Pascal Case": "pascal",
    "Camel Case": "camel",
    "Snake Case": "snake",
    "Kebab Case": "kebab",
    "Trim": "trim",
    "Substring": "substring"
  };
  function normalizeOp(raw) {
    const s = String(raw ?? "").trim();
    if (!s) return "upper";
    if (s in GRAFANA_FORMATS) {
      return GRAFANA_FORMATS[s];
    }
    const lower = s.toLowerCase().replaceAll(/[\s_-]+/g, "");
    switch (lower) {
      case "upper":
      case "uppercase":
      case "touppercase":
        return "upper";
      case "lower":
      case "lowercase":
      case "tolowercase":
        return "lower";
      case "sentence":
      case "sentencecase":
        return "sentence";
      case "title":
      case "titlecase":
        return "title";
      case "pascal":
      case "pascalcase":
        return "pascal";
      case "camel":
      case "camelcase":
        return "camel";
      case "snake":
      case "snakecase":
        return "snake";
      case "kebab":
      case "kebabcase":
        return "kebab";
      case "trim":
        return "trim";
      case "substring":
      case "substr":
        return "substring";
      case "replace":
        return "replace";
      default:
        return s;
    }
  }
  function splitToCapitalWords(input) {
    return input.split(" ").map((w) => w ? w.charAt(0).toUpperCase() + w.slice(1).toLowerCase() : w);
  }
  function resolveOpAndRange(options) {
    const substringOpt = options.substring;
    const rangeObj = substringOpt && typeof substringOpt === "object" && !Array.isArray(substringOpt) ? substringOpt : void 0;
    const substringAsOp = typeof substringOpt === "string" && substringOpt.trim() ? substringOpt : void 0;
    const rawOp = options.outputFormat ?? options.algorithm ?? options.operation ?? substringAsOp ?? (rangeObj ? "substring" : "upper");
    const start = Number(options.substringStart ?? rangeObj?.start ?? options.start ?? 0);
    const endRaw = options.substringEnd ?? rangeObj?.end ?? options.end;
    const end = endRaw == null || endRaw === "" ? void 0 : Number(endRaw);
    return {
      op: normalizeOp(String(rawOp)),
      start: Number.isFinite(start) ? start : 0,
      end: end != null && Number.isFinite(end) ? end : void 0
    };
  }
  function formatValue$1(s, op, start, end, options) {
    switch (op) {
      case "upper":
        return s.toUpperCase();
      case "lower":
        return s.toLowerCase();
      case "sentence":
        return s.charAt(0).toUpperCase() + s.slice(1);
      case "title":
        return splitToCapitalWords(s).join(" ");
      case "pascal":
        return splitToCapitalWords(s).join("");
      case "camel": {
        const p = splitToCapitalWords(s).join("");
        return p.charAt(0).toLowerCase() + p.slice(1);
      }
      case "snake":
        return s.toLowerCase().split(" ").join("_");
      case "kebab":
        return s.toLowerCase().split(" ").join("-");
      case "trim":
        return s.trim();
      case "substring":
        return end == null ? s.slice(start) : s.slice(start, end);
      case "replace":
        try {
          return s.replace(
            new RegExp(String(options.pattern ?? ""), String(options.flags ?? "g")),
            String(options.replacement ?? "")
          );
        } catch {
          return s;
        }
      default:
        return s;
    }
  }
  registerTransformer("formatString", (frames, options = {}) => {
    const opts = options;
    const substringOpt = opts.substring;
    const rangeObj = substringOpt && typeof substringOpt === "object" && !Array.isArray(substringOpt) ? substringOpt : void 0;
    const fieldName2 = String(
      opts.stringField ?? opts.fieldName ?? rangeObj?.fieldName ?? opts.field ?? ""
    );
    if (!fieldName2) return frames;
    const { op, start, end } = resolveOpAndRange(opts);
    const alias = opts.alias != null ? String(opts.alias) : "";
    return frames.map(
      (frame) => createDataFrame({
        refId: frame.refId,
        name: frame.name,
        fields: frame.fields.map((f) => {
          if (!fieldMatchesName(f, fieldName2, frame, frames)) return f;
          const values = f.values.map((v) => formatValue$1(String(v ?? ""), op, start, end, opts));
          return {
            ...f,
            name: alias || f.name,
            type: "string",
            values
          };
        })
      })
    );
  });
  function isTimeSeriesFrame(frame) {
    if (!frame.fields?.length) return false;
    const timeFields = frame.fields.filter((f) => f.type === "time");
    const valueFields = frame.fields.filter((f) => f.type !== "time" && f.type !== "string");
    return timeFields.length >= 1 && valueFields.length >= 1;
  }
  registerTransformer("seriesToRows", (frames) => {
    const data = (frames || []).filter((f) => (f.length ?? f.fields[0]?.values?.length ?? 0) > 0);
    if (!data.length) return frames;
    if (!data.every(isTimeSeriesFrame)) {
      return frames;
    }
    const times = [];
    const metrics = [];
    const values = [];
    let valueType = "number";
    let valueConfig = {};
    let timeConfig = {};
    for (const [frameIndex, frame] of data.entries()) {
      const timeField = frame.fields.find((f) => f.type === "time");
      if (!timeField) continue;
      const valueField = frame.fields.find((f) => f.type !== "time") ?? frame.fields.find((f) => f.type === "number");
      if (!valueField) continue;
      if (frameIndex === 0) {
        valueType = valueField.type;
        valueConfig = { ...valueField.config || {} };
        timeConfig = { ...timeField.config || {} };
      }
      const metricName = getFrameDisplayName(frame, frameIndex);
      const n = frame.length ?? timeField.values.length;
      for (let i = 0; i < n; i++) {
        times.push(Number(timeField.values[i]));
        metrics.push(metricName);
        values.push(valueField.values[i]);
      }
    }
    const idxs = times.map((_, i) => i);
    idxs.sort((a, b) => {
      const d = times[b] - times[a];
      return d !== 0 ? d : a - b;
    });
    return [
      createDataFrame({
        refId: `seriesToRows-${data.map((f) => f.refId ?? "").join("-")}`,
        name: "seriesToRows",
        fields: [
          {
            name: "Time",
            type: "time",
            config: timeConfig,
            values: idxs.map((i) => times[i])
          },
          {
            name: "Metric",
            type: "string",
            config: {},
            values: idxs.map((i) => metrics[i])
          },
          {
            name: "Value",
            type: valueType,
            config: valueConfig,
            values: idxs.map((i) => values[i])
          }
        ]
      })
    ];
  });
  registerTransformer("filterByValue", (frames, options = {}) => {
    const type = String(options.type ?? "include");
    const match = String(options.match ?? "all");
    const filters = options.filters ?? [];
    if (!filters.length) return frames;
    const matchOne = (n, op, opts) => {
      if (op === "isNull" || op === "ValueIsNull") return n == null || n === "";
      if (op === "isNotNull" || op === "ValueIsNotNull") return n != null && n !== "";
      if (op === "regex" || op === "ValueMatchesRegex") {
        try {
          return new RegExp(String(opts.pattern ?? opts.value ?? "")).test(String(n ?? ""));
        } catch {
          return false;
        }
      }
      const num = Number(n);
      const thr = Number(opts.value ?? 0);
      if (op.includes("greaterOrEqual") || op === "gte") return num >= thr;
      if (op.includes("lowerOrEqual") || op.includes("lessOrEqual") || op === "lte")
        return num <= thr;
      if (op.includes("greater") || op === "gt") return num > thr;
      if (op.includes("lower") || op.includes("less") || op === "lt") return num < thr;
      if (op.includes("equal") || op === "eq") return num === thr || String(n) === String(opts.value);
      if (op === "between" || op.includes("Between")) {
        const a = Number(opts.valueFrom ?? opts.value ?? 0);
        const b = Number(opts.valueTo ?? 0);
        return num >= Math.min(a, b) && num <= Math.max(a, b);
      }
      return true;
    };
    return frames.map((frame) => {
      const len = frame.length || frame.fields[0]?.values.length || 0;
      const keep = [];
      for (let i = 0; i < len; i++) {
        const results = filters.map((filter) => {
          const field = findFrameField(frame, filter.fieldName, frames);
          if (!field) return true;
          const op = String(filter.config?.id ?? "greater");
          return matchOne(field.values[i], op, filter.config?.options ?? {});
        });
        const rowOk = match === "any" ? results.some(Boolean) : results.every(Boolean);
        keep.push(type === "exclude" ? !rowOk : rowOk);
      }
      return createDataFrame({
        refId: frame.refId,
        name: frame.name,
        fields: frame.fields.map((f) => ({
          ...f,
          values: f.values.filter((_, i) => keep[i])
        }))
      });
    });
  });
  registerTransformer("renameByRegex", (frames, options = {}) => {
    const regexRaw = String(options.regex ?? "");
    const renamePattern = String(options.renamePattern ?? "$1");
    if (!regexRaw) return frames;
    const re = stringToJsRegexSafe(regexRaw) ?? (() => {
      try {
        return new RegExp(regexRaw);
      } catch {
        return null;
      }
    })();
    if (!re) return frames;
    return frames.map(
      (frame) => createDataFrame({
        refId: frame.refId,
        name: frame.name,
        meta: frame.meta,
        fields: frame.fields.map((f) => {
          const displayName = getFieldDisplayName(f, frame, frames);
          if (!re.test(displayName)) {
            return f;
          }
          re.lastIndex = 0;
          const newDisplayName = displayName.replace(re, renamePattern);
          re.lastIndex = 0;
          return {
            ...f,
            // Grafana keeps field.name; display goes through config/state.
            // Also mirror onto name when it equaled the old display name so
            // name-only consumers (organize/filterByName) still see the rename —
            // matches common dashboard expectations while displayName is source of truth.
            name: f.name === displayName || !f.config?.displayName ? newDisplayName : f.name,
            config: {
              ...f.config || {},
              displayName: newDisplayName
            },
            state: {
              ...f.state || {},
              displayName: newDisplayName
            }
          };
        })
      })
    );
  });
  const ISO8601 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3,})?(?:Z|[-+]\d{2}:?\d{2})$/;
  function parseWithDateFormat(value, dateFormat) {
    if (value == null || value === "") return null;
    const fmt = dateFormat?.trim();
    if (typeof value === "number") {
      if (!Number.isFinite(value)) return null;
      if (fmt === "X") return value * 1e3;
      if (fmt === "x") return value;
      return value;
    }
    const raw = String(value).trim();
    if (!raw) return null;
    if (fmt === "X") {
      const n = Number(raw);
      return Number.isFinite(n) ? n * 1e3 : null;
    }
    if (fmt === "x") {
      const n = Number(raw);
      return Number.isFinite(n) ? n : null;
    }
    if (!fmt) {
      if (ISO8601.test(raw)) {
        const t3 = Date.parse(raw);
        return Number.isFinite(t3) ? t3 : null;
      }
      const t2 = Date.parse(raw);
      if (Number.isFinite(t2)) return t2;
      const n = Number(raw);
      return Number.isFinite(n) ? n : null;
    }
    const tokenRe = /(YYYY|YY|MM|DD|HH|hh|mm|ss|[AaMDHh])/g;
    const parts = [];
    let last = 0;
    let m;
    while ((m = tokenRe.exec(fmt)) !== null) {
      if (m.index > last) {
        parts.push({ kind: "lit", v: fmt.slice(last, m.index) });
      }
      parts.push({ kind: "tok", v: m[1] });
      last = m.index + m[1].length;
    }
    if (last < fmt.length) parts.push({ kind: "lit", v: fmt.slice(last) });
    let pos = 0;
    const got = {};
    for (const part of parts) {
      if (part.kind === "lit") {
        if (raw.slice(pos, pos + part.v.length) !== part.v) {
          pos = -1;
          break;
        }
        pos += part.v.length;
        continue;
      }
      const tok = part.v;
      let take = tok.length;
      if (tok === "YYYY") take = 4;
      else if (tok === "YY") take = 2;
      else if (tok === "A" || tok === "a") {
        const ampm = raw.slice(pos, pos + 2).toLowerCase();
        if (ampm !== "am" && ampm !== "pm") {
          pos = -1;
          break;
        }
        got.ampm = ampm === "pm" ? 1 : 0;
        pos += 2;
        continue;
      } else if (tok.length === 1) {
        let j = pos;
        while (j < raw.length && /\d/.test(raw[j])) j++;
        take = Math.max(1, j - pos);
      }
      const slice = raw.slice(pos, pos + take);
      if (!/^\d+$/.test(slice)) {
        pos = -1;
        break;
      }
      got[tok] = Number(slice);
      pos += take;
    }
    if (pos >= 0) {
      const year = got.YYYY ?? (got.YY != null ? 2e3 + got.YY : (/* @__PURE__ */ new Date()).getFullYear());
      const month = (got.MM ?? got.M ?? 1) - 1;
      const day = got.DD ?? got.D ?? 1;
      let hour = got.HH ?? got.H ?? got.hh ?? got.h ?? 0;
      const minute = got.mm ?? 0;
      const second = got.ss ?? 0;
      if (got.ampm != null && (got.hh != null || got.h != null)) {
        hour = hour % 12;
        if (got.ampm === 1) hour += 12;
      }
      const d = new Date(year, month, day, hour, minute, second);
      const t2 = d.getTime();
      return Number.isFinite(t2) ? t2 : null;
    }
    if (fmt === "YYYY") {
      const ym = raw.match(/(\d{4})/);
      if (ym) {
        const d = new Date(Number(ym[1]), 0, 1);
        return d.getTime();
      }
    }
    const t = Date.parse(raw);
    return Number.isFinite(t) ? t : null;
  }
  function toNumber(v) {
    if (v == null || v === "") return null;
    if (typeof v === "number") return Number.isFinite(v) ? v : null;
    if (typeof v === "boolean") return v ? 1 : 0;
    const s = String(v).replaceAll(",", "").trim();
    if (!s) return null;
    const n = Number(s);
    return Number.isFinite(n) ? n : null;
  }
  registerTransformer("convertFieldType", (frames, options = {}) => {
    const conversions = options.conversions ?? [];
    if (!conversions.length && options.targetField) {
      conversions.push({
        targetField: String(options.targetField),
        destinationType: String(options.destinationType ?? "string"),
        dateFormat: options.dateFormat,
        timezone: options.timezone,
        joinWith: options.joinWith
      });
    }
    if (!conversions.length) return frames;
    return frames.map(
      (frame) => createDataFrame({
        refId: frame.refId,
        name: frame.name,
        fields: frame.fields.map((f) => {
          const conv = conversions.find(
            (c) => c.targetField === f.name || c.targetField != null && getFieldDisplayName(f, frame, frames) === String(c.targetField)
          );
          if (!conv) return f;
          const type = String(conv.destinationType);
          const dateFormat = conv.dateFormat ? String(conv.dateFormat) : void 0;
          if (type === "number") {
            return {
              ...f,
              type: "number",
              values: f.values.map((v) => toNumber(v))
            };
          }
          if (type === "string") {
            const tz = String(conv.timezone ?? "browser");
            const utc = tz.toLowerCase() === "utc";
            const joinWith = conv.joinWith;
            return {
              ...f,
              type: "string",
              values: f.values.map((v) => {
                if (joinWith && Array.isArray(v)) return v.join(String(joinWith));
                if (f.type === "time" || typeof v === "number" && dateFormat) {
                  const d = new Date(Number(v));
                  if (!Number.isFinite(d.getTime())) return String(v ?? "");
                  if (dateFormat) return formatTimeToken(d, dateFormat, utc);
                  return d.toISOString();
                }
                if (v != null && typeof v === "object") {
                  try {
                    return JSON.stringify(v);
                  } catch {
                    return String(v);
                  }
                }
                return String(v ?? "");
              })
            };
          }
          if (type === "time") {
            if (f.type === "time" && typeof f.values.find((x) => x != null) === "number" && dateFormat !== "X") {
              return { ...f, type: "time" };
            }
            if (typeof f.values.find((x) => x != null) === "number" && dateFormat !== "X" && dateFormat !== "x") {
              return { ...f, type: "time" };
            }
            return {
              ...f,
              type: "time",
              values: f.values.map((v) => parseWithDateFormat(v, dateFormat))
            };
          }
          if (type === "boolean") {
            return {
              ...f,
              type: "boolean",
              values: f.values.map((v) => v === true || v === 1 || v === "true" || v === "1")
            };
          }
          if (type === "enum") {
            const texts = conv.enumConfig?.text ?? [];
            if (!texts.length) return { ...f, type: "other" };
            const lookup = new Map(texts.map((t, i) => [t, i]));
            return {
              ...f,
              type: "other",
              values: f.values.map((v) => lookup.get(String(v)) ?? null),
              config: {
                ...f.config ?? {},
                type: { enum: { text: texts } }
              }
            };
          }
          if (type === "other") {
            return {
              ...f,
              type: "other",
              values: f.values.map((v) => {
                if (typeof v !== "string") return v;
                try {
                  return JSON.parse(v);
                } catch {
                  return null;
                }
              })
            };
          }
          return f;
        })
      })
    );
  });
  function fieldName(frame, field, multi) {
    if (!multi) return field.name;
    return frame.refId ? `${field.name} ${frame.refId}` : field.name;
  }
  function joinUnique(frames, by, mode) {
    const keySets = frames.map((frame) => {
      const keyField = findFrameField(frame, by, frames);
      const set = /* @__PURE__ */ new Set();
      if (keyField) for (const v of keyField.values) set.add(String(v));
      return set;
    });
    let keyValues = [];
    if (mode === "inner") {
      let inter = keySets[0] ? new Set(keySets[0]) : /* @__PURE__ */ new Set();
      for (const s of keySets.slice(1)) {
        inter = new Set([...inter].filter((k) => s.has(k)));
      }
      keyValues = [...inter];
    } else {
      const index2 = /* @__PURE__ */ new Map();
      for (const frame of frames) {
        const keyField = findFrameField(frame, by, frames);
        if (!keyField) continue;
        for (const v of keyField.values) {
          const k = String(v);
          if (!index2.has(k)) {
            index2.set(k, keyValues.length);
            keyValues.push(k);
          }
        }
      }
    }
    const outFields = [];
    const byType = findFrameField(frames[0], by, frames)?.type ?? "string";
    outFields.push({
      name: by,
      type: byType,
      values: keyValues,
      config: {}
    });
    const multi = frames.length > 1;
    for (const frame of frames) {
      const keyField = findFrameField(frame, by, frames);
      if (!keyField) continue;
      const local = /* @__PURE__ */ new Map();
      keyField.values.forEach((v, i) => {
        const k = String(v);
        if (!local.has(k)) local.set(k, i);
      });
      for (const field of frame.fields.filter((f) => f !== keyField)) {
        outFields.push({
          name: fieldName(frame, field, multi),
          type: field.type,
          values: keyValues.map((k) => {
            const i = local.get(k);
            return i == null ? null : field.values[i];
          }),
          config: field.config ?? {}
        });
      }
    }
    return createDataFrame({
      name: "joined",
      refId: frames[0]?.refId,
      fields: outFields
    });
  }
  function joinOuterTabular(frames, by) {
    if (!frames.length) {
      return createDataFrame({ name: "joined", fields: [] });
    }
    const tables = frames.map((frame) => {
      const keyField = findFrameField(frame, by, frames);
      return {
        keys: keyField ? [...keyField.values] : [],
        cols: frame.fields.filter((f) => f !== keyField).map((field) => ({ field, frame }))
      };
    });
    let plan = tables[0].keys.map((key, i) => ({
      key,
      src: tables.map((_, ti) => ti === 0 ? i : -1)
    }));
    for (let ti = 1; ti < tables.length; ti++) {
      const right = tables[ti];
      const index2 = /* @__PURE__ */ new Map();
      right.keys.forEach((v, i) => {
        const k = String(v);
        const list = index2.get(k) ?? [];
        list.push(i);
        index2.set(k, list);
      });
      const next = [];
      const matchedRight = /* @__PURE__ */ new Set();
      for (const row of plan) {
        if (row.key == null || row.key === "") {
          next.push(row);
          continue;
        }
        const ridxs = index2.get(String(row.key));
        if (ridxs?.length) {
          for (const ri of ridxs) {
            matchedRight.add(ri);
            const src = [...row.src];
            src[ti] = ri;
            next.push({ key: row.key, src });
          }
        } else {
          next.push(row);
        }
      }
      right.keys.forEach((key, ri) => {
        if (matchedRight.has(ri)) return;
        const src = tables.map(() => -1);
        src[ti] = ri;
        next.push({ key, src });
      });
      plan = next;
    }
    const multi = frames.length > 1;
    const byType = findFrameField(frames[0], by, frames)?.type ?? "string";
    const outFields = [
      {
        name: by,
        type: byType,
        values: plan.map((p) => p.key),
        config: {}
      }
    ];
    tables.forEach((table, ti) => {
      for (const { field, frame } of table.cols) {
        outFields.push({
          name: fieldName(frame, field, multi),
          type: field.type,
          values: plan.map((p) => {
            const ri = p.src[ti];
            return ri < 0 ? null : field.values[ri];
          }),
          config: field.config ?? {}
        });
      }
    });
    return createDataFrame({
      name: "joined",
      refId: frames[0]?.refId,
      fields: outFields
    });
  }
  registerTransformer("joinByField", (frames, options = {}) => {
    const by = String(options.byField ?? options.by ?? "Time");
    const mode = String(options.mode ?? "outer");
    if (frames.length <= 1) return frames;
    if (mode === "outerTabular") {
      return [joinOuterTabular(frames, by)];
    }
    if (mode === "inner") {
      return [joinUnique(frames, by, "inner")];
    }
    return [joinUnique(frames, by, "outer")];
  });
  var SpecialValue = /* @__PURE__ */ ((SpecialValue2) => {
    SpecialValue2["True"] = "true";
    SpecialValue2["False"] = "false";
    SpecialValue2["Null"] = "null";
    SpecialValue2["Empty"] = "empty";
    SpecialValue2["Zero"] = "zero";
    return SpecialValue2;
  })(SpecialValue || {});
  function getSpecialValue(specialValue) {
    switch (String(
      specialValue ?? "empty"
      /* Empty */
    )) {
      case "false":
      case "False":
        return false;
      case "true":
      case "True":
        return true;
      case "null":
      case "Null":
        return null;
      case "zero":
      case "Zero":
        return 0;
      case "empty":
      case "Empty":
      default:
        return "";
    }
  }
  registerTransformer("groupingToMatrix", (frames, options = {}) => {
    const columnField = String(options.columnField ?? options.column ?? "");
    const rowField = String(options.rowField ?? options.row ?? "");
    const valueField = String(options.valueField ?? options.cellValue ?? options.value ?? "");
    const emptyValue = getSpecialValue(
      options.emptyValue ?? SpecialValue.Empty
    );
    return frames.map((frame) => {
      const col = findFrameField(frame, columnField, frames) ?? frame.fields.find((f) => f.type === "string");
      const row = findFrameField(frame, rowField, frames) ?? frame.fields.filter((f) => f.type === "string")[1];
      const val = findFrameField(frame, valueField, frames) ?? frame.fields.find((f) => f.type === "number");
      if (!col || !row || !val) return frame;
      const cols = [...new Set(col.values.map(String))];
      const rows = [...new Set(row.values.map(String))];
      const map = /* @__PURE__ */ new Map();
      for (let i = 0; i < col.values.length; i++) {
        map.set(`${row.values[i]}\0${col.values[i]}`, val.values[i]);
      }
      return createDataFrame({
        refId: frame.refId,
        name: frame.name || "matrix",
        fields: [
          { name: row.name, type: "string", values: rows },
          ...cols.map((c) => ({
            name: c,
            type: val.type === "number" ? "number" : val.type,
            values: rows.map((r) => {
              if (!map.has(`${r}\0${c}`)) return emptyValue;
              const v = map.get(`${r}\0${c}`);
              return v == null ? emptyValue : val.type === "number" ? Number(v) : v;
            })
          }))
        ]
      });
    });
  });
  function finiteNums(values) {
    const out = [];
    for (const v of values) {
      const n = Number(v);
      if (Number.isFinite(n)) out.push(n);
    }
    return out;
  }
  function resolveSizeAndStart(allValues, cfg) {
    const vals = allValues.filter((n) => Number.isFinite(n));
    if (!vals.length) return null;
    const min = Math.min(...vals);
    const max = Math.max(...vals);
    const bucketCount2 = cfg.bucketCount;
    const size = cfg.bucketSizeOpt > 0 ? cfg.bucketSizeOpt : (max - min) / bucketCount2 || 1;
    const start = size > 0 ? Math.floor((min - cfg.offset) / size) * size + cfg.offset : min + cfg.offset;
    return { size, start, bucketCount: bucketCount2 };
  }
  function countIntoBuckets(values, start, size, bucketCount2) {
    const counts = new Array(bucketCount2).fill(0);
    for (const v of values) {
      if (!Number.isFinite(v)) continue;
      let idx = Math.floor((v - start) / size);
      if (idx < 0) idx = 0;
      if (idx >= bucketCount2) idx = bucketCount2 - 1;
      counts[idx]++;
    }
    return counts;
  }
  function bucketEdges(start, size, bucketCount2) {
    const bucketMin = [];
    const bucketMax = [];
    for (let i = 0; i < bucketCount2; i++) {
      bucketMin.push(start + i * size);
      bucketMax.push(start + (i + 1) * size);
    }
    return { bucketMin, bucketMax };
  }
  function collectNumericSeries(frames) {
    const out = [];
    for (const frame of frames) {
      for (const field of frame.fields) {
        if (field.type !== "number") continue;
        if (field.name === "BucketMin" || field.name === "BucketMax") continue;
        if (field.name === "xMin" || field.name === "xMax") continue;
        const values = finiteNums(field.values);
        if (!values.length) continue;
        out.push({
          name: field.name,
          displayName: getFieldDisplayName(field, frame, frames),
          values,
          config: { ...field.config },
          frame,
          field
        });
      }
    }
    return out;
  }
  registerTransformer("histogram", (frames, options = {}) => {
    const bucketCount2 = Math.max(1, Number(options.bucketCount ?? 10));
    const bucketSizeOpt = Number(options.bucketSize ?? 0);
    const bucketOffsetRaw = options.bucketOffset;
    const bucketOffset = bucketOffsetRaw == null || bucketOffsetRaw === "" ? 0 : Number(bucketOffsetRaw);
    const offset = Number.isFinite(bucketOffset) ? bucketOffset : 0;
    const combine = options.combine === true;
    const cfg = { bucketCount: bucketCount2, bucketSizeOpt, offset };
    const series = collectNumericSeries(frames);
    if (!series.length) return frames;
    const allValues = series.flatMap((s) => s.values);
    const geo = resolveSizeAndStart(allValues, cfg);
    if (!geo) return frames;
    const { size, start, bucketCount: bc } = geo;
    const { bucketMin, bucketMax } = bucketEdges(start, size, bc);
    const countColumns = series.map((s) => ({
      name: s.name,
      values: countIntoBuckets(s.values, start, size, bc),
      config: {
        ...s.config,
        // preserve display name for legend when multi-count
        ...s.displayName && s.displayName !== s.name ? { displayName: s.displayName } : {}
      }
    }));
    let countFields;
    if (combine || countColumns.length === 1) {
      const values = countColumns.length === 1 ? countColumns[0].values : countColumns[0].values.map(
        (_, i) => countColumns.reduce((sum, col) => sum + Number(col.values[i] ?? 0), 0)
      );
      countFields = [
        {
          name: "Count",
          type: "number",
          values,
          config: countColumns.length === 1 ? countColumns[0].config : { displayName: "Count" }
        }
      ];
    } else {
      const seen = /* @__PURE__ */ new Map();
      countFields = countColumns.map((col) => {
        const n = seen.get(col.name) ?? 0;
        seen.set(col.name, n + 1);
        const name = n === 0 ? col.name : `${col.name} ${n + 1}`;
        return {
          name,
          type: "number",
          values: col.values,
          config: col.config
        };
      });
    }
    return [
      createDataFrame({
        refId: frames[0]?.refId ?? "histogram",
        name: "histogram",
        meta: { preferredVisualisationType: "histogram" },
        fields: [
          { name: "BucketMin", type: "number", values: bucketMin, config: {} },
          { name: "BucketMax", type: "number", values: bucketMax, config: {} },
          ...countFields
        ]
      })
    ];
  });
  function fieldValuesAsStrings(field, values, emptyValue) {
    return values.map((v) => {
      if (v == null || v === "") return String(emptyValue ?? "");
      if (field.type === "enum") {
        const text = field.config?.type?.enum?.text;
        if (Array.isArray(text) && text[v] != null) {
          return String(text[v]);
        }
      }
      if (field.type === "time" || field.type === "number" || field.type === "boolean" || field.type === "string") {
        return String(v);
      }
      try {
        return JSON.stringify(v);
      } catch {
        return String(v);
      }
    });
  }
  function determineFieldType(types) {
    const unique = new Set(types);
    return unique.size === 1 ? [...unique][0] : "string";
  }
  registerTransformer("transpose", (frames, options = {}) => {
    const firstName = String(options.firstFieldName ?? "Field");
    const restName = String(options.restFieldsName ?? "Value");
    const emptyValue = getSpecialValue(
      options.emptyValue ?? SpecialValue.Empty
    );
    return frames.map((frame) => {
      if (!frame.fields.length) return frame;
      const firstField = frame.fields[0];
      const useFirstFieldAsHeaders = firstField.type === "string" || firstField.type === "time" || firstField.type === "enum" || // also treat "other" stringy as headers when name-like
      false;
      const headers = useFirstFieldAsHeaders ? [firstName, ...fieldValuesAsStrings(firstField, firstField.values, emptyValue)] : [firstName, ...firstField.values.map(() => restName)];
      const rows = useFirstFieldAsHeaders ? frame.fields.slice(1).map((f) => String(f.state?.displayName ?? f.config?.displayName ?? f.name)) : frame.fields.map((f) => String(f.state?.displayName ?? f.config?.displayName ?? f.name));
      const typeSource = useFirstFieldAsHeaders ? frame.fields.slice(1).map((f) => f.type) : frame.fields.map((f) => f.type);
      const fieldType = determineFieldType(typeSource);
      const newFields = headers.map((fieldName2, index2) => {
        if (index2 === 0) {
          return {
            name: firstName,
            type: "string",
            config: {},
            values: rows
          };
        }
        const values = frame.fields.map((field) => {
          const raw = field.values[index2 - 1];
          if (fieldType === "string") {
            return fieldValuesAsStrings(field, [raw], emptyValue)[0];
          }
          return raw;
        });
        const labelName = useFirstFieldAsHeaders ? firstField.name : "row";
        const labelValue = useFirstFieldAsHeaders ? fieldName2 : index2;
        return {
          name: useFirstFieldAsHeaders ? restName : String(fieldName2),
          labels: {
            [labelName]: String(labelValue)
          },
          type: fieldType,
          config: {},
          values: useFirstFieldAsHeaders ? values.slice(1) : values
        };
      });
      return createDataFrame({
        refId: frame.refId ? `transpose-${frame.refId}` : frame.refId,
        name: frame.name || "transposed",
        fields: newFields
      });
    });
  });
  registerTransformer("formatTime", (frames, options = {}) => {
    const fieldName2 = String(options.field ?? options.timeField ?? "");
    const outputFormat = String(options.outputFormat ?? options.format ?? "YYYY-MM-DD HH:mm:ss");
    const useTimezone = options.useTimezone !== false;
    const tz = String(options.timezone ?? options.timeZone ?? "browser");
    const utc = useTimezone && tz.toLowerCase() === "utc";
    return frames.map(
      (frame) => createDataFrame({
        refId: frame.refId,
        name: frame.name,
        fields: frame.fields.map((f) => {
          const hit = !fieldName2 && f.type === "time" || f.name === fieldName2 || getFieldDisplayName(f, frame, frames) === fieldName2;
          if (!hit) return f;
          return {
            ...f,
            type: "string",
            values: f.values.map((v) => {
              const d = new Date(Number(v));
              if (!Number.isFinite(d.getTime())) return String(v ?? "");
              if (outputFormat === "ms") return String(Number(v));
              if (outputFormat === "ISO" || outputFormat === "iso") return d.toISOString();
              return formatTimeToken(d, outputFormat, utc);
            })
          };
        })
      })
    );
  });
  function pathGet(obj, path) {
    if (obj == null || !path) return void 0;
    const parts = path.replaceAll(/\[(\d+)\]/g, ".$1").replaceAll(/\["([^"]+)"\]/g, ".$1").replaceAll(/\['([^']+)'\]/g, ".$1").split(".").filter(Boolean);
    let cur = obj;
    for (const p of parts) {
      if (cur == null) return void 0;
      cur = cur[p];
    }
    return cur;
  }
  function fieldTypeFromValues(values) {
    const sample = values.find((v) => v != null);
    if (typeof sample === "number") return "number";
    if (typeof sample === "boolean") return "boolean";
    if (sample instanceof Date) return "time";
    return "string";
  }
  function parseKvp(text, delimiter) {
    const o = {};
    const parts = text.split(new RegExp(`[${escapeReg(delimiter)}\\s]+`));
    for (const pair of parts) {
      if (!pair) continue;
      const eq = pair.indexOf("=");
      if (eq <= 0) continue;
      const k = pair.slice(0, eq);
      const v = pair.slice(eq + 1);
      if (k) o[k] = v;
    }
    return o;
  }
  function escapeReg(s) {
    return s.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&");
  }
  function parseRow(raw, format, options) {
    let obj = raw;
    if (typeof obj === "string") {
      try {
        if (format === "json" || format === "auto") {
          obj = JSON.parse(obj);
        } else if (format === "kvp" || format === "delimiter") {
          obj = parseKvp(obj, String(options.delimiter ?? ","));
        } else if (format === "regexp" || format === "regex") {
          const re = new RegExp(
            String(options.regExp ?? options.regexp ?? options.pattern ?? "(.*)")
          );
          const m = String(raw ?? "").match(re);
          const o = {};
          if (m) {
            if (m.groups) {
              for (const [k, v] of Object.entries(m.groups)) o[k] = v;
            } else {
              m.slice(1).forEach((v, i) => {
                o[`Match ${i + 1}`] = v;
              });
            }
          }
          obj = o;
        } else {
          obj = {};
        }
      } catch {
        obj = {};
      }
    }
    if (obj == null || typeof obj !== "object" || Array.isArray(obj)) {
      return {};
    }
    let rec = obj;
    if ((format === "json" || format === "auto") && Array.isArray(options.jsonPaths) && options.jsonPaths.length > 0) {
      const filtered = options.jsonPaths.filter(
        (p) => p && String(p.path ?? "").trim() !== ""
      );
      if (filtered.length) {
        const next = {};
        for (const p of filtered) {
          const path = String(p.path);
          const key = p.alias != null && String(p.alias).length > 0 ? String(p.alias) : path;
          const v = pathGet(rec, path);
          next[key] = v === void 0 ? "Not Found" : v;
        }
        rec = next;
      }
    }
    return rec;
  }
  registerTransformer("extractFields", (frames, options = {}) => {
    const opts = options;
    const source = String(opts.source ?? opts.field ?? "");
    let format = String(opts.format ?? "json");
    if (format === "auto") format = "json";
    const replace = opts.replaceFields === true || opts.replace === true;
    const keepTime = opts.keepTime === true;
    return frames.map((frame) => {
      const f = (source ? findFrameField(frame, source, frames) : void 0) ?? frame.fields.find((x) => x.type === "string");
      if (!f) return frame;
      const count = frame.length ?? f.values.length;
      const names = [];
      const buffers = /* @__PURE__ */ new Map();
      for (let i = 0; i < count; i++) {
        const rec = parseRow(f.values[i], format, opts);
        for (const [key, val] of Object.entries(rec)) {
          let buf = buffers.get(key);
          if (!buf) {
            buf = new Array(count).fill(void 0);
            buffers.set(key, buf);
            names.push(key);
          }
          buf[i] = val;
        }
      }
      let fields = names.map((name) => {
        const values = buffers.get(name) ?? [];
        return {
          name,
          type: fieldTypeFromValues(values),
          values,
          config: {}
        };
      });
      if (keepTime) {
        const sourceTime = frame.fields.find((x) => x.name === "Time") ?? frame.fields.find((x) => x.name === "time") ?? frame.fields.find((x) => x.type === "time");
        if (sourceTime) {
          fields = [
            {
              name: sourceTime.name,
              type: sourceTime.type,
              values: [...sourceTime.values],
              config: { ...sourceTime.config || {} }
            },
            ...fields
          ];
        }
      }
      if (!replace) {
        fields = [
          ...frame.fields.map((x) => ({
            name: x.name,
            type: x.type,
            values: [...x.values],
            config: { ...x.config || {} },
            labels: x.labels
          })),
          ...fields
        ];
      }
      return createDataFrame({
        refId: frame.refId,
        name: frame.name,
        fields
      });
    });
  });
  registerTransformer("prepareTimeSeries", (frames, options = {}) => {
    const format = String(options.format ?? "multi");
    if (format === "wide") {
      const by = frames[0]?.fields.find((f) => f.type === "time")?.name || frames[0]?.fields.find((f) => /time/i.test(f.name))?.name || "Time";
      if (frames.length <= 1) return frames;
      const join = (framesIn, byField) => {
        const keyValues = [];
        const index2 = /* @__PURE__ */ new Map();
        for (const frame of framesIn) {
          const keyField = findFrameField(frame, byField, framesIn) ?? frame.fields.find((f) => f.type === "time");
          if (!keyField) continue;
          for (const v of keyField.values) {
            const k = String(v);
            if (!index2.has(k)) {
              index2.set(k, keyValues.length);
              keyValues.push(k);
            }
          }
        }
        const outFields = [
          {
            name: byField,
            type: findFrameField(framesIn[0], byField, framesIn)?.type ?? framesIn[0].fields.find((f) => f.type === "time")?.type ?? "time",
            values: keyValues.map((k) => Number.isFinite(Number(k)) ? Number(k) : k),
            config: {}
          }
        ];
        for (const frame of framesIn) {
          const keyField = findFrameField(frame, byField, framesIn) ?? frame.fields.find((f) => f.type === "time");
          if (!keyField) continue;
          const local = new Map(keyField.values.map((v, i) => [String(v), i]));
          for (const field of frame.fields.filter((f) => f !== keyField)) {
            outFields.push({
              name: frame.refId ? `${field.name} ${frame.refId}` : field.name,
              type: field.type,
              values: keyValues.map((k) => {
                const i = local.get(k);
                return i == null ? null : field.values[i];
              }),
              config: field.config ?? {},
              labels: field.labels
            });
          }
        }
        return [
          createDataFrame({
            name: "wide",
            refId: framesIn[0]?.refId,
            fields: outFields
          })
        ];
      };
      return join(frames, by);
    }
    if (format === "long") {
      const metric = [];
      const values = [];
      const times = [];
      for (const frame of frames) {
        const time = frame.fields.find((f) => f.type === "time");
        for (const field of frame.fields.filter((f) => f.type === "number")) {
          for (let i = 0; i < field.values.length; i++) {
            metric.push(getFieldDisplayName(field, frame, frames));
            values.push(Number(field.values[i] ?? 0));
            times.push(Number(time?.values[i] ?? i));
          }
        }
      }
      return [
        createDataFrame({
          name: "long",
          fields: [
            { name: "Time", type: "time", values: times },
            { name: "Metric", type: "string", values: metric },
            { name: "Value", type: "number", values }
          ]
        })
      ];
    }
    if (format === "multi") {
      const out = [];
      for (const frame of frames) {
        const time = frame.fields.find((f) => f.type === "time");
        const nums = frame.fields.filter((f) => f.type === "number");
        if (!time || nums.length <= 1) {
          out.push(frame);
          continue;
        }
        for (const num of nums) {
          out.push(
            createDataFrame({
              refId: frame.refId,
              name: getFieldDisplayName(num, frame, frames),
              fields: [
                { name: time.name, type: "time", values: [...time.values] },
                { ...num, values: [...num.values] }
              ]
            })
          );
        }
      }
      return out.length ? out : frames;
    }
    return frames;
  });
  const collator = new Intl.Collator(void 0, {
    sensitivity: "base",
    numeric: true
  });
  function orderAuto(frame, orderBy) {
    const fields = frame.fields;
    const firstTime = fields.find((f) => f.type === "time");
    return fields.slice().sort((fieldA, fieldB) => {
      if (fieldA === firstTime) return -1;
      if (fieldB === firstTime) return 1;
      for (const item of orderBy) {
        const type = String(item?.type ?? "name");
        const desc = !!item?.desc;
        const labelKey = String(item?.name ?? "");
        const aVal = type === "label" ? String(fieldA.labels?.[labelKey] ?? "") : getFieldDisplayName(fieldA, frame);
        const bVal = type === "label" ? String(fieldB.labels?.[labelKey] ?? "") : getFieldDisplayName(fieldB, frame);
        const res = collator.compare(aVal, bVal) * (desc ? -1 : 1);
        if (res !== 0) return res;
      }
      return 0;
    });
  }
  function orderManual(frame, indexByName) {
    const names = Object.entries(indexByName).sort((a, b) => Number(a[1]) - Number(b[1])).map(([n]) => n);
    if (!names.length) return frame.fields;
    const ordered = [];
    const used = /* @__PURE__ */ new Set();
    for (const n of names) {
      const f = frame.fields.find((x) => x.name === n) ?? frame.fields.find((x) => getFieldDisplayName(x, frame) === n);
      if (f && !used.has(f.name)) {
        ordered.push(f);
        used.add(f.name);
      }
    }
    const rest = frame.fields.filter((f) => !used.has(f.name));
    return [...ordered, ...rest];
  }
  registerTransformer("order", (frames, options = {}) => {
    const mode = String(options.orderByMode ?? "manual").toLowerCase();
    const orderBy = options.orderBy;
    if (mode === "auto" && Array.isArray(orderBy) && orderBy.length) {
      return frames.map(
        (frame) => createDataFrame({
          refId: frame.refId,
          name: frame.name,
          fields: orderAuto(frame, orderBy)
        })
      );
    }
    const indexByName = options.indexByName ?? options.orderByNames ?? {};
    if (!indexByName || !Object.keys(indexByName).length) return frames;
    return frames.map(
      (frame) => createDataFrame({
        refId: frame.refId,
        name: frame.name,
        fields: orderManual(frame, indexByName)
      })
    );
  });
  registerTransformer("rename", (frames, options = {}) => {
    const renameByName = options.renameByName ?? options;
    if (!renameByName || typeof renameByName !== "object") return frames;
    if (!Object.keys(renameByName).length) return frames;
    return frames.map(
      (frame) => createDataFrame({
        refId: frame.refId,
        name: frame.name,
        fields: frame.fields.map((f) => {
          const displayName = getFieldDisplayName(f, frame, frames);
          const raw = renameByName[displayName] ?? renameByName[f.name];
          if (typeof raw !== "string" || raw.length === 0) return f;
          return {
            ...f,
            config: {
              ...f.config || {},
              displayName: raw
            },
            state: {
              ...f.state || {},
              displayName: raw
            }
          };
        })
      })
    );
  });
  registerTransformer("noop", (frames) => frames);
  function buildFrameName(opts, names, values) {
    const sep1 = opts.separator1 ?? "=";
    const sep2 = opts.separator2 ?? " ";
    return names.map((name, i) => opts.withNames ? `${name}${sep1}${values[i]}` : String(values[i])).join(sep2);
  }
  function buildFieldLabels(names, values) {
    const labels = {};
    names.forEach((name, i) => {
      labels[name] = String(values[i]);
    });
    return labels;
  }
  registerTransformer("partitionByValues", (frames, options = {}) => {
    const fields = options.fields ?? (options.field ? [String(options.field)] : []);
    const keepFields = options.keepFields === true;
    const naming = {
      asLabels: true,
      append: false,
      withNames: false,
      separator1: "=",
      separator2: " ",
      ...options.naming ?? {}
    };
    if (!fields.length) return frames;
    const out = [];
    for (const frame of frames) {
      const keyFields = fields.map((n) => findFrameField(frame, n, frames)).filter(Boolean);
      if (!keyFields.length) {
        out.push(frame);
        continue;
      }
      const names = fields.map((n) => findFrameField(frame, n, frames) && n).filter(Boolean);
      const labelNames = names.length === keyFields.length ? names : keyFields.map((f) => f.name);
      const groups = /* @__PURE__ */ new Map();
      const len = frame.length || frame.fields[0]?.values.length || 0;
      for (let i = 0; i < len; i++) {
        const key = keyFields.map((f) => String(f.values[i] ?? "")).join("|");
        if (!groups.has(key)) groups.set(key, []);
        groups.get(key).push(i);
      }
      for (const [, idxs] of groups) {
        const keyValues = keyFields.map((f) => f.values[idxs[0]]);
        let frameName = frame.name;
        let fieldLabels = {};
        if (naming.asLabels !== false) {
          fieldLabels = buildFieldLabels(labelNames, keyValues);
        } else {
          let name = buildFrameName(naming, labelNames, keyValues);
          if (naming.append && frame.name) name = `${frame.name} ${name}`;
          frameName = name;
        }
        const selected = keepFields ? frame.fields : frame.fields.filter((f) => !fields.some((n) => fieldMatchesName(f, n, frame, frames)));
        out.push(
          createDataFrame({
            refId: frame.refId ? `${frame.refId}-${frameName ?? keyValues.join("|")}` : frame.refId,
            name: frameName,
            fields: selected.map((f) => ({
              ...f,
              labels: { ...f.labels ?? {}, ...fieldLabels },
              values: idxs.map((i) => f.values[i])
            }))
          })
        );
      }
    }
    return out;
  });
  registerTransformer("rowsToFields", (frames, options = {}) => {
    const nameField = String(options.nameField ?? options.fieldName ?? "name");
    const valueField = String(options.valueField ?? "value");
    const mappings = options.mappings ?? [];
    return frames.map((frame) => {
      const nf = findFrameField(frame, nameField, frames);
      const vf = findFrameField(frame, valueField, frames) ?? frame.fields.find((f) => f.type === "number");
      if (!nf || !vf) return frame;
      const fields = nf.values.map((name, i) => {
        const config = {};
        for (const m of mappings) {
          if (!m?.fieldName || !m?.handlerKey) continue;
          const src = findFrameField(frame, m.fieldName, frames);
          if (!src) continue;
          const key = String(m.handlerKey);
          const raw = src.values[i];
          if (key === "min" || key === "max" || key === "decimals") config[key] = Number(raw);
          else config[key] = raw;
        }
        return {
          name: String(name),
          type: typeof vf.values[i] === "number" ? "number" : "string",
          values: [vf.values[i]],
          config
        };
      });
      return createDataFrame({ refId: frame.refId, name: frame.name, fields });
    });
  });
  registerTransformer("ensureColumns", (frames) => {
    if (frames.length > 1) {
      const hasTime = frames.every((f) => f.fields.some((x) => x.type === "time"));
      if (hasTime) {
        const by = frames[0].fields.find((f) => f.type === "time").name;
        const keyValues = [];
        const index2 = /* @__PURE__ */ new Map();
        for (const frame of frames) {
          const keyField = findFrameField(frame, by, frames) ?? frame.fields.find((f) => f.type === "time");
          if (!keyField) continue;
          for (const v of keyField.values) {
            const k = String(v);
            if (!index2.has(k)) {
              index2.set(k, keyValues.length);
              keyValues.push(k);
            }
          }
        }
        const outFields = [
          {
            name: by,
            type: "time",
            values: keyValues.map(Number),
            config: {}
          }
        ];
        for (const frame of frames) {
          const keyField = findFrameField(frame, by, frames) ?? frame.fields.find((f) => f.type === "time");
          if (!keyField) continue;
          const local = new Map(keyField.values.map((v, i) => [String(v), i]));
          for (const field of frame.fields.filter((f) => f.type !== "time")) {
            outFields.push({
              name: field.name,
              type: field.type,
              values: keyValues.map((k) => {
                const i = local.get(k);
                return i == null ? null : field.values[i];
              }),
              config: field.config ?? {},
              labels: field.labels
            });
          }
        }
        return [
          createDataFrame({
            name: "columns",
            refId: frames[0]?.refId,
            fields: outFields
          })
        ];
      }
    }
    return frames.map((frame) => {
      const time = frame.fields.filter((f) => f.type === "time");
      const rest = frame.fields.filter((f) => f.type !== "time");
      return createDataFrame({
        refId: frame.refId,
        name: frame.name,
        fields: [...time, ...rest]
      });
    });
  });
  registerTransformer("convertFrameType", (frames, options = {}) => {
    const target = String(options.targetType ?? options.type ?? options.visualizationType ?? "");
    if (!target) return frames;
    return frames.map(
      (frame) => createDataFrame({
        refId: frame.refId,
        name: frame.name,
        fields: frame.fields.map((f) => ({
          ...f,
          values: [...f.values],
          config: { ...f.config || {} }
        })),
        meta: {
          ...frame.meta || {},
          preferredVisualisationType: target,
          convertedFrameType: target
        }
      })
    );
  });
  registerTransformer("filterFields", getTransformer("filterByName"));
  const impl = getTransformer("filterByName");
  if (!impl) {
    throw new Error("filterFieldsByName requires filterByName to be registered first");
  }
  registerTransformer("filterFieldsByName", impl);
  registerTransformer("filterFrames", (frames, options = {}) => {
    const include = options.include;
    const names = options.names ?? (include && typeof include === "object" ? include.names : void 0);
    const pattern = String(
      options.pattern ?? (include && typeof include === "object" ? include.pattern : "") ?? (typeof include === "string" ? include : "")
    );
    if (names?.length) {
      const set = new Set(names);
      return frames.filter((f) => set.has(String(f.refId)) || set.has(String(f.name)));
    }
    if (pattern) {
      try {
        const re = new RegExp(pattern);
        const filtered = frames.filter(
          (f) => re.test(String(f.refId ?? "")) || re.test(String(f.name ?? ""))
        );
        if (filtered.length) return filtered;
      } catch {
      }
    }
    const refIdsRaw = options.refIds ?? (typeof include === "string" && !include.includes("*") && !include.includes(".") ? include : "");
    const refIds = refIdsRaw != null && refIdsRaw !== "" ? String(refIdsRaw) : "";
    if (refIds) {
      const set = new Set(
        refIds.split(/[|,]/).map((s) => s.trim()).filter(Boolean)
      );
      return frames.filter((f) => set.has(String(f.refId)));
    }
    return frames;
  });
  registerTransformer("seriesToColumns", getTransformer("joinByField"));
  registerTransformer("append", getTransformer("concatenate"));
  function distinctLabels(data) {
    const s = /* @__PURE__ */ new Set();
    for (const frame of data) {
      for (const f of frame.fields) {
        for (const k of Object.keys(f.labels ?? {})) s.add(k);
      }
    }
    return s;
  }
  function errorFrame(text) {
    return createDataFrame({
      meta: { notices: [{ severity: "error", text }] },
      fields: [{ name: "Error", type: "string", values: [text], config: {} }]
    });
  }
  function joinByLabelsGrafana(options, data) {
    const valueLabel = options.value;
    const labels = distinctLabels(data);
    if (labels.size < 1) return errorFrame("No labels in result");
    if (!labels.has(valueLabel)) return errorFrame("Value label not found");
    let join = options.join?.length ? [...options.join] : [...labels];
    join = join.filter((f) => f !== valueLabel);
    const names = /* @__PURE__ */ new Set();
    const found = /* @__PURE__ */ new Map();
    const inputFields = {};
    for (const frame of data) {
      for (const field of frame.fields) {
        if (!field.labels || field.type === "time") continue;
        const keys = join.map((v) => String(field.labels[v] ?? ""));
        const key = keys.join(",");
        let item = found.get(key);
        if (!item) {
          item = { keys, values: {} };
          found.set(key, item);
        }
        const name = String(field.labels[valueLabel] ?? "");
        const vals = [...field.values];
        const old = item.values[name];
        item.values[name] = old ? old.concat(vals) : vals;
        if (!inputFields[name]) inputFields[name] = field;
        names.add(name);
      }
    }
    const allNames = [...names];
    const joinValues = join.map(() => []);
    const nameValues = allNames.map(() => []);
    for (const item of found.values()) {
      let valueOffset = -1;
      let done = false;
      while (!done) {
        valueOffset++;
        done = true;
        for (let i = 0; i < join.length; i++) {
          joinValues[i].push(item.keys[i]);
        }
        for (const [i, name] of allNames.entries()) {
          const values = item.values[name] ?? [];
          nameValues[i].push(values[valueOffset]);
          if (values.length > valueOffset + 1) done = false;
        }
      }
    }
    const fields = [];
    for (const [i, element] of join.entries()) {
      fields.push({
        name: element,
        config: {},
        type: "string",
        values: joinValues[i]
      });
    }
    for (const [i, allName] of allNames.entries()) {
      const old = inputFields[allName];
      fields.push({
        name: allName,
        config: {},
        type: old?.type ?? "number",
        values: nameValues[i]
      });
    }
    return createDataFrame({
      refId: `joinByLabels-${data.map((f) => f.refId ?? "").join("-")}`,
      fields
    });
  }
  function joinByLabelsLegacy(frames, valueFieldName, joinKeys) {
    const rows = [];
    const allLabelKeys = /* @__PURE__ */ new Set();
    for (const frame of frames) {
      for (const f of frame.fields) {
        if (f.type === "time") continue;
        if (!(f.type === "number" || fieldMatchesName(f, valueFieldName, frame, frames))) continue;
        if (!f.labels || !Object.keys(f.labels).length) continue;
        for (const k of Object.keys(f.labels)) allLabelKeys.add(k);
        const keys = joinKeys.length ? joinKeys.map((k) => String(f.labels[k] ?? "")) : [...Object.keys(f.labels)].sort().map((k) => String(f.labels[k] ?? ""));
        const colName = f.labels.__name__ || f.config?.displayName || f.state?.displayName || f.name || frame.refId || "Value";
        rows.push({
          keys,
          colName: String(colName),
          value: f.values[f.values.length - 1],
          type: f.type
        });
      }
    }
    if (!rows.length) return frames;
    const effectiveJoin = joinKeys.length > 0 ? joinKeys : [...allLabelKeys].sort();
    const groups = /* @__PURE__ */ new Map();
    const colNames = /* @__PURE__ */ new Set();
    for (const r of rows) {
      const key = r.keys.join("");
      let g = groups.get(key);
      if (!g) {
        g = { keys: r.keys, cols: {} };
        groups.set(key, g);
      }
      let name = r.colName;
      if (name in g.cols && g.cols[name] !== r.value) {
        name = `${name}_${Object.keys(g.cols).length}`;
      }
      g.cols[name] = r.value;
      colNames.add(name);
    }
    const groupList = [...groups.values()];
    const fields = effectiveJoin.map((name, i) => ({
      name,
      type: "string",
      values: groupList.map((g) => g.keys[i] ?? ""),
      config: {}
    }));
    for (const col of colNames) {
      fields.push({
        name: col,
        type: "number",
        values: groupList.map((g) => g.cols[col] ?? null),
        config: {}
      });
    }
    return [createDataFrame({ name: "joinByLabels", fields })];
  }
  registerTransformer("joinByLabels", (frames, options = {}) => {
    if (!frames?.length) return frames;
    const value = String(options.value ?? options.valueField ?? "Value");
    if (!value) {
      return [errorFrame("No value label configured")];
    }
    const joinRaw = options.join ?? options.by ?? options.byField;
    const joinArr = Array.isArray(joinRaw) ? joinRaw.map(String) : joinRaw != null && String(joinRaw) !== "" ? [String(joinRaw)] : [];
    const labels = distinctLabels(frames);
    if (labels.has(value)) {
      return [joinByLabelsGrafana({ value, join: joinArr }, frames)];
    }
    return joinByLabelsLegacy(frames, value, joinArr);
  });
  function compareFieldValues(left, op, right) {
    const o = String(op).toLowerCase();
    const lv = left;
    const rv = right;
    switch (o) {
      case "eq":
      case "==":
        return lv == rv;
      case "neq":
      case "!=":
        return lv != rv;
      case "gt":
      case ">":
        return Number(lv) > Number(rv);
      case "gte":
      case ">=":
        return Number(lv) >= Number(rv);
      case "lt":
      case "<":
        return Number(lv) < Number(rv);
      case "lte":
      case "<=":
        return Number(lv) <= Number(rv);
      default:
        return lv == rv;
    }
  }
  function asNames(options) {
    if (Array.isArray(options)) return options.map(String);
    if (options && typeof options === "object" && Array.isArray(options.names)) {
      return options.names.map(String);
    }
    return String(options?.names ?? options ?? "").split(",").map((s) => s.trim()).filter(Boolean);
  }
  function fieldNameFallback(names) {
    let fallback;
    if (names.has("Value")) {
      fallback = (field) => Boolean(field.labels) && field.labels?.__name__ === field.name;
    } else if (names.has("Time") || names.has("time")) {
      fallback = (field, frame) => frame?.meta?.typeVersion == null && field.type === "time";
    }
    return fallback;
  }
  function matchesNameOrDisplay(field, name, frame, allFrames) {
    if (!name) return false;
    if (field.name === name) return true;
    return getFieldDisplayName(field, frame, allFrames) === name;
  }
  const MATCHERS = [
    {
      id: "byName",
      name: "字段名称为",
      pickerDefault: true,
      // Grafana: raw name OR getFieldDisplayName (+ Value/Time fallback)
      get: (options) => {
        const name = String(options ?? "");
        const fallback = fieldNameFallback(/* @__PURE__ */ new Set([name]));
        return (field, frame, allFrames) => matchesNameOrDisplay(field, name, frame, allFrames) || Boolean(fallback && fallback(field, frame, allFrames));
      }
    },
    {
      id: "byNames",
      name: "字段名称为（列表）",
      pickerDefault: true,
      get: (options) => {
        const names = asNames(options);
        const unique = new Set(names);
        const fallback = fieldNameFallback(unique);
        const mode = typeof options === "object" && options && !Array.isArray(options) ? options.mode || "include" : "include";
        const matcher = (field, frame, allFrames) => names.some((n) => matchesNameOrDisplay(field, n, frame, allFrames)) || Boolean(fallback && fallback(field, frame, allFrames));
        if (mode === "exclude") {
          return (field, frame, allFrames) => !matcher(field, frame, allFrames);
        }
        return matcher;
      }
    },
    {
      id: "byRegexp",
      name: "字段名匹配正则",
      pickerDefault: true,
      get: (options) => {
        const re = stringToJsRegexSafe(options);
        return (field, frame, allFrames) => {
          if (!re) return false;
          const displayName = getFieldDisplayName(field, frame, allFrames);
          return re.test(displayName) || re.test(field.name);
        };
      }
    },
    {
      id: "byRegexpOrNames",
      name: "字段名匹配正则或列表",
      pickerDefault: false,
      get: (options) => {
        const opts = options;
        const pattern = typeof opts === "string" ? opts : opts?.pattern ?? "";
        const names = typeof opts === "object" && opts ? asNames(opts) : [];
        const re = stringToJsRegexSafe(pattern);
        return (field, frame, allFrames) => {
          if (names.some((n) => matchesNameOrDisplay(field, n, frame, allFrames))) {
            return true;
          }
          if (!re) return false;
          const displayName = getFieldDisplayName(field, frame, allFrames);
          return re.test(displayName) || re.test(field.name);
        };
      }
    },
    {
      id: "byType",
      name: "字段类型为",
      pickerDefault: true,
      get: (options) => (field) => field.type === options
    },
    {
      id: "byTypes",
      name: "字段类型为（列表）",
      pickerDefault: false,
      get: (options) => {
        const types = Array.isArray(options) ? options.map(String) : String(options ?? "").split(",").map((s) => s.trim()).filter(Boolean);
        return (field) => types.includes(String(field.type));
      }
    },
    {
      id: "byFrameRefID",
      name: "查询返回的字段",
      pickerDefault: true,
      get: (options) => (_field, frame) => (frame?.refId ?? "") === String(options ?? "")
    },
    {
      id: "byValue",
      name: "值为（reducer）",
      description: "将字段 reduce 为单值后与阈值比较（对齐 Grafana fieldValueMatcher）",
      pickerDefault: true,
      get: (options) => {
        const props = options ?? {};
        if (options != null && (typeof options === "number" || typeof options === "string")) {
          const target = options;
          return (field) => field.values.some((v) => {
            if (typeof target === "number") return Number(v) === target;
            return String(v) === String(target);
          });
        }
        const reducer = props.reducer;
        if (!reducer) return () => false;
        const op = props.op || "eq";
        const isBoolean = reducer === ReducerID.allIsNull || reducer === ReducerID.allIsZero || reducer === "allIsNull" || reducer === "allIsZero";
        return (field) => {
          const reduced = reduceField$1(field, [reducer]);
          const left = reduced[reducer];
          if (isBoolean) return Boolean(left);
          return compareFieldValues(left, op, props.value);
        };
      }
    },
    {
      id: "numeric",
      name: "数值字段",
      pickerDefault: false,
      get: () => (field) => field.type === "number"
    },
    {
      id: "time",
      name: "时间字段",
      pickerDefault: false,
      get: () => (field) => field.type === "time"
    },
    {
      id: "first",
      name: "第一个字段",
      pickerDefault: false,
      get: () => (field, frame) => !!frame && frame.fields[0] === field
    },
    {
      id: "firstTimeField",
      name: "第一个时间字段",
      pickerDefault: false,
      get: () => (field, frame) => {
        if (!frame) return field.type === "time";
        const first = frame.fields.find((f) => f.type === "time");
        return first === field;
      }
    }
  ];
  const byId = new Map(MATCHERS.map((m) => [m.id, m]));
  function getFieldMatcher(config) {
    const info = byId.get(config.id);
    if (!info) {
      return () => false;
    }
    return info.get(config.options);
  }
  function isFieldsMap(raw) {
    return !!raw && typeof raw === "object" && !Array.isArray(raw);
  }
  function isV1Options(opts) {
    return "fields" in opts && !("rules" in opts);
  }
  function migrateV1ToRules(fields) {
    return Object.entries(fields).map(([fieldName2, fieldOpts]) => ({
      matcher: { id: "byName", options: fieldName2 },
      operation: fieldOpts?.operation ?? null,
      aggregations: Array.isArray(fieldOpts?.aggregations) ? fieldOpts.aggregations.map(String) : [],
      keepNestedField: fieldOpts?.keepNestedField === true
    }));
  }
  function resolveRules(options) {
    if (Array.isArray(options.rules)) {
      return options.rules.filter((r) => r && typeof r === "object" && r.matcher).map((r) => ({
        matcher: r.matcher,
        operation: r.operation ?? null,
        aggregations: Array.isArray(r.aggregations) ? r.aggregations.map(String) : [],
        keepNestedField: r.keepNestedField === true
      }));
    }
    const raw = options.fields;
    if (isFieldsMap(raw) && isV1Options(options)) {
      return migrateV1ToRules(raw);
    }
    if (isFieldsMap(raw)) {
      return migrateV1ToRules(raw);
    }
    if (Array.isArray(raw)) {
      return raw.map((f) => {
        const name = String(f?.fieldName ?? f?.name ?? f ?? "");
        if (!name) return null;
        return {
          matcher: { id: "byName", options: name },
          operation: f?.operation ?? "groupby",
          aggregations: Array.isArray(f?.aggregations) ? f.aggregations.map(String) : [],
          keepNestedField: f?.keepNestedField === true
        };
      }).filter((r) => !!r);
    }
    if (Array.isArray(options.groupBy)) {
      return options.groupBy.map((name) => ({
        matcher: { id: "byName", options: String(name) },
        operation: "groupby",
        aggregations: []
      }));
    }
    if (options.groupByField) {
      return [
        {
          matcher: { id: "byName", options: String(options.groupByField) },
          operation: "groupby",
          aggregations: []
        }
      ];
    }
    return [];
  }
  function findMatchingRule(field, frame, allFrames, rules) {
    for (const rule of rules) {
      const matcher = getFieldMatcher(rule.matcher);
      if (matcher(field, frame, allFrames)) {
        return rule;
      }
    }
    return void 0;
  }
  function shouldGroupOn(field, frame, allFrames, rules) {
    return findMatchingRule(field, frame, allFrames, rules)?.operation === "groupby";
  }
  function shouldAggregate(field, frame, allFrames, rules) {
    const rule = findMatchingRule(field, frame, allFrames, rules);
    return rule?.operation === "aggregate" && Array.isArray(rule.aggregations) && rule.aggregations.length > 0;
  }
  function calcValue(field, agg) {
    const calcs = reduceField$1(field, [agg]);
    const v = calcs[agg];
    if (typeof v === "number") return v;
    if (v == null || typeof v === "boolean") return null;
    if (Array.isArray(v)) return v.length;
    const n = Number(v);
    return Number.isFinite(n) ? n : null;
  }
  function groupToNestedFrame(frame, allFrames, rules, options) {
    const groupByFields = frame.fields.filter((f) => shouldGroupOn(f, frame, allFrames, rules));
    if (!groupByFields.length) {
      return frame;
    }
    const buckets = /* @__PURE__ */ new Map();
    const n = frame.length ?? groupByFields[0].values.length;
    for (let i = 0; i < n; i++) {
      const keys = groupByFields.map((f) => f.values[i]);
      const key = keys.map((v) => String(v)).join("");
      let bucket = buckets.get(key);
      if (!bucket) {
        bucket = { keys, idxs: [] };
        buckets.set(key, bucket);
      }
      bucket.idxs.push(i);
    }
    const groupEntries = [...buckets.entries()];
    const parentFields = groupByFields.map((f, gi) => ({
      name: f.name,
      type: f.type,
      values: groupEntries.map(([, b]) => b.keys[gi]),
      config: { ...f.config || {} }
    }));
    for (const field of frame.fields) {
      if (!shouldAggregate(field, frame, allFrames, rules)) continue;
      const rule = findMatchingRule(field, frame, allFrames, rules);
      const fieldName2 = getFieldDisplayName(field, frame, allFrames);
      for (const agg of rule.aggregations) {
        const values = groupEntries.map(([, b]) => {
          const fake = {
            name: field.name,
            type: field.type,
            config: field.config ?? {},
            values: b.idxs.map((i) => field.values[i])
          };
          return calcValue(fake, agg);
        });
        parentFields.push({
          name: `${fieldName2} (${agg})`,
          type: "number",
          values,
          config: {}
        });
      }
    }
    const expandAllRows = options.expandAllRows === true;
    const showSubframeHeaders = options.showSubframeHeaders !== false;
    const nestedValues = groupEntries.map(([k, b]) => {
      const nestedFields = [];
      for (const field of frame.fields) {
        const rule = findMatchingRule(field, frame, allFrames, rules);
        let include = false;
        if (rule === void 0) {
          include = true;
        } else if (rule.operation == null || rule.operation === "aggregate" && rule.aggregations.length === 0) {
          include = true;
        } else if (rule.operation === "aggregate" && rule.keepNestedField === true) {
          include = true;
        } else if (rule.operation === "groupby") {
          include = false;
        } else if (rule.operation === "aggregate") {
          include = false;
        } else {
          include = true;
        }
        if (!include) continue;
        nestedFields.push({
          name: field.name,
          type: field.type,
          values: b.idxs.map((i) => field.values[i]),
          config: { ...field.config || {} },
          labels: field.labels
        });
      }
      const sub = createDataFrame({
        name: k.replaceAll("", " / "),
        fields: nestedFields,
        meta: {
          custom: {
            noHeader: !showSubframeHeaders,
            stableRowKey: k
          }
        }
      });
      return [sub];
    });
    return createDataFrame({
      refId: frame.refId,
      name: frame.name || "nested",
      meta: {
        preferredVisualisationType: "table",
        nested: true,
        custom: {
          ...expandAllRows ? { expandAllRows: true } : {},
          showSubframeHeaders
        }
      },
      fields: [
        ...parentFields,
        {
          // Grafana FieldType.nestedFrames + __nestedFrames name — table ExpandedRow consumer
          name: "__nestedFrames",
          type: "nestedFrames",
          values: nestedValues,
          config: { custom: { nested: true } }
        }
      ]
    });
  }
  registerTransformer("groupToNestedTable", (frames, options = {}) => {
    const opts = options;
    let rules = resolveRules(opts);
    if (!rules.some((r) => r.operation === "groupby")) {
      const auto = frames[0]?.fields.filter((f) => f.type === "string" || f.type === "other").slice(0, 1).map((f) => f.name) ?? [];
      if (auto.length) {
        rules = [
          ...rules,
          {
            matcher: { id: "byName", options: auto[0] },
            operation: "groupby",
            aggregations: []
          }
        ];
      }
    }
    if (!rules.some((r) => r.operation === "groupby")) {
      const gb = getTransformer("groupBy");
      return gb ? gb(frames, options) : frames;
    }
    return frames.map((frame) => groupToNestedFrame(frame, frames, rules, opts));
  });
  function reduceValues(values, reducerId) {
    const nums = values.map(Number).filter((n) => Number.isFinite(n));
    const r = String(reducerId || "lastNotNull");
    if (r === "min") return nums.length ? Math.min(...nums) : null;
    if (r === "max") return nums.length ? Math.max(...nums) : null;
    if (r === "mean") return nums.length ? nums.reduce((a, b) => a + b, 0) / nums.length : null;
    if (r === "sum") return nums.length ? nums.reduce((a, b) => a + b, 0) : null;
    if (r === "first" || r === "firstNotNull") return values.find((v) => v != null) ?? null;
    for (let i = values.length - 1; i >= 0; i--) {
      if (values[i] != null && values[i] !== "") return values[i];
    }
    return null;
  }
  function resolveApplyMatcher(applyTo) {
    if (applyTo == null || applyTo === "" || applyTo === "field") {
      return getFieldMatcher({ id: "numeric" });
    }
    if (applyTo === "frame") {
      return (f) => f.type !== "time";
    }
    if (typeof applyTo === "string") {
      return getFieldMatcher({ id: "byName", options: applyTo });
    }
    if (typeof applyTo === "object" && applyTo && applyTo.id) {
      return getFieldMatcher(applyTo);
    }
    return getFieldMatcher({ id: "numeric" });
  }
  function buildConfigPatch(reduced, fieldName2) {
    const cfg = {};
    if (reduced.min != null) cfg.min = Number(reduced.min);
    if (reduced.max != null) cfg.max = Number(reduced.max);
    if (reduced.unit != null) cfg.unit = String(reduced.unit);
    if (reduced.decimals != null) cfg.decimals = Number(reduced.decimals);
    if (reduced.displayname != null) cfg.displayName = String(reduced.displayname);
    for (const key of ["thresholds", "mappings", "color", "noValue", "filterable"]) {
      if (reduced[key] != null) cfg[key] = reduced[key];
      if (reduced[key.toLowerCase()] != null) cfg[key] = reduced[key.toLowerCase()];
    }
    for (const [k, v] of Object.entries(reduced)) {
      if (k.startsWith(`${fieldName2}.`)) {
        cfg[k.slice(fieldName2.length + 1)] = v;
      }
    }
    return cfg;
  }
  registerTransformer("configFromData", (frames, options = {}) => {
    if (!frames.length) return frames;
    const configRefId = options.configRefId != null ? String(options.configRefId) : "config";
    let configFrame = frames.find((f) => f.refId === configRefId) ?? (options.configFrameIndex != null ? frames[Number(options.configFrameIndex)] : void 0);
    if (!configFrame && frames.length > 1 && options.configRefId == null) {
      configFrame = frames[frames.length - 1];
    }
    if (!configFrame) return frames;
    const mappings = options.mappings ?? [];
    const mappingByField = /* @__PURE__ */ new Map();
    for (const m of mappings) {
      if (m?.fieldName) mappingByField.set(String(m.fieldName), m);
    }
    const reduced = {};
    for (const field of configFrame.fields) {
      const display = getFieldDisplayName(field, configFrame, frames);
      const m = mappingByField.get(field.name) ?? mappingByField.get(display) ?? void 0;
      const handlerKey = String(m?.handlerKey ?? field.name.toLowerCase()).toLowerCase();
      if (handlerKey === "null" || m?.handlerKey === null) continue;
      const reducer = m?.reducerId ?? "lastNotNull";
      reduced[handlerKey] = reduceValues(field.values, reducer);
      reduced[field.name.toLowerCase()] = reduced[handlerKey];
      reduced[field.name] = reduced[handlerKey];
      if (display && display !== field.name) {
        reduced[display] = reduced[handlerKey];
        reduced[display.toLowerCase()] = reduced[handlerKey];
      }
    }
    if (!mappings.length) {
      const nameF = configFrame.fields.find((f) => /name|field|key/i.test(f.name));
      const valF = configFrame.fields.find(
        (f) => f !== nameF && (f.type === "number" || f.type === "string")
      );
      if (nameF && valF) {
        nameF.values.forEach((n, i) => {
          reduced[String(n)] = valF.values[i];
          reduced[String(n).toLowerCase()] = valF.values[i];
        });
      } else {
        for (const f of configFrame.fields) {
          reduced[f.name] = f.values[0];
          reduced[f.name.toLowerCase()] = f.values[0];
        }
      }
    }
    const matcher = resolveApplyMatcher(options.applyTo);
    const dataFrames = frames.filter((f) => f !== configFrame || frames.length === 1);
    const out = dataFrames.map(
      (frame) => createDataFrame({
        refId: frame.refId,
        name: frame.name,
        meta: frame.meta,
        fields: frame.fields.map((f) => {
          if (!matcher(f, frame, frames)) return f;
          const display = getFieldDisplayName(f, frame, frames);
          const patch = {
            ...buildConfigPatch(reduced, f.name),
            ...display !== f.name ? buildConfigPatch(reduced, display) : {}
          };
          if (!Object.keys(patch).length) return f;
          return {
            ...f,
            config: {
              ...f.config || {},
              ...patch
            }
          };
        })
      })
    );
    return out.length ? out : frames;
  });
  registerTransformer("fieldLookup", (frames, options = {}) => {
    const lookupField = String(options.lookupField ?? options.field ?? "");
    const gazetteer = String(options.gazetteer ?? "countries");
    if (frames.length >= 2 && options.fromField) {
      const fromField = String(options.fromField);
      const lookup = frames[1];
      const key = findFrameField(lookup, lookupField, frames);
      const val = findFrameField(lookup, fromField, frames) ?? lookup.fields.find((f) => f !== key);
      if (!key || !val) return frames;
      const map = new Map(key.values.map((k, i) => [String(k), val.values[i]]));
      return frames.slice(0, 1).map((frame) => {
        const src = findFrameField(frame, lookupField, frames) ?? frame.fields[0];
        return createDataFrame({
          refId: frame.refId,
          name: frame.name,
          fields: [
            ...frame.fields,
            {
              name: `${fromField} lookup`,
              type: val.type,
              values: src.values.map((v) => map.get(String(v)) ?? null),
              config: {}
            }
          ]
        });
      });
    }
    return frames.map((frame) => {
      const src = findFrameField(frame, lookupField, frames) || frame.fields.find((f) => /country|geoip|code/i.test(f.name)) || frame.fields.find((f) => f.type === "string");
      if (!src) return frame;
      if (gazetteer === "countries" || !options.fromField) {
        return createDataFrame({
          refId: frame.refId,
          name: frame.name,
          fields: [
            ...frame.fields,
            {
              name: "country name",
              type: "string",
              values: src.values.map(
                (v) => GAZETTEER_COUNTRIES[String(v).toUpperCase()]?.name ?? null
              ),
              config: {}
            },
            {
              name: "latitude",
              type: "number",
              values: src.values.map(
                (v) => GAZETTEER_COUNTRIES[String(v).toUpperCase()]?.lat ?? null
              ),
              config: {}
            },
            {
              name: "longitude",
              type: "number",
              values: src.values.map(
                (v) => GAZETTEER_COUNTRIES[String(v).toUpperCase()]?.lon ?? null
              ),
              config: {}
            }
          ]
        });
      }
      return frame;
    });
  });
  function bucketCount(raw, fallback) {
    if (raw == null) return fallback;
    if (typeof raw === "number" && Number.isFinite(raw)) return Math.max(2, raw);
    if (typeof raw === "string" && raw.trim() !== "") {
      const n = Number(raw);
      if (Number.isFinite(n)) return Math.max(2, n);
    }
    if (typeof raw === "object") {
      const v = raw.value;
      const n = Number(v);
      if (Number.isFinite(n) && n > 0) return Math.max(2, n);
    }
    return fallback;
  }
  registerTransformer("heatmap", (frames, options = {}) => {
    const xBuckets = bucketCount(
      options.xBuckets ?? options["xBuckets.value"],
      Number(options.bucketCount ?? 10) || 10
    );
    const yBuckets = bucketCount(options.yBuckets ?? options["yBuckets.value"], 8);
    const out = [];
    for (const frame of frames) {
      const time = frame.fields.find((f) => f.type === "time");
      const nums = frame.fields.filter((f) => f.type === "number");
      if (!time || !nums.length) {
        out.push(frame);
        continue;
      }
      const times = time.values.map(Number);
      const tMin = Math.min(...times.filter(Number.isFinite));
      const tMax = Math.max(...times.filter(Number.isFinite));
      const tSpan = Math.max(1, tMax - tMin);
      let vMin = Infinity, vMax = -Infinity;
      for (const n of nums) {
        for (const v of n.values) {
          const x = Number(v);
          if (!Number.isFinite(x)) continue;
          vMin = Math.min(vMin, x);
          vMax = Math.max(vMax, x);
        }
      }
      if (!Number.isFinite(vMin)) {
        vMin = 0;
        vMax = 1;
      }
      if (vMin === vMax) vMax = vMin + 1;
      const counts = Array.from({ length: yBuckets }, () => new Array(xBuckets).fill(0));
      for (const n of nums) {
        for (let i = 0; i < n.values.length; i++) {
          const tv = Number(time.values[i]);
          const vv = Number(n.values[i]);
          if (!Number.isFinite(tv) || !Number.isFinite(vv)) continue;
          const xi = Math.min(
            xBuckets - 1,
            Math.max(0, Math.floor((tv - tMin) / tSpan * xBuckets))
          );
          const yi = Math.min(
            yBuckets - 1,
            Math.max(0, Math.floor((vv - vMin) / (vMax - vMin) * yBuckets))
          );
          counts[yi][xi] += 1;
        }
      }
      const xs = [];
      const ys = [];
      const cs = [];
      for (let y = 0; y < yBuckets; y++) {
        for (let x = 0; x < xBuckets; x++) {
          xs.push(tMin + (x + 0.5) / xBuckets * tSpan);
          ys.push(vMin + (y + 0.5) / yBuckets * (vMax - vMin));
          cs.push(counts[y][x]);
        }
      }
      out.push(
        createDataFrame({
          refId: frame.refId,
          name: frame.name || "heatmap",
          meta: { preferredVisualisationType: "heatmap", xBuckets, yBuckets },
          fields: [
            { name: "xMax", type: "time", values: xs },
            { name: "y", type: "number", values: ys },
            { name: "count", type: "number", values: cs }
          ]
        })
      );
    }
    return out;
  });
  function resolveLatLon(frame, options) {
    const source = options.source ?? {};
    const latField = String(
      source.latField ?? source.latitude ?? options.latitudeField ?? options.lat ?? "lat"
    );
    const lonField = String(
      source.lngField ?? source.longitude ?? options.longitudeField ?? options.lon ?? "lon"
    );
    const lat = findFrameField(frame, latField) ?? frame.fields.find(
      (f) => /lat/i.test(f.name) || /lat/i.test(String(f.config?.displayName ?? ""))
    );
    const lon = findFrameField(frame, lonField) ?? frame.fields.find(
      (f) => /lon|lng/i.test(f.name) || /lon|lng/i.test(String(f.config?.displayName ?? ""))
    );
    if (!lat || !lon) return null;
    return { lat, lon };
  }
  function haversineM(lat1, lon1, lat2, lon2) {
    if (![lat1, lon1, lat2, lon2].every(Number.isFinite)) return null;
    const toRad = (d) => d * Math.PI / 180;
    const R = 6371e3;
    const φ1 = toRad(lat1);
    const φ2 = toRad(lat2);
    const Δφ = toRad(lat2 - lat1);
    const Δλ = toRad(lon2 - lon1);
    const a = Math.sin(Δφ / 2) ** 2 + Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ / 2) ** 2;
    return 2 * R * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  }
  function headingDeg(lat1, lon1, lat2, lon2) {
    if (![lat1, lon1, lat2, lon2].every(Number.isFinite)) return null;
    const toRad = (d) => d * Math.PI / 180;
    const φ1 = toRad(lat1);
    const φ2 = toRad(lat2);
    const Δλ = toRad(lon2 - lon1);
    const y = Math.sin(Δλ) * Math.cos(φ2);
    const x = Math.cos(φ1) * Math.sin(φ2) - Math.sin(φ1) * Math.cos(φ2) * Math.cos(Δλ);
    let deg = Math.atan2(y, x) * 180 / Math.PI;
    if (deg < 0) deg += 360;
    return deg;
  }
  function extractFrame(frame, lat, lon) {
    return createDataFrame({
      refId: frame.refId,
      name: frame.name,
      fields: [
        {
          name: "latitude",
          type: "number",
          values: lat.values.map(Number),
          config: {}
        },
        {
          name: "longitude",
          type: "number",
          values: lon.values.map(Number),
          config: {}
        }
      ]
    });
  }
  registerTransformer("spatial", (frames, options = {}) => {
    const opts = options;
    let action = String(opts.action ?? opts.calc ?? "prepare").toLowerCase();
    if (action === "extract") action = "prepare";
    if (action === "distance" || action === "heading" || action === "area") {
      if (!opts.calculate) {
        opts.calculate = { calc: action };
      }
      action = "calculate";
    }
    const calcOpts = opts.calculate ?? {};
    const calc = String(
      calcOpts.calc ?? (typeof opts.calc === "string" && !["prepare", "calculate", "modify", "extract", "distance"].includes(String(opts.calc)) ? opts.calc : void 0) ?? "distance"
    ).toLowerCase();
    const outName = String(calcOpts.field ?? calc);
    return frames.map((frame) => {
      const pair = resolveLatLon(frame, opts);
      if (!pair) return frame;
      const { lat, lon } = pair;
      if (action === "prepare") {
        return extractFrame(frame, lat, lon);
      }
      if (action === "calculate" || action === "modify") {
        const n = lat.values.length;
        if (calc === "heading") {
          const values = new Array(n).fill(null);
          for (let i = 1; i < n; i++) {
            const h = headingDeg(
              Number(lat.values[i - 1]),
              Number(lon.values[i - 1]),
              Number(lat.values[i]),
              Number(lon.values[i])
            );
            values[i] = h;
            if (values[i - 1] == null) values[i - 1] = h;
          }
          if (n === 1) values[0] = 0;
          return createDataFrame({
            refId: frame.refId,
            name: frame.name,
            fields: [
              ...frame.fields,
              {
                name: outName === "heading" ? "heading" : outName,
                type: "number",
                values,
                config: { unit: "degree" }
              }
            ]
          });
        }
        if (calc === "area") {
          const values = new Array(n).fill(null);
          if (n >= 3) {
            const toRad = (d) => d * Math.PI / 180;
            const R = 6371e3;
            let area = 0;
            const lat0 = toRad(Number(lat.values[0]));
            const lon0 = toRad(Number(lon.values[0]));
            for (let i = 1; i < n - 1; i++) {
              const lat1 = toRad(Number(lat.values[i]));
              const lon1 = toRad(Number(lon.values[i]));
              const lat2 = toRad(Number(lat.values[i + 1]));
              const lon2 = toRad(Number(lon.values[i + 1]));
              const cross = (a, b) => [
                a[1] * b[2] - a[2] * b[1],
                a[2] * b[0] - a[0] * b[2],
                a[0] * b[1] - a[1] * b[0]
              ];
              const toVec = (φ, λ) => [
                Math.cos(φ) * Math.cos(λ),
                Math.cos(φ) * Math.sin(λ),
                Math.sin(φ)
              ];
              const v0 = toVec(lat0, lon0);
              const v1 = toVec(lat1, lon1);
              const v2 = toVec(lat2, lon2);
              const c = cross(
                [v1[0] - v0[0], v1[1] - v0[1], v1[2] - v0[2]],
                [v2[0] - v0[0], v2[1] - v0[1], v2[2] - v0[2]]
              );
              const mag = Math.hypot(c[0], c[1], c[2]);
              area += 0.5 * mag * R * R;
              values[i + 1] = area;
            }
            values[0] = 0;
            values[1] = values[1] ?? 0;
          } else {
            values.fill(0);
          }
          return createDataFrame({
            refId: frame.refId,
            name: frame.name,
            fields: [
              ...frame.fields,
              {
                name: outName === "area" ? "area" : outName,
                type: "number",
                values,
                config: { unit: "areaM2" }
              }
            ]
          });
        }
        const distances = lat.values.map((la, i) => {
          if (i === 0) return 0;
          return haversineM(
            Number(lat.values[0]),
            Number(lon.values[0]),
            Number(la),
            Number(lon.values[i])
          );
        });
        return createDataFrame({
          refId: frame.refId,
          name: frame.name,
          fields: [
            ...frame.fields,
            {
              name: outName === "distance" || outName === "distance_m" ? "distance_m" : outName,
              type: "number",
              values: distances,
              config: { unit: "lengthm" }
            }
          ]
        });
      }
      return frame;
    });
  });
  registerTransformer("regression", (frames, options = {}) => {
    const modelType = String(options.modelType ?? options.model ?? "linear");
    const degree = Math.min(5, Math.max(1, Number(options.degree ?? 2)));
    const predictionCount = Math.max(0, Number(options.predictionCount ?? 0));
    return frames.map((frame) => {
      const yName = String(options.yFieldName ?? options.fieldName ?? "");
      const xName = String(options.xFieldName ?? "");
      const time = (xName ? findFrameField(frame, xName, frames) : void 0) ?? frame.fields.find((f) => f.type === "time");
      const num = (yName ? findFrameField(frame, yName, frames) : void 0) ?? (options.fieldName ? findFrameField(frame, String(options.fieldName), frames) : void 0) ?? frame.fields.find((f) => f.type === "number");
      if (!num) return frame;
      const xs = (time?.values ?? (xName ? findFrameField(frame, xName, frames)?.values : void 0) ?? num.values.map((_, i) => i)).map(Number);
      const ys = num.values.map(Number);
      const n = xs.length || 1;
      let predicted = [];
      if (modelType === "polynomial" && degree >= 2) {
        const d = Math.min(degree, 2);
        if (d === 2) {
          let s0 = 0, s1 = 0, s2 = 0, s3 = 0, s4 = 0, sy = 0, sxy = 0, sx2y = 0;
          for (let i = 0; i < n; i++) {
            const x = xs[i];
            const y = Number.isFinite(ys[i]) ? ys[i] : 0;
            s0++;
            s1 += x;
            s2 += x * x;
            s3 += x * x * x;
            s4 += x * x * x * x;
            sy += y;
            sxy += x * y;
            sx2y += x * x * y;
          }
          const A = [
            [s0, s1, s2, sy],
            [s1, s2, s3, sxy],
            [s2, s3, s4, sx2y]
          ];
          for (let i = 0; i < 3; i++) {
            const piv = A[i][i] || 1e-12;
            for (let j = i; j < 4; j++) A[i][j] /= piv;
            for (let k = 0; k < 3; k++) {
              if (k === i) continue;
              const f = A[k][i];
              for (let j = i; j < 4; j++) A[k][j] -= f * A[i][j];
            }
          }
          const a = A[0][3], b = A[1][3], c = A[2][3];
          predicted = xs.map((x) => a + b * x + c * x * x);
          if (predictionCount > 0 && xs.length >= 2) {
            const step = xs[xs.length - 1] - xs[xs.length - 2] || 1;
            for (let p = 1; p <= predictionCount; p++) {
              const x = xs[xs.length - 1] + step * p;
              xs.push(x);
              predicted.push(a + b * x + c * x * x);
            }
          }
        }
      } else {
        const sumX = xs.reduce((a, b) => a + (Number.isFinite(b) ? b : 0), 0);
        const sumY = ys.reduce((a, b) => a + (Number.isFinite(b) ? b : 0), 0);
        const sumXY = xs.reduce((a, x, i) => a + x * (Number.isFinite(ys[i]) ? ys[i] : 0), 0);
        const sumXX = xs.reduce((a, x) => a + x * x, 0);
        const den = n * sumXX - sumX * sumX || 1;
        const slope = (n * sumXY - sumX * sumY) / den;
        const intercept = (sumY - slope * sumX) / n;
        predicted = xs.map((x) => intercept + slope * x);
        if (predictionCount > 0 && xs.length >= 2) {
          const step = xs[xs.length - 1] - xs[xs.length - 2] || 1;
          for (let p = 1; p <= predictionCount; p++) {
            const x = xs[xs.length - 1] + step * p;
            xs.push(x);
            predicted.push(intercept + slope * x);
          }
        }
      }
      const fields = [...frame.fields];
      if (predictionCount > 0 && time) {
        const tvals = [...time.values];
        const step = Number(tvals[tvals.length - 1]) - Number(tvals[tvals.length - 2]) || 1;
        for (let p = 1; p <= predictionCount; p++) tvals.push(Number(tvals[tvals.length - 1]) + step);
        return createDataFrame({
          refId: frame.refId,
          name: frame.name,
          fields: [
            { ...time, values: tvals },
            ...frame.fields.filter((f) => f !== time && f !== num).map((f) => ({
              ...f,
              values: [...f.values, ...new Array(predictionCount).fill(null)]
            })),
            {
              ...num,
              values: [...num.values, ...new Array(predictionCount).fill(null)]
            },
            {
              name: `${num.name} predicted`,
              type: "number",
              values: predicted,
              config: {}
            }
          ]
        });
      }
      return createDataFrame({
        refId: frame.refId,
        name: frame.name,
        fields: [
          ...fields,
          {
            name: `${num.name} predicted`,
            type: "number",
            values: predicted.slice(0, num.values.length),
            config: {}
          }
        ]
      });
    });
  });
  registerTransformer("smoothing", (frames, options = {}) => {
    const window2 = Math.max(1, Number(options.windowSize ?? options.window ?? 3));
    const algorithm = String(options.algorithm ?? "movingAvg");
    const alpha2 = Math.min(1, Math.max(0.01, Number(options.alpha ?? 2 / (window2 + 1))));
    const fieldName2 = String(options.field ?? options.fieldName ?? "");
    return frames.map(
      (frame) => createDataFrame({
        refId: frame.refId,
        name: frame.name,
        fields: frame.fields.map((f) => {
          if (f.type !== "number") return f;
          if (fieldName2 && !fieldMatchesName(f, fieldName2, frame, frames)) return f;
          let values;
          if (algorithm === "ema") {
            let prev = null;
            values = f.values.map((v) => {
              const n = Number(v);
              if (!Number.isFinite(n)) return prev;
              prev = prev == null ? n : alpha2 * n + (1 - alpha2) * prev;
              return prev;
            });
          } else {
            values = f.values.map((_, i) => {
              const from = Math.max(0, i - window2 + 1);
              const slice = f.values.slice(from, i + 1).map(Number).filter((n) => Number.isFinite(n));
              if (!slice.length) return null;
              return slice.reduce((a, b) => a + b, 0) / slice.length;
            });
          }
          return { ...f, name: `${f.name} smooth`, values };
        })
      })
    );
  });
  function applyStat(vals, stat) {
    if (!vals.length) return null;
    const s = String(stat || "lastNotNull");
    if (s === "min") return Math.min(...vals);
    if (s === "max") return Math.max(...vals);
    if (s === "mean" || s === "avg") return vals.reduce((a, b) => a + b, 0) / vals.length;
    if (s === "sum") return vals.reduce((a, b) => a + b, 0);
    if (s === "first" || s === "firstNotNull") return vals[0] ?? null;
    if (s === "count") return vals.length;
    if (s === "range") return Math.max(...vals) - Math.min(...vals);
    return vals[vals.length - 1] ?? null;
  }
  registerTransformer("timeSeriesTable", (frames, options = {}) => {
    const refIdToStatRaw = options.refIdToStat ?? {};
    const rows = [];
    for (const frame of frames) {
      const refId = String(frame.refId ?? "");
      let stat = "lastNotNull";
      const fromMap = refIdToStatRaw[refId];
      if (typeof fromMap === "string") stat = fromMap;
      else if (fromMap && typeof fromMap === "object" && fromMap.stat)
        stat = String(fromMap.stat);
      else if (options[refId] && typeof options[refId] === "object") {
        const o = options[refId];
        if (o?.stat) stat = String(o.stat);
      }
      const nums = frame.fields.filter((f) => f.type === "number");
      for (const num of nums) {
        const vals = num.values.map(Number).filter((n) => Number.isFinite(n));
        const last = vals.length ? vals[vals.length - 1] : null;
        const first = vals.length ? vals[0] : null;
        const avg = vals.length ? vals.reduce((a, b) => a + b, 0) / vals.length : null;
        const statValue = applyStat(vals, stat);
        rows.push({
          Metric: getFieldDisplayName(num, frame, frames),
          Stat: statValue,
          Last: last,
          First: first,
          Mean: avg,
          Min: vals.length ? Math.min(...vals) : null,
          Max: vals.length ? Math.max(...vals) : null,
          Points: vals.length,
          refId,
          ...num.labels || {},
          Trend: vals.slice(-20)
        });
      }
    }
    if (!rows.length) return frames;
    const keys = Object.keys(rows[0]).filter((k) => k !== "Trend");
    return [
      createDataFrame({
        refId: frames[0]?.refId,
        name: "timeSeriesTable",
        meta: { preferredVisualisationType: "table" },
        fields: [
          ...keys.map((k) => ({
            name: k,
            type: typeof rows[0][k] === "number" ? "number" : "string",
            values: rows.map((r) => r[k]),
            config: {}
          })),
          {
            name: "Trend",
            type: "other",
            values: rows.map((r) => r.Trend),
            config: { custom: { cellOptions: { type: "sparkline" } } }
          }
        ]
      })
    ];
  });
  function listStandardTransformers() {
    return listTransformerIds();
  }
  listStandardTransformers();
  function identity(v) {
    return v;
  }
  function numberOrUndefined(v) {
    if (v === "" || v === null || v === void 0) return void 0;
    const n = Number(v);
    return Number.isFinite(n) ? n : void 0;
  }
  const STANDARD_OVERRIDE_PROCESSORS = [
    {
      id: "unit",
      name: "单位",
      path: "unit",
      process: (v) => v == null || v === "" ? void 0 : String(v)
    },
    {
      id: "decimals",
      name: "小数位",
      path: "decimals",
      process: numberOrUndefined
    },
    { id: "min", name: "最小值", path: "min", process: numberOrUndefined },
    { id: "max", name: "最大值", path: "max", process: numberOrUndefined },
    {
      id: "fieldMinMax",
      name: "字段最小/最大",
      path: "fieldMinMax",
      process: (v) => v == null ? void 0 : Boolean(v)
    },
    {
      id: "displayName",
      name: "显示名称",
      path: "displayName",
      process: (v) => v == null || v === "" ? void 0 : String(v)
    },
    {
      id: "noValue",
      name: "空值显示",
      path: "noValue",
      process: (v) => v == null ? void 0 : String(v)
    },
    { id: "color", name: "颜色", path: "color", process: identity },
    { id: "thresholds", name: "阈值", path: "thresholds", process: identity },
    { id: "mappings", name: "值映射", path: "mappings", process: identity },
    { id: "links", name: "数据链接", path: "links", process: identity },
    { id: "actions", name: "动作", path: "actions", process: identity },
    {
      id: "filterable",
      name: "可过滤",
      path: "filterable",
      process: (v) => v == null ? void 0 : Boolean(v)
    }
  ];
  const processorById = new Map(STANDARD_OVERRIDE_PROCESSORS.map((p) => [p.id, p]));
  function getOverrideProcessor(id) {
    if (processorById.has(id)) return processorById.get(id);
    if (id.startsWith("custom.")) {
      return {
        id,
        name: id.slice(7),
        path: id,
        process: identity
      };
    }
    return {
      id,
      name: id,
      path: id,
      process: identity,
      shouldApply: () => false
    };
  }
  function processOverrideValue(id, value) {
    return getOverrideProcessor(id).process(value);
  }
  function isKnownOverrideProperty(id) {
    return processorById.has(id) || id.startsWith("custom.");
  }
  function applyProcessedProperty(config, id, raw) {
    const processor = getOverrideProcessor(id);
    if (processor.shouldApply === void 0 && !isKnownOverrideProperty(id) && !id.startsWith("custom.")) {
      return config;
    }
    const value = processor.process(raw);
    if (value === void 0) {
      const next = { ...config };
      if (id.startsWith("custom.")) {
        const custom = { ...config.custom ?? {} };
        delete custom[id.slice(7)];
        return { ...config, custom };
      }
      delete next[id];
      return next;
    }
    if (id.startsWith("custom.")) {
      const key = id.slice(7);
      return { ...config, custom: { ...config.custom ?? {}, [key]: value } };
    }
    if (id === "filterable") {
      return {
        ...config,
        filterable: value,
        custom: { ...config.custom ?? {}, filterable: value }
      };
    }
    return { ...config, [id]: value };
  }
  const compiledRulesCache = /* @__PURE__ */ new WeakMap();
  const compiledRulesLru = [];
  const COMPILED_RULES_LRU_MAX = 32;
  function defaultsCacheKey(defaults) {
    const unit = defaults.unit ?? "";
    const decimals = defaults.decimals ?? "";
    const displayName = defaults.displayName ?? "";
    const customKeys = defaults.custom ? Object.keys(defaults.custom).join(",") : "";
    return `${unit}|${decimals}|${displayName}|${customKeys}`;
  }
  function rulesSignature(overrides) {
    let s = String(overrides.length);
    for (const r of overrides) {
      s += `|${r.matcher?.id}:${JSON.stringify(r.matcher?.options)}:${r.properties?.length ?? 0}`;
      for (const p of r.properties || []) s += `:${p.id}`;
    }
    return s;
  }
  function compileOverrideRules(overrides = []) {
    return overrides.map((rule) => ({
      matcher: rule.matcher,
      properties: rule.properties || [],
      match: getFieldMatcher(rule.matcher || { id: "" })
    }));
  }
  function getCompiledRules(overrides, defaults) {
    const dKey = defaultsCacheKey(defaults);
    const weakHit = compiledRulesCache.get(overrides);
    if (weakHit && weakHit.defaultsKey === dKey) return weakHit.rules;
    const sig = `${rulesSignature(overrides)}::${dKey}`;
    const lruHit = compiledRulesLru.find((e) => e.key === sig);
    if (lruHit) {
      compiledRulesCache.set(overrides, {
        rules: lruHit.rules,
        defaultsKey: dKey
      });
      return lruHit.rules;
    }
    const rules = compileOverrideRules(overrides);
    compiledRulesCache.set(overrides, { rules, defaultsKey: dKey });
    compiledRulesLru.unshift({ key: sig, rules });
    if (compiledRulesLru.length > COMPILED_RULES_LRU_MAX) compiledRulesLru.pop();
    return rules;
  }
  function normalizePropId(id) {
    if (id === "unit" || id === "decimals" || id === "displayName" || id === "min" || id === "max" || id === "noValue" || id === "fieldMinMax" || id === "filterable" || id === "color" || id === "thresholds" || id === "mappings" || id === "links" || id === "actions") {
      return id;
    }
    if (id.startsWith("standardOptions.")) return id.slice("standardOptions.".length);
    if (id.startsWith("custom.")) return id;
    const customKeys = [
      "drawStyle",
      "lineInterpolation",
      "lineWidth",
      "fillOpacity",
      "gradientMode",
      "spanNulls",
      "showPoints",
      "pointSize",
      "stacking",
      "axisPlacement",
      "axisLabel",
      "axisSoftMin",
      "axisSoftMax",
      "axisCenteredZero",
      "hideFrom",
      "scaleDistribution",
      "thresholdsStyle",
      "barAlignment",
      "lineStyle",
      "insertNulls",
      "barWidthFactor"
    ];
    if (customKeys.includes(id)) return `custom.${id}`;
    return id;
  }
  function setNested(config, path, value) {
    if (path.startsWith("custom.")) {
      const rest = path.slice(7);
      const custom = { ...config.custom ?? {} };
      const parts = rest.split(".");
      let cur = custom;
      for (let i = 0; i < parts.length - 1; i++) {
        cur[parts[i]] = cur[parts[i]] && typeof cur[parts[i]] === "object" ? { ...cur[parts[i]] } : {};
        cur = cur[parts[i]];
      }
      cur[parts[parts.length - 1]] = value;
      return { ...config, custom };
    }
    if (path.includes(".")) {
      const parts = path.split(".");
      const root = { ...config };
      let cur = root;
      for (let i = 0; i < parts.length - 1; i++) {
        cur[parts[i]] = cur[parts[i]] && typeof cur[parts[i]] === "object" ? { ...cur[parts[i]] } : {};
        cur = cur[parts[i]];
      }
      cur[parts[parts.length - 1]] = value;
      return root;
    }
    return { ...config, [path]: value };
  }
  function applyFieldOverrides(frames, defaults = {}, overrides = []) {
    const compiled = getCompiledRules(overrides, defaults);
    return frames.map((frame) => ({
      ...frame,
      fields: frame.fields.map((field) => {
        const mergedCustom = {
          ...defaults.custom ?? {},
          ...field.config?.custom ?? {}
        };
        let config = {
          ...defaults,
          ...field.config,
          ...Object.keys(mergedCustom).length ? { custom: mergedCustom } : {}
        };
        for (const [ri, element] of compiled.entries()) {
          const rule = element;
          if (!rule.match(field, frame, frames)) continue;
          const properties = overrides[ri]?.properties ?? rule.properties;
          for (const prop of properties) {
            const id = normalizePropId(prop.id);
            if (!isKnownOverrideProperty(id) && !id.includes(".")) {
              continue;
            }
            const processed = processOverrideValue(id, prop.value);
            if (id.startsWith("custom.") || !isKnownOverrideProperty(id)) {
              config = setNested(config, id, processed);
            } else {
              config = applyProcessedProperty(config, id, prop.value);
            }
            if (id === "color" && prop.value && typeof prop.value === "object" && prop.value.fixedColor) {
              config = {
                ...config,
                color: {
                  ...config.color,
                  ...prop.value,
                  mode: prop.value.mode ?? "fixed"
                }
              };
            }
          }
        }
        return { ...field, config };
      })
    }));
  }
  var DataTransformerID = /* @__PURE__ */ ((DataTransformerID2) => {
    DataTransformerID2["append"] = "append";
    DataTransformerID2["reduce"] = "reduce";
    DataTransformerID2["order"] = "order";
    DataTransformerID2["organize"] = "organize";
    DataTransformerID2["rename"] = "rename";
    DataTransformerID2["calculateField"] = "calculateField";
    DataTransformerID2["seriesToColumns"] = "seriesToColumns";
    DataTransformerID2["seriesToRows"] = "seriesToRows";
    DataTransformerID2["merge"] = "merge";
    DataTransformerID2["concatenate"] = "concatenate";
    DataTransformerID2["labelsToFields"] = "labelsToFields";
    DataTransformerID2["filterFields"] = "filterFields";
    DataTransformerID2["filterFieldsByName"] = "filterFieldsByName";
    DataTransformerID2["filterFrames"] = "filterFrames";
    DataTransformerID2["filterByRefId"] = "filterByRefId";
    DataTransformerID2["renameByRegex"] = "renameByRegex";
    DataTransformerID2["filterByValue"] = "filterByValue";
    DataTransformerID2["noop"] = "noop";
    DataTransformerID2["ensureColumns"] = "ensureColumns";
    DataTransformerID2["groupBy"] = "groupBy";
    DataTransformerID2["sortBy"] = "sortBy";
    DataTransformerID2["histogram"] = "histogram";
    DataTransformerID2["configFromData"] = "configFromData";
    DataTransformerID2["rowsToFields"] = "rowsToFields";
    DataTransformerID2["prepareTimeSeries"] = "prepareTimeSeries";
    DataTransformerID2["convertFieldType"] = "convertFieldType";
    DataTransformerID2["convertFrameType"] = "convertFrameType";
    DataTransformerID2["fieldLookup"] = "fieldLookup";
    DataTransformerID2["heatmap"] = "heatmap";
    DataTransformerID2["spatial"] = "spatial";
    DataTransformerID2["joinByField"] = "joinByField";
    DataTransformerID2["joinByLabels"] = "joinByLabels";
    DataTransformerID2["extractFields"] = "extractFields";
    DataTransformerID2["groupingToMatrix"] = "groupingToMatrix";
    DataTransformerID2["limit"] = "limit";
    DataTransformerID2["partitionByValues"] = "partitionByValues";
    DataTransformerID2["timeSeriesTable"] = "timeSeriesTable";
    DataTransformerID2["transpose"] = "transpose";
    DataTransformerID2["formatTime"] = "formatTime";
    DataTransformerID2["formatString"] = "formatString";
    DataTransformerID2["regression"] = "regression";
    DataTransformerID2["smoothing"] = "smoothing";
    DataTransformerID2["groupToNestedTable"] = "groupToNestedTable";
    return DataTransformerID2;
  })(DataTransformerID || {});
  Object.values(DataTransformerID);
  const DEFAULT_MAX_ENTRIES = 64;
  const DEFAULT_MAX_BYTES = 512 * 1024;
  const cache = /* @__PURE__ */ new Map();
  let cacheBytes = 0;
  let maxEntries = DEFAULT_MAX_ENTRIES;
  let maxBytes = DEFAULT_MAX_BYTES;
  const DEFAULT_OPTIONS = {
    limit: { limitField: 10 },
    sortBy: { sort: [] },
    reduce: { reducers: ["sum"] },
    histogram: { bucketCount: 10 },
    smoothing: { windowSize: 3 },
    filterByValue: { type: "include", filters: [] },
    prepareTimeSeries: { format: "multi" }
  };
  function readLimitOption(options) {
    if (!options) return void 0;
    const raw = options.limit ?? options.limitField ?? options.limitValue;
    if (raw == null) return void 0;
    const n = Math.floor(Number(raw));
    return Number.isFinite(n) && n >= 0 ? n : void 0;
  }
  function tryFuseSortLimit(steps, index2) {
    const cur = steps[index2];
    const next = steps[index2 + 1];
    if (!cur || !next) return null;
    if (cur.disabled || next.disabled) return null;
    const curId = resolveTransformerId(cur.id);
    const nextId = resolveTransformerId(next.id);
    if (curId !== "sortBy" || nextId !== "limit") return null;
    if (JSON.stringify(cur.filter ?? null) !== JSON.stringify(next.filter ?? null)) {
      return null;
    }
    const lim = readLimitOption(next.options);
    if (lim == null) return null;
    const defaults = DEFAULT_OPTIONS.sortBy ?? {};
    return {
      fused: {
        id: "sortBy",
        filter: cur.filter,
        options: {
          ...defaults,
          ...cur.options || {},
          limit: lim,
          limitField: lim,
          limitValue: lim
        }
      },
      skipNext: true
    };
  }
  function compileTransformSteps(transformations = []) {
    const out = [];
    const src = transformations ?? [];
    for (let i = 0; i < src.length; i++) {
      const t = src[i];
      if (t.disabled) continue;
      const fuse = tryFuseSortLimit(src, i);
      if (fuse) {
        out.push(fuse.fused);
        if (fuse.skipNext) i += 1;
        continue;
      }
      const resolvedId = resolveTransformerId(t.id);
      const defaults = DEFAULT_OPTIONS[resolvedId] ?? DEFAULT_OPTIONS[t.id] ?? {};
      out.push({
        id: resolvedId,
        filter: t.filter,
        options: { ...defaults, ...t.options || {} }
      });
    }
    return out;
  }
  function estimateConfigBytes(config) {
    let n = 128;
    const transforms = config.transformations ?? [];
    n += transforms.length * 64;
    for (const t of transforms) {
      n += String(t.id).length + 16;
      if (t.options) n += Object.keys(t.options).length * 24;
    }
    const overrides = config.fieldConfigOverrides ?? [];
    n += overrides.length * 96;
    for (const r of overrides) {
      n += String(r.matcher?.id ?? "").length;
      n += (r.properties?.length ?? 0) * 32;
    }
    const defaults = config.fieldConfigDefaults;
    if (defaults) n += Object.keys(defaults).length * 24 + 32;
    return n;
  }
  function pipelineConfigRevision(config) {
    const transforms = config.transformations ?? [];
    const overrides = config.fieldConfigOverrides ?? [];
    const defaults = config.fieldConfigDefaults ?? {};
    const parts = [`t${transforms.length}`, `o${overrides.length}`];
    for (const t of transforms) {
      parts.push(
        `${t.disabled ? "D" : ""}${t.id}:${stableSmallJson(t.options)}:${stableSmallJson(t.filter)}`
      );
    }
    for (const r of overrides) {
      const props = (r.properties || []).map((p) => `${p.id}=${stableSmallJson(p.value)}`).join(",");
      parts.push(`m${r.matcher?.id}:${stableSmallJson(r.matcher?.options)}:${props}`);
    }
    parts.push(`d:${stableSmallJson(defaults)}`);
    return parts.join("|");
  }
  function stableSmallJson(value) {
    if (value == null) return "";
    if (typeof value === "string") return value.length > 64 ? value.slice(0, 64) : value;
    if (typeof value === "number" || typeof value === "boolean") return String(value);
    try {
      const s = JSON.stringify(value);
      return s.length > 256 ? s.slice(0, 256) : s;
    } catch {
      return "?";
    }
  }
  function touch(revision, entry) {
    cache.delete(revision);
    cache.set(revision, entry);
  }
  function evictIfNeeded() {
    while ((cache.size > maxEntries || cacheBytes > maxBytes) && cache.size > 0) {
      const oldest = cache.keys().next().value;
      if (oldest == null) break;
      const e = cache.get(oldest);
      cache.delete(oldest);
      if (e) cacheBytes -= e.bytes;
    }
    if (cacheBytes < 0) cacheBytes = 0;
  }
  function getCompiledPipeline(config) {
    const revision = pipelineConfigRevision(config);
    const hit = cache.get(revision);
    if (hit) {
      touch(revision, hit);
      return hit.compiled;
    }
    const transformations = (config.transformations ?? []).map((t) => ({
      id: t.id,
      options: t.options ? { ...t.options } : void 0,
      disabled: t.disabled,
      filter: t.filter
    }));
    const defaults = { ...config.fieldConfigDefaults ?? {} };
    const overrides = (config.fieldConfigOverrides ?? []).map((r) => ({
      matcher: { ...r.matcher || { id: "" } },
      properties: (r.properties || []).map((p) => ({ ...p }))
    }));
    const fastSteps = compileTransformSteps(transformations);
    const compiledOverrides = compileOverrideRules(overrides);
    const estimatedBytes = estimateConfigBytes(config);
    const compiled = {
      revision,
      transformations,
      fastSteps,
      defaults,
      overrides,
      compiledOverrides,
      estimatedBytes
    };
    const bytes = Math.max(estimatedBytes, revision.length + 64);
    cacheBytes += bytes;
    cache.set(revision, { revision, compiled, bytes });
    evictIfNeeded();
    return compiled;
  }
  function runCompiledPipeline(frames, compiled, opts) {
    const transformed = applyTransformations(frames, compiled.fastSteps);
    const series = applyFieldOverrides(transformed, compiled.defaults, compiled.overrides);
    return { frames: series, steps: [], diagnostics: [] };
  }
  function canEncodeF64(values) {
    for (const v of values) {
      if (v == null) continue;
      if (typeof v !== "number") return false;
    }
    return true;
  }
  function packFramesForTransfer(frames) {
    const transfer = [];
    const wire = (frames ?? []).map((frame) => {
      const fields = (frame.fields ?? []).map((f) => {
        const values = f.values ?? [];
        const type = f.type;
        const numericLike = (type === "number" || type === "time") && canEncodeF64(values);
        if (numericLike) {
          const f64 = new Float64Array(values.length);
          const nulls = new Uint8Array(values.length);
          for (const [i, v] of values.entries()) {
            if (v == null) {
              nulls[i] = 1;
              f64[i] = 0;
            } else {
              nulls[i] = 0;
              f64[i] = v;
            }
          }
          transfer.push(f64.buffer, nulls.buffer);
          return {
            name: f.name,
            type,
            config: f.config ? { ...f.config } : {},
            labels: f.labels ? { ...f.labels } : void 0,
            encoding: "f64",
            f64,
            nulls
          };
        }
        return {
          name: f.name,
          type,
          config: f.config ? { ...f.config } : {},
          labels: f.labels ? { ...f.labels } : void 0,
          encoding: "clone",
          values: values.slice()
        };
      });
      const len = frame.length ?? fields[0]?.f64?.length ?? fields[0]?.values?.length ?? 0;
      return {
        refId: frame.refId,
        name: frame.name,
        meta: frame.meta ? { ...frame.meta } : void 0,
        length: len,
        fields
      };
    });
    return { frames: wire, transfer };
  }
  function unpackWireFrames(frames) {
    return (frames ?? []).map((frame) => {
      const fields = (frame.fields ?? []).map((f) => {
        if (f.encoding === "f64" && f.f64) {
          const n = f.f64.length;
          const values = new Array(n);
          const nulls = f.nulls;
          for (let i = 0; i < n; i++) {
            values[i] = nulls && nulls[i] ? null : f.f64[i];
          }
          return {
            name: f.name,
            type: f.type,
            config: f.config ?? {},
            values,
            labels: f.labels
          };
        }
        return {
          name: f.name,
          type: f.type,
          config: f.config ?? {},
          values: f.values ?? [],
          labels: f.labels
        };
      });
      return {
        refId: frame.refId,
        name: frame.name,
        meta: frame.meta,
        fields,
        length: frame.length ?? fields.reduce((m, field) => Math.max(m, field.values.length), 0)
      };
    });
  }
  const cancelled = /* @__PURE__ */ new Set();
  function handlePanelPipelineMessage(msg, post) {
    if (msg == null || msg.id == null) return;
    if (msg.type === "cancel") {
      cancelled.add(msg.id);
      return;
    }
    if (cancelled.has(msg.id)) {
      cancelled.delete(msg.id);
      post({
        id: msg.id,
        generation: msg.generation,
        ok: false,
        error: "aborted",
        aborted: true
      });
      return;
    }
    try {
      const series = unpackWireFrames(msg.frames ?? []);
      const compiled = getCompiledPipeline({
        transformations: msg.transformations ?? [],
        fieldConfigDefaults: msg.fieldConfigDefaults ?? {},
        fieldConfigOverrides: msg.fieldConfigOverrides ?? []
      });
      if (cancelled.has(msg.id)) {
        cancelled.delete(msg.id);
        post({
          id: msg.id,
          generation: msg.generation,
          ok: false,
          error: "aborted",
          aborted: true
        });
        return;
      }
      const out = runCompiledPipeline(series, compiled, { withTrace: false });
      if (cancelled.has(msg.id)) {
        cancelled.delete(msg.id);
        post({
          id: msg.id,
          generation: msg.generation,
          ok: false,
          error: "aborted",
          aborted: true
        });
        return;
      }
      const packed = packFramesForTransfer(out.frames);
      post(
        {
          id: msg.id,
          generation: msg.generation,
          ok: true,
          frames: packed.frames
        },
        packed.transfer
      );
    } catch (error) {
      post({
        id: msg.id,
        generation: msg.generation,
        ok: false,
        error: error instanceof Error ? error.message : String(error)
      });
    }
  }
  function onMessage(ev) {
    handlePanelPipelineMessage(ev.data, (res, transfer) => {
      const scope = self;
      if (transfer?.length) scope.postMessage(res, transfer);
      else scope.postMessage(res);
    });
  }
  const isDedicatedWorker = typeof WorkerGlobalScope !== "undefined" && typeof self !== "undefined" && self instanceof WorkerGlobalScope;
  if (isDedicatedWorker) {
    self.onmessage = onMessage;
  }
})();
//# sourceMappingURL=panelPipelineWorker-Dj5aM1Pj.js.map
