proto.io 0.0.208 → 0.0.210

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 (80) hide show
  1. package/dist/adapters/file/aliyun-oss.d.ts +6 -6
  2. package/dist/adapters/file/aliyun-oss.js +14 -13
  3. package/dist/adapters/file/aliyun-oss.js.map +1 -1
  4. package/dist/adapters/file/aliyun-oss.mjs +14 -13
  5. package/dist/adapters/file/aliyun-oss.mjs.map +1 -1
  6. package/dist/adapters/file/database.d.ts +3 -3
  7. package/dist/adapters/file/database.js +2 -2
  8. package/dist/adapters/file/database.js.map +1 -1
  9. package/dist/adapters/file/database.mjs +2 -2
  10. package/dist/adapters/file/database.mjs.map +1 -1
  11. package/dist/adapters/file/filesystem.d.ts +5 -5
  12. package/dist/adapters/file/filesystem.js +11 -7
  13. package/dist/adapters/file/filesystem.js.map +1 -1
  14. package/dist/adapters/file/filesystem.mjs +11 -7
  15. package/dist/adapters/file/filesystem.mjs.map +1 -1
  16. package/dist/adapters/file/google-cloud-storage.d.ts +6 -6
  17. package/dist/adapters/file/google-cloud-storage.js +23 -13
  18. package/dist/adapters/file/google-cloud-storage.js.map +1 -1
  19. package/dist/adapters/file/google-cloud-storage.mjs +23 -13
  20. package/dist/adapters/file/google-cloud-storage.mjs.map +1 -1
  21. package/dist/adapters/storage/progres.d.ts +1 -1
  22. package/dist/adapters/storage/progres.js +22 -28
  23. package/dist/adapters/storage/progres.js.map +1 -1
  24. package/dist/adapters/storage/progres.mjs +22 -28
  25. package/dist/adapters/storage/progres.mjs.map +1 -1
  26. package/dist/client.d.ts +3 -3
  27. package/dist/client.js +2 -1
  28. package/dist/client.js.map +1 -1
  29. package/dist/client.mjs +3 -2
  30. package/dist/client.mjs.map +1 -1
  31. package/dist/index.d.ts +3 -3
  32. package/dist/index.js +159 -31
  33. package/dist/index.js.map +1 -1
  34. package/dist/index.mjs +152 -24
  35. package/dist/index.mjs.map +1 -1
  36. package/dist/internals/{base-wSknxBv7.d.ts → base-C1ndp06_.d.ts} +2 -2
  37. package/dist/internals/base-C1ndp06_.d.ts.map +1 -0
  38. package/dist/internals/{base-CfQi0T0I.mjs → base-DYc1_peK.mjs} +3 -3
  39. package/dist/internals/{base-CfQi0T0I.mjs.map → base-DYc1_peK.mjs.map} +1 -1
  40. package/dist/internals/{base-BFKQpiws.js → base-NsJYo2MG.js} +3 -3
  41. package/dist/internals/{base-BFKQpiws.js.map → base-NsJYo2MG.js.map} +1 -1
  42. package/dist/internals/{chunk-BuMQw4dz.js → chunk-BuKmyceG.js} +5 -3
  43. package/dist/internals/chunk-BuKmyceG.js.map +1 -0
  44. package/dist/internals/{chunk-C_BXf1Er.d.ts → chunk-DF4KyvgB.d.ts} +6 -6
  45. package/dist/internals/chunk-DF4KyvgB.d.ts.map +1 -0
  46. package/dist/internals/{chunk-DxYhYVky.mjs → chunk-bpt1C6W4.mjs} +5 -3
  47. package/dist/internals/chunk-bpt1C6W4.mjs.map +1 -0
  48. package/dist/internals/const-C3I6cfav.js +42 -0
  49. package/dist/internals/const-C3I6cfav.js.map +1 -0
  50. package/dist/internals/const-Dkp7Nsv5.mjs +34 -0
  51. package/dist/internals/const-Dkp7Nsv5.mjs.map +1 -0
  52. package/dist/internals/index-B8TESzd9.js.map +1 -1
  53. package/dist/internals/{index-BvwYz4Yp.mjs → index-BgSBzm-K.mjs} +95 -20
  54. package/dist/internals/index-BgSBzm-K.mjs.map +1 -0
  55. package/dist/internals/{index-DVUiXLfI.js → index-Clo9hepf.js} +101 -29
  56. package/dist/internals/index-Clo9hepf.js.map +1 -0
  57. package/dist/internals/{index-CkAvNaAe.js → index-D8O7SinR.js} +50 -3
  58. package/dist/internals/index-D8O7SinR.js.map +1 -0
  59. package/dist/internals/{index-A-hoMfDO.d.ts → index-DIRjiWPh.d.ts} +32 -1
  60. package/dist/internals/index-DIRjiWPh.d.ts.map +1 -0
  61. package/dist/internals/{index-DlY33lfO.mjs → index-DPPLcZx8.mjs} +51 -4
  62. package/dist/internals/index-DPPLcZx8.mjs.map +1 -0
  63. package/dist/internals/index-al1N-qi7.mjs.map +1 -1
  64. package/dist/internals/{index-iqOd-Wdg.d.ts → index-l-Mk0lCc.d.ts} +2 -2
  65. package/dist/internals/index-l-Mk0lCc.d.ts.map +1 -0
  66. package/dist/internals/{random-B0V0EnjP.js → random-CyU_Y2Ay.js} +2 -2
  67. package/dist/internals/{random-B0V0EnjP.js.map → random-CyU_Y2Ay.js.map} +1 -1
  68. package/dist/internals/{random-ZgzzM5v_.mjs → random-ycCeBd0S.mjs} +2 -2
  69. package/dist/internals/{random-ZgzzM5v_.mjs.map → random-ycCeBd0S.mjs.map} +1 -1
  70. package/package.json +1 -1
  71. package/dist/internals/base-wSknxBv7.d.ts.map +0 -1
  72. package/dist/internals/chunk-BuMQw4dz.js.map +0 -1
  73. package/dist/internals/chunk-C_BXf1Er.d.ts.map +0 -1
  74. package/dist/internals/chunk-DxYhYVky.mjs.map +0 -1
  75. package/dist/internals/index-A-hoMfDO.d.ts.map +0 -1
  76. package/dist/internals/index-BvwYz4Yp.mjs.map +0 -1
  77. package/dist/internals/index-CkAvNaAe.js.map +0 -1
  78. package/dist/internals/index-DVUiXLfI.js.map +0 -1
  79. package/dist/internals/index-DlY33lfO.mjs.map +0 -1
  80. package/dist/internals/index-iqOd-Wdg.d.ts.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, s as serialize, U as UPLOAD_TOKEN_HEADER_NAME } from './internals/index-BvwYz4Yp.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-BvwYz4Yp.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-BgSBzm-K.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-BgSBzm-K.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';
@@ -330,11 +331,22 @@ class _ProtoQuery extends TQuery {
330
331
  await tragger(proxy(Object.setPrototypeOf({ object: obj }, this._proto)));
331
332
  }
332
333
  catch (e) {
333
- console.error(e);
334
+ this._proto.logger.error(e);
334
335
  }
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 ?? [];
@@ -345,11 +357,21 @@ class _ProtoQuery extends TQuery {
345
357
  await tragger(proxy(Object.setPrototypeOf({ object: obj }, this._proto)));
346
358
  }
347
359
  catch (e) {
348
- console.error(e);
360
+ this._proto.logger.error(e);
349
361
  }
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 {
@@ -972,7 +1001,7 @@ class ProtoInternal {
972
1001
  await proto.fileStorage.destroy(proto, id);
973
1002
  }
974
1003
  catch (e) {
975
- console.error(e);
1004
+ proto.logger.error(e);
976
1005
  }
977
1006
  })();
978
1007
  }
@@ -1023,17 +1052,67 @@ 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);
1029
1058
  }
1030
1059
  catch (e) {
1031
- console.error(e);
1060
+ proto.logger.error(e);
1032
1061
  }
1033
1062
  })();
1034
1063
  }),
1035
1064
  };
1036
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(_.filter(objects, object => {
1081
+ if (isMaster)
1082
+ return true;
1083
+ const acl = object.acl();
1084
+ const clp = proto.schema[object.className].classLevelPermissions?.get ?? ['*'];
1085
+ return _.some(_roles, x => _.includes(clp, x) && _.includes(acl.read, x));
1086
+ }));
1087
+ await callback(event, payload);
1088
+ }
1089
+ catch (e) {
1090
+ proto.logger.error(e);
1091
+ }
1092
+ })();
1093
+ }),
1094
+ };
1095
+ }
1096
+ liveQuery(proto, event, className, filter, callback) {
1097
+ const _filter = _.isEmpty(filter) ? true : QuerySelector.decode(filter);
1098
+ return this._liveQuery(proto, (ev, objs) => {
1099
+ if (event !== ev)
1100
+ return;
1101
+ for (const object of objs) {
1102
+ if (className !== object.className)
1103
+ continue;
1104
+ (async () => {
1105
+ try {
1106
+ if (_filter === true || _filter.eval(object))
1107
+ await callback(object);
1108
+ }
1109
+ catch (e) {
1110
+ proto.logger.error(e);
1111
+ }
1112
+ })();
1113
+ }
1114
+ });
1115
+ }
1037
1116
  validateCLPs(className, acls, keys) {
1038
1117
  if (!_.has(this.options.schema, className))
1039
1118
  throw Error('No permission');
@@ -1358,7 +1437,7 @@ const schedule = (proto) => {
1358
1437
  await task(proto);
1359
1438
  }
1360
1439
  catch (e) {
1361
- console.error(`Errors on schedule ${op}: ${e}`);
1440
+ proto.logger.error(`Errors on schedule ${op}: ${e}`);
1362
1441
  }
1363
1442
  }
1364
1443
  running = false;
@@ -1428,6 +1507,7 @@ class ProtoService extends ProtoType {
1428
1507
  keySize: 64,
1429
1508
  saltSize: 64,
1430
1509
  },
1510
+ logger: {},
1431
1511
  ...options,
1432
1512
  });
1433
1513
  }
@@ -1435,6 +1515,21 @@ class ProtoService extends ProtoType {
1435
1515
  this._schedule.destroy();
1436
1516
  this[PVK].shutdown();
1437
1517
  }
1518
+ get logger() {
1519
+ const logger = this[PVK].options.logger;
1520
+ const loggerLevel = logger.loggerLevel ?? 'warn';
1521
+ const callbacks = _.map(_logLevels, (x, i) => [x, (...args) => {
1522
+ if (loggerLevel !== 'all' && _.indexOf(_logLevels, loggerLevel) < i)
1523
+ return;
1524
+ const func = logger[x] ?? console[x];
1525
+ if (_.isFunction(func))
1526
+ func(...args);
1527
+ }]);
1528
+ return {
1529
+ loggerLevel,
1530
+ ..._.fromPairs(callbacks),
1531
+ };
1532
+ }
1438
1533
  classes() {
1439
1534
  return _.keys(this[PVK].options.schema);
1440
1535
  }
@@ -1621,10 +1716,10 @@ class ProtoService extends ProtoType {
1621
1716
  }
1622
1717
  listen(callback, selector) {
1623
1718
  const _selector = !_.isNil(selector) ? QuerySelector.decode(selector) : undefined;
1624
- return this[PVK].listen(this, data => {
1719
+ return this[PVK].listen(this, async (data) => {
1625
1720
  if (_selector && !_selector.eval(data))
1626
1721
  return;
1627
- callback(data);
1722
+ await callback(data);
1628
1723
  });
1629
1724
  }
1630
1725
  refs(object, options) {
@@ -1698,7 +1793,7 @@ var authHandler = (proto) => async (req, res, next) => {
1698
1793
  return next();
1699
1794
  }
1700
1795
  catch (e) {
1701
- console.error(e);
1796
+ proto.logger.error(e);
1702
1797
  return next(new Error('Internal server error'));
1703
1798
  }
1704
1799
  };
@@ -2151,7 +2246,7 @@ var filesRoute = (router, proto) => {
2151
2246
  res.setHeader('Content-Length', endBytes - startBytes + 1);
2152
2247
  res.setHeader('Content-Range', `bytes ${startBytes}-${endBytes}/${file.size}`);
2153
2248
  res.status(206);
2154
- stream = payload.fileStorage.fileData(payload, file.token, startBytes, endBytes);
2249
+ stream = payload.fileStorage.fileData(payload, file.token, startBytes, endBytes + 1);
2155
2250
  }
2156
2251
  else {
2157
2252
  res.setHeader('Content-Length', file.size);
@@ -2495,15 +2590,34 @@ const ProtoRoute = async (options) => {
2495
2590
  const registerProtoSocket = (proto, server, endpoint) => {
2496
2591
  const io = endpoint ? server.socket().of(endpoint) : server.socket();
2497
2592
  io.on('connection', async (socket) => {
2498
- let listeners = {};
2593
+ let events = {};
2594
+ let queries = {};
2499
2595
  const connect = async (token) => {
2500
2596
  const payload = await proto.connectWithSessionToken(token);
2501
- const { remove } = payload.listen(data => {
2502
- const ids = _.keys(_.pickBy(listeners, v => v instanceof QuerySelector ? v.eval(data) : v));
2597
+ const { remove: remove_basic } = payload.listen(data => {
2598
+ const ids = _.keys(_.pickBy(events, v => v instanceof QuerySelector ? v.eval(data) : v));
2599
+ const payload = JSON.parse(serialize(data));
2503
2600
  if (!_.isEmpty(ids))
2504
- socket.emit('data', { ids, data });
2601
+ socket.emit('ON_EV_NOTIFY', { ids, data: payload });
2505
2602
  });
2506
- return remove;
2603
+ const { remove: remove_livequery } = payload[PVK]._liveQuery(payload, (ev, objs) => {
2604
+ const ids = {};
2605
+ for (const obj of objs) {
2606
+ ids[obj.objectId] = _.keys(_.pickBy(queries, v => {
2607
+ if (v.event !== ev || v.className !== obj.className)
2608
+ return false;
2609
+ return v.filter instanceof QuerySelector ? v.filter.eval(obj) : v.filter;
2610
+ }));
2611
+ }
2612
+ if (_.isEmpty(ids))
2613
+ return;
2614
+ const payload = JSON.parse(serialize(_.filter(objs, obj => !_.isEmpty(ids[obj.objectId]))));
2615
+ socket.emit('ON_EV_LIVEQUERY', { ids, data: payload });
2616
+ });
2617
+ return () => {
2618
+ remove_basic();
2619
+ remove_livequery();
2620
+ };
2507
2621
  };
2508
2622
  const { token } = socket.handshake.auth;
2509
2623
  let remove = connect(token);
@@ -2514,19 +2628,33 @@ const registerProtoSocket = (proto, server, endpoint) => {
2514
2628
  socket.on('disconnect', () => {
2515
2629
  remove.then(rm => rm());
2516
2630
  });
2517
- socket.on('register', (payload) => {
2518
- listeners = _.mapValues(payload, v => {
2631
+ socket.on('EV_NOTIFY', (payload) => {
2632
+ events = _.mapValues(payload, v => {
2519
2633
  if (_.isBoolean(v))
2520
2634
  return true;
2521
2635
  try {
2522
2636
  return QuerySelector.decode(v);
2523
2637
  }
2524
2638
  catch (error) {
2525
- console.error(error);
2639
+ proto.logger.error(error);
2526
2640
  return false;
2527
2641
  }
2528
2642
  });
2529
2643
  });
2644
+ socket.on('EV_LIVEQUERY', (payload) => {
2645
+ queries = _.mapValues(payload, v => {
2646
+ const { event = '', className = '', filter } = v ?? {};
2647
+ if (_.isBoolean(v))
2648
+ return { event, className, filter: true };
2649
+ try {
2650
+ return { event, className, filter: QuerySelector.decode(filter) };
2651
+ }
2652
+ catch (error) {
2653
+ proto.logger.error(error);
2654
+ return { event, className, filter: false };
2655
+ }
2656
+ });
2657
+ });
2530
2658
  });
2531
2659
  return io;
2532
2660
  };