@clairejs/server 3.18.2 → 3.19.1
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/README.md +5 -0
- package/dist/http/controller/AbstractHttpController.d.ts +2 -2
- package/dist/http/controller/AbstractHttpController.js +4 -4
- package/dist/http/controller/CrudHttpController.d.ts +2 -2
- package/dist/http/controller/CrudHttpController.js +4 -5
- package/dist/http/repository/DtoRepository.d.ts +10 -9
- package/dist/http/repository/DtoRepository.js +13 -11
- package/dist/http/repository/ICrudRepository.d.ts +3 -3
- package/dist/http/repository/ModelRepository.d.ts +5 -4
- package/dist/http/repository/ModelRepository.js +40 -32
- package/dist/job/AbstractJobRepository.d.ts +5 -5
- package/dist/job/LocalJobScheduler.js +3 -3
- package/dist/job/default-job-repo.d.ts +6 -5
- package/dist/job/default-job-repo.js +10 -8
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@ import { type ITransactionFactory } from "@clairejs/orm";
|
|
|
2
2
|
import { type EndpointMetadata } from "../../common/request/endpoint-metadata";
|
|
3
3
|
import { Transactionable } from "../../common/Transactionable";
|
|
4
4
|
export declare abstract class AbstractHttpController extends Transactionable {
|
|
5
|
-
protected readonly
|
|
6
|
-
constructor(
|
|
5
|
+
protected readonly db: ITransactionFactory;
|
|
6
|
+
constructor(db: ITransactionFactory);
|
|
7
7
|
getEndpointMetadata(): Readonly<EndpointMetadata>[];
|
|
8
8
|
}
|
|
@@ -4,10 +4,10 @@ const isEndpoint = (metadata) => {
|
|
|
4
4
|
return !!metadata.method;
|
|
5
5
|
};
|
|
6
6
|
export class AbstractHttpController extends Transactionable {
|
|
7
|
-
|
|
8
|
-
constructor(
|
|
9
|
-
super(
|
|
10
|
-
this.
|
|
7
|
+
db;
|
|
8
|
+
constructor(db) {
|
|
9
|
+
super(db);
|
|
10
|
+
this.db = db;
|
|
11
11
|
}
|
|
12
12
|
getEndpointMetadata() {
|
|
13
13
|
const controllerMetadata = getObjectMetadata(this.constructor);
|
|
@@ -8,10 +8,10 @@ import { type ICrudRepository } from "../repository/ICrudRepository";
|
|
|
8
8
|
export declare class CrudHttpController<T extends Identifiable> extends AbstractHttpController {
|
|
9
9
|
protected readonly model: Constructor<T>;
|
|
10
10
|
protected readonly crudRepository: ICrudRepository<T>;
|
|
11
|
-
protected readonly
|
|
11
|
+
protected readonly db: ITransactionFactory & IQueryProvider;
|
|
12
12
|
protected readonly modelMetadata: ModelMetadata;
|
|
13
13
|
private principalResolver?;
|
|
14
|
-
constructor(model: Constructor<T>, crudRepository: ICrudRepository<T>,
|
|
14
|
+
constructor(model: Constructor<T>, crudRepository: ICrudRepository<T>, db: ITransactionFactory & IQueryProvider);
|
|
15
15
|
protected getMountedUrl(): string;
|
|
16
16
|
private getAuthProvider;
|
|
17
17
|
/**
|
|
@@ -19,14 +19,14 @@ import { AbstractHttpController } from "./AbstractHttpController";
|
|
|
19
19
|
export class CrudHttpController extends AbstractHttpController {
|
|
20
20
|
model;
|
|
21
21
|
crudRepository;
|
|
22
|
-
|
|
22
|
+
db;
|
|
23
23
|
modelMetadata;
|
|
24
24
|
principalResolver;
|
|
25
|
-
constructor(model, crudRepository,
|
|
26
|
-
super(
|
|
25
|
+
constructor(model, crudRepository, db) {
|
|
26
|
+
super(db);
|
|
27
27
|
this.model = model;
|
|
28
28
|
this.crudRepository = crudRepository;
|
|
29
|
-
this.
|
|
29
|
+
this.db = db;
|
|
30
30
|
this.modelMetadata = getObjectMetadata(model);
|
|
31
31
|
}
|
|
32
32
|
getMountedUrl() {
|
|
@@ -197,7 +197,6 @@ export class CrudHttpController extends AbstractHttpController {
|
|
|
197
197
|
async getMany(req) {
|
|
198
198
|
const result = await this.crudRepository.getMany({
|
|
199
199
|
queries: req.getQuery(),
|
|
200
|
-
queryProvider: this.databaseAdapter,
|
|
201
200
|
});
|
|
202
201
|
return ResponseBuilder.json(result).get();
|
|
203
202
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { IPrincipal } from "../../common/auth/IPrincipal";
|
|
1
|
+
import { type Identifiable, type Constructor, type CreateManyRequestBody, type CreateManyResponseBody, type DeepPartial, type GetManyQueries, type GetManyResponseBody, type UpdateManyBody, type UpdateManyQueries, type UpdateManyResponse, AbstractLogger, AbstractModel } from "@clairejs/core";
|
|
2
|
+
import { type ITransaction, type QueryCondition, AbstractDbAdapter } from "@clairejs/orm";
|
|
3
|
+
import { type IPrincipal } from "../../common/auth/IPrincipal";
|
|
4
4
|
import { AbstractRepository } from "./AbstractRepository";
|
|
5
|
-
import { ICrudRepository } from "./ICrudRepository";
|
|
5
|
+
import { type ICrudRepository } from "./ICrudRepository";
|
|
6
6
|
export type DtoDissolver<R extends Identifiable, K extends Identifiable> = (t: DeepPartial<K>) => MappingMetadata<R, any>[];
|
|
7
7
|
export interface MappingMetadata<R extends Identifiable, K extends AbstractModel> {
|
|
8
8
|
multiple: boolean;
|
|
@@ -30,13 +30,14 @@ export declare const MultipleMap: <R extends Identifiable, K extends AbstractMod
|
|
|
30
30
|
};
|
|
31
31
|
export declare class DtoRepository<T extends Identifiable> extends AbstractRepository<T> implements ICrudRepository<T> {
|
|
32
32
|
protected readonly model: Constructor<T>;
|
|
33
|
+
protected readonly db: AbstractDbAdapter;
|
|
33
34
|
protected readonly dissolver: DtoDissolver<T, any>;
|
|
34
|
-
constructor(model: Constructor<T>, dissolver: DtoDissolver<T, any>);
|
|
35
|
+
constructor(model: Constructor<T>, db: AbstractDbAdapter, dissolver: DtoDissolver<T, any>);
|
|
35
36
|
private getMapValue;
|
|
36
37
|
createMany({ principal, body, tx, logger, }: {
|
|
37
38
|
principal?: IPrincipal | undefined;
|
|
38
39
|
body: CreateManyRequestBody<T>;
|
|
39
|
-
tx: ITransaction
|
|
40
|
+
tx: ITransaction;
|
|
40
41
|
logger?: AbstractLogger;
|
|
41
42
|
}): Promise<CreateManyResponseBody<T>>;
|
|
42
43
|
updateMany({ principal, queries, ops, body, tx, logger, }: {
|
|
@@ -44,13 +45,13 @@ export declare class DtoRepository<T extends Identifiable> extends AbstractRepos
|
|
|
44
45
|
queries?: UpdateManyQueries<T>;
|
|
45
46
|
ops?: QueryCondition<T>[];
|
|
46
47
|
body: UpdateManyBody<T>;
|
|
47
|
-
tx: ITransaction
|
|
48
|
+
tx: ITransaction;
|
|
48
49
|
logger?: AbstractLogger;
|
|
49
50
|
}): Promise<UpdateManyResponse<T>>;
|
|
50
|
-
getMany({ queries, ops,
|
|
51
|
+
getMany({ queries, ops, tx, logger, }: {
|
|
51
52
|
queries?: GetManyQueries<T>;
|
|
52
53
|
ops?: QueryCondition<T>[];
|
|
53
|
-
|
|
54
|
+
tx?: ITransaction;
|
|
54
55
|
logger?: AbstractLogger;
|
|
55
56
|
}): Promise<GetManyResponseBody<T>>;
|
|
56
57
|
deleteMany({ queries, ops, tx, logger, }: {
|
|
@@ -25,10 +25,12 @@ export const MultipleMap = (modelClass, forwardOps, forwardMapping, rootMapping,
|
|
|
25
25
|
});
|
|
26
26
|
export class DtoRepository extends AbstractRepository {
|
|
27
27
|
model;
|
|
28
|
+
db;
|
|
28
29
|
dissolver;
|
|
29
|
-
constructor(model, dissolver) {
|
|
30
|
+
constructor(model, db, dissolver) {
|
|
30
31
|
super(model);
|
|
31
32
|
this.model = model;
|
|
33
|
+
this.db = db;
|
|
32
34
|
this.dissolver = dissolver;
|
|
33
35
|
}
|
|
34
36
|
async getMapValue(root, currentInstancesResolver, mappers, preOperator, postOperator) {
|
|
@@ -56,10 +58,10 @@ export class DtoRepository extends AbstractRepository {
|
|
|
56
58
|
await this.beforeCreating(principal, body.records);
|
|
57
59
|
for (const record of body.records) {
|
|
58
60
|
await this.getMapValue(record, async (mapper) => {
|
|
59
|
-
const repo = new ModelRepository(mapper.modelClass);
|
|
61
|
+
const repo = new ModelRepository(mapper.modelClass, this.db);
|
|
60
62
|
const currentInstances = await repo.getMany({
|
|
61
63
|
ops: mapper.forwardOps(),
|
|
62
|
-
|
|
64
|
+
tx,
|
|
63
65
|
logger,
|
|
64
66
|
});
|
|
65
67
|
return currentInstances.records;
|
|
@@ -67,7 +69,7 @@ export class DtoRepository extends AbstractRepository {
|
|
|
67
69
|
if (!ks) {
|
|
68
70
|
return [];
|
|
69
71
|
}
|
|
70
|
-
const repo = new ModelRepository(mapper.modelClass);
|
|
72
|
+
const repo = new ModelRepository(mapper.modelClass, this.db);
|
|
71
73
|
const ops = mapper.forwardOps();
|
|
72
74
|
if (mapper.multiple) {
|
|
73
75
|
//-- if ks contain an array of instances, we need to remove old instances and create new ones
|
|
@@ -118,10 +120,10 @@ export class DtoRepository extends AbstractRepository {
|
|
|
118
120
|
const result = { ...body.update, id: queries.fields.id[0] };
|
|
119
121
|
await this.beforeCreating(principal, [result]);
|
|
120
122
|
await this.getMapValue(result, async (mapper) => {
|
|
121
|
-
const repo = new ModelRepository(mapper.modelClass);
|
|
123
|
+
const repo = new ModelRepository(mapper.modelClass, this.db);
|
|
122
124
|
const currentInstances = await repo.getMany({
|
|
123
125
|
ops: mapper.forwardOps(ops),
|
|
124
|
-
|
|
126
|
+
tx,
|
|
125
127
|
logger,
|
|
126
128
|
});
|
|
127
129
|
return currentInstances.records;
|
|
@@ -129,7 +131,7 @@ export class DtoRepository extends AbstractRepository {
|
|
|
129
131
|
if (!ks) {
|
|
130
132
|
return [];
|
|
131
133
|
}
|
|
132
|
-
const repo = new ModelRepository(mapper.modelClass);
|
|
134
|
+
const repo = new ModelRepository(mapper.modelClass, this.db);
|
|
133
135
|
const opsx = mapper.forwardOps(ops);
|
|
134
136
|
if (mapper.multiple) {
|
|
135
137
|
//-- if ks contain an array of instances, we need to remove old instances and create new ones
|
|
@@ -171,18 +173,18 @@ export class DtoRepository extends AbstractRepository {
|
|
|
171
173
|
}
|
|
172
174
|
return { modified: result.id ? this.project([result], projection) : [] };
|
|
173
175
|
}
|
|
174
|
-
async getMany({ queries, ops,
|
|
176
|
+
async getMany({ queries, ops, tx, logger, }) {
|
|
175
177
|
//-- check queries for id field
|
|
176
178
|
if (!queries?.fields?.id || queries.fields.id.length !== 1) {
|
|
177
179
|
throw Errors.VALIDATION_ERROR("Missing required id field in query");
|
|
178
180
|
}
|
|
179
181
|
const result = { id: queries.fields.id[0] };
|
|
180
182
|
await this.getMapValue(result, async () => [], this.dissolver(result), async (mapper) => {
|
|
181
|
-
const repo = new ModelRepository(mapper.modelClass);
|
|
183
|
+
const repo = new ModelRepository(mapper.modelClass, this.db);
|
|
182
184
|
//-- forward get
|
|
183
185
|
const instances = await repo.getMany({
|
|
184
186
|
ops: mapper.forwardOps(ops),
|
|
185
|
-
|
|
187
|
+
tx,
|
|
186
188
|
logger,
|
|
187
189
|
});
|
|
188
190
|
return instances.records;
|
|
@@ -198,7 +200,7 @@ export class DtoRepository extends AbstractRepository {
|
|
|
198
200
|
}
|
|
199
201
|
const result = { id: queries.fields.id[0] };
|
|
200
202
|
await this.getMapValue(result, async () => [], this.dissolver(result), undefined, async (mapper) => {
|
|
201
|
-
const repo = new ModelRepository(mapper.modelClass);
|
|
203
|
+
const repo = new ModelRepository(mapper.modelClass, this.db);
|
|
202
204
|
//const nestedQueries = mapper.forwardQuery();
|
|
203
205
|
const nestedOps = mapper.forwardOps(ops);
|
|
204
206
|
const result = await repo.deleteMany({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type AbstractLogger, type CreateManyRequestBody, type CreateManyResponseBody, type GetManyQueries, type GetManyResponseBody, type UpdateManyBody, type UpdateManyQueries, type UpdateManyResponse } from "@clairejs/core";
|
|
2
|
-
import { type
|
|
2
|
+
import { type ITransaction, type QueryCondition } from "@clairejs/orm";
|
|
3
3
|
import { type IPrincipal } from "../../common/auth/IPrincipal";
|
|
4
4
|
export interface ICrudRepository<T> {
|
|
5
5
|
createMany({ principal, body, tx, logger, }: {
|
|
@@ -8,10 +8,10 @@ export interface ICrudRepository<T> {
|
|
|
8
8
|
logger?: AbstractLogger;
|
|
9
9
|
principal?: IPrincipal;
|
|
10
10
|
}): Promise<CreateManyResponseBody<T>>;
|
|
11
|
-
getMany({ queries, ops,
|
|
11
|
+
getMany({ queries, ops, tx, logger, }: {
|
|
12
12
|
queries?: GetManyQueries<T>;
|
|
13
13
|
ops?: QueryCondition<T>[];
|
|
14
|
-
|
|
14
|
+
tx?: ITransaction;
|
|
15
15
|
logger?: AbstractLogger;
|
|
16
16
|
}): Promise<GetManyResponseBody<T>>;
|
|
17
17
|
updateMany({ principal, queries, ops, body, tx, logger, }: {
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { AbstractModel, Constructor, CreateManyRequestBody, CreateManyResponseBody, GetManyQueries, GetManyResponseBody, UpdateManyBody, UpdateManyQueries, UpdateManyResponse, AbstractLogger } from "@clairejs/core";
|
|
2
|
-
import {
|
|
2
|
+
import { AbstractDbAdapter, ITransaction, QueryCondition } from "@clairejs/orm";
|
|
3
3
|
import { IPrincipal } from "../../common/auth/IPrincipal";
|
|
4
4
|
import { ICrudRepository } from "./ICrudRepository";
|
|
5
5
|
import { AbstractRepository } from "./AbstractRepository";
|
|
6
6
|
export declare class ModelRepository<T extends AbstractModel> extends AbstractRepository<T> implements ICrudRepository<T> {
|
|
7
7
|
protected readonly model: Constructor<T>;
|
|
8
|
+
protected readonly db: AbstractDbAdapter;
|
|
8
9
|
private fileUploadHandler?;
|
|
9
|
-
constructor(model: Constructor<T
|
|
10
|
+
constructor(model: Constructor<T>, db: AbstractDbAdapter);
|
|
10
11
|
private getNestedQueries;
|
|
11
12
|
private getUploadHandler;
|
|
12
13
|
private getRequestQueryConditionFromQuery;
|
|
@@ -26,10 +27,10 @@ export declare class ModelRepository<T extends AbstractModel> extends AbstractRe
|
|
|
26
27
|
tx: ITransaction;
|
|
27
28
|
logger?: AbstractLogger;
|
|
28
29
|
}): Promise<UpdateManyResponse<T>>;
|
|
29
|
-
getMany({ queries, ops,
|
|
30
|
+
getMany({ queries, ops, tx, logger, }: {
|
|
30
31
|
queries?: GetManyQueries<T>;
|
|
31
32
|
ops?: QueryCondition<T>[];
|
|
32
|
-
|
|
33
|
+
tx?: ITransaction;
|
|
33
34
|
logger?: AbstractLogger;
|
|
34
35
|
}): Promise<GetManyResponseBody<T>>;
|
|
35
36
|
deleteMany({ queries, ops, tx, logger, }: {
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { DataType, getModelById, getServiceProvider, RangeQueryDto, uniqueReducer, leanData, getSystemLocale, Errors, omitData, } from "@clairejs/core";
|
|
2
|
-
import { getDirectFields } from "@clairejs/orm";
|
|
2
|
+
import { getDirectFields, } from "@clairejs/orm";
|
|
3
3
|
import { AbstractFileUploadHandler } from "../file-upload/AbstractFileUploadHandler";
|
|
4
4
|
import { AbstractRepository } from "./AbstractRepository";
|
|
5
5
|
import { LocaleTranslation } from "../../system/locale/LocaleTranslation";
|
|
6
6
|
import { LocaleEntry } from "../../system/locale/LocaleEntry";
|
|
7
7
|
export class ModelRepository extends AbstractRepository {
|
|
8
8
|
model;
|
|
9
|
+
db;
|
|
9
10
|
fileUploadHandler;
|
|
10
|
-
constructor(model) {
|
|
11
|
+
constructor(model, db) {
|
|
11
12
|
super(model);
|
|
12
13
|
this.model = model;
|
|
14
|
+
this.db = db;
|
|
13
15
|
}
|
|
14
16
|
getNestedQueries(queries) {
|
|
15
17
|
return this.modelMetadata.fields
|
|
@@ -238,8 +240,8 @@ export class ModelRepository extends AbstractRepository {
|
|
|
238
240
|
entryObject: {},
|
|
239
241
|
}));
|
|
240
242
|
});
|
|
241
|
-
const translationEntries = await
|
|
242
|
-
.use(LocaleEntry)
|
|
243
|
+
const translationEntries = await this.db
|
|
244
|
+
.use(LocaleEntry, tx)
|
|
243
245
|
.createMany(translationEntryData.map((data) => data.entryObject));
|
|
244
246
|
//-- translation data will have same length as translationEntries
|
|
245
247
|
const translationData = originalRecords.flatMap((record) => {
|
|
@@ -256,7 +258,7 @@ export class ModelRepository extends AbstractRepository {
|
|
|
256
258
|
}));
|
|
257
259
|
});
|
|
258
260
|
//-- create translation records
|
|
259
|
-
await
|
|
261
|
+
await this.db.use(LocaleTranslation, tx).createMany(translations);
|
|
260
262
|
//-- first create records for direct fields
|
|
261
263
|
body.records = originalRecords.map((record, index) => {
|
|
262
264
|
const data = directFields.reduce((collector, field) => {
|
|
@@ -278,7 +280,9 @@ export class ModelRepository extends AbstractRepository {
|
|
|
278
280
|
return data;
|
|
279
281
|
});
|
|
280
282
|
await this.beforeCreating(principal, body.records);
|
|
281
|
-
let records = body.records.length
|
|
283
|
+
let records = body.records.length
|
|
284
|
+
? await this.db.use(this.model, tx).createMany(body.records)
|
|
285
|
+
: [];
|
|
282
286
|
await this.beforeReturning(records);
|
|
283
287
|
const projection = this.modelMetadata.fields
|
|
284
288
|
.filter((field) => !field.multiLocaleColumn && (field.pk || field.serverValue || field.mimeProps))
|
|
@@ -301,7 +305,7 @@ export class ModelRepository extends AbstractRepository {
|
|
|
301
305
|
});
|
|
302
306
|
if (hasManyRecords.length) {
|
|
303
307
|
//-- insert to db
|
|
304
|
-
const innerService = new ModelRepository(getModelById(field.hasMany.relationDto.id));
|
|
308
|
+
const innerService = new ModelRepository(getModelById(field.hasMany.relationDto.id), this.db);
|
|
305
309
|
body.records = hasManyRecords;
|
|
306
310
|
const persistedInnerRecords = await innerService.createMany({ principal, body, tx });
|
|
307
311
|
//-- map back ids to hasManyRecords
|
|
@@ -362,12 +366,14 @@ export class ModelRepository extends AbstractRepository {
|
|
|
362
366
|
let modified = [];
|
|
363
367
|
let updatedRecords = [];
|
|
364
368
|
if (nestedQueries.length) {
|
|
365
|
-
const tobeUpdated = await
|
|
369
|
+
const tobeUpdated = await this.db
|
|
370
|
+
.use(this.model, tx)
|
|
371
|
+
.getMany(condition, { projection: ["id"] }, nestedQueries);
|
|
366
372
|
modified = tobeUpdated.records.map((r) => r.id);
|
|
367
373
|
if (modified.length) {
|
|
368
374
|
if (directUpdateFields.length) {
|
|
369
|
-
updatedRecords = await
|
|
370
|
-
.use(this.model)
|
|
375
|
+
updatedRecords = await this.db
|
|
376
|
+
.use(this.model, tx)
|
|
371
377
|
.updateMany({ _in: { id: modified } }, directUpdate, true);
|
|
372
378
|
}
|
|
373
379
|
else {
|
|
@@ -377,11 +383,11 @@ export class ModelRepository extends AbstractRepository {
|
|
|
377
383
|
}
|
|
378
384
|
else {
|
|
379
385
|
if (directUpdateFields.length) {
|
|
380
|
-
updatedRecords = await
|
|
386
|
+
updatedRecords = await this.db.use(this.model, tx).updateMany(condition, directUpdate, true);
|
|
381
387
|
modified = updatedRecords.map((re) => re.id);
|
|
382
388
|
}
|
|
383
389
|
else {
|
|
384
|
-
const tobeUpdated = await
|
|
390
|
+
const tobeUpdated = await this.db.use(this.model, tx).getMany(condition, { projection: ["id"] });
|
|
385
391
|
modified = tobeUpdated.records.map((r) => r.id);
|
|
386
392
|
updatedRecords = modified.map((id) => ({ id }));
|
|
387
393
|
}
|
|
@@ -391,7 +397,7 @@ export class ModelRepository extends AbstractRepository {
|
|
|
391
397
|
//-- update translations
|
|
392
398
|
if (localeOfFields.length) {
|
|
393
399
|
//-- check if there is missing locale entry for localeFields
|
|
394
|
-
const records = await
|
|
400
|
+
const records = await this.db.use(this.model, tx).getRecords({
|
|
395
401
|
_in: { id: modified },
|
|
396
402
|
}, { projection: ["id", ...localeOfFields.map((f) => f.name)] });
|
|
397
403
|
//-- check missing
|
|
@@ -403,7 +409,9 @@ export class ModelRepository extends AbstractRepository {
|
|
|
403
409
|
field: field.name,
|
|
404
410
|
})))
|
|
405
411
|
.flatMap((arr) => arr);
|
|
406
|
-
const missingEntries = !missing.length
|
|
412
|
+
const missingEntries = !missing.length
|
|
413
|
+
? []
|
|
414
|
+
: await this.db.use(LocaleEntry, tx).createMany(missing.map(() => ({})));
|
|
407
415
|
const updateEntryRecords = [];
|
|
408
416
|
missingEntries.forEach((entry, index) => {
|
|
409
417
|
const missingData = missing[index];
|
|
@@ -420,7 +428,7 @@ export class ModelRepository extends AbstractRepository {
|
|
|
420
428
|
}
|
|
421
429
|
});
|
|
422
430
|
//-- update records
|
|
423
|
-
await Promise.all(updateEntryRecords.map((re) =>
|
|
431
|
+
await Promise.all(updateEntryRecords.map((re) => this.db.use(this.model, tx).updateById(re.id, omitData(re, ["id"]))));
|
|
424
432
|
const tobeModified = [];
|
|
425
433
|
for (const field of localeOfFields) {
|
|
426
434
|
const localOfData = body.update[field.name];
|
|
@@ -438,13 +446,13 @@ export class ModelRepository extends AbstractRepository {
|
|
|
438
446
|
}
|
|
439
447
|
if (tobeModified.length) {
|
|
440
448
|
//-- remove old translations
|
|
441
|
-
await
|
|
449
|
+
await this.db.use(LocaleTranslation, tx).deleteMany({
|
|
442
450
|
_or: tobeModified.map((rem) => ({
|
|
443
451
|
_eq: { entryId: rem.entryId, localeCode: rem.langCode },
|
|
444
452
|
})),
|
|
445
453
|
});
|
|
446
454
|
//-- add new translations
|
|
447
|
-
await
|
|
455
|
+
await this.db.use(LocaleTranslation, tx).createMany(tobeModified.map((rem) => ({
|
|
448
456
|
entryId: rem.entryId,
|
|
449
457
|
localeCode: rem.langCode,
|
|
450
458
|
translation: rem.translation,
|
|
@@ -463,7 +471,7 @@ export class ModelRepository extends AbstractRepository {
|
|
|
463
471
|
const theRecord = records.find((r) => r.id === modified[0]);
|
|
464
472
|
//-- get all inner records and compare
|
|
465
473
|
const model = getModelById(field.hasMany.relationDto.id);
|
|
466
|
-
const adapter =
|
|
474
|
+
const adapter = this.db.use(model, tx);
|
|
467
475
|
const allInnerRecords = await adapter.getRecords({ _eq: { [field.hasMany.column]: theRecord.id } }, { limit: field.hasMany?.single ? 1 : undefined });
|
|
468
476
|
const currentIds = allInnerRecords.map((r) => r.id);
|
|
469
477
|
const newIds = innerUpdates.map((r) => r.id).filter((id) => !!id);
|
|
@@ -475,7 +483,7 @@ export class ModelRepository extends AbstractRepository {
|
|
|
475
483
|
if (tobeRemovedIds.length) {
|
|
476
484
|
await adapter.deleteMany({ _in: { id: tobeRemovedIds } });
|
|
477
485
|
}
|
|
478
|
-
const modelService = new ModelRepository(model);
|
|
486
|
+
const modelService = new ModelRepository(model, this.db);
|
|
479
487
|
const added = await modelService.createMany({
|
|
480
488
|
principal,
|
|
481
489
|
body: { records: tobeAdded },
|
|
@@ -510,7 +518,7 @@ export class ModelRepository extends AbstractRepository {
|
|
|
510
518
|
await this.beforeReturning(records);
|
|
511
519
|
return { modified: this.project(records, projection) };
|
|
512
520
|
}
|
|
513
|
-
async getMany({ queries, ops,
|
|
521
|
+
async getMany({ queries, ops, tx, logger: _logger, }) {
|
|
514
522
|
const conditions = ops || [];
|
|
515
523
|
if (queries?.fields) {
|
|
516
524
|
conditions.push(...this.getRequestQueryConditionFromQuery(queries.fields, this.modelMetadata));
|
|
@@ -533,7 +541,7 @@ export class ModelRepository extends AbstractRepository {
|
|
|
533
541
|
...queries.projection.filter((fieldName) => !this.modelMetadata.fields.find((f) => f.name === fieldName && !!f.hasMany)),
|
|
534
542
|
...localeOfFields.map((f) => f.name),
|
|
535
543
|
];
|
|
536
|
-
const result = await
|
|
544
|
+
const result = await this.db.use(this.model, tx).getMany(conditions.length ? { _and: conditions } : {}, {
|
|
537
545
|
limit: queries?.limit,
|
|
538
546
|
page: queries?.page,
|
|
539
547
|
projection: finalProjection,
|
|
@@ -551,12 +559,12 @@ export class ModelRepository extends AbstractRepository {
|
|
|
551
559
|
? []
|
|
552
560
|
: !queries?.locale
|
|
553
561
|
? //-- if locale is not specified then get translation for all locales
|
|
554
|
-
await
|
|
562
|
+
await this.db.use(LocaleTranslation, tx).getRecords({
|
|
555
563
|
_in: { entryId: allLocaleEntries },
|
|
556
564
|
}, { projection: ["entryId", "localeCode", "translation"] })
|
|
557
565
|
: //-- if locale is specified then get only the translation of that locale
|
|
558
566
|
queries.locale.toLowerCase() !== systemLocale
|
|
559
|
-
? await
|
|
567
|
+
? await this.db.use(LocaleTranslation, tx).getRecords({
|
|
560
568
|
_in: { entryId: allLocaleEntries },
|
|
561
569
|
_eq: { localeCode: queries.locale },
|
|
562
570
|
}, { projection: ["entryId", "localeCode", "translation"] })
|
|
@@ -593,12 +601,12 @@ export class ModelRepository extends AbstractRepository {
|
|
|
593
601
|
if (!model) {
|
|
594
602
|
throw Errors.NOT_FOUND(`Model not found by id: ${field.hasMany.relationDto.id}`);
|
|
595
603
|
}
|
|
596
|
-
const service = new ModelRepository(model);
|
|
604
|
+
const service = new ModelRepository(model, this.db);
|
|
597
605
|
const innerRecords = !recordIds.length
|
|
598
606
|
? { records: [] }
|
|
599
607
|
: await service.getMany({
|
|
600
608
|
queries: { fields: { [field.hasMany.column]: recordIds }, limit: field.hasMany.single ? 1 : 0 },
|
|
601
|
-
|
|
609
|
+
tx,
|
|
602
610
|
});
|
|
603
611
|
//-- filter corresponding inner records for each master record
|
|
604
612
|
for (const record of result.records) {
|
|
@@ -627,10 +635,10 @@ export class ModelRepository extends AbstractRepository {
|
|
|
627
635
|
const uriMapperFields = this.modelMetadata.fields.filter((f) => f.uriMapper);
|
|
628
636
|
const localeOfFields = this.modelMetadata.fields.filter((f) => f.multiLocaleColumn);
|
|
629
637
|
if (nestedQueries.length || localeOfFields.length || uriMapperFields.length) {
|
|
630
|
-
const tobeRemoved = await
|
|
631
|
-
.use(this.model)
|
|
638
|
+
const tobeRemoved = await this.db
|
|
639
|
+
.use(this.model, tx)
|
|
632
640
|
.getRecords(condition, { projection: ["id", ...[...localeOfFields, ...uriMapperFields].map((f) => f.name)] }, nestedQueries);
|
|
633
|
-
await
|
|
641
|
+
await this.db.use(this.model, tx).deleteMany({
|
|
634
642
|
_in: { id: tobeRemoved.map((r) => r.id) },
|
|
635
643
|
});
|
|
636
644
|
//-- collect uri to remove
|
|
@@ -655,8 +663,8 @@ export class ModelRepository extends AbstractRepository {
|
|
|
655
663
|
}
|
|
656
664
|
if (localeUriLocalEntryIds.length) {
|
|
657
665
|
//-- get all uris and add to remove list
|
|
658
|
-
const records = await
|
|
659
|
-
.use(LocaleTranslation)
|
|
666
|
+
const records = await this.db
|
|
667
|
+
.use(LocaleTranslation, tx)
|
|
660
668
|
.getRecords({ _in: { entryId: localeUriLocalEntryIds } }, { projection: ["translation"] });
|
|
661
669
|
for (const record of records) {
|
|
662
670
|
if (record.translation) {
|
|
@@ -671,7 +679,7 @@ export class ModelRepository extends AbstractRepository {
|
|
|
671
679
|
.filter((id) => !!id);
|
|
672
680
|
//-- remove locale entry, will cascade locale translations
|
|
673
681
|
if (localeEntryIds.length) {
|
|
674
|
-
await
|
|
682
|
+
await this.db.use(LocaleEntry, tx).deleteMany({ _in: { id: localeEntryIds } });
|
|
675
683
|
}
|
|
676
684
|
//-- remove uris
|
|
677
685
|
if (toBeRemovedUris.length) {
|
|
@@ -683,7 +691,7 @@ export class ModelRepository extends AbstractRepository {
|
|
|
683
691
|
returning = tobeRemoved;
|
|
684
692
|
}
|
|
685
693
|
else {
|
|
686
|
-
returning = await
|
|
694
|
+
returning = await this.db.use(this.model, tx).deleteMany(condition, queries?.returning);
|
|
687
695
|
}
|
|
688
696
|
return { modified: returning };
|
|
689
697
|
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CustomJobInfo } from "./interfaces";
|
|
1
|
+
import { type ITransaction } from "@clairejs/orm";
|
|
2
|
+
import { type CustomJobInfo } from "./interfaces";
|
|
3
3
|
export declare abstract class AbstractJobRepository<T extends CustomJobInfo> {
|
|
4
4
|
/**
|
|
5
5
|
* Return all persisted jobs
|
|
6
6
|
*/
|
|
7
|
-
abstract getJobs(
|
|
7
|
+
abstract getJobs(): Promise<T[]>;
|
|
8
8
|
/**
|
|
9
9
|
* Save the job info and return a unique id
|
|
10
10
|
* @param jobInfo The custom job info to save
|
|
11
11
|
*/
|
|
12
|
-
abstract saveJob(jobInfo: T,
|
|
12
|
+
abstract saveJob(jobInfo: T, tx?: ITransaction): Promise<string>;
|
|
13
13
|
/**
|
|
14
14
|
* Remove job info by id
|
|
15
15
|
* @param id Unique id of job
|
|
16
16
|
*/
|
|
17
|
-
abstract removeJobById(id: string,
|
|
17
|
+
abstract removeJobById(id: string, tx?: ITransaction): Promise<void>;
|
|
18
18
|
}
|
|
@@ -180,7 +180,7 @@ let LocalJobScheduler = class LocalJobScheduler extends AbstractJobScheduler {
|
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
182
|
//-- re-schedule jobs that are stored in repo
|
|
183
|
-
const allPersistedJobs = await this.jobRepo.getJobs(
|
|
183
|
+
const allPersistedJobs = await this.jobRepo.getJobs();
|
|
184
184
|
//-- run job anyway, expired job will be removed then
|
|
185
185
|
for (const job of allPersistedJobs) {
|
|
186
186
|
await this.scheduleJob(job);
|
|
@@ -205,7 +205,7 @@ let LocalJobScheduler = class LocalJobScheduler extends AbstractJobScheduler {
|
|
|
205
205
|
jobName: jobInfo.jobName,
|
|
206
206
|
params: jobInfo.params,
|
|
207
207
|
at: jobInfo.at,
|
|
208
|
-
}
|
|
208
|
+
}));
|
|
209
209
|
//-- use the lib
|
|
210
210
|
const scheduledJob = { ...jobInfo, id };
|
|
211
211
|
const timeout = setTimeout(() => {
|
|
@@ -256,7 +256,7 @@ let LocalJobScheduler = class LocalJobScheduler extends AbstractJobScheduler {
|
|
|
256
256
|
this.jobHolder[id] = undefined;
|
|
257
257
|
}
|
|
258
258
|
//-- remove from persistence
|
|
259
|
-
await this.jobRepo.removeJobById(id
|
|
259
|
+
await this.jobRepo.removeJobById(id);
|
|
260
260
|
}
|
|
261
261
|
else {
|
|
262
262
|
//-- get unique message id
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { AbstractModel, Constructor } from "@clairejs/core";
|
|
2
|
-
import {
|
|
2
|
+
import { type ITransaction, AbstractDbAdapter } from "@clairejs/orm";
|
|
3
3
|
import { CustomJobInfo } from "./interfaces";
|
|
4
4
|
import { AbstractJobRepository } from "./AbstractJobRepository";
|
|
5
5
|
export declare class DefaultJobRepository<T extends CustomJobInfo & AbstractModel> extends AbstractJobRepository<T> {
|
|
6
6
|
protected readonly model: Constructor<T>;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
protected db: AbstractDbAdapter;
|
|
8
|
+
constructor(model: Constructor<T>, db: AbstractDbAdapter);
|
|
9
|
+
getJobs(): Promise<T[]>;
|
|
10
|
+
saveJob({ id, ...jobInfo }: T, tx?: ITransaction): Promise<string>;
|
|
11
|
+
removeJobById(id: string, tx?: ITransaction): Promise<void>;
|
|
11
12
|
}
|
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
import { AbstractJobRepository } from "./AbstractJobRepository";
|
|
2
2
|
export class DefaultJobRepository extends AbstractJobRepository {
|
|
3
3
|
model;
|
|
4
|
-
|
|
4
|
+
db;
|
|
5
|
+
constructor(model, db) {
|
|
5
6
|
super();
|
|
6
7
|
this.model = model;
|
|
8
|
+
this.db = db;
|
|
7
9
|
}
|
|
8
|
-
async getJobs(
|
|
9
|
-
const jobs = await
|
|
10
|
+
async getJobs() {
|
|
11
|
+
const jobs = await this.db.use(this.model).getRecords();
|
|
10
12
|
return jobs;
|
|
11
13
|
}
|
|
12
|
-
async saveJob({ id, ...jobInfo },
|
|
14
|
+
async saveJob({ id, ...jobInfo }, tx) {
|
|
13
15
|
if (id) {
|
|
14
16
|
//-- update
|
|
15
|
-
await
|
|
17
|
+
await this.db.use(this.model, tx).updateById(id, jobInfo);
|
|
16
18
|
}
|
|
17
19
|
else {
|
|
18
20
|
//-- create new
|
|
19
|
-
const job = await
|
|
21
|
+
const job = await this.db.use(this.model, tx).createOne(jobInfo);
|
|
20
22
|
id = job.id;
|
|
21
23
|
}
|
|
22
24
|
return id;
|
|
23
25
|
}
|
|
24
|
-
async removeJobById(id,
|
|
25
|
-
await
|
|
26
|
+
async removeJobById(id, tx) {
|
|
27
|
+
await this.db.use(this.model, tx).deleteById(id);
|
|
26
28
|
}
|
|
27
29
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clairejs/server",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.19.1",
|
|
4
4
|
"description": "Claire server NodeJs framework written in Typescript.",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@clairejs/core": "^3.7.9",
|
|
37
|
-
"@clairejs/orm": "^3.
|
|
37
|
+
"@clairejs/orm": "^3.15.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/cookie-parser": "^1.4.3",
|