proto.io 0.0.153 → 0.0.155

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 (38) hide show
  1. package/dist/adapters/file/database.d.ts +2 -2
  2. package/dist/adapters/file/filesystem.d.ts +2 -2
  3. package/dist/adapters/file/google-cloud-storage.d.ts +2 -2
  4. package/dist/adapters/storage/progres.d.ts +11 -7
  5. package/dist/adapters/storage/progres.js +55 -14
  6. package/dist/adapters/storage/progres.js.map +1 -1
  7. package/dist/adapters/storage/progres.mjs +55 -14
  8. package/dist/adapters/storage/progres.mjs.map +1 -1
  9. package/dist/client.d.ts +3 -3
  10. package/dist/client.js +1 -1
  11. package/dist/client.mjs +2 -2
  12. package/dist/index.d.ts +3 -3
  13. package/dist/index.js +64 -31
  14. package/dist/index.js.map +1 -1
  15. package/dist/index.mjs +65 -32
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/internals/{index-c-CaNuVY.mjs → index-B01TqoO1.mjs} +19 -4
  18. package/dist/internals/index-B01TqoO1.mjs.map +1 -0
  19. package/dist/internals/{index-m4WmZoWj.d.ts → index-BLVOKfv3.d.ts} +17 -6
  20. package/dist/internals/index-BLVOKfv3.d.ts.map +1 -0
  21. package/dist/internals/{index-D1YGwuNK.js → index-Bs06MNCK.js} +19 -4
  22. package/dist/internals/index-Bs06MNCK.js.map +1 -0
  23. package/dist/internals/{index-DeD3CiUK.d.ts → index-DSU589g6.d.ts} +2 -2
  24. package/dist/internals/index-DSU589g6.d.ts.map +1 -0
  25. package/dist/internals/{index-DQm5Xz3Q.d.ts → index-DmcvF1dx.d.ts} +3 -2
  26. package/dist/internals/index-DmcvF1dx.d.ts.map +1 -0
  27. package/dist/internals/{random-KZTFMK9-.mjs → random-DXre8Q46.mjs} +11 -1
  28. package/dist/internals/random-DXre8Q46.mjs.map +1 -0
  29. package/dist/internals/{random-DBDmz54D.js → random-DfnhGdY1.js} +11 -1
  30. package/dist/internals/random-DfnhGdY1.js.map +1 -0
  31. package/package.json +1 -1
  32. package/dist/internals/index-D1YGwuNK.js.map +0 -1
  33. package/dist/internals/index-DQm5Xz3Q.d.ts.map +0 -1
  34. package/dist/internals/index-DeD3CiUK.d.ts.map +0 -1
  35. package/dist/internals/index-c-CaNuVY.mjs.map +0 -1
  36. package/dist/internals/index-m4WmZoWj.d.ts.map +0 -1
  37. package/dist/internals/random-DBDmz54D.js.map +0 -1
  38. package/dist/internals/random-KZTFMK9-.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, g as generateId } from './internals/random-KZTFMK9-.mjs';
3
+ import { Q as QueryValidator, g as generateId } from './internals/random-DXre8Q46.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-c-CaNuVY.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-c-CaNuVY.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-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
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';
9
9
  import jwt from 'jsonwebtoken';
10
10
  import { Blob } from 'node:buffer';
@@ -292,22 +292,25 @@ const proxy = (x) => {
292
292
  //
293
293
  class ProtoQuery extends TQuery {
294
294
  _proto;
295
- constructor(className, proto) {
295
+ _opts;
296
+ constructor(className, proto, opts) {
296
297
  super(className);
297
298
  this._proto = proto;
299
+ this._opts = opts;
298
300
  }
299
301
  get _queryOptions() {
300
302
  return {
301
303
  className: this.className,
304
+ relatedBy: this._opts.relatedBy,
302
305
  ...this[PVK].options,
303
306
  };
304
307
  }
305
308
  _dispatcher(options) {
306
- if (this instanceof InsecureProtoQuery) {
309
+ if (this._opts.insecure) {
307
310
  if (options?.master !== true)
308
311
  throw Error('No permission');
309
312
  }
310
- return dispatcher(options?.session ?? this._proto, options ?? {}, this instanceof InsecureProtoQuery);
313
+ return dispatcher(options?.session ?? this._proto, options ?? {}, !!this._opts.insecure);
311
314
  }
312
315
  explain(options) {
313
316
  return this._dispatcher(options).explain(this._queryOptions);
@@ -316,7 +319,7 @@ class ProtoQuery extends TQuery {
316
319
  return this._dispatcher(options).count(this._queryOptions);
317
320
  }
318
321
  clone(options) {
319
- const clone = new ProtoQuery(this.className, this._proto);
322
+ const clone = new ProtoQuery(this.className, this._proto, this._opts);
320
323
  clone[PVK].options = options ?? { ...this[PVK].options };
321
324
  return clone;
322
325
  }
@@ -509,13 +512,6 @@ class ProtoQuery extends TQuery {
509
512
  return this._dispatcher(options).deleteMany(this._queryOptions);
510
513
  }
511
514
  }
512
- class InsecureProtoQuery extends ProtoQuery {
513
- clone(options) {
514
- const clone = new InsecureProtoQuery(this.className, this._proto);
515
- clone[PVK].options = options ?? { ...this[PVK].options };
516
- return clone;
517
- }
518
- }
519
515
 
520
516
  //
521
517
  // defaults.ts
@@ -1106,7 +1102,12 @@ const _sessionWithToken = (proto, token) => {
1106
1102
  const payload = proto[PVK].jwtVarify(token, 'login');
1107
1103
  if (!_.isObject(payload))
1108
1104
  return;
1109
- return payload;
1105
+ return {
1106
+ ...payload,
1107
+ sessionId: payload.sessionId ?? randomUUID(),
1108
+ createdAt: payload.createdAt && _.isSafeInteger(payload.createdAt) ? new Date(payload.createdAt) : new Date,
1109
+ loginedAt: payload.loginedAt && _.isSafeInteger(payload.loginedAt) ? new Date(payload.loginedAt) : new Date,
1110
+ };
1110
1111
  };
1111
1112
  const _session = (proto, request) => {
1112
1113
  const cached = sessionMap.get(request);
@@ -1115,6 +1116,7 @@ const _session = (proto, request) => {
1115
1116
  sessionMap.set(request, {
1116
1117
  sessionId: randomUUID(),
1117
1118
  createdAt: new Date,
1119
+ loginedAt: new Date,
1118
1120
  });
1119
1121
  const jwtToken = proto[PVK].options.jwtToken;
1120
1122
  if (_.isEmpty(jwtToken))
@@ -1130,14 +1132,9 @@ const _session = (proto, request) => {
1130
1132
  }
1131
1133
  if (_.isEmpty(authorization))
1132
1134
  return;
1133
- const payload = proto[PVK].jwtVarify(authorization, 'login');
1134
- if (!_.isObject(payload))
1135
+ const session = _sessionWithToken(proto, authorization);
1136
+ if (!_.isObject(session))
1135
1137
  return;
1136
- const session = {
1137
- ...payload,
1138
- sessionId: payload.sessionId ?? randomUUID(),
1139
- createdAt: payload.createdAt && _.isSafeInteger(payload.createdAt) ? new Date(payload.createdAt) : new Date,
1140
- };
1141
1138
  sessionMap.set(request, session);
1142
1139
  return session;
1143
1140
  };
@@ -1156,18 +1153,29 @@ const fetchSessionInfo = async (proto, userId) => {
1156
1153
  };
1157
1154
  const sessionWithToken = async (proto, token) => {
1158
1155
  const session = _sessionWithToken(proto, token);
1159
- const sessionId = session?.sessionId;
1160
1156
  const info = await fetchSessionInfo(proto, session?.user);
1161
- return { sessionId, ...info };
1157
+ return {
1158
+ ...session ?? {},
1159
+ ...info,
1160
+ loginedAt: info?.user ? session?.loginedAt : undefined,
1161
+ };
1162
1162
  };
1163
1163
  const session = async (proto, request) => {
1164
1164
  const session = _session(proto, request);
1165
1165
  const cached = sessionInfoMap.get(request);
1166
1166
  if (cached)
1167
- return { ...session ?? {}, ...cached };
1167
+ return {
1168
+ ...session ?? {},
1169
+ ...cached,
1170
+ loginedAt: cached?.user ? session?.loginedAt : undefined,
1171
+ };
1168
1172
  const info = await fetchSessionInfo(proto, session?.user);
1169
1173
  sessionInfoMap.set(request, info);
1170
- return { ...session ?? {}, ...info };
1174
+ return {
1175
+ ...session ?? {},
1176
+ ...info,
1177
+ loginedAt: info?.user ? session?.loginedAt : undefined,
1178
+ };
1171
1179
  };
1172
1180
  const sessionIsMaster = (proto, request) => {
1173
1181
  const user = request.header(MASTER_USER_HEADER_NAME);
@@ -1184,6 +1192,7 @@ const signUser = async (proto, res, user, options) => {
1184
1192
  const token = proto[PVK].jwtSign({
1185
1193
  sessionId: session?.sessionId ?? randomUUID(),
1186
1194
  createdAt: session?.createdAt?.getTime() ?? Date.now(),
1195
+ loginedAt: user ? session?.loginedAt?.getTime() ?? Date.now() : undefined,
1187
1196
  user: user?.objectId,
1188
1197
  cookieOptions,
1189
1198
  }, options?.jwtSignOptions ?? 'login');
@@ -1332,10 +1341,22 @@ class ProtoService extends ProtoType {
1332
1341
  return _.keys(this[PVK].options.schema);
1333
1342
  }
1334
1343
  Query(className) {
1335
- return new ProtoQuery(className, this);
1344
+ return new ProtoQuery(className, this, {});
1345
+ }
1346
+ Relation(className, object, key) {
1347
+ const objectId = object.objectId;
1348
+ if (!objectId)
1349
+ throw Error('Invalid object');
1350
+ return new ProtoQuery(className, this, {
1351
+ relatedBy: {
1352
+ className: object.className,
1353
+ objectId,
1354
+ key,
1355
+ },
1356
+ });
1336
1357
  }
1337
1358
  InsecureQuery(className) {
1338
- return new InsecureProtoQuery(className, this);
1359
+ return new ProtoQuery(className, this, { insecure: true });
1339
1360
  }
1340
1361
  get sessionId() {
1341
1362
  if (this.session)
@@ -1600,6 +1621,16 @@ const decodeFormStream = (req, onFile) => {
1600
1621
  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1601
1622
  // THE SOFTWARE.
1602
1623
  //
1624
+ const verifyRelatedBy = (relatedBy) => {
1625
+ if (!_.isPlainObject(relatedBy))
1626
+ return;
1627
+ if (!_.isString(relatedBy.className) || _.isEmpty(relatedBy.className))
1628
+ throw Error('Invalid option');
1629
+ if (!_.isString(relatedBy.objectId) || _.isEmpty(relatedBy.objectId))
1630
+ throw Error('Invalid option');
1631
+ if (!_.isString(relatedBy.key) || _.isEmpty(relatedBy.key))
1632
+ throw Error('Invalid option');
1633
+ };
1603
1634
  var classesRoute = (router, proto) => {
1604
1635
  router.post('/classes/:name', Server.text({ type: '*/*' }), async (req, res) => {
1605
1636
  res.setHeader('Cache-Control', ['no-cache', 'no-store']);
@@ -1608,9 +1639,10 @@ var classesRoute = (router, proto) => {
1608
1639
  if (!_.includes(classes, name))
1609
1640
  return res.sendStatus(404);
1610
1641
  await response(res, async () => {
1611
- const { operation, context, silent, random, attributes, update, setOnInsert, ...options } = deserialize(req.body);
1642
+ const { operation, context, silent, random, attributes, update, setOnInsert, relatedBy, ...options } = deserialize(req.body);
1643
+ verifyRelatedBy(relatedBy);
1612
1644
  const payload = proto.connect(req);
1613
- const query = payload.Query(name);
1645
+ const query = relatedBy ? payload.Relation(name, payload.Object(relatedBy.className, relatedBy.objectId), relatedBy.key) : payload.Query(name);
1614
1646
  query[PVK].options = options;
1615
1647
  const opts = { master: payload.isMaster, context, silent };
1616
1648
  switch (operation) {
@@ -1655,8 +1687,9 @@ var classesRoute = (router, proto) => {
1655
1687
  });
1656
1688
  const createQuery = (payload, req, checkLimit) => {
1657
1689
  const { name } = req.params;
1658
- const query = payload.Query(name);
1659
- const { filter, sort, includes, skip, limit, } = req.query;
1690
+ const { filter, sort, includes, skip, limit, relatedBy, } = req.query;
1691
+ verifyRelatedBy(relatedBy);
1692
+ const query = relatedBy ? payload.Relation(name, payload.Object(relatedBy.className, relatedBy.objectId), relatedBy.key) : payload.Query(name);
1660
1693
  query[PVK].options.filter = !_.isEmpty(filter) && _.isString(filter) ? _.castArray(deserialize(filter)) : [];
1661
1694
  query[PVK].options.sort = _.isPlainObject(sort) && _.every(_.values(sort), _.isNumber) ? sort : undefined;
1662
1695
  query[PVK].options.includes = _.isArray(includes) && _.every(includes, _.isString) ? includes : undefined;