@sprucelabs/postgres-data-store 3.0.1 → 3.0.3
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,12 +1,32 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
4
24
|
};
|
|
5
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
26
|
const data_stores_1 = require("@sprucelabs/data-stores");
|
|
7
27
|
const schema_1 = require("@sprucelabs/schema");
|
|
8
28
|
const pg_1 = require("pg");
|
|
9
|
-
const QueryBuilder_1 =
|
|
29
|
+
const QueryBuilder_1 = __importStar(require("./QueryBuilder"));
|
|
10
30
|
class PostgresDatabase {
|
|
11
31
|
constructor(connectionString) {
|
|
12
32
|
this.idCount = 1;
|
|
@@ -172,7 +192,7 @@ class PostgresDatabase {
|
|
|
172
192
|
const { fields, values } = parsed;
|
|
173
193
|
throw new data_stores_1.DataStoresError({
|
|
174
194
|
code: 'DUPLICATE_RECORD',
|
|
175
|
-
duplicateFields: fields,
|
|
195
|
+
duplicateFields: fields.map((f) => f.replace(/"/g, '')),
|
|
176
196
|
duplicateValues: values,
|
|
177
197
|
collectionName: tableName,
|
|
178
198
|
action,
|
|
@@ -183,11 +203,11 @@ class PostgresDatabase {
|
|
|
183
203
|
}
|
|
184
204
|
async connect() {
|
|
185
205
|
var _a;
|
|
186
|
-
|
|
206
|
+
this.client = new pg_1.Client({
|
|
187
207
|
connectionString: this.connectionString,
|
|
188
208
|
});
|
|
189
209
|
try {
|
|
190
|
-
await client.connect();
|
|
210
|
+
await this.client.connect();
|
|
191
211
|
}
|
|
192
212
|
catch (err) {
|
|
193
213
|
const message = err.message;
|
|
@@ -210,7 +230,6 @@ class PostgresDatabase {
|
|
|
210
230
|
originalError: err,
|
|
211
231
|
});
|
|
212
232
|
}
|
|
213
|
-
this.client = client;
|
|
214
233
|
}
|
|
215
234
|
async getUniqueIndexes(collectionName) {
|
|
216
235
|
const isUnique = true;
|
|
@@ -312,7 +331,7 @@ class PostgresDatabase {
|
|
|
312
331
|
const parts = field.split('.');
|
|
313
332
|
return `(${parts[0]}->>'${parts[1]}')`;
|
|
314
333
|
}
|
|
315
|
-
return field;
|
|
334
|
+
return (0, QueryBuilder_1.quote)(field);
|
|
316
335
|
}
|
|
317
336
|
generateIndexName(collection, fields) {
|
|
318
337
|
return `${collection}_${fields
|
|
@@ -324,7 +343,7 @@ class PostgresDatabase {
|
|
|
324
343
|
}
|
|
325
344
|
isConnected() {
|
|
326
345
|
//@ts-ignore
|
|
327
|
-
return this.client._connected && !this.client._ending;
|
|
346
|
+
return this.client ? this.client._connected && !this.client._ending : false;
|
|
328
347
|
}
|
|
329
348
|
parseIndexViolatedForFieldsAndValues(input) {
|
|
330
349
|
const regex = /Key \((.*)\)=\((.*)\) already exists\./;
|
package/build/QueryBuilder.d.ts
CHANGED
package/build/QueryBuilder.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.quote = void 0;
|
|
3
4
|
class QueryBuilder {
|
|
4
5
|
constructor() { }
|
|
5
6
|
static Builder() {
|
|
@@ -44,34 +45,34 @@ class QueryBuilder {
|
|
|
44
45
|
let value = query[k];
|
|
45
46
|
if (value === null || value === void 0 ? void 0 : value.$in) {
|
|
46
47
|
values.push(...value.$in.map((v) => this.normalizeValue(v)));
|
|
47
|
-
set.push(
|
|
48
|
+
set.push(`"${k}" IN (${value.$in
|
|
48
49
|
.map(() => `$${++placeholderCount}`)
|
|
49
50
|
.join(', ')})`);
|
|
50
51
|
}
|
|
51
52
|
else if (value === null || value === void 0 ? void 0 : value.$regex) {
|
|
52
53
|
values.push(this.normalizeValue(value.$regex));
|
|
53
|
-
set.push(
|
|
54
|
+
set.push(`"${k}" ~* $${++placeholderCount}`);
|
|
54
55
|
}
|
|
55
56
|
else if (value === null || value === void 0 ? void 0 : value.$lte) {
|
|
56
57
|
values.push(this.normalizeValue(value.$lte));
|
|
57
|
-
set.push(
|
|
58
|
+
set.push(`"${k}" <= $${++placeholderCount}`);
|
|
58
59
|
}
|
|
59
60
|
else if (value === null || value === void 0 ? void 0 : value.$lt) {
|
|
60
61
|
values.push(this.normalizeValue(value.$lt));
|
|
61
|
-
set.push(
|
|
62
|
+
set.push(`"${k}" < $${++placeholderCount}`);
|
|
62
63
|
}
|
|
63
64
|
else if (value === null || value === void 0 ? void 0 : value.$gte) {
|
|
64
65
|
values.push(this.normalizeValue(value.$gte));
|
|
65
|
-
set.push(
|
|
66
|
+
set.push(`"${k}" >= $${++placeholderCount}`);
|
|
66
67
|
}
|
|
67
68
|
else if (value === null || value === void 0 ? void 0 : value.$gt) {
|
|
68
69
|
values.push(this.normalizeValue(value.$gt));
|
|
69
|
-
set.push(
|
|
70
|
+
set.push(`"${k}" > $${++placeholderCount}`);
|
|
70
71
|
}
|
|
71
72
|
else if (typeof (value === null || value === void 0 ? void 0 : value.$ne) !== 'undefined') {
|
|
72
73
|
const v = value.$ne;
|
|
73
74
|
v !== null && values.push(this.normalizeValue(v));
|
|
74
|
-
set.push(
|
|
75
|
+
set.push(`"${k}" ${v === null ? 'IS NOT NULL' : `!= $${++placeholderCount}`}`);
|
|
75
76
|
}
|
|
76
77
|
else if (k === '$or') {
|
|
77
78
|
const { set: orWheres, values: orValues } = this.buildSetClausFor$Or(value, placeholderCount);
|
|
@@ -88,7 +89,7 @@ class QueryBuilder {
|
|
|
88
89
|
set.push(...sub.set);
|
|
89
90
|
}
|
|
90
91
|
else if (value === null || value === undefined) {
|
|
91
|
-
set.push(
|
|
92
|
+
set.push(`"${k}" IS NULL`);
|
|
92
93
|
}
|
|
93
94
|
else {
|
|
94
95
|
placeholderCount++;
|
|
@@ -104,11 +105,11 @@ class QueryBuilder {
|
|
|
104
105
|
}
|
|
105
106
|
else {
|
|
106
107
|
k = field;
|
|
107
|
-
placeholder =
|
|
108
|
+
placeholder = `"${k}" || jsonb_build_object('${prop}', ${placeholder}::text)`;
|
|
108
109
|
}
|
|
109
110
|
}
|
|
110
111
|
values.push(this.normalizeValue(value));
|
|
111
|
-
set.push(`${k} = ${placeholder}`);
|
|
112
|
+
set.push(`${quote(k)} = ${placeholder}`);
|
|
112
113
|
}
|
|
113
114
|
});
|
|
114
115
|
return { set, values };
|
|
@@ -136,7 +137,9 @@ class QueryBuilder {
|
|
|
136
137
|
}
|
|
137
138
|
createWithoutReturning(tableName, records) {
|
|
138
139
|
const { fields, placeholders, values } = this.splitRecordsIntoFieldsPlaceholdersAndValues(records);
|
|
139
|
-
const sql = `INSERT INTO ${this.buildTableName(tableName)} (${fields
|
|
140
|
+
const sql = `INSERT INTO ${this.buildTableName(tableName)} (${fields
|
|
141
|
+
.map((f) => `"${f}"`)
|
|
142
|
+
.join(', ')}) VALUES ${placeholders.join(', ')}`;
|
|
140
143
|
return { sql, values };
|
|
141
144
|
}
|
|
142
145
|
splitRecordsIntoFieldsPlaceholdersAndValues(records) {
|
|
@@ -180,7 +183,7 @@ class QueryBuilder {
|
|
|
180
183
|
}
|
|
181
184
|
optionallyBuildSort(sort) {
|
|
182
185
|
if (sort) {
|
|
183
|
-
const sortSpecs = sort.map((s) =>
|
|
186
|
+
const sortSpecs = sort.map((s) => `"${s.field}" ${s.direction.toUpperCase()}`);
|
|
184
187
|
return ` ORDER BY ${sortSpecs.join(', ')}`;
|
|
185
188
|
}
|
|
186
189
|
return '';
|
|
@@ -198,7 +201,7 @@ class QueryBuilder {
|
|
|
198
201
|
return '';
|
|
199
202
|
}
|
|
200
203
|
buildColumnListFromIncludeFields(includeFields) {
|
|
201
|
-
return !includeFields ? '*' : includeFields.join(', ');
|
|
204
|
+
return !includeFields ? '*' : includeFields.map((f) => quote(f)).join(', ');
|
|
202
205
|
}
|
|
203
206
|
update(tableName, query, updates, shouldReturnUpdatedRecords = true) {
|
|
204
207
|
const { set: set, values } = this.buildSetClause({
|
|
@@ -245,3 +248,7 @@ class QueryBuilder {
|
|
|
245
248
|
}
|
|
246
249
|
}
|
|
247
250
|
exports.default = QueryBuilder;
|
|
251
|
+
function quote(f) {
|
|
252
|
+
return f.includes(' ') ? f : `"${f}"`;
|
|
253
|
+
}
|
|
254
|
+
exports.quote = quote;
|
|
@@ -10,7 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import { DataStoresError, } from '@sprucelabs/data-stores';
|
|
11
11
|
import { assertOptions } from '@sprucelabs/schema';
|
|
12
12
|
import { Client } from 'pg';
|
|
13
|
-
import QueryBuilder from './QueryBuilder.js';
|
|
13
|
+
import QueryBuilder, { quote } from './QueryBuilder.js';
|
|
14
14
|
export default class PostgresDatabase {
|
|
15
15
|
constructor(connectionString) {
|
|
16
16
|
this.idCount = 1;
|
|
@@ -213,7 +213,7 @@ export default class PostgresDatabase {
|
|
|
213
213
|
const { fields, values } = parsed;
|
|
214
214
|
throw new DataStoresError({
|
|
215
215
|
code: 'DUPLICATE_RECORD',
|
|
216
|
-
duplicateFields: fields,
|
|
216
|
+
duplicateFields: fields.map((f) => f.replace(/"/g, '')),
|
|
217
217
|
duplicateValues: values,
|
|
218
218
|
collectionName: tableName,
|
|
219
219
|
action,
|
|
@@ -226,11 +226,11 @@ export default class PostgresDatabase {
|
|
|
226
226
|
connect() {
|
|
227
227
|
var _a;
|
|
228
228
|
return __awaiter(this, void 0, void 0, function* () {
|
|
229
|
-
|
|
229
|
+
this.client = new Client({
|
|
230
230
|
connectionString: this.connectionString,
|
|
231
231
|
});
|
|
232
232
|
try {
|
|
233
|
-
yield client.connect();
|
|
233
|
+
yield this.client.connect();
|
|
234
234
|
}
|
|
235
235
|
catch (err) {
|
|
236
236
|
const message = err.message;
|
|
@@ -253,7 +253,6 @@ export default class PostgresDatabase {
|
|
|
253
253
|
originalError: err,
|
|
254
254
|
});
|
|
255
255
|
}
|
|
256
|
-
this.client = client;
|
|
257
256
|
});
|
|
258
257
|
}
|
|
259
258
|
getUniqueIndexes(collectionName) {
|
|
@@ -372,7 +371,7 @@ export default class PostgresDatabase {
|
|
|
372
371
|
const parts = field.split('.');
|
|
373
372
|
return `(${parts[0]}->>'${parts[1]}')`;
|
|
374
373
|
}
|
|
375
|
-
return field;
|
|
374
|
+
return quote(field);
|
|
376
375
|
}
|
|
377
376
|
generateIndexName(collection, fields) {
|
|
378
377
|
return `${collection}_${fields
|
|
@@ -386,7 +385,7 @@ export default class PostgresDatabase {
|
|
|
386
385
|
}
|
|
387
386
|
isConnected() {
|
|
388
387
|
//@ts-ignore
|
|
389
|
-
return this.client._connected && !this.client._ending;
|
|
388
|
+
return this.client ? this.client._connected && !this.client._ending : false;
|
|
390
389
|
}
|
|
391
390
|
parseIndexViolatedForFieldsAndValues(input) {
|
|
392
391
|
const regex = /Key \((.*)\)=\((.*)\) already exists\./;
|
|
@@ -42,34 +42,34 @@ export default class QueryBuilder {
|
|
|
42
42
|
let value = query[k];
|
|
43
43
|
if (value === null || value === void 0 ? void 0 : value.$in) {
|
|
44
44
|
values.push(...value.$in.map((v) => this.normalizeValue(v)));
|
|
45
|
-
set.push(
|
|
45
|
+
set.push(`"${k}" IN (${value.$in
|
|
46
46
|
.map(() => `$${++placeholderCount}`)
|
|
47
47
|
.join(', ')})`);
|
|
48
48
|
}
|
|
49
49
|
else if (value === null || value === void 0 ? void 0 : value.$regex) {
|
|
50
50
|
values.push(this.normalizeValue(value.$regex));
|
|
51
|
-
set.push(
|
|
51
|
+
set.push(`"${k}" ~* $${++placeholderCount}`);
|
|
52
52
|
}
|
|
53
53
|
else if (value === null || value === void 0 ? void 0 : value.$lte) {
|
|
54
54
|
values.push(this.normalizeValue(value.$lte));
|
|
55
|
-
set.push(
|
|
55
|
+
set.push(`"${k}" <= $${++placeholderCount}`);
|
|
56
56
|
}
|
|
57
57
|
else if (value === null || value === void 0 ? void 0 : value.$lt) {
|
|
58
58
|
values.push(this.normalizeValue(value.$lt));
|
|
59
|
-
set.push(
|
|
59
|
+
set.push(`"${k}" < $${++placeholderCount}`);
|
|
60
60
|
}
|
|
61
61
|
else if (value === null || value === void 0 ? void 0 : value.$gte) {
|
|
62
62
|
values.push(this.normalizeValue(value.$gte));
|
|
63
|
-
set.push(
|
|
63
|
+
set.push(`"${k}" >= $${++placeholderCount}`);
|
|
64
64
|
}
|
|
65
65
|
else if (value === null || value === void 0 ? void 0 : value.$gt) {
|
|
66
66
|
values.push(this.normalizeValue(value.$gt));
|
|
67
|
-
set.push(
|
|
67
|
+
set.push(`"${k}" > $${++placeholderCount}`);
|
|
68
68
|
}
|
|
69
69
|
else if (typeof (value === null || value === void 0 ? void 0 : value.$ne) !== 'undefined') {
|
|
70
70
|
const v = value.$ne;
|
|
71
71
|
v !== null && values.push(this.normalizeValue(v));
|
|
72
|
-
set.push(
|
|
72
|
+
set.push(`"${k}" ${v === null ? 'IS NOT NULL' : `!= $${++placeholderCount}`}`);
|
|
73
73
|
}
|
|
74
74
|
else if (k === '$or') {
|
|
75
75
|
const { set: orWheres, values: orValues } = this.buildSetClausFor$Or(value, placeholderCount);
|
|
@@ -86,7 +86,7 @@ export default class QueryBuilder {
|
|
|
86
86
|
set.push(...sub.set);
|
|
87
87
|
}
|
|
88
88
|
else if (value === null || value === undefined) {
|
|
89
|
-
set.push(
|
|
89
|
+
set.push(`"${k}" IS NULL`);
|
|
90
90
|
}
|
|
91
91
|
else {
|
|
92
92
|
placeholderCount++;
|
|
@@ -102,11 +102,11 @@ export default class QueryBuilder {
|
|
|
102
102
|
}
|
|
103
103
|
else {
|
|
104
104
|
k = field;
|
|
105
|
-
placeholder =
|
|
105
|
+
placeholder = `"${k}" || jsonb_build_object('${prop}', ${placeholder}::text)`;
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
values.push(this.normalizeValue(value));
|
|
109
|
-
set.push(`${k} = ${placeholder}`);
|
|
109
|
+
set.push(`${quote(k)} = ${placeholder}`);
|
|
110
110
|
}
|
|
111
111
|
});
|
|
112
112
|
return { set, values };
|
|
@@ -134,7 +134,9 @@ export default class QueryBuilder {
|
|
|
134
134
|
}
|
|
135
135
|
createWithoutReturning(tableName, records) {
|
|
136
136
|
const { fields, placeholders, values } = this.splitRecordsIntoFieldsPlaceholdersAndValues(records);
|
|
137
|
-
const sql = `INSERT INTO ${this.buildTableName(tableName)} (${fields
|
|
137
|
+
const sql = `INSERT INTO ${this.buildTableName(tableName)} (${fields
|
|
138
|
+
.map((f) => `"${f}"`)
|
|
139
|
+
.join(', ')}) VALUES ${placeholders.join(', ')}`;
|
|
138
140
|
return { sql, values };
|
|
139
141
|
}
|
|
140
142
|
splitRecordsIntoFieldsPlaceholdersAndValues(records) {
|
|
@@ -178,7 +180,7 @@ export default class QueryBuilder {
|
|
|
178
180
|
}
|
|
179
181
|
optionallyBuildSort(sort) {
|
|
180
182
|
if (sort) {
|
|
181
|
-
const sortSpecs = sort.map((s) =>
|
|
183
|
+
const sortSpecs = sort.map((s) => `"${s.field}" ${s.direction.toUpperCase()}`);
|
|
182
184
|
return ` ORDER BY ${sortSpecs.join(', ')}`;
|
|
183
185
|
}
|
|
184
186
|
return '';
|
|
@@ -196,7 +198,7 @@ export default class QueryBuilder {
|
|
|
196
198
|
return '';
|
|
197
199
|
}
|
|
198
200
|
buildColumnListFromIncludeFields(includeFields) {
|
|
199
|
-
return !includeFields ? '*' : includeFields.join(', ');
|
|
201
|
+
return !includeFields ? '*' : includeFields.map((f) => quote(f)).join(', ');
|
|
200
202
|
}
|
|
201
203
|
update(tableName, query, updates, shouldReturnUpdatedRecords = true) {
|
|
202
204
|
const { set: set, values } = this.buildSetClause({
|
|
@@ -242,3 +244,6 @@ export default class QueryBuilder {
|
|
|
242
244
|
};
|
|
243
245
|
}
|
|
244
246
|
}
|
|
247
|
+
export function quote(f) {
|
|
248
|
+
return f.includes(' ') ? f : `"${f}"`;
|
|
249
|
+
}
|
package/package.json
CHANGED