proto.io 0.0.209 → 0.0.211

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.
Files changed (56) hide show
  1. package/dist/adapters/file/aliyun-oss.d.ts +3 -3
  2. package/dist/adapters/file/database.d.ts +2 -2
  3. package/dist/adapters/file/database.js +1 -1
  4. package/dist/adapters/file/database.mjs +1 -1
  5. package/dist/adapters/file/filesystem.d.ts +3 -3
  6. package/dist/adapters/file/google-cloud-storage.d.ts +3 -3
  7. package/dist/adapters/storage/progres.d.ts +1 -1
  8. package/dist/adapters/storage/progres.js +22 -28
  9. package/dist/adapters/storage/progres.js.map +1 -1
  10. package/dist/adapters/storage/progres.mjs +22 -28
  11. package/dist/adapters/storage/progres.mjs.map +1 -1
  12. package/dist/client.d.ts +3 -3
  13. package/dist/client.js +2 -1
  14. package/dist/client.js.map +1 -1
  15. package/dist/client.mjs +3 -2
  16. package/dist/client.mjs.map +1 -1
  17. package/dist/index.d.ts +3 -3
  18. package/dist/index.js +134 -23
  19. package/dist/index.js.map +1 -1
  20. package/dist/index.mjs +127 -16
  21. package/dist/index.mjs.map +1 -1
  22. package/dist/internals/{base-DbSaGX_u.d.ts → base-BCWOHUaQ.d.ts} +2 -2
  23. package/dist/internals/base-BCWOHUaQ.d.ts.map +1 -0
  24. package/dist/internals/{chunk-bYrnqXiI.d.ts → chunk-2pKgkO5-.d.ts} +3 -3
  25. package/dist/internals/chunk-2pKgkO5-.d.ts.map +1 -0
  26. package/dist/internals/const-C3I6cfav.js +42 -0
  27. package/dist/internals/const-C3I6cfav.js.map +1 -0
  28. package/dist/internals/const-Dkp7Nsv5.mjs +34 -0
  29. package/dist/internals/const-Dkp7Nsv5.mjs.map +1 -0
  30. package/dist/internals/{index-Dx36qTUa.d.ts → index-8AdKlZUU.d.ts} +2 -2
  31. package/dist/internals/index-8AdKlZUU.d.ts.map +1 -0
  32. package/dist/internals/index-B8TESzd9.js.map +1 -1
  33. package/dist/internals/{index-CK1snZyh.js → index-Btxxs0KS.js} +106 -29
  34. package/dist/internals/index-Btxxs0KS.js.map +1 -0
  35. package/dist/internals/{index-Eo70ZAdZ.mjs → index-CoeDMG5V.mjs} +101 -20
  36. package/dist/internals/index-CoeDMG5V.mjs.map +1 -0
  37. package/dist/internals/{index-CkAvNaAe.js → index-D8O7SinR.js} +50 -3
  38. package/dist/internals/index-D8O7SinR.js.map +1 -0
  39. package/dist/internals/{index-DlY33lfO.mjs → index-DPPLcZx8.mjs} +51 -4
  40. package/dist/internals/index-DPPLcZx8.mjs.map +1 -0
  41. package/dist/internals/index-al1N-qi7.mjs.map +1 -1
  42. package/dist/internals/{index-Dn1IkLDx.d.ts → index-lTzbCO8S.d.ts} +24 -1
  43. package/dist/internals/index-lTzbCO8S.d.ts.map +1 -0
  44. package/dist/internals/{random-B0V0EnjP.js → random-CyU_Y2Ay.js} +2 -2
  45. package/dist/internals/{random-B0V0EnjP.js.map → random-CyU_Y2Ay.js.map} +1 -1
  46. package/dist/internals/{random-ZgzzM5v_.mjs → random-ycCeBd0S.mjs} +2 -2
  47. package/dist/internals/{random-ZgzzM5v_.mjs.map → random-ycCeBd0S.mjs.map} +1 -1
  48. package/package.json +1 -1
  49. package/dist/internals/base-DbSaGX_u.d.ts.map +0 -1
  50. package/dist/internals/chunk-bYrnqXiI.d.ts.map +0 -1
  51. package/dist/internals/index-CK1snZyh.js.map +0 -1
  52. package/dist/internals/index-CkAvNaAe.js.map +0 -1
  53. package/dist/internals/index-DlY33lfO.mjs.map +0 -1
  54. package/dist/internals/index-Dn1IkLDx.d.ts.map +0 -1
  55. package/dist/internals/index-Dx36qTUa.d.ts.map +0 -1
  56. package/dist/internals/index-Eo70ZAdZ.mjs.map +0 -1
package/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import _ from 'lodash';
2
2
  import { Server } from '@o2ter/server-js';
3
- import { Q as QueryValidator, r as resolveColumn, a as resolveDataType, g as generateId } from './internals/random-ZgzzM5v_.mjs';
3
+ import { Q as QueryValidator, r as resolveColumn, a as resolveDataType, g as generateId } from './internals/random-ycCeBd0S.mjs';
4
4
  import { P as PVK } from './internals/private-CNw40LZ7.mjs';
5
5
  import { prototypes, asyncStream, isBinaryData, base64ToBuffer } from '@o2ter/utils-js';
6
- import { T as TQuery, d as deserialize, P as PROTO_NOTY_MSG, M as MASTER_USER_HEADER_NAME, a as MASTER_PASS_HEADER_NAME, A as AUTH_COOKIE_KEY, b as TUser, c as ProtoType, _ as _logLevels, s as serialize, U as UPLOAD_TOKEN_HEADER_NAME } from './internals/index-Eo70ZAdZ.mjs';
7
- export { e as ProtoClient, f as classExtends, k as isFile, l as isJob, g as isObject, i as isQuery, j as isRole, h as isUser } from './internals/index-Eo70ZAdZ.mjs';
6
+ import { L as LiveQuerySubscription, T as TQuery, d as deserialize, s as serialize, a as TUser, P as ProtoType, _ as _logLevels } from './internals/index-CoeDMG5V.mjs';
7
+ export { b as ProtoClient, c as classExtends, h as isFile, j as isJob, e as isObject, i as isQuery, g as isRole, f as isUser } from './internals/index-CoeDMG5V.mjs';
8
8
  import { i as isPointer, a as isRelation, T as TObject, b as isShape, d as defaultObjectKeyTypes, c as isPrimitive } from './internals/index-al1N-qi7.mjs';
9
9
  import jwt from 'jsonwebtoken';
10
10
  import { Blob } from 'node:buffer';
@@ -12,8 +12,9 @@ import { Readable } from 'node:stream';
12
12
  import { scrypt } from 'node:crypto';
13
13
  import { promisify } from 'util';
14
14
  import { randomBytes, randomUUID } from '@o2ter/crypto-js';
15
+ import { P as PROTO_NOTY_MSG, a as PROTO_LIVEQUERY_MSG, M as MASTER_USER_HEADER_NAME, b as MASTER_PASS_HEADER_NAME, A as AUTH_COOKIE_KEY, U as UPLOAD_TOKEN_HEADER_NAME } from './internals/const-Dkp7Nsv5.mjs';
16
+ import { Q as QuerySelector } from './internals/index-DPPLcZx8.mjs';
15
17
  export { Decimal } from 'decimal.js';
16
- import { Q as QuerySelector } from './internals/index-DlY33lfO.mjs';
17
18
  import queryType from 'query-types';
18
19
  import busboy from 'busboy';
19
20
  import 'axios';
@@ -335,6 +336,17 @@ class _ProtoQuery extends TQuery {
335
336
  })();
336
337
  }
337
338
  }
339
+ if (this._proto.schema[this.className]?.liveQuery) {
340
+ (async () => {
341
+ try {
342
+ await this._proto[PVK].publishLiveQuery(this._proto, 'create', _.filter(objects, x => x.__v === 0));
343
+ await this._proto[PVK].publishLiveQuery(this._proto, 'update', _.filter(objects, x => x.__v !== 0));
344
+ }
345
+ catch (e) {
346
+ this._proto.logger.error(e);
347
+ }
348
+ })();
349
+ }
338
350
  }
339
351
  _on_delete(objects) {
340
352
  const traggers = this._proto[PVK].triggers[this.className]?.delete ?? [];
@@ -350,6 +362,16 @@ class _ProtoQuery extends TQuery {
350
362
  })();
351
363
  }
352
364
  }
365
+ if (this._proto.schema[this.className]?.liveQuery) {
366
+ (async () => {
367
+ try {
368
+ await this._proto[PVK].publishLiveQuery(this._proto, 'delete', objects);
369
+ }
370
+ catch (e) {
371
+ this._proto.logger.error(e);
372
+ }
373
+ })();
374
+ }
353
375
  }
354
376
  async insertMany(values, options) {
355
377
  const objs = this._objectMethods(await this._dispatcher(options).insert({
@@ -395,6 +417,9 @@ class ProtoQuery extends _ProtoQuery {
395
417
  clone[PVK].options = options ?? { ...this[PVK].options };
396
418
  return clone;
397
419
  }
420
+ subscribe() {
421
+ return new LiveQuerySubscription(this.className, this._proto, this[PVK].options.filter ?? []);
422
+ }
398
423
  }
399
424
  class ProtoRelationQuery extends _ProtoQuery {
400
425
  constructor(proto, opts) {
@@ -412,6 +437,9 @@ class ProtoRelationQuery extends _ProtoQuery {
412
437
  clone[PVK].options = options ?? { ...this[PVK].options };
413
438
  return clone;
414
439
  }
440
+ subscribe() {
441
+ throw Error('Unable to subscribe to relationship query');
442
+ }
415
443
  }
416
444
 
417
445
  //
@@ -752,6 +780,7 @@ const mergeSchema = (...schemas) => _.reduce(schemas, (acc, schema) => ({
752
780
  ]),
753
781
  ...(s.indexes ?? []),
754
782
  ],
783
+ liveQuery: acc[className]?.liveQuery || s.liveQuery,
755
784
  })),
756
785
  }), {});
757
786
  class ProtoInternal {
@@ -1023,9 +1052,38 @@ class ProtoInternal {
1023
1052
  const { _rperm } = payload;
1024
1053
  (async () => {
1025
1054
  try {
1026
- if (isMaster || _.some(await roles, x => _.includes(_rperm, x))) {
1027
- callback(payload);
1028
- }
1055
+ if (!isMaster && !_.some(await roles, x => _.includes(_rperm, x)))
1056
+ return;
1057
+ await callback(payload);
1058
+ }
1059
+ catch (e) {
1060
+ proto.logger.error(e);
1061
+ }
1062
+ })();
1063
+ }),
1064
+ };
1065
+ }
1066
+ async publishLiveQuery(proto, event, objects) {
1067
+ if (_.isEmpty(objects))
1068
+ return;
1069
+ return this.options.pubsub.publish(PROTO_LIVEQUERY_MSG, JSON.parse(serialize({ event, objects }, { objAttrs: TObject.defaultKeys })));
1070
+ }
1071
+ _liveQuery(proto, callback) {
1072
+ const isMaster = proto.isMaster;
1073
+ const roles = isMaster ? [] : this._perms(proto);
1074
+ return {
1075
+ remove: this.options.pubsub.subscribe(PROTO_LIVEQUERY_MSG, payload => {
1076
+ const { event, objects } = deserialize(JSON.stringify(payload));
1077
+ (async () => {
1078
+ try {
1079
+ const _roles = await roles;
1080
+ const payload = proto.rebind(isMaster ? objects : _.filter(objects, object => {
1081
+ const acl = object.acl();
1082
+ const clp = proto.schema[object.className].classLevelPermissions?.get ?? ['*'];
1083
+ return _.some(_roles, x => _.includes(clp, x) && _.includes(acl.read, x));
1084
+ }));
1085
+ if (!_.isEmpty(payload))
1086
+ await callback(event, payload);
1029
1087
  }
1030
1088
  catch (e) {
1031
1089
  proto.logger.error(e);
@@ -1034,6 +1092,26 @@ class ProtoInternal {
1034
1092
  }),
1035
1093
  };
1036
1094
  }
1095
+ liveQuery(proto, event, className, filter, callback) {
1096
+ const _filter = _.isEmpty(filter) ? true : QuerySelector.decode(filter);
1097
+ return this._liveQuery(proto, (ev, objs) => {
1098
+ if (event !== ev)
1099
+ return;
1100
+ for (const object of objs) {
1101
+ if (className !== object.className)
1102
+ continue;
1103
+ (async () => {
1104
+ try {
1105
+ if (_filter === true || _filter.eval(object))
1106
+ await callback(object);
1107
+ }
1108
+ catch (e) {
1109
+ proto.logger.error(e);
1110
+ }
1111
+ })();
1112
+ }
1113
+ });
1114
+ }
1037
1115
  validateCLPs(className, acls, keys) {
1038
1116
  if (!_.has(this.options.schema, className))
1039
1117
  throw Error('No permission');
@@ -1637,10 +1715,10 @@ class ProtoService extends ProtoType {
1637
1715
  }
1638
1716
  listen(callback, selector) {
1639
1717
  const _selector = !_.isNil(selector) ? QuerySelector.decode(selector) : undefined;
1640
- return this[PVK].listen(this, data => {
1718
+ return this[PVK].listen(this, async (data) => {
1641
1719
  if (_selector && !_selector.eval(data))
1642
1720
  return;
1643
- callback(data);
1721
+ await callback(data);
1644
1722
  });
1645
1723
  }
1646
1724
  refs(object, options) {
@@ -2511,15 +2589,34 @@ const ProtoRoute = async (options) => {
2511
2589
  const registerProtoSocket = (proto, server, endpoint) => {
2512
2590
  const io = endpoint ? server.socket().of(endpoint) : server.socket();
2513
2591
  io.on('connection', async (socket) => {
2514
- let listeners = {};
2592
+ let events = {};
2593
+ let queries = {};
2515
2594
  const connect = async (token) => {
2516
2595
  const payload = await proto.connectWithSessionToken(token);
2517
- const { remove } = payload.listen(data => {
2518
- const ids = _.keys(_.pickBy(listeners, v => v instanceof QuerySelector ? v.eval(data) : v));
2596
+ const { remove: remove_basic } = payload.listen(data => {
2597
+ const ids = _.keys(_.pickBy(events, v => v instanceof QuerySelector ? v.eval(data) : v));
2598
+ const payload = JSON.parse(serialize(data));
2519
2599
  if (!_.isEmpty(ids))
2520
- socket.emit('data', { ids, data });
2600
+ socket.emit('ON_EV_NOTIFY', { ids, data: payload });
2601
+ });
2602
+ const { remove: remove_livequery } = payload[PVK]._liveQuery(payload, (ev, objs) => {
2603
+ const ids = {};
2604
+ for (const obj of objs) {
2605
+ ids[obj.objectId] = _.keys(_.pickBy(queries, v => {
2606
+ if (v.event !== ev || v.className !== obj.className)
2607
+ return false;
2608
+ return v.filter instanceof QuerySelector ? v.filter.eval(obj) : v.filter;
2609
+ }));
2610
+ }
2611
+ if (_.isEmpty(ids))
2612
+ return;
2613
+ const payload = JSON.parse(serialize(_.filter(objs, obj => !_.isEmpty(ids[obj.objectId]))));
2614
+ socket.emit('ON_EV_LIVEQUERY', { ids, data: payload });
2521
2615
  });
2522
- return remove;
2616
+ return () => {
2617
+ remove_basic();
2618
+ remove_livequery();
2619
+ };
2523
2620
  };
2524
2621
  const { token } = socket.handshake.auth;
2525
2622
  let remove = connect(token);
@@ -2530,8 +2627,8 @@ const registerProtoSocket = (proto, server, endpoint) => {
2530
2627
  socket.on('disconnect', () => {
2531
2628
  remove.then(rm => rm());
2532
2629
  });
2533
- socket.on('register', (payload) => {
2534
- listeners = _.mapValues(payload, v => {
2630
+ socket.on('EV_NOTIFY', (payload) => {
2631
+ events = _.mapValues(payload, v => {
2535
2632
  if (_.isBoolean(v))
2536
2633
  return true;
2537
2634
  try {
@@ -2543,6 +2640,20 @@ const registerProtoSocket = (proto, server, endpoint) => {
2543
2640
  }
2544
2641
  });
2545
2642
  });
2643
+ socket.on('EV_LIVEQUERY', (payload) => {
2644
+ queries = _.mapValues(payload, v => {
2645
+ const { event = '', className = '', filter } = v ?? {};
2646
+ if (_.isBoolean(v))
2647
+ return { event, className, filter: true };
2648
+ try {
2649
+ return { event, className, filter: QuerySelector.decode(filter) };
2650
+ }
2651
+ catch (error) {
2652
+ proto.logger.error(error);
2653
+ return { event, className, filter: false };
2654
+ }
2655
+ });
2656
+ });
2546
2657
  });
2547
2658
  return io;
2548
2659
  };