@sprucelabs/postgres-data-store 5.1.174 → 6.0.1

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.
@@ -29,8 +29,11 @@ const schema_1 = require("@sprucelabs/schema");
29
29
  const pg_1 = require("pg");
30
30
  const QueryBuilder_1 = __importStar(require("./QueryBuilder"));
31
31
  class PostgresDatabase {
32
+ connectionString;
33
+ client;
34
+ idCount = 1;
35
+ queries;
32
36
  constructor(connectionString) {
33
- this.idCount = 1;
34
37
  (0, schema_1.assertOptions)({ connectionString }, ['connectionString']);
35
38
  this.connectionString = connectionString;
36
39
  this.queries = QueryBuilder_1.default.Builder();
@@ -44,16 +47,15 @@ class PostgresDatabase {
44
47
  : `${this.idCount++}`;
45
48
  }
46
49
  async update(collection, query, updates) {
47
- var _a;
48
50
  const { sql, values } = this.queries.update(collection, query, updates, false);
49
51
  const results = await this.client.query({
50
52
  text: sql,
51
53
  values,
52
54
  });
53
- return (_a = results.rowCount) !== null && _a !== void 0 ? _a : 0;
55
+ return results.rowCount ?? 0;
54
56
  }
55
57
  async count(collection, query) {
56
- const { sql, values } = this.queries.find(collection, query !== null && query !== void 0 ? query : {}, {
58
+ const { sql, values } = this.queries.find(collection, query ?? {}, {
57
59
  includeFields: ['count(*) as count'],
58
60
  });
59
61
  const results = await this.client.query({
@@ -81,7 +83,7 @@ class PostgresDatabase {
81
83
  return record;
82
84
  }
83
85
  async find(collection, query, options) {
84
- const { sql, values } = this.queries.find(collection, query !== null && query !== void 0 ? query : {}, options);
86
+ const { sql, values } = this.queries.find(collection, query ?? {}, options);
85
87
  const results = await this.client.query({
86
88
  text: sql,
87
89
  values,
@@ -95,18 +97,19 @@ class PostgresDatabase {
95
97
  return this.executeGetIndexes(collectionName, false);
96
98
  }
97
99
  async findOne(collection, query, options) {
98
- var _a;
99
- const results = await this.find(collection, query, Object.assign(Object.assign({}, options), { limit: 1 }));
100
- return (_a = results[0]) !== null && _a !== void 0 ? _a : null;
100
+ const results = await this.find(collection, query, {
101
+ ...options,
102
+ limit: 1,
103
+ });
104
+ return results[0] ?? null;
101
105
  }
102
106
  async delete(collection, query) {
103
- var _a;
104
107
  const { sql, values } = this.queries.delete(collection, query);
105
108
  const results = await this.client.query({
106
109
  text: sql,
107
110
  values,
108
111
  });
109
- return (_a = results.rowCount) !== null && _a !== void 0 ? _a : 0;
112
+ return results.rowCount ?? 0;
110
113
  }
111
114
  async dropDatabase() {
112
115
  await this.truncateTables();
@@ -148,19 +151,18 @@ class PostgresDatabase {
148
151
  }
149
152
  }
150
153
  async deleteOne(collection, query) {
151
- var _a;
152
154
  if (!query.id) {
153
155
  const match = await this.findOne(collection, query, {
154
156
  includeFields: ['id'],
155
157
  });
156
- query = { id: match === null || match === void 0 ? void 0 : match.id };
158
+ query = { id: match?.id };
157
159
  }
158
160
  let { sql, values } = this.queries.delete(collection, query);
159
161
  const results = await this.client.query({
160
162
  text: sql,
161
163
  values,
162
164
  });
163
- return (_a = results.rowCount) !== null && _a !== void 0 ? _a : 0;
165
+ return results.rowCount ?? 0;
164
166
  }
165
167
  async truncateTables() {
166
168
  const res = await this.client.query(`
@@ -193,7 +195,7 @@ class PostgresDatabase {
193
195
  return results;
194
196
  }
195
197
  catch (err) {
196
- const parsed = this.parseIndexViolatedForFieldsAndValues(err === null || err === void 0 ? void 0 : err.detail);
198
+ const parsed = this.parseIndexViolatedForFieldsAndValues(err?.detail);
197
199
  if (parsed) {
198
200
  const { fields, values } = parsed;
199
201
  throw new data_stores_1.DataStoresError({
@@ -208,7 +210,6 @@ class PostgresDatabase {
208
210
  }
209
211
  }
210
212
  async connect() {
211
- var _a, _b, _c;
212
213
  this.client = new pg_1.Client({
213
214
  connectionString: this.connectionString,
214
215
  });
@@ -217,14 +218,14 @@ class PostgresDatabase {
217
218
  }
218
219
  catch (err) {
219
220
  const message = err.message;
220
- if ((_b = ((_a = err.code) !== null && _a !== void 0 ? _a : message)) === null || _b === void 0 ? void 0 : _b.includes('ECONNREFUSED')) {
221
+ if ((err.code ?? message)?.includes('ECONNREFUSED')) {
221
222
  throw new data_stores_1.DataStoresError({
222
223
  code: 'UNABLE_TO_CONNECT_TO_DB',
223
224
  originalError: err,
224
225
  });
225
226
  }
226
- if (message === null || message === void 0 ? void 0 : message.includes('does not exist')) {
227
- const match = (_c = message.match(/"([^"]*)"/)) !== null && _c !== void 0 ? _c : ['', ''];
227
+ if (message?.includes('does not exist')) {
228
+ const match = message.match(/"([^"]*)"/) ?? ['', ''];
228
229
  throw new data_stores_1.DataStoresError({
229
230
  code: 'INVALID_DATABASE_NAME',
230
231
  suppliedName: match[1],
@@ -283,12 +284,11 @@ class PostgresDatabase {
283
284
  const indexesToRemove = existingIndexes.filter((existing) => !indexes.find((index) => this.areIndexesEqual(existing, index)));
284
285
  await Promise.all([
285
286
  ...indexesToAdd.map(async (index) => {
286
- var _a;
287
287
  try {
288
288
  await this.executeCreateIndex(collectionName, index, isUnique);
289
289
  }
290
290
  catch (err) {
291
- if (((_a = err.options) === null || _a === void 0 ? void 0 : _a.code) !== 'INDEX_EXISTS') {
291
+ if (err.options?.code !== 'INDEX_EXISTS') {
292
292
  throw new data_stores_1.DataStoresError({
293
293
  code: 'DUPLICATE_KEY',
294
294
  originalError: err,
@@ -309,7 +309,6 @@ class PostgresDatabase {
309
309
  await this.executeCreateIndex(collection, fields, isUnique);
310
310
  }
311
311
  async executeCreateIndex(collection, fields, isUnique) {
312
- var _a, _b;
313
312
  const indexName = this.generateIndexName(collection, fields);
314
313
  const keys = this.generateKeyExpressions(fields);
315
314
  const query = `CREATE ${isUnique ? `UNIQUE` : ''} INDEX ${indexName} ON "${collection}" (${keys})`;
@@ -319,7 +318,7 @@ class PostgresDatabase {
319
318
  });
320
319
  }
321
320
  catch (err) {
322
- if ((_b = (_a = err.message) === null || _a === void 0 ? void 0 : _a.includes) === null || _b === void 0 ? void 0 : _b.call(_a, 'already exists')) {
321
+ if (err.message?.includes?.('already exists')) {
323
322
  throw new data_stores_1.DataStoresError({
324
323
  code: 'INDEX_EXISTS',
325
324
  collectionName: collection,
@@ -348,12 +347,14 @@ class PostgresDatabase {
348
347
  await this.client.end();
349
348
  }
350
349
  isConnected() {
351
- //@ts-ignore
352
- return this.client ? this.client._connected && !this.client._ending : false;
350
+ return this.client
351
+ ? //@ts-ignore
352
+ this.client._connected && !this.client._ending
353
+ : false;
353
354
  }
354
355
  parseIndexViolatedForFieldsAndValues(input) {
355
356
  const regex = /Key \((.*)\)=\((.*)\) already exists\./;
356
- const matches = input === null || input === void 0 ? void 0 : input.match(regex);
357
+ const matches = input?.match(regex);
357
358
  if (!matches) {
358
359
  return null;
359
360
  }
@@ -370,12 +371,11 @@ class PostgresDatabase {
370
371
  return result;
371
372
  }
372
373
  async query(query, params) {
373
- var _a;
374
374
  const results = await this.client.query({
375
375
  text: query,
376
376
  values: params,
377
377
  });
378
- return (_a = results === null || results === void 0 ? void 0 : results.rows) !== null && _a !== void 0 ? _a : [];
378
+ return results?.rows ?? [];
379
379
  }
380
380
  }
381
381
  exports.default = PostgresDatabase;
@@ -7,7 +7,7 @@ class QueryBuilder {
7
7
  return new this();
8
8
  }
9
9
  find(tableName, query, options) {
10
- const { includeFields, limit, skip, sort } = options !== null && options !== void 0 ? options : {};
10
+ const { includeFields, limit, skip, sort } = options ?? {};
11
11
  const fields = this.buildColumnListFromIncludeFields(includeFields);
12
12
  let sql = `SELECT ${fields} FROM ${this.buildTableName(tableName)}`;
13
13
  const { values, sql: where } = this.optionallyBuildWhere(query);
@@ -31,7 +31,7 @@ class QueryBuilder {
31
31
  let sql = '';
32
32
  const values = [];
33
33
  const queryKeys = Object.keys(query);
34
- if ((queryKeys !== null && queryKeys !== void 0 ? queryKeys : []).length > 0) {
34
+ if ((queryKeys ?? []).length > 0) {
35
35
  const { set: columnSpecs, values: whereValues } = this.buildSetClause({
36
36
  query,
37
37
  startingCount: startingPlaceholderCount,
@@ -52,33 +52,33 @@ class QueryBuilder {
52
52
  let value = query[k];
53
53
  const isNull = value === null && useIsNull;
54
54
  const formattedK = this.conditionalQuote(k);
55
- if (value === null || value === void 0 ? void 0 : value.$in) {
55
+ if (value?.$in) {
56
56
  values.push(...value.$in.map((v) => this.normalizeValue(v)));
57
57
  set.push(`${formattedK} IN (${value.$in
58
58
  .map(() => `$${++placeholderCount}`)
59
59
  .join(', ')})`);
60
60
  }
61
- else if (value === null || value === void 0 ? void 0 : value.$regex) {
61
+ else if (value?.$regex) {
62
62
  values.push(this.normalizeValue(value.$regex));
63
63
  set.push(`${formattedK} ~* $${++placeholderCount}`);
64
64
  }
65
- else if (value === null || value === void 0 ? void 0 : value.$lte) {
65
+ else if (value?.$lte) {
66
66
  values.push(this.normalizeValue(value.$lte));
67
67
  set.push(`${formattedK} <= $${++placeholderCount}`);
68
68
  }
69
- else if (value === null || value === void 0 ? void 0 : value.$lt) {
69
+ else if (value?.$lt) {
70
70
  values.push(this.normalizeValue(value.$lt));
71
71
  set.push(`${formattedK} < $${++placeholderCount}`);
72
72
  }
73
- else if (value === null || value === void 0 ? void 0 : value.$gte) {
73
+ else if (value?.$gte) {
74
74
  values.push(this.normalizeValue(value.$gte));
75
75
  set.push(`${formattedK} >= $${++placeholderCount}`);
76
76
  }
77
- else if (value === null || value === void 0 ? void 0 : value.$gt) {
77
+ else if (value?.$gt) {
78
78
  values.push(this.normalizeValue(value.$gt));
79
79
  set.push(`${formattedK} > $${++placeholderCount}`);
80
80
  }
81
- else if (typeof (value === null || value === void 0 ? void 0 : value.$ne) !== 'undefined') {
81
+ else if (typeof value?.$ne !== 'undefined') {
82
82
  const v = value.$ne;
83
83
  v !== null && values.push(this.normalizeValue(v));
84
84
  set.push(`${formattedK} ${v === null ? 'IS NOT NULL' : `!= $${++placeholderCount}`}`);
@@ -168,7 +168,8 @@ class QueryBuilder {
168
168
  fields.forEach((f) => {
169
169
  values.push(this.fieldValueToSqlValue(record, f));
170
170
  let placeholder = `$${++placeholderCount}`;
171
- if (this.isValueObject(record[f]) && !Array.isArray(record[f])) {
171
+ if (this.isValueObject(record[f]) &&
172
+ !Array.isArray(record[f])) {
172
173
  placeholder += `::json`;
173
174
  }
174
175
  placeholders.push(placeholder);
@@ -195,10 +196,11 @@ class QueryBuilder {
195
196
  value = JSON.stringify(value);
196
197
  }
197
198
  }
198
- return value !== null && value !== void 0 ? value : null;
199
+ return value ?? null;
199
200
  }
200
201
  isValueObject(value) {
201
- return value !== null && (Array.isArray(value) || typeof value === 'object');
202
+ return (value !== null &&
203
+ (Array.isArray(value) || typeof value === 'object'));
202
204
  }
203
205
  buildColumnListFromAllRecords(records) {
204
206
  const fields = records.map((r) => Object.keys(r)).flat();
@@ -225,7 +227,9 @@ class QueryBuilder {
225
227
  return '';
226
228
  }
227
229
  buildColumnListFromIncludeFields(includeFields) {
228
- return !includeFields ? '*' : includeFields.map((f) => quote(f)).join(', ');
230
+ return !includeFields
231
+ ? '*'
232
+ : includeFields.map((f) => quote(f)).join(', ');
229
233
  }
230
234
  update(tableName, query, updates, shouldReturnUpdatedRecords = true) {
231
235
  const { set: set, values } = this.buildSetClause({
@@ -248,7 +252,7 @@ class QueryBuilder {
248
252
  }
249
253
  delete(tableName, query) {
250
254
  let sql = `DELETE FROM ${this.buildTableName(tableName)}`;
251
- const { values, sql: where } = this.optionallyBuildWhere(query !== null && query !== void 0 ? query : {});
255
+ const { values, sql: where } = this.optionallyBuildWhere(query ?? {});
252
256
  sql += where;
253
257
  this.log('delete', sql, values);
254
258
  return {
@@ -258,7 +262,7 @@ class QueryBuilder {
258
262
  }
259
263
  upsert(tableName, query, updates) {
260
264
  let { sql, values } = this.createWithoutReturning(tableName, [
261
- Object.assign(Object.assign({}, query), updates),
265
+ { ...query, ...updates },
262
266
  ]);
263
267
  const { sql: whereSql, values: whereValues } = this.optionallyBuildWhere(query, values.length);
264
268
  const queryFields = this.buildColumnListFromAllRecords([query]);
@@ -390,8 +390,10 @@ export default class PostgresDatabase {
390
390
  });
391
391
  }
392
392
  isConnected() {
393
- //@ts-ignore
394
- return this.client ? this.client._connected && !this.client._ending : false;
393
+ return this.client
394
+ ? //@ts-ignore
395
+ this.client._connected && !this.client._ending
396
+ : false;
395
397
  }
396
398
  parseIndexViolatedForFieldsAndValues(input) {
397
399
  const regex = /Key \((.*)\)=\((.*)\) already exists\./;
@@ -165,7 +165,8 @@ export default class QueryBuilder {
165
165
  fields.forEach((f) => {
166
166
  values.push(this.fieldValueToSqlValue(record, f));
167
167
  let placeholder = `$${++placeholderCount}`;
168
- if (this.isValueObject(record[f]) && !Array.isArray(record[f])) {
168
+ if (this.isValueObject(record[f]) &&
169
+ !Array.isArray(record[f])) {
169
170
  placeholder += `::json`;
170
171
  }
171
172
  placeholders.push(placeholder);
@@ -195,7 +196,8 @@ export default class QueryBuilder {
195
196
  return value !== null && value !== void 0 ? value : null;
196
197
  }
197
198
  isValueObject(value) {
198
- return value !== null && (Array.isArray(value) || typeof value === 'object');
199
+ return (value !== null &&
200
+ (Array.isArray(value) || typeof value === 'object'));
199
201
  }
200
202
  buildColumnListFromAllRecords(records) {
201
203
  const fields = records.map((r) => Object.keys(r)).flat();
@@ -222,7 +224,9 @@ export default class QueryBuilder {
222
224
  return '';
223
225
  }
224
226
  buildColumnListFromIncludeFields(includeFields) {
225
- return !includeFields ? '*' : includeFields.map((f) => quote(f)).join(', ');
227
+ return !includeFields
228
+ ? '*'
229
+ : includeFields.map((f) => quote(f)).join(', ');
226
230
  }
227
231
  update(tableName, query, updates, shouldReturnUpdatedRecords = true) {
228
232
  const { set: set, values } = this.buildSetClause({
package/package.json CHANGED
@@ -4,7 +4,8 @@
4
4
  "skill": {
5
5
  "namespace": "postgres-data-store",
6
6
  "upgradeIgnoreList": [
7
- "@sprucelabs/spruce-core-schemas"
7
+ "@sprucelabs/spruce-core-schemas",
8
+ "@sprucelabs/spruce-test-fixtures"
8
9
  ]
9
10
  },
10
11
  "files": [
@@ -20,7 +21,7 @@
20
21
  "sprucebot",
21
22
  "sprucelabs"
22
23
  ],
23
- "version": "5.1.174",
24
+ "version": "6.0.1",
24
25
  "scripts": {
25
26
  "build.ci": "yarn build.tsc && yarn build.resolve-paths && yarn lint",
26
27
  "build.dev": "yarn build.tsc --sourceMap ; yarn resolve-paths.lint",
@@ -34,8 +35,8 @@
34
35
  "clean.build": "rm -rf build/",
35
36
  "clean.dependencies": "rm -rf node_modules/ package-lock.json yarn.lock",
36
37
  "clean.dist": "rm -rf build/__tests__ build/esm/__tests__",
37
- "fix.lint": "eslint --fix --cache '**/*.ts'",
38
- "lint": "eslint --cache '**/*.ts'",
38
+ "fix.lint": "eslint --fix --cache",
39
+ "lint": "eslint --cache",
39
40
  "lint.tsc": "tsc -p . --noEmit",
40
41
  "post.watch.build": "yarn build.copy-files && yarn build.resolve-paths",
41
42
  "rebuild": "yarn clean.all && yarn && yarn build.dev",
@@ -49,30 +50,29 @@
49
50
  "watch.tsc": "tsc -w"
50
51
  },
51
52
  "dependencies": {
52
- "@sprucelabs/data-stores": "^26.4.89",
53
- "@sprucelabs/schema": "^29.4.60",
53
+ "@sprucelabs/data-stores": "^27.0.0",
54
+ "@sprucelabs/schema": "^30.0.0",
54
55
  "pg": "^8.11.5"
55
56
  },
56
57
  "devDependencies": {
57
- "@sprucelabs/esm-postbuild": "^5.0.200",
58
+ "@sprucelabs/esm-postbuild": "^6.0.1",
58
59
  "@sprucelabs/jest-json-reporter": "^7.0.207",
59
- "@sprucelabs/resolve-path-aliases": "^1.1.304",
60
- "@sprucelabs/semantic-release": "^4.0.8",
61
- "@sprucelabs/spruce-test-fixtures": "^61.1.33",
62
- "@sprucelabs/test": "^8.0.50",
63
- "@sprucelabs/test-utils": "^4.0.157",
64
- "@types/node": "^20.12.4",
65
- "@types/pg": "^8.11.4",
60
+ "@sprucelabs/resolve-path-aliases": "^2.0.3",
61
+ "@sprucelabs/semantic-release": "^5.0.1",
62
+ "@sprucelabs/test": "^9.0.2",
63
+ "@sprucelabs/test-utils": "^5.0.1",
64
+ "@types/node": "^20.12.7",
65
+ "@types/pg": "^8.11.5",
66
66
  "chokidar-cli": "^3.0.0",
67
67
  "concurrently": "^8.2.2",
68
- "eslint": "^8.57.0",
69
- "eslint-config-spruce": "^10.13.6",
68
+ "eslint": "^9.0.0",
69
+ "eslint-config-spruce": "^11.2.5",
70
70
  "jest": "^29.7.0",
71
71
  "jest-circus": "^29.7.0",
72
72
  "prettier": "^3.2.5",
73
73
  "ts-node": "^10.9.2",
74
74
  "tsc-watch": "^6.2.0",
75
- "typescript": "^5.4.4"
75
+ "typescript": "^5.4.5"
76
76
  },
77
77
  "jest": {
78
78
  "testRunner": "jest-circus/runner",