{"version":3,"file":"y-op-sqlite.mjs","sources":["../node_modules/.pnpm/lib0@0.2.93/node_modules/lib0/promise.js","../node_modules/.pnpm/lib0@0.2.93/node_modules/lib0/map.js","../node_modules/.pnpm/lib0@0.2.93/node_modules/lib0/set.js","../node_modules/.pnpm/lib0@0.2.93/node_modules/lib0/array.js","../node_modules/.pnpm/lib0@0.2.93/node_modules/lib0/observable.js","../src/index.ts"],"sourcesContent":["/**\n * Utility helpers to work with promises.\n *\n * @module promise\n */\n\nimport * as time from './time.js'\n\n/**\n * @template T\n * @callback PromiseResolve\n * @param {T|PromiseLike<T>} [result]\n */\n\n/**\n * @template T\n * @param {function(PromiseResolve<T>,function(Error):void):any} f\n * @return {Promise<T>}\n */\nexport const create = f => /** @type {Promise<T>} */ (new Promise(f))\n\n/**\n * @param {function(function():void,function(Error):void):void} f\n * @return {Promise<void>}\n */\nexport const createEmpty = f => new Promise(f)\n\n/**\n * `Promise.all` wait for all promises in the array to resolve and return the result\n * @template {unknown[] | []} PS\n *\n * @param {PS} ps\n * @return {Promise<{ -readonly [P in keyof PS]: Awaited<PS[P]> }>}\n */\nexport const all = Promise.all.bind(Promise)\n\n/**\n * @param {Error} [reason]\n * @return {Promise<never>}\n */\nexport const reject = reason => Promise.reject(reason)\n\n/**\n * @template T\n * @param {T|void} res\n * @return {Promise<T|void>}\n */\nexport const resolve = res => Promise.resolve(res)\n\n/**\n * @template T\n * @param {T} res\n * @return {Promise<T>}\n */\nexport const resolveWith = res => Promise.resolve(res)\n\n/**\n * @todo Next version, reorder parameters: check, [timeout, [intervalResolution]]\n *\n * @param {number} timeout\n * @param {function():boolean} check\n * @param {number} [intervalResolution]\n * @return {Promise<void>}\n */\nexport const until = (timeout, check, intervalResolution = 10) => create((resolve, reject) => {\n  const startTime = time.getUnixTime()\n  const hasTimeout = timeout > 0\n  const untilInterval = () => {\n    if (check()) {\n      clearInterval(intervalHandle)\n      resolve()\n    } else if (hasTimeout) {\n      /* c8 ignore else */\n      if (time.getUnixTime() - startTime > timeout) {\n        clearInterval(intervalHandle)\n        reject(new Error('Timeout'))\n      }\n    }\n  }\n  const intervalHandle = setInterval(untilInterval, intervalResolution)\n})\n\n/**\n * @param {number} timeout\n * @return {Promise<undefined>}\n */\nexport const wait = timeout => create((resolve, reject) => setTimeout(resolve, timeout))\n\n/**\n * Checks if an object is a promise using ducktyping.\n *\n * Promises are often polyfilled, so it makes sense to add some additional guarantees if the user of this\n * library has some insane environment where global Promise objects are overwritten.\n *\n * @param {any} p\n * @return {boolean}\n */\nexport const isPromise = p => p instanceof Promise || (p && p.then && p.catch && p.finally)\n","/**\n * Utility module to work with key-value stores.\n *\n * @module map\n */\n\n/**\n * Creates a new Map instance.\n *\n * @function\n * @return {Map<any, any>}\n *\n * @function\n */\nexport const create = () => new Map()\n\n/**\n * Copy a Map object into a fresh Map object.\n *\n * @function\n * @template K,V\n * @param {Map<K,V>} m\n * @return {Map<K,V>}\n */\nexport const copy = m => {\n  const r = create()\n  m.forEach((v, k) => { r.set(k, v) })\n  return r\n}\n\n/**\n * Get map property. Create T if property is undefined and set T on map.\n *\n * ```js\n * const listeners = map.setIfUndefined(events, 'eventName', set.create)\n * listeners.add(listener)\n * ```\n *\n * @function\n * @template {Map<any, any>} MAP\n * @template {MAP extends Map<any,infer V> ? function():V : unknown} CF\n * @param {MAP} map\n * @param {MAP extends Map<infer K,any> ? K : unknown} key\n * @param {CF} createT\n * @return {ReturnType<CF>}\n */\nexport const setIfUndefined = (map, key, createT) => {\n  let set = map.get(key)\n  if (set === undefined) {\n    map.set(key, set = createT())\n  }\n  return set\n}\n\n/**\n * Creates an Array and populates it with the content of all key-value pairs using the `f(value, key)` function.\n *\n * @function\n * @template K\n * @template V\n * @template R\n * @param {Map<K,V>} m\n * @param {function(V,K):R} f\n * @return {Array<R>}\n */\nexport const map = (m, f) => {\n  const res = []\n  for (const [key, value] of m) {\n    res.push(f(value, key))\n  }\n  return res\n}\n\n/**\n * Tests whether any key-value pairs pass the test implemented by `f(value, key)`.\n *\n * @todo should rename to some - similarly to Array.some\n *\n * @function\n * @template K\n * @template V\n * @param {Map<K,V>} m\n * @param {function(V,K):boolean} f\n * @return {boolean}\n */\nexport const any = (m, f) => {\n  for (const [key, value] of m) {\n    if (f(value, key)) {\n      return true\n    }\n  }\n  return false\n}\n\n/**\n * Tests whether all key-value pairs pass the test implemented by `f(value, key)`.\n *\n * @function\n * @template K\n * @template V\n * @param {Map<K,V>} m\n * @param {function(V,K):boolean} f\n * @return {boolean}\n */\nexport const all = (m, f) => {\n  for (const [key, value] of m) {\n    if (!f(value, key)) {\n      return false\n    }\n  }\n  return true\n}\n","/**\n * Utility module to work with sets.\n *\n * @module set\n */\n\nexport const create = () => new Set()\n\n/**\n * @template T\n * @param {Set<T>} set\n * @return {Array<T>}\n */\nexport const toArray = set => Array.from(set)\n\n/**\n * @template T\n * @param {Set<T>} set\n * @return {T}\n */\nexport const first = set =>\n  set.values().next().value || undefined\n\n/**\n * @template T\n * @param {Iterable<T>} entries\n * @return {Set<T>}\n */\nexport const from = entries => new Set(entries)\n","/**\n * Utility module to work with Arrays.\n *\n * @module array\n */\n\nimport * as set from './set.js'\n\n/**\n * Return the last element of an array. The element must exist\n *\n * @template L\n * @param {ArrayLike<L>} arr\n * @return {L}\n */\nexport const last = arr => arr[arr.length - 1]\n\n/**\n * @template C\n * @return {Array<C>}\n */\nexport const create = () => /** @type {Array<C>} */ ([])\n\n/**\n * @template D\n * @param {Array<D>} a\n * @return {Array<D>}\n */\nexport const copy = a => /** @type {Array<D>} */ (a.slice())\n\n/**\n * Append elements from src to dest\n *\n * @template M\n * @param {Array<M>} dest\n * @param {Array<M>} src\n */\nexport const appendTo = (dest, src) => {\n  for (let i = 0; i < src.length; i++) {\n    dest.push(src[i])\n  }\n}\n\n/**\n * Transforms something array-like to an actual Array.\n *\n * @function\n * @template T\n * @param {ArrayLike<T>|Iterable<T>} arraylike\n * @return {T}\n */\nexport const from = Array.from\n\n/**\n * True iff condition holds on every element in the Array.\n *\n * @function\n * @template ITEM\n * @template {ArrayLike<ITEM>} ARR\n *\n * @param {ARR} arr\n * @param {function(ITEM, number, ARR):boolean} f\n * @return {boolean}\n */\nexport const every = (arr, f) => {\n  for (let i = 0; i < arr.length; i++) {\n    if (!f(arr[i], i, arr)) {\n      return false\n    }\n  }\n  return true\n}\n\n/**\n * True iff condition holds on some element in the Array.\n *\n * @function\n * @template S\n * @template {ArrayLike<S>} ARR\n * @param {ARR} arr\n * @param {function(S, number, ARR):boolean} f\n * @return {boolean}\n */\nexport const some = (arr, f) => {\n  for (let i = 0; i < arr.length; i++) {\n    if (f(arr[i], i, arr)) {\n      return true\n    }\n  }\n  return false\n}\n\n/**\n * @template ELEM\n *\n * @param {ArrayLike<ELEM>} a\n * @param {ArrayLike<ELEM>} b\n * @return {boolean}\n */\nexport const equalFlat = (a, b) => a.length === b.length && every(a, (item, index) => item === b[index])\n\n/**\n * @template ELEM\n * @param {Array<Array<ELEM>>} arr\n * @return {Array<ELEM>}\n */\nexport const flatten = arr => fold(arr, /** @type {Array<ELEM>} */ ([]), (acc, val) => acc.concat(val))\n\n/**\n * @template T\n * @param {number} len\n * @param {function(number, Array<T>):T} f\n * @return {Array<T>}\n */\nexport const unfold = (len, f) => {\n  const array = new Array(len)\n  for (let i = 0; i < len; i++) {\n    array[i] = f(i, array)\n  }\n  return array\n}\n\n/**\n * @template T\n * @template RESULT\n * @param {Array<T>} arr\n * @param {RESULT} seed\n * @param {function(RESULT, T, number):RESULT} folder\n */\nexport const fold = (arr, seed, folder) => arr.reduce(folder, seed)\n\nexport const isArray = Array.isArray\n\n/**\n * @template T\n * @param {Array<T>} arr\n * @return {Array<T>}\n */\nexport const unique = arr => from(set.from(arr))\n\n/**\n * @template T\n * @template M\n * @param {ArrayLike<T>} arr\n * @param {function(T):M} mapper\n * @return {Array<T>}\n */\nexport const uniqueBy = (arr, mapper) => {\n  /**\n   * @type {Set<M>}\n   */\n  const happened = set.create()\n  /**\n   * @type {Array<T>}\n   */\n  const result = []\n  for (let i = 0; i < arr.length; i++) {\n    const el = arr[i]\n    const mapped = mapper(el)\n    if (!happened.has(mapped)) {\n      happened.add(mapped)\n      result.push(el)\n    }\n  }\n  return result\n}\n\n/**\n * @template {ArrayLike<any>} ARR\n * @template {function(ARR extends ArrayLike<infer T> ? T : never, number, ARR):any} MAPPER\n * @param {ARR} arr\n * @param {MAPPER} mapper\n * @return {Array<MAPPER extends function(...any): infer M ? M : never>}\n */\nexport const map = (arr, mapper) => {\n  /**\n   * @type {Array<any>}\n   */\n  const res = Array(arr.length)\n  for (let i = 0; i < arr.length; i++) {\n    res[i] = mapper(/** @type {any} */ (arr[i]), i, /** @type {any} */ (arr))\n  }\n  return /** @type {any} */ (res)\n}\n","/**\n * Observable class prototype.\n *\n * @module observable\n */\n\nimport * as map from './map.js'\nimport * as set from './set.js'\nimport * as array from './array.js'\n\n/**\n * Handles named events.\n * @experimental\n *\n * This is basically a (better typed) duplicate of Observable, which will replace Observable in the\n * next release.\n *\n * @template {{[key in keyof EVENTS]: function(...any):void}} EVENTS\n */\nexport class ObservableV2 {\n  constructor () {\n    /**\n     * Some desc.\n     * @type {Map<string, Set<any>>}\n     */\n    this._observers = map.create()\n  }\n\n  /**\n   * @template {keyof EVENTS & string} NAME\n   * @param {NAME} name\n   * @param {EVENTS[NAME]} f\n   */\n  on (name, f) {\n    map.setIfUndefined(this._observers, /** @type {string} */ (name), set.create).add(f)\n    return f\n  }\n\n  /**\n   * @template {keyof EVENTS & string} NAME\n   * @param {NAME} name\n   * @param {EVENTS[NAME]} f\n   */\n  once (name, f) {\n    /**\n     * @param  {...any} args\n     */\n    const _f = (...args) => {\n      this.off(name, /** @type {any} */ (_f))\n      f(...args)\n    }\n    this.on(name, /** @type {any} */ (_f))\n  }\n\n  /**\n   * @template {keyof EVENTS & string} NAME\n   * @param {NAME} name\n   * @param {EVENTS[NAME]} f\n   */\n  off (name, f) {\n    const observers = this._observers.get(name)\n    if (observers !== undefined) {\n      observers.delete(f)\n      if (observers.size === 0) {\n        this._observers.delete(name)\n      }\n    }\n  }\n\n  /**\n   * Emit a named event. All registered event listeners that listen to the\n   * specified name will receive the event.\n   *\n   * @todo This should catch exceptions\n   *\n   * @template {keyof EVENTS & string} NAME\n   * @param {NAME} name The event name.\n   * @param {Parameters<EVENTS[NAME]>} args The arguments that are applied to the event listener.\n   */\n  emit (name, args) {\n    // copy all listeners to an array first to make sure that no event is emitted to listeners that are subscribed while the event handler is called.\n    return array.from((this._observers.get(name) || map.create()).values()).forEach(f => f(...args))\n  }\n\n  destroy () {\n    this._observers = map.create()\n  }\n}\n\n/* c8 ignore start */\n/**\n * Handles named events.\n *\n * @deprecated\n * @template N\n */\nexport class Observable {\n  constructor () {\n    /**\n     * Some desc.\n     * @type {Map<N, any>}\n     */\n    this._observers = map.create()\n  }\n\n  /**\n   * @param {N} name\n   * @param {function} f\n   */\n  on (name, f) {\n    map.setIfUndefined(this._observers, name, set.create).add(f)\n  }\n\n  /**\n   * @param {N} name\n   * @param {function} f\n   */\n  once (name, f) {\n    /**\n     * @param  {...any} args\n     */\n    const _f = (...args) => {\n      this.off(name, _f)\n      f(...args)\n    }\n    this.on(name, _f)\n  }\n\n  /**\n   * @param {N} name\n   * @param {function} f\n   */\n  off (name, f) {\n    const observers = this._observers.get(name)\n    if (observers !== undefined) {\n      observers.delete(f)\n      if (observers.size === 0) {\n        this._observers.delete(name)\n      }\n    }\n  }\n\n  /**\n   * Emit a named event. All registered event listeners that listen to the\n   * specified name will receive the event.\n   *\n   * @todo This should catch exceptions\n   *\n   * @param {N} name The event name.\n   * @param {Array<any>} args The arguments that are applied to the event listener.\n   */\n  emit (name, args) {\n    // copy all listeners to an array first to make sure that no event is emitted to listeners that are subscribed while the event handler is called.\n    return array.from((this._observers.get(name) || map.create()).values()).forEach(f => f(...args))\n  }\n\n  destroy () {\n    this._observers = map.create()\n  }\n}\n/* c8 ignore end */\n","import * as Y from \"yjs\";\nimport * as promise from \"lib0/promise\";\nimport { ObservableV2 } from \"lib0/observable\";\nimport { open, OPSQLiteConnection } from \"@op-engineering/op-sqlite\";\n\nexport const PREFERRED_TRIM_SIZE = 500;\n\nconst DB_PREFIX = \"opssqlite-persistence-\";\n\nexport class OPSQLitePersistence extends ObservableV2<{\n  synced: (persistence: OPSQLitePersistence) => void;\n}> {\n  doc: Y.Doc;\n  name: string;\n  whenSynced: Promise<this>;\n  db: OPSQLiteConnection;\n  synced: boolean = false;\n  _dbref = 0;\n  _dbsize = 0;\n  _destroyed = false;\n\n  constructor(name: string, doc: Y.Doc) {\n    super();\n    this.doc = doc;\n    this.name = name;\n\n    this.whenSynced = promise.create((resolve) =>\n      this.on(\"synced\", () => resolve(this))\n    );\n\n    this.db = open({ name: DB_PREFIX + name + \".sqlite\" });\n    this.db\n      .executeAsync(\n        \"CREATE TABLE IF NOT EXISTS updates (id INTEGER PRIMARY KEY, content BLOB)\"\n      )\n      .then(() => {\n        const s = Y.encodeStateAsUpdate(doc);\n        if (s.length > 0) {\n          this._storeUpdate(s, null);\n        }\n      })\n      .then(() =>\n        this.db\n          .executeAsync(\"SELECT content FROM updates\")\n          .catch((e) => console.error(\"error loading updates\", e))\n      )\n      .then((res) => {\n        if (res != undefined && res.rows != undefined) {\n          for (const row of res.rows._array) {\n            Y.applyUpdate(doc, new Uint8Array(row.content));\n          }\n        }\n\n        this.synced = true;\n        this.emit(\"synced\", [this]);\n      });\n\n    this.destroy = this.destroy.bind(this);\n    this._storeUpdate.bind(this);\n    doc.on(\"update\", this._storeUpdate.bind(this));\n    doc.on(\"destroy\", this.destroy.bind(this));\n  }\n  _storeUpdate(update: Uint8Array, origin: any) {\n    if (!this.db || origin == this) {\n      !this.db && console.error(\"trying to store update without db\");\n      return;\n    }\n\n    return this.db\n      .executeAsync(`INSERT INTO updates (content) VALUES (?)`, [update])\n      .catch((e) => console.error(\"error storing update\", e));\n  }\n\n  destroy() {\n    this.doc.off(\"update\", this._storeUpdate);\n    this.doc.off(\"destroy\", this.destroy);\n    this._destroyed = true;\n    return this.db.close();\n  }\n}\n"],"names":["create","f","setIfUndefined","map","key","createT","set","from","ObservableV2","map.create","name","map.setIfUndefined","set.create","_f","args","observers","array.from","PREFERRED_TRIM_SIZE","DB_PREFIX","OPSQLitePersistence","doc","__publicField","promise.create","resolve","open","s","Y","e","res","row","update","origin"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4]}