@nymphjs/driver-sqlite3 1.0.0-beta.105 → 1.0.0-beta.107

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/CHANGELOG.md CHANGED
@@ -3,6 +3,19 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [1.0.0-beta.107](https://github.com/sciactive/nymphjs/compare/v1.0.0-beta.106...v1.0.0-beta.107) (2026-02-13)
7
+
8
+ ### Features
9
+
10
+ - move tilmeld fields into columns in entities tables ([5f46048](https://github.com/sciactive/nymphjs/commit/5f46048c3e04839ca9a8b81f71a950b9086d0a41))
11
+ - update packages and fix all new issues ([0e9d17c](https://github.com/sciactive/nymphjs/commit/0e9d17c6e2db12c11bdfb559031719c1b52b5fa1))
12
+
13
+ # [1.0.0-beta.106](https://github.com/sciactive/nymphjs/compare/v1.0.0-beta.105...v1.0.0-beta.106) (2025-12-05)
14
+
15
+ ### Bug Fixes
16
+
17
+ - don't sort qref queries unless explicitly told to ([e92c413](https://github.com/sciactive/nymphjs/commit/e92c413800032a9347a06f965281263a55c9547b))
18
+
6
19
  # [1.0.0-beta.105](https://github.com/sciactive/nymphjs/compare/v1.0.0-beta.104...v1.0.0-beta.105) (2025-12-04)
7
20
 
8
21
  ### Features
@@ -45,6 +45,8 @@ export default class SQLite3Driver extends NymphDriver {
45
45
  */
46
46
  isConnected(): boolean;
47
47
  private createEntitiesTable;
48
+ private addTilmeldColumnsAndIndexes;
49
+ private createEntitiesTilmeldIndexes;
48
50
  private createDataTable;
49
51
  private createReferencesTable;
50
52
  private createTokensTable;
@@ -119,6 +121,14 @@ export default class SQLite3Driver extends NymphDriver {
119
121
  sdata: SerializedEntityData;
120
122
  etype: string;
121
123
  }): Promise<void>;
124
+ importEntityTilmeldAC(entity: {
125
+ guid: string;
126
+ cdate: number;
127
+ mdate: number;
128
+ tags: string[];
129
+ sdata: SerializedEntityData;
130
+ etype: string;
131
+ }): Promise<void>;
122
132
  private importEntityInternal;
123
133
  importUID({ name, value }: {
124
134
  name: string;
@@ -131,7 +141,7 @@ export default class SQLite3Driver extends NymphDriver {
131
141
  setUID(name: string, curUid: number): Promise<boolean>;
132
142
  internalTransaction(name: string): Promise<void>;
133
143
  startTransaction(name: string): Promise<import("@nymphjs/nymph").Nymph>;
134
- needsMigration(): Promise<'json' | 'tokens' | false>;
135
- liveMigration(_migrationType: 'tokenTables'): Promise<void>;
144
+ needsMigration(): Promise<'json' | 'tokens' | 'tilmeldColumns' | false>;
145
+ liveMigration(migrationType: 'tokenTables' | 'tilmeldColumns'): Promise<void>;
136
146
  }
137
147
  export {};
@@ -179,10 +179,25 @@ export default class SQLite3Driver extends NymphDriver {
179
179
  }
180
180
  createEntitiesTable(etype) {
181
181
  // Create the entity table.
182
- this.queryRun(`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("guid" CHARACTER(24) PRIMARY KEY, "tags" TEXT, "cdate" REAL NOT NULL, "mdate" REAL NOT NULL);`);
182
+ this.queryRun(`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("guid" CHARACTER(24) PRIMARY KEY, "tags" TEXT, "cdate" REAL NOT NULL, "mdate" REAL NOT NULL, "user" CHARACTER(24), "group" CHARACTER(24), "acUser" INT(1), "acGroup" INT(1), "acOther" INT(1), "acRead" TEXT, "acWrite" TEXT, "acFull" TEXT);`);
183
183
  this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_cdate`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("cdate");`);
184
184
  this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_mdate`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("mdate");`);
185
185
  this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_tags`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("tags");`);
186
+ this.createEntitiesTilmeldIndexes(etype);
187
+ }
188
+ addTilmeldColumnsAndIndexes(etype) {
189
+ this.queryRun(`ALTER TABLE ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ADD COLUMN "user" CHARACTER(24), ADD COLUMN "group" CHARACTER(24), ADD COLUMN "acUser" INT(1), ADD COLUMN "acGroup" INT(1), ADD COLUMN "acOther" INT(1), ADD COLUMN "acRead" TEXT, ADD COLUMN "acWrite" TEXT, ADD COLUMN "acFull" TEXT;`);
190
+ this.createEntitiesTilmeldIndexes(etype);
191
+ }
192
+ createEntitiesTilmeldIndexes(etype) {
193
+ this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_user_acUser`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("user", "acUser");`);
194
+ this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_group_acGroup`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("group", "acGroup");`);
195
+ this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_acUser`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("acUser");`);
196
+ this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_acGroup`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("acGroup");`);
197
+ this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_acOther`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("acOther");`);
198
+ this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_acRead`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("acRead");`);
199
+ this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_acWrite`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("acWrite");`);
200
+ this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_acFull`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("acFull");`);
186
201
  }
187
202
  createDataTable(etype) {
188
203
  // Create the data table.
@@ -1370,14 +1385,14 @@ export default class SQLite3Driver extends NymphDriver {
1370
1385
  break;
1371
1386
  case 'selector':
1372
1387
  case '!selector':
1373
- const subquery = this.makeEntityQuery(options, [curValue], etype, count, params, true, tableSuffix, etypes);
1388
+ const innerquery = this.makeEntityQuery({ ...options, sort: null, limit: undefined }, [curValue], etype, count, params, true, tableSuffix, etypes);
1374
1389
  if (curQuery) {
1375
1390
  curQuery += typeIsOr ? ' OR ' : ' AND ';
1376
1391
  }
1377
1392
  curQuery +=
1378
1393
  (xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
1379
1394
  '(' +
1380
- subquery.query +
1395
+ innerquery.query +
1381
1396
  ')';
1382
1397
  break;
1383
1398
  case 'qref':
@@ -1386,7 +1401,12 @@ export default class SQLite3Driver extends NymphDriver {
1386
1401
  const [qrefOptions, ...qrefSelectors] = curValue[1];
1387
1402
  const QrefEntityClass = qrefOptions.class;
1388
1403
  etypes.push(QrefEntityClass.ETYPE);
1389
- const qrefQuery = this.makeEntityQuery({ ...qrefOptions, return: 'guid', class: QrefEntityClass }, qrefSelectors, QrefEntityClass.ETYPE, count, params, false, makeTableSuffix(), etypes, 'r' + referenceTableSuffix + '."reference"');
1404
+ const qrefQuery = this.makeEntityQuery({
1405
+ ...qrefOptions,
1406
+ sort: qrefOptions.sort ?? null,
1407
+ return: 'guid',
1408
+ class: QrefEntityClass,
1409
+ }, qrefSelectors, QrefEntityClass.ETYPE, count, params, false, makeTableSuffix(), etypes, 'r' + referenceTableSuffix + '."reference"');
1390
1410
  if (curQuery) {
1391
1411
  curQuery += typeIsOr ? ' OR ' : ' AND ';
1392
1412
  }
@@ -1646,14 +1666,17 @@ export default class SQLite3Driver extends NymphDriver {
1646
1666
  return result?.cur_uid ?? null;
1647
1667
  }
1648
1668
  async importEntity(entity) {
1649
- return await this.importEntityInternal(entity, false);
1669
+ return await this.importEntityInternal(entity);
1650
1670
  }
1651
1671
  async importEntityTokens(entity) {
1652
- return await this.importEntityInternal(entity, true);
1672
+ return await this.importEntityInternal(entity, { only: 'tokens' });
1673
+ }
1674
+ async importEntityTilmeldAC(entity) {
1675
+ return await this.importEntityInternal(entity, { only: 'tilmeldAC' });
1653
1676
  }
1654
- async importEntityInternal({ guid, cdate, mdate, tags, sdata, etype, }, onlyTokens) {
1677
+ async importEntityInternal({ guid, cdate, mdate, tags, sdata, etype, }, { only = undefined } = {}) {
1655
1678
  try {
1656
- if (!onlyTokens) {
1679
+ if (only == null) {
1657
1680
  this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} WHERE "guid"=@guid;`, {
1658
1681
  etypes: [etype],
1659
1682
  params: {
@@ -1673,13 +1696,15 @@ export default class SQLite3Driver extends NymphDriver {
1673
1696
  },
1674
1697
  });
1675
1698
  }
1676
- this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}`)} WHERE "guid"=@guid;`, {
1677
- etypes: [etype],
1678
- params: {
1679
- guid,
1680
- },
1681
- });
1682
- if (!onlyTokens) {
1699
+ if (only == null || only === 'tokens') {
1700
+ this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}`)} WHERE "guid"=@guid;`, {
1701
+ etypes: [etype],
1702
+ params: {
1703
+ guid,
1704
+ },
1705
+ });
1706
+ }
1707
+ if (only == null) {
1683
1708
  this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}uniques_${etype}`)} WHERE "guid"=@guid;`, {
1684
1709
  etypes: [etype],
1685
1710
  params: {
@@ -1687,14 +1712,23 @@ export default class SQLite3Driver extends NymphDriver {
1687
1712
  },
1688
1713
  });
1689
1714
  }
1690
- if (!onlyTokens) {
1691
- this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("guid", "tags", "cdate", "mdate") VALUES (@guid, @tags, @cdate, @mdate);`, {
1715
+ if (only == null) {
1716
+ let { user, group, acUser, acGroup, acOther, acRead, acWrite, acFull } = this.removeAndReturnACValues(etype, {}, sdata);
1717
+ this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("guid", "tags", "cdate", "mdate", "user", "group", "acUser", "acGroup", "acOther", "acRead", "acWrite", "acFull") VALUES (@guid, @tags, @cdate, @mdate, @user, @group, @acUser, @acGroup, @acOther, @acRead, @acWrite, @acFull);`, {
1692
1718
  etypes: [etype],
1693
1719
  params: {
1694
1720
  guid,
1695
1721
  tags: ',' + tags.join(',') + ',',
1696
1722
  cdate,
1697
1723
  mdate,
1724
+ user,
1725
+ group,
1726
+ acUser,
1727
+ acGroup,
1728
+ acOther,
1729
+ acRead: acRead && ',' + acRead.join(',') + ',',
1730
+ acWrite: acWrite && ',' + acWrite.join(',') + ',',
1731
+ acFull: acFull && ',' + acFull.join(',') + ',',
1698
1732
  },
1699
1733
  });
1700
1734
  for (const name in sdata) {
@@ -1734,45 +1768,64 @@ export default class SQLite3Driver extends NymphDriver {
1734
1768
  }
1735
1769
  }
1736
1770
  }
1771
+ if (only === 'tilmeldAC') {
1772
+ let { user, group, acUser, acGroup, acOther, acRead, acWrite, acFull } = this.removeAndReturnACValues(etype, {}, sdata);
1773
+ this.queryRun(`UPDATE OR IGNORE ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} SET "user"=@user, "group"=@group, "acUser"=@acUser, "acGroup"=@acGroup, "acOther"=@acOther, "acRead"=@acRead, "acWrite"=@acWrite, "acFull"=@acFull WHERE "guid"=@guid;`, {
1774
+ etypes: [etype],
1775
+ params: {
1776
+ user,
1777
+ group,
1778
+ acUser,
1779
+ acGroup,
1780
+ acOther,
1781
+ acRead: acRead && ',' + acRead.join(',') + ',',
1782
+ acWrite: acWrite && ',' + acWrite.join(',') + ',',
1783
+ acFull: acFull && ',' + acFull.join(',') + ',',
1784
+ guid,
1785
+ },
1786
+ });
1787
+ }
1737
1788
  const EntityClass = this.nymph.getEntityClassByEtype(etype);
1738
- for (let name in sdata) {
1739
- let tokenString = null;
1740
- try {
1741
- tokenString = EntityClass.getFTSText(name, JSON.parse(sdata[name]));
1742
- }
1743
- catch (e) {
1744
- // Ignore error.
1745
- }
1746
- if (tokenString != null) {
1747
- const tokens = this.tokenizer.tokenize(tokenString);
1748
- while (tokens.length) {
1749
- const currentTokens = tokens.splice(0, 100);
1750
- const params = {
1751
- guid,
1752
- name,
1753
- };
1754
- const values = [];
1755
- for (let i = 0; i < currentTokens.length; i++) {
1756
- const token = currentTokens[i];
1757
- params['token' + i] = token.token;
1758
- params['position' + i] = token.position;
1759
- params['stem' + i] = token.stem ? 1 : 0;
1760
- values.push('(@guid, @name, @token' +
1761
- i +
1762
- ', @position' +
1763
- i +
1764
- ', @stem' +
1765
- i +
1766
- ')');
1789
+ if (only == null || only === 'tokens') {
1790
+ for (let name in sdata) {
1791
+ let tokenString = null;
1792
+ try {
1793
+ tokenString = EntityClass.getFTSText(name, JSON.parse(sdata[name]));
1794
+ }
1795
+ catch (e) {
1796
+ // Ignore error.
1797
+ }
1798
+ if (tokenString != null) {
1799
+ const tokens = this.tokenizer.tokenize(tokenString);
1800
+ while (tokens.length) {
1801
+ const currentTokens = tokens.splice(0, 100);
1802
+ const params = {
1803
+ guid,
1804
+ name,
1805
+ };
1806
+ const values = [];
1807
+ for (let i = 0; i < currentTokens.length; i++) {
1808
+ const token = currentTokens[i];
1809
+ params['token' + i] = token.token;
1810
+ params['position' + i] = token.position;
1811
+ params['stem' + i] = token.stem ? 1 : 0;
1812
+ values.push('(@guid, @name, @token' +
1813
+ i +
1814
+ ', @position' +
1815
+ i +
1816
+ ', @stem' +
1817
+ i +
1818
+ ')');
1819
+ }
1820
+ this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}`)} ("guid", "name", "token", "position", "stem") VALUES ${values.join(', ')};`, {
1821
+ etypes: [etype],
1822
+ params,
1823
+ });
1767
1824
  }
1768
- this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}`)} ("guid", "name", "token", "position", "stem") VALUES ${values.join(', ')};`, {
1769
- etypes: [etype],
1770
- params,
1771
- });
1772
1825
  }
1773
1826
  }
1774
1827
  }
1775
- if (!onlyTokens) {
1828
+ if (only == null) {
1776
1829
  const uniques = await EntityClass.getUniques({
1777
1830
  guid,
1778
1831
  cdate,
@@ -2002,12 +2055,21 @@ export default class SQLite3Driver extends NymphDriver {
2002
2055
  Object.keys(sdata).length === 0) {
2003
2056
  return false;
2004
2057
  }
2005
- this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("guid", "tags", "cdate", "mdate") VALUES (@guid, @tags, @cdate, @cdate);`, {
2058
+ let { user, group, acUser, acGroup, acOther, acRead, acWrite, acFull, } = this.removeAndReturnACValues(etype, data, sdata);
2059
+ this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("guid", "tags", "cdate", "mdate", "user", "group", "acUser", "acGroup", "acOther", "acRead", "acWrite", "acFull") VALUES (@guid, @tags, @cdate, @cdate, @user, @group, @acUser, @acGroup, @acOther, @acRead, @acWrite, @acFull);`, {
2006
2060
  etypes: [etype],
2007
2061
  params: {
2008
2062
  guid,
2009
2063
  tags: ',' + tags.join(',') + ',',
2010
2064
  cdate,
2065
+ user,
2066
+ group,
2067
+ acUser,
2068
+ acGroup,
2069
+ acOther,
2070
+ acRead: acRead && ',' + acRead.join(',') + ',',
2071
+ acWrite: acWrite && ',' + acWrite.join(',') + ',',
2072
+ acFull: acFull && ',' + acFull.join(',') + ',',
2011
2073
  },
2012
2074
  });
2013
2075
  insertData(guid, data, sdata, uniques, etype);
@@ -2017,11 +2079,20 @@ export default class SQLite3Driver extends NymphDriver {
2017
2079
  Object.keys(sdata).length === 0) {
2018
2080
  return false;
2019
2081
  }
2020
- const info = this.queryRun(`UPDATE ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} SET "tags"=@tags, "mdate"=@mdate WHERE "guid"=@guid AND "mdate" <= @emdate;`, {
2082
+ let { user, group, acUser, acGroup, acOther, acRead, acWrite, acFull, } = this.removeAndReturnACValues(etype, data, sdata);
2083
+ const info = this.queryRun(`UPDATE ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} SET "tags"=@tags, "mdate"=@mdate, "user"=@user, "group"=@group, "acUser"=@acUser, "acGroup"=@acGroup, "acOther"=@acOther, "acRead"=@acRead, "acWrite"=@acWrite, "acFull"=@acFull WHERE "guid"=@guid AND "mdate" <= @emdate;`, {
2021
2084
  etypes: [etype],
2022
2085
  params: {
2023
2086
  tags: ',' + tags.join(',') + ',',
2024
2087
  mdate,
2088
+ user,
2089
+ group,
2090
+ acUser,
2091
+ acGroup,
2092
+ acOther,
2093
+ acRead: acRead && ',' + acRead.join(',') + ',',
2094
+ acWrite: acWrite && ',' + acWrite.join(',') + ',',
2095
+ acFull: acFull && ',' + acFull.join(',') + ',',
2025
2096
  guid,
2026
2097
  emdate: Number(entity.mdate),
2027
2098
  },
@@ -2137,12 +2208,35 @@ export default class SQLite3Driver extends NymphDriver {
2137
2208
  if (!table2 || !table2.name) {
2138
2209
  return 'tokens';
2139
2210
  }
2211
+ const table3 = this.queryGet("SELECT `name` FROM `sqlite_master` WHERE `type`='table' AND `name` LIKE @prefix LIMIT 1;", {
2212
+ params: {
2213
+ prefix: this.prefix + 'entities_' + '%',
2214
+ },
2215
+ });
2216
+ if (table3?.name) {
2217
+ const result = this.queryGet("SELECT 1 AS `exists` FROM pragma_table_info(@table) WHERE `name`='user';", {
2218
+ params: {
2219
+ table: table3.name,
2220
+ },
2221
+ });
2222
+ if (!result?.exists) {
2223
+ return 'tilmeldColumns';
2224
+ }
2225
+ }
2140
2226
  return false;
2141
2227
  }
2142
- async liveMigration(_migrationType) {
2143
- const etypes = await this.getEtypes();
2144
- for (let etype of etypes) {
2145
- this.createTokensTable(etype);
2228
+ async liveMigration(migrationType) {
2229
+ if (migrationType === 'tokenTables') {
2230
+ const etypes = await this.getEtypes();
2231
+ for (let etype of etypes) {
2232
+ this.createTokensTable(etype);
2233
+ }
2234
+ }
2235
+ else if (migrationType === 'tilmeldColumns') {
2236
+ const etypes = await this.getEtypes();
2237
+ for (let etype of etypes) {
2238
+ this.addTilmeldColumnsAndIndexes(etype);
2239
+ }
2146
2240
  }
2147
2241
  }
2148
2242
  }