proto.io 0.0.222 → 0.0.223

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 (34) 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/filesystem.d.ts +3 -3
  4. package/dist/adapters/file/google-cloud-storage.d.ts +3 -3
  5. package/dist/adapters/storage/progres.d.ts +1 -1
  6. package/dist/client.d.ts +3 -3
  7. package/dist/client.js +1 -1
  8. package/dist/client.mjs +2 -2
  9. package/dist/index.d.ts +3 -3
  10. package/dist/index.js +126 -87
  11. package/dist/index.js.map +1 -1
  12. package/dist/index.mjs +127 -88
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/internals/{base-C1uAg1dD.d.ts → base-D7eiLTdl.d.ts} +2 -2
  15. package/dist/internals/base-D7eiLTdl.d.ts.map +1 -0
  16. package/dist/internals/{chunk-CpgqvFNO.d.ts → chunk-B95QS-B7.d.ts} +3 -3
  17. package/dist/internals/chunk-B95QS-B7.d.ts.map +1 -0
  18. package/dist/internals/{index-82GLvDiN.d.ts → index-B9kyejqo.d.ts} +38 -27
  19. package/dist/internals/index-B9kyejqo.d.ts.map +1 -0
  20. package/dist/internals/{index-CsclRNTO.mjs → index-BozJOOCD.mjs} +49 -1
  21. package/dist/internals/index-BozJOOCD.mjs.map +1 -0
  22. package/dist/internals/{index-dk8iIkyr.js → index-C01HL8O6.js} +49 -1
  23. package/dist/internals/index-C01HL8O6.js.map +1 -0
  24. package/dist/internals/index-CLKTEIj0.js.map +1 -1
  25. package/dist/internals/{index-Cc-yXi8f.d.ts → index-DRgs8WkW.d.ts} +2 -2
  26. package/dist/internals/index-DRgs8WkW.d.ts.map +1 -0
  27. package/dist/internals/index-gWcE22mf.mjs.map +1 -1
  28. package/package.json +1 -1
  29. package/dist/internals/base-C1uAg1dD.d.ts.map +0 -1
  30. package/dist/internals/chunk-CpgqvFNO.d.ts.map +0 -1
  31. package/dist/internals/index-82GLvDiN.d.ts.map +0 -1
  32. package/dist/internals/index-Cc-yXi8f.d.ts.map +0 -1
  33. package/dist/internals/index-CsclRNTO.mjs.map +0 -1
  34. package/dist/internals/index-dk8iIkyr.js.map +0 -1
package/dist/index.mjs CHANGED
@@ -3,8 +3,8 @@ import { Server } from '@o2ter/server-js';
3
3
  import { Q as QueryValidator, a as QueryExpression, r as resolveColumn, b as resolveDataType, c as QuerySelector } from './internals/validator-DX2nXeQo.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 { L as LiveQuerySubscription, T as TQuery, d as deserialize, s as serialize, a as TUser, P as ProtoType, _ as _logLevels } from './internals/index-CsclRNTO.mjs';
7
- export { b as ProtoClient, c as classExtends } from './internals/index-CsclRNTO.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-BozJOOCD.mjs';
7
+ export { b as ProtoClient, c as classExtends } from './internals/index-BozJOOCD.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-gWcE22mf.mjs';
9
9
  import jwt from 'jsonwebtoken';
10
10
  import { Blob } from 'node:buffer';
@@ -470,6 +470,30 @@ class ProtoRelationQuery extends _ProtoQuery {
470
470
  // THE SOFTWARE.
471
471
  //
472
472
  const defaultSchema = {
473
+ '_Session': {
474
+ fields: {
475
+ token: 'string',
476
+ user: { type: 'pointer', target: 'User' },
477
+ loginedAt: 'date',
478
+ },
479
+ classLevelPermissions: {
480
+ find: [],
481
+ count: [],
482
+ create: [],
483
+ update: [],
484
+ delete: [],
485
+ },
486
+ fieldLevelPermissions: {
487
+ token: { update: [] },
488
+ _expired_at: { create: [], update: [] },
489
+ },
490
+ indexes: [
491
+ {
492
+ keys: { token: 1 },
493
+ unique: true,
494
+ },
495
+ ],
496
+ },
473
497
  'User': {
474
498
  fields: {
475
499
  password: 'object',
@@ -1278,98 +1302,102 @@ class JobRunner {
1278
1302
  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1279
1303
  // THE SOFTWARE.
1280
1304
  //
1281
- const sessionMap = new WeakMap();
1282
- const _sessionWithToken = (proto, token) => {
1305
+ const _sessionWithToken = async (proto, token) => {
1283
1306
  if (_.isEmpty(token))
1284
1307
  return;
1285
- const payload = proto[PVK].jwtVarify(token, 'login');
1286
- if (!_.isObject(payload))
1308
+ const payload = proto[PVK].jwtVarify(token, 'login') ?? {};
1309
+ if (!_.isString(payload.sessionId) || _.isEmpty(payload.sessionId))
1310
+ return;
1311
+ const session = await proto.Query('_Session')
1312
+ .equalTo('token', payload.sessionId)
1313
+ .includes('user')
1314
+ .first({ master: true });
1315
+ if (!session)
1287
1316
  return;
1317
+ return { payload, session };
1318
+ };
1319
+ const userCacheMap = new WeakMap();
1320
+ const fetchUserRole = async (proto, user) => {
1321
+ if (!userCacheMap.has(proto[PVK]))
1322
+ userCacheMap.set(proto[PVK], {});
1323
+ const cache = userCacheMap.get(proto[PVK]);
1324
+ if (_.isNil(user?.id))
1325
+ return {};
1326
+ if (_.isNil(cache[user.id]))
1327
+ cache[user.id] = (async () => {
1328
+ const _roles = user instanceof TUser ? _.filter(await proto.userRoles(user), x => !_.isEmpty(x.name)) : [];
1329
+ cache[user.id] = undefined;
1330
+ return _roles;
1331
+ })();
1332
+ const _roles = await cache[user.id];
1288
1333
  return {
1289
- ...payload,
1290
- sessionId: payload.sessionId ?? randomUUID(),
1291
- createdAt: payload.createdAt && _.isSafeInteger(payload.createdAt) ? new Date(payload.createdAt) : new Date,
1292
- loginedAt: payload.loginedAt && _.isSafeInteger(payload.loginedAt) ? new Date(payload.loginedAt) : new Date,
1334
+ user: user?.clone(),
1335
+ _roles: _.map(_roles, x => x.clone()),
1293
1336
  };
1294
1337
  };
1295
- const _session = (proto, request) => {
1338
+ const sessionMap = new WeakMap();
1339
+ const _session = async (proto, request) => {
1296
1340
  const cached = sessionMap.get(request);
1297
1341
  if (cached)
1298
- return cached;
1299
- sessionMap.set(request, {
1300
- sessionId: randomUUID(),
1301
- createdAt: new Date,
1302
- loginedAt: new Date,
1303
- });
1304
- const jwtToken = proto[PVK].options.jwtToken;
1305
- if (_.isEmpty(jwtToken))
1306
- throw Error('Invalid jwt token');
1342
+ return {
1343
+ sessionId: cached.session.sessionId,
1344
+ createdAt: cached.session.createdAt,
1345
+ updatedAt: cached.session.updatedAt,
1346
+ loginedAt: cached.session.loginedAt,
1347
+ user: cached.session.user,
1348
+ cookieOptions: cached.payload.cookieOptions,
1349
+ };
1307
1350
  const cookieKey = _.last(_.castArray(request.headers[AUTH_ALT_COOKIE_KEY] || [])) || AUTH_COOKIE_KEY;
1308
- let authorization = '';
1351
+ let sessionId = '';
1309
1352
  if (request.headers.authorization) {
1310
1353
  const parts = request.headers.authorization.split(' ');
1311
1354
  if (parts.length === 2 && parts[0] === 'Bearer')
1312
- authorization = parts[1];
1355
+ sessionId = parts[1];
1313
1356
  }
1314
1357
  else if (request.cookies[cookieKey]) {
1315
- authorization = request.cookies[cookieKey];
1358
+ sessionId = request.cookies[cookieKey];
1316
1359
  }
1317
- if (_.isEmpty(authorization))
1360
+ const { payload, session } = await _sessionWithToken(proto, sessionId) ?? {};
1361
+ if (!session)
1318
1362
  return;
1319
- const session = _sessionWithToken(proto, authorization);
1320
- if (!_.isObject(session))
1321
- return;
1322
- sessionMap.set(request, session);
1323
- return session;
1324
- };
1325
- const sessionId = (proto, request) => {
1326
- const session = _session(proto, request);
1327
- return sessionMap.get(request)?.sessionId ?? session?.sessionId;
1328
- };
1329
- const userCacheMap = new WeakMap;
1330
- const fetchSessionInfo = async (proto, userId = '') => {
1331
- if (!userCacheMap.has(proto[PVK]))
1332
- userCacheMap.set(proto[PVK], {});
1333
- const cache = userCacheMap.get(proto[PVK]);
1334
- if (_.isNil(cache[userId]))
1335
- cache[userId] = (async () => {
1336
- const _user = userId ? await proto.Query('User').get(userId, { master: true }) : undefined;
1337
- const user = proto.req ? await proto[PVK].options.userResolver(proto, _user) : _user;
1338
- const _roles = user instanceof TUser ? _.filter(await proto.userRoles(user), x => !_.isEmpty(x.name)) : [];
1339
- cache[userId] = undefined;
1340
- return { user, _roles };
1341
- })();
1342
- const { user, _roles } = await cache[userId];
1343
- return {
1344
- user: user?.clone(),
1345
- _roles: _.map(_roles, x => x.clone()),
1346
- };
1347
- };
1348
- const sessionWithToken = async (proto, token) => {
1349
- const session = _sessionWithToken(proto, token);
1350
- const info = await fetchSessionInfo(proto, session?.user);
1363
+ sessionMap.set(request, { payload, session });
1351
1364
  return {
1352
- ...session ?? {},
1353
- ...info,
1354
- loginedAt: info?.user ? session?.loginedAt : undefined,
1365
+ sessionId: session.sessionId,
1366
+ createdAt: session.createdAt,
1367
+ updatedAt: session.updatedAt,
1368
+ loginedAt: session.loginedAt,
1369
+ user: session.user,
1370
+ cookieOptions: payload.cookieOptions,
1355
1371
  };
1356
1372
  };
1357
- const sessionInfoMap = new WeakMap();
1373
+ const userRoleMap = new WeakMap();
1358
1374
  const session = async (proto, request) => {
1359
- const session = _session(proto, request);
1360
- const cached = sessionInfoMap.get(request);
1375
+ const session = await _session(proto, request);
1376
+ const cached = userRoleMap.get(request);
1361
1377
  if (cached)
1362
1378
  return {
1363
1379
  ...session ?? {},
1364
1380
  ...cached,
1365
- loginedAt: cached?.user ? session?.loginedAt : undefined,
1366
1381
  };
1367
- const info = await fetchSessionInfo(proto, session?.user);
1368
- sessionInfoMap.set(request, info);
1382
+ const info = await fetchUserRole(proto, session?.user);
1383
+ userRoleMap.set(request, info);
1369
1384
  return {
1370
1385
  ...session ?? {},
1371
1386
  ...info,
1372
- loginedAt: info?.user ? session?.loginedAt : undefined,
1387
+ };
1388
+ };
1389
+ const sessionWithToken = async (proto, token) => {
1390
+ const { payload, session } = await _sessionWithToken(proto, token) ?? {};
1391
+ if (!session)
1392
+ return;
1393
+ const info = await fetchUserRole(proto, session?.user);
1394
+ return {
1395
+ sessionId: session.sessionId,
1396
+ createdAt: session.createdAt,
1397
+ updatedAt: session.updatedAt,
1398
+ loginedAt: session.loginedAt,
1399
+ cookieOptions: payload.cookieOptions,
1400
+ ...info,
1373
1401
  };
1374
1402
  };
1375
1403
  const sessionIsMaster = (proto, request) => {
@@ -1382,18 +1410,30 @@ const sessionIsMaster = (proto, request) => {
1382
1410
  const signUser = async (proto, res, user, options) => {
1383
1411
  if (_.isNil(proto[PVK].options.jwtToken))
1384
1412
  return;
1385
- const session = _session(proto, res.req);
1413
+ const session = await _session(proto, res.req);
1386
1414
  const cookieOptions = options?.cookieOptions ?? session?.cookieOptions ?? proto[PVK].options.cookieOptions;
1415
+ const sessionId = session?.sessionId ?? randomUUID();
1416
+ const expiredAt = cookieOptions?.expires ?? (cookieOptions?.maxAge ? new Date(Date.now() + cookieOptions.maxAge) : undefined);
1417
+ const loginedAt = user ? session?.loginedAt ?? new Date() : undefined;
1418
+ await proto.Query('_Session')
1419
+ .equalTo('token', sessionId)
1420
+ .upsertOne({
1421
+ loginedAt: { $set: loginedAt },
1422
+ user: { $set: user },
1423
+ _expired_at: { $set: expiredAt },
1424
+ }, {
1425
+ token: sessionId,
1426
+ loginedAt: loginedAt,
1427
+ user,
1428
+ _expired_at: expiredAt,
1429
+ }, { master: true });
1387
1430
  const token = proto[PVK].jwtSign({
1388
- sessionId: session?.sessionId ?? randomUUID(),
1389
- createdAt: session?.createdAt?.getTime() ?? Date.now(),
1390
- loginedAt: user ? session?.loginedAt?.getTime() ?? Date.now() : undefined,
1391
- user: user?.id,
1431
+ sessionId,
1392
1432
  cookieOptions,
1393
1433
  }, options?.jwtSignOptions ?? 'login');
1394
1434
  const cookieKey = _.last(_.castArray(res.req.headers[AUTH_ALT_COOKIE_KEY] || [])) || AUTH_COOKIE_KEY;
1395
1435
  res.cookie(cookieKey, token, cookieOptions);
1396
- sessionInfoMap.set(res.req, user ? await fetchSessionInfo(proto, user.id) : {});
1436
+ userRoleMap.set(res.req, user ? await fetchUserRole(proto, user) : {});
1397
1437
  };
1398
1438
 
1399
1439
  //
@@ -1488,7 +1528,6 @@ class ProtoService extends ProtoType {
1488
1528
  constructor(options) {
1489
1529
  super();
1490
1530
  this[PVK] = new ProtoInternal({
1491
- userResolver: (_req, user) => user,
1492
1531
  roleResolver: {},
1493
1532
  objectIdSize: 10,
1494
1533
  maxFetchLimit: 1000,
@@ -1555,11 +1594,6 @@ class ProtoService extends ProtoType {
1555
1594
  InsecureQuery(className) {
1556
1595
  return new ProtoQuery(className, this, { insecure: true });
1557
1596
  }
1558
- get sessionId() {
1559
- if (this.session)
1560
- return this.session.sessionId;
1561
- return this.req ? sessionId(this, this.req) : undefined;
1562
- }
1563
1597
  async sessionInfo() {
1564
1598
  if (this.session)
1565
1599
  return this.session;
@@ -1589,8 +1623,14 @@ class ProtoService extends ProtoType {
1589
1623
  }
1590
1624
  async connectWithSessionToken(token, attrs) {
1591
1625
  const session = _.isString(token) ? await sessionWithToken(this, token) : undefined;
1592
- const payload = _.create(this, { session });
1593
- return _.assign(payload, _.isFunction(attrs) ? attrs(payload) : attrs);
1626
+ if (Object.getPrototypeOf(this) instanceof ProtoService) {
1627
+ this.session = session;
1628
+ return _.assign(this, _.isFunction(attrs) ? attrs(this) : attrs);
1629
+ }
1630
+ else {
1631
+ const payload = _.create(this, { session });
1632
+ return _.assign(payload, _.isFunction(attrs) ? attrs(payload) : attrs);
1633
+ }
1594
1634
  }
1595
1635
  async userRoles(user) {
1596
1636
  const self = this;
@@ -2592,15 +2632,14 @@ const registerProtoSocket = (proto, server, endpoint) => {
2592
2632
  io.on('connection', async (socket) => {
2593
2633
  let events = {};
2594
2634
  let queries = {};
2595
- const connect = async (token) => {
2596
- const payload = await proto.connectWithSessionToken(token);
2597
- const { remove: remove_basic } = payload.listen(data => {
2635
+ const connect = (proto) => {
2636
+ const { remove: remove_basic } = proto.listen(data => {
2598
2637
  const ids = _.keys(_.pickBy(events, v => v instanceof QuerySelector ? v.eval(data) : v));
2599
2638
  const payload = JSON.parse(serialize(data));
2600
2639
  if (!_.isEmpty(ids))
2601
2640
  socket.emit('ON_EV_NOTIFY', { ids, data: payload });
2602
2641
  });
2603
- const { remove: remove_livequery } = payload[PVK]._liveQuery(payload, (ev, objs) => {
2642
+ const { remove: remove_livequery } = proto[PVK]._liveQuery(proto, (ev, objs) => {
2604
2643
  const ids = {};
2605
2644
  for (const obj of objs) {
2606
2645
  ids[obj.id] = _.keys(_.pickBy(queries, v => {
@@ -2620,13 +2659,13 @@ const registerProtoSocket = (proto, server, endpoint) => {
2620
2659
  };
2621
2660
  };
2622
2661
  const { token } = socket.handshake.auth;
2623
- let remove = connect(token);
2662
+ const service = await proto.connectWithSessionToken(token);
2663
+ const remove = connect(service);
2624
2664
  socket.on('auth', (token) => {
2625
- remove.then(rm => rm());
2626
- remove = connect(token);
2665
+ service.connectWithSessionToken(token);
2627
2666
  });
2628
2667
  socket.on('disconnect', () => {
2629
- remove.then(rm => rm());
2668
+ remove();
2630
2669
  });
2631
2670
  socket.on('EV_NOTIFY', (payload) => {
2632
2671
  events = _.mapValues(payload, v => {