proto.io 0.0.224 → 0.0.226
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.
- package/dist/adapters/file/aliyun-oss.d.ts +3 -3
- package/dist/adapters/file/aliyun-oss.d.ts.map +1 -1
- package/dist/adapters/file/aliyun-oss.js.map +1 -1
- package/dist/adapters/file/aliyun-oss.mjs.map +1 -1
- package/dist/adapters/file/database.d.ts +2 -2
- package/dist/adapters/file/database.d.ts.map +1 -1
- package/dist/adapters/file/database.js.map +1 -1
- package/dist/adapters/file/database.mjs +2 -2
- package/dist/adapters/file/database.mjs.map +1 -1
- package/dist/adapters/file/filesystem.d.ts +3 -3
- package/dist/adapters/file/filesystem.d.ts.map +1 -1
- package/dist/adapters/file/filesystem.js.map +1 -1
- package/dist/adapters/file/filesystem.mjs.map +1 -1
- package/dist/adapters/file/google-cloud-storage.d.ts +3 -3
- package/dist/adapters/file/google-cloud-storage.d.ts.map +1 -1
- package/dist/adapters/file/google-cloud-storage.js.map +1 -1
- package/dist/adapters/file/google-cloud-storage.mjs.map +1 -1
- package/dist/adapters/storage/progres.d.ts +1 -1
- package/dist/adapters/storage/progres.d.ts.map +1 -1
- package/dist/adapters/storage/progres.js +1 -1
- package/dist/adapters/storage/progres.js.map +1 -1
- package/dist/adapters/storage/progres.mjs +5 -5
- package/dist/adapters/storage/progres.mjs.map +1 -1
- package/dist/client.d.ts +3 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.mjs +4 -4
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +43 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +48 -19
- package/dist/index.mjs.map +1 -1
- package/dist/internals/{base-NZIvB1zK.d.ts → base-DSo02iAX.d.ts} +4 -3
- package/dist/internals/base-DSo02iAX.d.ts.map +1 -0
- package/dist/internals/base-DYc1_peK.mjs.map +1 -1
- package/dist/internals/base-NsJYo2MG.js.map +1 -1
- package/dist/internals/{chunk-B9i8NMB_.d.ts → chunk-BhwfdCdq.d.ts} +3 -3
- package/dist/internals/chunk-BhwfdCdq.d.ts.map +1 -0
- package/dist/internals/chunk-BuKmyceG.js.map +1 -1
- package/dist/internals/chunk-bpt1C6W4.mjs.map +1 -1
- package/dist/internals/{const-DqPhhmor.mjs → const-68KwNmag.mjs} +2 -2
- package/dist/internals/{const-DqPhhmor.mjs.map → const-68KwNmag.mjs.map} +1 -1
- package/dist/internals/{index-BOboD1oK.d.ts → index-1ZK5N4yb.d.ts} +4 -3
- package/dist/internals/index-1ZK5N4yb.d.ts.map +1 -0
- package/dist/internals/{index-BZ79Ljis.mjs → index-BWZIV3_T.mjs} +4 -4
- package/dist/internals/{index-BZ79Ljis.mjs.map → index-BWZIV3_T.mjs.map} +1 -1
- package/dist/internals/index-CLKTEIj0.js.map +1 -1
- package/dist/internals/{index-gWcE22mf.mjs → index-CSOoWRr1.mjs} +2 -2
- package/dist/internals/{index-gWcE22mf.mjs.map → index-CSOoWRr1.mjs.map} +1 -1
- package/dist/internals/{index-BcNiVp-e.d.ts → index-Cj45GkKv.d.ts} +2 -2
- package/dist/internals/index-Cj45GkKv.d.ts.map +1 -0
- package/dist/internals/index-vOFh8pVc.js.map +1 -1
- package/dist/internals/random-CYjWDvex.mjs.map +1 -1
- package/dist/internals/random-nkOQ9U6S.js.map +1 -1
- package/dist/internals/validator-Bc1jRJfA.js.map +1 -1
- package/dist/internals/{validator-0I1kvhsL.mjs → validator-Boj1PUjM.mjs} +2 -2
- package/dist/internals/{validator-0I1kvhsL.mjs.map → validator-Boj1PUjM.mjs.map} +1 -1
- package/package.json +23 -23
- package/dist/internals/base-NZIvB1zK.d.ts.map +0 -1
- package/dist/internals/chunk-B9i8NMB_.d.ts.map +0 -1
- package/dist/internals/index-BOboD1oK.d.ts.map +0 -1
- package/dist/internals/index-BcNiVp-e.d.ts.map +0 -1
package/dist/client.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { P as ProtoClient } from './internals/index-
|
|
2
|
-
export { c as classExtends } from './internals/index-
|
|
3
|
-
export { D as DeserializeOptions, S as SerializeOptions, e as TNumber, f as TSerializable, g as deserialize, s as serialize } from './internals/index-
|
|
1
|
+
import { P as ProtoClient } from './internals/index-Cj45GkKv.js';
|
|
2
|
+
export { c as classExtends } from './internals/index-Cj45GkKv.js';
|
|
3
|
+
export { D as DeserializeOptions, S as SerializeOptions, e as TNumber, f as TSerializable, g as deserialize, s as serialize } from './internals/index-1ZK5N4yb.js';
|
|
4
4
|
export { Decimal } from 'decimal.js';
|
|
5
5
|
import '@o2ter/utils-js';
|
|
6
6
|
import 'socket.io-client';
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"client.d.ts","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;"}
|
package/dist/client.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { b as ProtoClient } from './internals/index-
|
|
2
|
-
export { c as classExtends, d as deserialize, s as serialize } from './internals/index-
|
|
1
|
+
import { b as ProtoClient } from './internals/index-BWZIV3_T.mjs';
|
|
2
|
+
export { c as classExtends, d as deserialize, s as serialize } from './internals/index-BWZIV3_T.mjs';
|
|
3
3
|
export { Decimal } from 'decimal.js';
|
|
4
4
|
import '@o2ter/utils-js';
|
|
5
5
|
import './internals/private-CNw40LZ7.mjs';
|
|
6
6
|
import 'lodash';
|
|
7
|
-
import './internals/index-
|
|
7
|
+
import './internals/index-CSOoWRr1.mjs';
|
|
8
8
|
import 'axios';
|
|
9
|
-
import './internals/const-
|
|
9
|
+
import './internals/const-68KwNmag.mjs';
|
|
10
10
|
import '@o2ter/server-js/dist/const';
|
|
11
11
|
import 'socket.io-client';
|
|
12
12
|
import '@o2ter/crypto-js';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as socket_io from 'socket.io';
|
|
2
2
|
import { Router } from 'express';
|
|
3
3
|
import { Server } from '@o2ter/server-js';
|
|
4
|
-
import {
|
|
5
|
-
export { D as DeserializeOptions, S as SerializeOptions, d as TFileStorage, e as TNumber, f as TSerializable, g as deserialize, s as serialize } from './internals/index-
|
|
4
|
+
import { P as ProtoService, a as ProtoServiceOptions, b as ProtoServiceKeyOptions, T as TSchema, c as TValueWithoutObject } from './internals/index-1ZK5N4yb.js';
|
|
5
|
+
export { D as DeserializeOptions, S as SerializeOptions, d as TFileStorage, e as TNumber, f as TSerializable, g as deserialize, s as serialize } from './internals/index-1ZK5N4yb.js';
|
|
6
6
|
import Decimal from 'decimal.js';
|
|
7
7
|
export { Decimal } from 'decimal.js';
|
|
8
|
-
export { P as ProtoClient, c as classExtends } from './internals/index-
|
|
8
|
+
export { P as ProtoClient, c as classExtends } from './internals/index-Cj45GkKv.js';
|
|
9
9
|
import '@o2ter/utils-js';
|
|
10
10
|
import 'jsonwebtoken';
|
|
11
11
|
import 'lodash';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sources":["../src/index.ts"],"sourcesContent":["//\n// index.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport { Router } from 'express';\nimport { Server } from '@o2ter/server-js';\nimport { ProtoService } from './server/proto';\nimport { ProtoServiceKeyOptions, ProtoServiceOptions } from './server/proto/types';\nimport authHandler from './server/auth';\nimport classesRoute from './server/routes/classes';\nimport functionRoute from './server/routes/function';\nimport jobRoute from './server/routes/job';\nimport filesRoute from './server/routes/files';\nimport userRoute from './server/routes/user';\nimport notifyRoute from './server/routes/notify';\nimport schemaRoute from './server/routes/schema';\nimport configRoute from './server/routes/config';\nimport { TSchema } from './internals/schema';\nimport { PVK } from './internals/private';\nimport { TValueWithoutObject } from './internals/types';\nimport Decimal from 'decimal.js';\nimport { response } from './server/routes/common';\nimport { QuerySelector } from './server/query/dispatcher/parser';\nimport { serialize } from './internals/codec';\n\nexport * from './internals/codec';\nexport { classExtends } from './internals/utils';\nexport { TFileStorage } from './server/file';\nexport { ProtoService } from './server/proto';\nexport { ProtoClient } from './client';\n\n/**\n * Schema definition utility functions.\n */\nexport const schema = _.assign((x: Record<string, TSchema>) => x, {\n /**\n * Defines a boolean schema.\n * @param defaultValue - The default value for the boolean.\n * @returns The boolean schema.\n */\n boolean: (defaultValue?: boolean) => ({ type: 'boolean', default: defaultValue }) as const,\n\n /**\n * Defines a number schema.\n * @param defaultValue - The default value for the number.\n * @returns The number schema.\n */\n number: (defaultValue?: number) => ({ type: 'number', default: defaultValue }) as const,\n\n /**\n * Defines a decimal schema.\n * @param defaultValue - The default value for the decimal.\n * @returns The decimal schema.\n */\n decimal: (defaultValue?: Decimal) => ({ type: 'decimal', default: defaultValue }) as const,\n\n /**\n * Defines a string schema.\n * @param defaultValue - The default value for the string.\n * @returns The string schema.\n */\n string: (defaultValue?: string) => ({ type: 'string', default: defaultValue }) as const,\n\n /**\n * Defines a string array schema.\n * @param defaultValue - The default value for the string array.\n * @returns The string array schema.\n */\n stringArray: (defaultValue?: string[]) => ({ type: 'string[]', default: defaultValue }) as const,\n\n /**\n * Defines a date schema.\n * @param defaultValue - The default value for the date.\n * @returns The date schema.\n */\n date: (defaultValue?: Date) => ({ type: 'date', default: defaultValue }) as const,\n\n /**\n * Defines an object schema.\n * @param defaultValue - The default value for the object.\n * @returns The object schema.\n */\n object: <T extends Record<string, TValueWithoutObject>>(defaultValue?: T) => ({ type: 'object', default: defaultValue }) as const,\n\n /**\n * Defines an array schema.\n * @param defaultValue - The default value for the array.\n * @returns The array schema.\n */\n array: <T extends TValueWithoutObject[]>(defaultValue?: T) => ({ type: 'array', default: defaultValue }) as const,\n\n /**\n * Defines a vector schema.\n * @param dimension - The dimension of the vector.\n * @param defaultValue - The default value for the vector.\n * @returns The vector schema.\n */\n vector: (dimension: number, defaultValue?: number[]) => ({ type: 'vector', dimension, default: defaultValue }) as const,\n\n /**\n * Defines a shape schema.\n * @param shape - The shape definition.\n * @returns The shape schema.\n */\n shape: (shape: Record<string, TSchema.DataType>) => ({ type: 'shape', shape }) as const,\n\n /**\n * Defines a pointer schema.\n * @param target - The target of the pointer.\n * @returns The pointer schema.\n */\n pointer: (target: string) => ({ type: 'pointer', target }) as const,\n\n /**\n * Defines a relation schema.\n * @param target - The target of the relation.\n * @param foreignField - The foreign field of the relation.\n * @returns The relation schema.\n */\n relation: (target: string, foreignField?: string) => ({ type: 'relation', target, foreignField }) as const,\n});\n\n/**\n * Creates a ProtoRoute.\n * @param options - The options for the ProtoRoute.\n * @returns A promise that resolves to a Router.\n */\nexport const ProtoRoute = async <E>(options: {\n proto: ProtoService<E> | (ProtoServiceOptions<E> & ProtoServiceKeyOptions);\n}): Promise<Router> => {\n\n const proto = options.proto instanceof ProtoService ? options.proto : new ProtoService(options.proto);\n await proto[PVK].prepare();\n\n const router = Server.Router().use(\n authHandler(proto),\n (req, res, next) => {\n const payload = proto.connect(req);\n if (!payload.isInvalidMasterToken) return next();\n res.status(400).json({ message: 'Invalid token' });\n },\n );\n\n router.get('/health', (req, res) => { res.sendStatus(200); });\n router.get('/sessionInfo', async (req, res) => {\n await response(res, () => proto.connect(req).sessionInfo());\n });\n\n classesRoute(router, proto);\n functionRoute(router, proto);\n jobRoute(router, proto);\n filesRoute(router, proto);\n userRoute(router, proto);\n notifyRoute(router, proto);\n schemaRoute(router, proto);\n configRoute(router, proto);\n\n return router;\n}\n\n/**\n * Registers a ProtoSocket.\n * @param proto - The ProtoService instance.\n * @param server - The server instance.\n * @param endpoint - The optional endpoint.\n * @returns The socket.io instance.\n */\nexport const registerProtoSocket = <E>(\n proto: ProtoService<E>,\n server: Server,\n endpoint?: string,\n) => {\n const io = endpoint ? server.socket().of(endpoint) : server.socket();\n\n io.on('connection', async (socket) => {\n\n let { token } = socket.handshake.auth;\n const service = await proto.connectWithSessionToken(token);\n\n socket.on('auth', (t) => {\n token = t;\n service.connectWithSessionToken(t);\n });\n\n type QueryOpts = {\n event: string;\n className: string;\n filter: QuerySelector | boolean;\n };\n\n let events: Record<string, QuerySelector | boolean> = {};\n let queries: Record<string, QueryOpts> = {};\n\n const { remove: remove_basic } = service.listen(data => {\n const ids = _.keys(_.pickBy(events, v => v instanceof QuerySelector ? v.eval(data) : v));\n const payload = JSON.parse(serialize(data));\n if (!_.isEmpty(ids)) socket.emit('ON_EV_NOTIFY', { ids, data: payload });\n });\n\n const { remove: remove_livequery } = service[PVK]._liveQuery(service, (ev, objs) => {\n const ids: Record<string, string[]> = {};\n for (const obj of objs) {\n ids[obj.id!] = _.keys(_.pickBy(queries, v => {\n if (v.event !== ev || v.className !== obj.className) return false;\n return v.filter instanceof QuerySelector ? v.filter.eval(obj) : v.filter;\n }));\n }\n if (_.isEmpty(ids)) return;\n const payload = JSON.parse(serialize(_.filter(objs, obj => !_.isEmpty(ids[obj.id!]))));\n socket.emit('ON_EV_LIVEQUERY', { ids, data: payload });\n });\n\n socket.on('disconnect', () => {\n remove_basic();\n remove_livequery();\n });\n\n socket.on('EV_NOTIFY', (payload) => {\n events = _.mapValues(payload, v => {\n if (_.isBoolean(v)) return true;\n try {\n return QuerySelector.decode(v);\n } catch (error) {\n proto.logger.error(error);\n return false;\n }\n });\n });\n\n socket.on('EV_LIVEQUERY', (payload) => {\n queries = _.mapValues(payload, v => {\n const { event = '', className = '', filter } = v ?? {};\n if (_.isBoolean(v)) return { event, className, filter: true };\n try {\n return { event, className, filter: QuerySelector.decode(filter) };\n } catch (error) {\n proto.logger.error(error);\n return { event, className, filter: false };\n }\n });\n });\n });\n\n return io;\n}\n\nexport default ProtoRoute;"],"names":[],"mappings":";;;;;;;;;;;;;;;AAYA;AACA;AACA;AACO,cAAA,MAAA,OAAA,MAAA,SAAA,OAAA,MAAA,MAAA,SAAA,OAAA;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6BAAA,OAAA;AACA;AACA,0BAAA,OAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0BAAA,IAAA;AACA;AACA,0BAAA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uBAAA,MAAA,SAAA,mBAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAA,mBAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAA,MAAA,SAAA,OAAA,CAAA,QAAA;AACA;AACA,wBAAA,MAAA,SAAA,OAAA,CAAA,QAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,cAAA,UAAA;AACP,WAAA,YAAA,OAAA,mBAAA,MAAA,sBAAA;AACA,MAAA,OAAA,CAAA,MAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,cAAA,mBAAA,aAAA,YAAA,aAAA,MAAA,wBAAqG,SAAmB,CAAA,MAAA,CAAQ,SAAmB,CAAA,gBAAA,EAAmB,SAAmB,CAAA,gBAAA,EAAmB,SAAmB,CAAA,gBAAA,SAA0B,SAAmB,CAAA,SAAA,CAAW,SAAmB,CAAA,gBAAA,EAAmB,SAAmB,mBAAmB,SAAmB,CAAA,gBAAA;;;;"}
|
package/dist/index.js
CHANGED
|
@@ -265,6 +265,7 @@ const proxy = (x) => {
|
|
|
265
265
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
266
266
|
// THE SOFTWARE.
|
|
267
267
|
//
|
|
268
|
+
const afterCommitTasks = new WeakMap();
|
|
268
269
|
class _ProtoQuery extends index.TQuery {
|
|
269
270
|
_proto;
|
|
270
271
|
_opts;
|
|
@@ -383,6 +384,15 @@ class _ProtoQuery extends index.TQuery {
|
|
|
383
384
|
})();
|
|
384
385
|
}
|
|
385
386
|
}
|
|
387
|
+
_do_tasks(session, task) {
|
|
388
|
+
const registers = session && afterCommitTasks.get(session);
|
|
389
|
+
if (!_.isNil(registers)) {
|
|
390
|
+
registers.push(task);
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
task();
|
|
394
|
+
}
|
|
395
|
+
}
|
|
386
396
|
async insertMany(values, options) {
|
|
387
397
|
const objs = this._objectMethods(await this._dispatcher(options).insert({
|
|
388
398
|
className: this.className,
|
|
@@ -390,30 +400,38 @@ class _ProtoQuery extends index.TQuery {
|
|
|
390
400
|
matches: this[_private.PVK].options.matches,
|
|
391
401
|
groupMatches: this[_private.PVK].options.groupMatches,
|
|
392
402
|
}, values));
|
|
393
|
-
this.
|
|
394
|
-
|
|
395
|
-
|
|
403
|
+
this._do_tasks(options?.session, () => {
|
|
404
|
+
this._on_upsert(objs);
|
|
405
|
+
if (!options?.silent || !options.master)
|
|
406
|
+
this._on_upsert_traggers(objs);
|
|
407
|
+
});
|
|
396
408
|
return objs;
|
|
397
409
|
}
|
|
398
410
|
async updateMany(update, options) {
|
|
399
411
|
const objs = this._objectMethods(await this._dispatcher(options).update(this._queryOptions, update));
|
|
400
|
-
this.
|
|
401
|
-
|
|
402
|
-
|
|
412
|
+
this._do_tasks(options?.session, () => {
|
|
413
|
+
this._on_upsert(objs);
|
|
414
|
+
if (!options?.silent || !options.master)
|
|
415
|
+
this._on_upsert_traggers(objs);
|
|
416
|
+
});
|
|
403
417
|
return objs;
|
|
404
418
|
}
|
|
405
419
|
async upsertMany(update, setOnInsert, options) {
|
|
406
420
|
const objs = this._objectMethods(await this._dispatcher(options).upsert(this._queryOptions, update, setOnInsert));
|
|
407
|
-
this.
|
|
408
|
-
|
|
409
|
-
|
|
421
|
+
this._do_tasks(options?.session, () => {
|
|
422
|
+
this._on_upsert(objs);
|
|
423
|
+
if (!options?.silent || !options.master)
|
|
424
|
+
this._on_upsert_traggers(objs);
|
|
425
|
+
});
|
|
410
426
|
return objs;
|
|
411
427
|
}
|
|
412
428
|
async deleteMany(options) {
|
|
413
429
|
const objs = this._objectMethods(await this._dispatcher(options).delete(this._queryOptions));
|
|
414
|
-
this.
|
|
415
|
-
|
|
416
|
-
|
|
430
|
+
this._do_tasks(options?.session, () => {
|
|
431
|
+
this._on_delete(objs);
|
|
432
|
+
if (!options?.silent || !options.master)
|
|
433
|
+
this._on_delete_traggers(objs);
|
|
434
|
+
});
|
|
417
435
|
return objs;
|
|
418
436
|
}
|
|
419
437
|
}
|
|
@@ -1749,8 +1767,18 @@ class ProtoService extends index.ProtoType {
|
|
|
1749
1767
|
lockTable(className, update) {
|
|
1750
1768
|
return this.storage.lockTable(className, update);
|
|
1751
1769
|
}
|
|
1752
|
-
withTransaction(callback, options) {
|
|
1753
|
-
|
|
1770
|
+
async withTransaction(callback, options) {
|
|
1771
|
+
const tasks = afterCommitTasks.get(this) ?? [];
|
|
1772
|
+
const result = await this.storage.withTransaction((storage) => {
|
|
1773
|
+
const payload = _.create(this, { _storage: storage });
|
|
1774
|
+
afterCommitTasks.set(payload, tasks);
|
|
1775
|
+
return callback(payload);
|
|
1776
|
+
}, options);
|
|
1777
|
+
if (!afterCommitTasks.has(this)) {
|
|
1778
|
+
for (const task of tasks)
|
|
1779
|
+
task();
|
|
1780
|
+
}
|
|
1781
|
+
return result;
|
|
1754
1782
|
}
|
|
1755
1783
|
generateUploadToken(options = {}) {
|
|
1756
1784
|
return this[_private.PVK].jwtSign({
|
|
@@ -2288,6 +2316,7 @@ var filesRoute = (router, proto) => {
|
|
|
2288
2316
|
}
|
|
2289
2317
|
res.setHeader('Content-Type', file.type);
|
|
2290
2318
|
res.setHeader('Cache-Control', 'public, max-age=0');
|
|
2319
|
+
res.setHeader('Content-Disposition', 'attachment');
|
|
2291
2320
|
res.setHeader('ETag', `"${id}"`);
|
|
2292
2321
|
let stream;
|
|
2293
2322
|
if (_.isArray(ranges) && ranges.type === 'bytes') {
|