@nymphjs/driver-sqlite3 1.0.0-beta.46 → 1.0.0-beta.48

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.
@@ -44,7 +44,7 @@ export default class SQLite3Driver extends NymphDriver {
44
44
  static escape(input: string) {
45
45
  if (input.indexOf('\x00') !== -1) {
46
46
  throw new InvalidParametersError(
47
- 'SQLite3 identifiers (like entity ETYPE) cannot contain null characters.'
47
+ 'SQLite3 identifiers (like entity ETYPE) cannot contain null characters.',
48
48
  );
49
49
  }
50
50
 
@@ -106,7 +106,7 @@ export default class SQLite3Driver extends NymphDriver {
106
106
  // Create the preg_match and regexp functions.
107
107
  link.function('regexp', { deterministic: true }, ((
108
108
  pattern: string,
109
- subject: string
109
+ subject: string,
110
110
  ) => (this.posixRegexMatch(pattern, subject) ? 1 : 0)) as (
111
111
  ...params: any[]
112
112
  ) => any);
@@ -153,7 +153,7 @@ export default class SQLite3Driver extends NymphDriver {
153
153
  if (!this.store) {
154
154
  if (write) {
155
155
  throw new Error(
156
- 'Tried to open in write without opening in read first.'
156
+ 'Tried to open in write without opening in read first.',
157
157
  );
158
158
  }
159
159
  this.store = new InternalStore(link);
@@ -171,7 +171,7 @@ export default class SQLite3Driver extends NymphDriver {
171
171
  if (filename === ':memory:') {
172
172
  throw new NotConfiguredError(
173
173
  "It seems the config hasn't been set up correctly. Could not connect: " +
174
- e?.message
174
+ e?.message,
175
175
  );
176
176
  } else {
177
177
  throw new UnableToConnectError('Could not connect: ' + e?.message);
@@ -226,151 +226,152 @@ export default class SQLite3Driver extends NymphDriver {
226
226
  // Create the entity table.
227
227
  this.queryRun(
228
228
  `CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(
229
- `${this.prefix}entities_${etype}`
230
- )} ("guid" CHARACTER(24) PRIMARY KEY, "tags" TEXT, "cdate" REAL NOT NULL, "mdate" REAL NOT NULL);`
229
+ `${this.prefix}entities_${etype}`,
230
+ )} ("guid" CHARACTER(24) PRIMARY KEY, "tags" TEXT, "cdate" REAL NOT NULL, "mdate" REAL NOT NULL);`,
231
231
  );
232
232
  this.queryRun(
233
233
  `CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
234
- `${this.prefix}entities_${etype}_id_cdate`
234
+ `${this.prefix}entities_${etype}_id_cdate`,
235
235
  )} ON ${SQLite3Driver.escape(
236
- `${this.prefix}entities_${etype}`
237
- )} ("cdate");`
236
+ `${this.prefix}entities_${etype}`,
237
+ )} ("cdate");`,
238
238
  );
239
239
  this.queryRun(
240
240
  `CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
241
- `${this.prefix}entities_${etype}_id_mdate`
241
+ `${this.prefix}entities_${etype}_id_mdate`,
242
242
  )} ON ${SQLite3Driver.escape(
243
- `${this.prefix}entities_${etype}`
244
- )} ("mdate");`
243
+ `${this.prefix}entities_${etype}`,
244
+ )} ("mdate");`,
245
245
  );
246
246
  this.queryRun(
247
247
  `CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
248
- `${this.prefix}entities_${etype}_id_tags`
248
+ `${this.prefix}entities_${etype}_id_tags`,
249
249
  )} ON ${SQLite3Driver.escape(
250
- `${this.prefix}entities_${etype}`
251
- )} ("tags");`
250
+ `${this.prefix}entities_${etype}`,
251
+ )} ("tags");`,
252
252
  );
253
253
  // Create the data table.
254
254
  this.queryRun(
255
255
  `CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(
256
- `${this.prefix}data_${etype}`
256
+ `${this.prefix}data_${etype}`,
257
257
  )} ("guid" CHARACTER(24) NOT NULL REFERENCES ${SQLite3Driver.escape(
258
- `${this.prefix}entities_${etype}`
259
- )} ("guid") ON DELETE CASCADE, "name" TEXT NOT NULL, "value" TEXT NOT NULL, PRIMARY KEY("guid", "name"));`
258
+ `${this.prefix}entities_${etype}`,
259
+ )} ("guid") ON DELETE CASCADE, "name" TEXT NOT NULL, "value" TEXT NOT NULL, PRIMARY KEY("guid", "name"));`,
260
260
  );
261
261
  this.queryRun(
262
262
  `CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
263
- `${this.prefix}data_${etype}_id_guid`
263
+ `${this.prefix}data_${etype}_id_guid`,
264
264
  )} ON ${SQLite3Driver.escape(
265
- `${this.prefix}data_${etype}`
266
- )} ("guid");`
265
+ `${this.prefix}data_${etype}`,
266
+ )} ("guid");`,
267
267
  );
268
268
  this.queryRun(
269
269
  `CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
270
- `${this.prefix}data_${etype}_id_name`
270
+ `${this.prefix}data_${etype}_id_name`,
271
271
  )} ON ${SQLite3Driver.escape(
272
- `${this.prefix}data_${etype}`
273
- )} ("name");`
272
+ `${this.prefix}data_${etype}`,
273
+ )} ("name");`,
274
274
  );
275
275
  this.queryRun(
276
276
  `CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
277
- `${this.prefix}data_${etype}_id_value`
277
+ `${this.prefix}data_${etype}_id_value`,
278
278
  )} ON ${SQLite3Driver.escape(
279
- `${this.prefix}data_${etype}`
280
- )} ("value");`
279
+ `${this.prefix}data_${etype}`,
280
+ )} ("value");`,
281
281
  );
282
282
  this.queryRun(
283
283
  `CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
284
- `${this.prefix}data_${etype}_id_guid__name_user`
284
+ `${this.prefix}data_${etype}_id_guid__name_user`,
285
285
  )} ON ${SQLite3Driver.escape(
286
- `${this.prefix}data_${etype}`
287
- )} ("guid") WHERE "name" = \'user\';`
286
+ `${this.prefix}data_${etype}`,
287
+ )} ("guid") WHERE "name" = \'user\';`,
288
288
  );
289
289
  this.queryRun(
290
290
  `CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
291
- `${this.prefix}data_${etype}_id_guid__name_group`
291
+ `${this.prefix}data_${etype}_id_guid__name_group`,
292
292
  )} ON ${SQLite3Driver.escape(
293
- `${this.prefix}data_${etype}`
294
- )} ("guid") WHERE "name" = \'group\';`
293
+ `${this.prefix}data_${etype}`,
294
+ )} ("guid") WHERE "name" = \'group\';`,
295
295
  );
296
296
  // Create the comparisons table.
297
297
  this.queryRun(
298
298
  `CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(
299
- `${this.prefix}comparisons_${etype}`
299
+ `${this.prefix}comparisons_${etype}`,
300
300
  )} ("guid" CHARACTER(24) NOT NULL REFERENCES ${SQLite3Driver.escape(
301
- `${this.prefix}entities_${etype}`
302
- )} ("guid") ON DELETE CASCADE, "name" TEXT NOT NULL, "truthy" INTEGER, "string" TEXT, "number" REAL, PRIMARY KEY("guid", "name"));`
301
+ `${this.prefix}entities_${etype}`,
302
+ )} ("guid") ON DELETE CASCADE, "name" TEXT NOT NULL, "truthy" INTEGER, "string" TEXT, "number" REAL, PRIMARY KEY("guid", "name"));`,
303
303
  );
304
304
  this.queryRun(
305
305
  `CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
306
- `${this.prefix}comparisons_${etype}_id_guid`
306
+ `${this.prefix}comparisons_${etype}_id_guid`,
307
307
  )} ON ${SQLite3Driver.escape(
308
- `${this.prefix}comparisons_${etype}`
309
- )} ("guid");`
308
+ `${this.prefix}comparisons_${etype}`,
309
+ )} ("guid");`,
310
310
  );
311
311
  this.queryRun(
312
312
  `CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
313
- `${this.prefix}comparisons_${etype}_id_name`
313
+ `${this.prefix}comparisons_${etype}_id_name`,
314
314
  )} ON ${SQLite3Driver.escape(
315
- `${this.prefix}comparisons_${etype}`
316
- )} ("name");`
315
+ `${this.prefix}comparisons_${etype}`,
316
+ )} ("name");`,
317
317
  );
318
318
  this.queryRun(
319
319
  `CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
320
- `${this.prefix}comparisons_${etype}_id_name__truthy`
320
+ `${this.prefix}comparisons_${etype}_id_name__truthy`,
321
321
  )} ON ${SQLite3Driver.escape(
322
- `${this.prefix}comparisons_${etype}`
323
- )} ("name") WHERE "truthy" = 1;`
322
+ `${this.prefix}comparisons_${etype}`,
323
+ )} ("name") WHERE "truthy" = 1;`,
324
324
  );
325
325
  // Create the references table.
326
326
  this.queryRun(
327
327
  `CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(
328
- `${this.prefix}references_${etype}`
328
+ `${this.prefix}references_${etype}`,
329
329
  )} ("guid" CHARACTER(24) NOT NULL REFERENCES ${SQLite3Driver.escape(
330
- `${this.prefix}entities_${etype}`
331
- )} ("guid") ON DELETE CASCADE, "name" TEXT NOT NULL, "reference" CHARACTER(24) NOT NULL, PRIMARY KEY("guid", "name", "reference"));`
330
+ `${this.prefix}entities_${etype}`,
331
+ )} ("guid") ON DELETE CASCADE, "name" TEXT NOT NULL, "reference" CHARACTER(24) NOT NULL, PRIMARY KEY("guid", "name", "reference"));`,
332
332
  );
333
333
  this.queryRun(
334
334
  `CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
335
- `${this.prefix}references_${etype}_id_guid`
335
+ `${this.prefix}references_${etype}_id_guid`,
336
336
  )} ON ${SQLite3Driver.escape(
337
- `${this.prefix}references_${etype}`
338
- )} ("guid");`
337
+ `${this.prefix}references_${etype}`,
338
+ )} ("guid");`,
339
339
  );
340
340
  this.queryRun(
341
341
  `CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
342
- `${this.prefix}references_${etype}_id_name`
342
+ `${this.prefix}references_${etype}_id_name`,
343
343
  )} ON ${SQLite3Driver.escape(
344
- `${this.prefix}references_${etype}`
345
- )} ("name");`
344
+ `${this.prefix}references_${etype}`,
345
+ )} ("name");`,
346
346
  );
347
347
  this.queryRun(
348
348
  `CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
349
- `${this.prefix}references_${etype}_id_reference`
349
+ `${this.prefix}references_${etype}_id_reference`,
350
350
  )} ON ${SQLite3Driver.escape(
351
- `${this.prefix}references_${etype}`
352
- )} ("reference");`
351
+ `${this.prefix}references_${etype}`,
352
+ )} ("reference");`,
353
353
  );
354
354
  } else {
355
355
  // Create the UID table.
356
356
  this.queryRun(
357
357
  `CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(
358
- `${this.prefix}uids`
359
- )} ("name" TEXT PRIMARY KEY NOT NULL, "cur_uid" INTEGER NOT NULL);`
358
+ `${this.prefix}uids`,
359
+ )} ("name" TEXT PRIMARY KEY NOT NULL, "cur_uid" INTEGER NOT NULL);`,
360
360
  );
361
361
  }
362
- this.commit('nymph-tablecreation');
363
- return true;
364
362
  } catch (e: any) {
365
363
  this.rollback('nymph-tablecreation');
366
364
  throw e;
367
365
  }
366
+
367
+ this.commit('nymph-tablecreation');
368
+ return true;
368
369
  }
369
370
 
370
371
  private query<T extends () => any>(
371
372
  runQuery: T,
372
373
  query: string,
373
- etypes: string[] = []
374
+ etypes: string[] = [],
374
375
  ): ReturnType<T> {
375
376
  try {
376
377
  return runQuery();
@@ -390,13 +391,13 @@ export default class SQLite3Driver extends NymphDriver {
390
391
  } catch (e2: any) {
391
392
  throw new QueryFailedError(
392
393
  'Query failed: ' + e2?.code + ' - ' + e2?.message,
393
- query
394
+ query,
394
395
  );
395
396
  }
396
397
  } else {
397
398
  throw new QueryFailedError(
398
399
  'Query failed: ' + e?.code + ' - ' + e?.message,
399
- query
400
+ query,
400
401
  );
401
402
  }
402
403
  }
@@ -407,7 +408,7 @@ export default class SQLite3Driver extends NymphDriver {
407
408
  {
408
409
  etypes = [],
409
410
  params = {},
410
- }: { etypes?: string[]; params?: { [k: string]: any } } = {}
411
+ }: { etypes?: string[]; params?: { [k: string]: any } } = {},
411
412
  ) {
412
413
  return this.query(
413
414
  () =>
@@ -415,7 +416,7 @@ export default class SQLite3Driver extends NymphDriver {
415
416
  .prepare(query)
416
417
  .iterate(params),
417
418
  `${query} -- ${JSON.stringify(params)}`,
418
- etypes
419
+ etypes,
419
420
  );
420
421
  }
421
422
 
@@ -424,13 +425,13 @@ export default class SQLite3Driver extends NymphDriver {
424
425
  {
425
426
  etypes = [],
426
427
  params = {},
427
- }: { etypes?: string[]; params?: { [k: string]: any } } = {}
428
+ }: { etypes?: string[]; params?: { [k: string]: any } } = {},
428
429
  ) {
429
430
  return this.query(
430
431
  () =>
431
432
  (this.store.linkWrite || this.store.link).prepare(query).get(params),
432
433
  `${query} -- ${JSON.stringify(params)}`,
433
- etypes
434
+ etypes,
434
435
  );
435
436
  }
436
437
 
@@ -439,20 +440,20 @@ export default class SQLite3Driver extends NymphDriver {
439
440
  {
440
441
  etypes = [],
441
442
  params = {},
442
- }: { etypes?: string[]; params?: { [k: string]: any } } = {}
443
+ }: { etypes?: string[]; params?: { [k: string]: any } } = {},
443
444
  ) {
444
445
  return this.query(
445
446
  () =>
446
447
  (this.store.linkWrite || this.store.link).prepare(query).run(params),
447
448
  `${query} -- ${JSON.stringify(params)}`,
448
- etypes
449
+ etypes,
449
450
  );
450
451
  }
451
452
 
452
453
  public async commit(name: string) {
453
454
  if (name == null || typeof name !== 'string' || name.length === 0) {
454
455
  throw new InvalidParametersError(
455
- 'Transaction commit attempted without a name.'
456
+ 'Transaction commit attempted without a name.',
456
457
  );
457
458
  }
458
459
  if (this.store.transactionsStarted === 0) {
@@ -476,7 +477,7 @@ export default class SQLite3Driver extends NymphDriver {
476
477
 
477
478
  public async deleteEntityByID(
478
479
  guid: string,
479
- className?: EntityConstructor | string | null
480
+ className?: EntityConstructor | string | null,
480
481
  ) {
481
482
  let EntityClass: EntityConstructor;
482
483
  if (typeof className === 'string' || className == null) {
@@ -490,58 +491,59 @@ export default class SQLite3Driver extends NymphDriver {
490
491
  try {
491
492
  this.queryRun(
492
493
  `DELETE FROM ${SQLite3Driver.escape(
493
- `${this.prefix}entities_${etype}`
494
+ `${this.prefix}entities_${etype}`,
494
495
  )} WHERE "guid"=@guid;`,
495
496
  {
496
497
  etypes: [etype],
497
498
  params: {
498
499
  guid,
499
500
  },
500
- }
501
+ },
501
502
  );
502
503
  this.queryRun(
503
504
  `DELETE FROM ${SQLite3Driver.escape(
504
- `${this.prefix}data_${etype}`
505
+ `${this.prefix}data_${etype}`,
505
506
  )} WHERE "guid"=@guid;`,
506
507
  {
507
508
  etypes: [etype],
508
509
  params: {
509
510
  guid,
510
511
  },
511
- }
512
+ },
512
513
  );
513
514
  this.queryRun(
514
515
  `DELETE FROM ${SQLite3Driver.escape(
515
- `${this.prefix}comparisons_${etype}`
516
+ `${this.prefix}comparisons_${etype}`,
516
517
  )} WHERE "guid"=@guid;`,
517
518
  {
518
519
  etypes: [etype],
519
520
  params: {
520
521
  guid,
521
522
  },
522
- }
523
+ },
523
524
  );
524
525
  this.queryRun(
525
526
  `DELETE FROM ${SQLite3Driver.escape(
526
- `${this.prefix}references_${etype}`
527
+ `${this.prefix}references_${etype}`,
527
528
  )} WHERE "guid"=@guid;`,
528
529
  {
529
530
  etypes: [etype],
530
531
  params: {
531
532
  guid,
532
533
  },
533
- }
534
+ },
534
535
  );
535
- await this.commit('nymph-delete');
536
- // Remove any cached versions of this entity.
537
- if (this.nymph.config.cache) {
538
- this.cleanCache(guid);
539
- }
540
- return true;
541
536
  } catch (e: any) {
542
537
  await this.rollback('nymph-delete');
543
538
  throw e;
544
539
  }
540
+
541
+ await this.commit('nymph-delete');
542
+ // Remove any cached versions of this entity.
543
+ if (this.nymph.config.cache) {
544
+ this.cleanCache(guid);
545
+ }
546
+ return true;
545
547
  }
546
548
 
547
549
  public async deleteUID(name: string) {
@@ -551,13 +553,13 @@ export default class SQLite3Driver extends NymphDriver {
551
553
  await this.startTransaction('nymph-delete-uid');
552
554
  this.queryRun(
553
555
  `DELETE FROM ${SQLite3Driver.escape(
554
- `${this.prefix}uids`
556
+ `${this.prefix}uids`,
555
557
  )} WHERE "name"=@name;`,
556
558
  {
557
559
  params: {
558
560
  name,
559
561
  },
560
- }
562
+ },
561
563
  );
562
564
  await this.commit('nymph-delete-uid');
563
565
  return true;
@@ -579,8 +581,8 @@ export default class SQLite3Driver extends NymphDriver {
579
581
  // Export UIDs.
580
582
  let uids: IterableIterator<any> = this.queryIter(
581
583
  `SELECT * FROM ${SQLite3Driver.escape(
582
- `${this.prefix}uids`
583
- )} ORDER BY "name";`
584
+ `${this.prefix}uids`,
585
+ )} ORDER BY "name";`,
584
586
  );
585
587
  for (const uid of uids) {
586
588
  writeLine(`<${uid.name}>[${uid.cur_uid}]`);
@@ -594,7 +596,7 @@ export default class SQLite3Driver extends NymphDriver {
594
596
 
595
597
  // Get the etypes.
596
598
  const tables: IterableIterator<any> = this.queryIter(
597
- "SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name;"
599
+ "SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name;",
598
600
  );
599
601
  const etypes = [];
600
602
  for (const table of tables) {
@@ -607,12 +609,12 @@ export default class SQLite3Driver extends NymphDriver {
607
609
  // Export entities.
608
610
  const dataIterator: IterableIterator<any> = this.queryIter(
609
611
  `SELECT e.*, d."name" AS "dname", d."value" AS "dvalue", c."string", c."number" FROM ${SQLite3Driver.escape(
610
- `${this.prefix}entities_${etype}`
612
+ `${this.prefix}entities_${etype}`,
611
613
  )} e LEFT JOIN ${SQLite3Driver.escape(
612
- `${this.prefix}data_${etype}`
614
+ `${this.prefix}data_${etype}`,
613
615
  )} d USING ("guid") INNER JOIN ${SQLite3Driver.escape(
614
- `${this.prefix}comparisons_${etype}`
615
- )} c USING ("guid", "name") ORDER BY e."guid";`
616
+ `${this.prefix}comparisons_${etype}`,
617
+ )} c USING ("guid", "name") ORDER BY e."guid";`,
616
618
  )[Symbol.iterator]();
617
619
  let datum = dataIterator.next();
618
620
  while (!datum.done) {
@@ -664,7 +666,7 @@ export default class SQLite3Driver extends NymphDriver {
664
666
  params: { [k: string]: any } = {},
665
667
  subquery = false,
666
668
  tableSuffix = '',
667
- etypes: string[] = []
669
+ etypes: string[] = [],
668
670
  ) {
669
671
  if (typeof options.class?.alterOptions === 'function') {
670
672
  options = options.class.alterOptions(options);
@@ -1368,7 +1370,7 @@ export default class SQLite3Driver extends NymphDriver {
1368
1370
  params,
1369
1371
  true,
1370
1372
  tableSuffix,
1371
- etypes
1373
+ etypes,
1372
1374
  );
1373
1375
  if (curQuery) {
1374
1376
  curQuery += typeIsOr ? ' OR ' : ' AND ';
@@ -1383,7 +1385,7 @@ export default class SQLite3Driver extends NymphDriver {
1383
1385
  case '!qref':
1384
1386
  const [qrefOptions, ...qrefSelectors] = curValue[1] as [
1385
1387
  Options,
1386
- ...FormattedSelector[]
1388
+ ...FormattedSelector[],
1387
1389
  ];
1388
1390
  const QrefEntityClass = qrefOptions.class as EntityConstructor;
1389
1391
  etypes.push(QrefEntityClass.ETYPE);
@@ -1395,7 +1397,7 @@ export default class SQLite3Driver extends NymphDriver {
1395
1397
  params,
1396
1398
  false,
1397
1399
  makeTableSuffix(),
1398
- etypes
1400
+ etypes,
1399
1401
  );
1400
1402
  if (curQuery) {
1401
1403
  curQuery += typeIsOr ? ' OR ' : ' AND ';
@@ -1416,7 +1418,7 @@ export default class SQLite3Driver extends NymphDriver {
1416
1418
  }
1417
1419
  }
1418
1420
  return curQuery;
1419
- }
1421
+ },
1420
1422
  );
1421
1423
 
1422
1424
  let sortBy: string;
@@ -1465,21 +1467,21 @@ export default class SQLite3Driver extends NymphDriver {
1465
1467
  query = `SELECT COUNT("guid") AS "count" FROM (
1466
1468
  SELECT "guid"
1467
1469
  FROM ${SQLite3Driver.escape(
1468
- this.prefix + 'entities_' + etype
1470
+ this.prefix + 'entities_' + etype,
1469
1471
  )} ${ieTable}
1470
1472
  WHERE (${whereClause})${limit}${offset}
1471
1473
  )`;
1472
1474
  } else {
1473
1475
  query = `SELECT COUNT("guid") AS "count"
1474
1476
  FROM ${SQLite3Driver.escape(
1475
- this.prefix + 'entities_' + etype
1477
+ this.prefix + 'entities_' + etype,
1476
1478
  )} ${ieTable}
1477
1479
  WHERE (${whereClause})`;
1478
1480
  }
1479
1481
  } else if (options.return === 'guid') {
1480
1482
  query = `SELECT "guid"
1481
1483
  FROM ${SQLite3Driver.escape(
1482
- this.prefix + 'entities_' + etype
1484
+ this.prefix + 'entities_' + etype,
1483
1485
  )} ${ieTable}
1484
1486
  ${sortJoin}
1485
1487
  WHERE (${whereClause})
@@ -1495,19 +1497,19 @@ export default class SQLite3Driver extends NymphDriver {
1495
1497
  ${cTable}."string",
1496
1498
  ${cTable}."number"
1497
1499
  FROM ${SQLite3Driver.escape(
1498
- this.prefix + 'entities_' + etype
1500
+ this.prefix + 'entities_' + etype,
1499
1501
  )} ${eTable}
1500
1502
  LEFT JOIN ${SQLite3Driver.escape(
1501
- this.prefix + 'data_' + etype
1503
+ this.prefix + 'data_' + etype,
1502
1504
  )} ${dTable} USING ("guid")
1503
1505
  INNER JOIN ${SQLite3Driver.escape(
1504
- this.prefix + 'comparisons_' + etype
1506
+ this.prefix + 'comparisons_' + etype,
1505
1507
  )} ${cTable} USING ("guid", "name")
1506
1508
  ${sortJoin}
1507
1509
  INNER JOIN (
1508
1510
  SELECT "guid"
1509
1511
  FROM ${SQLite3Driver.escape(
1510
- this.prefix + 'entities_' + etype
1512
+ this.prefix + 'entities_' + etype,
1511
1513
  )} ${ieTable}
1512
1514
  ${sortJoin}
1513
1515
  WHERE (${whereClause})
@@ -1533,19 +1535,19 @@ export default class SQLite3Driver extends NymphDriver {
1533
1535
  query = `SELECT COUNT("guid") AS "count" FROM (
1534
1536
  SELECT "guid"
1535
1537
  FROM ${SQLite3Driver.escape(
1536
- this.prefix + 'entities_' + etype
1538
+ this.prefix + 'entities_' + etype,
1537
1539
  )} ${ieTable}${limit}${offset}
1538
1540
  )`;
1539
1541
  } else {
1540
1542
  query = `SELECT COUNT("guid") AS "count"
1541
1543
  FROM ${SQLite3Driver.escape(
1542
- this.prefix + 'entities_' + etype
1544
+ this.prefix + 'entities_' + etype,
1543
1545
  )} ${ieTable}`;
1544
1546
  }
1545
1547
  } else if (options.return === 'guid') {
1546
1548
  query = `SELECT "guid"
1547
1549
  FROM ${SQLite3Driver.escape(
1548
- this.prefix + 'entities_' + etype
1550
+ this.prefix + 'entities_' + etype,
1549
1551
  )} ${ieTable}
1550
1552
  ${sortJoin}
1551
1553
  ORDER BY ${sortByInner}, "guid"${limit}${offset}`;
@@ -1561,19 +1563,19 @@ export default class SQLite3Driver extends NymphDriver {
1561
1563
  ${cTable}."string",
1562
1564
  ${cTable}."number"
1563
1565
  FROM ${SQLite3Driver.escape(
1564
- this.prefix + 'entities_' + etype
1566
+ this.prefix + 'entities_' + etype,
1565
1567
  )} ${eTable}
1566
1568
  LEFT JOIN ${SQLite3Driver.escape(
1567
- this.prefix + 'data_' + etype
1569
+ this.prefix + 'data_' + etype,
1568
1570
  )} ${dTable} USING ("guid")
1569
1571
  INNER JOIN ${SQLite3Driver.escape(
1570
- this.prefix + 'comparisons_' + etype
1572
+ this.prefix + 'comparisons_' + etype,
1571
1573
  )} c USING ("guid", "name")
1572
1574
  ${sortJoin}
1573
1575
  INNER JOIN (
1574
1576
  SELECT "guid"
1575
1577
  FROM ${SQLite3Driver.escape(
1576
- this.prefix + 'entities_' + etype
1578
+ this.prefix + 'entities_' + etype,
1577
1579
  )} ${ieTable}
1578
1580
  ${sortJoin}
1579
1581
  ORDER BY ${sortByInner}${limit}${offset}
@@ -1590,13 +1592,13 @@ export default class SQLite3Driver extends NymphDriver {
1590
1592
  ${cTable}."string",
1591
1593
  ${cTable}."number"
1592
1594
  FROM ${SQLite3Driver.escape(
1593
- this.prefix + 'entities_' + etype
1595
+ this.prefix + 'entities_' + etype,
1594
1596
  )} ${eTable}
1595
1597
  LEFT JOIN ${SQLite3Driver.escape(
1596
- this.prefix + 'data_' + etype
1598
+ this.prefix + 'data_' + etype,
1597
1599
  )} ${dTable} USING ("guid")
1598
1600
  INNER JOIN ${SQLite3Driver.escape(
1599
- this.prefix + 'comparisons_' + etype
1601
+ this.prefix + 'comparisons_' + etype,
1600
1602
  )} ${cTable} USING ("guid", "name")
1601
1603
  ${sortJoin}
1602
1604
  ORDER BY ${sortBy}, ${eTable}."guid"`;
@@ -1619,14 +1621,14 @@ export default class SQLite3Driver extends NymphDriver {
1619
1621
  protected performQuery(
1620
1622
  options: Options,
1621
1623
  formattedSelectors: FormattedSelector[],
1622
- etype: string
1624
+ etype: string,
1623
1625
  ): {
1624
1626
  result: any;
1625
1627
  } {
1626
1628
  const { query, params, etypes } = this.makeEntityQuery(
1627
1629
  options,
1628
1630
  formattedSelectors,
1629
- etype
1631
+ etype,
1630
1632
  );
1631
1633
  const result = this.queryIter(query, { etypes, params })[Symbol.iterator]();
1632
1634
  return {
@@ -1675,7 +1677,7 @@ export default class SQLite3Driver extends NymphDriver {
1675
1677
  : row.value === 'S'
1676
1678
  ? JSON.stringify(row.string)
1677
1679
  : row.value,
1678
- })
1680
+ }),
1679
1681
  );
1680
1682
  const value = process();
1681
1683
  if (value instanceof Error) {
@@ -1690,13 +1692,13 @@ export default class SQLite3Driver extends NymphDriver {
1690
1692
  }
1691
1693
  const result: any = this.queryGet(
1692
1694
  `SELECT "cur_uid" FROM ${SQLite3Driver.escape(
1693
- `${this.prefix}uids`
1695
+ `${this.prefix}uids`,
1694
1696
  )} WHERE "name"=@name;`,
1695
1697
  {
1696
1698
  params: {
1697
1699
  name: name,
1698
1700
  },
1699
- }
1701
+ },
1700
1702
  );
1701
1703
  return (result?.cur_uid as number | null) ?? null;
1702
1704
  }
@@ -1708,51 +1710,51 @@ export default class SQLite3Driver extends NymphDriver {
1708
1710
  async (guid, tags, sdata, etype) => {
1709
1711
  this.queryRun(
1710
1712
  `DELETE FROM ${SQLite3Driver.escape(
1711
- `${this.prefix}entities_${etype}`
1713
+ `${this.prefix}entities_${etype}`,
1712
1714
  )} WHERE "guid"=@guid;`,
1713
1715
  {
1714
1716
  etypes: [etype],
1715
1717
  params: {
1716
1718
  guid,
1717
1719
  },
1718
- }
1720
+ },
1719
1721
  );
1720
1722
  this.queryRun(
1721
1723
  `DELETE FROM ${SQLite3Driver.escape(
1722
- `${this.prefix}data_${etype}`
1724
+ `${this.prefix}data_${etype}`,
1723
1725
  )} WHERE "guid"=@guid;`,
1724
1726
  {
1725
1727
  etypes: [etype],
1726
1728
  params: {
1727
1729
  guid,
1728
1730
  },
1729
- }
1731
+ },
1730
1732
  );
1731
1733
  this.queryRun(
1732
1734
  `DELETE FROM ${SQLite3Driver.escape(
1733
- `${this.prefix}comparisons_${etype}`
1735
+ `${this.prefix}comparisons_${etype}`,
1734
1736
  )} WHERE "guid"=@guid;`,
1735
1737
  {
1736
1738
  etypes: [etype],
1737
1739
  params: {
1738
1740
  guid,
1739
1741
  },
1740
- }
1742
+ },
1741
1743
  );
1742
1744
  this.queryRun(
1743
1745
  `DELETE FROM ${SQLite3Driver.escape(
1744
- `${this.prefix}references_${etype}`
1746
+ `${this.prefix}references_${etype}`,
1745
1747
  )} WHERE "guid"=@guid;`,
1746
1748
  {
1747
1749
  etypes: [etype],
1748
1750
  params: {
1749
1751
  guid,
1750
1752
  },
1751
- }
1753
+ },
1752
1754
  );
1753
1755
  this.queryRun(
1754
1756
  `INSERT INTO ${SQLite3Driver.escape(
1755
- `${this.prefix}entities_${etype}`
1757
+ `${this.prefix}entities_${etype}`,
1756
1758
  )} ("guid", "tags", "cdate", "mdate") VALUES (@guid, @tags, @cdate, @mdate);`,
1757
1759
  {
1758
1760
  etypes: [etype],
@@ -1762,7 +1764,7 @@ export default class SQLite3Driver extends NymphDriver {
1762
1764
  cdate: Number(JSON.parse(sdata.cdate)),
1763
1765
  mdate: Number(JSON.parse(sdata.mdate)),
1764
1766
  },
1765
- }
1767
+ },
1766
1768
  );
1767
1769
  delete sdata.cdate;
1768
1770
  delete sdata.mdate;
@@ -1780,7 +1782,7 @@ export default class SQLite3Driver extends NymphDriver {
1780
1782
  : value;
1781
1783
  this.queryRun(
1782
1784
  `INSERT INTO ${SQLite3Driver.escape(
1783
- `${this.prefix}data_${etype}`
1785
+ `${this.prefix}data_${etype}`,
1784
1786
  )} ("guid", "name", "value") VALUES (@guid, @name, @storageValue);`,
1785
1787
  {
1786
1788
  etypes: [etype],
@@ -1789,11 +1791,11 @@ export default class SQLite3Driver extends NymphDriver {
1789
1791
  name,
1790
1792
  storageValue,
1791
1793
  },
1792
- }
1794
+ },
1793
1795
  );
1794
1796
  this.queryRun(
1795
1797
  `INSERT INTO ${SQLite3Driver.escape(
1796
- `${this.prefix}comparisons_${etype}`
1798
+ `${this.prefix}comparisons_${etype}`,
1797
1799
  )} ("guid", "name", "truthy", "string", "number") VALUES (@guid, @name, @truthy, @string, @number);`,
1798
1800
  {
1799
1801
  etypes: [etype],
@@ -1804,13 +1806,13 @@ export default class SQLite3Driver extends NymphDriver {
1804
1806
  string: `${uvalue}`,
1805
1807
  number: Number(uvalue),
1806
1808
  },
1807
- }
1809
+ },
1808
1810
  );
1809
1811
  const references = this.findReferences(value);
1810
1812
  for (const reference of references) {
1811
1813
  this.queryRun(
1812
1814
  `INSERT INTO ${SQLite3Driver.escape(
1813
- `${this.prefix}references_${etype}`
1815
+ `${this.prefix}references_${etype}`,
1814
1816
  )} ("guid", "name", "reference") VALUES (@guid, @name, @reference);`,
1815
1817
  {
1816
1818
  etypes: [etype],
@@ -1819,7 +1821,7 @@ export default class SQLite3Driver extends NymphDriver {
1819
1821
  name,
1820
1822
  reference,
1821
1823
  },
1822
- }
1824
+ },
1823
1825
  );
1824
1826
  }
1825
1827
  }
@@ -1827,24 +1829,24 @@ export default class SQLite3Driver extends NymphDriver {
1827
1829
  async (name, curUid) => {
1828
1830
  this.queryRun(
1829
1831
  `DELETE FROM ${SQLite3Driver.escape(
1830
- `${this.prefix}uids`
1832
+ `${this.prefix}uids`,
1831
1833
  )} WHERE "name"=@name;`,
1832
1834
  {
1833
1835
  params: {
1834
1836
  name,
1835
1837
  },
1836
- }
1838
+ },
1837
1839
  );
1838
1840
  this.queryRun(
1839
1841
  `INSERT INTO ${SQLite3Driver.escape(
1840
- `${this.prefix}uids`
1842
+ `${this.prefix}uids`,
1841
1843
  )} ("name", "cur_uid") VALUES (@name, @curUid);`,
1842
1844
  {
1843
1845
  params: {
1844
1846
  name,
1845
1847
  curUid,
1846
1848
  },
1847
- }
1849
+ },
1848
1850
  );
1849
1851
  },
1850
1852
  async () => {
@@ -1852,7 +1854,7 @@ export default class SQLite3Driver extends NymphDriver {
1852
1854
  },
1853
1855
  async () => {
1854
1856
  await this.commit('nymph-import');
1855
- }
1857
+ },
1856
1858
  );
1857
1859
  } catch (e: any) {
1858
1860
  await this.rollback('nymph-import');
@@ -1865,53 +1867,55 @@ export default class SQLite3Driver extends NymphDriver {
1865
1867
  throw new InvalidParametersError('Name not given for UID.');
1866
1868
  }
1867
1869
  await this.startTransaction('nymph-newuid');
1870
+ let curUid: number | undefined = undefined;
1868
1871
  try {
1869
- let curUid =
1872
+ curUid =
1870
1873
  (
1871
1874
  this.queryGet(
1872
1875
  `SELECT "cur_uid" FROM ${SQLite3Driver.escape(
1873
- `${this.prefix}uids`
1876
+ `${this.prefix}uids`,
1874
1877
  )} WHERE "name"=@name;`,
1875
1878
  {
1876
1879
  params: {
1877
1880
  name,
1878
1881
  },
1879
- }
1882
+ },
1880
1883
  ) as any
1881
1884
  )?.cur_uid ?? null;
1882
1885
  if (curUid == null) {
1883
1886
  curUid = 1;
1884
1887
  this.queryRun(
1885
1888
  `INSERT INTO ${SQLite3Driver.escape(
1886
- `${this.prefix}uids`
1889
+ `${this.prefix}uids`,
1887
1890
  )} ("name", "cur_uid") VALUES (@name, @curUid);`,
1888
1891
  {
1889
1892
  params: {
1890
1893
  name,
1891
1894
  curUid,
1892
1895
  },
1893
- }
1896
+ },
1894
1897
  );
1895
1898
  } else {
1896
1899
  curUid++;
1897
1900
  this.queryRun(
1898
1901
  `UPDATE ${SQLite3Driver.escape(
1899
- `${this.prefix}uids`
1902
+ `${this.prefix}uids`,
1900
1903
  )} SET "cur_uid"=@curUid WHERE "name"=@name;`,
1901
1904
  {
1902
1905
  params: {
1903
1906
  curUid,
1904
1907
  name,
1905
1908
  },
1906
- }
1909
+ },
1907
1910
  );
1908
1911
  }
1909
- await this.commit('nymph-newuid');
1910
- return curUid as number;
1911
1912
  } catch (e: any) {
1912
1913
  await this.rollback('nymph-newuid');
1913
1914
  throw e;
1914
1915
  }
1916
+
1917
+ await this.commit('nymph-newuid');
1918
+ return curUid as number;
1915
1919
  }
1916
1920
 
1917
1921
  public async renameUID(oldName: string, newName: string) {
@@ -1921,14 +1925,14 @@ export default class SQLite3Driver extends NymphDriver {
1921
1925
  await this.startTransaction('nymph-rename-uid');
1922
1926
  this.queryRun(
1923
1927
  `UPDATE ${SQLite3Driver.escape(
1924
- `${this.prefix}uids`
1928
+ `${this.prefix}uids`,
1925
1929
  )} SET "name"=@newName WHERE "name"=@oldName;`,
1926
1930
  {
1927
1931
  params: {
1928
1932
  newName,
1929
1933
  oldName,
1930
1934
  },
1931
- }
1935
+ },
1932
1936
  );
1933
1937
  await this.commit('nymph-rename-uid');
1934
1938
  return true;
@@ -1937,7 +1941,7 @@ export default class SQLite3Driver extends NymphDriver {
1937
1941
  public async rollback(name: string) {
1938
1942
  if (name == null || typeof name !== 'string' || name.length === 0) {
1939
1943
  throw new InvalidParametersError(
1940
- 'Transaction rollback attempted without a name.'
1944
+ 'Transaction rollback attempted without a name.',
1941
1945
  );
1942
1946
  }
1943
1947
  if (this.store.transactionsStarted === 0) {
@@ -1964,7 +1968,7 @@ export default class SQLite3Driver extends NymphDriver {
1964
1968
  guid: string,
1965
1969
  data: EntityData,
1966
1970
  sdata: SerializedEntityData,
1967
- etype: string
1971
+ etype: string,
1968
1972
  ) => {
1969
1973
  const runInsertQuery = (name: string, value: any, svalue: string) => {
1970
1974
  if (value === undefined) {
@@ -1978,7 +1982,7 @@ export default class SQLite3Driver extends NymphDriver {
1978
1982
  : svalue;
1979
1983
  this.queryRun(
1980
1984
  `INSERT INTO ${SQLite3Driver.escape(
1981
- `${this.prefix}data_${etype}`
1985
+ `${this.prefix}data_${etype}`,
1982
1986
  )} ("guid", "name", "value") VALUES (@guid, @name, @storageValue);`,
1983
1987
  {
1984
1988
  etypes: [etype],
@@ -1987,11 +1991,11 @@ export default class SQLite3Driver extends NymphDriver {
1987
1991
  name,
1988
1992
  storageValue,
1989
1993
  },
1990
- }
1994
+ },
1991
1995
  );
1992
1996
  this.queryRun(
1993
1997
  `INSERT INTO ${SQLite3Driver.escape(
1994
- `${this.prefix}comparisons_${etype}`
1998
+ `${this.prefix}comparisons_${etype}`,
1995
1999
  )} ("guid", "name", "truthy", "string", "number") VALUES (@guid, @name, @truthy, @string, @number);`,
1996
2000
  {
1997
2001
  etypes: [etype],
@@ -2002,13 +2006,13 @@ export default class SQLite3Driver extends NymphDriver {
2002
2006
  string: `${value}`,
2003
2007
  number: Number(value),
2004
2008
  },
2005
- }
2009
+ },
2006
2010
  );
2007
2011
  const references = this.findReferences(svalue);
2008
2012
  for (const reference of references) {
2009
2013
  this.queryRun(
2010
2014
  `INSERT INTO ${SQLite3Driver.escape(
2011
- `${this.prefix}references_${etype}`
2015
+ `${this.prefix}references_${etype}`,
2012
2016
  )} ("guid", "name", "reference") VALUES (@guid, @name, @reference);`,
2013
2017
  {
2014
2018
  etypes: [etype],
@@ -2017,7 +2021,7 @@ export default class SQLite3Driver extends NymphDriver {
2017
2021
  name,
2018
2022
  reference,
2019
2023
  },
2020
- }
2024
+ },
2021
2025
  );
2022
2026
  }
2023
2027
  };
@@ -2028,6 +2032,7 @@ export default class SQLite3Driver extends NymphDriver {
2028
2032
  runInsertQuery(name, JSON.parse(sdata[name]), sdata[name]);
2029
2033
  }
2030
2034
  };
2035
+ let inTransaction = false;
2031
2036
  try {
2032
2037
  return this.saveEntityRowLike(
2033
2038
  entity,
@@ -2040,7 +2045,7 @@ export default class SQLite3Driver extends NymphDriver {
2040
2045
  }
2041
2046
  this.queryRun(
2042
2047
  `INSERT INTO ${SQLite3Driver.escape(
2043
- `${this.prefix}entities_${etype}`
2048
+ `${this.prefix}entities_${etype}`,
2044
2049
  )} ("guid", "tags", "cdate", "mdate") VALUES (@guid, @tags, @cdate, @cdate);`,
2045
2050
  {
2046
2051
  etypes: [etype],
@@ -2049,7 +2054,7 @@ export default class SQLite3Driver extends NymphDriver {
2049
2054
  tags: ',' + tags.join(',') + ',',
2050
2055
  cdate,
2051
2056
  },
2052
- }
2057
+ },
2053
2058
  );
2054
2059
  insertData(guid, data, sdata, etype);
2055
2060
  return true;
@@ -2063,7 +2068,7 @@ export default class SQLite3Driver extends NymphDriver {
2063
2068
  }
2064
2069
  const info = this.queryRun(
2065
2070
  `UPDATE ${SQLite3Driver.escape(
2066
- `${this.prefix}entities_${etype}`
2071
+ `${this.prefix}entities_${etype}`,
2067
2072
  )} SET "tags"=@tags, "mdate"=@mdate WHERE "guid"=@guid AND "mdate" <= @emdate;`,
2068
2073
  {
2069
2074
  etypes: [etype],
@@ -2073,42 +2078,42 @@ export default class SQLite3Driver extends NymphDriver {
2073
2078
  guid,
2074
2079
  emdate: Number(entity.mdate),
2075
2080
  },
2076
- }
2081
+ },
2077
2082
  );
2078
2083
  let success = false;
2079
2084
  if (info.changes === 1) {
2080
2085
  this.queryRun(
2081
2086
  `DELETE FROM ${SQLite3Driver.escape(
2082
- `${this.prefix}data_${etype}`
2087
+ `${this.prefix}data_${etype}`,
2083
2088
  )} WHERE "guid"=@guid;`,
2084
2089
  {
2085
2090
  etypes: [etype],
2086
2091
  params: {
2087
2092
  guid,
2088
2093
  },
2089
- }
2094
+ },
2090
2095
  );
2091
2096
  this.queryRun(
2092
2097
  `DELETE FROM ${SQLite3Driver.escape(
2093
- `${this.prefix}comparisons_${etype}`
2098
+ `${this.prefix}comparisons_${etype}`,
2094
2099
  )} WHERE "guid"=@guid;`,
2095
2100
  {
2096
2101
  etypes: [etype],
2097
2102
  params: {
2098
2103
  guid,
2099
2104
  },
2100
- }
2105
+ },
2101
2106
  );
2102
2107
  this.queryRun(
2103
2108
  `DELETE FROM ${SQLite3Driver.escape(
2104
- `${this.prefix}references_${etype}`
2109
+ `${this.prefix}references_${etype}`,
2105
2110
  )} WHERE "guid"=@guid;`,
2106
2111
  {
2107
2112
  etypes: [etype],
2108
2113
  params: {
2109
2114
  guid,
2110
2115
  },
2111
- }
2116
+ },
2112
2117
  );
2113
2118
  insertData(guid, data, sdata, etype);
2114
2119
  success = true;
@@ -2117,18 +2122,24 @@ export default class SQLite3Driver extends NymphDriver {
2117
2122
  },
2118
2123
  async () => {
2119
2124
  await this.startTransaction('nymph-save');
2125
+ inTransaction = true;
2120
2126
  },
2121
2127
  async (success) => {
2122
- if (success) {
2123
- await this.commit('nymph-save');
2124
- } else {
2125
- await this.rollback('nymph-save');
2128
+ if (inTransaction) {
2129
+ inTransaction = false;
2130
+ if (success) {
2131
+ await this.commit('nymph-save');
2132
+ } else {
2133
+ await this.rollback('nymph-save');
2134
+ }
2126
2135
  }
2127
2136
  return success;
2128
- }
2137
+ },
2129
2138
  );
2130
2139
  } catch (e: any) {
2131
- await this.rollback('nymph-save');
2140
+ if (inTransaction) {
2141
+ await this.rollback('nymph-save');
2142
+ }
2132
2143
  throw e;
2133
2144
  }
2134
2145
  }
@@ -2140,24 +2151,24 @@ export default class SQLite3Driver extends NymphDriver {
2140
2151
  await this.startTransaction('nymph-set-uid');
2141
2152
  this.queryRun(
2142
2153
  `DELETE FROM ${SQLite3Driver.escape(
2143
- `${this.prefix}uids`
2154
+ `${this.prefix}uids`,
2144
2155
  )} WHERE "name"=@name;`,
2145
2156
  {
2146
2157
  params: {
2147
2158
  name,
2148
2159
  },
2149
- }
2160
+ },
2150
2161
  );
2151
2162
  this.queryRun(
2152
2163
  `INSERT INTO ${SQLite3Driver.escape(
2153
- `${this.prefix}uids`
2164
+ `${this.prefix}uids`,
2154
2165
  )} ("name", "cur_uid") VALUES (@name, @curUid);`,
2155
2166
  {
2156
2167
  params: {
2157
2168
  name,
2158
2169
  curUid,
2159
2170
  },
2160
- }
2171
+ },
2161
2172
  );
2162
2173
  await this.commit('nymph-set-uid');
2163
2174
  return true;
@@ -2166,7 +2177,7 @@ export default class SQLite3Driver extends NymphDriver {
2166
2177
  public async startTransaction(name: string) {
2167
2178
  if (name == null || typeof name !== 'string' || name.length === 0) {
2168
2179
  throw new InvalidParametersError(
2169
- 'Transaction start attempted without a name.'
2180
+ 'Transaction start attempted without a name.',
2170
2181
  );
2171
2182
  }
2172
2183
  if (!this.config.explicitWrite && !this.store.linkWrite) {