av6-core 1.2.0 → 1.2.2
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/index.d.mts +18 -19
- package/dist/index.d.ts +18 -19
- package/dist/index.js +436 -40
- package/dist/index.mjs +436 -40
- package/package.json +4 -3
package/dist/index.d.mts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import * as PrismaNamespace from '@prisma/client';
|
|
2
|
-
import { PrismaClient } from '@prisma/client';
|
|
3
1
|
import winston from 'winston';
|
|
4
2
|
import { AsyncLocalStorage } from 'async_hooks';
|
|
5
3
|
import { Readable } from 'stream';
|
|
6
4
|
import { JsonValue } from '@prisma/client/runtime/library';
|
|
7
5
|
import ExcelJs from 'exceljs';
|
|
8
6
|
import { AxiosResponse } from 'axios';
|
|
7
|
+
import * as PrismaNamespace from '@prisma/client';
|
|
8
|
+
import { PrismaClient, Prisma } from '@prisma/client';
|
|
9
9
|
|
|
10
10
|
declare enum ErrorMessageType {
|
|
11
11
|
INVALID_ID = "Invalid id: %1 Numeric value expected.",
|
|
@@ -29,6 +29,8 @@ declare enum ErrorMessageType {
|
|
|
29
29
|
EXCEL = "No data found to be downloaded"
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
type TxClient = PrismaClient | Prisma.TransactionClient;
|
|
33
|
+
|
|
32
34
|
interface EmployeeCache {
|
|
33
35
|
id: number;
|
|
34
36
|
name: string;
|
|
@@ -102,6 +104,7 @@ type DynamicShortCode = {
|
|
|
102
104
|
permission?: string | null;
|
|
103
105
|
whereClause?: JsonValue | null;
|
|
104
106
|
selectClause?: JsonValue | null;
|
|
107
|
+
config?: unknown | null;
|
|
105
108
|
};
|
|
106
109
|
interface ExportExcel {
|
|
107
110
|
shortCode: string;
|
|
@@ -192,20 +195,13 @@ interface LockUnlockParams {
|
|
|
192
195
|
interface LockUnlockRequestRepository<T extends DynamicShortCode> extends LockUnlockParams {
|
|
193
196
|
shortCodeData: T;
|
|
194
197
|
}
|
|
195
|
-
interface
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
description?: string;
|
|
198
|
+
interface CommonCreateRequestRepository {
|
|
199
|
+
shortCodeData: DynamicShortCode;
|
|
200
|
+
body: Record<string, unknown>;
|
|
199
201
|
}
|
|
200
|
-
interface
|
|
201
|
-
shortCodeData: T;
|
|
202
|
-
}
|
|
203
|
-
interface CommonUpdateParams extends CommonCreateParams {
|
|
202
|
+
interface CommonUpdateRequestRepository extends CommonCreateRequestRepository {
|
|
204
203
|
id: number;
|
|
205
204
|
}
|
|
206
|
-
interface CommonUpdateRequestRepository<T extends DynamicShortCode> extends CommonUpdateParams {
|
|
207
|
-
shortCodeData: T;
|
|
208
|
-
}
|
|
209
205
|
interface PaginatedResponse<T> {
|
|
210
206
|
totalRecords: number;
|
|
211
207
|
currentPageNumber: number;
|
|
@@ -234,6 +230,7 @@ interface CacheAdapter {
|
|
|
234
230
|
updateCache(key: string, id: number | string, value: unknown): Promise<void>;
|
|
235
231
|
createCache(table: string, data: DataType[]): Promise<void>;
|
|
236
232
|
deleteCache(key: string, id: number | string): Promise<void>;
|
|
233
|
+
addToCache(key: string, id: number | string, data: unknown): Promise<void>;
|
|
237
234
|
}
|
|
238
235
|
interface Mapper {
|
|
239
236
|
dtoMapping: Record<string, DtoMappingFunction>;
|
|
@@ -276,7 +273,7 @@ interface Deps {
|
|
|
276
273
|
logger: winston.Logger;
|
|
277
274
|
cacheAdapter: CacheAdapter;
|
|
278
275
|
requestStorage: AsyncLocalStorage<Store>;
|
|
279
|
-
db:
|
|
276
|
+
db: TxClient;
|
|
280
277
|
}
|
|
281
278
|
interface CommonServiceResponse {
|
|
282
279
|
search: (searchParams: SearchRequestService<DynamicShortCode>) => Promise<unknown>;
|
|
@@ -290,8 +287,8 @@ interface CommonServiceResponse {
|
|
|
290
287
|
delete: (deleteParams: DeleteRequestRepository<DynamicShortCode>) => Promise<void>;
|
|
291
288
|
updateStatus: (updateStatusParams: UpdateStatusRequestRepository<DynamicShortCode>) => Promise<unknown>;
|
|
292
289
|
lockUnlock: (lockUnlockParams: LockUnlockRequestRepository<DynamicShortCode>) => Promise<unknown>;
|
|
293
|
-
create: (createParams: CommonCreateRequestRepository
|
|
294
|
-
update: (updateParams: CommonUpdateRequestRepository
|
|
290
|
+
create: (createParams: CommonCreateRequestRepository) => Promise<unknown>;
|
|
291
|
+
update: (updateParams: CommonUpdateRequestRepository) => Promise<unknown>;
|
|
295
292
|
fetchImageStream: (imageBaseUrl: string, fileName: string) => Promise<AxiosResponse<Readable>>;
|
|
296
293
|
}
|
|
297
294
|
|
|
@@ -434,14 +431,16 @@ declare class NotificationEmitter {
|
|
|
434
431
|
interface AuditContext {
|
|
435
432
|
userId: number | null;
|
|
436
433
|
traceId: string | null;
|
|
437
|
-
|
|
434
|
+
level1Id: number | null;
|
|
435
|
+
level2Id: number | null;
|
|
438
436
|
module: "OPD" | "PROCEDURE" | "GENERAL_BILL" | "PHARMACY" | "LAB" | "IPD";
|
|
439
437
|
}
|
|
440
438
|
type AuditContextProvider = () => AuditContext;
|
|
441
439
|
interface AuditLogPayload {
|
|
442
440
|
message: string;
|
|
443
441
|
type?: "INFO" | "CREATE" | "UPDATE" | "DELETE" | "ERROR";
|
|
444
|
-
|
|
442
|
+
level1Id?: number | null;
|
|
443
|
+
level2Id?: number | null;
|
|
445
444
|
extra?: Record<string, any>;
|
|
446
445
|
}
|
|
447
446
|
|
|
@@ -472,4 +471,4 @@ declare class AuditProxy {
|
|
|
472
471
|
createAuditedService<T extends object>(serviceName: string, service: T): T;
|
|
473
472
|
}
|
|
474
473
|
|
|
475
|
-
export { type AuditContext, type AuditContextProvider, AuditCore, type AuditLogPayload, AuditLogger, AuditProxy, type CacheAdapter, type CalculationRes, type ColValue, type
|
|
474
|
+
export { type AuditContext, type AuditContextProvider, AuditCore, type AuditLogPayload, AuditLogger, AuditProxy, type CacheAdapter, type CalculationRes, type ColValue, type CommonCreateRequestRepository, type CommonExcelRequest, type CommonFilterRequest, type CommonFilterWithDate, type CommonServiceResponse, type CommonUpdateRequestRepository, type Config, type Context, type CreateUINConfigRequest, type DataType, type DeleteParams, type DeleteRequestRepository, type Deps, type DropdownRequest, type DropdownRequestService, type DynamicShortCode, type EmitPayload, type EmployeeCache, type ExcelConfig, type ExportExcel, type ExportExcelRequestService, type FetchRequest, type FetchRequestRepository, type FixedSearchRequest, type FixedSearchRequestService, type Helpers, type ImportExcel, type ImportExcelRequestService, type LockUnlockParams, type LockUnlockRequestRepository, type Mapper, type NewFixedSearchRequest, type NewFixedSearchRequestService, type NewSearchRequest, NotificationEmitter, type PaginatedResponse, type Recipient, type SearchRequest, type SearchRequestService, type ServiceCacheAdapter, type Store, type ToggleActive, type UINConfigDTO, type UINPreviewRequest, type UINSegment, type UINSegmentType, type UIN_RESET_POLICY, type UinDeps, type UpdateStatusRequestRepository, type UpdateUINConfigRequest, type ValidationErrorItem, commonService, customOmit, findDifferences, fromTimestampToSqlDatetime, getDynamicValue, getPattern, interpolate, objectTo2DArray, toNumberOrNull, toUINConfigDTO, uinConfigService, type updateStatusParams };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import * as PrismaNamespace from '@prisma/client';
|
|
2
|
-
import { PrismaClient } from '@prisma/client';
|
|
3
1
|
import winston from 'winston';
|
|
4
2
|
import { AsyncLocalStorage } from 'async_hooks';
|
|
5
3
|
import { Readable } from 'stream';
|
|
6
4
|
import { JsonValue } from '@prisma/client/runtime/library';
|
|
7
5
|
import ExcelJs from 'exceljs';
|
|
8
6
|
import { AxiosResponse } from 'axios';
|
|
7
|
+
import * as PrismaNamespace from '@prisma/client';
|
|
8
|
+
import { PrismaClient, Prisma } from '@prisma/client';
|
|
9
9
|
|
|
10
10
|
declare enum ErrorMessageType {
|
|
11
11
|
INVALID_ID = "Invalid id: %1 Numeric value expected.",
|
|
@@ -29,6 +29,8 @@ declare enum ErrorMessageType {
|
|
|
29
29
|
EXCEL = "No data found to be downloaded"
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
type TxClient = PrismaClient | Prisma.TransactionClient;
|
|
33
|
+
|
|
32
34
|
interface EmployeeCache {
|
|
33
35
|
id: number;
|
|
34
36
|
name: string;
|
|
@@ -102,6 +104,7 @@ type DynamicShortCode = {
|
|
|
102
104
|
permission?: string | null;
|
|
103
105
|
whereClause?: JsonValue | null;
|
|
104
106
|
selectClause?: JsonValue | null;
|
|
107
|
+
config?: unknown | null;
|
|
105
108
|
};
|
|
106
109
|
interface ExportExcel {
|
|
107
110
|
shortCode: string;
|
|
@@ -192,20 +195,13 @@ interface LockUnlockParams {
|
|
|
192
195
|
interface LockUnlockRequestRepository<T extends DynamicShortCode> extends LockUnlockParams {
|
|
193
196
|
shortCodeData: T;
|
|
194
197
|
}
|
|
195
|
-
interface
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
description?: string;
|
|
198
|
+
interface CommonCreateRequestRepository {
|
|
199
|
+
shortCodeData: DynamicShortCode;
|
|
200
|
+
body: Record<string, unknown>;
|
|
199
201
|
}
|
|
200
|
-
interface
|
|
201
|
-
shortCodeData: T;
|
|
202
|
-
}
|
|
203
|
-
interface CommonUpdateParams extends CommonCreateParams {
|
|
202
|
+
interface CommonUpdateRequestRepository extends CommonCreateRequestRepository {
|
|
204
203
|
id: number;
|
|
205
204
|
}
|
|
206
|
-
interface CommonUpdateRequestRepository<T extends DynamicShortCode> extends CommonUpdateParams {
|
|
207
|
-
shortCodeData: T;
|
|
208
|
-
}
|
|
209
205
|
interface PaginatedResponse<T> {
|
|
210
206
|
totalRecords: number;
|
|
211
207
|
currentPageNumber: number;
|
|
@@ -234,6 +230,7 @@ interface CacheAdapter {
|
|
|
234
230
|
updateCache(key: string, id: number | string, value: unknown): Promise<void>;
|
|
235
231
|
createCache(table: string, data: DataType[]): Promise<void>;
|
|
236
232
|
deleteCache(key: string, id: number | string): Promise<void>;
|
|
233
|
+
addToCache(key: string, id: number | string, data: unknown): Promise<void>;
|
|
237
234
|
}
|
|
238
235
|
interface Mapper {
|
|
239
236
|
dtoMapping: Record<string, DtoMappingFunction>;
|
|
@@ -276,7 +273,7 @@ interface Deps {
|
|
|
276
273
|
logger: winston.Logger;
|
|
277
274
|
cacheAdapter: CacheAdapter;
|
|
278
275
|
requestStorage: AsyncLocalStorage<Store>;
|
|
279
|
-
db:
|
|
276
|
+
db: TxClient;
|
|
280
277
|
}
|
|
281
278
|
interface CommonServiceResponse {
|
|
282
279
|
search: (searchParams: SearchRequestService<DynamicShortCode>) => Promise<unknown>;
|
|
@@ -290,8 +287,8 @@ interface CommonServiceResponse {
|
|
|
290
287
|
delete: (deleteParams: DeleteRequestRepository<DynamicShortCode>) => Promise<void>;
|
|
291
288
|
updateStatus: (updateStatusParams: UpdateStatusRequestRepository<DynamicShortCode>) => Promise<unknown>;
|
|
292
289
|
lockUnlock: (lockUnlockParams: LockUnlockRequestRepository<DynamicShortCode>) => Promise<unknown>;
|
|
293
|
-
create: (createParams: CommonCreateRequestRepository
|
|
294
|
-
update: (updateParams: CommonUpdateRequestRepository
|
|
290
|
+
create: (createParams: CommonCreateRequestRepository) => Promise<unknown>;
|
|
291
|
+
update: (updateParams: CommonUpdateRequestRepository) => Promise<unknown>;
|
|
295
292
|
fetchImageStream: (imageBaseUrl: string, fileName: string) => Promise<AxiosResponse<Readable>>;
|
|
296
293
|
}
|
|
297
294
|
|
|
@@ -434,14 +431,16 @@ declare class NotificationEmitter {
|
|
|
434
431
|
interface AuditContext {
|
|
435
432
|
userId: number | null;
|
|
436
433
|
traceId: string | null;
|
|
437
|
-
|
|
434
|
+
level1Id: number | null;
|
|
435
|
+
level2Id: number | null;
|
|
438
436
|
module: "OPD" | "PROCEDURE" | "GENERAL_BILL" | "PHARMACY" | "LAB" | "IPD";
|
|
439
437
|
}
|
|
440
438
|
type AuditContextProvider = () => AuditContext;
|
|
441
439
|
interface AuditLogPayload {
|
|
442
440
|
message: string;
|
|
443
441
|
type?: "INFO" | "CREATE" | "UPDATE" | "DELETE" | "ERROR";
|
|
444
|
-
|
|
442
|
+
level1Id?: number | null;
|
|
443
|
+
level2Id?: number | null;
|
|
445
444
|
extra?: Record<string, any>;
|
|
446
445
|
}
|
|
447
446
|
|
|
@@ -472,4 +471,4 @@ declare class AuditProxy {
|
|
|
472
471
|
createAuditedService<T extends object>(serviceName: string, service: T): T;
|
|
473
472
|
}
|
|
474
473
|
|
|
475
|
-
export { type AuditContext, type AuditContextProvider, AuditCore, type AuditLogPayload, AuditLogger, AuditProxy, type CacheAdapter, type CalculationRes, type ColValue, type
|
|
474
|
+
export { type AuditContext, type AuditContextProvider, AuditCore, type AuditLogPayload, AuditLogger, AuditProxy, type CacheAdapter, type CalculationRes, type ColValue, type CommonCreateRequestRepository, type CommonExcelRequest, type CommonFilterRequest, type CommonFilterWithDate, type CommonServiceResponse, type CommonUpdateRequestRepository, type Config, type Context, type CreateUINConfigRequest, type DataType, type DeleteParams, type DeleteRequestRepository, type Deps, type DropdownRequest, type DropdownRequestService, type DynamicShortCode, type EmitPayload, type EmployeeCache, type ExcelConfig, type ExportExcel, type ExportExcelRequestService, type FetchRequest, type FetchRequestRepository, type FixedSearchRequest, type FixedSearchRequestService, type Helpers, type ImportExcel, type ImportExcelRequestService, type LockUnlockParams, type LockUnlockRequestRepository, type Mapper, type NewFixedSearchRequest, type NewFixedSearchRequestService, type NewSearchRequest, NotificationEmitter, type PaginatedResponse, type Recipient, type SearchRequest, type SearchRequestService, type ServiceCacheAdapter, type Store, type ToggleActive, type UINConfigDTO, type UINPreviewRequest, type UINSegment, type UINSegmentType, type UIN_RESET_POLICY, type UinDeps, type UpdateStatusRequestRepository, type UpdateUINConfigRequest, type ValidationErrorItem, commonService, customOmit, findDifferences, fromTimestampToSqlDatetime, getDynamicValue, getPattern, interpolate, objectTo2DArray, toNumberOrNull, toUINConfigDTO, uinConfigService, type updateStatusParams };
|
package/dist/index.js
CHANGED
|
@@ -458,39 +458,6 @@ var commonRepository = (serviceDeps) => {
|
|
|
458
458
|
logger.info("exiting::commonLock::repository");
|
|
459
459
|
return updatedRecord;
|
|
460
460
|
},
|
|
461
|
-
async commonCreate({ shortCodeData, value, description }) {
|
|
462
|
-
logger.info("entering::commonCreate::repository");
|
|
463
|
-
const tableName = shortCodeData.tableName;
|
|
464
|
-
const model = db[tableName];
|
|
465
|
-
if (!model) {
|
|
466
|
-
throw new ErrorHandler(400, generateErrorMessage("INVALID_TABLE"));
|
|
467
|
-
}
|
|
468
|
-
const results = model.create({
|
|
469
|
-
data: {
|
|
470
|
-
value,
|
|
471
|
-
description
|
|
472
|
-
}
|
|
473
|
-
});
|
|
474
|
-
logger.info("exiting::commonCreate::repository");
|
|
475
|
-
return results;
|
|
476
|
-
},
|
|
477
|
-
async commonUpdate({ id, shortCodeData, value, description }) {
|
|
478
|
-
logger.info("entering::commonUpdate::repository");
|
|
479
|
-
const tableName = shortCodeData.tableName;
|
|
480
|
-
const model = db[tableName];
|
|
481
|
-
if (!model) {
|
|
482
|
-
throw new ErrorHandler(400, generateErrorMessage("INVALID_TABLE"));
|
|
483
|
-
}
|
|
484
|
-
const results = model.update({
|
|
485
|
-
where: { id },
|
|
486
|
-
data: {
|
|
487
|
-
value,
|
|
488
|
-
description
|
|
489
|
-
}
|
|
490
|
-
});
|
|
491
|
-
logger.info("exiting::commonUpdate::repository");
|
|
492
|
-
return results;
|
|
493
|
-
},
|
|
494
461
|
async generateRootCondition({
|
|
495
462
|
fixedSearch,
|
|
496
463
|
fixedNotSearch
|
|
@@ -818,6 +785,382 @@ var commonRepository = (serviceDeps) => {
|
|
|
818
785
|
};
|
|
819
786
|
};
|
|
820
787
|
|
|
788
|
+
// src/utils/dynamicCreateUpdate.utils.ts
|
|
789
|
+
var isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
790
|
+
var getByPath = (root, path) => {
|
|
791
|
+
if (!path) return void 0;
|
|
792
|
+
const parts = path.split(".");
|
|
793
|
+
let cur = root;
|
|
794
|
+
for (const p of parts) {
|
|
795
|
+
if (!isRecord(cur)) return void 0;
|
|
796
|
+
cur = cur[p];
|
|
797
|
+
}
|
|
798
|
+
return cur;
|
|
799
|
+
};
|
|
800
|
+
var omitUndefined = (obj) => {
|
|
801
|
+
const out = {};
|
|
802
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
803
|
+
if (v !== void 0) out[k] = v;
|
|
804
|
+
}
|
|
805
|
+
return out;
|
|
806
|
+
};
|
|
807
|
+
|
|
808
|
+
// src/utils/dynamicPrismaBuilder.utils.ts
|
|
809
|
+
var resolveSrc = (f, env) => {
|
|
810
|
+
const src = f.src ?? `body.${f.name}`;
|
|
811
|
+
if (src.startsWith("body.")) return getByPath(env.body, src.slice(5));
|
|
812
|
+
if (src.startsWith("vars.")) return getByPath(env.ctx.vars ?? {}, src.slice(5));
|
|
813
|
+
if (src.startsWith("ctx.")) return getByPath(env.ctx, src.slice(4));
|
|
814
|
+
return void 0;
|
|
815
|
+
};
|
|
816
|
+
var setAudit = (cfg, op, out, ctx) => {
|
|
817
|
+
const createdByField = cfg.audit?.createdByField ?? "createdBy";
|
|
818
|
+
const updatedByField = cfg.audit?.updatedByField ?? "updatedBy";
|
|
819
|
+
if (op === "create" && ctx.userId != null) out[createdByField] = ctx.userId;
|
|
820
|
+
if (ctx.userId != null) out[updatedByField] = ctx.userId;
|
|
821
|
+
};
|
|
822
|
+
var buildScalarData = (cfg, op, env) => {
|
|
823
|
+
const out = {};
|
|
824
|
+
for (const f of cfg.fields) {
|
|
825
|
+
const dbKey = f.db ?? f.name;
|
|
826
|
+
const presence = f.presence[op];
|
|
827
|
+
if (presence === "forbidden") continue;
|
|
828
|
+
if (dbKey === cfg.primaryKey) continue;
|
|
829
|
+
const value = resolveSrc(f, env);
|
|
830
|
+
if (value === void 0) continue;
|
|
831
|
+
if (value === null && !f.allowNull) continue;
|
|
832
|
+
out[dbKey] = value;
|
|
833
|
+
}
|
|
834
|
+
setAudit(cfg, op, out, env.ctx);
|
|
835
|
+
return out;
|
|
836
|
+
};
|
|
837
|
+
var buildRelationWrite = (rel, op, env) => {
|
|
838
|
+
const raw = env.body[rel.name];
|
|
839
|
+
if (raw === void 0) return void 0;
|
|
840
|
+
const writeCfg = op === "create" ? rel.write.create : rel.write.update;
|
|
841
|
+
const itemPrimaryKey = writeCfg.itemPrimaryKey ?? "id";
|
|
842
|
+
const toItemData = (item, itemOp) => {
|
|
843
|
+
const itemBody = isRecord(item) ? item : {};
|
|
844
|
+
const itemOut = {};
|
|
845
|
+
for (const f of rel.items.fields) {
|
|
846
|
+
const dbKey = f.db ?? f.name;
|
|
847
|
+
const presence = f.presence[itemOp];
|
|
848
|
+
if (presence === "forbidden") continue;
|
|
849
|
+
if (dbKey === itemPrimaryKey) continue;
|
|
850
|
+
const v = itemBody[f.name];
|
|
851
|
+
if (v === void 0) continue;
|
|
852
|
+
if (v === null && !f.allowNull) continue;
|
|
853
|
+
itemOut[dbKey] = v;
|
|
854
|
+
}
|
|
855
|
+
if (rel.items.audit?.createdBy?.startsWith("ctx.") && env.ctx.userId != null) {
|
|
856
|
+
itemOut["createdBy"] = env.ctx.userId;
|
|
857
|
+
}
|
|
858
|
+
if (rel.items.audit?.updatedBy?.startsWith("ctx.") && env.ctx.userId != null) {
|
|
859
|
+
itemOut["updatedBy"] = env.ctx.userId;
|
|
860
|
+
}
|
|
861
|
+
return itemOut;
|
|
862
|
+
};
|
|
863
|
+
if (rel.kind === "one") {
|
|
864
|
+
const itemData = toItemData(raw, op);
|
|
865
|
+
if (op === "create") return { create: itemData };
|
|
866
|
+
if (writeCfg.strategy === "replace") return { delete: true, create: itemData };
|
|
867
|
+
if (writeCfg.strategy === "upsert")
|
|
868
|
+
return { upsert: { create: itemData, update: omitUndefined(itemData), where: {} } };
|
|
869
|
+
return { create: itemData };
|
|
870
|
+
}
|
|
871
|
+
const arr = Array.isArray(raw) ? raw : [];
|
|
872
|
+
const itemsCreate = arr.map((i) => toItemData(i, op));
|
|
873
|
+
if (op === "create") return { create: itemsCreate };
|
|
874
|
+
if (writeCfg.strategy === "replace") return { deleteMany: {}, create: itemsCreate };
|
|
875
|
+
if (writeCfg.strategy === "upsert") {
|
|
876
|
+
const incomingIds = [];
|
|
877
|
+
const upsertItems = [];
|
|
878
|
+
const createOnly = [];
|
|
879
|
+
for (const item of arr) {
|
|
880
|
+
const itemRec = isRecord(item) ? item : {};
|
|
881
|
+
const pk = itemRec[itemPrimaryKey];
|
|
882
|
+
const dataCreate = toItemData(itemRec, "create");
|
|
883
|
+
const dataUpdate = toItemData(itemRec, "update");
|
|
884
|
+
if (pk === void 0 || pk === null || pk === "") {
|
|
885
|
+
createOnly.push(dataCreate);
|
|
886
|
+
continue;
|
|
887
|
+
}
|
|
888
|
+
const pkNum = typeof pk === "string" ? Number(pk) : pk;
|
|
889
|
+
if (Number.isFinite(pkNum)) incomingIds.push(pkNum);
|
|
890
|
+
upsertItems.push({
|
|
891
|
+
where: { [itemPrimaryKey]: pkNum },
|
|
892
|
+
create: dataCreate,
|
|
893
|
+
update: omitUndefined(dataUpdate)
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
const payload = {};
|
|
897
|
+
if (upsertItems.length) payload.upsert = upsertItems;
|
|
898
|
+
if (createOnly.length) payload.create = createOnly;
|
|
899
|
+
const cfgAny = writeCfg;
|
|
900
|
+
const now = /* @__PURE__ */ new Date();
|
|
901
|
+
if (cfgAny.softDeleteMissing) {
|
|
902
|
+
const whereExtra = cfgAny.softDelete?.whereExtra ?? { isActive: true };
|
|
903
|
+
const data = {
|
|
904
|
+
...cfgAny.softDelete?.data ?? { isActive: false }
|
|
905
|
+
};
|
|
906
|
+
if (data.deletedAt === "now") data.deletedAt = now;
|
|
907
|
+
if (data.deletedBy === "ctx.userId") data.deletedBy = env.ctx.userId ?? void 0;
|
|
908
|
+
if (incomingIds.length > 0) {
|
|
909
|
+
payload.updateMany = [
|
|
910
|
+
{
|
|
911
|
+
where: {
|
|
912
|
+
...whereExtra,
|
|
913
|
+
createdAt: { lt: now },
|
|
914
|
+
[itemPrimaryKey]: { notIn: incomingIds }
|
|
915
|
+
},
|
|
916
|
+
data
|
|
917
|
+
}
|
|
918
|
+
];
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
return payload;
|
|
922
|
+
}
|
|
923
|
+
return { create: itemsCreate };
|
|
924
|
+
};
|
|
925
|
+
var buildPrismaData = (cfg, op, validatedBody, ctx) => {
|
|
926
|
+
const env = { body: validatedBody, ctx };
|
|
927
|
+
const out = buildScalarData(cfg, op, env);
|
|
928
|
+
for (const rel of cfg.relations ?? []) {
|
|
929
|
+
const write = buildRelationWrite(rel, op, env);
|
|
930
|
+
if (write) out[rel.name] = write;
|
|
931
|
+
}
|
|
932
|
+
return out;
|
|
933
|
+
};
|
|
934
|
+
|
|
935
|
+
// src/repository/commonCreateUpdate.repository.ts
|
|
936
|
+
var commonCreateUpdateRepository = (serviceDeps) => {
|
|
937
|
+
const { mappingExport, mappingImport, dtoMapping } = serviceDeps.mapper;
|
|
938
|
+
const db = serviceDeps.db;
|
|
939
|
+
const { generateErrorMessage, ErrorHandler } = serviceDeps.helpers;
|
|
940
|
+
const logger = serviceDeps.logger;
|
|
941
|
+
const createCache = serviceDeps.cacheAdapter.createCache;
|
|
942
|
+
const requestStorage = serviceDeps.requestStorage;
|
|
943
|
+
return {
|
|
944
|
+
// async commonCreate({
|
|
945
|
+
// pageNo = 1,
|
|
946
|
+
// pageSize = 10,
|
|
947
|
+
// searchText,
|
|
948
|
+
// sortBy,
|
|
949
|
+
// sortDir,
|
|
950
|
+
// searchColumns,
|
|
951
|
+
// shortCodeData,
|
|
952
|
+
// includes,
|
|
953
|
+
// }: SearchRequestService<DynamicShortCode>) {
|
|
954
|
+
// logger.info("entering::commonSearch::repository");
|
|
955
|
+
// const tableName = shortCodeData.tableName;
|
|
956
|
+
// const whereClause: { OR?: Array<Record<string, unknown>> } = {};
|
|
957
|
+
// if (searchText && searchColumns.length > 0) {
|
|
958
|
+
// // Build an array of sub-objects
|
|
959
|
+
// whereClause.OR = searchColumns.map((column: string) => {
|
|
960
|
+
// if (column.includes(".")) {
|
|
961
|
+
// const keys = column.split(".");
|
|
962
|
+
// return buildNestedCondition(keys, searchText);
|
|
963
|
+
// }
|
|
964
|
+
// return { [column]: { contains: searchText } };
|
|
965
|
+
// });
|
|
966
|
+
// // Then transform them
|
|
967
|
+
// whereClause.OR = transformData(whereClause.OR);
|
|
968
|
+
// }
|
|
969
|
+
// const orderByClause: Record<string, "asc" | "desc"> = {};
|
|
970
|
+
// if (sortBy && sortDir) {
|
|
971
|
+
// orderByClause[sortBy] = sortDir.toLowerCase() as "asc" | "desc";
|
|
972
|
+
// }
|
|
973
|
+
// const skip = (pageNo - 1) * pageSize;
|
|
974
|
+
// const take = pageSize;
|
|
975
|
+
// const model = db[tableName];
|
|
976
|
+
// if (!model) {
|
|
977
|
+
// throw new ErrorHandler(400, "Invalid mapping table name");
|
|
978
|
+
// }
|
|
979
|
+
// const query: QueryType = {
|
|
980
|
+
// where: whereClause,
|
|
981
|
+
// orderBy: orderByClause,
|
|
982
|
+
// skip,
|
|
983
|
+
// take,
|
|
984
|
+
// };
|
|
985
|
+
// if (includes) {
|
|
986
|
+
// query.include = includes;
|
|
987
|
+
// }
|
|
988
|
+
// const results = await model.findMany(query);
|
|
989
|
+
// const totalRecords = await model.count({ where: whereClause });
|
|
990
|
+
// const totalPages = Math.ceil(totalRecords / pageSize);
|
|
991
|
+
// const DTOClass = dtoMapping[shortCodeData.shortCode];
|
|
992
|
+
// if (shortCodeData.isDTO && DTOClass) {
|
|
993
|
+
// let DTOs = [];
|
|
994
|
+
// if (shortCodeData.isSingleDto === undefined || shortCodeData.isSingleDto === true) {
|
|
995
|
+
// DTOs = await Promise.all(results.map((record: unknown) => DTOClass(record)));
|
|
996
|
+
// } else {
|
|
997
|
+
// DTOs = await DTOClass(results);
|
|
998
|
+
// }
|
|
999
|
+
// return {
|
|
1000
|
+
// data: DTOs,
|
|
1001
|
+
// totalRecords,
|
|
1002
|
+
// currentPageNumber: pageNo,
|
|
1003
|
+
// pageSize,
|
|
1004
|
+
// lastPageNumber: totalPages,
|
|
1005
|
+
// };
|
|
1006
|
+
// }
|
|
1007
|
+
// logger.info("exiting::commonSearch::repository");
|
|
1008
|
+
// return {
|
|
1009
|
+
// data: results,
|
|
1010
|
+
// totalRecords,
|
|
1011
|
+
// currentPageNumber: pageNo,
|
|
1012
|
+
// pageSize,
|
|
1013
|
+
// lastPageNumber: totalPages,
|
|
1014
|
+
// };
|
|
1015
|
+
// },
|
|
1016
|
+
getDelegate(tableName) {
|
|
1017
|
+
const d = db[tableName];
|
|
1018
|
+
if (!d || typeof d !== "object") throw new ErrorHandler(400, "Invalid mapping table name");
|
|
1019
|
+
const del = d;
|
|
1020
|
+
if (typeof del.create !== "function" || typeof del.update !== "function" || typeof del.findFirst !== "function") {
|
|
1021
|
+
throw new ErrorHandler(400, "Invalid prisma delegate for tableName");
|
|
1022
|
+
}
|
|
1023
|
+
return del;
|
|
1024
|
+
},
|
|
1025
|
+
resolveUniqueWhere(u, vars, body, ctx) {
|
|
1026
|
+
const out = {};
|
|
1027
|
+
for (const c of u.where) {
|
|
1028
|
+
if (c.src.startsWith("vars.")) out[c.field] = (vars ?? {})[c.src.slice(5)];
|
|
1029
|
+
else if (c.src.startsWith("body.")) out[c.field] = (body ?? {})[c.src.slice(5)];
|
|
1030
|
+
else if (c.src.startsWith("ctx.")) out[c.field] = ctx[c.src.slice(4)];
|
|
1031
|
+
}
|
|
1032
|
+
return omitUndefined(out);
|
|
1033
|
+
},
|
|
1034
|
+
async runUniqueChecks(delegate, cfg, op, pkField, pkValue, body, ctx) {
|
|
1035
|
+
for (const u of cfg.uniques ?? []) {
|
|
1036
|
+
if (!u.op.includes(op)) continue;
|
|
1037
|
+
const where = this.resolveUniqueWhere(u, ctx.vars ?? {}, body, ctx);
|
|
1038
|
+
if (op === "update" && pkValue != null) {
|
|
1039
|
+
where["NOT"] = { [pkField]: pkValue };
|
|
1040
|
+
}
|
|
1041
|
+
if (!Object.keys(where).length) continue;
|
|
1042
|
+
const query = { where, select: { [pkField]: true } };
|
|
1043
|
+
console.log(query);
|
|
1044
|
+
const existing = await delegate.findFirst({ where, select: { [pkField]: true } });
|
|
1045
|
+
if (existing) throw new ErrorHandler(400, u.message);
|
|
1046
|
+
}
|
|
1047
|
+
},
|
|
1048
|
+
async commonCreate({ body, ctx, shortCodeData }) {
|
|
1049
|
+
if (!shortCodeData.config) throw new ErrorHandler(400, "ShortCode config missing");
|
|
1050
|
+
const cfg = shortCodeData.config;
|
|
1051
|
+
const delegate = this.getDelegate(shortCodeData.tableName);
|
|
1052
|
+
await this.runUniqueChecks(delegate, cfg, "create", cfg.primaryKey, void 0, body, ctx);
|
|
1053
|
+
const data = buildPrismaData(cfg, "create", body, ctx);
|
|
1054
|
+
const include = cfg.response?.include;
|
|
1055
|
+
const select = cfg.response?.select ?? void 0;
|
|
1056
|
+
return delegate.create({ data, include, select });
|
|
1057
|
+
},
|
|
1058
|
+
async commonUpdate({ body, ctx, id, shortCodeData }) {
|
|
1059
|
+
if (!shortCodeData.config) throw new ErrorHandler(400, "ShortCode config missing");
|
|
1060
|
+
const cfg = shortCodeData.config;
|
|
1061
|
+
const pk = cfg.primaryKey;
|
|
1062
|
+
if (cfg.operations.update.requirePrimaryKey && (id === void 0 || id === null || isNaN(Number(id)))) {
|
|
1063
|
+
throw new ErrorHandler(400, "Missing id for update");
|
|
1064
|
+
}
|
|
1065
|
+
const delegate = this.getDelegate(shortCodeData.tableName);
|
|
1066
|
+
await this.runUniqueChecks(delegate, cfg, "update", pk, id, body, ctx);
|
|
1067
|
+
const data = buildPrismaData(cfg, "update", body, ctx);
|
|
1068
|
+
const include = cfg.response?.include;
|
|
1069
|
+
const select = cfg.response?.select ?? void 0;
|
|
1070
|
+
return delegate.update({
|
|
1071
|
+
where: { [pk]: id },
|
|
1072
|
+
data,
|
|
1073
|
+
include,
|
|
1074
|
+
select
|
|
1075
|
+
});
|
|
1076
|
+
}
|
|
1077
|
+
};
|
|
1078
|
+
};
|
|
1079
|
+
|
|
1080
|
+
// src/utils/dynamicJoiBuilder.utils.ts
|
|
1081
|
+
var import_joi = __toESM(require("joi"));
|
|
1082
|
+
var buildScalar = (f) => {
|
|
1083
|
+
const rules = f.rules ?? {};
|
|
1084
|
+
let s;
|
|
1085
|
+
switch (f.type) {
|
|
1086
|
+
case "string": {
|
|
1087
|
+
let j = import_joi.default.string();
|
|
1088
|
+
if (rules.trim) j = j.trim();
|
|
1089
|
+
if (typeof rules.min === "number") j = j.min(rules.min);
|
|
1090
|
+
if (typeof rules.max === "number") j = j.max(rules.max);
|
|
1091
|
+
if (rules.regex) j = j.pattern(new RegExp(rules.regex));
|
|
1092
|
+
s = j;
|
|
1093
|
+
break;
|
|
1094
|
+
}
|
|
1095
|
+
case "number": {
|
|
1096
|
+
let j = import_joi.default.number();
|
|
1097
|
+
if (rules.integer) j = j.integer();
|
|
1098
|
+
if (typeof rules.min === "number") j = j.min(rules.min);
|
|
1099
|
+
if (typeof rules.max === "number") j = j.max(rules.max);
|
|
1100
|
+
s = j;
|
|
1101
|
+
break;
|
|
1102
|
+
}
|
|
1103
|
+
case "boolean":
|
|
1104
|
+
s = import_joi.default.boolean();
|
|
1105
|
+
break;
|
|
1106
|
+
case "date": {
|
|
1107
|
+
let j = import_joi.default.date();
|
|
1108
|
+
if (rules.iso) j = j.iso();
|
|
1109
|
+
s = j;
|
|
1110
|
+
break;
|
|
1111
|
+
}
|
|
1112
|
+
case "enum": {
|
|
1113
|
+
const values = rules.values ?? [];
|
|
1114
|
+
s = import_joi.default.string().valid(...values);
|
|
1115
|
+
break;
|
|
1116
|
+
}
|
|
1117
|
+
case "object":
|
|
1118
|
+
s = import_joi.default.object(rules.schema ?? {});
|
|
1119
|
+
break;
|
|
1120
|
+
case "array":
|
|
1121
|
+
s = import_joi.default.array();
|
|
1122
|
+
break;
|
|
1123
|
+
case "json":
|
|
1124
|
+
default:
|
|
1125
|
+
s = import_joi.default.any();
|
|
1126
|
+
}
|
|
1127
|
+
if (f.allowNull) s = s.allow(null);
|
|
1128
|
+
if (f.default !== void 0) s = s.default(f.default);
|
|
1129
|
+
if (f.messages) s = s.messages(f.messages);
|
|
1130
|
+
return s;
|
|
1131
|
+
};
|
|
1132
|
+
var applyPresence = (schema, presence) => {
|
|
1133
|
+
if (presence === "required") return schema.required();
|
|
1134
|
+
if (presence === "forbidden") return schema.forbidden();
|
|
1135
|
+
return schema.optional();
|
|
1136
|
+
};
|
|
1137
|
+
var buildRelationSchema = (rel, op) => {
|
|
1138
|
+
const itemShape = {};
|
|
1139
|
+
for (const f of rel.items.fields) {
|
|
1140
|
+
const scalar = buildScalar(f);
|
|
1141
|
+
itemShape[f.name] = applyPresence(scalar, f.presence[op]);
|
|
1142
|
+
}
|
|
1143
|
+
const itemSchema = import_joi.default.object(itemShape);
|
|
1144
|
+
const base = rel.kind === "many" ? import_joi.default.array().items(itemSchema) : itemSchema;
|
|
1145
|
+
return applyPresence(base, rel.presence[op]);
|
|
1146
|
+
};
|
|
1147
|
+
var buildJoiSchemaForOp = (cfg, op) => {
|
|
1148
|
+
const shape = {};
|
|
1149
|
+
for (const f of cfg.fields) {
|
|
1150
|
+
const scalar = buildScalar(f);
|
|
1151
|
+
shape[f.name] = applyPresence(scalar, f.presence[op]);
|
|
1152
|
+
}
|
|
1153
|
+
for (const rel of cfg.relations ?? []) {
|
|
1154
|
+
shape[rel.name] = buildRelationSchema(rel, op);
|
|
1155
|
+
}
|
|
1156
|
+
return import_joi.default.object(shape).prefs({
|
|
1157
|
+
abortEarly: cfg.validation.abortEarly,
|
|
1158
|
+
allowUnknown: cfg.validation.allowUnknown,
|
|
1159
|
+
stripUnknown: cfg.validation.stripUnknown,
|
|
1160
|
+
convert: cfg.validation.convert
|
|
1161
|
+
});
|
|
1162
|
+
};
|
|
1163
|
+
|
|
821
1164
|
// src/utils/helper.utils.ts
|
|
822
1165
|
function customOmit(obj, keys) {
|
|
823
1166
|
const rest = { ...obj };
|
|
@@ -944,11 +1287,13 @@ var import_exceljs = __toESM(require("exceljs"));
|
|
|
944
1287
|
var commonService = (serviceDeps) => {
|
|
945
1288
|
const generateErrorMessage = serviceDeps.helpers.generateErrorMessage;
|
|
946
1289
|
const ErrorHandler = serviceDeps.helpers.ErrorHandler;
|
|
947
|
-
const { deleteCache, getCacheById, updateCache, createCache } = serviceDeps.cacheAdapter;
|
|
1290
|
+
const { deleteCache, getCacheById, updateCache, createCache, addToCache } = serviceDeps.cacheAdapter;
|
|
948
1291
|
const logger = serviceDeps.logger;
|
|
949
1292
|
const dtoMapping = serviceDeps.mapper.dtoMapping;
|
|
950
1293
|
const { REDIS_PREFIX, CACHE_KEY_NAME } = serviceDeps.config;
|
|
951
1294
|
const commonRepositoryFactory = commonRepository(serviceDeps);
|
|
1295
|
+
const commonCreateUpdateRepositoryFactory = commonCreateUpdateRepository(serviceDeps);
|
|
1296
|
+
const requestStorage = serviceDeps.requestStorage;
|
|
952
1297
|
return {
|
|
953
1298
|
async search(searchParams) {
|
|
954
1299
|
logger.info("entering::search::service");
|
|
@@ -1188,18 +1533,55 @@ var commonService = (serviceDeps) => {
|
|
|
1188
1533
|
},
|
|
1189
1534
|
async create(createParams) {
|
|
1190
1535
|
logger.info("entering::create::service");
|
|
1536
|
+
const store = requestStorage.getStore();
|
|
1537
|
+
const currentUser = store?.user?.id ?? null;
|
|
1191
1538
|
const shortCodeData = createParams.shortCodeData;
|
|
1192
|
-
const
|
|
1539
|
+
const cfg = shortCodeData.config;
|
|
1540
|
+
const ctx = { userId: currentUser ?? void 0, vars: {} };
|
|
1541
|
+
const schema = buildJoiSchemaForOp(cfg, "create");
|
|
1542
|
+
const validated = await schema.validateAsync(createParams.body);
|
|
1543
|
+
const createResult = await commonCreateUpdateRepositoryFactory.commonCreate({
|
|
1544
|
+
body: validated,
|
|
1545
|
+
ctx,
|
|
1546
|
+
shortCodeData
|
|
1547
|
+
});
|
|
1193
1548
|
if (shortCodeData.isCacheable) {
|
|
1194
|
-
await
|
|
1549
|
+
await addToCache(
|
|
1550
|
+
`${REDIS_PREFIX}${CACHE_KEY_NAME}:${shortCodeData.tableName}:all`,
|
|
1551
|
+
createResult[cfg.primaryKey],
|
|
1552
|
+
createResult
|
|
1553
|
+
);
|
|
1554
|
+
}
|
|
1555
|
+
if (shortCodeData.isDTO && dtoMapping[shortCodeData.shortCode]) {
|
|
1556
|
+
let dtoResult;
|
|
1557
|
+
if (shortCodeData.isSingleDto === void 0 || shortCodeData.isSingleDto === true) {
|
|
1558
|
+
dtoResult = await dtoMapping[shortCodeData.shortCode](createResult);
|
|
1559
|
+
} else {
|
|
1560
|
+
dtoResult = (await dtoMapping[shortCodeData.shortCode]([createResult]))?.[0];
|
|
1561
|
+
}
|
|
1562
|
+
if (!dtoResult) {
|
|
1563
|
+
throw new ErrorHandler(404, generateErrorMessage("NOT_FOUND", `${shortCodeData.tableName}`));
|
|
1564
|
+
}
|
|
1565
|
+
return dtoResult;
|
|
1195
1566
|
}
|
|
1196
1567
|
logger.info("exiting::create::service");
|
|
1197
1568
|
return createResult;
|
|
1198
1569
|
},
|
|
1199
1570
|
async update(updateParams) {
|
|
1200
1571
|
logger.info("entering::update::service");
|
|
1572
|
+
const store = requestStorage.getStore();
|
|
1573
|
+
const currentUser = store?.user?.id ?? null;
|
|
1201
1574
|
const shortCodeData = updateParams.shortCodeData;
|
|
1202
|
-
const
|
|
1575
|
+
const cfg = shortCodeData.config;
|
|
1576
|
+
const ctx = { userId: currentUser ?? void 0, vars: {} };
|
|
1577
|
+
const schema = buildJoiSchemaForOp(cfg, "update");
|
|
1578
|
+
const validated = await schema.validateAsync(updateParams.body);
|
|
1579
|
+
const updateResult = await commonCreateUpdateRepositoryFactory.commonUpdate({
|
|
1580
|
+
body: validated,
|
|
1581
|
+
ctx,
|
|
1582
|
+
shortCodeData,
|
|
1583
|
+
id: updateParams.id
|
|
1584
|
+
});
|
|
1203
1585
|
if (shortCodeData.isCacheable) {
|
|
1204
1586
|
await updateCache(
|
|
1205
1587
|
`${REDIS_PREFIX}${CACHE_KEY_NAME}:${shortCodeData.tableName}:all`,
|
|
@@ -1207,6 +1589,18 @@ var commonService = (serviceDeps) => {
|
|
|
1207
1589
|
updateResult
|
|
1208
1590
|
);
|
|
1209
1591
|
}
|
|
1592
|
+
if (shortCodeData.isDTO && dtoMapping[shortCodeData.shortCode]) {
|
|
1593
|
+
let dtoResult;
|
|
1594
|
+
if (shortCodeData.isSingleDto === void 0 || shortCodeData.isSingleDto === true) {
|
|
1595
|
+
dtoResult = await dtoMapping[shortCodeData.shortCode](updateResult);
|
|
1596
|
+
} else {
|
|
1597
|
+
dtoResult = (await dtoMapping[shortCodeData.shortCode]([updateResult]))?.[0];
|
|
1598
|
+
}
|
|
1599
|
+
if (!dtoResult) {
|
|
1600
|
+
throw new ErrorHandler(404, generateErrorMessage("NOT_FOUND", `${shortCodeData.tableName}`));
|
|
1601
|
+
}
|
|
1602
|
+
return dtoResult;
|
|
1603
|
+
}
|
|
1210
1604
|
logger.info("exiting::update::service");
|
|
1211
1605
|
return updateResult;
|
|
1212
1606
|
},
|
|
@@ -2126,7 +2520,7 @@ var AuditLogger = class {
|
|
|
2126
2520
|
async logIfEnabled(params) {
|
|
2127
2521
|
const { service, method, payload } = params;
|
|
2128
2522
|
const prisma = this.core.getPrisma();
|
|
2129
|
-
const { userId, traceId,
|
|
2523
|
+
const { userId, traceId, level1Id: ctxLvl1Id, level2Id: ctxLvl2Id, module: module2 } = this.core.getContext();
|
|
2130
2524
|
try {
|
|
2131
2525
|
const config = await prisma.auditConfig.findFirst({
|
|
2132
2526
|
where: {
|
|
@@ -2141,14 +2535,16 @@ var AuditLogger = class {
|
|
|
2141
2535
|
}
|
|
2142
2536
|
const message = payload.type === "ERROR" ? payload.message : config.message;
|
|
2143
2537
|
const type = payload.type ?? "INFO";
|
|
2144
|
-
const
|
|
2538
|
+
const level1Id = payload.level1Id ?? ctxLvl1Id ?? 0;
|
|
2539
|
+
const level2Id = payload.level2Id ?? ctxLvl2Id ?? 0;
|
|
2145
2540
|
await prisma.commonAudit.create({
|
|
2146
2541
|
data: {
|
|
2147
2542
|
service,
|
|
2148
2543
|
module: module2,
|
|
2149
2544
|
type,
|
|
2150
2545
|
message,
|
|
2151
|
-
|
|
2546
|
+
level1Id,
|
|
2547
|
+
level2Id,
|
|
2152
2548
|
methodName: method,
|
|
2153
2549
|
traceId,
|
|
2154
2550
|
createdBy: userId ?? void 0
|
package/dist/index.mjs
CHANGED
|
@@ -408,39 +408,6 @@ var commonRepository = (serviceDeps) => {
|
|
|
408
408
|
logger.info("exiting::commonLock::repository");
|
|
409
409
|
return updatedRecord;
|
|
410
410
|
},
|
|
411
|
-
async commonCreate({ shortCodeData, value, description }) {
|
|
412
|
-
logger.info("entering::commonCreate::repository");
|
|
413
|
-
const tableName = shortCodeData.tableName;
|
|
414
|
-
const model = db[tableName];
|
|
415
|
-
if (!model) {
|
|
416
|
-
throw new ErrorHandler(400, generateErrorMessage("INVALID_TABLE"));
|
|
417
|
-
}
|
|
418
|
-
const results = model.create({
|
|
419
|
-
data: {
|
|
420
|
-
value,
|
|
421
|
-
description
|
|
422
|
-
}
|
|
423
|
-
});
|
|
424
|
-
logger.info("exiting::commonCreate::repository");
|
|
425
|
-
return results;
|
|
426
|
-
},
|
|
427
|
-
async commonUpdate({ id, shortCodeData, value, description }) {
|
|
428
|
-
logger.info("entering::commonUpdate::repository");
|
|
429
|
-
const tableName = shortCodeData.tableName;
|
|
430
|
-
const model = db[tableName];
|
|
431
|
-
if (!model) {
|
|
432
|
-
throw new ErrorHandler(400, generateErrorMessage("INVALID_TABLE"));
|
|
433
|
-
}
|
|
434
|
-
const results = model.update({
|
|
435
|
-
where: { id },
|
|
436
|
-
data: {
|
|
437
|
-
value,
|
|
438
|
-
description
|
|
439
|
-
}
|
|
440
|
-
});
|
|
441
|
-
logger.info("exiting::commonUpdate::repository");
|
|
442
|
-
return results;
|
|
443
|
-
},
|
|
444
411
|
async generateRootCondition({
|
|
445
412
|
fixedSearch,
|
|
446
413
|
fixedNotSearch
|
|
@@ -768,6 +735,382 @@ var commonRepository = (serviceDeps) => {
|
|
|
768
735
|
};
|
|
769
736
|
};
|
|
770
737
|
|
|
738
|
+
// src/utils/dynamicCreateUpdate.utils.ts
|
|
739
|
+
var isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
740
|
+
var getByPath = (root, path) => {
|
|
741
|
+
if (!path) return void 0;
|
|
742
|
+
const parts = path.split(".");
|
|
743
|
+
let cur = root;
|
|
744
|
+
for (const p of parts) {
|
|
745
|
+
if (!isRecord(cur)) return void 0;
|
|
746
|
+
cur = cur[p];
|
|
747
|
+
}
|
|
748
|
+
return cur;
|
|
749
|
+
};
|
|
750
|
+
var omitUndefined = (obj) => {
|
|
751
|
+
const out = {};
|
|
752
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
753
|
+
if (v !== void 0) out[k] = v;
|
|
754
|
+
}
|
|
755
|
+
return out;
|
|
756
|
+
};
|
|
757
|
+
|
|
758
|
+
// src/utils/dynamicPrismaBuilder.utils.ts
|
|
759
|
+
var resolveSrc = (f, env) => {
|
|
760
|
+
const src = f.src ?? `body.${f.name}`;
|
|
761
|
+
if (src.startsWith("body.")) return getByPath(env.body, src.slice(5));
|
|
762
|
+
if (src.startsWith("vars.")) return getByPath(env.ctx.vars ?? {}, src.slice(5));
|
|
763
|
+
if (src.startsWith("ctx.")) return getByPath(env.ctx, src.slice(4));
|
|
764
|
+
return void 0;
|
|
765
|
+
};
|
|
766
|
+
var setAudit = (cfg, op, out, ctx) => {
|
|
767
|
+
const createdByField = cfg.audit?.createdByField ?? "createdBy";
|
|
768
|
+
const updatedByField = cfg.audit?.updatedByField ?? "updatedBy";
|
|
769
|
+
if (op === "create" && ctx.userId != null) out[createdByField] = ctx.userId;
|
|
770
|
+
if (ctx.userId != null) out[updatedByField] = ctx.userId;
|
|
771
|
+
};
|
|
772
|
+
var buildScalarData = (cfg, op, env) => {
|
|
773
|
+
const out = {};
|
|
774
|
+
for (const f of cfg.fields) {
|
|
775
|
+
const dbKey = f.db ?? f.name;
|
|
776
|
+
const presence = f.presence[op];
|
|
777
|
+
if (presence === "forbidden") continue;
|
|
778
|
+
if (dbKey === cfg.primaryKey) continue;
|
|
779
|
+
const value = resolveSrc(f, env);
|
|
780
|
+
if (value === void 0) continue;
|
|
781
|
+
if (value === null && !f.allowNull) continue;
|
|
782
|
+
out[dbKey] = value;
|
|
783
|
+
}
|
|
784
|
+
setAudit(cfg, op, out, env.ctx);
|
|
785
|
+
return out;
|
|
786
|
+
};
|
|
787
|
+
var buildRelationWrite = (rel, op, env) => {
|
|
788
|
+
const raw = env.body[rel.name];
|
|
789
|
+
if (raw === void 0) return void 0;
|
|
790
|
+
const writeCfg = op === "create" ? rel.write.create : rel.write.update;
|
|
791
|
+
const itemPrimaryKey = writeCfg.itemPrimaryKey ?? "id";
|
|
792
|
+
const toItemData = (item, itemOp) => {
|
|
793
|
+
const itemBody = isRecord(item) ? item : {};
|
|
794
|
+
const itemOut = {};
|
|
795
|
+
for (const f of rel.items.fields) {
|
|
796
|
+
const dbKey = f.db ?? f.name;
|
|
797
|
+
const presence = f.presence[itemOp];
|
|
798
|
+
if (presence === "forbidden") continue;
|
|
799
|
+
if (dbKey === itemPrimaryKey) continue;
|
|
800
|
+
const v = itemBody[f.name];
|
|
801
|
+
if (v === void 0) continue;
|
|
802
|
+
if (v === null && !f.allowNull) continue;
|
|
803
|
+
itemOut[dbKey] = v;
|
|
804
|
+
}
|
|
805
|
+
if (rel.items.audit?.createdBy?.startsWith("ctx.") && env.ctx.userId != null) {
|
|
806
|
+
itemOut["createdBy"] = env.ctx.userId;
|
|
807
|
+
}
|
|
808
|
+
if (rel.items.audit?.updatedBy?.startsWith("ctx.") && env.ctx.userId != null) {
|
|
809
|
+
itemOut["updatedBy"] = env.ctx.userId;
|
|
810
|
+
}
|
|
811
|
+
return itemOut;
|
|
812
|
+
};
|
|
813
|
+
if (rel.kind === "one") {
|
|
814
|
+
const itemData = toItemData(raw, op);
|
|
815
|
+
if (op === "create") return { create: itemData };
|
|
816
|
+
if (writeCfg.strategy === "replace") return { delete: true, create: itemData };
|
|
817
|
+
if (writeCfg.strategy === "upsert")
|
|
818
|
+
return { upsert: { create: itemData, update: omitUndefined(itemData), where: {} } };
|
|
819
|
+
return { create: itemData };
|
|
820
|
+
}
|
|
821
|
+
const arr = Array.isArray(raw) ? raw : [];
|
|
822
|
+
const itemsCreate = arr.map((i) => toItemData(i, op));
|
|
823
|
+
if (op === "create") return { create: itemsCreate };
|
|
824
|
+
if (writeCfg.strategy === "replace") return { deleteMany: {}, create: itemsCreate };
|
|
825
|
+
if (writeCfg.strategy === "upsert") {
|
|
826
|
+
const incomingIds = [];
|
|
827
|
+
const upsertItems = [];
|
|
828
|
+
const createOnly = [];
|
|
829
|
+
for (const item of arr) {
|
|
830
|
+
const itemRec = isRecord(item) ? item : {};
|
|
831
|
+
const pk = itemRec[itemPrimaryKey];
|
|
832
|
+
const dataCreate = toItemData(itemRec, "create");
|
|
833
|
+
const dataUpdate = toItemData(itemRec, "update");
|
|
834
|
+
if (pk === void 0 || pk === null || pk === "") {
|
|
835
|
+
createOnly.push(dataCreate);
|
|
836
|
+
continue;
|
|
837
|
+
}
|
|
838
|
+
const pkNum = typeof pk === "string" ? Number(pk) : pk;
|
|
839
|
+
if (Number.isFinite(pkNum)) incomingIds.push(pkNum);
|
|
840
|
+
upsertItems.push({
|
|
841
|
+
where: { [itemPrimaryKey]: pkNum },
|
|
842
|
+
create: dataCreate,
|
|
843
|
+
update: omitUndefined(dataUpdate)
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
const payload = {};
|
|
847
|
+
if (upsertItems.length) payload.upsert = upsertItems;
|
|
848
|
+
if (createOnly.length) payload.create = createOnly;
|
|
849
|
+
const cfgAny = writeCfg;
|
|
850
|
+
const now = /* @__PURE__ */ new Date();
|
|
851
|
+
if (cfgAny.softDeleteMissing) {
|
|
852
|
+
const whereExtra = cfgAny.softDelete?.whereExtra ?? { isActive: true };
|
|
853
|
+
const data = {
|
|
854
|
+
...cfgAny.softDelete?.data ?? { isActive: false }
|
|
855
|
+
};
|
|
856
|
+
if (data.deletedAt === "now") data.deletedAt = now;
|
|
857
|
+
if (data.deletedBy === "ctx.userId") data.deletedBy = env.ctx.userId ?? void 0;
|
|
858
|
+
if (incomingIds.length > 0) {
|
|
859
|
+
payload.updateMany = [
|
|
860
|
+
{
|
|
861
|
+
where: {
|
|
862
|
+
...whereExtra,
|
|
863
|
+
createdAt: { lt: now },
|
|
864
|
+
[itemPrimaryKey]: { notIn: incomingIds }
|
|
865
|
+
},
|
|
866
|
+
data
|
|
867
|
+
}
|
|
868
|
+
];
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
return payload;
|
|
872
|
+
}
|
|
873
|
+
return { create: itemsCreate };
|
|
874
|
+
};
|
|
875
|
+
var buildPrismaData = (cfg, op, validatedBody, ctx) => {
|
|
876
|
+
const env = { body: validatedBody, ctx };
|
|
877
|
+
const out = buildScalarData(cfg, op, env);
|
|
878
|
+
for (const rel of cfg.relations ?? []) {
|
|
879
|
+
const write = buildRelationWrite(rel, op, env);
|
|
880
|
+
if (write) out[rel.name] = write;
|
|
881
|
+
}
|
|
882
|
+
return out;
|
|
883
|
+
};
|
|
884
|
+
|
|
885
|
+
// src/repository/commonCreateUpdate.repository.ts
|
|
886
|
+
var commonCreateUpdateRepository = (serviceDeps) => {
|
|
887
|
+
const { mappingExport, mappingImport, dtoMapping } = serviceDeps.mapper;
|
|
888
|
+
const db = serviceDeps.db;
|
|
889
|
+
const { generateErrorMessage, ErrorHandler } = serviceDeps.helpers;
|
|
890
|
+
const logger = serviceDeps.logger;
|
|
891
|
+
const createCache = serviceDeps.cacheAdapter.createCache;
|
|
892
|
+
const requestStorage = serviceDeps.requestStorage;
|
|
893
|
+
return {
|
|
894
|
+
// async commonCreate({
|
|
895
|
+
// pageNo = 1,
|
|
896
|
+
// pageSize = 10,
|
|
897
|
+
// searchText,
|
|
898
|
+
// sortBy,
|
|
899
|
+
// sortDir,
|
|
900
|
+
// searchColumns,
|
|
901
|
+
// shortCodeData,
|
|
902
|
+
// includes,
|
|
903
|
+
// }: SearchRequestService<DynamicShortCode>) {
|
|
904
|
+
// logger.info("entering::commonSearch::repository");
|
|
905
|
+
// const tableName = shortCodeData.tableName;
|
|
906
|
+
// const whereClause: { OR?: Array<Record<string, unknown>> } = {};
|
|
907
|
+
// if (searchText && searchColumns.length > 0) {
|
|
908
|
+
// // Build an array of sub-objects
|
|
909
|
+
// whereClause.OR = searchColumns.map((column: string) => {
|
|
910
|
+
// if (column.includes(".")) {
|
|
911
|
+
// const keys = column.split(".");
|
|
912
|
+
// return buildNestedCondition(keys, searchText);
|
|
913
|
+
// }
|
|
914
|
+
// return { [column]: { contains: searchText } };
|
|
915
|
+
// });
|
|
916
|
+
// // Then transform them
|
|
917
|
+
// whereClause.OR = transformData(whereClause.OR);
|
|
918
|
+
// }
|
|
919
|
+
// const orderByClause: Record<string, "asc" | "desc"> = {};
|
|
920
|
+
// if (sortBy && sortDir) {
|
|
921
|
+
// orderByClause[sortBy] = sortDir.toLowerCase() as "asc" | "desc";
|
|
922
|
+
// }
|
|
923
|
+
// const skip = (pageNo - 1) * pageSize;
|
|
924
|
+
// const take = pageSize;
|
|
925
|
+
// const model = db[tableName];
|
|
926
|
+
// if (!model) {
|
|
927
|
+
// throw new ErrorHandler(400, "Invalid mapping table name");
|
|
928
|
+
// }
|
|
929
|
+
// const query: QueryType = {
|
|
930
|
+
// where: whereClause,
|
|
931
|
+
// orderBy: orderByClause,
|
|
932
|
+
// skip,
|
|
933
|
+
// take,
|
|
934
|
+
// };
|
|
935
|
+
// if (includes) {
|
|
936
|
+
// query.include = includes;
|
|
937
|
+
// }
|
|
938
|
+
// const results = await model.findMany(query);
|
|
939
|
+
// const totalRecords = await model.count({ where: whereClause });
|
|
940
|
+
// const totalPages = Math.ceil(totalRecords / pageSize);
|
|
941
|
+
// const DTOClass = dtoMapping[shortCodeData.shortCode];
|
|
942
|
+
// if (shortCodeData.isDTO && DTOClass) {
|
|
943
|
+
// let DTOs = [];
|
|
944
|
+
// if (shortCodeData.isSingleDto === undefined || shortCodeData.isSingleDto === true) {
|
|
945
|
+
// DTOs = await Promise.all(results.map((record: unknown) => DTOClass(record)));
|
|
946
|
+
// } else {
|
|
947
|
+
// DTOs = await DTOClass(results);
|
|
948
|
+
// }
|
|
949
|
+
// return {
|
|
950
|
+
// data: DTOs,
|
|
951
|
+
// totalRecords,
|
|
952
|
+
// currentPageNumber: pageNo,
|
|
953
|
+
// pageSize,
|
|
954
|
+
// lastPageNumber: totalPages,
|
|
955
|
+
// };
|
|
956
|
+
// }
|
|
957
|
+
// logger.info("exiting::commonSearch::repository");
|
|
958
|
+
// return {
|
|
959
|
+
// data: results,
|
|
960
|
+
// totalRecords,
|
|
961
|
+
// currentPageNumber: pageNo,
|
|
962
|
+
// pageSize,
|
|
963
|
+
// lastPageNumber: totalPages,
|
|
964
|
+
// };
|
|
965
|
+
// },
|
|
966
|
+
getDelegate(tableName) {
|
|
967
|
+
const d = db[tableName];
|
|
968
|
+
if (!d || typeof d !== "object") throw new ErrorHandler(400, "Invalid mapping table name");
|
|
969
|
+
const del = d;
|
|
970
|
+
if (typeof del.create !== "function" || typeof del.update !== "function" || typeof del.findFirst !== "function") {
|
|
971
|
+
throw new ErrorHandler(400, "Invalid prisma delegate for tableName");
|
|
972
|
+
}
|
|
973
|
+
return del;
|
|
974
|
+
},
|
|
975
|
+
resolveUniqueWhere(u, vars, body, ctx) {
|
|
976
|
+
const out = {};
|
|
977
|
+
for (const c of u.where) {
|
|
978
|
+
if (c.src.startsWith("vars.")) out[c.field] = (vars ?? {})[c.src.slice(5)];
|
|
979
|
+
else if (c.src.startsWith("body.")) out[c.field] = (body ?? {})[c.src.slice(5)];
|
|
980
|
+
else if (c.src.startsWith("ctx.")) out[c.field] = ctx[c.src.slice(4)];
|
|
981
|
+
}
|
|
982
|
+
return omitUndefined(out);
|
|
983
|
+
},
|
|
984
|
+
async runUniqueChecks(delegate, cfg, op, pkField, pkValue, body, ctx) {
|
|
985
|
+
for (const u of cfg.uniques ?? []) {
|
|
986
|
+
if (!u.op.includes(op)) continue;
|
|
987
|
+
const where = this.resolveUniqueWhere(u, ctx.vars ?? {}, body, ctx);
|
|
988
|
+
if (op === "update" && pkValue != null) {
|
|
989
|
+
where["NOT"] = { [pkField]: pkValue };
|
|
990
|
+
}
|
|
991
|
+
if (!Object.keys(where).length) continue;
|
|
992
|
+
const query = { where, select: { [pkField]: true } };
|
|
993
|
+
console.log(query);
|
|
994
|
+
const existing = await delegate.findFirst({ where, select: { [pkField]: true } });
|
|
995
|
+
if (existing) throw new ErrorHandler(400, u.message);
|
|
996
|
+
}
|
|
997
|
+
},
|
|
998
|
+
async commonCreate({ body, ctx, shortCodeData }) {
|
|
999
|
+
if (!shortCodeData.config) throw new ErrorHandler(400, "ShortCode config missing");
|
|
1000
|
+
const cfg = shortCodeData.config;
|
|
1001
|
+
const delegate = this.getDelegate(shortCodeData.tableName);
|
|
1002
|
+
await this.runUniqueChecks(delegate, cfg, "create", cfg.primaryKey, void 0, body, ctx);
|
|
1003
|
+
const data = buildPrismaData(cfg, "create", body, ctx);
|
|
1004
|
+
const include = cfg.response?.include;
|
|
1005
|
+
const select = cfg.response?.select ?? void 0;
|
|
1006
|
+
return delegate.create({ data, include, select });
|
|
1007
|
+
},
|
|
1008
|
+
async commonUpdate({ body, ctx, id, shortCodeData }) {
|
|
1009
|
+
if (!shortCodeData.config) throw new ErrorHandler(400, "ShortCode config missing");
|
|
1010
|
+
const cfg = shortCodeData.config;
|
|
1011
|
+
const pk = cfg.primaryKey;
|
|
1012
|
+
if (cfg.operations.update.requirePrimaryKey && (id === void 0 || id === null || isNaN(Number(id)))) {
|
|
1013
|
+
throw new ErrorHandler(400, "Missing id for update");
|
|
1014
|
+
}
|
|
1015
|
+
const delegate = this.getDelegate(shortCodeData.tableName);
|
|
1016
|
+
await this.runUniqueChecks(delegate, cfg, "update", pk, id, body, ctx);
|
|
1017
|
+
const data = buildPrismaData(cfg, "update", body, ctx);
|
|
1018
|
+
const include = cfg.response?.include;
|
|
1019
|
+
const select = cfg.response?.select ?? void 0;
|
|
1020
|
+
return delegate.update({
|
|
1021
|
+
where: { [pk]: id },
|
|
1022
|
+
data,
|
|
1023
|
+
include,
|
|
1024
|
+
select
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
1027
|
+
};
|
|
1028
|
+
};
|
|
1029
|
+
|
|
1030
|
+
// src/utils/dynamicJoiBuilder.utils.ts
|
|
1031
|
+
import Joi from "joi";
|
|
1032
|
+
var buildScalar = (f) => {
|
|
1033
|
+
const rules = f.rules ?? {};
|
|
1034
|
+
let s;
|
|
1035
|
+
switch (f.type) {
|
|
1036
|
+
case "string": {
|
|
1037
|
+
let j = Joi.string();
|
|
1038
|
+
if (rules.trim) j = j.trim();
|
|
1039
|
+
if (typeof rules.min === "number") j = j.min(rules.min);
|
|
1040
|
+
if (typeof rules.max === "number") j = j.max(rules.max);
|
|
1041
|
+
if (rules.regex) j = j.pattern(new RegExp(rules.regex));
|
|
1042
|
+
s = j;
|
|
1043
|
+
break;
|
|
1044
|
+
}
|
|
1045
|
+
case "number": {
|
|
1046
|
+
let j = Joi.number();
|
|
1047
|
+
if (rules.integer) j = j.integer();
|
|
1048
|
+
if (typeof rules.min === "number") j = j.min(rules.min);
|
|
1049
|
+
if (typeof rules.max === "number") j = j.max(rules.max);
|
|
1050
|
+
s = j;
|
|
1051
|
+
break;
|
|
1052
|
+
}
|
|
1053
|
+
case "boolean":
|
|
1054
|
+
s = Joi.boolean();
|
|
1055
|
+
break;
|
|
1056
|
+
case "date": {
|
|
1057
|
+
let j = Joi.date();
|
|
1058
|
+
if (rules.iso) j = j.iso();
|
|
1059
|
+
s = j;
|
|
1060
|
+
break;
|
|
1061
|
+
}
|
|
1062
|
+
case "enum": {
|
|
1063
|
+
const values = rules.values ?? [];
|
|
1064
|
+
s = Joi.string().valid(...values);
|
|
1065
|
+
break;
|
|
1066
|
+
}
|
|
1067
|
+
case "object":
|
|
1068
|
+
s = Joi.object(rules.schema ?? {});
|
|
1069
|
+
break;
|
|
1070
|
+
case "array":
|
|
1071
|
+
s = Joi.array();
|
|
1072
|
+
break;
|
|
1073
|
+
case "json":
|
|
1074
|
+
default:
|
|
1075
|
+
s = Joi.any();
|
|
1076
|
+
}
|
|
1077
|
+
if (f.allowNull) s = s.allow(null);
|
|
1078
|
+
if (f.default !== void 0) s = s.default(f.default);
|
|
1079
|
+
if (f.messages) s = s.messages(f.messages);
|
|
1080
|
+
return s;
|
|
1081
|
+
};
|
|
1082
|
+
var applyPresence = (schema, presence) => {
|
|
1083
|
+
if (presence === "required") return schema.required();
|
|
1084
|
+
if (presence === "forbidden") return schema.forbidden();
|
|
1085
|
+
return schema.optional();
|
|
1086
|
+
};
|
|
1087
|
+
var buildRelationSchema = (rel, op) => {
|
|
1088
|
+
const itemShape = {};
|
|
1089
|
+
for (const f of rel.items.fields) {
|
|
1090
|
+
const scalar = buildScalar(f);
|
|
1091
|
+
itemShape[f.name] = applyPresence(scalar, f.presence[op]);
|
|
1092
|
+
}
|
|
1093
|
+
const itemSchema = Joi.object(itemShape);
|
|
1094
|
+
const base = rel.kind === "many" ? Joi.array().items(itemSchema) : itemSchema;
|
|
1095
|
+
return applyPresence(base, rel.presence[op]);
|
|
1096
|
+
};
|
|
1097
|
+
var buildJoiSchemaForOp = (cfg, op) => {
|
|
1098
|
+
const shape = {};
|
|
1099
|
+
for (const f of cfg.fields) {
|
|
1100
|
+
const scalar = buildScalar(f);
|
|
1101
|
+
shape[f.name] = applyPresence(scalar, f.presence[op]);
|
|
1102
|
+
}
|
|
1103
|
+
for (const rel of cfg.relations ?? []) {
|
|
1104
|
+
shape[rel.name] = buildRelationSchema(rel, op);
|
|
1105
|
+
}
|
|
1106
|
+
return Joi.object(shape).prefs({
|
|
1107
|
+
abortEarly: cfg.validation.abortEarly,
|
|
1108
|
+
allowUnknown: cfg.validation.allowUnknown,
|
|
1109
|
+
stripUnknown: cfg.validation.stripUnknown,
|
|
1110
|
+
convert: cfg.validation.convert
|
|
1111
|
+
});
|
|
1112
|
+
};
|
|
1113
|
+
|
|
771
1114
|
// src/utils/helper.utils.ts
|
|
772
1115
|
function customOmit(obj, keys) {
|
|
773
1116
|
const rest = { ...obj };
|
|
@@ -894,11 +1237,13 @@ import ExcelJs from "exceljs";
|
|
|
894
1237
|
var commonService = (serviceDeps) => {
|
|
895
1238
|
const generateErrorMessage = serviceDeps.helpers.generateErrorMessage;
|
|
896
1239
|
const ErrorHandler = serviceDeps.helpers.ErrorHandler;
|
|
897
|
-
const { deleteCache, getCacheById, updateCache, createCache } = serviceDeps.cacheAdapter;
|
|
1240
|
+
const { deleteCache, getCacheById, updateCache, createCache, addToCache } = serviceDeps.cacheAdapter;
|
|
898
1241
|
const logger = serviceDeps.logger;
|
|
899
1242
|
const dtoMapping = serviceDeps.mapper.dtoMapping;
|
|
900
1243
|
const { REDIS_PREFIX, CACHE_KEY_NAME } = serviceDeps.config;
|
|
901
1244
|
const commonRepositoryFactory = commonRepository(serviceDeps);
|
|
1245
|
+
const commonCreateUpdateRepositoryFactory = commonCreateUpdateRepository(serviceDeps);
|
|
1246
|
+
const requestStorage = serviceDeps.requestStorage;
|
|
902
1247
|
return {
|
|
903
1248
|
async search(searchParams) {
|
|
904
1249
|
logger.info("entering::search::service");
|
|
@@ -1138,18 +1483,55 @@ var commonService = (serviceDeps) => {
|
|
|
1138
1483
|
},
|
|
1139
1484
|
async create(createParams) {
|
|
1140
1485
|
logger.info("entering::create::service");
|
|
1486
|
+
const store = requestStorage.getStore();
|
|
1487
|
+
const currentUser = store?.user?.id ?? null;
|
|
1141
1488
|
const shortCodeData = createParams.shortCodeData;
|
|
1142
|
-
const
|
|
1489
|
+
const cfg = shortCodeData.config;
|
|
1490
|
+
const ctx = { userId: currentUser ?? void 0, vars: {} };
|
|
1491
|
+
const schema = buildJoiSchemaForOp(cfg, "create");
|
|
1492
|
+
const validated = await schema.validateAsync(createParams.body);
|
|
1493
|
+
const createResult = await commonCreateUpdateRepositoryFactory.commonCreate({
|
|
1494
|
+
body: validated,
|
|
1495
|
+
ctx,
|
|
1496
|
+
shortCodeData
|
|
1497
|
+
});
|
|
1143
1498
|
if (shortCodeData.isCacheable) {
|
|
1144
|
-
await
|
|
1499
|
+
await addToCache(
|
|
1500
|
+
`${REDIS_PREFIX}${CACHE_KEY_NAME}:${shortCodeData.tableName}:all`,
|
|
1501
|
+
createResult[cfg.primaryKey],
|
|
1502
|
+
createResult
|
|
1503
|
+
);
|
|
1504
|
+
}
|
|
1505
|
+
if (shortCodeData.isDTO && dtoMapping[shortCodeData.shortCode]) {
|
|
1506
|
+
let dtoResult;
|
|
1507
|
+
if (shortCodeData.isSingleDto === void 0 || shortCodeData.isSingleDto === true) {
|
|
1508
|
+
dtoResult = await dtoMapping[shortCodeData.shortCode](createResult);
|
|
1509
|
+
} else {
|
|
1510
|
+
dtoResult = (await dtoMapping[shortCodeData.shortCode]([createResult]))?.[0];
|
|
1511
|
+
}
|
|
1512
|
+
if (!dtoResult) {
|
|
1513
|
+
throw new ErrorHandler(404, generateErrorMessage("NOT_FOUND", `${shortCodeData.tableName}`));
|
|
1514
|
+
}
|
|
1515
|
+
return dtoResult;
|
|
1145
1516
|
}
|
|
1146
1517
|
logger.info("exiting::create::service");
|
|
1147
1518
|
return createResult;
|
|
1148
1519
|
},
|
|
1149
1520
|
async update(updateParams) {
|
|
1150
1521
|
logger.info("entering::update::service");
|
|
1522
|
+
const store = requestStorage.getStore();
|
|
1523
|
+
const currentUser = store?.user?.id ?? null;
|
|
1151
1524
|
const shortCodeData = updateParams.shortCodeData;
|
|
1152
|
-
const
|
|
1525
|
+
const cfg = shortCodeData.config;
|
|
1526
|
+
const ctx = { userId: currentUser ?? void 0, vars: {} };
|
|
1527
|
+
const schema = buildJoiSchemaForOp(cfg, "update");
|
|
1528
|
+
const validated = await schema.validateAsync(updateParams.body);
|
|
1529
|
+
const updateResult = await commonCreateUpdateRepositoryFactory.commonUpdate({
|
|
1530
|
+
body: validated,
|
|
1531
|
+
ctx,
|
|
1532
|
+
shortCodeData,
|
|
1533
|
+
id: updateParams.id
|
|
1534
|
+
});
|
|
1153
1535
|
if (shortCodeData.isCacheable) {
|
|
1154
1536
|
await updateCache(
|
|
1155
1537
|
`${REDIS_PREFIX}${CACHE_KEY_NAME}:${shortCodeData.tableName}:all`,
|
|
@@ -1157,6 +1539,18 @@ var commonService = (serviceDeps) => {
|
|
|
1157
1539
|
updateResult
|
|
1158
1540
|
);
|
|
1159
1541
|
}
|
|
1542
|
+
if (shortCodeData.isDTO && dtoMapping[shortCodeData.shortCode]) {
|
|
1543
|
+
let dtoResult;
|
|
1544
|
+
if (shortCodeData.isSingleDto === void 0 || shortCodeData.isSingleDto === true) {
|
|
1545
|
+
dtoResult = await dtoMapping[shortCodeData.shortCode](updateResult);
|
|
1546
|
+
} else {
|
|
1547
|
+
dtoResult = (await dtoMapping[shortCodeData.shortCode]([updateResult]))?.[0];
|
|
1548
|
+
}
|
|
1549
|
+
if (!dtoResult) {
|
|
1550
|
+
throw new ErrorHandler(404, generateErrorMessage("NOT_FOUND", `${shortCodeData.tableName}`));
|
|
1551
|
+
}
|
|
1552
|
+
return dtoResult;
|
|
1553
|
+
}
|
|
1160
1554
|
logger.info("exiting::update::service");
|
|
1161
1555
|
return updateResult;
|
|
1162
1556
|
},
|
|
@@ -2076,7 +2470,7 @@ var AuditLogger = class {
|
|
|
2076
2470
|
async logIfEnabled(params) {
|
|
2077
2471
|
const { service, method, payload } = params;
|
|
2078
2472
|
const prisma = this.core.getPrisma();
|
|
2079
|
-
const { userId, traceId,
|
|
2473
|
+
const { userId, traceId, level1Id: ctxLvl1Id, level2Id: ctxLvl2Id, module } = this.core.getContext();
|
|
2080
2474
|
try {
|
|
2081
2475
|
const config = await prisma.auditConfig.findFirst({
|
|
2082
2476
|
where: {
|
|
@@ -2091,14 +2485,16 @@ var AuditLogger = class {
|
|
|
2091
2485
|
}
|
|
2092
2486
|
const message = payload.type === "ERROR" ? payload.message : config.message;
|
|
2093
2487
|
const type = payload.type ?? "INFO";
|
|
2094
|
-
const
|
|
2488
|
+
const level1Id = payload.level1Id ?? ctxLvl1Id ?? 0;
|
|
2489
|
+
const level2Id = payload.level2Id ?? ctxLvl2Id ?? 0;
|
|
2095
2490
|
await prisma.commonAudit.create({
|
|
2096
2491
|
data: {
|
|
2097
2492
|
service,
|
|
2098
2493
|
module,
|
|
2099
2494
|
type,
|
|
2100
2495
|
message,
|
|
2101
|
-
|
|
2496
|
+
level1Id,
|
|
2497
|
+
level2Id,
|
|
2102
2498
|
methodName: method,
|
|
2103
2499
|
traceId,
|
|
2104
2500
|
createdBy: userId ?? void 0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "av6-core",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "dist/index.mjs",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -21,12 +21,13 @@
|
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@prisma/client": "^6.19.0",
|
|
24
|
-
"prisma": "^6.19.0",
|
|
25
24
|
"axios": "^1.11.0",
|
|
26
25
|
"exceljs": "^4.4.0",
|
|
27
26
|
"handlebars": "^4.7.8",
|
|
27
|
+
"joi": "^17.13.3",
|
|
28
28
|
"node-cron": "^4.2.1",
|
|
29
29
|
"nodemailer": "^7.0.10",
|
|
30
|
-
"prettier": "^3.6.2"
|
|
30
|
+
"prettier": "^3.6.2",
|
|
31
|
+
"prisma": "^6.19.0"
|
|
31
32
|
}
|
|
32
33
|
}
|