@nymphjs/driver-postgresql 1.0.0-beta.62 → 1.0.0-beta.63

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,17 @@
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.63](https://github.com/sciactive/nymphjs/compare/v1.0.0-beta.62...v1.0.0-beta.63) (2024-06-18)
7
+
8
+ ### Bug Fixes
9
+
10
+ - undo ts compilation to module change ([84be6d4](https://github.com/sciactive/nymphjs/commit/84be6d434be29f8afd53907d15be2eb77d1736ce))
11
+
12
+ ### Features
13
+
14
+ - allow importing from text and iterables ([9d766bd](https://github.com/sciactive/nymphjs/commit/9d766bdad4b0f17bc2dd68b0336a0064857eb4e9))
15
+ - export data iterator ([b86aa19](https://github.com/sciactive/nymphjs/commit/b86aa19fc77d744b5a683046dfb697fc4746df5c))
16
+
6
17
  # [1.0.0-beta.62](https://github.com/sciactive/nymphjs/compare/v1.0.0-beta.61...v1.0.0-beta.62) (2024-06-15)
7
18
 
8
19
  **Note:** Version bump only for package @nymphjs/driver-postgresql
@@ -1,5 +1,5 @@
1
1
  import { Pool, PoolClient } from 'pg';
2
- import { NymphDriver, type EntityConstructor, type EntityInterface, type EntityInstanceType, type FormattedSelector, type Options, type Selector } from '@nymphjs/nymph';
2
+ import { NymphDriver, type EntityConstructor, type EntityInterface, type EntityInstanceType, type SerializedEntityData, type FormattedSelector, type Options, type Selector } from '@nymphjs/nymph';
3
3
  import { PostgreSQLDriverConfig } from './conf';
4
4
  type PostgreSQLDriverConnection = {
5
5
  client: PoolClient;
@@ -63,7 +63,10 @@ export default class PostgreSQLDriver extends NymphDriver {
63
63
  commit(name: string): Promise<boolean>;
64
64
  deleteEntityByID(guid: string, className?: EntityConstructor | string | null): Promise<boolean>;
65
65
  deleteUID(name: string): Promise<boolean>;
66
- protected exportEntities(writeLine: (line: string) => void): Promise<void>;
66
+ exportDataIterator(): AsyncGenerator<{
67
+ type: 'comment' | 'uid' | 'entity';
68
+ content: string;
69
+ }, void, false | undefined>;
67
70
  /**
68
71
  * Generate the PostgreSQL query.
69
72
  * @param options The options array.
@@ -86,13 +89,24 @@ export default class PostgreSQLDriver extends NymphDriver {
86
89
  }, ...selectors: Selector[]): Promise<string[]>;
87
90
  getEntities<T extends EntityConstructor = EntityConstructor>(options?: Options<T>, ...selectors: Selector[]): Promise<EntityInstanceType<T>[]>;
88
91
  getUID(name: string): Promise<number | null>;
89
- import(filename: string, transaction?: boolean): Promise<boolean>;
92
+ importEntity({ guid, cdate, mdate, tags, sdata, etype, }: {
93
+ guid: string;
94
+ cdate: number;
95
+ mdate: number;
96
+ tags: string[];
97
+ sdata: SerializedEntityData;
98
+ etype: string;
99
+ }): Promise<void>;
100
+ importUID({ name, value }: {
101
+ name: string;
102
+ value: number;
103
+ }): Promise<void>;
90
104
  newUID(name: string): Promise<number>;
91
105
  renameUID(oldName: string, newName: string): Promise<boolean>;
92
106
  rollback(name: string): Promise<boolean>;
93
107
  saveEntity(entity: EntityInterface): Promise<boolean>;
94
108
  setUID(name: string, curUid: number): Promise<boolean>;
95
- private internalTransaction;
109
+ protected internalTransaction(name: string): Promise<PostgreSQLDriverTransaction>;
96
110
  startTransaction(name: string): Promise<import("@nymphjs/nymph").Nymph>;
97
111
  }
98
112
  export {};
@@ -12,6 +12,13 @@ const conf_1 = require("./conf");
12
12
  * The PostgreSQL Nymph database driver.
13
13
  */
14
14
  class PostgreSQLDriver extends nymph_1.NymphDriver {
15
+ config;
16
+ postgresqlConfig;
17
+ prefix;
18
+ connected = false;
19
+ // @ts-ignore: this is assigned in connect(), which is called by the constructor.
20
+ link;
21
+ transaction = null;
15
22
  static escape(input) {
16
23
  return pg_format_1.default.ident(input);
17
24
  }
@@ -20,8 +27,6 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
20
27
  }
21
28
  constructor(config, link, transaction) {
22
29
  super();
23
- this.connected = false;
24
- this.transaction = null;
25
30
  this.config = { ...conf_1.PostgreSQLDriverConfigDefaults, ...config };
26
31
  const { host, user, password, database, port, customPoolConfig } = this.config;
27
32
  this.postgresqlConfig = customPoolConfig ?? {
@@ -398,27 +403,49 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
398
403
  });
399
404
  return true;
400
405
  }
401
- async exportEntities(writeLine) {
402
- writeLine('#nex2');
403
- writeLine('# Nymph Entity Exchange v2');
404
- writeLine('# http://nymph.io');
405
- writeLine('#');
406
- writeLine('# Generation Time: ' + new Date().toLocaleString());
407
- writeLine('');
408
- writeLine('#');
409
- writeLine('# UIDs');
410
- writeLine('#');
411
- writeLine('');
406
+ async *exportDataIterator() {
407
+ if (yield {
408
+ type: 'comment',
409
+ content: `#nex2
410
+ # Nymph Entity Exchange v2
411
+ # http://nymph.io
412
+ #
413
+ # Generation Time: ${new Date().toLocaleString()}
414
+ `,
415
+ }) {
416
+ return;
417
+ }
418
+ if (yield {
419
+ type: 'comment',
420
+ content: `
421
+
422
+ #
423
+ # UIDs
424
+ #
425
+
426
+ `,
427
+ }) {
428
+ return;
429
+ }
412
430
  // Export UIDs.
413
431
  let uids = await this.queryIter(`SELECT * FROM ${PostgreSQLDriver.escape(`${this.prefix}uids`)} ORDER BY "name";`);
414
432
  for (const uid of uids) {
415
- writeLine(`<${uid.name}>[${uid.cur_uid}]`);
433
+ if (yield { type: 'uid', content: `<${uid.name}>[${uid.cur_uid}]\n` }) {
434
+ return;
435
+ }
436
+ }
437
+ if (yield {
438
+ type: 'comment',
439
+ content: `
440
+
441
+ #
442
+ # Entities
443
+ #
444
+
445
+ `,
446
+ }) {
447
+ return;
416
448
  }
417
- writeLine('');
418
- writeLine('#');
419
- writeLine('# Entities');
420
- writeLine('#');
421
- writeLine('');
422
449
  // Get the etypes.
423
450
  const tables = await this.queryIter('SELECT relname FROM pg_stat_user_tables ORDER BY relname;');
424
451
  const etypes = [];
@@ -441,9 +468,10 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
441
468
  const tags = datum.value.tags.join(',');
442
469
  const cdate = datum.value.cdate;
443
470
  const mdate = datum.value.mdate;
444
- writeLine(`{${guid}}<${etype}>[${tags}]`);
445
- writeLine(`\tcdate=${JSON.stringify(cdate)}`);
446
- writeLine(`\tmdate=${JSON.stringify(mdate)}`);
471
+ let currentEntityExport = [];
472
+ currentEntityExport.push(`{${guid}}<${etype}>[${tags}]`);
473
+ currentEntityExport.push(`\tcdate=${JSON.stringify(cdate)}`);
474
+ currentEntityExport.push(`\tmdate=${JSON.stringify(mdate)}`);
447
475
  if (datum.value.dname != null) {
448
476
  // This do will keep going and adding the data until the
449
477
  // next entity is reached. $row will end on the next entity.
@@ -453,7 +481,7 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
453
481
  : datum.value.dvalue === 'S'
454
482
  ? JSON.stringify(datum.value.string)
455
483
  : datum.value.dvalue;
456
- writeLine(`\t${datum.value.dname}=${value}`);
484
+ currentEntityExport.push(`\t${datum.value.dname}=${value}`);
457
485
  datum = dataIterator.next();
458
486
  } while (!datum.done && datum.value.guid === guid);
459
487
  }
@@ -461,9 +489,12 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
461
489
  // Make sure that datum is incremented :)
462
490
  datum = dataIterator.next();
463
491
  }
492
+ currentEntityExport.push('');
493
+ if (yield { type: 'entity', content: currentEntityExport.join('\n') }) {
494
+ return;
495
+ }
464
496
  }
465
497
  }
466
- return;
467
498
  }
468
499
  /**
469
500
  * Generate the PostgreSQL query.
@@ -1481,161 +1512,138 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
1481
1512
  });
1482
1513
  return result?.cur_uid == null ? null : Number(result.cur_uid);
1483
1514
  }
1484
- async import(filename, transaction) {
1515
+ async importEntity({ guid, cdate, mdate, tags, sdata, etype, }) {
1485
1516
  try {
1486
- const result = await this.importFromFile(filename, async (guid, tags, sdata, etype) => {
1487
- try {
1488
- await this.internalTransaction(`nymph-import-entity-${guid}`);
1489
- const cdate = Number(JSON.parse(sdata.cdate));
1490
- delete sdata.cdate;
1491
- const mdate = Number(JSON.parse(sdata.mdate));
1492
- delete sdata.mdate;
1493
- await this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1494
- etypes: [etype],
1495
- params: {
1496
- guid,
1497
- },
1498
- });
1499
- await this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} ("guid", "tags", "cdate", "mdate") VALUES (decode(@guid, 'hex'), @tags, @cdate, @mdate);`, {
1500
- etypes: [etype],
1501
- params: {
1502
- guid,
1503
- tags,
1504
- cdate: isNaN(cdate) ? null : cdate,
1505
- mdate: isNaN(mdate) ? null : mdate,
1506
- },
1507
- });
1508
- const promises = [];
1509
- promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}data_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1510
- etypes: [etype],
1511
- params: {
1512
- guid,
1513
- },
1514
- }));
1515
- promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}comparisons_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1516
- etypes: [etype],
1517
- params: {
1518
- guid,
1519
- },
1520
- }));
1521
- promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}references_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1522
- etypes: [etype],
1523
- params: {
1524
- guid,
1525
- },
1526
- }));
1527
- promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}uniques_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1517
+ await this.internalTransaction(`nymph-import-entity-${guid}`);
1518
+ await this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1519
+ etypes: [etype],
1520
+ params: {
1521
+ guid,
1522
+ },
1523
+ });
1524
+ await this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} ("guid", "tags", "cdate", "mdate") VALUES (decode(@guid, 'hex'), @tags, @cdate, @mdate);`, {
1525
+ etypes: [etype],
1526
+ params: {
1527
+ guid,
1528
+ tags,
1529
+ cdate: isNaN(cdate) ? null : cdate,
1530
+ mdate: isNaN(mdate) ? null : mdate,
1531
+ },
1532
+ });
1533
+ const promises = [];
1534
+ promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}data_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1535
+ etypes: [etype],
1536
+ params: {
1537
+ guid,
1538
+ },
1539
+ }));
1540
+ promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}comparisons_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1541
+ etypes: [etype],
1542
+ params: {
1543
+ guid,
1544
+ },
1545
+ }));
1546
+ promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}references_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1547
+ etypes: [etype],
1548
+ params: {
1549
+ guid,
1550
+ },
1551
+ }));
1552
+ promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}uniques_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1553
+ etypes: [etype],
1554
+ params: {
1555
+ guid,
1556
+ },
1557
+ }));
1558
+ await Promise.all(promises);
1559
+ for (const name in sdata) {
1560
+ const value = sdata[name];
1561
+ const uvalue = JSON.parse(value);
1562
+ if (value === undefined) {
1563
+ continue;
1564
+ }
1565
+ const storageValue = typeof uvalue === 'number'
1566
+ ? 'N'
1567
+ : typeof uvalue === 'string'
1568
+ ? 'S'
1569
+ : value;
1570
+ const promises = [];
1571
+ promises.push(this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}data_${etype}`)} ("guid", "name", "value") VALUES (decode(@guid, 'hex'), @name, @storageValue);`, {
1572
+ etypes: [etype],
1573
+ params: {
1574
+ guid,
1575
+ name,
1576
+ storageValue,
1577
+ },
1578
+ }));
1579
+ promises.push(this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}comparisons_${etype}`)} ("guid", "name", "truthy", "string", "number") VALUES (decode(@guid, 'hex'), @name, @truthy, @string, @number);`, {
1580
+ etypes: [etype],
1581
+ params: {
1582
+ guid,
1583
+ name,
1584
+ truthy: !!uvalue,
1585
+ string: `${uvalue}`,
1586
+ number: isNaN(Number(uvalue)) ? null : Number(uvalue),
1587
+ },
1588
+ }));
1589
+ const references = this.findReferences(value);
1590
+ for (const reference of references) {
1591
+ promises.push(this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}references_${etype}`)} ("guid", "name", "reference") VALUES (decode(@guid, 'hex'), @name, decode(@reference, 'hex'));`, {
1528
1592
  etypes: [etype],
1529
1593
  params: {
1530
1594
  guid,
1531
- },
1532
- }));
1533
- await Promise.all(promises);
1534
- for (const name in sdata) {
1535
- const value = sdata[name];
1536
- const uvalue = JSON.parse(value);
1537
- if (value === undefined) {
1538
- continue;
1539
- }
1540
- const storageValue = typeof uvalue === 'number'
1541
- ? 'N'
1542
- : typeof uvalue === 'string'
1543
- ? 'S'
1544
- : value;
1545
- const promises = [];
1546
- promises.push(this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}data_${etype}`)} ("guid", "name", "value") VALUES (decode(@guid, 'hex'), @name, @storageValue);`, {
1547
- etypes: [etype],
1548
- params: {
1549
- guid,
1550
- name,
1551
- storageValue,
1552
- },
1553
- }));
1554
- promises.push(this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}comparisons_${etype}`)} ("guid", "name", "truthy", "string", "number") VALUES (decode(@guid, 'hex'), @name, @truthy, @string, @number);`, {
1555
- etypes: [etype],
1556
- params: {
1557
- guid,
1558
- name,
1559
- truthy: !!uvalue,
1560
- string: `${uvalue}`,
1561
- number: isNaN(Number(uvalue)) ? null : Number(uvalue),
1562
- },
1563
- }));
1564
- const references = this.findReferences(value);
1565
- for (const reference of references) {
1566
- promises.push(this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}references_${etype}`)} ("guid", "name", "reference") VALUES (decode(@guid, 'hex'), @name, decode(@reference, 'hex'));`, {
1567
- etypes: [etype],
1568
- params: {
1569
- guid,
1570
- name,
1571
- reference,
1572
- },
1573
- }));
1574
- }
1575
- }
1576
- const uniques = await this.nymph
1577
- .getEntityClassByEtype(etype)
1578
- .getUniques({ guid, cdate, mdate, tags, data: {}, sdata });
1579
- for (const unique of uniques) {
1580
- promises.push(this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}uniques_${etype}`)} ("guid", "unique") VALUES (decode(@guid, 'hex'), @unique);`, {
1581
- etypes: [etype],
1582
- params: {
1583
- guid,
1584
- unique,
1585
- },
1586
- }).catch((e) => {
1587
- if (e instanceof nymph_1.EntityUniqueConstraintError) {
1588
- this.nymph.config.debugError('postgresql', `Import entity unique constraint violation for GUID "${guid}" on etype "${etype}": "${unique}"`);
1589
- }
1590
- return e;
1591
- }));
1592
- }
1593
- await Promise.all(promises);
1594
- await this.commit(`nymph-import-entity-${guid}`);
1595
- }
1596
- catch (e) {
1597
- this.nymph.config.debugError('postgresql', `Import entity error: "${e}"`);
1598
- await this.rollback(`nymph-import-entity-${guid}`);
1599
- throw e;
1600
- }
1601
- }, async (name, curUid) => {
1602
- try {
1603
- await this.internalTransaction(`nymph-import-uid-${name}`);
1604
- await this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}uids`)} WHERE "name"=@name;`, {
1605
- params: {
1606
1595
  name,
1596
+ reference,
1607
1597
  },
1608
- });
1609
- await this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}uids`)} ("name", "cur_uid") VALUES (@name, @curUid);`, {
1610
- params: {
1611
- name,
1612
- curUid,
1613
- },
1614
- });
1615
- await this.commit(`nymph-import-uid-${name}`);
1616
- }
1617
- catch (e) {
1618
- this.nymph.config.debugError('postgresql', `Import UID error: "${e}"`);
1619
- await this.rollback(`nymph-import-uid-${name}`);
1620
- throw e;
1621
- }
1622
- }, async () => {
1623
- if (transaction) {
1624
- await this.internalTransaction('nymph-import');
1625
- }
1626
- }, async () => {
1627
- if (transaction) {
1628
- await this.commit('nymph-import');
1598
+ }));
1629
1599
  }
1600
+ }
1601
+ const uniques = await this.nymph
1602
+ .getEntityClassByEtype(etype)
1603
+ .getUniques({ guid, cdate, mdate, tags, data: {}, sdata });
1604
+ for (const unique of uniques) {
1605
+ promises.push(this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}uniques_${etype}`)} ("guid", "unique") VALUES (decode(@guid, 'hex'), @unique);`, {
1606
+ etypes: [etype],
1607
+ params: {
1608
+ guid,
1609
+ unique,
1610
+ },
1611
+ }).catch((e) => {
1612
+ if (e instanceof nymph_1.EntityUniqueConstraintError) {
1613
+ this.nymph.config.debugError('postgresql', `Import entity unique constraint violation for GUID "${guid}" on etype "${etype}": "${unique}"`);
1614
+ }
1615
+ return e;
1616
+ }));
1617
+ }
1618
+ await Promise.all(promises);
1619
+ await this.commit(`nymph-import-entity-${guid}`);
1620
+ }
1621
+ catch (e) {
1622
+ this.nymph.config.debugError('postgresql', `Import entity error: "${e}"`);
1623
+ await this.rollback(`nymph-import-entity-${guid}`);
1624
+ throw e;
1625
+ }
1626
+ }
1627
+ async importUID({ name, value }) {
1628
+ try {
1629
+ await this.internalTransaction(`nymph-import-uid-${name}`);
1630
+ await this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}uids`)} WHERE "name"=@name;`, {
1631
+ params: {
1632
+ name,
1633
+ },
1630
1634
  });
1631
- return result;
1635
+ await this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}uids`)} ("name", "cur_uid") VALUES (@name, @value);`, {
1636
+ params: {
1637
+ name,
1638
+ value,
1639
+ },
1640
+ });
1641
+ await this.commit(`nymph-import-uid-${name}`);
1632
1642
  }
1633
1643
  catch (e) {
1634
- this.nymph.config.debugError('postgresql', `Import error: "${e}"`);
1635
- if (transaction) {
1636
- await this.rollback('nymph-import');
1637
- }
1638
- return false;
1644
+ this.nymph.config.debugError('postgresql', `Import UID error: "${e}"`);
1645
+ await this.rollback(`nymph-import-uid-${name}`);
1646
+ throw e;
1639
1647
  }
1640
1648
  }
1641
1649
  async newUID(name) {