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.
Files changed (53) hide show
  1. package/dist/adapters/file/database.d.ts +2 -2
  2. package/dist/adapters/file/database.js.map +1 -1
  3. package/dist/adapters/file/database.mjs +2 -2
  4. package/dist/adapters/file/database.mjs.map +1 -1
  5. package/dist/adapters/file/filesystem.d.ts +2 -2
  6. package/dist/adapters/file/filesystem.js.map +1 -1
  7. package/dist/adapters/file/filesystem.mjs.map +1 -1
  8. package/dist/adapters/file/google-cloud-storage.d.ts +2 -2
  9. package/dist/adapters/file/google-cloud-storage.js.map +1 -1
  10. package/dist/adapters/file/google-cloud-storage.mjs.map +1 -1
  11. package/dist/adapters/storage/progres.d.ts +16 -13
  12. package/dist/adapters/storage/progres.js +136 -81
  13. package/dist/adapters/storage/progres.js.map +1 -1
  14. package/dist/adapters/storage/progres.mjs +138 -83
  15. package/dist/adapters/storage/progres.mjs.map +1 -1
  16. package/dist/client.d.ts +3 -3
  17. package/dist/client.js +1 -1
  18. package/dist/client.mjs +3 -3
  19. package/dist/index.d.ts +7 -12
  20. package/dist/index.js +84 -47
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.mjs +87 -50
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/internals/{index-Dz3jvqxZ.js → index-B-pq8xkP.js} +5 -21
  25. package/dist/internals/index-B-pq8xkP.js.map +1 -0
  26. package/dist/internals/{index-BsuUdR0W.d.ts → index-BQggoDNX.d.ts} +2 -2
  27. package/dist/internals/index-BQggoDNX.d.ts.map +1 -0
  28. package/dist/internals/{index-ByfpVHca.mjs → index-BYbMU-Ao.mjs} +2 -2
  29. package/dist/internals/{index-ByfpVHca.mjs.map → index-BYbMU-Ao.mjs.map} +1 -1
  30. package/dist/internals/{index-S5Bq-KsU.mjs → index-BejQNqvC.mjs} +2 -2
  31. package/dist/internals/{index-S5Bq-KsU.mjs.map → index-BejQNqvC.mjs.map} +1 -1
  32. package/dist/internals/index-BqFdBhFc.js.map +1 -1
  33. package/dist/internals/index-CSNRyhjB.js.map +1 -1
  34. package/dist/internals/{index-BoP4kl2R.mjs → index-CUJMde7V.mjs} +6 -22
  35. package/dist/internals/index-CUJMde7V.mjs.map +1 -0
  36. package/dist/internals/index-CVutVPmd.js.map +1 -1
  37. package/dist/internals/index-be1VYBY2.mjs.map +1 -1
  38. package/dist/internals/{index-BeV63sFw.d.ts → index-rkqvel7o.d.ts} +2 -2
  39. package/dist/internals/index-rkqvel7o.d.ts.map +1 -0
  40. package/dist/internals/{index-YdOGTHp1.d.ts → index-y8EePsDY.d.ts} +10 -6
  41. package/dist/internals/index-y8EePsDY.d.ts.map +1 -0
  42. package/dist/internals/{random-w8WDYQEe.mjs → random-DrURPPxr.mjs} +5 -10
  43. package/dist/internals/random-DrURPPxr.mjs.map +1 -0
  44. package/dist/internals/{random-uT4D0y_q.js → random-q0PeamQE.js} +3 -8
  45. package/dist/internals/random-q0PeamQE.js.map +1 -0
  46. package/package.json +20 -20
  47. package/dist/internals/index-BeV63sFw.d.ts.map +0 -1
  48. package/dist/internals/index-BoP4kl2R.mjs.map +0 -1
  49. package/dist/internals/index-BsuUdR0W.d.ts.map +0 -1
  50. package/dist/internals/index-Dz3jvqxZ.js.map +0 -1
  51. package/dist/internals/index-YdOGTHp1.d.ts.map +0 -1
  52. package/dist/internals/random-uT4D0y_q.js.map +0 -1
  53. package/dist/internals/random-w8WDYQEe.mjs.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, r as resolveColumn, g as generateId, a as resolveDataType } from './internals/random-w8WDYQEe.mjs';
3
+ import { Q as QueryValidator, r as resolveColumn, a as resolveDataType, g as generateId } from './internals/random-DrURPPxr.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-BoP4kl2R.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-BoP4kl2R.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';
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-CUJMde7V.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-CUJMde7V.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-BYbMU-Ao.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-S5Bq-KsU.mjs';
15
+ import { Q as QuerySelector } from './internals/index-BejQNqvC.mjs';
16
16
  import queryType from 'query-types';
17
17
  import busboy from 'busboy';
18
18
  export { Decimal } from 'decimal.js';
@@ -780,8 +780,10 @@ const validateShapedObject = (schema, dataType) => {
780
780
  }
781
781
  };
782
782
  const validateSchemaName = (schema) => {
783
- if (!_.isNil(schema['_Schema']) || !_.isNil(schema['_Config']))
784
- throw Error('Reserved name of class');
783
+ for (const name of ['_Schema', '_Config']) {
784
+ if (!_.isNil(schema[name]))
785
+ throw Error('Reserved name of class');
786
+ }
785
787
  for (const [, _schema] of _.toPairs(schema)) {
786
788
  for (const [key] of _.toPairs(_schema.fields)) {
787
789
  if (_.includes(TObject.defaultKeys, key))
@@ -853,6 +855,12 @@ class ProtoInternal {
853
855
  validateSchemaName(options.schema);
854
856
  const schema = mergeSchema(defaultSchema, options.fileStorage.schema, options.schema);
855
857
  validateSchema(schema);
858
+ if (!_.every(options.roleInheritKeys, k => {
859
+ const type = resolveDataType(schema, 'Role', k);
860
+ return type && isRelation(type) && _.includes(['User', 'Role'], type.target);
861
+ })) {
862
+ throw Error(`Invalid role keys`);
863
+ }
856
864
  this.options = {
857
865
  ...options,
858
866
  schema,
@@ -1291,29 +1299,7 @@ const signUser = async (proto, res, user, options) => {
1291
1299
  //
1292
1300
  const scheduleOp = {
1293
1301
  expireDocument: async (proto) => {
1294
- for (const className of proto.classes()) {
1295
- if (className === 'File') {
1296
- const found = proto.storage.find({
1297
- className: 'File',
1298
- filter: QuerySelector.decode({ _expired_at: { $lt: new Date() } }),
1299
- matches: {},
1300
- includes: ['_id', '_expired_at', 'token'],
1301
- objectIdSize: 0
1302
- });
1303
- for await (const item of found) {
1304
- const token = item.get('token');
1305
- if (!_.isEmpty(token))
1306
- await proto.fileStorage.destroy(proto, token);
1307
- }
1308
- }
1309
- await proto.storage.deleteMany({
1310
- className,
1311
- filter: QuerySelector.decode({ _expired_at: { $lt: new Date() } }),
1312
- includes: ['_id', '_expired_at'],
1313
- matches: {},
1314
- objectIdSize: 0
1315
- });
1316
- }
1302
+ await proto.gc();
1317
1303
  }
1318
1304
  };
1319
1305
  const schedule = (proto) => {
@@ -1375,6 +1361,7 @@ class ProtoService extends ProtoType {
1375
1361
  constructor(options) {
1376
1362
  super();
1377
1363
  this[PVK] = new ProtoInternal({
1364
+ roleInheritKeys: [],
1378
1365
  objectIdSize: 10,
1379
1366
  maxFetchLimit: 1000,
1380
1367
  maxUploadSize: 20 * 1024 * 1024,
@@ -1460,6 +1447,32 @@ class ProtoService extends ProtoType {
1460
1447
  const payload = _.create(this, { session });
1461
1448
  return _.assign(payload, _.isFunction(attrs) ? attrs(payload) : attrs);
1462
1449
  }
1450
+ async userRoles(user) {
1451
+ const roleInheritKeys = this[PVK].options.roleInheritKeys;
1452
+ const schema = this.schema;
1453
+ const userKeys = _.filter(roleInheritKeys, k => {
1454
+ const type = resolveDataType(schema, 'Role', k);
1455
+ return !!type && isRelation(type) && type.target === 'User';
1456
+ });
1457
+ const roleKeys = _.filter(roleInheritKeys, k => {
1458
+ const type = resolveDataType(schema, 'Role', k);
1459
+ return !!type && isRelation(type) && type.target === 'Role';
1460
+ });
1461
+ let queue = await this.Query('Role')
1462
+ .or(_.map(_.uniq(['users', ...userKeys]), k => q => q.isIntersect(k, [user])))
1463
+ .includes('name')
1464
+ .find({ master: true });
1465
+ let roles = queue;
1466
+ while (!_.isEmpty(queue)) {
1467
+ queue = await this.Query('Role')
1468
+ .or(_.map(_.uniq(['roles', ...roleKeys]), k => q => q.isIntersect(k, queue)))
1469
+ .notContainsIn('_id', _.compact(_.map(roles, x => x.objectId)))
1470
+ .includes('name')
1471
+ .find({ master: true });
1472
+ roles = _.uniqBy([...roles, ...queue], x => x.objectId);
1473
+ }
1474
+ return roles;
1475
+ }
1463
1476
  async becomeUser(req, user, options) {
1464
1477
  if (!user.objectId)
1465
1478
  throw Error('Invalid user object');
@@ -1564,6 +1577,31 @@ class ProtoService extends ProtoType {
1564
1577
  yield self.rebind(object);
1565
1578
  });
1566
1579
  }
1580
+ async gc(classNames) {
1581
+ for (const className of _.castArray(classNames ?? this.classes())) {
1582
+ if (className === 'File') {
1583
+ const found = this.storage.find({
1584
+ className: 'File',
1585
+ filter: QuerySelector.decode({ _expired_at: { $lt: new Date() } }),
1586
+ matches: {},
1587
+ includes: ['_id', '_expired_at', 'token'],
1588
+ objectIdSize: 0
1589
+ });
1590
+ for await (const item of found) {
1591
+ const token = item.get('token');
1592
+ if (!_.isEmpty(token))
1593
+ await this.fileStorage.destroy(this, token);
1594
+ }
1595
+ }
1596
+ await this.storage.deleteMany({
1597
+ className,
1598
+ filter: QuerySelector.decode({ _expired_at: { $lt: new Date() } }),
1599
+ includes: ['_id', '_expired_at'],
1600
+ matches: {},
1601
+ objectIdSize: 0
1602
+ });
1603
+ }
1604
+ }
1567
1605
  }
1568
1606
 
1569
1607
  //
@@ -1749,7 +1787,7 @@ var classesRoute = (router, proto) => {
1749
1787
  const { name } = req.params;
1750
1788
  const classes = proto.classes();
1751
1789
  if (!_.includes(classes, name))
1752
- return res.sendStatus(404);
1790
+ return void res.sendStatus(404);
1753
1791
  await response(res, () => defaultHandler(req));
1754
1792
  });
1755
1793
  router.post('/relation', Server.text({ type: '*/*' }), async (req, res) => {
@@ -1781,7 +1819,7 @@ var classesRoute = (router, proto) => {
1781
1819
  const { name } = req.params;
1782
1820
  const classes = proto.classes();
1783
1821
  if (!_.includes(classes, name))
1784
- return res.sendStatus(404);
1822
+ return void res.sendStatus(404);
1785
1823
  const payload = proto.connect(req);
1786
1824
  await response(res, async () => createQuery(payload, req, true).find({ master: payload.isMaster }));
1787
1825
  });
@@ -1795,7 +1833,7 @@ var classesRoute = (router, proto) => {
1795
1833
  const { name } = req.params;
1796
1834
  const classes = proto.classes();
1797
1835
  if (!_.includes(classes, name))
1798
- return res.sendStatus(404);
1836
+ return void res.sendStatus(404);
1799
1837
  const payload = proto.connect(req);
1800
1838
  const { weight } = req.query;
1801
1839
  if (_.isEmpty(weight) || !_.isString(weight))
@@ -1815,7 +1853,7 @@ var classesRoute = (router, proto) => {
1815
1853
  const { name } = req.params;
1816
1854
  const classes = proto.classes();
1817
1855
  if (!_.includes(classes, name))
1818
- return res.sendStatus(404);
1856
+ return void res.sendStatus(404);
1819
1857
  const payload = proto.connect(req);
1820
1858
  await response(res, async () => createQuery(payload, req, true).nonrefs({ master: payload.isMaster }));
1821
1859
  });
@@ -1829,7 +1867,7 @@ var classesRoute = (router, proto) => {
1829
1867
  const { name, id } = req.params;
1830
1868
  const classes = proto.classes();
1831
1869
  if (!_.includes(classes, name))
1832
- return res.sendStatus(404);
1870
+ return void res.sendStatus(404);
1833
1871
  const payload = proto.connect(req);
1834
1872
  await response(res, () => payload.Query(name).get(id, { master: payload.isMaster }));
1835
1873
  });
@@ -1838,7 +1876,7 @@ var classesRoute = (router, proto) => {
1838
1876
  const { name, id } = req.params;
1839
1877
  const classes = proto.classes();
1840
1878
  if (!_.includes(classes, name))
1841
- return res.sendStatus(404);
1879
+ return void res.sendStatus(404);
1842
1880
  const payload = proto.connect(req);
1843
1881
  await response(res, async () => payload.refs(payload.Object(name, id), { master: payload.isMaster }));
1844
1882
  });
@@ -1847,7 +1885,7 @@ var classesRoute = (router, proto) => {
1847
1885
  const { name, id } = req.params;
1848
1886
  const classes = proto.classes();
1849
1887
  if (!_.includes(classes, name))
1850
- return res.sendStatus(404);
1888
+ return void res.sendStatus(404);
1851
1889
  const payload = proto.connect(req);
1852
1890
  const query = payload.Query(name).equalTo('_id', id);
1853
1891
  const update = _.mapValues(deserialize(req.body), v => ({ $set: v }));
@@ -1856,29 +1894,29 @@ var classesRoute = (router, proto) => {
1856
1894
  router.delete('/classes/:name', Server.text({ type: '*/*' }), async (req, res) => {
1857
1895
  res.setHeader('Cache-Control', ['no-cache', 'no-store']);
1858
1896
  if (!_.isEmpty(req.body))
1859
- return res.sendStatus(400);
1897
+ return void res.sendStatus(400);
1860
1898
  const { name } = req.params;
1861
1899
  const classes = proto.classes();
1862
1900
  if (!_.includes(classes, name))
1863
- return res.sendStatus(404);
1901
+ return void res.sendStatus(404);
1864
1902
  const payload = proto.connect(req);
1865
1903
  await response(res, () => createQuery(payload, req, false).deleteMany({ master: payload.isMaster }));
1866
1904
  });
1867
1905
  router.delete('/relation', Server.text({ type: '*/*' }), async (req, res) => {
1868
1906
  res.setHeader('Cache-Control', ['no-cache', 'no-store']);
1869
1907
  if (!_.isEmpty(req.body))
1870
- return res.sendStatus(400);
1908
+ return void res.sendStatus(400);
1871
1909
  const payload = proto.connect(req);
1872
1910
  await response(res, () => createQuery(payload, req, false).deleteMany({ master: payload.isMaster }));
1873
1911
  });
1874
1912
  router.delete('/classes/:name/:id', Server.text({ type: '*/*' }), async (req, res) => {
1875
1913
  res.setHeader('Cache-Control', ['no-cache', 'no-store']);
1876
1914
  if (!_.isEmpty(req.body))
1877
- return res.sendStatus(400);
1915
+ return void res.sendStatus(400);
1878
1916
  const { name, id } = req.params;
1879
1917
  const classes = proto.classes();
1880
1918
  if (!_.includes(classes, name))
1881
- return res.sendStatus(404);
1919
+ return void res.sendStatus(404);
1882
1920
  const payload = proto.connect(req);
1883
1921
  const query = payload.Query(name).equalTo('_id', id);
1884
1922
  await response(res, () => query.deleteOne({ master: payload.isMaster }));
@@ -1915,7 +1953,7 @@ var functionRoute = (router, proto) => {
1915
1953
  res.setHeader('Cache-Control', ['no-cache', 'no-store']);
1916
1954
  const { name } = req.params;
1917
1955
  if (_.isNil(proto[PVK].functions[name]))
1918
- return res.sendStatus(404);
1956
+ return void res.sendStatus(404);
1919
1957
  await response(res, () => {
1920
1958
  const payload = proto.connect(req, x => ({
1921
1959
  params: null,
@@ -1927,7 +1965,7 @@ var functionRoute = (router, proto) => {
1927
1965
  res.setHeader('Cache-Control', ['no-cache', 'no-store']);
1928
1966
  const { name } = req.params;
1929
1967
  if (_.isNil(proto[PVK].functions[name]))
1930
- return res.sendStatus(404);
1968
+ return void res.sendStatus(404);
1931
1969
  await response(res, () => {
1932
1970
  const payload = proto.connect(req, x => ({
1933
1971
  params: x.rebind(deserialize(req.body, { objAttrs: TObject.defaultReadonlyKeys })),
@@ -1989,9 +2027,9 @@ var filesRoute = (router, proto) => {
1989
2027
  const query = payload.Query('File').equalTo('_id', id);
1990
2028
  const file = await query.first({ master: payload.isMaster });
1991
2029
  if (!file || file.filename !== name)
1992
- return res.sendStatus(404);
2030
+ return void res.sendStatus(404);
1993
2031
  if (_.isNil(file.token) || _.isNil(file.size) || _.isNil(file.type))
1994
- return res.sendStatus(404);
2032
+ return void res.sendStatus(404);
1995
2033
  const ranges = req.range(file.size);
1996
2034
  const match = req.headers['if-none-match'];
1997
2035
  if (match === `"${id}"`) {
@@ -2146,7 +2184,7 @@ var schemaRoute = (router, proto) => {
2146
2184
  res.setHeader('Cache-Control', ['no-cache', 'no-store']);
2147
2185
  const { name } = req.params;
2148
2186
  if (_.isNil(proto.schema[name]))
2149
- return res.sendStatus(404);
2187
+ return void res.sendStatus(404);
2150
2188
  const payload = proto.connect(req);
2151
2189
  await response(res, () => {
2152
2190
  if (!payload.isMaster)
@@ -2247,10 +2285,9 @@ const schema = _.assign((x) => x, {
2247
2285
  relation: (target, foreignField) => ({ type: 'relation', target, foreignField }),
2248
2286
  });
2249
2287
  const ProtoRoute = async (options) => {
2250
- const { adapters, proto: _proto, } = options;
2251
- const proto = _proto instanceof ProtoService ? _proto : new ProtoService(_proto);
2288
+ const proto = options.proto instanceof ProtoService ? options.proto : new ProtoService(options.proto);
2252
2289
  await proto[PVK].prepare();
2253
- const router = Server.Router().use(authHandler(proto), ..._.map(adapters, x => ((req, res, next) => x(proto.connect(req), res, next))), (req, res, next) => {
2290
+ const router = Server.Router().use(authHandler(proto), (req, res, next) => {
2254
2291
  const payload = proto.connect(req);
2255
2292
  if (!payload.isInvalidMasterToken)
2256
2293
  return next();