UNPKG

kinto

Version:

An Offline-First JavaScript client for Kinto.

2,835 lines 88.7 kB
!(function (e, t) {
  "object" == typeof exports && "undefined" != typeof module
    ? t(exports)
    : "function" == typeof define && define.amd
      ? define(["exports"], t)
      : t(
          ((e =
            "undefined" != typeof globalThis ? globalThis : e || self).Kinto =
            {})
        );
})(this, function (e) {
  "use strict";
  function t(e, t, s, r) {
    var i,
      a = arguments.length,
      n =
        a < 3
          ? t
          : null === r
            ? (r = Object.getOwnPropertyDescriptor(t, s))
            : r;
    if ("object" == typeof Reflect && "function" == typeof Reflect.decorate)
      n = Reflect.decorate(e, t, s, r);
    else
      for (var o = e.length - 1; o >= 0; o--)
        (i = e[o]) && (n = (a < 3 ? i(n) : a > 3 ? i(t, s, n) : i(t, s)) || n);
    return (a > 3 && n && Object.defineProperty(t, s, n), n);
  }
  "function" == typeof SuppressedError && SuppressedError;
  const s = /^[a-zA-Z0-9][a-zA-Z0-9_-]*$/;
  function r(e) {
    return void 0 === e;
  }
  function i(e, t) {
    return Object.keys(e).every((s) => {
      const r = e[s];
      return Array.isArray(r)
        ? r.some((e) => e === t[s])
        : "object" == typeof r
          ? i(r, t[s])
          : Object.prototype.hasOwnProperty.call(t, s)
            ? t[s] === r
            : (console.error(`The property ${s} does not exist`), !1);
    });
  }
  function a(e, t) {
    return e.length
      ? e.reduce((e, t) => e.then(t), Promise.resolve(t))
      : Promise.resolve(t);
  }
  function n(e, t) {
    if (e === t) return !0;
    if (typeof e != typeof t) return !1;
    if (!e || "object" != typeof e || !t || "object" != typeof t) return !1;
    if (Object.keys(e).length !== Object.keys(t).length) return !1;
    for (const s in e) if (!n(e[s], t[s])) return !1;
    return !0;
  }
  function o(e, t = []) {
    const s = Object.assign({}, e);
    for (const e of t) delete s[e];
    return s;
  }
  function c(e, t, s) {
    const r = e.length - 1;
    return e.reduce(
      (e, s, i) =>
        i === r
          ? (e[s] = t)
          : Object.prototype.hasOwnProperty.call(e, s)
            ? e[s]
            : (e[s] = {}),
      s
    );
  }
  function d(e) {
    if (p(e)) return e;
    if ("string" == typeof e) return { id: e };
    throw new Error("Invalid argument.");
  }
  function h(e) {
    const t = (e) => encodeURIComponent("boolean" == typeof e ? String(e) : e),
      s = g(e);
    return Object.keys(s)
      .map((e) => {
        const r = t(e) + "=";
        return Array.isArray(s[e])
          ? r + s[e].map((e) => t(e)).join(",")
          : r + t(s[e]);
      })
      .join("&");
  }
  function l(e) {
    return function (t, s, r) {
      const i = r.value;
      return {
        configurable: !0,
        get() {
          const t = (...t) =>
            (this.client ? this.client : this)
              .fetchServerCapabilities()
              .then((t) => {
                const s = e.filter((e) => !(e in t));
                if (s.length) {
                  const e = s.join(", ");
                  throw new Error(
                    `Required capabilities ${e} not present on server`
                  );
                }
              })
              .then(() => i.apply(this, t));
          return (
            Object.defineProperty(this, s, {
              value: t,
              configurable: !0,
              writable: !0,
            }),
            t
          );
        },
      };
    };
  }
  function u(e) {
    return function (t, s, r) {
      const i = r.value;
      return {
        configurable: !0,
        get() {
          const t = (...t) => {
            if (this._isBatch) throw new Error(e);
            return i.apply(this, t);
          };
          return (
            Object.defineProperty(this, s, {
              value: t,
              configurable: !0,
              writable: !0,
            }),
            t
          );
        },
      };
    };
  }
  function p(e) {
    return "object" == typeof e && null !== e && !Array.isArray(e);
  }
  function f(e) {
    const {
        name: t,
        type: s,
        base64: r,
      } = (function (e) {
        const t = e.match(/^data:(.*);base64,(.*)/);
        if (!t)
          throw new Error(`Invalid data-url: ${String(e).substring(0, 32)}...`);
        const s = t[1],
          r = t[2],
          [i, ...a] = s.split(";"),
          n = a.reduce((e, t) => {
            const [s, r] = t.split("=");
            return Object.assign(Object.assign({}, e), { [s]: r });
          }, {});
        return Object.assign(Object.assign({}, n), { type: i, base64: r });
      })(e),
      i = atob(r),
      a = [];
    for (let e = 0; e < i.length; e++) a.push(i.charCodeAt(e));
    return { blob: new Blob([new Uint8Array(a)], { type: s }), name: t };
  }
  function g(e) {
    const t = {};
    for (const s in e) void 0 !== e[s] && (t[s] = e[s]);
    return t;
  }
  function m(e) {
    const t = new Headers(e);
    t.has("authorization") && t.set("authorization", "**** (suppressed)");
    const s = {};
    for (const [e, r] of t.entries()) s[e] = r;
    return s;
  }
  const y = {
    104: "Missing Authorization Token",
    105: "Invalid Authorization Token",
    106: "Request body was not valid JSON",
    107: "Invalid request parameter",
    108: "Missing request parameter",
    109: "Invalid posted data",
    110: "Invalid Token / id",
    111: "Missing Token / id",
    112: "Content-Length header was not provided",
    113: "Request body too large",
    114: "Resource was created, updated or deleted meanwhile",
    115: "Method not allowed on this end point (hint: server may be readonly)",
    116: "Requested version not available on this server",
    117: "Client has sent too many requests",
    121: "Resource access is forbidden for this user",
    122: "Another resource violates constraint",
    201: "Service Temporary unavailable due to high load",
    202: "Service deprecated",
    999: "Internal Server Error",
  };
  class _ extends Error {
    constructor(e, t) {
      (super(`Timeout while trying to access ${e} with ${JSON.stringify(t)}`),
        Error.captureStackTrace && Error.captureStackTrace(this, _),
        (this.url = e),
        (this.options = t));
    }
  }
  class b extends Error {
    constructor(e, t, s) {
      const { status: r } = e;
      (super(`Response from server unparseable (HTTP ${r || 0}; ${s}): ${t}`),
        Error.captureStackTrace && Error.captureStackTrace(this, b),
        (this.status = r),
        (this.response = e),
        (this.stack = s.stack),
        (this.error = s));
    }
  }
  class w extends Error {
    constructor(e, t) {
      const { status: s } = e;
      let r,
        { statusText: i } = e;
      t &&
        ((i = t.error || i),
        t.errno && t.errno in y
          ? (r = y[t.errno])
          : t.message && (r = t.message),
        r && t.message && t.message !== r && (r += ` (${t.message})`));
      let a = `HTTP ${s} ${i}`;
      (r && (a += `: ${r}`),
        super(a.trim()),
        Error.captureStackTrace && Error.captureStackTrace(this, w),
        (this.response = e),
        (this.data = t));
    }
  }
  class v {
    static get DEFAULT_REQUEST_HEADERS() {
      return { Accept: "application/json", "Content-Type": "application/json" };
    }
    static get defaultOptions() {
      return { timeout: null, requestMode: "cors" };
    }
    constructor(e, t = {}) {
      ((this.events = e),
        (this.requestMode = t.requestMode || v.defaultOptions.requestMode),
        (this.timeout = t.timeout || v.defaultOptions.timeout),
        (this.fetchFunc = t.fetchFunc || globalThis.fetch.bind(globalThis)));
    }
    timedFetch(e, t) {
      let s = !1;
      return new Promise((r, i) => {
        let a;
        function n(e) {
          return (t) => {
            s || (a && clearTimeout(a), e(t));
          };
        }
        (this.timeout &&
          (a = setTimeout(() => {
            ((s = !0),
              t &&
                t.headers &&
                (t = Object.assign(Object.assign({}, t), {
                  headers: m(t.headers),
                })),
              i(new _(e, t)));
          }, this.timeout)),
          this.fetchFunc(e, t).then(n(r)).catch(n(i)));
      });
    }
    async processResponse(e) {
      const { status: t, headers: s } = e,
        r = await e.text();
      let i;
      if (0 !== r.length)
        try {
          i = JSON.parse(r);
        } catch (t) {
          throw new b(e, r, t);
        }
      if (t >= 400) throw new w(e, i);
      return { status: t, json: i, headers: s };
    }
    async retry(e, t, s, r) {
      var i;
      return (
        await ((i = t), new Promise((e) => setTimeout(e, i))),
        this.request(
          e,
          s,
          Object.assign(Object.assign({}, r), { retry: r.retry - 1 })
        )
      );
    }
    async request(e, t = { headers: {} }, s = { retry: 0 }) {
      ((t.headers = Object.assign(
        Object.assign({}, v.DEFAULT_REQUEST_HEADERS),
        t.headers
      )),
        t.body &&
          t.body instanceof FormData &&
          (t.headers instanceof Headers
            ? t.headers.delete("Content-Type")
            : Array.isArray(t.headers) || delete t.headers["Content-Type"]),
        (t.mode = this.requestMode));
      const r = await this.timedFetch(e, t),
        { headers: i } = r;
      (this._checkForDeprecationHeader(i), this._checkForBackoffHeader(i));
      const a = this._checkForRetryAfterHeader(i);
      return a && s.retry > 0
        ? this.retry(e, a, t, s)
        : this.processResponse(r);
    }
    _checkForDeprecationHeader(e) {
      const t = e.get("Alert");
      if (!t) return;
      let s;
      try {
        s = JSON.parse(t);
      } catch (e) {
        return void console.warn("Unable to parse Alert header message", t);
      }
      (console.warn(s.message, s.url),
        this.events && this.events.emit("deprecated", s));
    }
    _checkForBackoffHeader(e) {
      let t;
      const s = e.get("Backoff"),
        r = s ? parseInt(s, 10) : 0;
      ((t = r > 0 ? new Date().getTime() + 1e3 * r : 0),
        this.events && this.events.emit("backoff", t));
    }
    _checkForRetryAfterHeader(e) {
      const t = e.get("Retry-After");
      if (!t) return null;
      const s = 1e3 * parseInt(t, 10),
        r = new Date().getTime() + s;
      return (this.events && this.events.emit("retry-after", r), s);
    }
  }
  const j = {
      root: () => "/",
      batch: () => "/batch",
      permissions: () => "/permissions",
      bucket: (e) => "/buckets" + (e ? `/${e}` : ""),
      history: (e) => `${j.bucket(e)}/history`,
      snapshot: (e, t, s) => `${j.bucket(e)}/snapshot/collections/${t}@${s}`,
      collection: (e, t) => `${j.bucket(e)}/collections` + (t ? `/${t}` : ""),
      group: (e, t) => `${j.bucket(e)}/groups` + (t ? `/${t}` : ""),
      record: (e, t, s) => `${j.collection(e, t)}/records` + (s ? `/${s}` : ""),
      attachment: (e, t, s) => `${j.record(e, t, s)}/attachment`,
    },
    O = { safe: !1, headers: {}, patch: !1 };
  function k(e, t) {
    return e ? (t ? { "If-Match": `"${t}"` } : { "If-None-Match": "*" }) : {};
  }
  function E(e, { data: t, permissions: s }, r = {}) {
    const { headers: i, safe: a } = Object.assign(Object.assign({}, O), r);
    return {
      method: r.method || (t && t.id) ? "PUT" : "POST",
      path: e,
      headers: Object.assign(Object.assign({}, i), k(a)),
      body: { data: t, permissions: s },
    };
  }
  function R(e, { data: t, permissions: s }, r = {}) {
    const {
        headers: i,
        safe: a,
        patch: n,
      } = Object.assign(Object.assign({}, O), r),
      { last_modified: o } = Object.assign(Object.assign({}, t), r);
    return (
      t &&
        0 ===
          Object.keys(t).filter((e) => "id" !== e && "last_modified" !== e)
            .length &&
        (t = void 0),
      {
        method: n ? "PATCH" : "PUT",
        path: e,
        headers: Object.assign(Object.assign({}, i), k(a, o)),
        body: { data: t, permissions: s },
      }
    );
  }
  function S(e, t, s, r = {}) {
    const {
        headers: i,
        safe: a,
        last_modified: n,
      } = Object.assign(Object.assign({}, O), r),
      o = [];
    for (const [e, r] of Object.entries(t))
      if (r)
        for (const t of r) o.push({ op: s, path: `/permissions/${e}/${t}` });
    return {
      method: "PATCH",
      path: e,
      headers: Object.assign(Object.assign(Object.assign({}, i), k(a, n)), {
        "Content-Type": "application/json-patch+json",
      }),
      body: o,
    };
  }
  function A(e, t = {}) {
    const {
      headers: s,
      safe: r,
      last_modified: i,
    } = Object.assign(Object.assign({}, O), t);
    if (r && !i)
      throw new Error("Safe concurrency check requires a last_modified value.");
    return {
      method: "DELETE",
      path: e,
      headers: Object.assign(Object.assign({}, s), k(r, i)),
    };
  }
  function T(e, t, { data: s, permissions: r } = {}, i = {}) {
    const { headers: a, safe: n } = Object.assign(Object.assign({}, O), i),
      { last_modified: o } = Object.assign(Object.assign({}, s), i),
      c = (function (e, t, s = {}) {
        const { filename: r = "untitled" } = s,
          { blob: i, name: a } = f(e),
          n = new FormData();
        n.append("attachment", i, a || r);
        for (const e in t) void 0 !== t[e] && n.append(e, JSON.stringify(t[e]));
        return n;
      })(t, { data: s, permissions: r }, i);
    return {
      method: "POST",
      path: e,
      headers: Object.assign(Object.assign({}, a), k(n, o)),
      body: c,
    };
  }
  const x = [];
  for (let e = 0; e < 256; ++e) x.push((e + 256).toString(16).slice(1));
  let I;
  const H = new Uint8Array(16);
  var P = {
    randomUUID:
      "undefined" != typeof crypto &&
      crypto.randomUUID &&
      crypto.randomUUID.bind(crypto),
  };
  function M(e, t, s) {
    const r =
      (e = e || {}).random ??
      e.rng?.() ??
      (function () {
        if (!I) {
          if ("undefined" == typeof crypto || !crypto.getRandomValues)
            throw new Error(
              "crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported"
            );
          I = crypto.getRandomValues.bind(crypto);
        }
        return I(H);
      })();
    if (r.length < 16) throw new Error("Random bytes length must be >= 16");
    return (
      (r[6] = (15 & r[6]) | 64),
      (r[8] = (63 & r[8]) | 128),
      (function (e, t = 0) {
        return (
          x[e[t + 0]] +
          x[e[t + 1]] +
          x[e[t + 2]] +
          x[e[t + 3]] +
          "-" +
          x[e[t + 4]] +
          x[e[t + 5]] +
          "-" +
          x[e[t + 6]] +
          x[e[t + 7]] +
          "-" +
          x[e[t + 8]] +
          x[e[t + 9]] +
          "-" +
          x[e[t + 10]] +
          x[e[t + 11]] +
          x[e[t + 12]] +
          x[e[t + 13]] +
          x[e[t + 14]] +
          x[e[t + 15]]
        ).toLowerCase();
      })(r)
    );
  }
  function q(e, t, s) {
    return P.randomUUID && !e ? P.randomUUID() : M(e);
  }
  let D = class {
    constructor(e, t, s, r = {}) {
      ((this.client = e),
        (this.bucket = t),
        (this.name = s),
        (this._endpoints = e.endpoints),
        (this._retry = r.retry || 0),
        (this._safe = !!r.safe),
        (this._headers = Object.assign(
          Object.assign({}, this.bucket.headers),
          r.headers
        )));
    }
    get execute() {
      return this.client.execute.bind(this.client);
    }
    _getHeaders(e) {
      return Object.assign(Object.assign({}, this._headers), e.headers);
    }
    _getSafe(e) {
      return Object.assign({ safe: this._safe }, e).safe;
    }
    _getRetry(e) {
      return Object.assign({ retry: this._retry }, e).retry;
    }
    async getTotalRecords(e = {}) {
      const t = this._endpoints.record(this.bucket.name, this.name),
        s = { headers: this._getHeaders(e), path: t, method: "HEAD" },
        { headers: r } = await this.client.execute(s, {
          raw: !0,
          retry: this._getRetry(e),
        });
      return parseInt(r.get("Total-Records"), 10);
    }
    async getRecordsTimestamp(e = {}) {
      const t = this._endpoints.record(this.bucket.name, this.name),
        s = { headers: this._getHeaders(e), path: t, method: "HEAD" },
        { headers: r } = await this.client.execute(s, {
          raw: !0,
          retry: this._getRetry(e),
        });
      return r.get("ETag");
    }
    async getData(e = {}) {
      const t = this._endpoints.collection(this.bucket.name, this.name),
        s = { headers: this._getHeaders(e), path: t },
        { data: r } = await this.client.execute(s, {
          retry: this._getRetry(e),
          query: e.query,
          fields: e.fields,
        });
      return r;
    }
    async setData(e, t = {}) {
      if (!p(e)) throw new Error("A collection object is required.");
      const { patch: s, permissions: r } = t,
        { last_modified: i } = Object.assign(Object.assign({}, e), t),
        a = R(
          this._endpoints.collection(this.bucket.name, this.name),
          { data: e, permissions: r },
          {
            last_modified: i,
            patch: s,
            headers: this._getHeaders(t),
            safe: this._getSafe(t),
          }
        );
      return this.client.execute(a, { retry: this._getRetry(t) });
    }
    async getPermissions(e = {}) {
      const t = this._endpoints.collection(this.bucket.name, this.name),
        s = { headers: this._getHeaders(e), path: t },
        { permissions: r } = await this.client.execute(s, {
          retry: this._getRetry(e),
        });
      return r;
    }
    async setPermissions(e, t = {}) {
      if (!p(e)) throw new Error("A permissions object is required.");
      const s = R(
        this._endpoints.collection(this.bucket.name, this.name),
        { data: { last_modified: t.last_modified }, permissions: e },
        { headers: this._getHeaders(t), safe: this._getSafe(t) }
      );
      return this.client.execute(s, { retry: this._getRetry(t) });
    }
    async addPermissions(e, t = {}) {
      if (!p(e)) throw new Error("A permissions object is required.");
      const s = this._endpoints.collection(this.bucket.name, this.name),
        { last_modified: r } = t,
        i = S(s, e, "add", {
          last_modified: r,
          headers: this._getHeaders(t),
          safe: this._getSafe(t),
        });
      return this.client.execute(i, { retry: this._getRetry(t) });
    }
    async removePermissions(e, t = {}) {
      if (!p(e)) throw new Error("A permissions object is required.");
      const s = this._endpoints.collection(this.bucket.name, this.name),
        { last_modified: r } = t,
        i = S(s, e, "remove", {
          last_modified: r,
          headers: this._getHeaders(t),
          safe: this._getSafe(t),
        });
      return this.client.execute(i, { retry: this._getRetry(t) });
    }
    async createRecord(e, t = {}) {
      const { permissions: s } = t,
        r = E(
          this._endpoints.record(this.bucket.name, this.name, e.id),
          { data: e, permissions: s },
          { headers: this._getHeaders(t), safe: this._getSafe(t) }
        );
      return this.client.execute(r, { retry: this._getRetry(t) });
    }
    async addAttachment(e, t = {}, s = {}) {
      const { permissions: r } = s,
        i = t.id || q(),
        a = this._endpoints.attachment(this.bucket.name, this.name, i),
        { last_modified: n } = Object.assign(Object.assign({}, t), s),
        o = T(
          a,
          e,
          { data: t, permissions: r },
          {
            last_modified: n,
            filename: s.filename,
            headers: this._getHeaders(s),
            safe: this._getSafe(s),
          }
        );
      return (
        await this.client.execute(o, {
          stringify: !1,
          retry: this._getRetry(s),
        }),
        this.getRecord(i)
      );
    }
    async removeAttachment(e, t = {}) {
      const { last_modified: s } = t,
        r = A(this._endpoints.attachment(this.bucket.name, this.name, e), {
          last_modified: s,
          headers: this._getHeaders(t),
          safe: this._getSafe(t),
        });
      return this.client.execute(r, { retry: this._getRetry(t) });
    }
    async updateRecord(e, t = {}) {
      if (!p(e)) throw new Error("A record object is required.");
      if (!e.id) throw new Error("A record id is required.");
      const { permissions: s } = t,
        { last_modified: r } = Object.assign(Object.assign({}, e), t),
        i = R(
          this._endpoints.record(this.bucket.name, this.name, e.id),
          { data: e, permissions: s },
          {
            headers: this._getHeaders(t),
            safe: this._getSafe(t),
            last_modified: r,
            patch: !!t.patch,
          }
        );
      return this.client.execute(i, { retry: this._getRetry(t) });
    }
    async deleteRecord(e, t = {}) {
      const s = d(e);
      if (!s.id) throw new Error("A record id is required.");
      const { id: r } = s,
        { last_modified: i } = Object.assign(Object.assign({}, s), t),
        a = A(this._endpoints.record(this.bucket.name, this.name, r), {
          last_modified: i,
          headers: this._getHeaders(t),
          safe: this._getSafe(t),
        });
      return this.client.execute(a, { retry: this._getRetry(t) });
    }
    async deleteRecords(e = {}) {
      const t = this._endpoints.record(this.bucket.name, this.name);
      return this.client.paginatedDelete(t, e, {
        headers: this._getHeaders(e),
        retry: this._getRetry(e),
      });
    }
    async getRecord(e, t = {}) {
      const s = this._endpoints.record(this.bucket.name, this.name, e),
        r = { headers: this._getHeaders(t), path: s };
      return this.client.execute(r, {
        retry: this._getRetry(t),
        query: t.query,
        fields: t.fields,
      });
    }
    async listRecords(e = {}) {
      const t = this._endpoints.record(this.bucket.name, this.name);
      return e.at
        ? this.getSnapshot(e.at)
        : this.client.paginatedList(t, e, {
            headers: this._getHeaders(e),
            retry: this._getRetry(e),
          });
    }
    async isHistoryComplete() {
      const {
        data: [e],
      } = await this.bucket.listHistory({
        limit: 1,
        filters: {
          action: "create",
          resource_name: "collection",
          collection_id: this.name,
        },
      });
      return !!e;
    }
    async getSnapshot(e, t = {}) {
      if (!e || !Number.isInteger(e) || e <= 0)
        throw new Error("Invalid argument, expected a positive integer.");
      const s = this._endpoints.snapshot(this.bucket.name, this.name, e),
        r = { headers: this._getHeaders(t), path: s, method: "GET" };
      let i = null;
      try {
        const { json: e } = await this.client.execute(r, {
          raw: !0,
          retry: this._getRetry(t),
        });
        i = e;
      } catch (e) {
        if (!/404/.test(String(e))) throw e;
      }
      if (null != i)
        return {
          last_modified: String(e),
          data: i.data,
          next: () => {
            throw new Error("Snapshots don't support pagination");
          },
          hasNextPage: !1,
          totalRecords: i.data.length,
        };
      if (!(await this.isHistoryComplete()))
        throw new Error(
          "Computing a snapshot is only possible when the full history for a collection is available. Here, the history plugin seems to have been enabled after the creation of the collection."
        );
      const { data: a } = await this.bucket.listHistory({
          pages: 1 / 0,
          sort: "last_modified",
          filters: { resource_name: "record", collection_id: this.name },
        }),
        n = new Map(),
        o = new Map();
      for (const t of a)
        (t.target.data.last_modified <= e && o.set(t.record_id, t),
          n.set(t.record_id, t));
      const { data: c } = await this.listRecords({
          pages: 1 / 0,
          fields: ["id"],
        }),
        d = new Set(c.map((e) => e.id)),
        h = new Set();
      for (const e of n.values())
        "delete" == e.action || d.has(e.record_id) || h.add(e.record_id);
      const l = [];
      for (const e of o.values())
        "delete" == e.action || h.has(e.record_id) || l.push(e.target.data);
      return {
        last_modified: String(e),
        data: Array.from(l).sort((e, t) => t.last_modified - e.last_modified),
        next: () => {
          throw new Error("Snapshots don't support pagination");
        },
        hasNextPage: !1,
        totalRecords: l.length,
      };
    }
    async batch(e, t = {}) {
      return this.client.batch(e, {
        bucket: this.bucket.name,
        collection: this.name,
        headers: this._getHeaders(t),
        retry: this._getRetry(t),
        safe: this._getSafe(t),
        aggregate: !!t.aggregate,
      });
    }
  };
  (t([l(["attachments"])], D.prototype, "addAttachment", null),
    t([l(["attachments"])], D.prototype, "removeAttachment", null),
    t([l(["history"])], D.prototype, "getSnapshot", null));
  class $ {
    constructor(e, t, s = {}) {
      ((this.client = e),
        (this.name = t),
        (this._endpoints = e.endpoints),
        (this._headers = s.headers || {}),
        (this._retry = s.retry || 0),
        (this._safe = !!s.safe));
    }
    get execute() {
      return this.client.execute.bind(this.client);
    }
    get headers() {
      return this._headers;
    }
    _getHeaders(e) {
      return Object.assign(Object.assign({}, this._headers), e.headers);
    }
    _getSafe(e) {
      return Object.assign({ safe: this._safe }, e).safe;
    }
    _getRetry(e) {
      return Object.assign({ retry: this._retry }, e).retry;
    }
    collection(e, t = {}) {
      return new D(this.client, this, e, {
        headers: this._getHeaders(t),
        retry: this._getRetry(t),
        safe: this._getSafe(t),
      });
    }
    async getCollectionsTimestamp(e = {}) {
      const t = this._endpoints.collection(this.name),
        s = { headers: this._getHeaders(e), path: t, method: "HEAD" },
        { headers: r } = await this.client.execute(s, {
          raw: !0,
          retry: this._getRetry(e),
        });
      return r.get("ETag");
    }
    async getGroupsTimestamp(e = {}) {
      const t = this._endpoints.group(this.name),
        s = { headers: this._getHeaders(e), path: t, method: "HEAD" },
        { headers: r } = await this.client.execute(s, {
          raw: !0,
          retry: this._getRetry(e),
        });
      return r.get("ETag");
    }
    async getData(e = {}) {
      const t = this._endpoints.bucket(this.name),
        s = { headers: this._getHeaders(e), path: t },
        { data: r } = await this.client.execute(s, {
          retry: this._getRetry(e),
          query: e.query,
          fields: e.fields,
        });
      return r;
    }
    async setData(e, t = {}) {
      if (!p(e)) throw new Error("A bucket object is required.");
      const s = Object.assign(Object.assign({}, e), { id: this.name }),
        r = s.id;
      "default" === s.id && delete s.id;
      const i = this._endpoints.bucket(r),
        { patch: a, permissions: n } = t,
        { last_modified: o } = Object.assign(Object.assign({}, e), t),
        c = R(
          i,
          { data: s, permissions: n },
          {
            last_modified: o,
            patch: a,
            headers: this._getHeaders(t),
            safe: this._getSafe(t),
          }
        );
      return this.client.execute(c, { retry: this._getRetry(t) });
    }
    async listHistory(e = {}) {
      const t = this._endpoints.history(this.name);
      return this.client.paginatedList(t, e, {
        headers: this._getHeaders(e),
        retry: this._getRetry(e),
      });
    }
    async listCollections(e = {}) {
      const t = this._endpoints.collection(this.name);
      return this.client.paginatedList(t, e, {
        headers: this._getHeaders(e),
        retry: this._getRetry(e),
      });
    }
    async createCollection(e, t = {}) {
      const { permissions: s, data: r = {} } = t;
      r.id = e;
      const i = E(
        this._endpoints.collection(this.name, e),
        { data: r, permissions: s },
        { headers: this._getHeaders(t), safe: this._getSafe(t) }
      );
      return this.client.execute(i, { retry: this._getRetry(t) });
    }
    async deleteCollection(e, t = {}) {
      const s = d(e);
      if (!s.id) throw new Error("A collection id is required.");
      const { id: r } = s,
        { last_modified: i } = Object.assign(Object.assign({}, s), t),
        a = A(this._endpoints.collection(this.name, r), {
          last_modified: i,
          headers: this._getHeaders(t),
          safe: this._getSafe(t),
        });
      return this.client.execute(a, { retry: this._getRetry(t) });
    }
    async deleteCollections(e = {}) {
      const t = this._endpoints.collection(this.name);
      return this.client.paginatedDelete(t, e, {
        headers: this._getHeaders(e),
        retry: this._getRetry(e),
      });
    }
    async listGroups(e = {}) {
      const t = this._endpoints.group(this.name);
      return this.client.paginatedList(t, e, {
        headers: this._getHeaders(e),
        retry: this._getRetry(e),
      });
    }
    async getGroup(e, t = {}) {
      const s = this._endpoints.group(this.name, e),
        r = { headers: this._getHeaders(t), path: s };
      return this.client.execute(r, {
        retry: this._getRetry(t),
        query: t.query,
        fields: t.fields,
      });
    }
    async createGroup(e, t = [], s = {}) {
      const r = Object.assign(Object.assign({}, s.data), { id: e, members: t }),
        i = this._endpoints.group(this.name, e),
        { permissions: a } = s,
        n = E(
          i,
          { data: r, permissions: a },
          { headers: this._getHeaders(s), safe: this._getSafe(s) }
        );
      return this.client.execute(n, { retry: this._getRetry(s) });
    }
    async updateGroup(e, t = {}) {
      if (!p(e)) throw new Error("A group object is required.");
      if (!e.id) throw new Error("A group id is required.");
      const s = Object.assign(Object.assign({}, t.data), e),
        r = this._endpoints.group(this.name, e.id),
        { patch: i, permissions: a } = t,
        { last_modified: n } = Object.assign(Object.assign({}, s), t),
        o = R(
          r,
          { data: s, permissions: a },
          {
            last_modified: n,
            patch: i,
            headers: this._getHeaders(t),
            safe: this._getSafe(t),
          }
        );
      return this.client.execute(o, { retry: this._getRetry(t) });
    }
    async deleteGroup(e, t = {}) {
      const s = d(e),
        { id: r } = s,
        { last_modified: i } = Object.assign(Object.assign({}, s), t),
        a = A(this._endpoints.group(this.name, r), {
          last_modified: i,
          headers: this._getHeaders(t),
          safe: this._getSafe(t),
        });
      return this.client.execute(a, { retry: this._getRetry(t) });
    }
    async deleteGroups(e = {}) {
      const t = this._endpoints.group(this.name);
      return this.client.paginatedDelete(t, e, {
        headers: this._getHeaders(e),
        retry: this._getRetry(e),
      });
    }
    async getPermissions(e = {}) {
      const t = {
          headers: this._getHeaders(e),
          path: this._endpoints.bucket(this.name),
        },
        { permissions: s } = await this.client.execute(t, {
          retry: this._getRetry(e),
        });
      return s;
    }
    async setPermissions(e, t = {}) {
      if (!p(e)) throw new Error("A permissions object is required.");
      const s = this._endpoints.bucket(this.name),
        { last_modified: r } = t,
        i = R(
          s,
          { data: { last_modified: r }, permissions: e },
          { headers: this._getHeaders(t), safe: this._getSafe(t) }
        );
      return this.client.execute(i, { retry: this._getRetry(t) });
    }
    async addPermissions(e, t = {}) {
      if (!p(e)) throw new Error("A permissions object is required.");
      const s = this._endpoints.bucket(this.name),
        { last_modified: r } = t,
        i = S(s, e, "add", {
          last_modified: r,
          headers: this._getHeaders(t),
          safe: this._getSafe(t),
        });
      return this.client.execute(i, { retry: this._getRetry(t) });
    }
    async removePermissions(e, t = {}) {
      if (!p(e)) throw new Error("A permissions object is required.");
      const s = this._endpoints.bucket(this.name),
        { last_modified: r } = t,
        i = S(s, e, "remove", {
          last_modified: r,
          headers: this._getHeaders(t),
          safe: this._getSafe(t),
        });
      return this.client.execute(i, { retry: this._getRetry(t) });
    }
    async batch(e, t = {}) {
      return this.client.batch(e, {
        bucket: this.name,
        headers: this._getHeaders(t),
        retry: this._getRetry(t),
        safe: this._getSafe(t),
        aggregate: !!t.aggregate,
      });
    }
  }
  t([l(["history"])], $.prototype, "listHistory", null);
  class C {
    constructor(e, t) {
      if ("string" != typeof e || !e.length)
        throw new Error("Invalid remote URL: " + e);
      ("/" === e[e.length - 1] && (e = e.slice(0, -1)),
        (this._backoffReleaseTime = null),
        (this._requests = []),
        (this._isBatch = !!t.batch),
        (this._retry = t.retry || 0),
        (this._safe = !!t.safe),
        (this._headers = t.headers || {}),
        (this.remote = e),
        (this.serverInfo = null),
        (this.events = t.events),
        (this.endpoints = j));
      const { fetchFunc: s, requestMode: r, timeout: i } = t;
      ((this.http = new v(this.events, {
        fetchFunc: s,
        requestMode: r,
        timeout: i,
      })),
        this._registerHTTPEvents());
    }
    get remote() {
      return this._remote;
    }
    set remote(e) {
      let t;
      try {
        t = e.match(/\/(v\d+)\/?$/)[1];
      } catch (t) {
        throw new Error("The remote URL must contain the version: " + e);
      }
      ((this._remote = e), (this._version = t));
    }
    get version() {
      return this._version;
    }
    get backoff() {
      const e = new Date().getTime();
      return this._backoffReleaseTime && e < this._backoffReleaseTime
        ? this._backoffReleaseTime - e
        : 0;
    }
    _registerHTTPEvents() {
      !this._isBatch &&
        this.events &&
        this.events.on("backoff", (e) => {
          this._backoffReleaseTime = e;
        });
    }
    bucket(e, t = {}) {
      return new $(this, e, {
        headers: this._getHeaders(t),
        safe: this._getSafe(t),
        retry: this._getRetry(t),
      });
    }
    setHeaders(e) {
      ((this._headers = Object.assign(Object.assign({}, this._headers), e)),
        (this.serverInfo = null));
    }
    _getHeaders(e) {
      return Object.assign(Object.assign({}, this._headers), e.headers);
    }
    _getSafe(e) {
      return Object.assign({ safe: this._safe }, e).safe;
    }
    _getRetry(e) {
      return Object.assign({ retry: this._retry }, e).retry;
    }
    async _getHello(e = {}) {
      const t = this.remote + j.root(),
        { json: s } = await this.http.request(
          t,
          { headers: this._getHeaders(e) },
          { retry: this._getRetry(e) }
        );
      return s;
    }
    async fetchServerInfo(e = {}) {
      return (
        this.serverInfo ||
          (this.serverInfo = await this._getHello({
            retry: this._getRetry(e),
          })),
        this.serverInfo
      );
    }
    async fetchServerSettings(e = {}) {
      const { settings: t } = await this.fetchServerInfo(e);
      return t;
    }
    async fetchServerCapabilities(e = {}) {
      const { capabilities: t } = await this.fetchServerInfo(e);
      return t;
    }
    async fetchUser(e = {}) {
      const { user: t } = await this._getHello(e);
      return t;
    }
    async fetchHTTPApiVersion(e = {}) {
      const { http_api_version: t } = await this.fetchServerInfo(e);
      return t;
    }
    async _batchRequests(e, t = {}) {
      const s = this._getHeaders(t);
      if (!e.length) return [];
      const r = (await this.fetchServerSettings({ retry: this._getRetry(t) }))
        .batch_max_requests;
      if (r && e.length > r) {
        const s =
            ((i = e),
            (a = r) <= 0
              ? [i]
              : i.reduce(
                  (e, t, s) => (
                    0 === s || s % a == 0
                      ? e.push([t])
                      : e[e.length - 1].push(t),
                    e
                  ),
                  []
                )),
          n = [];
        for (const e of s) {
          const s = await this._batchRequests(e, t);
          n.push(...s);
        }
        return n;
      }
      var i, a;
      const { responses: n } = await this.execute(
        {
          headers: s,
          path: j.batch(),
          method: "POST",
          body: { defaults: { headers: s }, requests: e },
        },
        { retry: this._getRetry(t) }
      );
      return n;
    }
    async batch(e, t = {}) {
      const s = new C(this.remote, {
        events: this.events,
        batch: !0,
        safe: this._getSafe(t),
        retry: this._getRetry(t),
      });
      t.bucket && t.collection
        ? e(s.bucket(t.bucket).collection(t.collection))
        : t.bucket
          ? e(s.bucket(t.bucket))
          : e(s);
      const r = await this._batchRequests(s._requests, t);
      return t.aggregate
        ? (function (e = [], t = []) {
            if (e.length !== t.length)
              throw new Error("Responses length should match requests one.");
            return e.reduce(
              (e, s, r) => {
                const { status: i } = s,
                  a = t[r];
                if (i >= 200 && i < 400) e.published.push(s.body);
                else if (404 === i) {
                  const t = /(buckets|groups|collections|records)\/([^/]+)$/,
                    r = a.path.match(t),
                    i = r && 3 === r.length ? r[2] : void 0;
                  e.skipped.push({ id: i, path: a.path, error: s.body });
                } else
                  412 === i
                    ? e.conflicts.push({
                        type: "outgoing",
                        local: a.body,
                        remote:
                          (s.body.details && s.body.details.existing) || null,
                      })
                    : e.errors.push({ path: a.path, sent: a, error: s.body });
                return e;
              },
              { errors: [], published: [], conflicts: [], skipped: [] }
            );
          })(r, s._requests)
        : r;
    }
    async execute(e, t = {}) {
      const { raw: s = !1, stringify: r = !0 } = t;
      if (this._isBatch) {
        this._requests.push(e);
        const t =
          "This result is generated from within a batch operation and should not be consumed.";
        return s ? { status: 0, json: t, headers: new Headers() } : t;
      }
      const i =
          this.remote +
          (function (e, t = {}) {
            const s = Object.assign({}, t.query);
            t.fields && (s._fields = t.fields);
            const r = h(s);
            return r ? e + "?" + r : e;
          })(e.path, t),
        a = await this.http.request(
          i,
          g({
            method: e.method,
            headers: e.headers,
            body: r ? JSON.stringify(e.body) : e.body,
          }),
          { retry: this._getRetry(t) }
        );
      return s ? a : a.json;
    }
    async paginatedOperation(e, t = {}, s = {}) {
      const {
        sort: r,
        filters: i,
        limit: a,
        pages: n,
        since: o,
        fields: c,
      } = Object.assign({ sort: "-last_modified" }, t);
      if (o && "string" != typeof o)
        throw new Error(
          `Invalid value for since (${o}), should be ETag value.`
        );
      const d = Object.assign(Object.assign({}, i), {
        _sort: r,
        _limit: a,
        _since: o,
      });
      c && (d._fields = c);
      const l = h(d);
      let u = [],
        p = 0;
      const f = async function (e) {
          if (!e) throw new Error("Pagination exhausted.");
          return g(e);
        },
        g = async (e) => {
          const { headers: t } = s;
          return y(await this.http.request(e, { headers: t }));
        },
        m = (e, t, s) => ({
          last_modified: s ? s.replace(/"/g, "") : s,
          data: e,
          next: f.bind(null, t),
          hasNextPage: !!t,
          totalRecords: -1,
        }),
        y = async function ({ headers: e = new Headers(), json: t = {} }) {
          const s = e.get("Next-Page"),
            r = e.get("ETag");
          return n
            ? ((u = u.concat(t.data)),
              (p += 1),
              p >= n || !s ? m(u, s, r) : g(s))
            : m(t.data, s, r);
        };
      return y(
        await this.execute(
          {
            headers: s.headers ? s.headers : {},
            path: e + "?" + l,
            method: s.method,
          },
          { raw: !0, retry: s.retry || 0 }
        )
      );
    }
    async paginatedList(e, t = {}, s = {}) {
      return this.paginatedOperation(e, t, s);
    }
    paginatedDelete(e, t = {}, s = {}) {
      const { headers: r, safe: i, last_modified: a } = s,
        n = A(e, { headers: r, safe: i || !1, last_modified: a });
      return this.paginatedOperation(
        e,
        t,
        Object.assign(Object.assign({}, s), {
          headers: n.headers,
          method: "DELETE",
        })
      );
    }
    async listPermissions(e = {}) {
      const t = j.permissions(),
        s = Object.assign({ sort: "id" }, e);
      return this.paginatedList(t, s, {
        headers: this._getHeaders(e),
        retry: this._getRetry(e),
      });
    }
    async listBuckets(e = {}) {
      const t = j.bucket();
      return this.paginatedList(t, e, {
        headers: this._getHeaders(e),
        retry: this._getRetry(e),
      });
    }
    async createBucket(e, t = {}) {
      const { data: s, permissions: r } = t,
        i = Object.assign(Object.assign({}, s), { id: e || void 0 }),
        a = i.id ? j.bucket(i.id) : j.bucket();
      return this.execute(
        E(
          a,
          { data: i, permissions: r },
          { headers: this._getHeaders(t), safe: this._getSafe(t) }
        ),
        { retry: this._getRetry(t) }
      );
    }
    async deleteBucket(e, t = {}) {
      const s = d(e);
      if (!s.id) throw new Error("A bucket id is required.");
      const r = j.bucket(s.id),
        { last_modified: i } = Object.assign(Object.assign({}, s), t);
      return this.execute(
        A(r, {
          last_modified: i,
          headers: this._getHeaders(t),
          safe: this._getSafe(t),
        }),
        { retry: this._getRetry(t) }
      );
    }
    async deleteBuckets(e = {}) {
      const t = j.bucket();
      return this.paginatedDelete(t, e, {
        headers: this._getHeaders(e),
        retry: this._getRetry(e),
        safe: e.safe,
        last_modified: e.last_modified,
      });
    }
    async createAccount(e, t) {
      return this.execute(
        E(`/accounts/${e}`, { data: { password: t } }, { method: "PUT" })
      );
    }
  }
  var L, N;
  (t(
    [u("This operation is not supported within a batch operation.")],
    C.prototype,
    "fetchServerSettings",
    null
  ),
    t(
      [u("This operation is not supported within a batch operation.")],
      C.prototype,
      "fetchServerCapabilities",
      null
    ),
    t(
      [u("This operation is not supported within a batch operation.")],
      C.prototype,
      "fetchUser",
      null
    ),
    t(
      [u("This operation is not supported within a batch operation.")],
      C.prototype,
      "fetchHTTPApiVersion",
      null
    ),
    t([u("Can't use batch within a batch!")], C.prototype, "batch", null),
    t([l(["permissions_endpoint"])], C.prototype, "listPermissions", null),
    t(
      [
        ((L = "1.4"),
        (N = "2.0"),
        function (e, t, s) {
          const r = s.value;
          return {
            configurable: !0,
            get() {
              const e = (...e) =>
                (this.client ? this.client : this)
                  .fetchHTTPApiVersion()
                  .then((e) =>
                    (function (e, t, s) {
                      const r = (e) => e.split(".").map((e) => parseInt(e, 10)),
                        [i, a] = r(e),
                        [n, o] = r(t),
                        [c, d] = r(s);
                      if (
                        [
                          i < n,
                          i === n && a < o,
                          i > c,
                          i === c && a >= d,
                        ].some((e) => e)
                      )
                        throw new Error(
                          `Version ${e} doesn't satisfy ${t} <= x < ${s}`
                        );
                    })(e, L, N)
                  )
                  .then(() => r.apply(this, e));
              return (
                Object.defineProperty(this, t, {
                  value: e,
                  configurable: !0,
                  writable: !0,
                }),
                e
              );
            },
          };
        }),
      ],
      C.prototype,
      "deleteBuckets",
      null
    ),
    t([l(["accounts"])], C.prototype, "createAccount", null));
  class B extends C {
    constructor(e, t = {}) {
      const s = t.events;
      super(e, Object.assign({ events: s }, t));
    }
  }
  class U {
    clear() {
      throw new Error("Not Implemented.");
    }
    execute(e, t = { preload: [] }) {
      throw new Error("Not Implemented.");
    }
    get(e) {
      throw new Error("Not Implemented.");
    }
    list(e = { filters: {}, order: "" }) {
      throw new Error("Not Implemented.");
    }
    saveLastModified(e) {
      throw new Error("Not Implemented.");
    }
    getLastModified() {
      throw new Error("Not Implemented.");
    }
    importBulk(e) {
      throw new Error("Not Implemented.");
    }
    loadDump(e) {
      throw new Error("Not Implemented.");
    }
    saveMetadata(e) {
      throw new Error("Not Implemented.");
    }
    getMetadata() {
      throw new Error("Not Implemented.");
    }
  }
  const F = ["id", "_status", "last_modified"];
  async function K(e, { version: t, onupgradeneeded: s }) {
    return new Promise((r, i) => {
      const a = indexedDB.open(e, t);
      ((a.onupgradeneeded = (e) => {
        a.result.onerror = (e) => i(a.error);
        const t = a.transaction;
        return (
          (t.onabort = (e) => {
            const s =
              a.error ||
              t.error ||
              new DOMException("The operation has been aborted", "AbortError");
            i(s);
          }),
          s(e)
        );
      }),
        (a.onerror = (e) => {
          i(e.target.error);
        }),
        (a.onsuccess = (e) => {
          const t = a.result;
          r(t);
        }));
    });
  }
  async function V(e, t, s, r = {}) {
    const { mode: i } = r;
    return new Promise((r, a) => {
      const n = i ? e.transaction([t], i) : e.transaction([t]),
        o = n.objectStore(t),
        c = (e) => {
          (n.abort(), console.error(e), a(e));
        };
      let d;
      try {
        d = s(o, c);
      } catch (e) {
        c(e);
      }
      ((n.onerror = (e) => a(e.target.error)),
        (n.oncomplete = (e) => r(d)),
        (n.onabort = (e) => {
          const t =
            e.target.error ||
            n.error ||
            new DOMException("The operation has been aborted", "AbortError");
          a(t);
        }));
    });
  }
  async function J(e) {
    return new Promise((t, s) => {
      const r = indexedDB.deleteDatabase(e);
      ((r.onsuccess = (e) => t(e.target)),
        (r.onerror = (e) => s(e.target.error)));
    });
  }
  const G = {
    all(e, t) {
      const s = [];
      return (r) => {
        const a = r.target.result;
        if (a) {
          const { value: t } = a;
          (i(e, t) && s.push(t), a.continue());
        } else t(s);
      };
    },
    in(e, t, s) {
      const r = [];
      let a = 0;
      return function (n) {
        const o = n.target.result;
        if (!o) return void s(r);
        const { key: c, value: d } = o;
        for (; c > e[a]; ) if ((++a, a === e.length)) return void s(r);
        const h = Array.isArray(c)
          ? (function (e, t) {
              if (e.length !== t.length) return !1;
              for (let s = e.length; s--; ) if (e[s] !== t[s]) return !1;
              return !0;
            })(c, e[a])
          : c === e[a];
        h ? (i(t, d) && r.push(d), o.continue()) : o.continue(e[a]);
      };
    },
  };
  function z(e, t, s, r) {
    const i = Object.keys(s);
    if (0 === i.length) {
      const s = t.index("cid").getAll(IDBKeyRange.only(e));
      return ((s.onsuccess = (e) => r(e.target.result)), s);
    }
    const a = i.find((e) => F.includes(e));
    if (!a) {
      if (Object.keys(s).some((e) => e.includes("."))) {
        const i = (function (e) {
            const t = {};
            for (const s in e) c(s.split("."), e[s], t);
            return t;
          })(s),
          a = t.index("cid").openCursor(IDBKeyRange.only(e));
        return ((a.onsuccess = G.all(i, r)), a);
      }
      const i = t.index("cid").openCursor(IDBKeyRange.only(e));
      return ((i.onsuccess = G.all(s, r)), i);
    }
    const n = o(s, [a]),
      d = s[a],
      h = "id" === a ? t : t.index(a);
    if (Array.isArray(d)) {
      if (0 === d.length) return r([]);
      const t = d.map((t) => [e, t]).sort(),
        s = IDBKeyRange.bound(t[0], t[t.length - 1]),
        i = h.openCursor(s);
      return ((i.onsuccess = G.in(t, n, r)), i);
    }
    if (0 === Object.keys(n).length) {
      const t = h.getAll(IDBKeyRange.only([e, d]));
      return ((t.onsuccess = (e) => r(e.target.result)), t);
    }
    const l = h.openCursor(IDBKeyRange.only([e, d]));
    return ((l.onsuccess = G.all(n, r)), l);
  }
  class W extends Error {
    constructor(e, t) {
      (super(`IndexedDB ${e}() ${t.message}`),
        (this.name = t.name),
        (this.stack = t.stack));
    }
  }
  class Y extends U {
    static get IDBError() {
      return W;
    }
    constructor(e, t = {}) {
      (super(),
        (this.cid = e),
        (this.dbName = t.dbName || "KintoDB"),
        (this._options = t),
        (this._db = null));
    }
    _handleError(e, t) {
      throw new W(e, t);
    }
    async open() {
      if (this._db) return this;
      const e = this._options.migrateOldData
        ? await (async function (e) {
            let t = !0;
            const s = await K(e, {
              version: 1,
              onupgradeneeded: (e) => {
                t = !1;
              },
            });
            if (
              ((t =
                s.objectStoreNames.contains("__meta__") &&
                s.objectStoreNames.contains(e)),
              !t)
            )
              return (s.close(), await J(e), null);
            console.warn(`${e}: old IndexedDB database found.`);
            try {
              let t;
              (await V(s, e, (e) => {
                e.openCursor().onsuccess = G.all({}, (e) => (t = e));
              }),
                console.log(`${e}: found ${t.length} records.`));
              let r = null;
              return (
                await V(s, "__meta__", (t) => {
                  t.get(`${e}-lastModified`).onsuccess = (e) => {
                    r = e.target.result ? e.target.result.value : null;
                  };
                }),
                r ||
                  (await V(s, "__meta__", (e) => {
                    e.get("lastModified").onsuccess = (e) => {
                      r = e.target.result ? e.target.result.value : null;
                    };
                  })),
                console.log(`${e}: ${r ? "found" : "no"} timestamp.`),
                { records: t, timestamp: r }
              );
            } catch (e) {
              return (console.error("Error occured during migration", e), null);
            } finally {
              s.close();
            }
          })(this.cid)
        : null;
      if (
        ((this._db = await K(this.dbName, {
          version: 2,
          onupgradeneeded: (e) => {
            const t = e.target.result;
            if (e.oldVersion < 1) {
              const e = t.createObjectStore("records", {
                keyPath: ["_cid", "id"],
              });
              (e.createIndex("cid", "_cid"),
                e.createIndex("_status", ["_cid", "_status"]),
                e.createIndex("last_modified", ["_cid", "last_modified"]),
                t.createObjectStore("timestamps", { keyPath: "cid" }));
            }
            e.oldVersion < 2 &&
              t.createObjectStore("collections", { keyPath: "cid" });
          },
        })),
        e)
      ) {
        const { records: t, timestamp: s } = e;
        (await this.importBulk(t),
          await this.saveLastModified(null != s ? s : 0),
          console.log(`${this.cid}: data was migrated successfully.`),
          await J(this.cid),
          console.warn(`${this.cid}: old database was deleted.`));
      }
      return this;
    }
    close() {
      return (
        this._db && (this._db.close(), (this._db = null)),
        Promise.resolve()
      );
    }
    async prepare(e, t, s) {
      (await this.open(), await V(this._db, e, t, s));
    }
    async clear() {
      try {
        await this.prepare(
          "records",
          (e) => {
            const t = IDBKeyRange.only(this.cid),
              s = e.index("cid").openKeyCursor(t);
            return (
              (s.onsuccess = (t) => {
                const s = t.target.result;
                s && (e.delete(s.primaryKey), s.continue());
              }),
              s
            );
          },
          { mode: "readwrite" }
        );
      } catch (e) {
        this._handleError("clear", e);
      }
    }
    async execute(e, t = { preload: [] }) {
      let s;
      return (
        await this.prepare(
          "records",
          (r, i) => {
            const a = (t = {}) => {
              const a = (function (e, t, s = {}) {
                const r = e.cid;
                return {
                  create(e) {
                    t.add(Object.assign(Object.assign({}, e), { _cid: r }));
                  },
                  update: (e) =>
                    t.put(Object.assign(Object.assign({}, e), { _cid: r })),
                  delete(e) {
                    t.delete([r, e]);
                  },
                  get: (e) => s[e],
                };
              })(this, r, t);
              try {
                const t = e(a);
                if (t instanceof Promise)
                  throw new Error(
                    "execute() callback should not return a Promise."
                  );
                s = t;
              } catch (e) {
                i && i(e);
              }
            };
            if (!t.preload) return void a();
            const n = { id: t.preload };
            z(this.cid, r, n, (e) => {
              const t = {};
              for (const s of e) (delete s._cid, (t[s.id] = s));
              a(t);
            });
          },
          { mode: "readwrite" }
        ),
        s
      );
    }
    async get(e) {
      try {
        let t;
        return (
          await this.prepare("records", (s) => {
            s.get([this.cid, e]).onsuccess = (e) => (t = e.target.result);
          }),
          t
        );
      } catch (e) {
        this._handleError("get", e);
      }
      return null;
    }
    async list(e = { filters: {} }) {
      const { filters: t } = e;
      try {
        let s = [];
        return (
          await this.prepare("records", (e) => {
            z(this.cid, e, t, (e) => {
              for (const t of e) delete t._cid;
              s = e;
            });
          }),
          e.order
            ? (function (e, t) {
                const s = "-" === e[0],
                  i = s ? e.slice(1) : e,
                  a = s ? -1 : 1;
                return t
                  .slice()
                  .sort((e, t) =>
                    e[i] && r(t[i])
                      ? a
                      : t[i] && r(e[i])
                        ? -a
                        : r(e[i]) && r(t[i])
                          ? 0
                          : e[i] > t[i]
                            ? a
                            : -a
                  );
              })(e.order, s)
            : s
        );
      } catch (e) {
        this._handleError("list", e);
      }
      return [];
    }
    async saveLastModified(e) {
      const t = e || null;
      try {
        return (
          await this.prepare(
            "timestamps",
            (e) => {
              null === t
                ? e.delete(this.cid)
                : e.put({ cid: this.cid, value: t });
            },
            { mode: "readwrite" }
          ),
          t
        );
      } catch (e) {
        this._handleError("saveLastModified", e);
      }
      return null;
    }
    async getLastModified() {
      try {
        let e = null;
        return (
          await this.prepare("timestamps", (t) => {
            t.get(this.cid).onsuccess = (t) => {
              e = t.target.result;
            };
          }),
          e ? e.value : null
        );
      } catch (e) {
        this._handleError("getLastModified", e);
      }
      return null;
    }
    async loadDump(e) {
      return this.importBulk(e);
    }
    async importBulk(e) {
      try {
        await this.execute((t) => {
          let s = 0;
          !(function r() {
            if (s === e.length) return;
            ((t.update(e[s]).onsuccess = r), ++s);
          })();
        });
        const t = await this.getLastModified(),
          s = Math.max(...e.map((e) => e.last_modified));
        return (t && s > t && (await this.saveLastModified(s)), e);
      } catch (e) {
        this._handleError("importBulk", e);
      }
      return [];
    }
    async saveMetadata(e) {
      try {
        return (
          await this.prepare(
            "collections",
            (t) => t.put({ cid: this.cid, metadata: e }),
            { mode: "readwrite" }
          ),
          e
        );
      } catch (e) {
        return (this._handleError("saveMetadata", e), null);
      }
    }
    async getMetadata() {
      try {
        let e = null;
        return (
          await this.prepare("collections", (t) => {
            t.get(this.cid).onsuccess = (t) => (e = t.target.result);
          }),
          e ? e.metadata : null
        );
      } catch (e) {
        return (this._handleError("getMetadata", e), null);
      }
    }
  }
  const Q = ["_status"],
    Z = ["incoming-changes"];
  function X(e, t, s = []) {
    const r = [...Q, "last_modified", ...s],
      i = (e) => o(e, r);
    return n(i(e), i(t));
  }
  class ee {
    constructor() {
      ((this.lastModified = null),
        (this._lists = {
          errors: [],
          created: [],
          updated: [],
          deleted: [],
          published: [],
          conflicts: [],
          skipped: [],
          resolved: [],
          void: [],
        }),
        (this._cached = {}));
    }
    add(e, t) {
      return Array.isArray(this._lists[e])
        ? (Array.isArray(t) || (t = [t]),
          (this._lists[e] = [...this._lists[e], ...t]),
          delete this._cached[e],
          this)
        : (console.warn(`Unknown type "${e}"`), this);
    }
    get ok() {
      return this.errors.length + this.conflicts.length === 0;
    }
    get errors() {
      return this._lists.errors;
    }
    get conflicts() {
      return this._lists.conflicts;
    }
    get skipped() {
      return this._deduplicate("skipped");
    }
    get resolved() {
      return this._deduplicate("resolved");
    }
    get created() {
      return this._deduplicate("created");
    }
    get updated() {
      return this._deduplicate("updated");
    }
    get deleted() {
      return this._deduplicate("deleted");
    }
    get published() {
      return this._deduplicate("published");
    }
    _deduplicate(e) {
      if (!(e in this._cached)) {
        const t = new Set(),
          s = new Map();
        (this._lists[e].forEach((e) => {
          e.id ? s.set(e.id, e) : t.add(e);
        }),
          (this._cached[e] = Array.from(s.values()).concat(Array.from(t))));
      }
      return this._cached[e];
    }
    reset(e) {
      return ((this._lists[e] = []), delete this._cached[e], this);
    }
    toObject() {
      return {
        ok: this.ok,
        lastModified: this.lastModified,
        errors: this.errors,
        created: this.created,
        updated: this.updated,
        deleted: this.deleted,
        skipped: this.skipped,
        published: this.published,
        conflicts: this.conflicts,
        resolved: this.resolved,
      };
    }
  }
  class te extends Error {
    constructor(e, t, s) {
      (super(s),
        Error.captureStackTrace && Error.captureStackTrace(this, te),
        (this.clientTimestamp = e),
        (this.serverTimestamp = t));
    }
  }
  function se(e, t) {
    return Object.assign(Object.assign({}, e), { _status: t });
  }
  function re(e) {
    return se(e, "deleted");
  }
  function ie(e) {
    return se(e, "synced");
  }
  function ae(e, t, s, r) {
    const i = e.get(t.id);
    if (!i) {
      if (t.deleted) return { type: "skipped", data: t };
      const s = ie(t);
      return (e.create(s), { type: "created", data: s });
    }
    const a = Object.assign(Object.assign({}, i), ie(t));
    if (r === ne.strategy.PULL_ONLY)
      return t.deleted
        ? (e.delete(t.id), { type: "deleted", data: i })
        : (e.update(a), { type: "updated", data: { old: i, new: a } });
    const n = X(i, t, s);
    return "synced" !== i._status
      ? "deleted" === i._status
        ? { type: "skipped", data: i }
        : n
          ? (e.update(a), { type: "updated", data: { old: i, new: a } })
          : void 0 !== i.last_modified && i.last_modified === t.last_modified
            ? { type: "void" }
            : {
                type: "conflicts",
                data: { type: "incoming", local: i, remote: t },
              }
      : t.deleted
        ? (e.delete(t.id), { type: "deleted", data: i })
        : (e.update(a),
          n ? { type: "void" } : { type: "updated", data: { old: i, new: a } });
  }
  class ne {
    constructor(e, t, s, r = {}) {
      ((this._bucket = e), (this._name = t), (this._lastModified = null));
      const i = r.adapter
        ? r.adapter(`${e}/${t}`, r.adapterOptions)
        : new Y(`${e}/${t}`, r.adapterOptions);
      if (!(i instanceof U)) throw new Error("Unsupported adapter.");
      ((this.db = i),
        (this.kinto = s),
        (this.events = r.events),
        (this.idSchema = this._validateIdSchema(r.idSchema)),
        (this.remoteTransformers = this._validateRemoteTransformers(
          r.remoteTransformers
        )),
        (this.hooks = this._validateHooks(r.hooks)),
        (this.localFields = r.localFields || []));
    }
    get api() {
      return this.kinto.api;
    }
    get name() {
      return this._name;
    }
    get bucket() {
      return this._bucket;
    }
    get lastModified() {
      return this._lastModified;
    }
    static get strategy() {
      return {
        CLIENT_WINS: "client_wins",
        SERVER_WINS: "server_wins",
        PULL_ONLY: "pull_only",
        MANUAL: "manual",
      };
    }
    _validateIdSchema(e) {
      if (void 0 === e)
        return {
          generate: () => q(),
          validate: (e) => "string" == typeof e && s.test(e),
        };
      if ("object" != typeof e) throw new Error("idSchema must be an object.");
      if ("function" != typeof e.generate)
        throw new Error("idSchema must provide a generate function.");
      if ("function" != typeof e.validate)
        throw new Error("idSchema must provide a validate function.");
      return e;
    }
    _validateRemoteTransformers(e) {
      if (void 0 === e) return [];
      if (!Array.isArray(e))
        throw new Error("remoteTransformers should be an array.");
      return e.map((e) => {
        if ("object" != typeof e)
          throw new Error("A transformer must be an object.");
        if ("function" != typeof e.encode)
          throw new Error("A transformer must provide an encode function.");
        if ("function" != typeof e.decode)
          throw new Error("A transformer must provide a decode function.");
        return e;
      });
    }
    _validateHook(e) {
      if (!Array.isArray(e))
        throw new Error("A hook definition should be an array of functions.");
      return e.map((e) => {
        if ("function" != typeof e)
          throw new Error("A hook definition should be an array of functions.");
        return e;
      });
    }
    _validateHooks(e) {
      if (void 0 === e) return {};
      if (Array.isArray(e))
        throw new Error("hooks should be an object, not an array.");
      if ("object" != typeof e) throw new Error("hooks should be an object.");
      const t = {};
      for (const s in e) {
        if (!Z.includes(s))
          throw new Error("The hook should be one of " + Z.join(", "));
        t[s] = this._validateHook(e[s]);
      }
      return t;
    }
    async clear() {
      return (
        await this.db.clear(),
        await this.db.saveMetadata(null),
        await this.db.saveLastModified(null),
        { data: [], permissions: {} }
      );
    }
    _encodeRecord(e, t) {
      const s = "remote" === e ? this.remoteTransformers : [];
      return s.length
        ? a(
            s.map((e) => (t) => e.encode(t)),
            t
          )
        : Promise.resolve(t);
    }
    _decodeRecord(e, t) {
      const s = "remote" === e ? this.remoteTransformers : [];
      return s.length
        ? a(
            s.reverse().map((e) => (t) => e.decode(t)),
            t
          )
        : Promise.resolve(t);
    }
    create(e, t = { useRecordId: !1, synced: !1 }) {
      const s = (e) => Promise.reject(new Error(e));
      if ("object" != typeof e) return s("Record is not an object.");
      if (
        (t.synced || t.useRecordId) &&
        !Object.prototype.hasOwnProperty.call(e, "id")
      )
        return s(
          "Missing required Id; synced and useRecordId options require one"
        );
      if (
        !t.synced &&
        !t.useRecordId &&
        Object.prototype.hasOwnProperty.call(e, "id")
      )
        return s("Extraneous Id; can't create a record having one set.");
      const r = Object.assign(Object.assign({}, e), {
        id: t.synced || t.useRecordId ? e.id : this.idSchema.generate(e),
        _status: t.synced ? "synced" : "created",
      });
      return this.idSchema.validate(r.id)
        ? this.execute((e) => e.create(r), { preloadIds: [r.id] }).catch(
            (e) => {
              if (t.useRecordId)
                throw new Error(
                  "Couldn't create record. It may have been virtually deleted."
                );
              throw e;
            }
          )
        : s(`Invalid Id: ${r.id}`);
    }
    update(e, t = { synced: !1, patch: !1 }) {
      return "object" != typeof e
        ? Promise.reject(new Error("Record is not an object."))
        : Object.prototype.hasOwnProperty.call(e, "id")
          ? this.idSchema.validate(e.id)
            ? this.execute(
                (s) => {
                  var r, i;
                  return s.update(e, {
                    synced: null !== (r = t.synced) && void 0 !== r && r,
                    patch: null !== (i = t.patch) && void 0 !== i && i,
                  });
                },
                { preloadIds: [e.id] }
              )
            : Promise.reject(new Error(`Invalid Id: ${e.id}`))
          : Promise.reject(new Error("Cannot update a record missing id."));
    }
    upsert(e) {
      return "object" != typeof e
        ? Promise.reject(new Error("Record is not an object."))
        : Object.prototype.hasOwnProperty.call(e, "id")
          ? this.idSchema.validate(e.id)
            ? this.execute((t) => t.upsert(e), { preloadIds: [e.id] })
            : Promise.reject(new Error(`Invalid Id: ${e.id}`))
          : Promise.reject(new Error("Cannot update a record missing id."));
    }
    get(e, t = { includeDeleted: !1 }) {
      return this.execute((s) => s.get(e, t), { preloadIds: [e] });
    }
    getAny(e) {
      return this.execute((t) => t.getAny(e), { preloadIds: [e] });
    }
    delete(e, t = { virtual: !0 }) {
      return this.execute((s) => s.delete(e, t), { preloadIds: [e] });
    }
    async deleteAll() {
      const { data: e } = await this.list({}, { includeDeleted: !1 }),
        t = e.map((e) => e.id);
      return this.execute((e) => e.deleteAll(t), { preloadIds: t });
    }
    deleteAny(e) {
      return this.execute((t) => t.deleteAny(e), { preloadIds: [e] });
    }
    async list(e = {}, t = { includeDeleted: !1 }) {
      e = Object.assign({ order: "-last_modified", filters: {} }, e);
      const s = await this.db.list(e);
      let r = s;
      return (
        t.includeDeleted || (r = s.filter((e) => "deleted" !== e._status)),
        { data: r, permissions: {} }
      );
    }
    async importChanges(e, t, s = ne.strategy.MANUAL) {
      try {
        for (let r = 0; r < t.length; r += 200) {
          const i = t.slice(r, r + 200),
            { imports: a, resolved: n } = await this.db.execute(
              (e) => {
                const t = i.map((t) => ae(e, t, this.localFields, s)),
                  r = t
                    .filter((e) => "conflicts" === e.type)
                    .map((e) => e.data);
                return { imports: t, resolved: this._handleConflicts(e, r, s) };
              },
              { preload: i.map((e) => e.id) }
            );
          (a.forEach(({ type: t, data: s }) => e.add(t, s)),
            n.length > 0 && e.reset("conflicts").add("resolved", n));
        }
      } catch (t) {
        const s = { type: "incoming", message: t.message, stack: t.stack };
        e.add("errors", s);
      }
      return e;
    }
    async _applyPushedResults(e, t, s, r = ne.strategy.MANUAL) {
      const i = t.filter((e) => e.deleted),
        a = t.filter((e) => !e.deleted),
        { published: n, resolved: o } = await this.db.execute((e) => {
          const t = a.map((t) => {
              const s = ie(t);
              return (e.update(s), s);
            }),
            n = i.map((t) => (e.delete(t.id), { id: t.id, deleted: !0 }));
          return {
            published: t.concat(n),
            resolved: this._handleConflicts(e, s, r),
          };
        });
      return (
        e.add("published", n),
        o.length > 0 &&
          e.reset("conflicts").reset("resolved").add("resolved", o),
        e
      );
    }
    _handleConflicts(e, t, s) {
      return s === ne.strategy.MANUAL
        ? []
        : t.map((t) => {
            const r = s === ne.strategy.CLIENT_WINS ? t.local : t.remote,
              i = s === ne.strategy.CLIENT_WINS ? t.remote : t.local;
            let a, n, o;
            if (null === r)
              (e.delete(t.local.id),
                (a = null),
                (n = "synced"),
                (o = t.local.id));
            else {
              const s = this._resolveRaw(t, r);
              (e.update(s), (a = s), (n = s._status), (o = s.id));
            }
            return { rejected: i, accepted: a, id: o, _status: n };
          });
    }
    execute(e, { preloadIds: t = [] } = {}) {
      for (const e of t)
        if (!this.idSchema.validate(e))
          return Promise.reject(Error(`Invalid Id: ${e}`));
      return this.db.execute(
        (t) => {
          const s = new oe(this, t),
            r = e(s);
          return (s.emitEvents(), r);
        },
        { preload: t }
      );
    }
    async resetSyncStatus() {
      const e = await this.list(
        { filters: { _status: ["deleted", "synced"] }, order: "" },
        { includeDeleted: !0 }
      );
      return (
        await this.db.execute((t) => {
          e.data.forEach((e) => {
            "deleted" === e._status
              ? t.delete(e.id)
              : t.update(
                  Object.assign(Object.assign({}, e), {
                    last_modified: void 0,
                    _status: "created",
                  })
                );
          });
        }),
        (this._lastModified = null),
        await this.db.saveLastModified(null),
        e.data.length
      );
    }
    async gatherLocalChanges() {
      const e = await this.list({
          filters: { _status: ["created", "updated"] },
          order: "",
        }),
        t = await this.list(
          { filters: { _status: "deleted" }, order: "" },
          { includeDeleted: !0 }
        );
      return await Promise.all(
        e.data.concat(t.data).map(this._encodeRecord.bind(this, "remote"))
      );
    }
    async pullChanges(e, t, s = {}) {
      if (!t.ok) return t;
      const r = this.lastModified
        ? this.lastModified
        : await this.db.getLastModified();
      let i;
      if (
        (s = Object.assign(
          { strategy: ne.strategy.MANUAL, lastModified: r, headers: {} },
          s
        )).exclude
      ) {
        i = {
          exclude_id: s.exclude
            .slice(0, 50)
            .map((e) => e.id)
            .join(","),
        };
      }
      s.expectedTimestamp &&
        (i = Object.assign(Object.assign({}, i), {
          _expected: s.expectedTimestamp,
        }));
      const { data: a, last_modified: n } = await e.listRecords({
          since: s.lastModified ? `${s.lastModified}` : void 0,
          headers: s.headers,
          retry: s.retry,
          pages: 1 / 0,
          filters: i,
        }),
        o = n ? parseInt(n, 10) : void 0,
        c = s.lastModified,
        d = o && o > s.lastModified,
        h = 0 === a.length;
      if (!s.exclude && c && d && h) {
        throw new te(
          c,
          o,
          "Server has been flushed. Client Side Timestamp: " +
            c +
            " Server Side Timestamp: " +
            o
        );
      }
      t.lastModified = o;
      const l = {
          lastModified: o,
          changes: await Promise.all(
            a.map((e) => this._decodeRecord("remote", e))
          ),
        },
        u = await this.applyHook("incoming-changes", l);
      return (
        u.changes.length > 0 &&
          (await this.importChanges(t, u.changes, s.strategy)),
        t
      );
    }
    applyHook(e, t) {
      return void 0 === this.hooks[e]
        ? Promise.resolve(t)
        : a(
            this.hooks[e].map((e) => (s) => {
              const r = e(t, this),
                i = r && "function" == typeof r.then,
                a = r && Object.prototype.hasOwnProperty.call(r, "changes");
              if (!i && !a)
                throw new Error(
                  `Invalid return value for hook: ${JSON.stringify(r)} has no 'then()' or 'changes' properties`
                );
              return r;
            }),
            t
          );
    }
    async pushChanges(e, t, s, r = {}) {
      if (!s.ok) return s;
      const i = !r.strategy || void 0 !== r.strategy,
        a = t.filter((e) => "deleted" === e._status),
        n = t.filter((e) => "deleted" != e._status),
        o = await e.batch(
          (e) => {
            (a.forEach((t) => {
              t.last_modified && e.deleteRecord(t);
            }),
              n.forEach((t) => {
                const s = this.cleanLocalFields(t);
                "created" === t._status ? e.createRecord(s) : e.updateRecord(s);
              }));
          },
          { headers: r.headers, retry: r.retry, safe: i, aggregate: !0 }
        );
      s.add(
        "errors",
        o.errors.map((e) =>
          Object.assign(Object.assign({}, e), { type: "outgoing" })
        )
      );
      const c = [];
      for (const { type: e, local: t, remote: s } of o.conflicts) {
        const r = (t && t.data) || { id: s.id },
          i = {
            type: e,
            local: await this._decodeRecord("remote", r),
            remote: s && (await this._decodeRecord("remote", s)),
          };
        c.push(i);
      }
      s.add("conflicts", c);
      const d = o.skipped.map((e) =>
          Object.assign(Object.assign({}, e), { deleted: !0 })
        ),
        h = o.published.map((e) => e.data).concat(d),
        l = await Promise.all(h.map((e) => this._decodeRecord("remote", e)));
      return (
        (l.length > 0 || c.length > 0) &&
          (await this._applyPushedResults(s, l, c, r.strategy)),
        s
      );
    }
    cleanLocalFields(e) {
      return o(e, [...Q, ...this.localFields]);
    }
    resolve(e, t) {
      return this.db.execute((s) => {
        const r = this._resolveRaw(e, t);
        return (s.update(r), { data: r, permissions: {} });
      });
    }
    _resolveRaw(e, t) {
      const s = Object.assign(Object.assign({}, t), {
        last_modified: e.remote && e.remote.last_modified,
      });
      return se(s, n(s, e.remote) ? "synced" : "updated");
    }
    async sync(
      e = {
        strategy: ne.strategy.MANUAL,
        headers: {},
        retry: 1,
        ignoreBackoff: !1,
        bucket: null,
        collection: null,
        remote: null,
        expectedTimestamp: null,
      }
    ) {
      var t, s;
      e = Object.assign(Object.assign({}, e), {
        bucket: e.bucket || this.bucket,
        collection: e.collection || this.name,
      });
      const r = this.api.remote;
      if (
        (e.remote && (this.api.remote = e.remote),
        !e.ignoreBackoff && this.api.backoff > 0)
      ) {
        const e = Math.ceil(this.api.backoff / 1e3);
        return Promise.reject(
          new Error(
            `Server is asking clients to back off; retry in ${e}s or use the ignoreBackoff option.`
          )
        );
      }
      const i = this.api.bucket(e.bucket).collection(e.collection),
        a = new ee();
      try {
        (await this.pullMetadata(i, e), await this.pullChanges(i, a, e));
        const { lastModified: t } = a;
        if (e.strategy !== ne.strategy.PULL_ONLY) {
          const s = await this.gatherLocalChanges();
          await this.pushChanges(i, s, a, e);
          const r = a.resolved.filter((e) => "synced" !== e._status);
          if (r.length > 0) {
            const t = await Promise.all(
              r.map((e) => {
                let t = e.accepted;
                return (
                  null === t && (t = { id: e.id, _status: e._status }),
                  this._encodeRecord("remote", t)
                );
              })
            );
            await this.pushChanges(i, t, a, e);
          }
          if (a.published.length > 0) {
            const s = Object.assign(Object.assign({}, e), {
              lastModified: t,
              exclude: a.published,
            });
            await this.pullChanges(i, a, s);
          }
        }
        a.ok &&
          (this._lastModified = await this.db.saveLastModified(a.lastModified));
      } catch (s) {
        throw (
          null === (t = this.events) ||
            void 0 === t ||
            t.emit(
              "sync:error",
              Object.assign(Object.assign({}, e), { error: s })
            ),
          s
        );
      } finally {
        this.api.remote = r;
      }
      return (
        null === (s = this.events) ||
          void 0 === s ||
          s.emit(
            "sync:success",
            Object.assign(Object.assign({}, e), { result: a })
          ),
        a
      );
    }
    async loadDump(e) {
      return this.importBulk(e);
    }
    async importBulk(e) {
      if (!Array.isArray(e)) throw new Error("Records is not an array.");
      for (const t of e) {
        if (
          !Object.prototype.hasOwnProperty.call(t, "id") ||
          !this.idSchema.validate(t.id)
        )
          throw new Error("Record has invalid ID: " + JSON.stringify(t));
        if (!t.last_modified)
          throw new Error(
            "Record has no last_modified value: " + JSON.stringify(t)
          );
      }
      const { data: t } = await this.list({}, { includeDeleted: !0 }),
        s = t.reduce((e, t) => ((e[t.id] = t), e), {}),
        r = e.filter((e) => {
          const t = s[e.id];
          return (
            void 0 === t ||
            ("synced" === t._status &&
              void 0 !== t.last_modified &&
              e.last_modified > t.last_modified)
          );
        });
      return await this.db.importBulk(r.map(ie));
    }
    async pullMetadata(e, t = {}) {
      const { expectedTimestamp: s, headers: r } = t,
        i = s ? { query: { _expected: s.toString() } } : void 0,
        a = await e.getData(
          Object.assign(Object.assign({}, i), { headers: r })
        );
      return this.db.saveMetadata(a);
    }
    async metadata() {
      return this.db.getMetadata();
    }
  }
  class oe {
    constructor(e, t) {
      ((this.collection = e),
        (this.adapterTransaction = t),
        (this._events = []));
    }
    _queueEvent(e, t) {
      this._events.push({ action: e, payload: t });
    }
    emitEvents() {
      var e, t;
      for (const { action: t, payload: s } of this._events)
        null === (e = this.collection.events) || void 0 === e || e.emit(t, s);
      if (this._events.length > 0) {
        const e = this._events.map(({ action: e, payload: t }) =>
          Object.assign({ action: e }, t)
        );
        null === (t = this.collection.events) ||
          void 0 === t ||
          t.emit("change", { targets: e });
      }
      this._events = [];
    }
    getAny(e) {
      return { data: this.adapterTransaction.get(e), permissions: {} };
    }
    get(e, t = { includeDeleted: !1 }) {
      const s = this.getAny(e);
      if (!s.data || (!t.includeDeleted && "deleted" === s.data._status))
        throw new Error(`Record with id=${e} not found.`);
      return s;
    }
    delete(e, t = { virtual: !0 }) {
      const s = this.adapterTransaction.get(e),
        r = s && "deleted" === s._status;
      if (!s || (r && t.virtual))
        throw new Error(`Record with id=${e} not found.`);
      return (
        t.virtual
          ? this.adapterTransaction.update(re(s))
          : this.adapterTransaction.delete(e),
        this._queueEvent("delete", { data: s }),
        { data: s, permissions: {} }
      );
    }
    deleteAll(e) {
      const t = [];
      return (
        e.forEach((e) => {
          (t.push(this.adapterTransaction.get(e)), this.delete(e));
        }),
        this._queueEvent("deleteAll", { data: t }),
        { data: t, permissions: {} }
      );
    }
    deleteAny(e) {
      const t = this.adapterTransaction.get(e);
      return (
        t &&
          (this.adapterTransaction.update(re(t)),
          this._queueEvent("delete", { data: t })),
        { data: Object.assign({ id: e }, t), deleted: !!t, permissions: {} }
      );
    }
    create(e) {
      if ("object" != typeof e) throw new Error("Record is not an object.");
      if (!Object.prototype.hasOwnProperty.call(e, "id"))
        throw new Error("Cannot create a record missing id");
      if (!this.collection.idSchema.validate(e.id))
        throw new Error(`Invalid Id: ${e.id}`);
      return (
        this.adapterTransaction.create(e),
        this._queueEvent("create", { data: e }),
        { data: e, permissions: {} }
      );
    }
    update(e, t = { synced: !1, patch: !1 }) {
      if ("object" != typeof e) throw new Error("Record is not an object.");
      if (!Object.prototype.hasOwnProperty.call(e, "id"))
        throw new Error("Cannot update a record missing id.");
      if (!this.collection.idSchema.validate(e.id))
        throw new Error(`Invalid Id: ${e.id}`);
      const s = this.adapterTransaction.get(e.id);
      if (!s) throw new Error(`Record with id=${e.id} not found.`);
      const r = t.patch ? Object.assign(Object.assign({}, s), e) : e,
        i = this._updateRaw(s, r, t);
      return (
        this.adapterTransaction.update(i),
        this._queueEvent("update", { data: i, oldRecord: s }),
        { data: i, oldRecord: s, permissions: {} }
      );
    }
    _updateRaw(e, t, { synced: s = !1 } = {}) {
      const r = Object.assign({}, t);
      e &&
        e.last_modified &&
        !r.last_modified &&
        (r.last_modified = e.last_modified);
      const i =
          e && X(e, r, this.collection.localFields) && "synced" === e._status,
        a = !e || (e && "created" === e._status);
      return se(r, i || s ? "synced" : a ? "created" : "updated");
    }
    upsert(e) {
      if ("object" != typeof e) throw new Error("Record is not an object.");
      if (!Object.prototype.hasOwnProperty.call(e, "id"))
        throw new Error("Cannot update a record missing id.");
      if (!this.collection.idSchema.validate(e.id))
        throw new Error(`Invalid Id: ${e.id}`);
      let t = this.adapterTransaction.get(e.id);
      const s = this._updateRaw(t, e);
      return (
        this.adapterTransaction.update(s),
        t && "deleted" === t._status && (t = void 0),
        t
          ? this._queueEvent("update", { data: s, oldRecord: t })
          : this._queueEvent("create", { data: s }),
        { data: s, oldRecord: t, permissions: {} }
      );
    }
  }
  class ce {
    static get adapters() {
      return { BaseAdapter: U };
    }
    static get syncStrategy() {
      return ne.strategy;
    }
    constructor(e = {}) {
      const t = {
        bucket: "default",
        remote: "http://localhost:8888/v1",
        retry: 1,
      };
      if (
        ((this._options = Object.assign(Object.assign({}, t), e)),
        !this._options.adapter)
      )
        throw new Error("No adapter provided");
      ((this._api = null), (this.events = this._options.events));
    }
    get ApiClass() {
      throw new Error("ApiClass() must be implemented by subclasses.");
    }
    get api() {
      const {
        events: e,
        headers: t,
        remote: s,
        requestMode: r,
        retry: i,
        timeout: a,
      } = this._options;
      return (
        this._api ||
          (this._api = new this.ApiClass(s, {
            events: e,
            headers: t,
            requestMode: r,
            retry: i,
            timeout: a,
          })),
        this._api
      );
    }
    collection(e, t = {}) {
      if (!e) throw new Error("missing collection name");
      const {
          bucket: s,
          events: r,
          adapter: i,
          adapterOptions: a,
        } = Object.assign(Object.assign({}, this._options), t),
        { idSchema: n, remoteTransformers: o, hooks: c, localFields: d } = t;
      return new ne(s, e, this, {
        events: r,
        adapter: i,
        adapterOptions: a,
        idSchema: n,
        remoteTransformers: o,
        hooks: c,
        localFields: d,
      });
    }
  }
  class de extends ce {
    static get adapters() {
      return { BaseAdapter: U, IDB: Y };
    }
    get ApiClass() {
      return B;
    }
    constructor(e = {}) {
      const t = { adapter: (e, t) => new de.adapters.IDB(e, t) };
      super(Object.assign(Object.assign({}, t), e));
    }
  }
  ((e.AbstractBaseAdapter = class {}),
    (e.BaseAdapter = U),
    (e.KintoBase = ce),
    (e.KintoClient = B),
    (e.default = de),
    (e.getDeepKey = function (e, t) {
      const s = t.split(".");
      let r = e;
      for (let e = 0; e < s.length; e++) r = r ? r[s[e]] : void 0;
      return null != r ? r : void 0;
    }),
    Object.defineProperty(e, "__esModule", { value: !0 }));
});
//# sourceMappingURL=kinto.min.js.map