(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined'
    ? factory(exports)
    : typeof define === 'function' && define.amd
      ? define(['exports'], factory)
      : ((global =
          typeof globalThis !== 'undefined' ? globalThis : global || self),
        factory((global.TinyBasePersisterSqliteWasm = {})));
})(this, function (exports) {
  'use strict';

  const getTypeOf = (thing) => typeof thing;
  const TINYBASE = 'tinybase';
  const EMPTY_STRING = '';
  const COMMA = ',';
  const STRING = getTypeOf(EMPTY_STRING);
  const UNDEFINED = '\uFFFC';

  var __async$7 = (__this, __arguments, generator) => {
    return new Promise((resolve, reject) => {
      var fulfilled = (value) => {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      };
      var rejected = (value) => {
        try {
          step(generator.throw(value));
        } catch (e) {
          reject(e);
        }
      };
      var step = (x) =>
        x.done
          ? resolve(x.value)
          : Promise.resolve(x.value).then(fulfilled, rejected);
      step((generator = generator.apply(__this, __arguments)).next());
    });
  };
  const promise = Promise;
  const startInterval = (callback, sec, immediate) => {
    return setInterval(callback, sec * 1e3);
  };
  const stopInterval = clearInterval;
  const isUndefined = (thing) => thing == void 0;
  const ifNotUndefined = (value, then, otherwise) =>
    isUndefined(value)
      ? otherwise == null
        ? void 0
        : otherwise()
      : then(value);
  const isString = (thing) => getTypeOf(thing) == STRING;
  const isArray = (thing) => Array.isArray(thing);
  const slice = (arrayOrString, start, end) => arrayOrString.slice(start, end);
  const size = (arrayOrString) => arrayOrString.length;
  const promiseAll = (promises) =>
    __async$7(void 0, null, function* () {
      return promise.all(promises);
    });
  const errorNew = (message) => {
    throw new Error(message);
  };

  const arrayNew = (size2, cb) =>
    arrayMap(new Array(size2).fill(0), (_, index) => cb(index));
  const arrayJoin = (array, sep = EMPTY_STRING) => array.join(sep);
  const arrayMap = (array, cb) => array.map(cb);
  const arrayIsEmpty = (array) => size(array) == 0;
  const arrayFilter = (array, cb) => array.filter(cb);
  const arrayClear = (array, to) => array.splice(0, to);
  const arrayPush = (array, ...values) => array.push(...values);
  const arrayShift = (array) => array.shift();

  var __async$6 = (__this, __arguments, generator) => {
    return new Promise((resolve, reject) => {
      var fulfilled = (value) => {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      };
      var rejected = (value) => {
        try {
          step(generator.throw(value));
        } catch (e) {
          reject(e);
        }
      };
      var step = (x) =>
        x.done
          ? resolve(x.value)
          : Promise.resolve(x.value).then(fulfilled, rejected);
      step((generator = generator.apply(__this, __arguments)).next());
    });
  };
  const SINGLE_ROW_ID = '_';
  const DEFAULT_ROW_ID_COLUMN_NAME = '_id';
  const SELECT = 'SELECT';
  const WHERE = 'WHERE';
  const TABLE = 'TABLE';
  const ALTER_TABLE = 'ALTER ' + TABLE;
  const DELETE_FROM = 'DELETE FROM';
  const SELECT_STAR_FROM = SELECT + '*FROM';
  const PRAGMA = 'pragma_';
  const DATA_VERSION = 'data_version';
  const SCHEMA_VERSION = 'schema_version';
  const FROM = 'FROM ';
  const PRAGMA_TABLE = 'pragma_table_';
  const getWrappedCommand = (executeCommand, onSqlCommand) =>
    onSqlCommand
      ? (sql, params) =>
          __async$6(void 0, null, function* () {
            onSqlCommand(sql, params);
            return yield executeCommand(sql, params);
          })
      : executeCommand;
  const escapeId = (str) => `"${str.replace(/"/g, '""')}"`;
  const getPlaceholders = (array) =>
    arrayJoin(
      arrayMap(array, (_, index) => '$' + (index + 1)),
      COMMA,
    );

  const collHas = (coll, keyOrValue) => {
    var _a;
    return (_a = coll == null ? void 0 : coll.has(keyOrValue)) != null
      ? _a
      : false;
  };
  const collValues = (coll) => {
    var _a;
    return [
      ...((_a = coll == null ? void 0 : coll.values()) != null ? _a : []),
    ];
  };
  const collClear = (coll) => coll.clear();
  const collDel = (coll, keyOrValue) =>
    coll == null ? void 0 : coll.delete(keyOrValue);

  const object = Object;
  const getPrototypeOf = (obj) => object.getPrototypeOf(obj);
  const objEntries = object.entries;
  const isObject = (obj) =>
    !isUndefined(obj) &&
    ifNotUndefined(
      getPrototypeOf(obj),
      (objPrototype) =>
        objPrototype == object.prototype ||
        isUndefined(getPrototypeOf(objPrototype)),

      /* istanbul ignore next */
      () => true,
    );
  const objIds = object.keys;
  const objFreeze = object.freeze;
  const objNew = (entries = []) => object.fromEntries(entries);
  const objMerge = (...objs) => object.assign({}, ...objs);
  const objHas = (obj, id) => id in obj;
  const objDel = (obj, id) => {
    delete obj[id];
    return obj;
  };
  const objToArray = (obj, cb) =>
    arrayMap(objEntries(obj), ([id, value]) => cb(value, id));
  const objMap = (obj, cb) =>
    objNew(objToArray(obj, (value, id) => [id, cb(value, id)]));
  const objValues = (obj) => object.values(obj);
  const objSize = (obj) => size(objIds(obj));
  const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;

  const jsonString = JSON.stringify;
  const jsonParse = JSON.parse;
  const jsonStringWithUndefined = (obj) =>
    jsonString(obj, (_key, value) => (value === void 0 ? UNDEFINED : value));
  const jsonParseWithUndefined = (str) =>
    jsonParse(str, (_key, value) => (value === UNDEFINED ? void 0 : value));

  const mapNew = (entries) => new Map(entries);
  const mapGet = (map, key) => (map == null ? void 0 : map.get(key));
  const mapMap = (coll, cb) => {
    var _a;
    return arrayMap(
      [...((_a = coll == null ? void 0 : coll.entries()) != null ? _a : [])],
      ([key, value]) => cb(value, key),
    );
  };
  const mapSet = (map, key, value) =>
    isUndefined(value)
      ? (collDel(map, key), map)
      : map == null
        ? void 0
        : map.set(key, value);
  const mapEnsure = (map, key, getDefaultValue, hadExistingValue) => {
    if (!collHas(map, key)) {
      mapSet(map, key, getDefaultValue());
    }
    return mapGet(map, key);
  };

  var __defProp$1 = Object.defineProperty;
  var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
  var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
  var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
  var __defNormalProp$1 = (obj, key, value) =>
    key in obj
      ? __defProp$1(obj, key, {
          enumerable: true,
          configurable: true,
          writable: true,
          value,
        })
      : (obj[key] = value);
  var __spreadValues$1 = (a, b) => {
    for (var prop in b || (b = {}))
      if (__hasOwnProp$1.call(b, prop)) __defNormalProp$1(a, prop, b[prop]);
    if (__getOwnPropSymbols$1)
      for (var prop of __getOwnPropSymbols$1(b)) {
        if (__propIsEnum$1.call(b, prop)) __defNormalProp$1(a, prop, b[prop]);
      }
    return a;
  };
  var __async$5 = (__this, __arguments, generator) => {
    return new Promise((resolve, reject) => {
      var fulfilled = (value) => {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      };
      var rejected = (value) => {
        try {
          step(generator.throw(value));
        } catch (e) {
          reject(e);
        }
      };
      var step = (x) =>
        x.done
          ? resolve(x.value)
          : Promise.resolve(x.value).then(fulfilled, rejected);
      step((generator = generator.apply(__this, __arguments)).next());
    });
  };
  const scheduleRunning = mapNew();
  const scheduleActions = mapNew();
  const getStoreFunctions = (persist = 1 /* StoreOnly */, store) =>
    persist != 1 /* StoreOnly */ && store.isMergeable()
      ? [
          1,
          store.getMergeableContent,
          store.getTransactionMergeableChanges,
          ([[changedTables], [changedValues]]) =>
            !objIsEmpty(changedTables) || !objIsEmpty(changedValues),
          store.setDefaultContent,
        ]
      : persist != 2 /* MergeableStoreOnly */
        ? [
            0,
            store.getContent,
            store.getTransactionChanges,
            ([changedTables, changedValues]) =>
              !objIsEmpty(changedTables) || !objIsEmpty(changedValues),
            store.setContent,
          ]
        : errorNew('Store type not supported by this Persister');
  const createCustomPersister = (
    store,
    getPersisted,
    setPersisted,
    addPersisterListener,
    delPersisterListener,
    onIgnoredError,
    persist,
    extra = {},
    scheduleId = [],
  ) => {
    let loadSave = 0;
    let loads = 0;
    let saves = 0;
    let action;
    let autoLoadHandle;
    let autoSaveListenerId;
    mapEnsure(scheduleRunning, scheduleId, () => 0);
    mapEnsure(scheduleActions, scheduleId, () => []);
    const [
      isMergeableStore,
      getContent,
      getChanges,
      hasChanges,
      setDefaultContent,
    ] = getStoreFunctions(persist, store);
    const run = () =>
      __async$5(void 0, null, function* () {
        /* istanbul ignore else */
        if (!mapGet(scheduleRunning, scheduleId)) {
          mapSet(scheduleRunning, scheduleId, 1);
          while (
            !isUndefined(
              (action = arrayShift(mapGet(scheduleActions, scheduleId))),
            )
          ) {
            try {
              yield action();
            } catch (error) {
              /* istanbul ignore next */
              onIgnoredError == null ? void 0 : onIgnoredError(error);
            }
          }
          mapSet(scheduleRunning, scheduleId, 0);
        }
      });
    const setContentOrChanges = (contentOrChanges) => {
      (isMergeableStore &&
        isArray(contentOrChanges == null ? void 0 : contentOrChanges[0])
        ? (contentOrChanges == null ? void 0 : contentOrChanges[2]) === 1
          ? store.applyMergeableChanges
          : store.setMergeableContent
        : (contentOrChanges == null ? void 0 : contentOrChanges[2]) === 1
          ? store.applyChanges
          : store.setContent)(contentOrChanges);
    };
    const load = (initialContent) =>
      __async$5(void 0, null, function* () {
        /* istanbul ignore else */
        if (loadSave != 2) {
          loadSave = 1;
          loads++;
          yield schedule(() =>
            __async$5(void 0, null, function* () {
              try {
                const content = yield getPersisted();
                if (isArray(content)) {
                  setContentOrChanges(content);
                } else {
                  errorNew(`Content is not an array ${content}`);
                }
              } catch (error) {
                onIgnoredError == null ? void 0 : onIgnoredError(error);
                if (initialContent) {
                  setDefaultContent(initialContent);
                }
              }
              loadSave = 0;
            }),
          );
        }
        return persister;
      });
    const startAutoLoad = (initialContent) =>
      __async$5(void 0, null, function* () {
        yield stopAutoLoad().load(initialContent);
        try {
          autoLoadHandle = yield addPersisterListener((content, changes) =>
            __async$5(void 0, null, function* () {
              if (changes || content) {
                /* istanbul ignore else */
                if (loadSave != 2) {
                  loadSave = 1;
                  loads++;
                  setContentOrChanges(changes != null ? changes : content);
                  loadSave = 0;
                }
              } else {
                yield load();
              }
            }),
          );
        } catch (error) {
          /* istanbul ignore next */
          onIgnoredError == null ? void 0 : onIgnoredError(error);
        }
        return persister;
      });
    const stopAutoLoad = () => {
      if (autoLoadHandle) {
        delPersisterListener(autoLoadHandle);
        autoLoadHandle = void 0;
      }
      return persister;
    };
    const isAutoLoading = () => !isUndefined(autoLoadHandle);
    const save = (changes) =>
      __async$5(void 0, null, function* () {
        /* istanbul ignore else */
        if (loadSave != 1) {
          loadSave = 2;
          saves++;
          yield schedule(() =>
            __async$5(void 0, null, function* () {
              try {
                yield setPersisted(getContent, changes);
              } catch (error) {
                /* istanbul ignore next */
                onIgnoredError == null ? void 0 : onIgnoredError(error);
              }
              loadSave = 0;
            }),
          );
        }
        return persister;
      });
    const startAutoSave = () =>
      __async$5(void 0, null, function* () {
        yield stopAutoSave().save();
        autoSaveListenerId = store.addDidFinishTransactionListener(() => {
          const changes = getChanges();
          if (hasChanges(changes)) {
            save(changes);
          }
        });
        return persister;
      });
    const stopAutoSave = () => {
      ifNotUndefined(autoSaveListenerId, store.delListener);
      autoSaveListenerId = void 0;
      return persister;
    };
    const isAutoSaving = () => !isUndefined(autoSaveListenerId);
    const schedule = (...actions) =>
      __async$5(void 0, null, function* () {
        arrayPush(mapGet(scheduleActions, scheduleId), ...actions);
        yield run();
        return persister;
      });
    const getStore = () => store;
    const destroy = () => {
      arrayClear(mapGet(scheduleActions, scheduleId));
      return stopAutoLoad().stopAutoSave();
    };
    const getStats = () => ({loads, saves});
    const persister = __spreadValues$1(
      {
        load,
        startAutoLoad,
        stopAutoLoad,
        isAutoLoading,
        save,
        startAutoSave,
        stopAutoSave,
        isAutoSaving,
        schedule,
        getStore,
        destroy,
        getStats,
      },
      extra,
    );
    return objFreeze(persister);
  };

  const setNew = (entryOrEntries) =>
    new Set(
      isArray(entryOrEntries) || isUndefined(entryOrEntries)
        ? entryOrEntries
        : [entryOrEntries],
    );
  const setAdd = (set, value) => (set == null ? void 0 : set.add(value));

  var __async$4 = (__this, __arguments, generator) => {
    return new Promise((resolve, reject) => {
      var fulfilled = (value) => {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      };
      var rejected = (value) => {
        try {
          step(generator.throw(value));
        } catch (e) {
          reject(e);
        }
      };
      var step = (x) =>
        x.done
          ? resolve(x.value)
          : Promise.resolve(x.value).then(fulfilled, rejected);
      step((generator = generator.apply(__this, __arguments)).next());
    });
  };
  const getCommandFunctions = (
    databaseExecuteCommand,
    managedTableNames,
    querySchema,
    onIgnoredError,
    columnType,
    orReplace,
    encode,
    decode,
  ) => {
    const schemaMap = mapNew();
    const canSelect = (tableName, rowIdColumnName) =>
      collHas(mapGet(schemaMap, tableName), rowIdColumnName);
    const refreshSchema = () =>
      __async$4(void 0, null, function* () {
        collClear(schemaMap);
        arrayMap(
          yield querySchema(databaseExecuteCommand, managedTableNames),
          ({tn, cn}) => setAdd(mapEnsure(schemaMap, tn, setNew), cn),
        );
      });
    const loadTable = (tableName, rowIdColumnName) =>
      __async$4(void 0, null, function* () {
        return canSelect(tableName, rowIdColumnName)
          ? objNew(
              arrayFilter(
                arrayMap(
                  yield databaseExecuteCommand(
                    SELECT_STAR_FROM + escapeId(tableName),
                  ),
                  (row) => [
                    row[rowIdColumnName],
                    decode
                      ? objMap(objDel(row, rowIdColumnName), decode)
                      : objDel(row, rowIdColumnName),
                  ],
                ),
                ([rowId, row]) => !isUndefined(rowId) && !objIsEmpty(row),
              ),
            )
          : {};
      });
    const saveTable = (
      tableName,
      rowIdColumnName,
      content,
      deleteEmptyColumns,
      deleteEmptyTable,
      partial = false,
    ) =>
      __async$4(void 0, null, function* () {
        const tableCellOrValueIds = setNew();
        objToArray(content != null ? content : {}, (contentRow) =>
          arrayMap(
            objIds(contentRow != null ? contentRow : {}),
            (cellOrValueId) => setAdd(tableCellOrValueIds, cellOrValueId),
          ),
        );
        const tableColumnNames = collValues(tableCellOrValueIds);
        if (
          !partial &&
          deleteEmptyTable &&
          arrayIsEmpty(tableColumnNames) &&
          collHas(schemaMap, tableName)
        ) {
          yield databaseExecuteCommand('DROP ' + TABLE + escapeId(tableName));
          mapSet(schemaMap, tableName);
          return;
        }
        const tableSchemaColumns = mapGet(schemaMap, tableName);
        const currentColumnNames = setNew(collValues(tableSchemaColumns));
        if (!arrayIsEmpty(tableColumnNames)) {
          if (!collHas(schemaMap, tableName)) {
            yield databaseExecuteCommand(
              'CREATE ' +
                TABLE +
                escapeId(tableName) +
                `(${escapeId(rowIdColumnName)}${columnType} PRIMARY KEY${arrayJoin(
                  arrayMap(
                    tableColumnNames,
                    (columnName) => COMMA + escapeId(columnName) + columnType,
                  ),
                )});`,
            );
            mapSet(
              schemaMap,
              tableName,
              setNew([rowIdColumnName, ...tableColumnNames]),
            );
          } else {
            yield promiseAll(
              arrayMap(
                [rowIdColumnName, ...tableColumnNames],
                (columnName, index) =>
                  __async$4(void 0, null, function* () {
                    if (!collDel(currentColumnNames, columnName)) {
                      yield databaseExecuteCommand(
                        ALTER_TABLE +
                          escapeId(tableName) +
                          'ADD' +
                          escapeId(columnName) +
                          columnType,
                      );
                      if (index == 0) {
                        yield databaseExecuteCommand(
                          'CREATE UNIQUE INDEX pk ON ' +
                            escapeId(tableName) +
                            `(${escapeId(rowIdColumnName)})`,
                        );
                      }
                      setAdd(tableSchemaColumns, columnName);
                    }
                  }),
              ),
            );
          }
        }
        yield promiseAll([
          ...(!partial && deleteEmptyColumns
            ? arrayMap(collValues(currentColumnNames), (columnName) =>
                __async$4(void 0, null, function* () {
                  if (columnName != rowIdColumnName) {
                    yield databaseExecuteCommand(
                      ALTER_TABLE +
                        escapeId(tableName) +
                        'DROP' +
                        escapeId(columnName),
                    );
                    collDel(tableSchemaColumns, columnName);
                  }
                }),
              )
            : []),
        ]);
        if (partial) {
          if (isUndefined(content)) {
            yield databaseExecuteCommand(
              DELETE_FROM + escapeId(tableName) + WHERE + ' true',
            );
          } else {
            yield promiseAll(
              objToArray(content, (row, rowId) =>
                __async$4(void 0, null, function* () {
                  if (isUndefined(row)) {
                    yield databaseExecuteCommand(
                      DELETE_FROM +
                        escapeId(tableName) +
                        WHERE +
                        escapeId(rowIdColumnName) +
                        '=$1',
                      [rowId],
                    );
                  } else if (!arrayIsEmpty(tableColumnNames)) {
                    yield upsert(
                      databaseExecuteCommand,
                      tableName,
                      rowIdColumnName,
                      objIds(row),
                      [
                        rowId,
                        ...(encode
                          ? arrayMap(objValues(row), encode)
                          : objValues(row)),
                      ],
                      orReplace,
                    );
                  }
                }),
              ),
            );
          }
        } else {
          if (!arrayIsEmpty(tableColumnNames)) {
            const changingColumnNames = arrayFilter(
              collValues(mapGet(schemaMap, tableName)),
              (columnName) => columnName != rowIdColumnName,
            );
            const params = [];
            const deleteRowIds = [];
            objToArray(content != null ? content : {}, (row, rowId) => {
              arrayPush(
                params,
                rowId,
                ...arrayMap(changingColumnNames, (cellId) =>
                  encode
                    ? encode(row == null ? void 0 : row[cellId])
                    : row == null
                      ? void 0
                      : row[cellId],
                ),
              );
              arrayPush(deleteRowIds, rowId);
            });
            yield upsert(
              databaseExecuteCommand,
              tableName,
              rowIdColumnName,
              changingColumnNames,
              params,
              orReplace,
            );
            yield databaseExecuteCommand(
              DELETE_FROM +
                escapeId(tableName) +
                WHERE +
                escapeId(rowIdColumnName) +
                `NOT IN(${getPlaceholders(deleteRowIds)})`,
              deleteRowIds,
            );
          } else if (collHas(schemaMap, tableName)) {
            yield databaseExecuteCommand(
              DELETE_FROM + escapeId(tableName) + WHERE + ' true',
            );
          }
        }
      });
    const transaction = (actions) =>
      __async$4(void 0, null, function* () {
        let result;
        yield databaseExecuteCommand('BEGIN');
        try {
          result = yield actions();
        } catch (error) {
          onIgnoredError == null ? void 0 : onIgnoredError(error);
        }
        yield databaseExecuteCommand('END');
        return result;
      });
    return [refreshSchema, loadTable, saveTable, transaction];
  };
  const upsert = (
    executeCommand,
    tableName,
    rowIdColumnName,
    changingColumnNames,
    params,
    orReplace = 0,
  ) =>
    __async$4(void 0, null, function* () {
      return yield executeCommand(
        'INSERT ' +
          (orReplace ? 'OR REPLACE ' : EMPTY_STRING) +
          'INTO' +
          escapeId(tableName) +
          '(' +
          escapeId(rowIdColumnName) +
          arrayJoin(
            arrayMap(
              changingColumnNames,
              (columnName) => COMMA + escapeId(columnName),
            ),
          ) +
          ')VALUES' +
          getUpsertPlaceholders(params, size(changingColumnNames) + 1) +
          (orReplace
            ? EMPTY_STRING
            : 'ON CONFLICT(' +
              escapeId(rowIdColumnName) +
              ')DO UPDATE SET' +
              arrayJoin(
                arrayMap(
                  changingColumnNames,
                  (columnName) =>
                    escapeId(columnName) + '=excluded.' + escapeId(columnName),
                ),
                COMMA,
              )),
        arrayMap(params, (param) => (param != null ? param : null)),
      );
    });
  const getUpsertPlaceholders = (array, columnCount) =>
    arrayJoin(
      arrayNew(
        size(array) / columnCount,
        (row) =>
          '(' +
          arrayJoin(
            arrayNew(
              columnCount,
              (column) => '$' + (row * columnCount + column + 1),
            ),
            COMMA,
          ) +
          ')',
      ),
      COMMA,
    );

  var __async$3 = (__this, __arguments, generator) => {
    return new Promise((resolve, reject) => {
      var fulfilled = (value) => {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      };
      var rejected = (value) => {
        try {
          step(generator.throw(value));
        } catch (e) {
          reject(e);
        }
      };
      var step = (x) =>
        x.done
          ? resolve(x.value)
          : Promise.resolve(x.value).then(fulfilled, rejected);
      step((generator = generator.apply(__this, __arguments)).next());
    });
  };
  const createJsonPersister = (
    store,
    executeCommand,
    addPersisterListener,
    delPersisterListener,
    onIgnoredError,
    destroyImpl,
    persist,
    [storeTableName, storeIdColumnName, storeColumnName],
    managedTableNames,
    querySchema,
    thing,
    getThing,
    columnType,
    orReplace,
  ) => {
    const [refreshSchema, loadTable, saveTable, transaction] =
      getCommandFunctions(
        executeCommand,
        managedTableNames,
        querySchema,
        onIgnoredError,
        columnType,
        orReplace,
      );
    const getPersisted = () =>
      __async$3(void 0, null, function* () {
        return yield transaction(() =>
          __async$3(void 0, null, function* () {
            var _a, _b;
            yield refreshSchema();
            return jsonParseWithUndefined(
              (_b =
                (_a = (yield loadTable(storeTableName, storeIdColumnName))[
                  SINGLE_ROW_ID
                ]) == null
                  ? void 0
                  : _a[storeColumnName]) != null
                ? _b
                : 'null',
            );
          }),
        );
      });
    const setPersisted = (getContent) =>
      __async$3(void 0, null, function* () {
        return yield transaction(() =>
          __async$3(void 0, null, function* () {
            var _a;
            yield refreshSchema();
            yield saveTable(
              storeTableName,
              storeIdColumnName,
              {
                [SINGLE_ROW_ID]: {
                  [storeColumnName]: jsonStringWithUndefined(
                    (_a = getContent()) != null ? _a : null,
                  ),
                },
              },
              true,
              true,
            );
          }),
        );
      });
    const destroy = () => {
      persister.stopAutoLoad().stopAutoSave();
      destroyImpl();
      return persister;
    };
    const persister = createCustomPersister(
      store,
      getPersisted,
      setPersisted,
      addPersisterListener,
      delPersisterListener,
      onIgnoredError,
      persist,
      {[getThing]: () => thing, destroy},
      thing,
    );
    return persister;
  };

  var __async$2 = (__this, __arguments, generator) => {
    return new Promise((resolve, reject) => {
      var fulfilled = (value) => {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      };
      var rejected = (value) => {
        try {
          step(generator.throw(value));
        } catch (e) {
          reject(e);
        }
      };
      var step = (x) =>
        x.done
          ? resolve(x.value)
          : Promise.resolve(x.value).then(fulfilled, rejected);
      step((generator = generator.apply(__this, __arguments)).next());
    });
  };
  const createTabularPersister = (
    store,
    executeCommand,
    addPersisterListener,
    delPersisterListener,
    onIgnoredError,
    destroyImpl,
    persist,
    [
      tablesLoadConfig,
      tablesSaveConfig,
      [valuesLoad, valuesSave, valuesTableName],
    ],
    managedTableNames,
    querySchema,
    thing,
    getThing,
    columnType,
    orReplace,
    encode,
    decode,
  ) => {
    const [refreshSchema, loadTable, saveTable, transaction] =
      getCommandFunctions(
        executeCommand,
        managedTableNames,
        querySchema,
        onIgnoredError,
        columnType,
        orReplace,
        encode,
        decode,
      );
    const saveTables = (tables, partial) =>
      __async$2(void 0, null, function* () {
        return yield promiseAll(
          mapMap(tablesSaveConfig, (_0, _1) =>
            __async$2(
              void 0,
              [_0, _1],
              function* (
                [
                  tableName,
                  rowIdColumnName,
                  deleteEmptyColumns,
                  deleteEmptyTable,
                ],
                tableId,
              ) {
                if (!partial || objHas(tables, tableId)) {
                  yield saveTable(
                    tableName,
                    rowIdColumnName,
                    tables[tableId],
                    deleteEmptyColumns,
                    deleteEmptyTable,
                    partial,
                  );
                }
              },
            ),
          ),
        );
      });
    const saveValues = (values, partial) =>
      __async$2(void 0, null, function* () {
        return valuesSave
          ? yield saveTable(
              valuesTableName,
              DEFAULT_ROW_ID_COLUMN_NAME,
              {[SINGLE_ROW_ID]: values},
              true,
              true,
              partial,
            )
          : null;
      });
    const loadTables = () =>
      __async$2(void 0, null, function* () {
        return objNew(
          arrayFilter(
            yield promiseAll(
              mapMap(tablesLoadConfig, (_0, _1) =>
                __async$2(
                  void 0,
                  [_0, _1],
                  function* ([tableId, rowIdColumnName], tableName) {
                    return [
                      tableId,
                      yield loadTable(tableName, rowIdColumnName),
                    ];
                  },
                ),
              ),
            ),
            (pair) => !objIsEmpty(pair[1]),
          ),
        );
      });
    const loadValues = () =>
      __async$2(void 0, null, function* () {
        return valuesLoad
          ? (yield loadTable(valuesTableName, DEFAULT_ROW_ID_COLUMN_NAME))[
              SINGLE_ROW_ID
            ]
          : {};
      });
    const getPersisted = () =>
      __async$2(void 0, null, function* () {
        return yield transaction(() =>
          __async$2(void 0, null, function* () {
            yield refreshSchema();
            const tables = yield loadTables();
            const values = yield loadValues();
            return !objIsEmpty(tables) || !isUndefined(values)
              ? [tables, values]
              : void 0;
          }),
        );
      });
    const setPersisted = (getContent, changes) =>
      __async$2(void 0, null, function* () {
        return yield transaction(() =>
          __async$2(void 0, null, function* () {
            yield refreshSchema();
            if (!isUndefined(changes)) {
              yield saveTables(changes[0], true);
              yield saveValues(changes[1], true);
            } else {
              const [tables, values] = getContent();
              yield saveTables(tables);
              yield saveValues(values);
            }
          }),
        );
      });
    const destroy = () => {
      persister.stopAutoLoad().stopAutoSave();
      destroyImpl();
      return persister;
    };
    const persister = createCustomPersister(
      store,
      getPersisted,
      setPersisted,
      addPersisterListener,
      delPersisterListener,
      onIgnoredError,
      persist,
      {[getThing]: () => thing, destroy},
      thing,
    );
    return persister;
  };

  const COLUMN_NAME = 'ColumnName';
  const STORE = 'store';
  const JSON$1 = 'json';
  const STORE_TABLE_NAME = STORE + 'TableName';
  const STORE_ID_COLUMN_NAME = STORE + 'Id' + COLUMN_NAME;
  const STORE_COLUMN_NAME = STORE + COLUMN_NAME;
  const AUTO_LOAD_INTERVAL_SECONDS = 'autoLoadIntervalSeconds';
  const ROW_ID_COLUMN_NAME = 'rowId' + COLUMN_NAME;
  const TABLE_ID = 'tableId';
  const TABLE_NAME = 'tableName';
  const DELETE_EMPTY_COLUMNS = 'deleteEmptyColumns';
  const DELETE_EMPTY_TABLE = 'deleteEmptyTable';
  const DEFAULT_CONFIG = {
    mode: JSON$1,
    [AUTO_LOAD_INTERVAL_SECONDS]: 1,
  };
  const DEFAULT_TABULAR_VALUES_CONFIG = {
    load: 0,
    save: 0,
    [TABLE_NAME]: TINYBASE + '_values',
  };
  const getDefaultedConfig = (configOrStoreTableName) =>
    objMerge(
      DEFAULT_CONFIG,
      isString(configOrStoreTableName)
        ? {[STORE_TABLE_NAME]: configOrStoreTableName}
        : configOrStoreTableName != null
          ? configOrStoreTableName
          : {},
    );
  const getDefaultedTabularConfigMap = (
    configsObj,
    defaultObj,
    tableField,
    exclude,
    then,
  ) => {
    const configMap = mapNew();
    objToArray(configsObj, (configObj, id) => {
      const defaultedConfig = slice(
        objValues(
          objMerge(
            defaultObj,
            isString(configObj) ? {[tableField]: configObj} : configObj,
          ),
        ),
        0,
        objSize(defaultObj),
      );
      if (
        !isUndefined(defaultedConfig[0]) &&
        !exclude(id, defaultedConfig[0])
      ) {
        then(id, defaultedConfig[0]);
        mapSet(configMap, id, defaultedConfig);
      }
    });
    return configMap;
  };
  const getConfigStructures = (configOrStoreTableName) => {
    var _a, _b, _c;
    const config = getDefaultedConfig(configOrStoreTableName);
    const autoLoadIntervalSeconds = config[AUTO_LOAD_INTERVAL_SECONDS];
    if (config.mode == JSON$1) {
      const storeTableName =
        (_a = config[STORE_TABLE_NAME]) != null ? _a : TINYBASE;
      return [
        1,
        autoLoadIntervalSeconds,
        [
          storeTableName,
          (_b = config[STORE_ID_COLUMN_NAME]) != null
            ? _b
            : DEFAULT_ROW_ID_COLUMN_NAME,
          (_c = config[STORE_COLUMN_NAME]) != null ? _c : STORE,
        ],
        setNew(storeTableName),
      ];
    }
    const {tables: {load = {}, save = {}} = {}, values = {}} = config;
    const valuesConfig = slice(
      objValues(objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values)),
      0,
      objSize(DEFAULT_TABULAR_VALUES_CONFIG),
    );
    const valuesTable = valuesConfig[2];
    const managedTableNames = setNew(valuesTable);
    const excludedTableNames = setNew(valuesTable);
    const tabularConfig = [
      getDefaultedTabularConfigMap(
        load,
        {[TABLE_ID]: null, [ROW_ID_COLUMN_NAME]: DEFAULT_ROW_ID_COLUMN_NAME},
        TABLE_ID,
        (tableName) => collHas(excludedTableNames, tableName),
        (tableName) => setAdd(managedTableNames, tableName),
      ),
      getDefaultedTabularConfigMap(
        save,
        {
          [TABLE_NAME]: null,
          [ROW_ID_COLUMN_NAME]: DEFAULT_ROW_ID_COLUMN_NAME,
          [DELETE_EMPTY_COLUMNS]: 0,
          [DELETE_EMPTY_TABLE]: 0,
        },
        TABLE_NAME,
        (_, tableName) => collHas(excludedTableNames, tableName),
        (_, tableName) => setAdd(managedTableNames, tableName),
      ),
      valuesConfig,
    ];
    return [0, autoLoadIntervalSeconds, tabularConfig, managedTableNames];
  };

  var __async$1 = (__this, __arguments, generator) => {
    return new Promise((resolve, reject) => {
      var fulfilled = (value) => {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      };
      var rejected = (value) => {
        try {
          step(generator.throw(value));
        } catch (e) {
          reject(e);
        }
      };
      var step = (x) =>
        x.done
          ? resolve(x.value)
          : Promise.resolve(x.value).then(fulfilled, rejected);
      step((generator = generator.apply(__this, __arguments)).next());
    });
  };
  const createCustomSqlitePersister = (
    store,
    configOrStoreTableName,
    rawExecuteCommand,
    addChangeListener,
    delChangeListener,
    onSqlCommand,
    onIgnoredError,
    destroy,
    persist,
    thing,
    getThing = 'getDb',
    orReplace,
  ) => {
    let dataVersion;
    let schemaVersion;
    let totalChanges;
    const executeCommand = getWrappedCommand(rawExecuteCommand, onSqlCommand);
    const [
      isJson,
      autoLoadIntervalSeconds,
      defaultedConfig,
      managedTableNamesSet,
    ] = getConfigStructures(configOrStoreTableName);
    const addPersisterListener = (listener) => {
      let interval;
      const startPolling = () =>
        (interval = startInterval(
          () =>
            __async$1(void 0, null, function* () {
              try {
                const [{d, s, c}] = yield executeCommand(
                  // eslint-disable-next-line max-len
                  `${SELECT} ${DATA_VERSION} d,${SCHEMA_VERSION} s,TOTAL_CHANGES() c FROM ${PRAGMA}${DATA_VERSION} JOIN ${PRAGMA}${SCHEMA_VERSION}`,
                );
                if (
                  d != dataVersion ||
                  s != schemaVersion ||
                  c != totalChanges
                ) {
                  if (dataVersion != null) {
                    listener();
                  }
                  dataVersion = d;
                  schemaVersion = s;
                  totalChanges = c;
                }
              } catch (e) {}
            }),
          autoLoadIntervalSeconds,
        ));
      const stopPolling = () => {
        dataVersion = schemaVersion = totalChanges = null;
        stopInterval(interval);
      };
      const listeningHandle = addChangeListener((tableName) => {
        if (managedTableNamesSet.has(tableName)) {
          stopPolling();
          listener();
          startPolling();
        }
      });
      startPolling();
      return () => {
        stopPolling();
        delChangeListener(listeningHandle);
      };
    };
    const delPersisterListener = (stopPollingAndDelUpdateListener) =>
      stopPollingAndDelUpdateListener();
    return (isJson ? createJsonPersister : createTabularPersister)(
      store,
      executeCommand,
      addPersisterListener,
      delPersisterListener,
      onIgnoredError,
      destroy,
      persist,
      defaultedConfig,
      collValues(managedTableNamesSet),
      (executeCommand2, managedTableNames) =>
        __async$1(void 0, null, function* () {
          return yield executeCommand2(
            // eslint-disable-next-line max-len
            `${SELECT} t.name tn,c.name cn ${FROM}${PRAGMA_TABLE}list()t,${PRAGMA_TABLE}info(t.name)c ${WHERE} t.schema='main'AND t.type IN('table','view')AND t.name IN(${getPlaceholders(managedTableNames)})ORDER BY t.name,c.name`,
            managedTableNames,
          );
        }),
      thing,
      getThing,
      EMPTY_STRING,
      orReplace,
      (cellOrValue) =>
        cellOrValue === true ? 1 : cellOrValue === false ? 0 : cellOrValue,
      void 0,
    );
  };

  var __defProp = Object.defineProperty;
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
  var __hasOwnProp = Object.prototype.hasOwnProperty;
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
  var __defNormalProp = (obj, key, value) =>
    key in obj
      ? __defProp(obj, key, {
          enumerable: true,
          configurable: true,
          writable: true,
          value,
        })
      : (obj[key] = value);
  var __spreadValues = (a, b) => {
    for (var prop in b || (b = {}))
      if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]);
    if (__getOwnPropSymbols)
      for (var prop of __getOwnPropSymbols(b)) {
        if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]);
      }
    return a;
  };
  var __async = (__this, __arguments, generator) => {
    return new Promise((resolve, reject) => {
      var fulfilled = (value) => {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      };
      var rejected = (value) => {
        try {
          step(generator.throw(value));
        } catch (e) {
          reject(e);
        }
      };
      var step = (x) =>
        x.done
          ? resolve(x.value)
          : Promise.resolve(x.value).then(fulfilled, rejected);
      step((generator = generator.apply(__this, __arguments)).next());
    });
  };
  const createSqliteWasmPersister = (
    store,
    sqlite3,
    db,
    configOrStoreTableName,
    onSqlCommand,
    onIgnoredError,
  ) =>
    createCustomSqlitePersister(
      store,
      configOrStoreTableName,
      (_0, ..._1) =>
        __async(void 0, [_0, ..._1], function* (sql, params = []) {
          return db
            .exec(sql, {
              bind: params,
              rowMode: 'object',
              returnValue: 'resultRows',
            })
            .map((row) => __spreadValues({}, row));
        }),
      (listener) =>
        sqlite3.capi.sqlite3_update_hook(
          db,
          (_, _2, _3, tableName) => listener(tableName),
          0,
        ),
      () => sqlite3.capi.sqlite3_update_hook(db, () => 0, 0),
      onSqlCommand,
      onIgnoredError,
      () => 0,
      3,
      // StoreOrMergeableStore,
      db,
    );

  exports.createSqliteWasmPersister = createSqliteWasmPersister;
});
