jsql-neo 6.4.0-beta.5 → 6.4.0-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  > **One engine to rule them all** — a Rust-powered embedded database that speaks your language:
4
4
  > MySQL, PostgreSQL, MongoDB, Redis, SQL, TypeScript, **and the browser**.
5
5
 
6
- > **v6.4.0-beta.5** — official release build · [github.com/vexify-org/JSQL-neo](https://github.com/vexify-org/JSQL-neo) · [jsql.vexify.top](https://jsql.vexify.top)
6
+ > **v6.4.0-beta.7** — official release build · [github.com/vexify-org/JSQL-neo](https://github.com/vexify-org/JSQL-neo) · [jsql.vexify.top](https://jsql.vexify.top)
7
7
 
8
8
  ![Engines](https://img.shields.io/badge/engines-Native%20%7C%20WASM%20%7C%20Pure%20JS-7ee787)
9
9
  ![MySQL](https://img.shields.io/badge/protocol-MySQL%20compatible-1f6feb)
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * JSQL-NEO v6.4.0-beta.5 — Rust-Powered Embedded Database (WASM + HTTP)
2
+ * JSQL-NEO v6.4.0-beta.7 — Rust-Powered Embedded Database (WASM + HTTP)
3
3
  *
4
4
  * @example
5
5
  * const jsql = require('jsql-neo');
package/lib/database.js CHANGED
@@ -652,13 +652,13 @@ class Database {
652
652
  switch (op.op) {
653
653
  case 'createTable':
654
654
  if (op.table && !this._tables[op.table]) {
655
- this.createTable(op.table, op.schema || {});
655
+ this._createTableSync(op.table, op.schema || {});
656
656
  }
657
657
  return true;
658
658
 
659
659
  case 'dropTable':
660
660
  if (op.table && this._tables[op.table]) {
661
- this.dropTable(op.table);
661
+ this._dropTableSync(op.table);
662
662
  }
663
663
  return true;
664
664
 
@@ -696,22 +696,7 @@ class Database {
696
696
  // 表管理
697
697
  // ============================================================
698
698
 
699
- createTable(name, schema) {
700
- if (!name || name.length > 64 || name === '.' || name === '..' || /[\x00-\x1f/\\]|\.\./.test(name)) {
701
- throw createError('ER_BAD_TABLE_NAME', name);
702
- }
703
- if (typeof schema === 'string') {
704
- const parsed = {};
705
- for (const seg of schema.split(',')) {
706
- const trimmed = seg.trim();
707
- if (!trimmed) continue;
708
- const parts = trimmed.split(/\s+/);
709
- const field = parts.shift();
710
- parsed[field] = parts.join(' ').toLowerCase().trim() || 'string';
711
- }
712
- schema = parsed;
713
- }
714
- if (!this._runHooks('beforeCreateTable', [name, schema])) throw createError('ER_PLUGIN_ABORT', 'createTable aborted by plugin');
699
+ _createTableSync(name, schema) {
715
700
  if (this._tables[name] || (this._dirMode && this._meta.tables[name])) {
716
701
  throw createError('ER_TABLE_EXISTS_ERROR', name);
717
702
  }
@@ -741,13 +726,31 @@ class Database {
741
726
  this._markDirty(name);
742
727
  this._walWrite({ op: 'createTable', table: name, schema });
743
728
  this._emit('createTable', { name, schema });
744
- this._runHooks('afterCreateTable', [name, schema]);
745
729
  return table;
746
730
  }
747
731
 
748
- dropTable(name) {
749
- if (!this._tables[name] && !(this._dirMode && this._meta.tables[name])) throw createError('ER_NO_SUCH_TABLE', name);
750
- if (!this._runHooks('beforeDropTable', [name])) return;
732
+ async createTable(name, schema) {
733
+ if (!name || name.length > 64 || name === '.' || name === '..' || /[\x00-\x1f/\\]|\.\./.test(name)) {
734
+ throw createError('ER_BAD_TABLE_NAME', name);
735
+ }
736
+ if (typeof schema === 'string') {
737
+ const parsed = {};
738
+ for (const seg of schema.split(',')) {
739
+ const trimmed = seg.trim();
740
+ if (!trimmed) continue;
741
+ const parts = trimmed.split(/\s+/);
742
+ const field = parts.shift();
743
+ parsed[field] = parts.join(' ').toLowerCase().trim() || 'string';
744
+ }
745
+ schema = parsed;
746
+ }
747
+ if (!(await this._runHooks('beforeCreateTable', [name, schema]))) throw createError('ER_PLUGIN_ABORT', 'createTable aborted by plugin');
748
+ const table = this._createTableSync(name, schema);
749
+ await this._runHooks('afterCreateTable', [name, schema]);
750
+ return table;
751
+ }
752
+
753
+ _dropTableSync(name) {
751
754
  if (this._tables[name]) {
752
755
  delete this._tables[name];
753
756
  }
@@ -766,7 +769,13 @@ class Database {
766
769
  this._walWrite({ op: 'dropTable', table: name });
767
770
  this._markDirty(name);
768
771
  this._emit('dropTable', { name });
769
- this._runHooks('afterDropTable', [name]);
772
+ }
773
+
774
+ async dropTable(name) {
775
+ if (!this._tables[name] && !(this._dirMode && this._meta.tables[name])) throw createError('ER_NO_SUCH_TABLE', name);
776
+ if (!(await this._runHooks('beforeDropTable', [name]))) return;
777
+ this._dropTableSync(name);
778
+ await this._runHooks('afterDropTable', [name]);
770
779
  }
771
780
 
772
781
  /**
@@ -777,7 +786,7 @@ class Database {
777
786
  * 各自都存了一份。漏掉任何一个都会留下一张「半改名」的表:
778
787
  * 查得到数据却列不出来,或者反过来。
779
788
  */
780
- renameTable(oldName, newName, { ifExists = false } = {}) {
789
+ async renameTable(oldName, newName, { ifExists = false } = {}) {
781
790
  if (oldName === newName) {
782
791
  if (!this._tables[oldName]) {
783
792
  if (ifExists) return false;
@@ -796,7 +805,7 @@ class Database {
796
805
  /[\x00-\x1f/\\]|\.\./.test(newName)) {
797
806
  throw createError('ER_BAD_TABLE_NAME', newName);
798
807
  }
799
- if (!this._runHooks('beforeRenameTable', [oldName, newName])) return false;
808
+ if (!(await this._runHooks('beforeRenameTable', [oldName, newName]))) return false;
800
809
 
801
810
  const table = this._tables[oldName];
802
811
 
@@ -848,7 +857,7 @@ class Database {
848
857
  this._markDirty(newName);
849
858
  this._walWrite({ op: 'renameTable', from: oldName, to: newName });
850
859
  this._emit('renameTable', { from: oldName, to: newName });
851
- this._runHooks('afterRenameTable', [oldName, newName]);
860
+ await this._runHooks('afterRenameTable', [oldName, newName]);
852
861
  return true;
853
862
  }
854
863
 
@@ -1723,7 +1732,7 @@ class Database {
1723
1732
  }
1724
1733
 
1725
1734
  async start() {
1726
- this._runHooks('onStart', []);
1735
+ await this._runHooks('onStart', []);
1727
1736
  this._emit('start', {});
1728
1737
  if (this._dirMode && !this._sigInstalled) {
1729
1738
  this._sigInstalled = true;
@@ -1772,11 +1781,11 @@ class Database {
1772
1781
  }
1773
1782
  }
1774
1783
 
1775
- insert(tableName, data) {
1784
+ async insert(tableName, data) {
1776
1785
  const table = this._ensureTable(tableName);
1777
1786
  if (!table) throw createError('ER_NO_SUCH_TABLE', tableName);
1778
1787
  const arr = Array.isArray(data) ? data : [data];
1779
- if (!this._runHooks('beforeInsert', [tableName, arr])) return [];
1788
+ if (!(await this._runHooks('beforeInsert', [tableName, arr]))) return [];
1780
1789
  const pk = this._pkOf(table);
1781
1790
  const ids = [];
1782
1791
  const logged = [];
@@ -1791,20 +1800,20 @@ class Database {
1791
1800
  // 有主键才可幂等回放;无主键表回放会重复插行,故不记录
1792
1801
  if (pk) this._walWrite({ op: 'insert', table: tableName, rows: logged });
1793
1802
  this._emit('insert', { table: tableName, count: arr.length, ids });
1794
- this._runHooks('afterInsert', [tableName, arr, ids]);
1803
+ await this._runHooks('afterInsert', [tableName, arr, ids]);
1795
1804
  this._markDirty(tableName);
1796
1805
  return ids;
1797
1806
  }
1798
1807
 
1799
1808
  async flush() {
1800
- if (!this._runHooks('beforeFlush', [])) return;
1809
+ if (!(await this._runHooks('beforeFlush', []))) return;
1801
1810
  if (this._dirMode) {
1802
1811
  this._flushDirty();
1803
1812
  this._saveMeta();
1804
1813
  } else if (!this._memoryMode) {
1805
1814
  this.save();
1806
1815
  }
1807
- this._runHooks('afterFlush', []);
1816
+ await this._runHooks('afterFlush', []);
1808
1817
  return this;
1809
1818
  }
1810
1819
 
@@ -1822,10 +1831,10 @@ class Database {
1822
1831
  return null;
1823
1832
  }
1824
1833
 
1825
- find(tableName, filter, opts = {}) {
1834
+ async find(tableName, filter, opts = {}) {
1826
1835
  const table = this._ensureTable(tableName);
1827
1836
  if (!table) throw createError('ER_NO_SUCH_TABLE', tableName);
1828
- if (!this._runHooks('beforeFind', [tableName, { filter, opts }])) return [];
1837
+ if (!(await this._runHooks('beforeFind', [tableName, { filter, opts }]))) return [];
1829
1838
  const { limit, offset = 0 } = opts;
1830
1839
  // P1-4: 软删除模式下不得泄露已删除行——只看可见行
1831
1840
  let rows = table._applyFilterOptimized(table._getVisibleRows(), filter || {});
@@ -1834,7 +1843,7 @@ class Database {
1834
1843
  // P1-11: 返回浅拷贝,防止调用方修改影响内部数据
1835
1844
  rows = rows.map(r => ({ ...r }));
1836
1845
  this._touchTable(tableName);
1837
- this._runHooks('afterFind', [tableName, { filter, opts }, rows]);
1846
+ await this._runHooks('afterFind', [tableName, { filter, opts }, rows]);
1838
1847
  return rows;
1839
1848
  }
1840
1849
 
@@ -1847,9 +1856,9 @@ class Database {
1847
1856
 
1848
1857
  async query(sql, paramsOrOpts, opts) {
1849
1858
  const { executeSQL } = require('./sql');
1850
- if (!this._runHooks('beforeQuery', [sql, paramsOrOpts, opts])) return null;
1859
+ if (!(await this._runHooks('beforeQuery', [sql, paramsOrOpts, opts]))) return null;
1851
1860
  const result = await executeSQL(this, sql, paramsOrOpts, opts);
1852
- this._runHooks('afterQuery', [sql, paramsOrOpts, opts, result]);
1861
+ await this._runHooks('afterQuery', [sql, paramsOrOpts, opts, result]);
1853
1862
  return result;
1854
1863
  }
1855
1864
 
@@ -1857,28 +1866,28 @@ class Database {
1857
1866
  return require('./prepared').createPrepared(this, sql);
1858
1867
  }
1859
1868
 
1860
- findById(tableName, id) {
1869
+ async findById(tableName, id) {
1861
1870
  const table = this._ensureTable(tableName);
1862
1871
  if (!table) throw createError('ER_NO_SUCH_TABLE', tableName);
1863
- if (!this._runHooks('beforeFind', [tableName, { id }])) return null;
1872
+ if (!(await this._runHooks('beforeFind', [tableName, { id }]))) return null;
1864
1873
  const row = this._resolveId(table, id);
1865
1874
  // P1-4: 软删除行对普通读取不可见
1866
1875
  if (row && row._deleted) return null;
1867
1876
  // P1-11: 返回浅拷贝,防止调用方修改影响内部数据
1868
1877
  const result = row ? { ...row } : null;
1869
1878
  this._touchTable(tableName);
1870
- this._runHooks('afterFind', [tableName, { id }, result]);
1879
+ await this._runHooks('afterFind', [tableName, { id }, result]);
1871
1880
  return result;
1872
1881
  }
1873
1882
 
1874
- findByIds(tableName, ids) {
1883
+ async findByIds(tableName, ids) {
1875
1884
  const table = this._ensureTable(tableName);
1876
1885
  if (!table) throw createError('ER_NO_SUCH_TABLE', tableName);
1877
- if (!this._runHooks('beforeFind', [tableName, { ids }])) return null;
1886
+ if (!(await this._runHooks('beforeFind', [tableName, { ids }]))) return null;
1878
1887
  // P1-4: 过滤掉软删除行;P1-11: 返回浅拷贝
1879
1888
  const rows = ids.map(id => this._resolveId(table, id)).filter(r => r !== null && !r._deleted).map(r => ({ ...r }));
1880
1889
  this._touchTable(tableName);
1881
- this._runHooks('afterFind', [tableName, { ids }, rows]);
1890
+ await this._runHooks('afterFind', [tableName, { ids }, rows]);
1882
1891
  return rows;
1883
1892
  }
1884
1893
 
@@ -1886,21 +1895,21 @@ class Database {
1886
1895
  return this.findByIds(tableName, ids);
1887
1896
  }
1888
1897
 
1889
- count(tableName) {
1898
+ async count(tableName) {
1890
1899
  const table = this._ensureTable(tableName);
1891
1900
  if (!table) throw createError('ER_NO_SUCH_TABLE', tableName);
1892
- this._runHooks('beforeCount', [tableName]);
1901
+ if (!(await this._runHooks('beforeCount', [tableName]))) return undefined;
1893
1902
  // P1-4: 软删除模式下只统计可见行
1894
1903
  const n = table._softDelete ? table._getVisibleRows().length : table._rows.length;
1895
1904
  this._touchTable(tableName);
1896
- this._runHooks('afterCount', [tableName, n]);
1905
+ await this._runHooks('afterCount', [tableName, n]);
1897
1906
  return n;
1898
1907
  }
1899
1908
 
1900
- updateById(tableName, id, data) {
1909
+ async updateById(tableName, id, data) {
1901
1910
  const table = this._ensureTable(tableName);
1902
1911
  if (!table) throw createError('ER_NO_SUCH_TABLE', tableName);
1903
- if (!this._runHooks('beforeUpdate', [tableName, id, data])) return;
1912
+ if (!(await this._runHooks('beforeUpdate', [tableName, id, data]))) return;
1904
1913
  // P1-9: updateById 绕过类型校验——先校验再更新
1905
1914
  const validated = table._validateDataTypes({ ...data }, true);
1906
1915
  const row = this._resolveId(table, id);
@@ -1925,16 +1934,16 @@ class Database {
1925
1934
  Object.assign(row, validated);
1926
1935
  if (pk) this._walWrite({ op: 'update', table: tableName, pk, id, row: { ...validated } });
1927
1936
  this._emit('update', { table: tableName, id, data: validated });
1928
- this._runHooks('afterUpdate', [tableName, id, validated, { ok: true }]);
1937
+ await this._runHooks('afterUpdate', [tableName, id, validated, { ok: true }]);
1929
1938
  this._markDirty(tableName);
1930
1939
  return { ok: true };
1931
1940
  }
1932
1941
 
1933
- updateByIds(tableName, entries) {
1942
+ async updateByIds(tableName, entries) {
1934
1943
  const table = this._ensureTable(tableName);
1935
1944
  if (!table) throw createError('ER_NO_SUCH_TABLE', tableName);
1936
1945
  const pairs = entries.map(([id, data]) => [id, data]);
1937
- if (!this._runHooks('beforeUpdate', [tableName, pairs])) return;
1946
+ if (!(await this._runHooks('beforeUpdate', [tableName, pairs]))) return;
1938
1947
  const pk = this._pkOf(table);
1939
1948
  let count = 0;
1940
1949
  for (const [id, data] of pairs) {
@@ -1946,21 +1955,21 @@ class Database {
1946
1955
  }
1947
1956
  }
1948
1957
  this._emit('update', { table: tableName, entries: pairs, result: { ok: true, count } });
1949
- this._runHooks('afterUpdate', [tableName, pairs, { ok: true, count }]);
1958
+ await this._runHooks('afterUpdate', [tableName, pairs, { ok: true, count }]);
1950
1959
  this._markDirty(tableName);
1951
1960
  return { ok: true, count };
1952
1961
  }
1953
1962
 
1954
- removeById(tableName, id) {
1963
+ async removeById(tableName, id) {
1955
1964
  const table = this._ensureTable(tableName);
1956
1965
  if (!table) throw createError('ER_NO_SUCH_TABLE', tableName);
1957
- if (!this._runHooks('beforeDelete', [tableName, id])) return;
1966
+ if (!(await this._runHooks('beforeDelete', [tableName, id]))) return;
1958
1967
  if (table._primaryKey) {
1959
1968
  const removed = table.removeById(id);
1960
1969
  if (removed === 0) return { ok: false, error: 'not found' };
1961
1970
  this._walWrite({ op: 'remove', table: tableName, pk: table._primaryKey, id });
1962
1971
  this._emit('delete', { table: tableName, id });
1963
- this._runHooks('afterDelete', [tableName, id, { ok: true }]);
1972
+ await this._runHooks('afterDelete', [tableName, id, { ok: true }]);
1964
1973
  this._markDirty(tableName);
1965
1974
  return { ok: true };
1966
1975
  }
@@ -1971,15 +1980,15 @@ class Database {
1971
1980
  table._rebuildAllBTrees();
1972
1981
  for (const field of Object.keys(table._indexes)) table.createIndex(field);
1973
1982
  this._emit('delete', { table: tableName, id });
1974
- this._runHooks('afterDelete', [tableName, id, { ok: true }]);
1983
+ await this._runHooks('afterDelete', [tableName, id, { ok: true }]);
1975
1984
  this._markDirty(tableName);
1976
1985
  return { ok: true };
1977
1986
  }
1978
1987
 
1979
- removeByIds(tableName, ids) {
1988
+ async removeByIds(tableName, ids) {
1980
1989
  const table = this._ensureTable(tableName);
1981
1990
  if (!table) throw createError('ER_NO_SUCH_TABLE', tableName);
1982
- if (!this._runHooks('beforeDelete', [tableName, ids])) return;
1991
+ if (!(await this._runHooks('beforeDelete', [tableName, ids]))) return;
1983
1992
  let removed = 0;
1984
1993
  if (table._primaryKey) {
1985
1994
  for (const id of ids) removed += table.removeById(id);
@@ -2014,15 +2023,15 @@ class Database {
2014
2023
  for (const field of Object.keys(table._indexes)) table.createIndex(field);
2015
2024
  }
2016
2025
  this._emit('delete', { table: tableName, ids, result: { ok: true, count: removed } });
2017
- this._runHooks('afterDelete', [tableName, ids, { ok: true, count: removed }]);
2026
+ await this._runHooks('afterDelete', [tableName, ids, { ok: true, count: removed }]);
2018
2027
  this._markDirty(tableName);
2019
2028
  return { ok: true, count: removed };
2020
2029
  }
2021
2030
 
2022
- removeWhere(tableName, filter) {
2031
+ async removeWhere(tableName, filter) {
2023
2032
  const table = this._ensureTable(tableName);
2024
2033
  if (!table) throw createError('ER_NO_SUCH_TABLE', tableName);
2025
- if (!this._runHooks('beforeDelete', [tableName, [filter]])) return { ok: true, count: 0 };
2034
+ if (!(await this._runHooks('beforeDelete', [tableName, [filter]]))) return { ok: true, count: 0 };
2026
2035
  const before = table._rows.length;
2027
2036
  // P1-4: 只匹配可见行(软删除行已“不存在”,不应被硬删操作波及)
2028
2037
  const matched = table._applyFilter(table._getVisibleRows(), filter || {});
@@ -2033,31 +2042,31 @@ class Database {
2033
2042
  table._rebuildAllBTrees();
2034
2043
  for (const field of Object.keys(table._indexes)) table.createIndex(field);
2035
2044
  this._emit('delete', { table: tableName, ids: [], result: { ok: true, count: removed } });
2036
- this._runHooks('afterDelete', [tableName, [filter], { ok: true, count: removed }]);
2045
+ await this._runHooks('afterDelete', [tableName, [filter], { ok: true, count: removed }]);
2037
2046
  this._markDirty(tableName);
2038
2047
  return { ok: true, count: removed };
2039
2048
  }
2040
2049
 
2041
- insertMany(tableName, items) {
2050
+ async insertMany(tableName, items) {
2042
2051
  const table = this._ensureTable(tableName);
2043
2052
  if (!table) throw createError('ER_NO_SUCH_TABLE', tableName);
2044
2053
  const arr = Array.isArray(items) ? items : [items];
2045
- if (!this._runHooks('beforeInsert', [tableName, arr])) return [];
2054
+ if (!(await this._runHooks('beforeInsert', [tableName, arr]))) return [];
2046
2055
  const inserted = table.insertMany(arr);
2047
2056
  // P1-6: insertMany 不写 WAL——崩溃恢复时丢失这些操作
2048
2057
  if (table._primaryKey && inserted.length > 0) {
2049
2058
  this._walWrite({ op: 'insert', table: tableName, rows: inserted });
2050
2059
  }
2051
2060
  this._emit('insert', { table: tableName, count: arr.length });
2052
- this._runHooks('afterInsert', [tableName, arr, inserted]);
2061
+ await this._runHooks('afterInsert', [tableName, arr, inserted]);
2053
2062
  this._markDirty(tableName);
2054
2063
  return inserted;
2055
2064
  }
2056
2065
 
2057
- update(tableName, query, updates) {
2066
+ async update(tableName, query, updates) {
2058
2067
  const table = this._ensureTable(tableName);
2059
2068
  if (!table) throw createError('ER_NO_SUCH_TABLE', tableName);
2060
- if (!this._runHooks('beforeUpdate', [tableName, query, updates])) return 0;
2069
+ if (!(await this._runHooks('beforeUpdate', [tableName, query, updates]))) return 0;
2061
2070
  const count = table.update(query, updates);
2062
2071
  // P1-6: update 不写 WAL——崩溃恢复时丢失这些操作
2063
2072
  if (table._primaryKey && count > 0) {
@@ -2068,15 +2077,15 @@ class Database {
2068
2077
  }
2069
2078
  }
2070
2079
  this._emit('update', { table: tableName, query, count });
2071
- this._runHooks('afterUpdate', [tableName, query, updates, count]);
2080
+ await this._runHooks('afterUpdate', [tableName, query, updates, count]);
2072
2081
  this._markDirty(tableName);
2073
2082
  return count;
2074
2083
  }
2075
2084
 
2076
- delete(tableName, query = {}) {
2085
+ async delete(tableName, query = {}) {
2077
2086
  const table = this._ensureTable(tableName);
2078
2087
  if (!table) throw createError('ER_NO_SUCH_TABLE', tableName);
2079
- if (!this._runHooks('beforeDelete', [tableName, query])) return 0;
2088
+ if (!(await this._runHooks('beforeDelete', [tableName, query]))) return 0;
2080
2089
  // P1-6: delete 不写 WAL——崩溃恢复时丢失这些操作
2081
2090
  if (table._primaryKey) {
2082
2091
  const toDelete = table.find(query);
@@ -2087,7 +2096,7 @@ class Database {
2087
2096
  }
2088
2097
  const count = table.remove(query);
2089
2098
  this._emit('delete', { table: tableName, query, count });
2090
- this._runHooks('afterDelete', [tableName, query, count]);
2099
+ await this._runHooks('afterDelete', [tableName, query, count]);
2091
2100
  this._markDirty(tableName);
2092
2101
  return count;
2093
2102
  }
@@ -2110,7 +2119,7 @@ class Database {
2110
2119
  }
2111
2120
 
2112
2121
  async stop() {
2113
- this._runHooks('onStop', []);
2122
+ await this._runHooks('onStop', []);
2114
2123
  this._emit('stop', {});
2115
2124
  // 内存监控定时器:stop() 此前从不清理,重复创建/销毁实例会堆积定时器
2116
2125
  if (this._monitorTimer) { clearInterval(this._monitorTimer); this._monitorTimer = null; }
@@ -2268,7 +2277,7 @@ class Database {
2268
2277
  if (this._jsqlMode) {
2269
2278
  this._jsqlFormat._open();
2270
2279
  for (const [name, t] of this._jsqlFormat.tables) {
2271
- if (!this._tables[name]) this.createTable(name, t.schema);
2280
+ if (!this._tables[name]) this._createTableSync(name, t.schema);
2272
2281
  if (t.rowCount > 0) {
2273
2282
  const { rows } = this._jsqlFormat.readTableSync(name);
2274
2283
  this._tables[name]._loadRows(rows);
@@ -2291,7 +2300,7 @@ class Database {
2291
2300
  if (data.__schema__) {
2292
2301
  for (const [name, schema] of Object.entries(data.__schema__)) {
2293
2302
  if (!this._tables[name]) {
2294
- this.createTable(name, schema);
2303
+ this._createTableSync(name, schema);
2295
2304
  }
2296
2305
  }
2297
2306
  }
@@ -401,7 +401,7 @@ class JSQL {
401
401
  }, this._evictInterval);
402
402
  if (this._evictTimer.unref) this._evictTimer.unref();
403
403
  }
404
- this._runHooks('onStart', []);
404
+ await this._runHooks('onStart', []);
405
405
  this._emit('start', {});
406
406
  }
407
407
 
@@ -554,7 +554,7 @@ class JSQL {
554
554
 
555
555
  async _flush() {
556
556
  this._flushOpsNow();
557
- if (!this._runHooks('beforeFlush', [])) return null;
557
+ if (!(await this._runHooks('beforeFlush', []))) return null;
558
558
  // 先把整个 buffer 原子取出再写入。
559
559
  // 旧写法是遍历 this._buffer、await 之后才清空 —— 期间其他协程继续往同一个数组
560
560
  // push,同一批行会被多个 flush 重复写入(并发 insert 行数暴涨/丢行)。
@@ -579,7 +579,7 @@ class JSQL {
579
579
  });
580
580
  throw e;
581
581
  }
582
- this._runHooks('afterFlush', []);
582
+ await this._runHooks('afterFlush', []);
583
583
  return flushed;
584
584
  }
585
585
 
@@ -611,7 +611,7 @@ class JSQL {
611
611
  const arr = Array.isArray(data) ? data : [data];
612
612
  arr.forEach((row, i) => assertRowObject(row, i, arr.length > 1 || Array.isArray(data)));
613
613
  var filtered = arr;
614
- if (!this._runHooks('beforeInsert', [table, filtered])) return [];
614
+ if (!(await this._runHooks('beforeInsert', [table, filtered]))) return [];
615
615
  if (arr.length > 1) {
616
616
  await this._flush();
617
617
  let result;
@@ -622,7 +622,7 @@ class JSQL {
622
622
  if (!result) result = r;
623
623
  }
624
624
  this._emit('insert', { table, count: arr.length, ids: result });
625
- this._runHooks('afterInsert', [table, filtered, result]);
625
+ await this._runHooks('afterInsert', [table, filtered, result]);
626
626
  return result;
627
627
  }
628
628
  if (!this._buffer[table]) this._buffer[table] = [];
@@ -631,20 +631,20 @@ class JSQL {
631
631
  const flushed = await this._flush();
632
632
  const result = flushed && flushed[table] ? flushed[table] : null;
633
633
  this._emit('insert', { table, count: arr.length, ids: result });
634
- this._runHooks('afterInsert', [table, filtered, result]);
634
+ await this._runHooks('afterInsert', [table, filtered, result]);
635
635
  return result;
636
636
  }
637
637
 
638
638
  async createTable(name, schema) {
639
639
  await this._flush();
640
640
  if (typeof schema === 'string') schema = parseSchemaString(schema);
641
- if (!this._runHooks('beforeCreateTable', [name, schema])) return null;
641
+ if (!(await this._runHooks('beforeCreateTable', [name, schema]))) return null;
642
642
  const r = safeParse(this._n('jsqlCreateTable', name, JSON.stringify(mapNativeSchema(schema))));
643
643
  if (r && r.ok === false) throw new Error(r.error || 'create table failed');
644
644
  this._tableNames.add(name);
645
645
  this._schemas[name] = typeof schema === 'string' ? mapNativeSchema(schema) : schema;
646
646
  this._emit('createTable', { name, schema });
647
- this._runHooks('afterCreateTable', [name, schema]);
647
+ await this._runHooks('afterCreateTable', [name, schema]);
648
648
  return r;
649
649
  }
650
650
 
@@ -661,30 +661,30 @@ class JSQL {
661
661
 
662
662
  async dropTable(name) {
663
663
  await this._flush();
664
- if (!this._runHooks('beforeDropTable', [name])) return null;
664
+ if (!(await this._runHooks('beforeDropTable', [name]))) return null;
665
665
  const r = safeParse(this._n('jsqlDropTable', name));
666
666
  if (r && r.ok === false) throw new Error(r.error || 'drop table failed');
667
667
  this._tableNames.delete(name);
668
668
  delete this._schemas[name];
669
669
  this._emit('dropTable', { name });
670
- this._runHooks('afterDropTable', [name]);
670
+ await this._runHooks('afterDropTable', [name]);
671
671
  return r;
672
672
  }
673
673
 
674
- findById(table, id) {
674
+ async findById(table, id) {
675
675
  this._flushOpsNow();
676
- if (!this._runHooks('beforeFind', [table, { id }])) return null;
676
+ if (!(await this._runHooks('beforeFind', [table, { id }]))) return null;
677
677
  const raw = this._findRawById(table, id);
678
678
  if (raw && raw.error) throw new Error(raw.error);
679
- this._runHooks('afterFind', [table, { id }, raw]);
679
+ await this._runHooks('afterFind', [table, { id }, raw]);
680
680
  const schema = this._schemas[table];
681
681
  if (schema && raw && typeof raw === 'object') return restoreRow(raw, schema);
682
682
  return raw;
683
683
  }
684
684
 
685
- findByIds(table, ids) {
685
+ async findByIds(table, ids) {
686
686
  this._flushOpsNow();
687
- if (!this._runHooks('beforeFind', [table, { ids }])) return null;
687
+ if (!(await this._runHooks('beforeFind', [table, { ids }]))) return null;
688
688
  let r;
689
689
  if (this._pkOf(table)) {
690
690
  r = ids.map(id => this._findRawById(table, id)).filter(x => x !== null && !(x && x.error));
@@ -692,7 +692,7 @@ class JSQL {
692
692
  r = safeParse(this._n('jsqlFindByIds', table, JSON.stringify(ids)));
693
693
  }
694
694
  if (r && r.error) throw new Error(r.error);
695
- this._runHooks('afterFind', [table, { ids }, r]);
695
+ await this._runHooks('afterFind', [table, { ids }, r]);
696
696
  const schema = this._schemas[table];
697
697
  if (schema && Array.isArray(r)) return r.map(row => restoreRow(row, schema));
698
698
  return r;
@@ -704,12 +704,12 @@ class JSQL {
704
704
 
705
705
  async find(table, filter, opts = {}) {
706
706
  this._flushOpsNow();
707
- if (!this._runHooks('beforeFind', [table, { filter, opts }])) return [];
707
+ if (!(await this._runHooks('beforeFind', [table, { filter, opts }]))) return [];
708
708
  const filterStr = filter ? JSON.stringify(filter) : '';
709
709
  const { limit = 100, offset = 0 } = opts;
710
710
  const r = safeParse(this._n('jsqlFind', table, filterStr, limit, offset));
711
711
  if (r && r.error) throw new Error(r.error);
712
- this._runHooks('afterFind', [table, { filter, opts }, r]);
712
+ await this._runHooks('afterFind', [table, { filter, opts }, r]);
713
713
  const schema = this._schemas[table];
714
714
  if (schema && Array.isArray(r)) return r.map(row => restoreRow(row, schema));
715
715
  return r;
@@ -717,27 +717,27 @@ class JSQL {
717
717
 
718
718
  async count(table) {
719
719
  this._flushOpsNow();
720
- this._runHooks('beforeCount', [table]);
720
+ await this._runHooks('beforeCount', [table]);
721
721
  const r = parseInt(this._n('jsqlCount', table), 10);
722
722
  const n = isNaN(r) ? 0 : r;
723
- this._runHooks('afterCount', [table, n]);
723
+ await this._runHooks('afterCount', [table, n]);
724
724
  return n;
725
725
  }
726
726
 
727
- updateByIds(table, entries) {
727
+ async updateByIds(table, entries) {
728
728
  const pairs = [];
729
729
  for (const [id, data] of entries) {
730
730
  const seq = this._seqIdByPk(table, id);
731
731
  if (seq !== null) pairs.push([seq, data]);
732
732
  }
733
- if (!this._runHooks('beforeUpdate', [table, pairs])) return;
733
+ if (!(await this._runHooks('beforeUpdate', [table, pairs]))) return;
734
734
  if (!this._opBuffer.update[table]) this._opBuffer.update[table] = [];
735
735
  this._opBuffer.update[table].push(...pairs);
736
736
  this._scheduleOpFlush();
737
737
  }
738
738
 
739
- removeByIds(table, ids) {
740
- if (!this._runHooks('beforeDelete', [table, ids])) return;
739
+ async removeByIds(table, ids) {
740
+ if (!(await this._runHooks('beforeDelete', [table, ids]))) return;
741
741
  if (!this._opBuffer.remove[table]) this._opBuffer.remove[table] = new Set();
742
742
  for (const id of ids) {
743
743
  const seq = this._seqIdByPk(table, id);
@@ -746,8 +746,8 @@ class JSQL {
746
746
  this._scheduleOpFlush();
747
747
  }
748
748
 
749
- updateById(table, id, data) {
750
- if (!this._runHooks('beforeUpdate', [table, id, data])) return;
749
+ async updateById(table, id, data) {
750
+ if (!(await this._runHooks('beforeUpdate', [table, id, data]))) return;
751
751
  const seq = this._seqIdByPk(table, id);
752
752
  if (seq === null) return;
753
753
  // 改主键 / UNIQUE 列前先查冲突(同步版,与 lib/database.js 的修复对齐)。
@@ -785,8 +785,8 @@ class JSQL {
785
785
  }
786
786
  }
787
787
 
788
- removeById(table, id) {
789
- if (!this._runHooks('beforeDelete', [table, id])) return;
788
+ async removeById(table, id) {
789
+ if (!(await this._runHooks('beforeDelete', [table, id]))) return;
790
790
  const seq = this._seqIdByPk(table, id);
791
791
  if (seq === null) return;
792
792
  if (!this._opBuffer.remove[table]) this._opBuffer.remove[table] = new Set();
@@ -814,9 +814,9 @@ class JSQL {
814
814
  * await db.query("UPDATE users SET age = age + 1 WHERE name = 'A'");
815
815
  */
816
816
  async query(sql, paramsOrOpts, opts) {
817
- if (!this._runHooks('beforeQuery', [sql, paramsOrOpts, opts])) return null;
817
+ if (!(await this._runHooks('beforeQuery', [sql, paramsOrOpts, opts]))) return null;
818
818
  const result = await executeSQL(this, sql, paramsOrOpts, opts);
819
- this._runHooks('afterQuery', [sql, paramsOrOpts, opts, result]);
819
+ await this._runHooks('afterQuery', [sql, paramsOrOpts, opts, result]);
820
820
  return result;
821
821
  }
822
822
 
@@ -847,7 +847,7 @@ class JSQL {
847
847
  } catch (e) { /* ignore */ }
848
848
  this._handle = null;
849
849
  }
850
- this._runHooks('onStop', []);
850
+ await this._runHooks('onStop', []);
851
851
  this._emit('stop', {});
852
852
  }
853
853
 
package/lib/plugin.js CHANGED
@@ -250,27 +250,18 @@ function runHooks(engine, hookName, args) {
250
250
  }
251
251
  engine._inHook = true;
252
252
  }
253
- try {
254
- for (const fn of hooks) {
255
- // 同步运行所有 hook。async hook 应在注册时用 async 包装,或用 afterHooks 队列。
256
- // 如果 hook 返回 false(同步)或 reject(异步),都视为拒绝。
257
- let result;
258
- try {
259
- result = fn(...args);
260
- } catch(e) {
261
- return false;
262
- }
263
- if (result === false) return false;
264
- // 如果 hook 返回 Promise,在同步模式下用 Promise.then 跟踪(不影响主流程)
265
- if (result && typeof result.then === 'function') {
266
- // 异步 hook:静默记录报错(同步运行不阻塞),throw 也算拒绝
267
- result.then(r => { if (r === false) return false; }).catch(() => false);
253
+
254
+ return (async () => {
255
+ try {
256
+ for (const fn of hooks) {
257
+ const result = await fn(...args);
258
+ if (result === false) return false;
268
259
  }
260
+ return true;
261
+ } finally {
262
+ if (guard) engine._inHook = false;
269
263
  }
270
- return true;
271
- } finally {
272
- if (guard) engine._inHook = false;
273
- }
264
+ })();
274
265
  }
275
266
 
276
267
  module.exports = {
@@ -406,7 +406,7 @@ class JSQL {
406
406
 
407
407
  async start() {
408
408
  wasmBindings.jsql_reset();
409
- this._runHooks('onStart', []);
409
+ await this._runHooks('onStart', []);
410
410
  this._emit('start', {});
411
411
  }
412
412
 
@@ -516,7 +516,7 @@ class JSQL {
516
516
  }
517
517
 
518
518
  async _flush() {
519
- if (!this._runHooks('beforeFlush', [])) return null;
519
+ if (!(await this._runHooks('beforeFlush', []))) return null;
520
520
  // 先把整个 buffer 原子取出再写入。
521
521
  // 旧写法是遍历 this._buffer 然后在 await 之后才清空 —— 这期间其他协程会继续
522
522
  // 往同一个数组 push,导致同一批行被多个 flush 重复写(并发 insert 行数暴涨)。
@@ -541,7 +541,7 @@ class JSQL {
541
541
  });
542
542
  throw e;
543
543
  }
544
- this._runHooks('afterFlush', []);
544
+ await this._runHooks('afterFlush', []);
545
545
  return flushed;
546
546
  }
547
547
 
@@ -559,7 +559,7 @@ class JSQL {
559
559
  // 难以定位的 "Cannot convert undefined or null to object",这里直接给明确 TypeError
560
560
  const arr = Array.isArray(data) ? data : [data];
561
561
  arr.forEach((row, i) => assertRowObject(row, i, arr.length > 1 || Array.isArray(data)));
562
- if (!this._runHooks('beforeInsert', [table, arr])) return [];
562
+ if (!(await this._runHooks('beforeInsert', [table, arr]))) return [];
563
563
  if (arr.length > 1) {
564
564
  await this._flush();
565
565
  let result;
@@ -570,7 +570,7 @@ class JSQL {
570
570
  if (!result) result = r;
571
571
  }
572
572
  this._emit('insert', { table, count: arr.length, ids: result });
573
- this._runHooks('afterInsert', [table, arr, result]);
573
+ await this._runHooks('afterInsert', [table, arr, result]);
574
574
  return result;
575
575
  }
576
576
  if (!this._buffer[table]) this._buffer[table] = [];
@@ -579,7 +579,7 @@ class JSQL {
579
579
  const flushed = await this._flush();
580
580
  const result = flushed && flushed[table] ? flushed[table] : null;
581
581
  this._emit('insert', { table, count: arr.length, ids: result });
582
- this._runHooks('afterInsert', [table, arr, result]);
582
+ await this._runHooks('afterInsert', [table, arr, result]);
583
583
  return result;
584
584
  }
585
585
 
@@ -590,13 +590,13 @@ class JSQL {
590
590
  async createTable(name, schema) {
591
591
  await this._flush();
592
592
  if (typeof schema === 'string') schema = parseSchemaString(schema);
593
- if (!this._runHooks('beforeCreateTable', [name, schema])) return null;
593
+ if (!(await this._runHooks('beforeCreateTable', [name, schema]))) return null;
594
594
  const r = safeJsonParse(wasmBindings.jsql_create_table(name, JSON.stringify(mapNativeSchema(schema))));
595
595
  if (r && r.ok === false) throw new Error(r.error || 'create table failed');
596
596
  this._tableNames.add(name);
597
597
  this._schemas[name] = typeof schema === 'string' ? mapNativeSchema(schema) : schema;
598
598
  this._emit('createTable', { name, schema });
599
- this._runHooks('afterCreateTable', [name, schema]);
599
+ await this._runHooks('afterCreateTable', [name, schema]);
600
600
  return r;
601
601
  }
602
602
 
@@ -613,22 +613,22 @@ class JSQL {
613
613
 
614
614
  async dropTable(name) {
615
615
  await this._flush();
616
- if (!this._runHooks('beforeDropTable', [name])) return null;
616
+ if (!(await this._runHooks('beforeDropTable', [name]))) return null;
617
617
  const r = safeJsonParse(wasmBindings.jsql_drop_table(name));
618
618
  if (r && r.ok === false) throw new Error(r.error || 'drop table failed');
619
619
  this._tableNames.delete(name);
620
620
  delete this._schemas[name];
621
621
  this._emit('dropTable', { name });
622
- this._runHooks('afterDropTable', [name]);
622
+ await this._runHooks('afterDropTable', [name]);
623
623
  return r;
624
624
  }
625
625
 
626
626
  async findById(table, id) {
627
627
  await this._flush();
628
- if (!this._runHooks('beforeFind', [table, { id }])) return null;
628
+ if (!(await this._runHooks('beforeFind', [table, { id }]))) return null;
629
629
  const r = this._findRawById(table, id);
630
630
  if (r && r.error) throw new Error(r.error);
631
- this._runHooks('afterFind', [table, { id }, r]);
631
+ await this._runHooks('afterFind', [table, { id }, r]);
632
632
  const schema = this._schemas[table];
633
633
  if (schema && r && typeof r === 'object') return restoreRow(r, schema);
634
634
  return r;
@@ -636,12 +636,12 @@ class JSQL {
636
636
 
637
637
  async find(table, filter, opts = {}) {
638
638
  await this._flush();
639
- if (!this._runHooks('beforeFind', [table, { filter, opts }])) return [];
639
+ if (!(await this._runHooks('beforeFind', [table, { filter, opts }]))) return [];
640
640
  const filterStr = filter ? JSON.stringify(filter) : '';
641
641
  const { limit = 100, offset = 0 } = opts;
642
642
  const r = safeJsonParse(wasmBindings.jsql_find(table, filterStr, limit, offset));
643
643
  if (r && r.error) throw new Error(r.error);
644
- this._runHooks('afterFind', [table, { filter, opts }, r]);
644
+ await this._runHooks('afterFind', [table, { filter, opts }, r]);
645
645
  const schema = this._schemas[table];
646
646
  if (schema && Array.isArray(r)) return r.map(row => restoreRow(row, schema));
647
647
  return r;
@@ -649,10 +649,10 @@ class JSQL {
649
649
 
650
650
  async count(table) {
651
651
  await this._flush();
652
- this._runHooks('beforeCount', [table]);
652
+ await this._runHooks('beforeCount', [table]);
653
653
  const r = parseInt(wasmBindings.jsql_count(table), 10);
654
654
  const n = isNaN(r) ? 0 : r;
655
- this._runHooks('afterCount', [table, n]);
655
+ await this._runHooks('afterCount', [table, n]);
656
656
  return n;
657
657
  }
658
658
 
@@ -662,29 +662,29 @@ class JSQL {
662
662
  const seq = this._seqIdByPk(table, id);
663
663
  if (seq !== null) pairs.push([seq, data]);
664
664
  }
665
- if (!this._runHooks('beforeUpdate', [table, pairs])) return;
665
+ if (!(await this._runHooks('beforeUpdate', [table, pairs]))) return;
666
666
  await this._flush();
667
667
  const r = safeJsonParse(wasmBindings.jsql_update_by_ids(table, JSON.stringify(pairs)));
668
668
  if (r && r.error) throw new Error(r.error);
669
669
  this._emit('update', { table, entries: pairs, result: r });
670
- this._runHooks('afterUpdate', [table, pairs, r]);
670
+ await this._runHooks('afterUpdate', [table, pairs, r]);
671
671
  return r;
672
672
  }
673
673
 
674
674
  async removeByIds(table, ids) {
675
- if (!this._runHooks('beforeDelete', [table, ids])) return;
675
+ if (!(await this._runHooks('beforeDelete', [table, ids]))) return;
676
676
  await this._flush();
677
677
  const seqs = ids.map(id => this._seqIdByPk(table, id)).filter(s => s !== null);
678
678
  const r = safeJsonParse(wasmBindings.jsql_remove_by_ids(table, JSON.stringify(seqs)));
679
679
  if (r && r.error) throw new Error(r.error);
680
680
  this._emit('delete', { table, ids: seqs, result: r });
681
- this._runHooks('afterDelete', [table, ids, r]);
681
+ await this._runHooks('afterDelete', [table, ids, r]);
682
682
  return r;
683
683
  }
684
684
 
685
685
  async findByIds(table, ids) {
686
686
  await this._flush();
687
- if (!this._runHooks('beforeFind', [table, { ids }])) return null;
687
+ if (!(await this._runHooks('beforeFind', [table, { ids }]))) return null;
688
688
  let r;
689
689
  if (this._pkOf(table)) {
690
690
  r = ids.map(id => this._findRawById(table, id)).filter(x => x !== null && !(x && x.error));
@@ -692,7 +692,7 @@ class JSQL {
692
692
  r = safeJsonParse(wasmBindings.jsql_find_by_ids(table, JSON.stringify(ids)));
693
693
  }
694
694
  if (r && r.error) throw new Error(r.error);
695
- this._runHooks('afterFind', [table, { ids }, r]);
695
+ await this._runHooks('afterFind', [table, { ids }, r]);
696
696
  const schema = this._schemas[table];
697
697
  if (schema && Array.isArray(r)) return r.map(row => restoreRow(row, schema));
698
698
  return r;
@@ -703,7 +703,7 @@ class JSQL {
703
703
  }
704
704
 
705
705
  async updateById(table, id, data) {
706
- if (!this._runHooks('beforeUpdate', [table, id, data])) return;
706
+ if (!(await this._runHooks('beforeUpdate', [table, id, data]))) return;
707
707
  await this._flush();
708
708
  const seq = this._seqIdByPk(table, id);
709
709
  if (seq === null) return null;
@@ -716,7 +716,7 @@ class JSQL {
716
716
  const r = safeJsonParse(wasmBindings.jsql_update_by_id(table, BigInt(seq), JSON.stringify(data)));
717
717
  if (r && r.ok === false) throw new Error(r.error || 'update failed');
718
718
  this._emit('update', { table, id, data });
719
- this._runHooks('afterUpdate', [table, id, data, r]);
719
+ await this._runHooks('afterUpdate', [table, id, data, r]);
720
720
  return r;
721
721
  }
722
722
 
@@ -750,14 +750,14 @@ class JSQL {
750
750
  }
751
751
 
752
752
  async removeById(table, id) {
753
- if (!this._runHooks('beforeDelete', [table, id])) return;
753
+ if (!(await this._runHooks('beforeDelete', [table, id]))) return;
754
754
  await this._flush();
755
755
  const seq = this._seqIdByPk(table, id);
756
756
  if (seq === null) return null;
757
757
  const r = safeJsonParse(wasmBindings.jsql_remove_by_id(table, BigInt(seq)));
758
758
  if (r && r.ok === false) throw new Error(r.error || 'remove failed');
759
759
  this._emit('delete', { table, id });
760
- this._runHooks('afterDelete', [table, id, r]);
760
+ await this._runHooks('afterDelete', [table, id, r]);
761
761
  return r;
762
762
  }
763
763
 
@@ -818,9 +818,9 @@ class JSQL {
818
818
  * const rows = await db.query("SELECT * FROM users WHERE age > ?", [21]);
819
819
  */
820
820
  async query(sql, paramsOrOpts, opts) {
821
- if (!this._runHooks('beforeQuery', [sql, paramsOrOpts, opts])) return null;
821
+ if (!(await this._runHooks('beforeQuery', [sql, paramsOrOpts, opts]))) return null;
822
822
  const result = await executeSQL(this, sql, paramsOrOpts, opts);
823
- this._runHooks('afterQuery', [sql, paramsOrOpts, opts, result]);
823
+ await this._runHooks('afterQuery', [sql, paramsOrOpts, opts, result]);
824
824
  return result;
825
825
  }
826
826
 
@@ -835,7 +835,7 @@ class JSQL {
835
835
 
836
836
  async stop() {
837
837
  await this._flush();
838
- this._runHooks('onStop', []);
838
+ await this._runHooks('onStop', []);
839
839
  this._emit('stop', {});
840
840
  }
841
841
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsql-neo",
3
- "version": "6.4.0-beta.5",
3
+ "version": "6.4.0-beta.7",
4
4
  "description": "JSQL-NEO — Rust-powered embedded database with WASM, REST API, B-Tree indexes, WAL, crash recovery",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -32,9 +32,9 @@ function ok(name, cond, extra) {
32
32
  ok('string prefix z', bt.prefix('z').length === 0);
33
33
  }
34
34
 
35
- {
35
+ (async () => {
36
36
  const db = new Database(':memory:');
37
- db.createTable('users', {
37
+ await db.createTable('users', {
38
38
  id: { type: 'integer', primaryKey: true, autoIncrement: true },
39
39
  name: { type: 'string', unique: true },
40
40
  age: { type: 'integer' }
@@ -63,11 +63,11 @@ function ok(name, cond, extra) {
63
63
 
64
64
  const one = db.users.findOne({ name: 'bob' });
65
65
  ok('findOne no full clone', one && one.name === 'bob' && one.age === 40);
66
- }
66
+ })();
67
67
 
68
68
  (async () => {
69
69
  const db = new Database(':memory:');
70
- db.createTable('users', {
70
+ await db.createTable('users', {
71
71
  id: { type: 'integer', primaryKey: true, autoIncrement: true },
72
72
  name: { type: 'string' },
73
73
  age: { type: 'integer' }
@@ -91,18 +91,18 @@ function ok(name, cond, extra) {
91
91
  {
92
92
  const pdb = new Database(':memory:');
93
93
  pdb.use('timestamps', { createdField: 'created_at', updatedField: 'updated_at' });
94
- pdb.createTable('notes', { id: { type: 'integer', primaryKey: true, autoIncrement: true }, title: { type: 'string' } });
94
+ await pdb.createTable('notes', { id: { type: 'integer', primaryKey: true, autoIncrement: true }, title: { type: 'string' } });
95
95
  const schema = pdb.getTableSchema('notes');
96
96
  ok('use opts timestamps fields', !!(schema && schema.created_at && schema.updated_at), schema);
97
- pdb.insert('notes', { title: 'hello' });
97
+ await pdb.insert('notes', { title: 'hello' });
98
98
  const row = pdb.notes.findOne({ title: 'hello' });
99
99
  ok('timestamps stamped', !!(row && row.created_at && row.updated_at), row);
100
100
 
101
101
  let afterInsertHits = 0;
102
102
  pdb.on('afterInsert', () => { afterInsertHits++; });
103
- pdb.insert('notes', { title: 'one' });
103
+ await pdb.insert('notes', { title: 'one' });
104
104
  ok('single-row afterInsert', afterInsertHits === 1, afterInsertHits);
105
- pdb.insert('notes', [{ title: 'a' }, { title: 'b' }]);
105
+ await pdb.insert('notes', [{ title: 'a' }, { title: 'b' }]);
106
106
  ok('batch afterInsert', afterInsertHits === 2, afterInsertHits);
107
107
  }
108
108