proto.io 0.0.160 → 0.0.162

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 (36) hide show
  1. package/dist/adapters/file/database.d.ts +2 -2
  2. package/dist/adapters/file/database.mjs +2 -2
  3. package/dist/adapters/file/filesystem.d.ts +2 -2
  4. package/dist/adapters/file/google-cloud-storage.d.ts +2 -2
  5. package/dist/adapters/storage/progres.d.ts +1 -1
  6. package/dist/adapters/storage/progres.mjs +3 -3
  7. package/dist/client.d.ts +3 -3
  8. package/dist/client.js +1 -1
  9. package/dist/client.mjs +3 -3
  10. package/dist/index.d.ts +3 -3
  11. package/dist/index.js +134 -64
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.mjs +138 -68
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/internals/{index-Bs06MNCK.js → index-4YC13MvT.js} +43 -24
  16. package/dist/internals/index-4YC13MvT.js.map +1 -0
  17. package/dist/internals/{index-BmRuvHVZ.mjs → index-ByfpVHca.mjs} +2 -2
  18. package/dist/internals/{index-BmRuvHVZ.mjs.map → index-ByfpVHca.mjs.map} +1 -1
  19. package/dist/internals/{index-CXPH5Pup.d.ts → index-C1NwI5ZD.d.ts} +5 -7
  20. package/dist/internals/index-C1NwI5ZD.d.ts.map +1 -0
  21. package/dist/internals/{index-B01TqoO1.mjs → index-CupbSHHH.mjs} +44 -25
  22. package/dist/internals/index-CupbSHHH.mjs.map +1 -0
  23. package/dist/internals/{index-sFLwlp-C.d.ts → index-DlvbXwIt.d.ts} +3 -3
  24. package/dist/internals/index-DlvbXwIt.d.ts.map +1 -0
  25. package/dist/internals/{index-BraAbRER.d.ts → index-LYC1mup1.d.ts} +2 -2
  26. package/dist/internals/index-LYC1mup1.d.ts.map +1 -0
  27. package/dist/internals/{index-tU-lsQqj.mjs → index-S5Bq-KsU.mjs} +2 -2
  28. package/dist/internals/{index-tU-lsQqj.mjs.map → index-S5Bq-KsU.mjs.map} +1 -1
  29. package/dist/internals/{random-DifCxbl6.mjs → random-w8WDYQEe.mjs} +4 -4
  30. package/dist/internals/{random-DifCxbl6.mjs.map → random-w8WDYQEe.mjs.map} +1 -1
  31. package/package.json +1 -1
  32. package/dist/internals/index-B01TqoO1.mjs.map +0 -1
  33. package/dist/internals/index-BraAbRER.d.ts.map +0 -1
  34. package/dist/internals/index-Bs06MNCK.js.map +0 -1
  35. package/dist/internals/index-CXPH5Pup.d.ts.map +0 -1
  36. package/dist/internals/index-sFLwlp-C.d.ts.map +0 -1
package/dist/index.mjs CHANGED
@@ -1,18 +1,18 @@
1
1
  import _ from 'lodash';
2
2
  import { Server } from '@o2ter/server-js';
3
- import { Q as QueryValidator, g as generateId, r as resolveDataType } from './internals/random-DifCxbl6.mjs';
3
+ import { Q as QueryValidator, r as resolveColumn, g as generateId, a as resolveDataType } from './internals/random-w8WDYQEe.mjs';
4
4
  import { P as PVK } from './internals/private-BUpLAMZi.mjs';
5
5
  import { asyncStream, asyncIterableToArray, isBinaryData, base64ToBuffer } from '@o2ter/utils-js';
6
- import { T as TQuery, M as MASTER_USER_HEADER_NAME, a as MASTER_PASS_HEADER_NAME, A as AUTH_COOKIE_KEY, b as TUser, P as ProtoType, s as serialize, d as deserialize, U as UPLOAD_TOKEN_HEADER_NAME } from './internals/index-B01TqoO1.mjs';
7
- export { c as ProtoClient, e as classExtends, j as isFile, f as isObject, i as isQuery, h as isRole, g as isUser } from './internals/index-B01TqoO1.mjs';
8
- import { d as decodeUpdateOp, T as TObject, i as isShape, a as isPointer, b as isRelation, c as defaultObjectKeyTypes, e as isPrimitive } from './internals/index-BmRuvHVZ.mjs';
6
+ import { T as TQuery, M as MASTER_USER_HEADER_NAME, a as MASTER_PASS_HEADER_NAME, A as AUTH_COOKIE_KEY, b as TUser, P as ProtoType, s as serialize, d as deserialize, U as UPLOAD_TOKEN_HEADER_NAME } from './internals/index-CupbSHHH.mjs';
7
+ export { c as ProtoClient, e as classExtends, j as isFile, f as isObject, i as isQuery, h as isRole, g as isUser } from './internals/index-CupbSHHH.mjs';
8
+ import { i as isPointer, a as isRelation, d as decodeUpdateOp, T as TObject, b as isShape, c as defaultObjectKeyTypes, e as isPrimitive } from './internals/index-ByfpVHca.mjs';
9
9
  import jwt from 'jsonwebtoken';
10
10
  import { Blob } from 'node:buffer';
11
11
  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 { Q as QuerySelector } from './internals/index-tU-lsQqj.mjs';
15
+ import { Q as QuerySelector } from './internals/index-S5Bq-KsU.mjs';
16
16
  import queryType from 'query-types';
17
17
  import busboy from 'busboy';
18
18
  export { Decimal } from 'decimal.js';
@@ -316,19 +316,19 @@ const _serviceOf = (options) => options?.session instanceof ProtoService ? optio
316
316
  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
317
317
  // THE SOFTWARE.
318
318
  //
319
- class ProtoQuery extends TQuery {
319
+ class _ProtoQuery extends TQuery {
320
320
  _proto;
321
321
  _opts;
322
- constructor(className, proto, opts) {
323
- super(className);
322
+ constructor(proto, opts) {
323
+ super();
324
324
  this._proto = proto;
325
325
  this._opts = opts;
326
326
  }
327
327
  get _queryOptions() {
328
328
  return {
329
+ ...this[PVK].options,
329
330
  className: this.className,
330
331
  relatedBy: this._opts.relatedBy,
331
- ...this[PVK].options,
332
332
  };
333
333
  }
334
334
  _dispatcher(options) {
@@ -344,11 +344,6 @@ class ProtoQuery extends TQuery {
344
344
  count(options) {
345
345
  return this._dispatcher(options).count(this._queryOptions);
346
346
  }
347
- clone(options) {
348
- const clone = new ProtoQuery(this.className, this._proto, this._opts);
349
- clone[PVK].options = options ?? { ...this[PVK].options };
350
- return clone;
351
- }
352
347
  _objectMethods(object) {
353
348
  return this._proto.rebind(object);
354
349
  }
@@ -538,6 +533,38 @@ class ProtoQuery extends TQuery {
538
533
  return this._dispatcher(options).deleteMany(this._queryOptions);
539
534
  }
540
535
  }
536
+ class ProtoQuery extends _ProtoQuery {
537
+ _className;
538
+ constructor(className, proto, opts) {
539
+ super(proto, opts);
540
+ this._className = className;
541
+ }
542
+ get className() {
543
+ return this._className;
544
+ }
545
+ clone(options) {
546
+ const clone = new ProtoQuery(this.className, this._proto, this._opts);
547
+ clone[PVK].options = options ?? { ...this[PVK].options };
548
+ return clone;
549
+ }
550
+ }
551
+ class ProtoRelationQuery extends _ProtoQuery {
552
+ constructor(proto, opts) {
553
+ super(proto, opts);
554
+ }
555
+ get className() {
556
+ const { className, key } = this._opts.relatedBy;
557
+ const { dataType } = resolveColumn(this._proto.schema, className, key);
558
+ if (!isPointer(dataType) && !isRelation(dataType))
559
+ throw Error(`Invalid relation key: ${key}`);
560
+ return dataType.target;
561
+ }
562
+ clone(options) {
563
+ const clone = new ProtoRelationQuery(this._proto, this._opts);
564
+ clone[PVK].options = options ?? { ...this[PVK].options };
565
+ return clone;
566
+ }
567
+ }
541
568
 
542
569
  //
543
570
  // defaults.ts
@@ -1168,13 +1195,24 @@ const sessionId = (proto, request) => {
1168
1195
  const session = _session(proto, request);
1169
1196
  return sessionMap.get(request)?.sessionId ?? session?.sessionId;
1170
1197
  };
1171
- const sessionInfoMap = new WeakMap();
1198
+ const userCacheMap = new WeakMap;
1172
1199
  const fetchSessionInfo = async (proto, userId) => {
1173
- const user = _.isString(userId) ? await proto.Query('User').get(userId, { master: true }) : undefined;
1174
- const roles = user instanceof TUser ? _.filter(await proto.userRoles(user), x => !_.isEmpty(x.name)) : [];
1200
+ if (!userId)
1201
+ return {};
1202
+ if (!userCacheMap.has(proto[PVK]))
1203
+ userCacheMap.set(proto[PVK], {});
1204
+ const cache = userCacheMap.get(proto[PVK]);
1205
+ if (_.isNil(cache[userId]))
1206
+ cache[userId] = (async () => {
1207
+ const user = _.isString(userId) ? await proto.Query('User').get(userId, { master: true }) : undefined;
1208
+ const _roles = user instanceof TUser ? _.filter(await proto.userRoles(user), x => !_.isEmpty(x.name)) : [];
1209
+ cache[userId] = undefined;
1210
+ return { user, _roles };
1211
+ })();
1212
+ const { user, _roles } = await cache[userId];
1175
1213
  return {
1176
- _roles: roles,
1177
- user: user instanceof TUser ? user : undefined,
1214
+ user: user?.clone(),
1215
+ _roles: _.map(_roles, x => x.clone()),
1178
1216
  };
1179
1217
  };
1180
1218
  const sessionWithToken = async (proto, token) => {
@@ -1186,6 +1224,7 @@ const sessionWithToken = async (proto, token) => {
1186
1224
  loginedAt: info?.user ? session?.loginedAt : undefined,
1187
1225
  };
1188
1226
  };
1227
+ const sessionInfoMap = new WeakMap();
1189
1228
  const session = async (proto, request) => {
1190
1229
  const session = _session(proto, request);
1191
1230
  const cached = sessionInfoMap.get(request);
@@ -1369,11 +1408,11 @@ class ProtoService extends ProtoType {
1369
1408
  Query(className) {
1370
1409
  return new ProtoQuery(className, this, {});
1371
1410
  }
1372
- Relation(className, object, key) {
1411
+ Relation(object, key) {
1373
1412
  const objectId = object.objectId;
1374
1413
  if (!objectId)
1375
1414
  throw Error('Invalid object');
1376
- return new ProtoQuery(className, this, {
1415
+ return new ProtoRelationQuery(this, {
1377
1416
  relatedBy: {
1378
1417
  className: object.className,
1379
1418
  objectId,
@@ -1658,64 +1697,70 @@ const verifyRelatedBy = (relatedBy) => {
1658
1697
  throw Error('Invalid option');
1659
1698
  };
1660
1699
  var classesRoute = (router, proto) => {
1700
+ const defaultHandler = async (req) => {
1701
+ const { name } = req.params;
1702
+ const { operation, context, silent, random, attributes, update, setOnInsert, relatedBy, ...options } = deserialize(req.body);
1703
+ verifyRelatedBy(relatedBy);
1704
+ const payload = proto.connect(req);
1705
+ const query = relatedBy ? payload.Relation(payload.Object(relatedBy.className, relatedBy.objectId), relatedBy.key) : payload.Query(name);
1706
+ query[PVK].options = options;
1707
+ const opts = { master: payload.isMaster, context, silent };
1708
+ switch (operation) {
1709
+ case 'explain':
1710
+ if (!payload.isMaster)
1711
+ throw Error('No permission');
1712
+ return query.explain(opts);
1713
+ case 'count': return query.count(opts);
1714
+ case 'find':
1715
+ {
1716
+ const maxFetchLimit = payload[PVK].options.maxFetchLimit;
1717
+ query[PVK].options.limit = query[PVK].options.limit ?? maxFetchLimit;
1718
+ if (query[PVK].options.limit > maxFetchLimit)
1719
+ throw Error('Query over limit');
1720
+ return await query.find(opts);
1721
+ }
1722
+ case 'random':
1723
+ {
1724
+ const maxFetchLimit = payload[PVK].options.maxFetchLimit;
1725
+ query[PVK].options.limit = query[PVK].options.limit ?? maxFetchLimit;
1726
+ if (query[PVK].options.limit > maxFetchLimit)
1727
+ throw Error('Query over limit');
1728
+ return await query.random(random, opts);
1729
+ }
1730
+ case 'nonrefs':
1731
+ {
1732
+ const maxFetchLimit = payload[PVK].options.maxFetchLimit;
1733
+ query[PVK].options.limit = query[PVK].options.limit ?? maxFetchLimit;
1734
+ if (query[PVK].options.limit > maxFetchLimit)
1735
+ throw Error('Query over limit');
1736
+ return await query.nonrefs(opts);
1737
+ }
1738
+ case 'insert': return query.insert(attributes, opts);
1739
+ case 'insertMany': return query.insertMany(attributes, opts);
1740
+ case 'updateOne': return query.updateOne(update, opts);
1741
+ case 'upsertOne': return query.upsertOne(update, setOnInsert, opts);
1742
+ case 'deleteOne': return query.deleteOne(opts);
1743
+ case 'deleteMany': return query.deleteMany(opts);
1744
+ default: throw Error('Invalid operation');
1745
+ }
1746
+ };
1661
1747
  router.post('/classes/:name', Server.text({ type: '*/*' }), async (req, res) => {
1662
1748
  res.setHeader('Cache-Control', ['no-cache', 'no-store']);
1663
1749
  const { name } = req.params;
1664
1750
  const classes = proto.classes();
1665
1751
  if (!_.includes(classes, name))
1666
1752
  return res.sendStatus(404);
1667
- await response(res, async () => {
1668
- const { operation, context, silent, random, attributes, update, setOnInsert, relatedBy, ...options } = deserialize(req.body);
1669
- verifyRelatedBy(relatedBy);
1670
- const payload = proto.connect(req);
1671
- const query = relatedBy ? payload.Relation(name, payload.Object(relatedBy.className, relatedBy.objectId), relatedBy.key) : payload.Query(name);
1672
- query[PVK].options = options;
1673
- const opts = { master: payload.isMaster, context, silent };
1674
- switch (operation) {
1675
- case 'explain':
1676
- if (!payload.isMaster)
1677
- throw Error('No permission');
1678
- return query.explain(opts);
1679
- case 'count': return query.count(opts);
1680
- case 'find':
1681
- {
1682
- const maxFetchLimit = payload[PVK].options.maxFetchLimit;
1683
- query[PVK].options.limit = query[PVK].options.limit ?? maxFetchLimit;
1684
- if (query[PVK].options.limit > maxFetchLimit)
1685
- throw Error('Query over limit');
1686
- return await query.find(opts);
1687
- }
1688
- case 'random':
1689
- {
1690
- const maxFetchLimit = payload[PVK].options.maxFetchLimit;
1691
- query[PVK].options.limit = query[PVK].options.limit ?? maxFetchLimit;
1692
- if (query[PVK].options.limit > maxFetchLimit)
1693
- throw Error('Query over limit');
1694
- return await query.random(random, opts);
1695
- }
1696
- case 'nonrefs':
1697
- {
1698
- const maxFetchLimit = payload[PVK].options.maxFetchLimit;
1699
- query[PVK].options.limit = query[PVK].options.limit ?? maxFetchLimit;
1700
- if (query[PVK].options.limit > maxFetchLimit)
1701
- throw Error('Query over limit');
1702
- return await query.nonrefs(opts);
1703
- }
1704
- case 'insert': return query.insert(attributes, opts);
1705
- case 'insertMany': return query.insertMany(attributes, opts);
1706
- case 'updateOne': return query.updateOne(update, opts);
1707
- case 'upsertOne': return query.upsertOne(update, setOnInsert, opts);
1708
- case 'deleteOne': return query.deleteOne(opts);
1709
- case 'deleteMany': return query.deleteMany(opts);
1710
- default: throw Error('Invalid operation');
1711
- }
1712
- });
1753
+ await response(res, () => defaultHandler(req));
1754
+ });
1755
+ router.post('/relation', Server.text({ type: '*/*' }), async (req, res) => {
1756
+ res.setHeader('Cache-Control', ['no-cache', 'no-store']);
1757
+ await response(res, () => defaultHandler(req));
1713
1758
  });
1714
1759
  const createQuery = (payload, req, checkLimit) => {
1715
1760
  const { name } = req.params;
1716
1761
  const { filter, sort, includes, skip, limit, relatedBy, } = req.query;
1717
1762
  verifyRelatedBy(relatedBy);
1718
- const query = relatedBy ? payload.Relation(name, payload.Object(relatedBy.className, relatedBy.objectId), relatedBy.key) : payload.Query(name);
1763
+ const query = relatedBy ? payload.Relation(payload.Object(relatedBy.className, relatedBy.objectId), relatedBy.key) : payload.Query(name);
1719
1764
  query[PVK].options.filter = !_.isEmpty(filter) && _.isString(filter) ? _.castArray(deserialize(filter)) : [];
1720
1765
  query[PVK].options.sort = _.isPlainObject(sort) && _.every(_.values(sort), _.isNumber) ? sort : undefined;
1721
1766
  query[PVK].options.includes = _.isArray(includes) && _.every(includes, _.isString) ? includes : undefined;
@@ -1740,6 +1785,11 @@ var classesRoute = (router, proto) => {
1740
1785
  const payload = proto.connect(req);
1741
1786
  await response(res, async () => createQuery(payload, req, true).find({ master: payload.isMaster }));
1742
1787
  });
1788
+ router.get('/relation', queryType.middleware(), async (req, res) => {
1789
+ res.setHeader('Cache-Control', ['no-cache', 'no-store']);
1790
+ const payload = proto.connect(req);
1791
+ await response(res, async () => createQuery(payload, req, true).find({ master: payload.isMaster }));
1792
+ });
1743
1793
  router.get('/classes/:name/random', queryType.middleware(), async (req, res) => {
1744
1794
  res.setHeader('Cache-Control', ['no-cache', 'no-store']);
1745
1795
  const { name } = req.params;
@@ -1752,6 +1802,14 @@ var classesRoute = (router, proto) => {
1752
1802
  throw Error('Invalid operation');
1753
1803
  await response(res, async () => createQuery(payload, req, true).random({ weight }, { master: payload.isMaster }));
1754
1804
  });
1805
+ router.get('/relation/random', queryType.middleware(), async (req, res) => {
1806
+ res.setHeader('Cache-Control', ['no-cache', 'no-store']);
1807
+ const payload = proto.connect(req);
1808
+ const { weight } = req.query;
1809
+ if (_.isEmpty(weight) || !_.isString(weight))
1810
+ throw Error('Invalid operation');
1811
+ await response(res, async () => createQuery(payload, req, true).random({ weight }, { master: payload.isMaster }));
1812
+ });
1755
1813
  router.get('/classes/:name/nonrefs', queryType.middleware(), async (req, res) => {
1756
1814
  res.setHeader('Cache-Control', ['no-cache', 'no-store']);
1757
1815
  const { name } = req.params;
@@ -1761,6 +1819,11 @@ var classesRoute = (router, proto) => {
1761
1819
  const payload = proto.connect(req);
1762
1820
  await response(res, async () => createQuery(payload, req, true).nonrefs({ master: payload.isMaster }));
1763
1821
  });
1822
+ router.get('/relation/nonrefs', queryType.middleware(), async (req, res) => {
1823
+ res.setHeader('Cache-Control', ['no-cache', 'no-store']);
1824
+ const payload = proto.connect(req);
1825
+ await response(res, async () => createQuery(payload, req, true).nonrefs({ master: payload.isMaster }));
1826
+ });
1764
1827
  router.get('/classes/:name/:id', async (req, res) => {
1765
1828
  res.setHeader('Cache-Control', ['no-cache', 'no-store']);
1766
1829
  const { name, id } = req.params;
@@ -1801,6 +1864,13 @@ var classesRoute = (router, proto) => {
1801
1864
  const payload = proto.connect(req);
1802
1865
  await response(res, () => createQuery(payload, req, false).deleteMany({ master: payload.isMaster }));
1803
1866
  });
1867
+ router.delete('/relation', Server.text({ type: '*/*' }), async (req, res) => {
1868
+ res.setHeader('Cache-Control', ['no-cache', 'no-store']);
1869
+ if (!_.isEmpty(req.body))
1870
+ return res.sendStatus(400);
1871
+ const payload = proto.connect(req);
1872
+ await response(res, () => createQuery(payload, req, false).deleteMany({ master: payload.isMaster }));
1873
+ });
1804
1874
  router.delete('/classes/:name/:id', Server.text({ type: '*/*' }), async (req, res) => {
1805
1875
  res.setHeader('Cache-Control', ['no-cache', 'no-store']);
1806
1876
  if (!_.isEmpty(req.body))