@sprucelabs/postgres-data-store 6.1.315 → 6.1.317

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.
@@ -1,4 +1,4 @@
1
- import { Database, Index, QueryOptions, UniqueIndex } from '@sprucelabs/data-stores';
1
+ import { Database, Index, IndexWithFilter, QueryOptions } from '@sprucelabs/data-stores';
2
2
  import { Client } from 'pg';
3
3
  export default class PostgresDatabase implements Database {
4
4
  private connectionString;
@@ -14,7 +14,7 @@ export default class PostgresDatabase implements Database {
14
14
  private executeUpdateAndThrowIfNoResults;
15
15
  find(collection: string, query?: Record<string, any> | undefined, options?: QueryOptions | undefined): Promise<Record<string, any>[]>;
16
16
  createIndex(collection: string, fields: Index): Promise<void>;
17
- getIndexes(collectionName: string): Promise<Index[] | UniqueIndex[]>;
17
+ getIndexes(collectionName: string): Promise<IndexWithFilter[]>;
18
18
  findOne(collection: string, query?: Record<string, any> | undefined, options?: QueryOptions | undefined): Promise<Record<string, any> | null>;
19
19
  delete(collection: string, query: Record<string, any>): Promise<number>;
20
20
  dropDatabase(): Promise<void>;
@@ -28,14 +28,13 @@ export default class PostgresDatabase implements Database {
28
28
  create(collection: string, records: Record<string, any>[]): Promise<Record<string, any>[]>;
29
29
  private executeQuery;
30
30
  connect(): Promise<void>;
31
- getUniqueIndexes(collectionName: string): Promise<UniqueIndex[]>;
31
+ getUniqueIndexes(collectionName: string): Promise<IndexWithFilter[]>;
32
32
  private executeGetIndexes;
33
- dropIndex(collectionName: string, index: UniqueIndex): Promise<void>;
33
+ dropIndex(collectionName: string, index: Index): Promise<void>;
34
34
  syncIndexes(collectionName: string, indexes: Index[]): Promise<void>;
35
- syncUniqueIndexes(collectionName: string, indexes: UniqueIndex[]): Promise<void>;
35
+ syncUniqueIndexes(collectionName: string, indexes: Index[]): Promise<void>;
36
36
  private executeSyncIndexes;
37
- private areIndexesEqual;
38
- createUniqueIndex(collection: string, fields: UniqueIndex): Promise<void>;
37
+ createUniqueIndex(collection: string, fields: Index): Promise<void>;
39
38
  private executeCreateIndex;
40
39
  private generateIndexName;
41
40
  close(): Promise<void>;
@@ -103,7 +103,7 @@ class PostgresDatabase {
103
103
  const indexNames = await this.getIndexNames(name);
104
104
  for (const indexName of indexNames) {
105
105
  try {
106
- await this.client.query(`DROP INDEX ${indexName}`);
106
+ await this.client.query(`DROP INDEX "${indexName}"`);
107
107
  }
108
108
  catch (err) {
109
109
  console.info('Failed to drop index', indexName, err.stack);
@@ -227,21 +227,21 @@ class PostgresDatabase {
227
227
  return uniqueIndexes;
228
228
  }
229
229
  async executeGetIndexes(collectionName, isUnique) {
230
- const query = `SELECT indexname FROM pg_indexes WHERE tablename = '${collectionName}' AND indexdef ${isUnique ? '' : 'NOT'} LIKE '%UNIQUE%';`;
230
+ const query = `SELECT * FROM pg_indexes WHERE tablename = '${collectionName}' AND indexdef ${isUnique ? '' : 'NOT'} LIKE '%UNIQUE%';`;
231
231
  const res = await this.client.query(query);
232
232
  const uniqueIndexes = [];
233
233
  res.rows.forEach((row) => {
234
234
  const indexName = row.indexname.replace(`${collectionName}_`, '');
235
235
  const fields = indexName.split('_').slice(0, -1);
236
236
  if (fields.length > 0) {
237
- uniqueIndexes.push(fields);
237
+ uniqueIndexes.push({ fields });
238
238
  }
239
239
  });
240
240
  return uniqueIndexes;
241
241
  }
242
242
  async dropIndex(collectionName, index) {
243
243
  const indexName = this.generateIndexName(collectionName, index);
244
- const query = `DROP INDEX ${indexName}`;
244
+ const query = `DROP INDEX "${indexName}"`;
245
245
  try {
246
246
  await this.client.query({
247
247
  text: query,
@@ -263,8 +263,9 @@ class PostgresDatabase {
263
263
  }
264
264
  async executeSyncIndexes(collectionName, indexes, isUnique) {
265
265
  const existingIndexes = await this.executeGetIndexes(collectionName, isUnique);
266
- const indexesToAdd = indexes.filter((index) => !existingIndexes.find((existing) => this.areIndexesEqual(existing, index)));
267
- const indexesToRemove = existingIndexes.filter((existing) => !indexes.find((index) => this.areIndexesEqual(existing, index)));
266
+ const indexesToAdd = (0, data_stores_1.pluckMissingIndexes)(indexes, existingIndexes);
267
+ const indexesToRemove = (0, data_stores_1.pluckMissingIndexes)(existingIndexes, indexes);
268
+ await Promise.all(indexesToRemove.map((index) => this.dropIndex(collectionName, index)));
268
269
  await Promise.all([
269
270
  ...indexesToAdd.map(async (index) => {
270
271
  var _a;
@@ -281,16 +282,10 @@ class PostgresDatabase {
281
282
  }
282
283
  return null;
283
284
  }),
284
- ...indexesToRemove.map((index) => this.dropIndex(collectionName, index)),
285
285
  ]);
286
286
  }
287
- areIndexesEqual(existing, index) {
288
- return (this.generateIndexName('any', existing) ===
289
- this.generateIndexName('any', index));
290
- }
291
287
  async createUniqueIndex(collection, fields) {
292
- const isUnique = true;
293
- await this.executeCreateIndex(collection, fields, isUnique);
288
+ await this.executeCreateIndex(collection, fields, true);
294
289
  }
295
290
  async executeCreateIndex(collection, index, isUnique) {
296
291
  var _a, _b;
@@ -305,7 +300,7 @@ class PostgresDatabase {
305
300
  throw new data_stores_1.DataStoresError({
306
301
  code: 'INDEX_EXISTS',
307
302
  collectionName: collection,
308
- index: ['uniqueField'],
303
+ index: (0, data_stores_1.normalizeIndex)(index).fields,
309
304
  });
310
305
  }
311
306
  throw err;
@@ -1,9 +1,9 @@
1
- import { QueryOptions, UniqueIndex } from '@sprucelabs/data-stores';
1
+ import { Index, QueryOptions } from '@sprucelabs/data-stores';
2
2
  import { Query } from './postgres.types';
3
3
  export default class QueryBuilder {
4
4
  private constructor();
5
5
  static Builder(): QueryBuilder;
6
- createIndex(tableName: string, index: UniqueIndex, isUnique?: boolean): BuiltQuery;
6
+ createIndex(tableName: string, index: Index, isUnique?: boolean): BuiltQuery;
7
7
  find(tableName: string, query: Query, options?: QueryOptions): BuiltQuery;
8
8
  buildTableName(tableName: string): string;
9
9
  private conditionalQuote;
@@ -12,12 +12,19 @@ class QueryBuilder {
12
12
  const { fields, filter } = (0, data_stores_1.normalizeIndex)(index);
13
13
  const indexName = (0, indexUtils_1.generateIndexName)(tableName, index);
14
14
  const keys = (0, indexUtils_1.generateKeyExpressions)(fields);
15
- let query = `CREATE ${isUnique ? `UNIQUE` : ''} INDEX ${indexName} ON "${tableName}" (${keys})`;
15
+ let values = [];
16
+ let query = `CREATE ${isUnique ? `UNIQUE` : ''} INDEX "${indexName}" ON "${tableName}" (${keys})`;
16
17
  if (filter) {
17
- const { sql: where } = this.optionallyBuildWhere(filter);
18
+ const { sql: where, values: v } = this.optionallyBuildWhere(filter);
18
19
  query += where;
20
+ values = v;
19
21
  }
20
- return { sql: query, values: [] };
22
+ if (values) {
23
+ for (let i = 0; i < values.length; i++) {
24
+ query = query.replace(`$${i + 1}`, values[i]);
25
+ }
26
+ }
27
+ return { sql: query, values };
21
28
  }
22
29
  find(tableName, query, options) {
23
30
  const { includeFields, limit, skip, sort } = options !== null && options !== void 0 ? options : {};
@@ -71,9 +78,12 @@ class QueryBuilder {
71
78
  .map(() => `$${++placeholderCount}`)
72
79
  .join(', ')})`);
73
80
  }
74
- else if ((value === null || value === void 0 ? void 0 : value.$type) === 'string' || (value === null || value === void 0 ? void 0 : value.$exists)) {
81
+ else if (value === null || value === void 0 ? void 0 : value.$exists) {
75
82
  set.push(`${formattedK} IS NOT NULL`);
76
83
  }
84
+ else if ((value === null || value === void 0 ? void 0 : value.$type) === 'string') {
85
+ set.push(`${formattedK} ~ '[A-Za-z]+'`);
86
+ }
77
87
  else if (value === null || value === void 0 ? void 0 : value.$regex) {
78
88
  values.push(this.normalizeValue(value.$regex));
79
89
  set.push(`${formattedK} ~* $${++placeholderCount}`);
@@ -1,4 +1,4 @@
1
- import { Database, Index, QueryOptions, UniqueIndex } from '@sprucelabs/data-stores';
1
+ import { Database, Index, IndexWithFilter, QueryOptions } from '@sprucelabs/data-stores';
2
2
  import { Client } from 'pg';
3
3
  export default class PostgresDatabase implements Database {
4
4
  private connectionString;
@@ -14,7 +14,7 @@ export default class PostgresDatabase implements Database {
14
14
  private executeUpdateAndThrowIfNoResults;
15
15
  find(collection: string, query?: Record<string, any> | undefined, options?: QueryOptions | undefined): Promise<Record<string, any>[]>;
16
16
  createIndex(collection: string, fields: Index): Promise<void>;
17
- getIndexes(collectionName: string): Promise<Index[] | UniqueIndex[]>;
17
+ getIndexes(collectionName: string): Promise<IndexWithFilter[]>;
18
18
  findOne(collection: string, query?: Record<string, any> | undefined, options?: QueryOptions | undefined): Promise<Record<string, any> | null>;
19
19
  delete(collection: string, query: Record<string, any>): Promise<number>;
20
20
  dropDatabase(): Promise<void>;
@@ -28,14 +28,13 @@ export default class PostgresDatabase implements Database {
28
28
  create(collection: string, records: Record<string, any>[]): Promise<Record<string, any>[]>;
29
29
  private executeQuery;
30
30
  connect(): Promise<void>;
31
- getUniqueIndexes(collectionName: string): Promise<UniqueIndex[]>;
31
+ getUniqueIndexes(collectionName: string): Promise<IndexWithFilter[]>;
32
32
  private executeGetIndexes;
33
- dropIndex(collectionName: string, index: UniqueIndex): Promise<void>;
33
+ dropIndex(collectionName: string, index: Index): Promise<void>;
34
34
  syncIndexes(collectionName: string, indexes: Index[]): Promise<void>;
35
- syncUniqueIndexes(collectionName: string, indexes: UniqueIndex[]): Promise<void>;
35
+ syncUniqueIndexes(collectionName: string, indexes: Index[]): Promise<void>;
36
36
  private executeSyncIndexes;
37
- private areIndexesEqual;
38
- createUniqueIndex(collection: string, fields: UniqueIndex): Promise<void>;
37
+ createUniqueIndex(collection: string, fields: Index): Promise<void>;
39
38
  private executeCreateIndex;
40
39
  private generateIndexName;
41
40
  close(): Promise<void>;
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { randomUUID } from 'crypto';
11
- import { DataStoresError, normalizeIndex, } from '@sprucelabs/data-stores';
11
+ import { DataStoresError, normalizeIndex, pluckMissingIndexes, } from '@sprucelabs/data-stores';
12
12
  import { assertOptions } from '@sprucelabs/schema';
13
13
  import { Client } from 'pg';
14
14
  import { generateIndexName } from './indexUtils.js';
@@ -125,7 +125,7 @@ export default class PostgresDatabase {
125
125
  const indexNames = yield this.getIndexNames(name);
126
126
  for (const indexName of indexNames) {
127
127
  try {
128
- yield this.client.query(`DROP INDEX ${indexName}`);
128
+ yield this.client.query(`DROP INDEX "${indexName}"`);
129
129
  }
130
130
  catch (err) {
131
131
  console.info('Failed to drop index', indexName, err.stack);
@@ -271,14 +271,14 @@ export default class PostgresDatabase {
271
271
  }
272
272
  executeGetIndexes(collectionName, isUnique) {
273
273
  return __awaiter(this, void 0, void 0, function* () {
274
- const query = `SELECT indexname FROM pg_indexes WHERE tablename = '${collectionName}' AND indexdef ${isUnique ? '' : 'NOT'} LIKE '%UNIQUE%';`;
274
+ const query = `SELECT * FROM pg_indexes WHERE tablename = '${collectionName}' AND indexdef ${isUnique ? '' : 'NOT'} LIKE '%UNIQUE%';`;
275
275
  const res = yield this.client.query(query);
276
276
  const uniqueIndexes = [];
277
277
  res.rows.forEach((row) => {
278
278
  const indexName = row.indexname.replace(`${collectionName}_`, '');
279
279
  const fields = indexName.split('_').slice(0, -1);
280
280
  if (fields.length > 0) {
281
- uniqueIndexes.push(fields);
281
+ uniqueIndexes.push({ fields });
282
282
  }
283
283
  });
284
284
  return uniqueIndexes;
@@ -287,7 +287,7 @@ export default class PostgresDatabase {
287
287
  dropIndex(collectionName, index) {
288
288
  return __awaiter(this, void 0, void 0, function* () {
289
289
  const indexName = this.generateIndexName(collectionName, index);
290
- const query = `DROP INDEX ${indexName}`;
290
+ const query = `DROP INDEX "${indexName}"`;
291
291
  try {
292
292
  yield this.client.query({
293
293
  text: query,
@@ -315,8 +315,9 @@ export default class PostgresDatabase {
315
315
  executeSyncIndexes(collectionName, indexes, isUnique) {
316
316
  return __awaiter(this, void 0, void 0, function* () {
317
317
  const existingIndexes = yield this.executeGetIndexes(collectionName, isUnique);
318
- const indexesToAdd = indexes.filter((index) => !existingIndexes.find((existing) => this.areIndexesEqual(existing, index)));
319
- const indexesToRemove = existingIndexes.filter((existing) => !indexes.find((index) => this.areIndexesEqual(existing, index)));
318
+ const indexesToAdd = pluckMissingIndexes(indexes, existingIndexes);
319
+ const indexesToRemove = pluckMissingIndexes(existingIndexes, indexes);
320
+ yield Promise.all(indexesToRemove.map((index) => this.dropIndex(collectionName, index)));
320
321
  yield Promise.all([
321
322
  ...indexesToAdd.map((index) => __awaiter(this, void 0, void 0, function* () {
322
323
  var _a;
@@ -333,18 +334,12 @@ export default class PostgresDatabase {
333
334
  }
334
335
  return null;
335
336
  })),
336
- ...indexesToRemove.map((index) => this.dropIndex(collectionName, index)),
337
337
  ]);
338
338
  });
339
339
  }
340
- areIndexesEqual(existing, index) {
341
- return (this.generateIndexName('any', existing) ===
342
- this.generateIndexName('any', index));
343
- }
344
340
  createUniqueIndex(collection, fields) {
345
341
  return __awaiter(this, void 0, void 0, function* () {
346
- const isUnique = true;
347
- yield this.executeCreateIndex(collection, fields, isUnique);
342
+ yield this.executeCreateIndex(collection, fields, true);
348
343
  });
349
344
  }
350
345
  executeCreateIndex(collection, index, isUnique) {
@@ -361,7 +356,7 @@ export default class PostgresDatabase {
361
356
  throw new DataStoresError({
362
357
  code: 'INDEX_EXISTS',
363
358
  collectionName: collection,
364
- index: ['uniqueField'],
359
+ index: normalizeIndex(index).fields,
365
360
  });
366
361
  }
367
362
  throw err;
@@ -1,9 +1,9 @@
1
- import { QueryOptions, UniqueIndex } from '@sprucelabs/data-stores';
1
+ import { Index, QueryOptions } from '@sprucelabs/data-stores';
2
2
  import { Query } from './postgres.types';
3
3
  export default class QueryBuilder {
4
4
  private constructor();
5
5
  static Builder(): QueryBuilder;
6
- createIndex(tableName: string, index: UniqueIndex, isUnique?: boolean): BuiltQuery;
6
+ createIndex(tableName: string, index: Index, isUnique?: boolean): BuiltQuery;
7
7
  find(tableName: string, query: Query, options?: QueryOptions): BuiltQuery;
8
8
  buildTableName(tableName: string): string;
9
9
  private conditionalQuote;
@@ -9,12 +9,19 @@ export default class QueryBuilder {
9
9
  const { fields, filter } = normalizeIndex(index);
10
10
  const indexName = generateIndexName(tableName, index);
11
11
  const keys = generateKeyExpressions(fields);
12
- let query = `CREATE ${isUnique ? `UNIQUE` : ''} INDEX ${indexName} ON "${tableName}" (${keys})`;
12
+ let values = [];
13
+ let query = `CREATE ${isUnique ? `UNIQUE` : ''} INDEX "${indexName}" ON "${tableName}" (${keys})`;
13
14
  if (filter) {
14
- const { sql: where } = this.optionallyBuildWhere(filter);
15
+ const { sql: where, values: v } = this.optionallyBuildWhere(filter);
15
16
  query += where;
17
+ values = v;
16
18
  }
17
- return { sql: query, values: [] };
19
+ if (values) {
20
+ for (let i = 0; i < values.length; i++) {
21
+ query = query.replace(`$${i + 1}`, values[i]);
22
+ }
23
+ }
24
+ return { sql: query, values };
18
25
  }
19
26
  find(tableName, query, options) {
20
27
  const { includeFields, limit, skip, sort } = options !== null && options !== void 0 ? options : {};
@@ -68,9 +75,12 @@ export default class QueryBuilder {
68
75
  .map(() => `$${++placeholderCount}`)
69
76
  .join(', ')})`);
70
77
  }
71
- else if ((value === null || value === void 0 ? void 0 : value.$type) === 'string' || (value === null || value === void 0 ? void 0 : value.$exists)) {
78
+ else if (value === null || value === void 0 ? void 0 : value.$exists) {
72
79
  set.push(`${formattedK} IS NOT NULL`);
73
80
  }
81
+ else if ((value === null || value === void 0 ? void 0 : value.$type) === 'string') {
82
+ set.push(`${formattedK} ~ '[A-Za-z]+'`);
83
+ }
74
84
  else if (value === null || value === void 0 ? void 0 : value.$regex) {
75
85
  values.push(this.normalizeValue(value.$regex));
76
86
  set.push(`${formattedK} ~* $${++placeholderCount}`);
@@ -1,4 +1,4 @@
1
- import { UniqueIndex } from '@sprucelabs/data-stores';
1
+ import { Index } from '@sprucelabs/data-stores';
2
2
  export declare function generateKeyExpression(field: string): string;
3
3
  export declare function generateKeyExpressions(fields: string[]): string;
4
- export declare function generateIndexName(collection: string, index: UniqueIndex): string;
4
+ export declare function generateIndexName(collection: string, index: Index): string;
@@ -15,7 +15,5 @@ export function generateKeyExpressions(fields) {
15
15
  return fields.map((f) => generateKeyExpression(f)).join(', ');
16
16
  }
17
17
  export function generateIndexName(collection, index) {
18
- return `${collection}_${normalizeIndex(index)
19
- .fields.map((f) => f.toLowerCase())
20
- .join('_')}${'_index'}`.replace(/\./g, '_');
18
+ return `${collection}_${normalizeIndex(index).fields.join('_')}${'_index'}`.replace(/\./g, '_');
21
19
  }
@@ -1,4 +1,4 @@
1
- import { UniqueIndex } from '@sprucelabs/data-stores';
1
+ import { Index } from '@sprucelabs/data-stores';
2
2
  export declare function generateKeyExpression(field: string): string;
3
3
  export declare function generateKeyExpressions(fields: string[]): string;
4
- export declare function generateIndexName(collection: string, index: UniqueIndex): string;
4
+ export declare function generateIndexName(collection: string, index: Index): string;
@@ -20,7 +20,5 @@ function generateKeyExpressions(fields) {
20
20
  return fields.map((f) => generateKeyExpression(f)).join(', ');
21
21
  }
22
22
  function generateIndexName(collection, index) {
23
- return `${collection}_${(0, data_stores_1.normalizeIndex)(index)
24
- .fields.map((f) => f.toLowerCase())
25
- .join('_')}${'_index'}`.replace(/\./g, '_');
23
+ return `${collection}_${(0, data_stores_1.normalizeIndex)(index).fields.join('_')}${'_index'}`.replace(/\./g, '_');
26
24
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sprucelabs/postgres-data-store",
3
- "version": "6.1.315",
3
+ "version": "6.1.317",
4
4
  "description": "Postgres production and test adapters for @sprucelabs/data-stores",
5
5
  "skill": {
6
6
  "namespace": "postgres-data-store",
@@ -49,17 +49,17 @@
49
49
  "watch.tsc": "tsc -w"
50
50
  },
51
51
  "dependencies": {
52
- "@sprucelabs/data-stores": "^28.1.333",
53
- "@sprucelabs/schema": "^30.0.383",
52
+ "@sprucelabs/data-stores": "^28.3.2",
53
+ "@sprucelabs/schema": "^30.0.394",
54
54
  "pg": "^8.12.0"
55
55
  },
56
56
  "devDependencies": {
57
- "@sprucelabs/esm-postbuild": "^6.0.319",
58
- "@sprucelabs/jest-json-reporter": "^8.0.336",
59
- "@sprucelabs/resolve-path-aliases": "^2.0.314",
57
+ "@sprucelabs/esm-postbuild": "^6.0.330",
58
+ "@sprucelabs/jest-json-reporter": "^8.0.347",
59
+ "@sprucelabs/resolve-path-aliases": "^2.0.325",
60
60
  "@sprucelabs/semantic-release": "^5.0.2",
61
- "@sprucelabs/test": "^9.0.44",
62
- "@sprucelabs/test-utils": "^5.1.281",
61
+ "@sprucelabs/test": "^9.0.45",
62
+ "@sprucelabs/test-utils": "^5.1.292",
63
63
  "@types/node": "^22.5.4",
64
64
  "@types/pg": "^8.11.9",
65
65
  "chokidar-cli": "^3.0.0",