proto.io 0.0.164 → 0.0.166
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/dist/adapters/file/database.d.ts +2 -2
- package/dist/adapters/file/database.js.map +1 -1
- package/dist/adapters/file/database.mjs +2 -2
- package/dist/adapters/file/database.mjs.map +1 -1
- package/dist/adapters/file/filesystem.d.ts +2 -2
- package/dist/adapters/file/filesystem.js.map +1 -1
- package/dist/adapters/file/filesystem.mjs.map +1 -1
- package/dist/adapters/file/google-cloud-storage.d.ts +2 -2
- package/dist/adapters/file/google-cloud-storage.js.map +1 -1
- package/dist/adapters/file/google-cloud-storage.mjs.map +1 -1
- package/dist/adapters/storage/progres.d.ts +16 -13
- package/dist/adapters/storage/progres.js +136 -81
- package/dist/adapters/storage/progres.js.map +1 -1
- package/dist/adapters/storage/progres.mjs +138 -83
- package/dist/adapters/storage/progres.mjs.map +1 -1
- package/dist/client.d.ts +3 -3
- package/dist/client.js +1 -1
- package/dist/client.mjs +3 -3
- package/dist/index.d.ts +7 -12
- package/dist/index.js +84 -47
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +87 -50
- package/dist/index.mjs.map +1 -1
- package/dist/internals/{index-Dz3jvqxZ.js → index-B-pq8xkP.js} +5 -21
- package/dist/internals/index-B-pq8xkP.js.map +1 -0
- package/dist/internals/{index-BsuUdR0W.d.ts → index-BQggoDNX.d.ts} +2 -2
- package/dist/internals/index-BQggoDNX.d.ts.map +1 -0
- package/dist/internals/{index-ByfpVHca.mjs → index-BYbMU-Ao.mjs} +2 -2
- package/dist/internals/{index-ByfpVHca.mjs.map → index-BYbMU-Ao.mjs.map} +1 -1
- package/dist/internals/{index-S5Bq-KsU.mjs → index-BejQNqvC.mjs} +2 -2
- package/dist/internals/{index-S5Bq-KsU.mjs.map → index-BejQNqvC.mjs.map} +1 -1
- package/dist/internals/index-BqFdBhFc.js.map +1 -1
- package/dist/internals/index-CSNRyhjB.js.map +1 -1
- package/dist/internals/{index-BoP4kl2R.mjs → index-CUJMde7V.mjs} +6 -22
- package/dist/internals/index-CUJMde7V.mjs.map +1 -0
- package/dist/internals/index-CVutVPmd.js.map +1 -1
- package/dist/internals/index-be1VYBY2.mjs.map +1 -1
- package/dist/internals/{index-BeV63sFw.d.ts → index-rkqvel7o.d.ts} +2 -2
- package/dist/internals/index-rkqvel7o.d.ts.map +1 -0
- package/dist/internals/{index-YdOGTHp1.d.ts → index-y8EePsDY.d.ts} +10 -6
- package/dist/internals/index-y8EePsDY.d.ts.map +1 -0
- package/dist/internals/{random-w8WDYQEe.mjs → random-DrURPPxr.mjs} +5 -10
- package/dist/internals/random-DrURPPxr.mjs.map +1 -0
- package/dist/internals/{random-uT4D0y_q.js → random-q0PeamQE.js} +3 -8
- package/dist/internals/random-q0PeamQE.js.map +1 -0
- package/package.json +20 -20
- package/dist/internals/index-BeV63sFw.d.ts.map +0 -1
- package/dist/internals/index-BoP4kl2R.mjs.map +0 -1
- package/dist/internals/index-BsuUdR0W.d.ts.map +0 -1
- package/dist/internals/index-Dz3jvqxZ.js.map +0 -1
- package/dist/internals/index-YdOGTHp1.d.ts.map +0 -1
- package/dist/internals/random-uT4D0y_q.js.map +0 -1
- package/dist/internals/random-w8WDYQEe.mjs.map +0 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
|
-
import { i as isPointer, a as isRelation, b as isShape, d as decodeUpdateOp, s as shapePaths, e as isPrimitive, T as TObject, f as isVector, _ as
|
|
2
|
+
import { i as isPointer, a as isRelation, b as isShape, d as decodeUpdateOp, s as shapePaths, e as isPrimitive, T as TObject, f as isVector, _ as _encodeValue, g as _decodeValue, h as dimensionOf, j as _typeof } from '../../internals/index-BYbMU-Ao.mjs';
|
|
3
3
|
import { Pool, types } from 'pg';
|
|
4
4
|
import QueryStream from 'pg-query-stream';
|
|
5
5
|
import { asyncStream } from '@o2ter/utils-js';
|
|
6
6
|
import Decimal from 'decimal.js';
|
|
7
7
|
import { escapeLiteral, escapeIdentifier } from 'pg/lib/utils';
|
|
8
|
-
import { a as QueryCoditionalSelector, b as QueryFieldSelector, c as QueryExpressionSelector, d as QueryDistanceExpression, e as QueryCoditionalExpression, f as QueryComparisonExpression, g as QueryNotExpression, h as QueryArrayExpression, i as QueryValueExpression, j as QueryKeyExpression, Q as QuerySelector, F as FieldSelectorExpression } from '../../internals/index-
|
|
8
|
+
import { a as QueryCoditionalSelector, b as QueryFieldSelector, c as QueryExpressionSelector, d as QueryDistanceExpression, e as QueryCoditionalExpression, f as QueryComparisonExpression, g as QueryNotExpression, h as QueryArrayExpression, i as QueryValueExpression, j as QueryKeyExpression, Q as QuerySelector, F as FieldSelectorExpression } from '../../internals/index-BejQNqvC.mjs';
|
|
9
9
|
import '@o2ter/crypto-js';
|
|
10
|
-
import { r as resolveColumn, a as resolveDataType, g as generateId, Q as QueryValidator } from '../../internals/random-
|
|
10
|
+
import { r as resolveColumn, a as resolveDataType, g as generateId, Q as QueryValidator } from '../../internals/random-DrURPPxr.mjs';
|
|
11
11
|
import { P as PVK } from '../../internals/private-BUpLAMZi.mjs';
|
|
12
12
|
|
|
13
13
|
//
|
|
@@ -220,12 +220,14 @@ class QueryCompiler {
|
|
|
220
220
|
dialect;
|
|
221
221
|
selectLock;
|
|
222
222
|
isUpdate;
|
|
223
|
+
extraFilter;
|
|
223
224
|
idx = 0;
|
|
224
|
-
constructor(
|
|
225
|
-
this.schema = schema;
|
|
226
|
-
this.dialect = dialect;
|
|
227
|
-
this.selectLock = selectLock;
|
|
228
|
-
this.isUpdate = isUpdate;
|
|
225
|
+
constructor(options) {
|
|
226
|
+
this.schema = options.schema;
|
|
227
|
+
this.dialect = options.dialect;
|
|
228
|
+
this.selectLock = options.selectLock;
|
|
229
|
+
this.isUpdate = options.isUpdate;
|
|
230
|
+
this.extraFilter = options.extraFilter;
|
|
229
231
|
}
|
|
230
232
|
nextIdx() {
|
|
231
233
|
return this.idx++;
|
|
@@ -282,11 +284,11 @@ class QueryCompiler {
|
|
|
282
284
|
}
|
|
283
285
|
_baseSelectQuery(query, options) {
|
|
284
286
|
const context = this._makeContext(query);
|
|
285
|
-
const _stages = _.mapValues(context.populates, (populate) => this.dialect.encodePopulate(this,
|
|
287
|
+
const _stages = _.mapValues(context.populates, (populate) => this.dialect.encodePopulate(this, populate));
|
|
286
288
|
const stages = _.fromPairs(_.flatMap(_.values(_stages), (p) => _.toPairs(p)));
|
|
287
289
|
const fetchName = `_fetch_$${query.className.toLowerCase()}`;
|
|
288
290
|
const parent = { className: query.className, name: fetchName };
|
|
289
|
-
const baseFilter = this._encodeFilter(
|
|
291
|
+
const baseFilter = this._encodeFilter(parent, query.filter);
|
|
290
292
|
const populates = this._selectPopulateMap(context, query.className, fetchName);
|
|
291
293
|
const joins = _.compact(_.map(populates, ({ join }) => join));
|
|
292
294
|
const includes = {
|
|
@@ -300,7 +302,7 @@ class QueryCompiler {
|
|
|
300
302
|
const filter = _.compact([
|
|
301
303
|
baseFilter,
|
|
302
304
|
_options?.extraFilter,
|
|
303
|
-
query.relatedBy && this.dialect.encodeRelation(this,
|
|
305
|
+
query.relatedBy && this.dialect.encodeRelation(this, parent, query.relatedBy),
|
|
304
306
|
]);
|
|
305
307
|
return {
|
|
306
308
|
stages,
|
|
@@ -321,9 +323,9 @@ class QueryCompiler {
|
|
|
321
323
|
`,
|
|
322
324
|
};
|
|
323
325
|
}
|
|
324
|
-
_refetch(name, query
|
|
326
|
+
_refetch(name, query) {
|
|
325
327
|
const _context = this._encodeIncludes(query.className, query.includes, query.matches);
|
|
326
|
-
const populates = _.mapValues(_context.populates, (populate) => this.dialect.encodePopulate(this,
|
|
328
|
+
const populates = _.mapValues(_context.populates, (populate) => this.dialect.encodePopulate(this, populate, { className: query.className, name }));
|
|
327
329
|
const stages = _.fromPairs(_.flatMap(_.values(populates), (p) => _.toPairs(p)));
|
|
328
330
|
const _populates = this._selectPopulateMap(_context, query.className, name);
|
|
329
331
|
const _joins = _.compact(_.map(_populates, ({ join }) => join));
|
|
@@ -394,8 +396,8 @@ class QueryCompiler {
|
|
|
394
396
|
}
|
|
395
397
|
return result;
|
|
396
398
|
}
|
|
397
|
-
_encodeCoditionalSelector(parent, filter
|
|
398
|
-
const queries = _.compact(_.map(filter.exprs, x => this._encodeFilter(
|
|
399
|
+
_encodeCoditionalSelector(parent, filter) {
|
|
400
|
+
const queries = _.compact(_.map(filter.exprs, x => this._encodeFilter(parent, x)));
|
|
399
401
|
if (_.isEmpty(queries))
|
|
400
402
|
return;
|
|
401
403
|
switch (filter.type) {
|
|
@@ -404,12 +406,12 @@ class QueryCompiler {
|
|
|
404
406
|
case '$or': return sql `(${{ literal: _.map(queries, x => sql `(${x})`), separator: ' OR ' }})`;
|
|
405
407
|
}
|
|
406
408
|
}
|
|
407
|
-
_encodeFilter(
|
|
409
|
+
_encodeFilter(parent, filter) {
|
|
408
410
|
if (filter instanceof QueryCoditionalSelector) {
|
|
409
|
-
return this._encodeCoditionalSelector(parent, filter
|
|
411
|
+
return this._encodeCoditionalSelector(parent, filter);
|
|
410
412
|
}
|
|
411
413
|
if (filter instanceof QueryFieldSelector) {
|
|
412
|
-
return this.dialect.encodeFieldExpression(this,
|
|
414
|
+
return this.dialect.encodeFieldExpression(this, parent, filter.field, filter.expr);
|
|
413
415
|
}
|
|
414
416
|
if (filter instanceof QueryExpressionSelector) {
|
|
415
417
|
return this.dialect.encodeQueryExpression(this, parent, filter.expr);
|
|
@@ -450,7 +452,7 @@ class QueryCompiler {
|
|
|
450
452
|
});
|
|
451
453
|
const name = `_insert_$${options.className.toLowerCase()}`;
|
|
452
454
|
const context = this._makeContext(options);
|
|
453
|
-
const populates = _.mapValues(context.populates, (populate) => this.dialect.encodePopulate(this,
|
|
455
|
+
const populates = _.mapValues(context.populates, (populate) => this.dialect.encodePopulate(this, populate));
|
|
454
456
|
const stages = _.fromPairs(_.flatMap(_.values(populates), (p) => _.toPairs(p)));
|
|
455
457
|
const _populates = this._selectPopulateMap(context, options.className, name);
|
|
456
458
|
const joins = _.compact(_.map(_populates, ({ join }) => join));
|
|
@@ -485,7 +487,7 @@ class QueryCompiler {
|
|
|
485
487
|
`;
|
|
486
488
|
}
|
|
487
489
|
updateOne(query, update) {
|
|
488
|
-
return this._modifyQuery({ ...query, limit: 1 }, (fetchName
|
|
490
|
+
return this._modifyQuery({ ...query, limit: 1 }, (fetchName) => {
|
|
489
491
|
const name = `_update_$${query.className.toLowerCase()}`;
|
|
490
492
|
return sql `
|
|
491
493
|
, ${{ identifier: name }} AS (
|
|
@@ -495,7 +497,7 @@ class QueryCompiler {
|
|
|
495
497
|
WHERE ${{ identifier: query.className }}._id IN (SELECT ${{ identifier: fetchName }}._id FROM ${{ identifier: fetchName }})
|
|
496
498
|
RETURNING *
|
|
497
499
|
)
|
|
498
|
-
${this._refetch(name, query
|
|
500
|
+
${this._refetch(name, query)}
|
|
499
501
|
`;
|
|
500
502
|
});
|
|
501
503
|
}
|
|
@@ -504,7 +506,7 @@ class QueryCompiler {
|
|
|
504
506
|
..._defaultInsertOpts(query),
|
|
505
507
|
...this._encodeObjectAttrs(query.className, setOnInsert),
|
|
506
508
|
});
|
|
507
|
-
return this._modifyQuery({ ...query, limit: 1 }, (fetchName
|
|
509
|
+
return this._modifyQuery({ ...query, limit: 1 }, (fetchName) => {
|
|
508
510
|
const updateName = `_update_$${query.className.toLowerCase()}`;
|
|
509
511
|
const insertName = `_insert_$${query.className.toLowerCase()}`;
|
|
510
512
|
const upsertName = `_upsert_$${query.className.toLowerCase()}`;
|
|
@@ -528,7 +530,7 @@ class QueryCompiler {
|
|
|
528
530
|
UNION
|
|
529
531
|
SELECT * FROM ${{ identifier: insertName }}
|
|
530
532
|
)
|
|
531
|
-
${this._refetch(upsertName, query
|
|
533
|
+
${this._refetch(upsertName, query)}
|
|
532
534
|
`;
|
|
533
535
|
});
|
|
534
536
|
}
|
|
@@ -663,12 +665,21 @@ class SqlStorage {
|
|
|
663
665
|
}
|
|
664
666
|
return obj;
|
|
665
667
|
}
|
|
668
|
+
_makeCompiler(isUpdate, extraFilter) {
|
|
669
|
+
return new QueryCompiler({
|
|
670
|
+
schema: this.schema,
|
|
671
|
+
dialect: this.dialect,
|
|
672
|
+
selectLock: this.selectLock(),
|
|
673
|
+
isUpdate,
|
|
674
|
+
extraFilter,
|
|
675
|
+
});
|
|
676
|
+
}
|
|
666
677
|
async explain(query) {
|
|
667
|
-
const compiler =
|
|
678
|
+
const compiler = this._makeCompiler(false, query.extraFilter);
|
|
668
679
|
return this._explain(compiler, query);
|
|
669
680
|
}
|
|
670
681
|
async count(query) {
|
|
671
|
-
const compiler =
|
|
682
|
+
const compiler = this._makeCompiler(false, query.extraFilter);
|
|
672
683
|
const [{ count: _count }] = await this.query(compiler._selectQuery(query, {
|
|
673
684
|
select: sql `COUNT(*) AS count`,
|
|
674
685
|
}));
|
|
@@ -677,7 +688,7 @@ class SqlStorage {
|
|
|
677
688
|
}
|
|
678
689
|
find(query) {
|
|
679
690
|
const self = this;
|
|
680
|
-
const compiler =
|
|
691
|
+
const compiler = self._makeCompiler(false, query.extraFilter);
|
|
681
692
|
const _query = compiler._selectQuery(query);
|
|
682
693
|
return (async function* () {
|
|
683
694
|
const objects = self.query(_query);
|
|
@@ -688,7 +699,7 @@ class SqlStorage {
|
|
|
688
699
|
}
|
|
689
700
|
random(query, opts) {
|
|
690
701
|
const self = this;
|
|
691
|
-
const compiler =
|
|
702
|
+
const compiler = self._makeCompiler(false, query.extraFilter);
|
|
692
703
|
const _query = compiler._selectQuery({ ...query, sort: {} }, {
|
|
693
704
|
sort: sql `ORDER BY ${self.dialect.random(opts ?? {})}`,
|
|
694
705
|
});
|
|
@@ -715,7 +726,7 @@ class SqlStorage {
|
|
|
715
726
|
}
|
|
716
727
|
nonrefs(query) {
|
|
717
728
|
const self = this;
|
|
718
|
-
const compiler =
|
|
729
|
+
const compiler = self._makeCompiler(false, query.extraFilter);
|
|
719
730
|
const _query = compiler._selectQuery(query, ({ fetchName }) => ({
|
|
720
731
|
extraFilter: sql `
|
|
721
732
|
NOT EXISTS (${this._refs(this.schema, query.className, ['_id'], sql `(${{ quote: query.className + '$' }} || ${{ identifier: fetchName }}.${{ identifier: '_id' }})`)})
|
|
@@ -729,32 +740,32 @@ class SqlStorage {
|
|
|
729
740
|
})();
|
|
730
741
|
}
|
|
731
742
|
async insert(options, attrs) {
|
|
732
|
-
const compiler =
|
|
743
|
+
const compiler = this._makeCompiler(true);
|
|
733
744
|
const result = _.first(await this.query(compiler.insert(options, attrs)));
|
|
734
745
|
return _.isNil(result) ? undefined : this._decodeObject(options.className, result);
|
|
735
746
|
}
|
|
736
747
|
async insertMany(options, values) {
|
|
737
|
-
const compiler =
|
|
748
|
+
const compiler = this._makeCompiler(true);
|
|
738
749
|
const result = await this.query(compiler.insertMany(options, values));
|
|
739
750
|
return result.length;
|
|
740
751
|
}
|
|
741
752
|
async updateOne(query, update) {
|
|
742
|
-
const compiler =
|
|
753
|
+
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
743
754
|
const updated = _.first(await this.query(compiler.updateOne(query, update)));
|
|
744
755
|
return _.isNil(updated) ? undefined : this._decodeObject(query.className, updated);
|
|
745
756
|
}
|
|
746
757
|
async upsertOne(query, update, setOnInsert) {
|
|
747
|
-
const compiler =
|
|
758
|
+
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
748
759
|
const upserted = _.first(await this.query(compiler.upsertOne(query, update, setOnInsert)));
|
|
749
760
|
return _.isNil(upserted) ? undefined : this._decodeObject(query.className, upserted);
|
|
750
761
|
}
|
|
751
762
|
async deleteOne(query) {
|
|
752
|
-
const compiler =
|
|
763
|
+
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
753
764
|
const deleted = _.first(await this.query(compiler.deleteOne(query)));
|
|
754
765
|
return _.isNil(deleted) ? undefined : this._decodeObject(query.className, deleted);
|
|
755
766
|
}
|
|
756
767
|
async deleteMany(query) {
|
|
757
|
-
const compiler =
|
|
768
|
+
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
758
769
|
const deleted = await this.query(compiler.deleteMany(query));
|
|
759
770
|
return deleted.length;
|
|
760
771
|
}
|
|
@@ -1110,10 +1121,55 @@ class PostgresClientDriver {
|
|
|
1110
1121
|
});
|
|
1111
1122
|
}
|
|
1112
1123
|
}
|
|
1124
|
+
class PostgresPubSub {
|
|
1125
|
+
client;
|
|
1126
|
+
subscribers = {};
|
|
1127
|
+
channels = [];
|
|
1128
|
+
constructor(client) {
|
|
1129
|
+
this.client = client;
|
|
1130
|
+
(async () => {
|
|
1131
|
+
try {
|
|
1132
|
+
(await client).on('notification', ({ channel, payload }) => {
|
|
1133
|
+
if (!payload)
|
|
1134
|
+
return;
|
|
1135
|
+
try {
|
|
1136
|
+
const _payload = _decodeValue(JSON.parse(payload));
|
|
1137
|
+
for (const subscriber of this.subscribers[_.toUpper(channel)]) {
|
|
1138
|
+
subscriber(_payload);
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
catch (e) {
|
|
1142
|
+
console.error(`Unknown payload: ${e}`);
|
|
1143
|
+
}
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
catch (e) {
|
|
1147
|
+
console.error(e);
|
|
1148
|
+
}
|
|
1149
|
+
})();
|
|
1150
|
+
}
|
|
1151
|
+
async shutdown() {
|
|
1152
|
+
(await this.client).release();
|
|
1153
|
+
}
|
|
1154
|
+
async listen(channel) {
|
|
1155
|
+
this.channels.push(channel);
|
|
1156
|
+
await (await this.client).query(`LISTEN ${channel}`);
|
|
1157
|
+
}
|
|
1158
|
+
subscribe(channel, callback) {
|
|
1159
|
+
if (_.isNil(this.subscribers[channel]))
|
|
1160
|
+
this.subscribers[channel] = [];
|
|
1161
|
+
this.subscribers[channel].push(callback);
|
|
1162
|
+
return () => {
|
|
1163
|
+
this.subscribers[channel] = this.subscribers[channel].filter(x => x !== callback);
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
isEmpty() {
|
|
1167
|
+
return _.every(_.values(this.subscribers), x => _.isEmpty(x));
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1113
1170
|
class PostgresDriver extends PostgresClientDriver {
|
|
1114
1171
|
database;
|
|
1115
1172
|
pubsub;
|
|
1116
|
-
subscribers = [];
|
|
1117
1173
|
constructor(config) {
|
|
1118
1174
|
if (_.isEmpty(config))
|
|
1119
1175
|
throw Error('Invalid postgre config.');
|
|
@@ -1126,26 +1182,11 @@ class PostgresDriver extends PostgresClientDriver {
|
|
|
1126
1182
|
await this._release_pubsub();
|
|
1127
1183
|
await this.database.end();
|
|
1128
1184
|
}
|
|
1129
|
-
|
|
1185
|
+
_init_pubsub() {
|
|
1130
1186
|
if (this.pubsub)
|
|
1131
1187
|
return;
|
|
1132
1188
|
try {
|
|
1133
|
-
this.pubsub = this.database.connect();
|
|
1134
|
-
const pubsub = await this.pubsub;
|
|
1135
|
-
pubsub.on('notification', ({ channel, payload }) => {
|
|
1136
|
-
if (_.toUpper(channel) !== PROTO_POSTGRES_MSG || !payload)
|
|
1137
|
-
return;
|
|
1138
|
-
try {
|
|
1139
|
-
const _payload = _decodeValue(JSON.parse(payload));
|
|
1140
|
-
for (const subscriber of this.subscribers) {
|
|
1141
|
-
subscriber(_payload);
|
|
1142
|
-
}
|
|
1143
|
-
}
|
|
1144
|
-
catch (e) {
|
|
1145
|
-
console.error(`Unknown payload: ${e}`);
|
|
1146
|
-
}
|
|
1147
|
-
});
|
|
1148
|
-
await pubsub.query(`LISTEN ${PROTO_POSTGRES_MSG}`);
|
|
1189
|
+
this.pubsub = new PostgresPubSub(this.database.connect());
|
|
1149
1190
|
}
|
|
1150
1191
|
catch (e) {
|
|
1151
1192
|
console.error(e);
|
|
@@ -1154,18 +1195,22 @@ class PostgresDriver extends PostgresClientDriver {
|
|
|
1154
1195
|
async _release_pubsub() {
|
|
1155
1196
|
const pubsub = this.pubsub;
|
|
1156
1197
|
this.pubsub = undefined;
|
|
1157
|
-
await
|
|
1198
|
+
await pubsub?.shutdown();
|
|
1158
1199
|
}
|
|
1159
|
-
|
|
1200
|
+
_subscribe(channel, callback) {
|
|
1160
1201
|
this._init_pubsub();
|
|
1161
|
-
this.
|
|
1202
|
+
if (!_.includes(this.pubsub.channels, channel))
|
|
1203
|
+
this.pubsub.listen(channel);
|
|
1204
|
+
const release = this.pubsub.subscribe(channel, callback);
|
|
1162
1205
|
return () => {
|
|
1163
|
-
|
|
1164
|
-
if (
|
|
1206
|
+
release();
|
|
1207
|
+
if (this.pubsub?.isEmpty())
|
|
1165
1208
|
this._release_pubsub();
|
|
1166
|
-
}
|
|
1167
1209
|
};
|
|
1168
1210
|
}
|
|
1211
|
+
subscribe(callback) {
|
|
1212
|
+
return this._subscribe(PROTO_POSTGRES_MSG, callback);
|
|
1213
|
+
}
|
|
1169
1214
|
}
|
|
1170
1215
|
|
|
1171
1216
|
//
|
|
@@ -1853,7 +1898,7 @@ const encodeQueryExpression = (compiler, parent, expr) => {
|
|
|
1853
1898
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
1854
1899
|
// THE SOFTWARE.
|
|
1855
1900
|
//
|
|
1856
|
-
const encodeFieldExpression = (compiler,
|
|
1901
|
+
const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
1857
1902
|
const [colname] = _.toPath(field);
|
|
1858
1903
|
const { element, dataType, relation } = fetchElement(compiler, parent, field);
|
|
1859
1904
|
const encodeValue = (value) => dataType ? encodeType(colname, dataType, value) : _encodeJsonValue(_encodeValue(value));
|
|
@@ -2082,7 +2127,7 @@ const encodeFieldExpression = (compiler, context, parent, field, expr) => {
|
|
|
2082
2127
|
{
|
|
2083
2128
|
if (!(expr.value instanceof FieldSelectorExpression))
|
|
2084
2129
|
break;
|
|
2085
|
-
return sql `NOT (${encodeFieldExpression(compiler,
|
|
2130
|
+
return sql `NOT (${encodeFieldExpression(compiler, parent, field, expr.value)})`;
|
|
2086
2131
|
}
|
|
2087
2132
|
case '$pattern':
|
|
2088
2133
|
{
|
|
@@ -2174,7 +2219,7 @@ const encodeFieldExpression = (compiler, context, parent, field, expr) => {
|
|
|
2174
2219
|
if (!(expr.value instanceof QuerySelector))
|
|
2175
2220
|
break;
|
|
2176
2221
|
const tempName = `_expr_$${compiler.nextIdx()}`;
|
|
2177
|
-
const filter = compiler._encodeFilter(
|
|
2222
|
+
const filter = compiler._encodeFilter({ name: tempName, className: relation?.target }, expr.value);
|
|
2178
2223
|
if (!filter)
|
|
2179
2224
|
break;
|
|
2180
2225
|
if (relation) {
|
|
@@ -2201,7 +2246,7 @@ const encodeFieldExpression = (compiler, context, parent, field, expr) => {
|
|
|
2201
2246
|
if (!(expr.value instanceof QuerySelector))
|
|
2202
2247
|
break;
|
|
2203
2248
|
const tempName = `_expr_$${compiler.nextIdx()}`;
|
|
2204
|
-
const filter = compiler._encodeFilter(
|
|
2249
|
+
const filter = compiler._encodeFilter({ name: tempName, className: relation?.target }, expr.value);
|
|
2205
2250
|
if (!filter)
|
|
2206
2251
|
break;
|
|
2207
2252
|
if (relation) {
|
|
@@ -2295,31 +2340,36 @@ const selectPopulate = (compiler, parent, populate, field) => {
|
|
|
2295
2340
|
const _local = (field) => sql `${{ identifier: parent.name }}.${{ identifier: field }}`;
|
|
2296
2341
|
const _foreign = (field) => sql `${{ identifier: populate.name }}.${{ identifier: field }}`;
|
|
2297
2342
|
const subpaths = resolveSubpaths(compiler, populate);
|
|
2343
|
+
const cond = [];
|
|
2344
|
+
if (compiler.extraFilter) {
|
|
2345
|
+
const filter = compiler.extraFilter(populate.className);
|
|
2346
|
+
cond.push(compiler._encodeFilter(populate, filter));
|
|
2347
|
+
}
|
|
2298
2348
|
if (populate.type === 'pointer') {
|
|
2349
|
+
cond.push(sql `${sql `(${{ quote: populate.className + '$' }} || ${_foreign('_id')})`} = ${_local(field)}`);
|
|
2299
2350
|
return {
|
|
2300
2351
|
columns: _.map(subpaths, ({ path }) => sql `${{ identifier: populate.name }}.${{ identifier: path }} AS ${{ identifier: `${field}.${path}` }}`),
|
|
2301
2352
|
join: sql `
|
|
2302
2353
|
LEFT JOIN ${{ identifier: populate.name }}
|
|
2303
|
-
ON ${
|
|
2354
|
+
ON ${{ literal: _.map(_.compact(cond), x => sql `(${x})`), separator: ' AND ' }}
|
|
2304
2355
|
`,
|
|
2305
2356
|
};
|
|
2306
2357
|
}
|
|
2307
|
-
let cond;
|
|
2308
2358
|
if (_.isNil(populate.foreignField)) {
|
|
2309
|
-
cond
|
|
2359
|
+
cond.push(sql `${sql `(${{ quote: populate.className + '$' }} || ${_foreign('_id')})`} = ANY(${_local(field)})`);
|
|
2310
2360
|
}
|
|
2311
2361
|
else if (_isPointer(compiler.schema, populate.className, populate.foreignField)) {
|
|
2312
|
-
cond
|
|
2362
|
+
cond.push(sql `${sql `(${{ quote: parent.className + '$' }} || ${_local('_id')})`} = ${_foreign(populate.colname)}`);
|
|
2313
2363
|
}
|
|
2314
2364
|
else {
|
|
2315
|
-
cond
|
|
2365
|
+
cond.push(sql `${sql `(${{ quote: parent.className + '$' }} || ${_local('_id')})`} = ANY(${_foreign(populate.colname)})`);
|
|
2316
2366
|
}
|
|
2317
2367
|
return {
|
|
2318
2368
|
columns: [sql `
|
|
2319
2369
|
ARRAY(
|
|
2320
2370
|
SELECT to_jsonb(${{ identifier: populate.name }}) FROM (
|
|
2321
2371
|
SELECT ${_.map(subpaths, ({ path, type }) => _encodePopulateInclude(populate.name, path, type))}
|
|
2322
|
-
FROM ${{ identifier: populate.name }} WHERE ${cond}
|
|
2372
|
+
FROM ${{ identifier: populate.name }} WHERE ${{ literal: _.map(_.compact(cond), x => sql `(${x})`), separator: ' AND ' }}
|
|
2323
2373
|
${!_.isEmpty(populate.sort) ? sql `ORDER BY ${compiler._encodeSort(populate.sort, { className: populate.className, name: populate.name })}` : sql ``}
|
|
2324
2374
|
${populate.limit ? sql `LIMIT ${{ literal: `${populate.limit}` }}` : sql ``}
|
|
2325
2375
|
${populate.skip ? sql `OFFSET ${{ literal: `${populate.skip}` }}` : sql ``}
|
|
@@ -2332,13 +2382,13 @@ const selectPopulate = (compiler, parent, populate, field) => {
|
|
|
2332
2382
|
const encodeRemix = (parent, remix) => sql `${remix?.className === parent.className ? sql `
|
|
2333
2383
|
(SELECT * FROM ${{ identifier: remix.name }} UNION SELECT * FROM ${{ identifier: parent.className }})
|
|
2334
2384
|
` : { identifier: parent.className }}`;
|
|
2335
|
-
const encodeForeignField = (compiler,
|
|
2385
|
+
const encodeForeignField = (compiler, parent, foreignField, remix) => {
|
|
2336
2386
|
const { paths: [colname, ...subpath], dataType } = resolveColumn(compiler.schema, parent.className, foreignField);
|
|
2337
2387
|
const tempName = `_populate_$${compiler.nextIdx()}`;
|
|
2338
2388
|
const _local = (field) => sql `${{ identifier: parent.name }}.${{ identifier: field }}`;
|
|
2339
2389
|
const _foreign = (field) => sql `${{ identifier: tempName }}.${{ identifier: field }}`;
|
|
2340
2390
|
if (_.isEmpty(subpath) && isRelation(dataType) && dataType.foreignField) {
|
|
2341
|
-
const { joins, field, rows, array } = encodeForeignField(compiler,
|
|
2391
|
+
const { joins, field, rows, array } = encodeForeignField(compiler, { className: dataType.target, name: tempName }, dataType.foreignField, remix);
|
|
2342
2392
|
return {
|
|
2343
2393
|
joins: [],
|
|
2344
2394
|
field: sql `(
|
|
@@ -2361,27 +2411,32 @@ const encodeForeignField = (compiler, context, parent, foreignField, remix) => {
|
|
|
2361
2411
|
}
|
|
2362
2412
|
if (!isPointer(dataType) && !isRelation(dataType))
|
|
2363
2413
|
throw Error(`Invalid path: ${foreignField}`);
|
|
2364
|
-
const { joins, field, rows, array } = encodeForeignField(compiler,
|
|
2414
|
+
const { joins, field, rows, array } = encodeForeignField(compiler, { className: dataType.target, name: tempName }, subpath.join('.'), remix);
|
|
2415
|
+
const cond = [];
|
|
2416
|
+
if (compiler.extraFilter) {
|
|
2417
|
+
const filter = compiler.extraFilter(dataType.target);
|
|
2418
|
+
cond.push(compiler._encodeFilter({ className: dataType.target, name: tempName }, filter));
|
|
2419
|
+
}
|
|
2365
2420
|
if (isPointer(dataType)) {
|
|
2421
|
+
cond.push(sql `${sql `(${{ quote: dataType.target + '$' }} || ${_foreign('_id')})`} = ${_local(colname)}`);
|
|
2366
2422
|
return {
|
|
2367
2423
|
joins: [sql `
|
|
2368
2424
|
LEFT JOIN ${encodeRemix({ className: dataType.target }, remix)} AS ${{ identifier: tempName }}
|
|
2369
|
-
ON ${
|
|
2425
|
+
ON ${{ literal: _.map(_.compact(cond), x => sql `(${x})`), separator: ' AND ' }}
|
|
2370
2426
|
`, ...joins],
|
|
2371
2427
|
field,
|
|
2372
2428
|
array,
|
|
2373
2429
|
rows,
|
|
2374
2430
|
};
|
|
2375
2431
|
}
|
|
2376
|
-
let cond;
|
|
2377
2432
|
if (_.isNil(dataType.foreignField)) {
|
|
2378
|
-
cond
|
|
2433
|
+
cond.push(sql `${sql `(${{ quote: dataType.target + '$' }} || ${_foreign('_id')})`} = ANY(${_local(colname)})`);
|
|
2379
2434
|
}
|
|
2380
2435
|
else if (_isPointer(compiler.schema, dataType.target, dataType.foreignField)) {
|
|
2381
|
-
cond
|
|
2436
|
+
cond.push(sql `${sql `(${{ quote: parent.className + '$' }} || ${_local('_id')})`} = ${_foreign(dataType.foreignField)}`);
|
|
2382
2437
|
}
|
|
2383
2438
|
else {
|
|
2384
|
-
cond
|
|
2439
|
+
cond.push(sql `${sql `(${{ quote: parent.className + '$' }} || ${_local('_id')})`} = ANY(${_foreign(dataType.foreignField)})`);
|
|
2385
2440
|
}
|
|
2386
2441
|
return {
|
|
2387
2442
|
joins: [],
|
|
@@ -2389,23 +2444,23 @@ const encodeForeignField = (compiler, context, parent, foreignField, remix) => {
|
|
|
2389
2444
|
SELECT ${array ? sql `UNNEST(${field})` : field}
|
|
2390
2445
|
FROM ${encodeRemix({ className: dataType.target }, remix)} AS ${{ identifier: tempName }}
|
|
2391
2446
|
${!_.isEmpty(joins) ? { literal: joins, separator: '\n' } : sql ``}
|
|
2392
|
-
WHERE ${cond}
|
|
2447
|
+
WHERE ${{ literal: _.map(_.compact(cond), x => sql `(${x})`), separator: ' AND ' }}
|
|
2393
2448
|
)`,
|
|
2394
2449
|
array: false,
|
|
2395
2450
|
rows: true,
|
|
2396
2451
|
};
|
|
2397
2452
|
};
|
|
2398
|
-
const encodePopulate = (compiler,
|
|
2399
|
-
const _filter = compiler._encodeFilter(
|
|
2453
|
+
const encodePopulate = (compiler, parent, remix) => {
|
|
2454
|
+
const _filter = parent.filter && compiler._encodeFilter(parent, parent.filter);
|
|
2400
2455
|
const _populates = _.map(parent.populates, (populate, field) => selectPopulate(compiler, parent, populate, field));
|
|
2401
2456
|
const _joins = _.compact(_.map(_populates, ({ join }) => join));
|
|
2402
2457
|
const _includes = _.pickBy(parent.includes, v => isPrimitive(v));
|
|
2403
|
-
const { joins: _joins2 = [], field: _foreignField = undefined, rows = false, } = parent.foreignField ? encodeForeignField(compiler,
|
|
2458
|
+
const { joins: _joins2 = [], field: _foreignField = undefined, rows = false, } = parent.foreignField ? encodeForeignField(compiler, {
|
|
2404
2459
|
className: parent.className,
|
|
2405
2460
|
name: parent.name,
|
|
2406
2461
|
}, parent.foreignField, remix) : {};
|
|
2407
2462
|
return _.reduce(parent.populates, (acc, populate) => ({
|
|
2408
|
-
...encodePopulate(compiler,
|
|
2463
|
+
...encodePopulate(compiler, populate, remix),
|
|
2409
2464
|
...acc,
|
|
2410
2465
|
}), {
|
|
2411
2466
|
[parent.name]: sql `
|
|
@@ -2450,11 +2505,11 @@ const encodePopulate = (compiler, context, parent, remix) => {
|
|
|
2450
2505
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
2451
2506
|
// THE SOFTWARE.
|
|
2452
2507
|
//
|
|
2453
|
-
const encodeRelation = (compiler,
|
|
2508
|
+
const encodeRelation = (compiler, parent, relatedBy) => {
|
|
2454
2509
|
const name = `_relation_$${relatedBy.className.toLowerCase()}`;
|
|
2455
2510
|
const _local = (field) => sql `${{ identifier: parent.name }}.${{ identifier: field }}`;
|
|
2456
2511
|
const _foreign = (field) => sql `${{ identifier: name }}.${{ identifier: field }}`;
|
|
2457
|
-
const { joins, field } = encodeForeignField(compiler,
|
|
2512
|
+
const { joins, field } = encodeForeignField(compiler, { className: relatedBy.className, name }, relatedBy.key);
|
|
2458
2513
|
return sql `EXISTS (
|
|
2459
2514
|
SELECT 1
|
|
2460
2515
|
FROM ${{ identifier: relatedBy.className }} AS ${{ identifier: name }}
|