av6-core 1.3.11 → 1.4.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/.cursor/debug-check-prisma.ts +100 -0
- package/dist/index.d.mts +36 -6
- package/dist/index.d.ts +36 -6
- package/dist/index.js +290 -122
- package/dist/index.mjs +290 -122
- package/package.json +4 -2
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// #region agent log
|
|
2
|
+
fetch('http://127.0.0.1:7244/ingest/0a9f7972-5d03-4255-b5c9-6164f846fb46',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'debug-check-prisma.ts:1',message:'Starting Prisma client check',data:{timestamp:Date.now()},sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{});
|
|
3
|
+
// #endregion
|
|
4
|
+
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
|
|
8
|
+
const workspaceRoot = path.resolve(__dirname, '..');
|
|
9
|
+
const nodeModulesPath = path.join(workspaceRoot, 'node_modules');
|
|
10
|
+
const prismaClientPath = path.join(nodeModulesPath, '@prisma', 'client');
|
|
11
|
+
const prismaGeneratedPath = path.join(nodeModulesPath, '.prisma', 'client');
|
|
12
|
+
|
|
13
|
+
// #region agent log
|
|
14
|
+
fetch('http://127.0.0.1:7244/ingest/0a9f7972-5d03-4255-b5c9-6164f846fb46',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'debug-check-prisma.ts:10',message:'Checking paths',data:{workspaceRoot,prismaClientPath,prismaGeneratedPath,prismaClientExists:fs.existsSync(prismaClientPath),prismaGeneratedExists:fs.existsSync(prismaGeneratedPath)},sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{});
|
|
15
|
+
// #endregion
|
|
16
|
+
|
|
17
|
+
// Check if @prisma/client package exists
|
|
18
|
+
const prismaClientExists = fs.existsSync(prismaClientPath);
|
|
19
|
+
const prismaGeneratedExists = fs.existsSync(prismaGeneratedPath);
|
|
20
|
+
|
|
21
|
+
// #region agent log
|
|
22
|
+
fetch('http://127.0.0.1:7244/ingest/0a9f7972-5d03-4255-b5c9-6164f846fb46',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'debug-check-prisma.ts:18',message:'Path check results',data:{prismaClientExists,prismaGeneratedExists},sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{});
|
|
23
|
+
// #endregion
|
|
24
|
+
|
|
25
|
+
// Try to read package.json from @prisma/client
|
|
26
|
+
let prismaClientPackageJson: any = null;
|
|
27
|
+
if (prismaClientExists) {
|
|
28
|
+
try {
|
|
29
|
+
const packageJsonPath = path.join(prismaClientPath, 'package.json');
|
|
30
|
+
// #region agent log
|
|
31
|
+
fetch('http://127.0.0.1:7244/ingest/0a9f7972-5d03-4255-b5c9-6164f846fb46',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'debug-check-prisma.ts:26',message:'Reading @prisma/client package.json',data:{packageJsonPath,exists:fs.existsSync(packageJsonPath)},sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{});
|
|
32
|
+
// #endregion
|
|
33
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
34
|
+
prismaClientPackageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
35
|
+
// #region agent log
|
|
36
|
+
fetch('http://127.0.0.1:7244/ingest/0a9f7972-5d03-4255-b5c9-6164f846fb46',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'debug-check-prisma.ts:30',message:'@prisma/client package.json content',data:{name:prismaClientPackageJson?.name,version:prismaClientPackageJson?.version,exports:prismaClientPackageJson?.exports},sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{});
|
|
37
|
+
// #endregion
|
|
38
|
+
}
|
|
39
|
+
} catch (e) {
|
|
40
|
+
// #region agent log
|
|
41
|
+
fetch('http://127.0.0.1:7244/ingest/0a9f7972-5d03-4255-b5c9-6164f846fb46',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'debug-check-prisma.ts:34',message:'Error reading package.json',data:{error:String(e)},sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{});
|
|
42
|
+
// #endregion
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Check index.d.ts in @prisma/client
|
|
47
|
+
let indexDtsContent: string | null = null;
|
|
48
|
+
if (prismaClientExists) {
|
|
49
|
+
try {
|
|
50
|
+
const indexDtsPath = path.join(prismaClientPath, 'index.d.ts');
|
|
51
|
+
// #region agent log
|
|
52
|
+
fetch('http://127.0.0.1:7244/ingest/0a9f7972-5d03-4255-b5c9-6164f846fb46',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'debug-check-prisma.ts:43',message:'Reading index.d.ts',data:{indexDtsPath,exists:fs.existsSync(indexDtsPath)},sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{});
|
|
53
|
+
// #endregion
|
|
54
|
+
if (fs.existsSync(indexDtsPath)) {
|
|
55
|
+
indexDtsContent = fs.readFileSync(indexDtsPath, 'utf-8');
|
|
56
|
+
// #region agent log
|
|
57
|
+
fetch('http://127.0.0.1:7244/ingest/0a9f7972-5d03-4255-b5c9-6164f846fb46',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'debug-check-prisma.ts:47',message:'index.d.ts content',data:{content:indexDtsContent.substring(0,200)},sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{});
|
|
58
|
+
// #endregion
|
|
59
|
+
}
|
|
60
|
+
} catch (e) {
|
|
61
|
+
// #region agent log
|
|
62
|
+
fetch('http://127.0.0.1:7244/ingest/0a9f7972-5d03-4255-b5c9-6164f846fb46',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'debug-check-prisma.ts:51',message:'Error reading index.d.ts',data:{error:String(e)},sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{});
|
|
63
|
+
// #endregion
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Try to dynamically import PrismaClient
|
|
68
|
+
let prismaClientImportSuccess = false;
|
|
69
|
+
let prismaClientImportError: string | null = null;
|
|
70
|
+
try {
|
|
71
|
+
// #region agent log
|
|
72
|
+
fetch('http://127.0.0.1:7244/ingest/0a9f7972-5d03-4255-b5c9-6164f846fb46',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'debug-check-prisma.ts:60',message:'Attempting dynamic import of PrismaClient',data:{},sessionId:'debug-session',runId:'run1',hypothesisId:'D'})}).catch(()=>{});
|
|
73
|
+
// #endregion
|
|
74
|
+
const prismaModule = require('@prisma/client');
|
|
75
|
+
// #region agent log
|
|
76
|
+
fetch('http://127.0.0.1:7244/ingest/0a9f7972-5d03-4255-b5c9-6164f846fb46',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'debug-check-prisma.ts:63',message:'Module loaded',data:{hasPrismaClient:!!prismaModule.PrismaClient,exports:Object.keys(prismaModule)},sessionId:'debug-session',runId:'run1',hypothesisId:'D'})}).catch(()=>{});
|
|
77
|
+
// #endregion
|
|
78
|
+
if (prismaModule.PrismaClient) {
|
|
79
|
+
prismaClientImportSuccess = true;
|
|
80
|
+
} else {
|
|
81
|
+
prismaClientImportError = 'PrismaClient not found in exports: ' + Object.keys(prismaModule).join(', ');
|
|
82
|
+
}
|
|
83
|
+
} catch (e) {
|
|
84
|
+
prismaClientImportError = String(e);
|
|
85
|
+
// #region agent log
|
|
86
|
+
fetch('http://127.0.0.1:7244/ingest/0a9f7972-5d03-4255-b5c9-6164f846fb46',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'debug-check-prisma.ts:72',message:'Dynamic import failed',data:{error:prismaClientImportError},sessionId:'debug-session',runId:'run1',hypothesisId:'D'})}).catch(()=>{});
|
|
87
|
+
// #endregion
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// #region agent log
|
|
91
|
+
fetch('http://127.0.0.1:7244/ingest/0a9f7972-5d03-4255-b5c9-6164f846fb46',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'debug-check-prisma.ts:76',message:'Final summary',data:{prismaClientExists,prismaGeneratedExists,prismaClientImportSuccess,prismaClientImportError,hasPackageJson:!!prismaClientPackageJson,hasIndexDts:!!indexDtsContent},sessionId:'debug-session',runId:'run1',hypothesisId:'ALL'})}).catch(()=>{});
|
|
92
|
+
// #endregion
|
|
93
|
+
|
|
94
|
+
console.log('Prisma Client Check Complete');
|
|
95
|
+
console.log('Prisma Client Package Exists:', prismaClientExists);
|
|
96
|
+
console.log('Prisma Generated Client Exists:', prismaGeneratedExists);
|
|
97
|
+
console.log('PrismaClient Import Success:', prismaClientImportSuccess);
|
|
98
|
+
if (prismaClientImportError) {
|
|
99
|
+
console.log('PrismaClient Import Error:', prismaClientImportError);
|
|
100
|
+
}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import winston from 'winston';
|
|
2
|
-
import { AsyncLocalStorage } from 'async_hooks';
|
|
3
|
-
import { Readable } from 'stream';
|
|
4
1
|
import { JsonValue } from '@prisma/client/runtime/library';
|
|
5
|
-
import
|
|
2
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
6
3
|
import { AxiosResponse } from 'axios';
|
|
4
|
+
import ExcelJs from 'exceljs';
|
|
5
|
+
import { Readable } from 'stream';
|
|
6
|
+
import winston from 'winston';
|
|
7
7
|
import * as PrismaNamespace from '@prisma/client';
|
|
8
8
|
import { PrismaClient, Prisma } from '@prisma/client';
|
|
9
9
|
|
|
@@ -31,7 +31,7 @@ declare enum ErrorMessageType {
|
|
|
31
31
|
|
|
32
32
|
type Presence = "required" | "optional" | "forbidden";
|
|
33
33
|
type Op = "create" | "update";
|
|
34
|
-
type FieldType = "string" | "number" | "boolean" | "date" | "enum" | "object" | "array" | "json";
|
|
34
|
+
type FieldType = "string" | "number" | "boolean" | "date" | "enum" | "object" | "array" | "json" | "file";
|
|
35
35
|
type SourcePath = `body.${string}` | `vars.${string}` | `ctx.${string}`;
|
|
36
36
|
interface FieldRules {
|
|
37
37
|
min?: number;
|
|
@@ -46,6 +46,7 @@ interface FieldRules {
|
|
|
46
46
|
precisionFrom?: "ctx.decimalPrecision";
|
|
47
47
|
minDate?: "today" | "now";
|
|
48
48
|
minDateFieldRef?: string;
|
|
49
|
+
fileKind?: "image" | "document";
|
|
49
50
|
when?: {
|
|
50
51
|
ref: string;
|
|
51
52
|
is: string | number | boolean | (string | number | boolean)[];
|
|
@@ -72,6 +73,7 @@ interface FieldConfig {
|
|
|
72
73
|
rules?: FieldRules;
|
|
73
74
|
default?: unknown;
|
|
74
75
|
allowNull?: boolean;
|
|
76
|
+
allowEmptyString?: boolean;
|
|
75
77
|
messages?: Record<string, string>;
|
|
76
78
|
}
|
|
77
79
|
type RelationStrategy = "create" | "replace" | "upsert";
|
|
@@ -134,6 +136,7 @@ interface DynamicCrudConfig {
|
|
|
134
136
|
include?: Record<string, unknown>;
|
|
135
137
|
select?: Record<string, unknown> | null;
|
|
136
138
|
};
|
|
139
|
+
bulk?: BulkConfig;
|
|
137
140
|
}
|
|
138
141
|
interface CrudContext {
|
|
139
142
|
userId?: number;
|
|
@@ -156,6 +159,10 @@ type CrudDelegate = {
|
|
|
156
159
|
where: Record<string, unknown>;
|
|
157
160
|
select?: Record<string, boolean>;
|
|
158
161
|
}) => Promise<unknown>;
|
|
162
|
+
findMany: (args: {
|
|
163
|
+
where: Record<string, unknown>;
|
|
164
|
+
select?: Record<string, boolean>;
|
|
165
|
+
}) => Promise<unknown>;
|
|
159
166
|
};
|
|
160
167
|
interface DynamicCreateInput {
|
|
161
168
|
shortCodeData: DynamicShortCode;
|
|
@@ -189,6 +196,28 @@ type DtoFromMapping<M extends Record<string, string>, Row> = {
|
|
|
189
196
|
type DtoNullOnMissing<M extends Record<string, string>, Row extends object> = {
|
|
190
197
|
[K in keyof M]: Exclude<DtoFromMapping<M, Row>[K], undefined> | null;
|
|
191
198
|
};
|
|
199
|
+
type BulkOnConflict = "error" | "update" | "skip";
|
|
200
|
+
interface BulkConflictConfig {
|
|
201
|
+
by: Array<{
|
|
202
|
+
field: string;
|
|
203
|
+
src?: SourcePath;
|
|
204
|
+
}>;
|
|
205
|
+
onConflict: BulkOnConflict;
|
|
206
|
+
updateFields?: string[];
|
|
207
|
+
allowRelationUpdate?: boolean;
|
|
208
|
+
}
|
|
209
|
+
interface BulkConfig {
|
|
210
|
+
arrayKey: string;
|
|
211
|
+
conflict: BulkConflictConfig;
|
|
212
|
+
}
|
|
213
|
+
type BulkAtomicResult = {
|
|
214
|
+
total: number;
|
|
215
|
+
created: number;
|
|
216
|
+
updated: number;
|
|
217
|
+
skipped: number;
|
|
218
|
+
createdRows: any[];
|
|
219
|
+
updatedRows: any[];
|
|
220
|
+
};
|
|
192
221
|
|
|
193
222
|
interface EmployeeCache {
|
|
194
223
|
id: number;
|
|
@@ -469,6 +498,7 @@ interface CommonServiceResponse {
|
|
|
469
498
|
updateConfigByCode: (input: UpdateConfigByCodeInput) => Promise<void>;
|
|
470
499
|
update: (updateParams: CommonUpdateRequestRepository) => Promise<unknown>;
|
|
471
500
|
fetchImageStream: (imageBaseUrl: string, fileName: string) => Promise<AxiosResponse<Readable>>;
|
|
501
|
+
commonBulkUpsert: (bulkUpsertParams: DynamicCreateInput) => Promise<BulkAtomicResult>;
|
|
472
502
|
}
|
|
473
503
|
|
|
474
504
|
declare const commonService: (serviceDeps: Deps) => CommonServiceResponse;
|
|
@@ -650,4 +680,4 @@ declare class AuditProxy<Module extends string = "OPD" | "PROCEDURE" | "GENERAL_
|
|
|
650
680
|
createAuditedService<T extends object>(serviceName: string, service: T): T;
|
|
651
681
|
}
|
|
652
682
|
|
|
653
|
-
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 CrudContext, type CrudDelegate, type DataType, type DeepMerge, type DeleteParams, type DeleteRequestRepository, type Deps, type DropdownRequest, type DropdownRequestService, type DtoFromMapping, type DtoNullOnMissing, type DynamicCreateInput, type DynamicCrudConfig, type DynamicShortCode, type DynamicUpdateInput, type EmitPayload, type EmployeeCache, type ExcelConfig, type ExportExcel, type ExportExcelRequestService, type FetchRequest, type FetchRequestRepository, type FieldConfig, type FieldRules, type FieldType, type FixedSearchRequest, type FixedSearchRequestService, type Helpers, type ImportExcel, type ImportExcelRequestService, type LockUnlockParams, type LockUnlockRequestRepository, type Mapper, type MergeAll, type NewFixedSearchRequest, type NewFixedSearchRequestService, type NewSearchRequest, NotificationEmitter, type Op, type PaginatedResponse, type PathToSelectWithSelect, type PathValue, type PathsToSelectWithSelect, type Presence, type Recipient, type RelationConfig, type RelationStrategy, type RelationWriteConfig, type SearchRequest, type SearchRequestService, type ServiceCacheAdapter, type SingleValidationMapping, type SourcePath, type Store, type ToggleActive, type TxClient, type UINConfigDTO, type UINPreviewRequest, type UINSegment, type UINSegmentType, type UIN_RESET_POLICY, type UinDeps, type UnionToIntersection, type UniqueConfig, type UpdateConfigByCodeInput, type UpdateStatusRequestRepository, type UpdateUINConfigRequest, type ValidationErrorItem, commonService, customOmit, findDifferences, fromTimestampToSqlDatetime, getDynamicValue, getPattern, interpolate, objectTo2DArray, toNumberOrNull, toUINConfigDTO, uinConfigService, type updateStatusParams };
|
|
683
|
+
export { type AuditContext, type AuditContextProvider, AuditCore, type AuditLogPayload, AuditLogger, AuditProxy, type BulkAtomicResult, type BulkConfig, type BulkConflictConfig, type BulkOnConflict, 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 CrudContext, type CrudDelegate, type DataType, type DeepMerge, type DeleteParams, type DeleteRequestRepository, type Deps, type DropdownRequest, type DropdownRequestService, type DtoFromMapping, type DtoNullOnMissing, type DynamicCreateInput, type DynamicCrudConfig, type DynamicShortCode, type DynamicUpdateInput, type EmitPayload, type EmployeeCache, type ExcelConfig, type ExportExcel, type ExportExcelRequestService, type FetchRequest, type FetchRequestRepository, type FieldConfig, type FieldRules, type FieldType, type FixedSearchRequest, type FixedSearchRequestService, type Helpers, type ImportExcel, type ImportExcelRequestService, type LockUnlockParams, type LockUnlockRequestRepository, type Mapper, type MergeAll, type NewFixedSearchRequest, type NewFixedSearchRequestService, type NewSearchRequest, NotificationEmitter, type Op, type PaginatedResponse, type PathToSelectWithSelect, type PathValue, type PathsToSelectWithSelect, type Presence, type Recipient, type RelationConfig, type RelationStrategy, type RelationWriteConfig, type SearchRequest, type SearchRequestService, type ServiceCacheAdapter, type SingleValidationMapping, type SourcePath, type Store, type ToggleActive, type TxClient, type UINConfigDTO, type UINPreviewRequest, type UINSegment, type UINSegmentType, type UIN_RESET_POLICY, type UinDeps, type UnionToIntersection, type UniqueConfig, type UpdateConfigByCodeInput, 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,9 +1,9 @@
|
|
|
1
|
-
import winston from 'winston';
|
|
2
|
-
import { AsyncLocalStorage } from 'async_hooks';
|
|
3
|
-
import { Readable } from 'stream';
|
|
4
1
|
import { JsonValue } from '@prisma/client/runtime/library';
|
|
5
|
-
import
|
|
2
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
6
3
|
import { AxiosResponse } from 'axios';
|
|
4
|
+
import ExcelJs from 'exceljs';
|
|
5
|
+
import { Readable } from 'stream';
|
|
6
|
+
import winston from 'winston';
|
|
7
7
|
import * as PrismaNamespace from '@prisma/client';
|
|
8
8
|
import { PrismaClient, Prisma } from '@prisma/client';
|
|
9
9
|
|
|
@@ -31,7 +31,7 @@ declare enum ErrorMessageType {
|
|
|
31
31
|
|
|
32
32
|
type Presence = "required" | "optional" | "forbidden";
|
|
33
33
|
type Op = "create" | "update";
|
|
34
|
-
type FieldType = "string" | "number" | "boolean" | "date" | "enum" | "object" | "array" | "json";
|
|
34
|
+
type FieldType = "string" | "number" | "boolean" | "date" | "enum" | "object" | "array" | "json" | "file";
|
|
35
35
|
type SourcePath = `body.${string}` | `vars.${string}` | `ctx.${string}`;
|
|
36
36
|
interface FieldRules {
|
|
37
37
|
min?: number;
|
|
@@ -46,6 +46,7 @@ interface FieldRules {
|
|
|
46
46
|
precisionFrom?: "ctx.decimalPrecision";
|
|
47
47
|
minDate?: "today" | "now";
|
|
48
48
|
minDateFieldRef?: string;
|
|
49
|
+
fileKind?: "image" | "document";
|
|
49
50
|
when?: {
|
|
50
51
|
ref: string;
|
|
51
52
|
is: string | number | boolean | (string | number | boolean)[];
|
|
@@ -72,6 +73,7 @@ interface FieldConfig {
|
|
|
72
73
|
rules?: FieldRules;
|
|
73
74
|
default?: unknown;
|
|
74
75
|
allowNull?: boolean;
|
|
76
|
+
allowEmptyString?: boolean;
|
|
75
77
|
messages?: Record<string, string>;
|
|
76
78
|
}
|
|
77
79
|
type RelationStrategy = "create" | "replace" | "upsert";
|
|
@@ -134,6 +136,7 @@ interface DynamicCrudConfig {
|
|
|
134
136
|
include?: Record<string, unknown>;
|
|
135
137
|
select?: Record<string, unknown> | null;
|
|
136
138
|
};
|
|
139
|
+
bulk?: BulkConfig;
|
|
137
140
|
}
|
|
138
141
|
interface CrudContext {
|
|
139
142
|
userId?: number;
|
|
@@ -156,6 +159,10 @@ type CrudDelegate = {
|
|
|
156
159
|
where: Record<string, unknown>;
|
|
157
160
|
select?: Record<string, boolean>;
|
|
158
161
|
}) => Promise<unknown>;
|
|
162
|
+
findMany: (args: {
|
|
163
|
+
where: Record<string, unknown>;
|
|
164
|
+
select?: Record<string, boolean>;
|
|
165
|
+
}) => Promise<unknown>;
|
|
159
166
|
};
|
|
160
167
|
interface DynamicCreateInput {
|
|
161
168
|
shortCodeData: DynamicShortCode;
|
|
@@ -189,6 +196,28 @@ type DtoFromMapping<M extends Record<string, string>, Row> = {
|
|
|
189
196
|
type DtoNullOnMissing<M extends Record<string, string>, Row extends object> = {
|
|
190
197
|
[K in keyof M]: Exclude<DtoFromMapping<M, Row>[K], undefined> | null;
|
|
191
198
|
};
|
|
199
|
+
type BulkOnConflict = "error" | "update" | "skip";
|
|
200
|
+
interface BulkConflictConfig {
|
|
201
|
+
by: Array<{
|
|
202
|
+
field: string;
|
|
203
|
+
src?: SourcePath;
|
|
204
|
+
}>;
|
|
205
|
+
onConflict: BulkOnConflict;
|
|
206
|
+
updateFields?: string[];
|
|
207
|
+
allowRelationUpdate?: boolean;
|
|
208
|
+
}
|
|
209
|
+
interface BulkConfig {
|
|
210
|
+
arrayKey: string;
|
|
211
|
+
conflict: BulkConflictConfig;
|
|
212
|
+
}
|
|
213
|
+
type BulkAtomicResult = {
|
|
214
|
+
total: number;
|
|
215
|
+
created: number;
|
|
216
|
+
updated: number;
|
|
217
|
+
skipped: number;
|
|
218
|
+
createdRows: any[];
|
|
219
|
+
updatedRows: any[];
|
|
220
|
+
};
|
|
192
221
|
|
|
193
222
|
interface EmployeeCache {
|
|
194
223
|
id: number;
|
|
@@ -469,6 +498,7 @@ interface CommonServiceResponse {
|
|
|
469
498
|
updateConfigByCode: (input: UpdateConfigByCodeInput) => Promise<void>;
|
|
470
499
|
update: (updateParams: CommonUpdateRequestRepository) => Promise<unknown>;
|
|
471
500
|
fetchImageStream: (imageBaseUrl: string, fileName: string) => Promise<AxiosResponse<Readable>>;
|
|
501
|
+
commonBulkUpsert: (bulkUpsertParams: DynamicCreateInput) => Promise<BulkAtomicResult>;
|
|
472
502
|
}
|
|
473
503
|
|
|
474
504
|
declare const commonService: (serviceDeps: Deps) => CommonServiceResponse;
|
|
@@ -650,4 +680,4 @@ declare class AuditProxy<Module extends string = "OPD" | "PROCEDURE" | "GENERAL_
|
|
|
650
680
|
createAuditedService<T extends object>(serviceName: string, service: T): T;
|
|
651
681
|
}
|
|
652
682
|
|
|
653
|
-
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 CrudContext, type CrudDelegate, type DataType, type DeepMerge, type DeleteParams, type DeleteRequestRepository, type Deps, type DropdownRequest, type DropdownRequestService, type DtoFromMapping, type DtoNullOnMissing, type DynamicCreateInput, type DynamicCrudConfig, type DynamicShortCode, type DynamicUpdateInput, type EmitPayload, type EmployeeCache, type ExcelConfig, type ExportExcel, type ExportExcelRequestService, type FetchRequest, type FetchRequestRepository, type FieldConfig, type FieldRules, type FieldType, type FixedSearchRequest, type FixedSearchRequestService, type Helpers, type ImportExcel, type ImportExcelRequestService, type LockUnlockParams, type LockUnlockRequestRepository, type Mapper, type MergeAll, type NewFixedSearchRequest, type NewFixedSearchRequestService, type NewSearchRequest, NotificationEmitter, type Op, type PaginatedResponse, type PathToSelectWithSelect, type PathValue, type PathsToSelectWithSelect, type Presence, type Recipient, type RelationConfig, type RelationStrategy, type RelationWriteConfig, type SearchRequest, type SearchRequestService, type ServiceCacheAdapter, type SingleValidationMapping, type SourcePath, type Store, type ToggleActive, type TxClient, type UINConfigDTO, type UINPreviewRequest, type UINSegment, type UINSegmentType, type UIN_RESET_POLICY, type UinDeps, type UnionToIntersection, type UniqueConfig, type UpdateConfigByCodeInput, type UpdateStatusRequestRepository, type UpdateUINConfigRequest, type ValidationErrorItem, commonService, customOmit, findDifferences, fromTimestampToSqlDatetime, getDynamicValue, getPattern, interpolate, objectTo2DArray, toNumberOrNull, toUINConfigDTO, uinConfigService, type updateStatusParams };
|
|
683
|
+
export { type AuditContext, type AuditContextProvider, AuditCore, type AuditLogPayload, AuditLogger, AuditProxy, type BulkAtomicResult, type BulkConfig, type BulkConflictConfig, type BulkOnConflict, 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 CrudContext, type CrudDelegate, type DataType, type DeepMerge, type DeleteParams, type DeleteRequestRepository, type Deps, type DropdownRequest, type DropdownRequestService, type DtoFromMapping, type DtoNullOnMissing, type DynamicCreateInput, type DynamicCrudConfig, type DynamicShortCode, type DynamicUpdateInput, type EmitPayload, type EmployeeCache, type ExcelConfig, type ExportExcel, type ExportExcelRequestService, type FetchRequest, type FetchRequestRepository, type FieldConfig, type FieldRules, type FieldType, type FixedSearchRequest, type FixedSearchRequestService, type Helpers, type ImportExcel, type ImportExcelRequestService, type LockUnlockParams, type LockUnlockRequestRepository, type Mapper, type MergeAll, type NewFixedSearchRequest, type NewFixedSearchRequestService, type NewSearchRequest, NotificationEmitter, type Op, type PaginatedResponse, type PathToSelectWithSelect, type PathValue, type PathsToSelectWithSelect, type Presence, type Recipient, type RelationConfig, type RelationStrategy, type RelationWriteConfig, type SearchRequest, type SearchRequestService, type ServiceCacheAdapter, type SingleValidationMapping, type SourcePath, type Store, type ToggleActive, type TxClient, type UINConfigDTO, type UINPreviewRequest, type UINSegment, type UINSegmentType, type UIN_RESET_POLICY, type UinDeps, type UnionToIntersection, type UniqueConfig, type UpdateConfigByCodeInput, type UpdateStatusRequestRepository, type UpdateUINConfigRequest, type ValidationErrorItem, commonService, customOmit, findDifferences, fromTimestampToSqlDatetime, getDynamicValue, getPattern, interpolate, objectTo2DArray, toNumberOrNull, toUINConfigDTO, uinConfigService, type updateStatusParams };
|
package/dist/index.js
CHANGED
|
@@ -1050,6 +1050,96 @@ var commonCreateUpdateRepository = (serviceDeps) => {
|
|
|
1050
1050
|
include,
|
|
1051
1051
|
select
|
|
1052
1052
|
});
|
|
1053
|
+
},
|
|
1054
|
+
resolveBulkWhere(by, row, ctx) {
|
|
1055
|
+
const out = {};
|
|
1056
|
+
for (const c of by) {
|
|
1057
|
+
const src = c.src ?? `body.${c.field}`;
|
|
1058
|
+
if (src.startsWith("body.")) out[c.field] = row[src.slice(5)];
|
|
1059
|
+
else if (src.startsWith("vars.")) out[c.field] = (ctx.vars ?? {})[src.slice(5)];
|
|
1060
|
+
else if (src.startsWith("ctx.")) out[c.field] = ctx[src.slice(4)];
|
|
1061
|
+
}
|
|
1062
|
+
return omitUndefined(out);
|
|
1063
|
+
},
|
|
1064
|
+
async commonBulkUpsertAtomic({ body, ctx, shortCodeData }) {
|
|
1065
|
+
const cfg = shortCodeData.config;
|
|
1066
|
+
const bulk = cfg.bulk;
|
|
1067
|
+
if (!bulk) throw new ErrorHandler(400, "Bulk config missing for this short code");
|
|
1068
|
+
const pk = cfg.primaryKey;
|
|
1069
|
+
const rows = body[bulk.arrayKey];
|
|
1070
|
+
const result = await db.$transaction(async (tx) => {
|
|
1071
|
+
const txModel = tx[shortCodeData.tableName];
|
|
1072
|
+
const include = cfg.response?.include;
|
|
1073
|
+
const select = cfg.response?.select ?? void 0;
|
|
1074
|
+
const conflictBy = bulk.conflict.by;
|
|
1075
|
+
const onConflict = bulk.conflict.onConflict;
|
|
1076
|
+
const makeKeyFromObj = (obj) => conflictBy.map((c) => String(obj[c.field] ?? "")).join("|");
|
|
1077
|
+
const updateFields = bulk.conflict.updateFields?.length ? new Set(bulk.conflict.updateFields) : null;
|
|
1078
|
+
const relationKeysToStrip = bulk.conflict.allowRelationUpdate === true || !cfg.relations?.length ? null : new Set(cfg.relations.map((r) => r.db));
|
|
1079
|
+
const wheres = rows.map((row, i) => {
|
|
1080
|
+
const where = this.resolveBulkWhere(conflictBy, row, ctx);
|
|
1081
|
+
if (!Object.keys(where).length) {
|
|
1082
|
+
throw new ErrorHandler(400, `Row ${i + 1}: Bulk conflict 'by' resolved to empty where`);
|
|
1083
|
+
}
|
|
1084
|
+
return where;
|
|
1085
|
+
});
|
|
1086
|
+
const existingRows = await txModel.findMany({
|
|
1087
|
+
where: { OR: wheres },
|
|
1088
|
+
select: { [pk]: true, ...Object.fromEntries(conflictBy.map((c) => [c.field, true])) }
|
|
1089
|
+
});
|
|
1090
|
+
const existingMap = /* @__PURE__ */ new Map();
|
|
1091
|
+
for (const ex of existingRows) {
|
|
1092
|
+
const key = makeKeyFromObj(ex);
|
|
1093
|
+
const id = ex[pk];
|
|
1094
|
+
if (typeof id === "number") existingMap.set(key, id);
|
|
1095
|
+
}
|
|
1096
|
+
let created = 0;
|
|
1097
|
+
let updated = 0;
|
|
1098
|
+
let skipped = 0;
|
|
1099
|
+
const createdRows = [];
|
|
1100
|
+
const updatedRows = [];
|
|
1101
|
+
for (let i = 0; i < rows.length; i++) {
|
|
1102
|
+
const row = rows[i];
|
|
1103
|
+
const key = makeKeyFromObj(wheres[i]);
|
|
1104
|
+
const existingId = existingMap.get(key);
|
|
1105
|
+
if (!existingId) {
|
|
1106
|
+
const data = buildPrismaData(cfg, "create", row, ctx);
|
|
1107
|
+
const createdRow = await txModel.create({ data, include, select });
|
|
1108
|
+
createdRows.push(createdRow);
|
|
1109
|
+
created++;
|
|
1110
|
+
continue;
|
|
1111
|
+
}
|
|
1112
|
+
if (onConflict === "error") {
|
|
1113
|
+
throw new ErrorHandler(400, `Row ${i + 1}: Record already exists`);
|
|
1114
|
+
}
|
|
1115
|
+
if (onConflict === "skip") {
|
|
1116
|
+
skipped++;
|
|
1117
|
+
continue;
|
|
1118
|
+
}
|
|
1119
|
+
let updateBody = row;
|
|
1120
|
+
if (updateFields) {
|
|
1121
|
+
const filtered = {};
|
|
1122
|
+
for (const k of updateFields) {
|
|
1123
|
+
if (row[k] !== void 0) filtered[k] = row[k];
|
|
1124
|
+
}
|
|
1125
|
+
updateBody = filtered;
|
|
1126
|
+
}
|
|
1127
|
+
if (relationKeysToStrip) {
|
|
1128
|
+
for (const k of relationKeysToStrip) delete updateBody[k];
|
|
1129
|
+
}
|
|
1130
|
+
const updateData = buildPrismaData(cfg, "update", updateBody, ctx);
|
|
1131
|
+
const updatedRow = await txModel.update({
|
|
1132
|
+
where: { [pk]: existingId },
|
|
1133
|
+
data: updateData,
|
|
1134
|
+
include,
|
|
1135
|
+
select
|
|
1136
|
+
});
|
|
1137
|
+
updatedRows.push(updatedRow);
|
|
1138
|
+
updated++;
|
|
1139
|
+
}
|
|
1140
|
+
return { total: rows.length, created, updated, skipped, createdRows, updatedRows };
|
|
1141
|
+
});
|
|
1142
|
+
return result;
|
|
1053
1143
|
}
|
|
1054
1144
|
};
|
|
1055
1145
|
};
|
|
@@ -1057,6 +1147,129 @@ var commonCreateUpdateRepository = (serviceDeps) => {
|
|
|
1057
1147
|
// src/utils/dynamicJoiBuilder.utils.ts
|
|
1058
1148
|
var import_joi = __toESM(require("joi"));
|
|
1059
1149
|
var import_dayjs = __toESM(require("dayjs"));
|
|
1150
|
+
|
|
1151
|
+
// src/utils/helper.utils.ts
|
|
1152
|
+
function customOmit(obj, keys) {
|
|
1153
|
+
const rest = { ...obj };
|
|
1154
|
+
const omitted = {};
|
|
1155
|
+
for (const key of keys) {
|
|
1156
|
+
if (key in obj) {
|
|
1157
|
+
omitted[key] = obj[key];
|
|
1158
|
+
delete rest[key];
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
return { rest, omitted };
|
|
1162
|
+
}
|
|
1163
|
+
function getDynamicValue(obj, accessorKey) {
|
|
1164
|
+
if (!accessorKey || obj == null || typeof obj !== "object") {
|
|
1165
|
+
return null;
|
|
1166
|
+
}
|
|
1167
|
+
const keys = accessorKey.split(".");
|
|
1168
|
+
let result = obj;
|
|
1169
|
+
for (const key of keys) {
|
|
1170
|
+
if (result == null || typeof result !== "object" || !(key in result)) {
|
|
1171
|
+
return null;
|
|
1172
|
+
}
|
|
1173
|
+
result = result[key];
|
|
1174
|
+
}
|
|
1175
|
+
return result === void 0 ? null : result;
|
|
1176
|
+
}
|
|
1177
|
+
function objectTo2DArray(obj, maxCols) {
|
|
1178
|
+
if (maxCols < 2) {
|
|
1179
|
+
throw new Error("maxCols must be at least 2");
|
|
1180
|
+
}
|
|
1181
|
+
const rows = [];
|
|
1182
|
+
let currentRow = [];
|
|
1183
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
1184
|
+
const pair = [key, value];
|
|
1185
|
+
if (currentRow.length + pair.length > maxCols) {
|
|
1186
|
+
if (currentRow.length > 0) {
|
|
1187
|
+
rows.push(currentRow);
|
|
1188
|
+
}
|
|
1189
|
+
currentRow = [];
|
|
1190
|
+
}
|
|
1191
|
+
currentRow.push(...pair);
|
|
1192
|
+
}
|
|
1193
|
+
if (currentRow.length > 0) {
|
|
1194
|
+
rows.push(currentRow);
|
|
1195
|
+
}
|
|
1196
|
+
return rows;
|
|
1197
|
+
}
|
|
1198
|
+
function toNumberOrNull(value) {
|
|
1199
|
+
if (typeof value === "number") {
|
|
1200
|
+
return value;
|
|
1201
|
+
}
|
|
1202
|
+
const converted = Number(value);
|
|
1203
|
+
return isNaN(converted) ? null : converted;
|
|
1204
|
+
}
|
|
1205
|
+
var getPattern = {
|
|
1206
|
+
stringBaseNum: /^[1-9][0-9]*$/,
|
|
1207
|
+
licenseTitle: /^(?=.{3,100}$)[A-Za-z0-9][A-Za-z0-9\s\-/&,.()]*$/,
|
|
1208
|
+
categoryName: /^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=[\]{};'":\\|,.<>/?]).{3,30}$/,
|
|
1209
|
+
namePattern: /^[A-Za-z\s]+$/,
|
|
1210
|
+
skuPattern: /^[A-Z0-9_-]+$/i,
|
|
1211
|
+
SlNoPattern: /^[A-Za-z0-9_-]+$/,
|
|
1212
|
+
nameWithNumPattern: /^[A-Za-z0-9\s]+$/,
|
|
1213
|
+
emailPattern: /^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$/,
|
|
1214
|
+
// phonePattern:
|
|
1215
|
+
// /^(?:\+?(\d{1,3})[\s.-]?)?(?:\(?(\d{3})\)?[\s.-]?)?(\d{3})[\s.-]?(\d{4})(?:\s*(?:x|ext)\s*(\d+))?$/,
|
|
1216
|
+
phonePattern: /^\d{9}$/,
|
|
1217
|
+
postalCodePattern: /^[0-9]{5}$/,
|
|
1218
|
+
alphanumericPattern: /^[a-zA-Z0-9]+$/,
|
|
1219
|
+
numericPattern: /^[0-9]+$/,
|
|
1220
|
+
datePattern: /^(0[1-9]|1[0-2])\/(0[1-9]|1\d|2\d|3[01])\/(19|20)\d{2}$/,
|
|
1221
|
+
timePattern: /^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9])$/,
|
|
1222
|
+
uuidPattern: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
|
|
1223
|
+
passwordPattern: /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{8,}$/,
|
|
1224
|
+
jsonPattern: /^(\[.+?\]|\{.+?\})$/,
|
|
1225
|
+
ipPattern: /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/,
|
|
1226
|
+
macAddressPattern: /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/,
|
|
1227
|
+
hexColorPattern: /^#?([a-f0-9]{6}|[a-f0-9]{3})$/,
|
|
1228
|
+
hexPattern: /^[0-9A-Fa-f]+$/,
|
|
1229
|
+
binaryPattern: /^[01]+$/,
|
|
1230
|
+
base64Pattern: /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$/,
|
|
1231
|
+
alphanumericDashPattern: /^[a-zA-Z0-9-]+$/,
|
|
1232
|
+
alphanumericDotPattern: /^[a-zA-Z0-9.]+$/,
|
|
1233
|
+
alphanumericUnderscorePattern: /^[a-zA-Z0-9_]+$/,
|
|
1234
|
+
alphanumericPlusPattern: /^[a-zA-Z0-9+]+$/,
|
|
1235
|
+
alphanumericSlashPattern: /^[a-zA-Z0-9/]+$/,
|
|
1236
|
+
alphanumericColonPattern: /^[a-zA-Z0-9:]+$/,
|
|
1237
|
+
alphanumericQuestionMarkPattern: /^[a-zA-Z0-9?]+$/,
|
|
1238
|
+
alphanumericAtPattern: /^[a-zA-Z0-9@]+$/,
|
|
1239
|
+
alphanumericHashPattern: /^[a-zA-Z0-9#]+$/,
|
|
1240
|
+
alphanumericDollarPattern: /^[a-zA-Z0-9$]+$/,
|
|
1241
|
+
alphanumericPercentPattern: /^[a-zA-Z0-9%]+$/,
|
|
1242
|
+
alphanumericAmpersandPattern: /^[a-zA-Z0-9&]+$/,
|
|
1243
|
+
alphanumericVerticalBarPattern: /^[a-zA-Z0-9|]+$/,
|
|
1244
|
+
alphanumericTildePattern: /^[a-zA-Z0-9~]+$/,
|
|
1245
|
+
alphanumericExclamationPattern: /^[a-zA-Z0-9!]+$/,
|
|
1246
|
+
alphanumericAndPattern: /^[a-zA-Z0-9&]+$/,
|
|
1247
|
+
alphanumericAsteriskPattern: /^[a-zA-Z0-9*]+$/,
|
|
1248
|
+
imagePattern: /^.*\.(jpe?g|png|gif)$/i,
|
|
1249
|
+
videoPattern: /\.(mp4|webm|ogg)$/i,
|
|
1250
|
+
audioPattern: /\.(mp3|wav)$/i,
|
|
1251
|
+
pdfPattern: /\.(pdf)$/i,
|
|
1252
|
+
docPattern: /\.(doc|docx)$/i,
|
|
1253
|
+
xlsPattern: /\.(xls|xlsx)$/i,
|
|
1254
|
+
pptPattern: /\.(ppt|pptx)$/i,
|
|
1255
|
+
zipPattern: /\.(zip)$/i,
|
|
1256
|
+
rarPattern: /\.(rar)$/i,
|
|
1257
|
+
tarPattern: /\.(tar)$/i,
|
|
1258
|
+
gzipPattern: /\.(gz|gzip)$/i,
|
|
1259
|
+
bz2Pattern: /\.(bz2)$/i,
|
|
1260
|
+
isoPattern: /\.(iso)$/i,
|
|
1261
|
+
txtPattern: /\.(txt)$/i,
|
|
1262
|
+
documentPattern: /\.(pdf|doc|docx|xls|xlsx|ppt|pptx|txt)$/i
|
|
1263
|
+
};
|
|
1264
|
+
var interpolate = (template, vars) => {
|
|
1265
|
+
return template.replace(/\{\{\s*([^}]+)\s*\}\}/g, (match, key) => {
|
|
1266
|
+
key = key.trim();
|
|
1267
|
+
return key in vars ? String(vars[key]) : "";
|
|
1268
|
+
});
|
|
1269
|
+
};
|
|
1270
|
+
var fromTimestampToSqlDatetime = (date) => date.replace("T", " ").replace("Z", "");
|
|
1271
|
+
|
|
1272
|
+
// src/utils/dynamicJoiBuilder.utils.ts
|
|
1060
1273
|
function applyNumberCompare(schema, op, ref) {
|
|
1061
1274
|
const r = import_joi.default.ref(ref);
|
|
1062
1275
|
switch (op) {
|
|
@@ -1110,9 +1323,9 @@ var buildScalar = (f, ctx, op) => {
|
|
|
1110
1323
|
if (typeof rules.min === "number") j = j.min(rules.min);
|
|
1111
1324
|
if (typeof rules.max === "number") j = j.max(rules.max);
|
|
1112
1325
|
const p = resolvePrecision(rules, ctx);
|
|
1113
|
-
if (typeof p === "number")
|
|
1326
|
+
if (typeof p === "number") j = j.precision(p);
|
|
1114
1327
|
if (rules.compare?.ref && rules.compare?.op) {
|
|
1115
|
-
|
|
1328
|
+
j = applyNumberCompare(j, rules.compare.op, rules.compare.ref);
|
|
1116
1329
|
}
|
|
1117
1330
|
s = j;
|
|
1118
1331
|
break;
|
|
@@ -1141,11 +1354,24 @@ var buildScalar = (f, ctx, op) => {
|
|
|
1141
1354
|
case "array":
|
|
1142
1355
|
s = import_joi.default.array();
|
|
1143
1356
|
break;
|
|
1357
|
+
case "file": {
|
|
1358
|
+
let j = import_joi.default.string();
|
|
1359
|
+
if (rules.trim) j = j.trim();
|
|
1360
|
+
const kind = rules.fileKind ?? "image";
|
|
1361
|
+
if (kind === "image") {
|
|
1362
|
+
j = j.pattern(getPattern.imagePattern);
|
|
1363
|
+
} else {
|
|
1364
|
+
j = j.pattern(getPattern.documentPattern);
|
|
1365
|
+
}
|
|
1366
|
+
s = j;
|
|
1367
|
+
break;
|
|
1368
|
+
}
|
|
1144
1369
|
case "json":
|
|
1145
1370
|
default:
|
|
1146
1371
|
s = import_joi.default.any();
|
|
1147
1372
|
}
|
|
1148
1373
|
if (f.allowNull) s = s.allow(null);
|
|
1374
|
+
if (f.allowEmptyString) s = s.allow("");
|
|
1149
1375
|
if (f.default !== void 0) s = s.default(f.default);
|
|
1150
1376
|
if (rules.when?.ref) {
|
|
1151
1377
|
const isVal = Array.isArray(rules.when.is) ? rules.when.is : [rules.when.is];
|
|
@@ -1196,129 +1422,10 @@ var buildJoiSchemaForOp = (cfg, op, ctx) => {
|
|
|
1196
1422
|
});
|
|
1197
1423
|
};
|
|
1198
1424
|
|
|
1199
|
-
// src/utils/helper.utils.ts
|
|
1200
|
-
function customOmit(obj, keys) {
|
|
1201
|
-
const rest = { ...obj };
|
|
1202
|
-
const omitted = {};
|
|
1203
|
-
for (const key of keys) {
|
|
1204
|
-
if (key in obj) {
|
|
1205
|
-
omitted[key] = obj[key];
|
|
1206
|
-
delete rest[key];
|
|
1207
|
-
}
|
|
1208
|
-
}
|
|
1209
|
-
return { rest, omitted };
|
|
1210
|
-
}
|
|
1211
|
-
function getDynamicValue(obj, accessorKey) {
|
|
1212
|
-
if (!accessorKey || obj == null || typeof obj !== "object") {
|
|
1213
|
-
return null;
|
|
1214
|
-
}
|
|
1215
|
-
const keys = accessorKey.split(".");
|
|
1216
|
-
let result = obj;
|
|
1217
|
-
for (const key of keys) {
|
|
1218
|
-
if (result == null || typeof result !== "object" || !(key in result)) {
|
|
1219
|
-
return null;
|
|
1220
|
-
}
|
|
1221
|
-
result = result[key];
|
|
1222
|
-
}
|
|
1223
|
-
return result === void 0 ? null : result;
|
|
1224
|
-
}
|
|
1225
|
-
function objectTo2DArray(obj, maxCols) {
|
|
1226
|
-
if (maxCols < 2) {
|
|
1227
|
-
throw new Error("maxCols must be at least 2");
|
|
1228
|
-
}
|
|
1229
|
-
const rows = [];
|
|
1230
|
-
let currentRow = [];
|
|
1231
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
1232
|
-
const pair = [key, value];
|
|
1233
|
-
if (currentRow.length + pair.length > maxCols) {
|
|
1234
|
-
if (currentRow.length > 0) {
|
|
1235
|
-
rows.push(currentRow);
|
|
1236
|
-
}
|
|
1237
|
-
currentRow = [];
|
|
1238
|
-
}
|
|
1239
|
-
currentRow.push(...pair);
|
|
1240
|
-
}
|
|
1241
|
-
if (currentRow.length > 0) {
|
|
1242
|
-
rows.push(currentRow);
|
|
1243
|
-
}
|
|
1244
|
-
return rows;
|
|
1245
|
-
}
|
|
1246
|
-
function toNumberOrNull(value) {
|
|
1247
|
-
if (typeof value === "number") {
|
|
1248
|
-
return value;
|
|
1249
|
-
}
|
|
1250
|
-
const converted = Number(value);
|
|
1251
|
-
return isNaN(converted) ? null : converted;
|
|
1252
|
-
}
|
|
1253
|
-
var getPattern = {
|
|
1254
|
-
stringBaseNum: /^[1-9][0-9]*$/,
|
|
1255
|
-
licenseTitle: /^(?=.{3,100}$)[A-Za-z0-9][A-Za-z0-9\s\-/&,.()]*$/,
|
|
1256
|
-
categoryName: /^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=[\]{};'":\\|,.<>/?]).{3,30}$/,
|
|
1257
|
-
namePattern: /^[A-Za-z\s]+$/,
|
|
1258
|
-
skuPattern: /^[A-Z0-9_-]+$/i,
|
|
1259
|
-
SlNoPattern: /^[A-Za-z0-9_-]+$/,
|
|
1260
|
-
nameWithNumPattern: /^[A-Za-z0-9\s]+$/,
|
|
1261
|
-
emailPattern: /^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$/,
|
|
1262
|
-
// phonePattern:
|
|
1263
|
-
// /^(?:\+?(\d{1,3})[\s.-]?)?(?:\(?(\d{3})\)?[\s.-]?)?(\d{3})[\s.-]?(\d{4})(?:\s*(?:x|ext)\s*(\d+))?$/,
|
|
1264
|
-
phonePattern: /^\d{9}$/,
|
|
1265
|
-
postalCodePattern: /^[0-9]{5}$/,
|
|
1266
|
-
alphanumericPattern: /^[a-zA-Z0-9]+$/,
|
|
1267
|
-
numericPattern: /^[0-9]+$/,
|
|
1268
|
-
datePattern: /^(0[1-9]|1[0-2])\/(0[1-9]|1\d|2\d|3[01])\/(19|20)\d{2}$/,
|
|
1269
|
-
timePattern: /^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9])$/,
|
|
1270
|
-
uuidPattern: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
|
|
1271
|
-
passwordPattern: /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{8,}$/,
|
|
1272
|
-
jsonPattern: /^(\[.+?\]|\{.+?\})$/,
|
|
1273
|
-
ipPattern: /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/,
|
|
1274
|
-
macAddressPattern: /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/,
|
|
1275
|
-
hexColorPattern: /^#?([a-f0-9]{6}|[a-f0-9]{3})$/,
|
|
1276
|
-
hexPattern: /^[0-9A-Fa-f]+$/,
|
|
1277
|
-
binaryPattern: /^[01]+$/,
|
|
1278
|
-
base64Pattern: /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$/,
|
|
1279
|
-
alphanumericDashPattern: /^[a-zA-Z0-9-]+$/,
|
|
1280
|
-
alphanumericDotPattern: /^[a-zA-Z0-9.]+$/,
|
|
1281
|
-
alphanumericUnderscorePattern: /^[a-zA-Z0-9_]+$/,
|
|
1282
|
-
alphanumericPlusPattern: /^[a-zA-Z0-9+]+$/,
|
|
1283
|
-
alphanumericSlashPattern: /^[a-zA-Z0-9/]+$/,
|
|
1284
|
-
alphanumericColonPattern: /^[a-zA-Z0-9:]+$/,
|
|
1285
|
-
alphanumericQuestionMarkPattern: /^[a-zA-Z0-9?]+$/,
|
|
1286
|
-
alphanumericAtPattern: /^[a-zA-Z0-9@]+$/,
|
|
1287
|
-
alphanumericHashPattern: /^[a-zA-Z0-9#]+$/,
|
|
1288
|
-
alphanumericDollarPattern: /^[a-zA-Z0-9$]+$/,
|
|
1289
|
-
alphanumericPercentPattern: /^[a-zA-Z0-9%]+$/,
|
|
1290
|
-
alphanumericAmpersandPattern: /^[a-zA-Z0-9&]+$/,
|
|
1291
|
-
alphanumericVerticalBarPattern: /^[a-zA-Z0-9|]+$/,
|
|
1292
|
-
alphanumericTildePattern: /^[a-zA-Z0-9~]+$/,
|
|
1293
|
-
alphanumericExclamationPattern: /^[a-zA-Z0-9!]+$/,
|
|
1294
|
-
alphanumericAndPattern: /^[a-zA-Z0-9&]+$/,
|
|
1295
|
-
alphanumericAsteriskPattern: /^[a-zA-Z0-9*]+$/,
|
|
1296
|
-
imagePattern: /^.*\.(jpe?g|png|gif)$/i,
|
|
1297
|
-
videoPattern: /\.(mp4|webm|ogg)$/i,
|
|
1298
|
-
audioPattern: /\.(mp3|wav)$/i,
|
|
1299
|
-
pdfPattern: /\.(pdf)$/i,
|
|
1300
|
-
docPattern: /\.(doc|docx)$/i,
|
|
1301
|
-
xlsPattern: /\.(xls|xlsx)$/i,
|
|
1302
|
-
pptPattern: /\.(ppt|pptx)$/i,
|
|
1303
|
-
zipPattern: /\.(zip)$/i,
|
|
1304
|
-
rarPattern: /\.(rar)$/i,
|
|
1305
|
-
tarPattern: /\.(tar)$/i,
|
|
1306
|
-
gzipPattern: /\.(gz|gzip)$/i,
|
|
1307
|
-
bz2Pattern: /\.(bz2)$/i,
|
|
1308
|
-
isoPattern: /\.(iso)$/i,
|
|
1309
|
-
txtPattern: /\.(txt)$/i
|
|
1310
|
-
};
|
|
1311
|
-
var interpolate = (template, vars) => {
|
|
1312
|
-
return template.replace(/\{\{\s*([^}]+)\s*\}\}/g, (match, key) => {
|
|
1313
|
-
key = key.trim();
|
|
1314
|
-
return key in vars ? String(vars[key]) : "";
|
|
1315
|
-
});
|
|
1316
|
-
};
|
|
1317
|
-
var fromTimestampToSqlDatetime = (date) => date.replace("T", " ").replace("Z", "");
|
|
1318
|
-
|
|
1319
1425
|
// src/services/common.service.ts
|
|
1320
1426
|
var import_axios = __toESM(require("axios"));
|
|
1321
1427
|
var import_exceljs = __toESM(require("exceljs"));
|
|
1428
|
+
var import_joi2 = __toESM(require("joi"));
|
|
1322
1429
|
var commonService = (serviceDeps) => {
|
|
1323
1430
|
const generateErrorMessage = serviceDeps.helpers.generateErrorMessage;
|
|
1324
1431
|
const ErrorHandler = serviceDeps.helpers.ErrorHandler;
|
|
@@ -1664,6 +1771,67 @@ var commonService = (serviceDeps) => {
|
|
|
1664
1771
|
logger.info("exiting::update::service");
|
|
1665
1772
|
return updateResult;
|
|
1666
1773
|
},
|
|
1774
|
+
async commonBulkUpsert(bulkUpsertParams) {
|
|
1775
|
+
logger.info("entering::commonBulkUpsert::service");
|
|
1776
|
+
const store = requestStorage.getStore();
|
|
1777
|
+
const currentUser = store?.user?.id ?? null;
|
|
1778
|
+
const shortCodeData = bulkUpsertParams.shortCodeData;
|
|
1779
|
+
const cfg = shortCodeData.config;
|
|
1780
|
+
if (!cfg) {
|
|
1781
|
+
throw new ErrorHandler(500, `Configuration not found for short code: ${shortCodeData.shortCode}`);
|
|
1782
|
+
}
|
|
1783
|
+
const bulk = cfg.bulk;
|
|
1784
|
+
if (!bulk) throw new ErrorHandler(400, "Bulk config missing for this short code");
|
|
1785
|
+
const ctx = {
|
|
1786
|
+
userId: currentUser ?? void 0,
|
|
1787
|
+
vars: {
|
|
1788
|
+
decimalPrecision: store?.defaultPrecision ?? 2
|
|
1789
|
+
}
|
|
1790
|
+
};
|
|
1791
|
+
const rowSchema = buildJoiSchemaForOp(cfg, "create", {
|
|
1792
|
+
decimalPrecision: ctx.vars?.decimalPrecision ?? 2
|
|
1793
|
+
});
|
|
1794
|
+
const bulkSchema = import_joi2.default.object({
|
|
1795
|
+
[bulk.arrayKey]: import_joi2.default.array().items(rowSchema).min(1).required().messages({
|
|
1796
|
+
"any.required": `"${bulk.arrayKey}" is required`,
|
|
1797
|
+
"array.base": `"${bulk.arrayKey}" must be an array`,
|
|
1798
|
+
"array.min": `"${bulk.arrayKey}" cannot be empty`
|
|
1799
|
+
})
|
|
1800
|
+
}).prefs({
|
|
1801
|
+
abortEarly: false,
|
|
1802
|
+
allowUnknown: cfg.validation.allowUnknown,
|
|
1803
|
+
stripUnknown: cfg.validation.stripUnknown,
|
|
1804
|
+
convert: cfg.validation.convert
|
|
1805
|
+
});
|
|
1806
|
+
const { value: validatedBulk, error } = bulkSchema.validate(bulkUpsertParams.body);
|
|
1807
|
+
if (error) {
|
|
1808
|
+
const messages = error.details.map((d) => d.message.replace(/['"]/g, "")).join(", ");
|
|
1809
|
+
throw new ErrorHandler(400, messages, error.details);
|
|
1810
|
+
}
|
|
1811
|
+
const commonData = await commonCreateUpdateRepositoryFactory.commonBulkUpsertAtomic({
|
|
1812
|
+
body: validatedBulk,
|
|
1813
|
+
shortCodeData,
|
|
1814
|
+
ctx
|
|
1815
|
+
});
|
|
1816
|
+
if (shortCodeData.isCacheable) {
|
|
1817
|
+
for (const row of commonData.createdRows) {
|
|
1818
|
+
await addToCache(
|
|
1819
|
+
`${REDIS_PREFIX}${MASTER_KEY_MODELS.includes(shortCodeData.tableName) ? MASTER_CACHE_KEY_NAME : CACHE_KEY_NAME}:${shortCodeData.tableName}:all`,
|
|
1820
|
+
row[cfg.primaryKey],
|
|
1821
|
+
row
|
|
1822
|
+
);
|
|
1823
|
+
}
|
|
1824
|
+
for (const row of commonData.updatedRows) {
|
|
1825
|
+
await updateCache(
|
|
1826
|
+
`${REDIS_PREFIX}${MASTER_KEY_MODELS.includes(shortCodeData.tableName) ? MASTER_CACHE_KEY_NAME : CACHE_KEY_NAME}:${shortCodeData.tableName}:all`,
|
|
1827
|
+
row.id,
|
|
1828
|
+
row
|
|
1829
|
+
);
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
logger.info("exiting::commonBulkUpsert::service");
|
|
1833
|
+
return commonData;
|
|
1834
|
+
},
|
|
1667
1835
|
async fetchImageStream(imageBaseUrl, fileName) {
|
|
1668
1836
|
const url = imageBaseUrl + fileName;
|
|
1669
1837
|
return import_axios.default.get(url, { responseType: "stream" });
|
package/dist/index.mjs
CHANGED
|
@@ -1000,6 +1000,96 @@ var commonCreateUpdateRepository = (serviceDeps) => {
|
|
|
1000
1000
|
include,
|
|
1001
1001
|
select
|
|
1002
1002
|
});
|
|
1003
|
+
},
|
|
1004
|
+
resolveBulkWhere(by, row, ctx) {
|
|
1005
|
+
const out = {};
|
|
1006
|
+
for (const c of by) {
|
|
1007
|
+
const src = c.src ?? `body.${c.field}`;
|
|
1008
|
+
if (src.startsWith("body.")) out[c.field] = row[src.slice(5)];
|
|
1009
|
+
else if (src.startsWith("vars.")) out[c.field] = (ctx.vars ?? {})[src.slice(5)];
|
|
1010
|
+
else if (src.startsWith("ctx.")) out[c.field] = ctx[src.slice(4)];
|
|
1011
|
+
}
|
|
1012
|
+
return omitUndefined(out);
|
|
1013
|
+
},
|
|
1014
|
+
async commonBulkUpsertAtomic({ body, ctx, shortCodeData }) {
|
|
1015
|
+
const cfg = shortCodeData.config;
|
|
1016
|
+
const bulk = cfg.bulk;
|
|
1017
|
+
if (!bulk) throw new ErrorHandler(400, "Bulk config missing for this short code");
|
|
1018
|
+
const pk = cfg.primaryKey;
|
|
1019
|
+
const rows = body[bulk.arrayKey];
|
|
1020
|
+
const result = await db.$transaction(async (tx) => {
|
|
1021
|
+
const txModel = tx[shortCodeData.tableName];
|
|
1022
|
+
const include = cfg.response?.include;
|
|
1023
|
+
const select = cfg.response?.select ?? void 0;
|
|
1024
|
+
const conflictBy = bulk.conflict.by;
|
|
1025
|
+
const onConflict = bulk.conflict.onConflict;
|
|
1026
|
+
const makeKeyFromObj = (obj) => conflictBy.map((c) => String(obj[c.field] ?? "")).join("|");
|
|
1027
|
+
const updateFields = bulk.conflict.updateFields?.length ? new Set(bulk.conflict.updateFields) : null;
|
|
1028
|
+
const relationKeysToStrip = bulk.conflict.allowRelationUpdate === true || !cfg.relations?.length ? null : new Set(cfg.relations.map((r) => r.db));
|
|
1029
|
+
const wheres = rows.map((row, i) => {
|
|
1030
|
+
const where = this.resolveBulkWhere(conflictBy, row, ctx);
|
|
1031
|
+
if (!Object.keys(where).length) {
|
|
1032
|
+
throw new ErrorHandler(400, `Row ${i + 1}: Bulk conflict 'by' resolved to empty where`);
|
|
1033
|
+
}
|
|
1034
|
+
return where;
|
|
1035
|
+
});
|
|
1036
|
+
const existingRows = await txModel.findMany({
|
|
1037
|
+
where: { OR: wheres },
|
|
1038
|
+
select: { [pk]: true, ...Object.fromEntries(conflictBy.map((c) => [c.field, true])) }
|
|
1039
|
+
});
|
|
1040
|
+
const existingMap = /* @__PURE__ */ new Map();
|
|
1041
|
+
for (const ex of existingRows) {
|
|
1042
|
+
const key = makeKeyFromObj(ex);
|
|
1043
|
+
const id = ex[pk];
|
|
1044
|
+
if (typeof id === "number") existingMap.set(key, id);
|
|
1045
|
+
}
|
|
1046
|
+
let created = 0;
|
|
1047
|
+
let updated = 0;
|
|
1048
|
+
let skipped = 0;
|
|
1049
|
+
const createdRows = [];
|
|
1050
|
+
const updatedRows = [];
|
|
1051
|
+
for (let i = 0; i < rows.length; i++) {
|
|
1052
|
+
const row = rows[i];
|
|
1053
|
+
const key = makeKeyFromObj(wheres[i]);
|
|
1054
|
+
const existingId = existingMap.get(key);
|
|
1055
|
+
if (!existingId) {
|
|
1056
|
+
const data = buildPrismaData(cfg, "create", row, ctx);
|
|
1057
|
+
const createdRow = await txModel.create({ data, include, select });
|
|
1058
|
+
createdRows.push(createdRow);
|
|
1059
|
+
created++;
|
|
1060
|
+
continue;
|
|
1061
|
+
}
|
|
1062
|
+
if (onConflict === "error") {
|
|
1063
|
+
throw new ErrorHandler(400, `Row ${i + 1}: Record already exists`);
|
|
1064
|
+
}
|
|
1065
|
+
if (onConflict === "skip") {
|
|
1066
|
+
skipped++;
|
|
1067
|
+
continue;
|
|
1068
|
+
}
|
|
1069
|
+
let updateBody = row;
|
|
1070
|
+
if (updateFields) {
|
|
1071
|
+
const filtered = {};
|
|
1072
|
+
for (const k of updateFields) {
|
|
1073
|
+
if (row[k] !== void 0) filtered[k] = row[k];
|
|
1074
|
+
}
|
|
1075
|
+
updateBody = filtered;
|
|
1076
|
+
}
|
|
1077
|
+
if (relationKeysToStrip) {
|
|
1078
|
+
for (const k of relationKeysToStrip) delete updateBody[k];
|
|
1079
|
+
}
|
|
1080
|
+
const updateData = buildPrismaData(cfg, "update", updateBody, ctx);
|
|
1081
|
+
const updatedRow = await txModel.update({
|
|
1082
|
+
where: { [pk]: existingId },
|
|
1083
|
+
data: updateData,
|
|
1084
|
+
include,
|
|
1085
|
+
select
|
|
1086
|
+
});
|
|
1087
|
+
updatedRows.push(updatedRow);
|
|
1088
|
+
updated++;
|
|
1089
|
+
}
|
|
1090
|
+
return { total: rows.length, created, updated, skipped, createdRows, updatedRows };
|
|
1091
|
+
});
|
|
1092
|
+
return result;
|
|
1003
1093
|
}
|
|
1004
1094
|
};
|
|
1005
1095
|
};
|
|
@@ -1007,6 +1097,129 @@ var commonCreateUpdateRepository = (serviceDeps) => {
|
|
|
1007
1097
|
// src/utils/dynamicJoiBuilder.utils.ts
|
|
1008
1098
|
import Joi from "joi";
|
|
1009
1099
|
import dayjs from "dayjs";
|
|
1100
|
+
|
|
1101
|
+
// src/utils/helper.utils.ts
|
|
1102
|
+
function customOmit(obj, keys) {
|
|
1103
|
+
const rest = { ...obj };
|
|
1104
|
+
const omitted = {};
|
|
1105
|
+
for (const key of keys) {
|
|
1106
|
+
if (key in obj) {
|
|
1107
|
+
omitted[key] = obj[key];
|
|
1108
|
+
delete rest[key];
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
return { rest, omitted };
|
|
1112
|
+
}
|
|
1113
|
+
function getDynamicValue(obj, accessorKey) {
|
|
1114
|
+
if (!accessorKey || obj == null || typeof obj !== "object") {
|
|
1115
|
+
return null;
|
|
1116
|
+
}
|
|
1117
|
+
const keys = accessorKey.split(".");
|
|
1118
|
+
let result = obj;
|
|
1119
|
+
for (const key of keys) {
|
|
1120
|
+
if (result == null || typeof result !== "object" || !(key in result)) {
|
|
1121
|
+
return null;
|
|
1122
|
+
}
|
|
1123
|
+
result = result[key];
|
|
1124
|
+
}
|
|
1125
|
+
return result === void 0 ? null : result;
|
|
1126
|
+
}
|
|
1127
|
+
function objectTo2DArray(obj, maxCols) {
|
|
1128
|
+
if (maxCols < 2) {
|
|
1129
|
+
throw new Error("maxCols must be at least 2");
|
|
1130
|
+
}
|
|
1131
|
+
const rows = [];
|
|
1132
|
+
let currentRow = [];
|
|
1133
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
1134
|
+
const pair = [key, value];
|
|
1135
|
+
if (currentRow.length + pair.length > maxCols) {
|
|
1136
|
+
if (currentRow.length > 0) {
|
|
1137
|
+
rows.push(currentRow);
|
|
1138
|
+
}
|
|
1139
|
+
currentRow = [];
|
|
1140
|
+
}
|
|
1141
|
+
currentRow.push(...pair);
|
|
1142
|
+
}
|
|
1143
|
+
if (currentRow.length > 0) {
|
|
1144
|
+
rows.push(currentRow);
|
|
1145
|
+
}
|
|
1146
|
+
return rows;
|
|
1147
|
+
}
|
|
1148
|
+
function toNumberOrNull(value) {
|
|
1149
|
+
if (typeof value === "number") {
|
|
1150
|
+
return value;
|
|
1151
|
+
}
|
|
1152
|
+
const converted = Number(value);
|
|
1153
|
+
return isNaN(converted) ? null : converted;
|
|
1154
|
+
}
|
|
1155
|
+
var getPattern = {
|
|
1156
|
+
stringBaseNum: /^[1-9][0-9]*$/,
|
|
1157
|
+
licenseTitle: /^(?=.{3,100}$)[A-Za-z0-9][A-Za-z0-9\s\-/&,.()]*$/,
|
|
1158
|
+
categoryName: /^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=[\]{};'":\\|,.<>/?]).{3,30}$/,
|
|
1159
|
+
namePattern: /^[A-Za-z\s]+$/,
|
|
1160
|
+
skuPattern: /^[A-Z0-9_-]+$/i,
|
|
1161
|
+
SlNoPattern: /^[A-Za-z0-9_-]+$/,
|
|
1162
|
+
nameWithNumPattern: /^[A-Za-z0-9\s]+$/,
|
|
1163
|
+
emailPattern: /^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$/,
|
|
1164
|
+
// phonePattern:
|
|
1165
|
+
// /^(?:\+?(\d{1,3})[\s.-]?)?(?:\(?(\d{3})\)?[\s.-]?)?(\d{3})[\s.-]?(\d{4})(?:\s*(?:x|ext)\s*(\d+))?$/,
|
|
1166
|
+
phonePattern: /^\d{9}$/,
|
|
1167
|
+
postalCodePattern: /^[0-9]{5}$/,
|
|
1168
|
+
alphanumericPattern: /^[a-zA-Z0-9]+$/,
|
|
1169
|
+
numericPattern: /^[0-9]+$/,
|
|
1170
|
+
datePattern: /^(0[1-9]|1[0-2])\/(0[1-9]|1\d|2\d|3[01])\/(19|20)\d{2}$/,
|
|
1171
|
+
timePattern: /^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9])$/,
|
|
1172
|
+
uuidPattern: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
|
|
1173
|
+
passwordPattern: /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{8,}$/,
|
|
1174
|
+
jsonPattern: /^(\[.+?\]|\{.+?\})$/,
|
|
1175
|
+
ipPattern: /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/,
|
|
1176
|
+
macAddressPattern: /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/,
|
|
1177
|
+
hexColorPattern: /^#?([a-f0-9]{6}|[a-f0-9]{3})$/,
|
|
1178
|
+
hexPattern: /^[0-9A-Fa-f]+$/,
|
|
1179
|
+
binaryPattern: /^[01]+$/,
|
|
1180
|
+
base64Pattern: /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$/,
|
|
1181
|
+
alphanumericDashPattern: /^[a-zA-Z0-9-]+$/,
|
|
1182
|
+
alphanumericDotPattern: /^[a-zA-Z0-9.]+$/,
|
|
1183
|
+
alphanumericUnderscorePattern: /^[a-zA-Z0-9_]+$/,
|
|
1184
|
+
alphanumericPlusPattern: /^[a-zA-Z0-9+]+$/,
|
|
1185
|
+
alphanumericSlashPattern: /^[a-zA-Z0-9/]+$/,
|
|
1186
|
+
alphanumericColonPattern: /^[a-zA-Z0-9:]+$/,
|
|
1187
|
+
alphanumericQuestionMarkPattern: /^[a-zA-Z0-9?]+$/,
|
|
1188
|
+
alphanumericAtPattern: /^[a-zA-Z0-9@]+$/,
|
|
1189
|
+
alphanumericHashPattern: /^[a-zA-Z0-9#]+$/,
|
|
1190
|
+
alphanumericDollarPattern: /^[a-zA-Z0-9$]+$/,
|
|
1191
|
+
alphanumericPercentPattern: /^[a-zA-Z0-9%]+$/,
|
|
1192
|
+
alphanumericAmpersandPattern: /^[a-zA-Z0-9&]+$/,
|
|
1193
|
+
alphanumericVerticalBarPattern: /^[a-zA-Z0-9|]+$/,
|
|
1194
|
+
alphanumericTildePattern: /^[a-zA-Z0-9~]+$/,
|
|
1195
|
+
alphanumericExclamationPattern: /^[a-zA-Z0-9!]+$/,
|
|
1196
|
+
alphanumericAndPattern: /^[a-zA-Z0-9&]+$/,
|
|
1197
|
+
alphanumericAsteriskPattern: /^[a-zA-Z0-9*]+$/,
|
|
1198
|
+
imagePattern: /^.*\.(jpe?g|png|gif)$/i,
|
|
1199
|
+
videoPattern: /\.(mp4|webm|ogg)$/i,
|
|
1200
|
+
audioPattern: /\.(mp3|wav)$/i,
|
|
1201
|
+
pdfPattern: /\.(pdf)$/i,
|
|
1202
|
+
docPattern: /\.(doc|docx)$/i,
|
|
1203
|
+
xlsPattern: /\.(xls|xlsx)$/i,
|
|
1204
|
+
pptPattern: /\.(ppt|pptx)$/i,
|
|
1205
|
+
zipPattern: /\.(zip)$/i,
|
|
1206
|
+
rarPattern: /\.(rar)$/i,
|
|
1207
|
+
tarPattern: /\.(tar)$/i,
|
|
1208
|
+
gzipPattern: /\.(gz|gzip)$/i,
|
|
1209
|
+
bz2Pattern: /\.(bz2)$/i,
|
|
1210
|
+
isoPattern: /\.(iso)$/i,
|
|
1211
|
+
txtPattern: /\.(txt)$/i,
|
|
1212
|
+
documentPattern: /\.(pdf|doc|docx|xls|xlsx|ppt|pptx|txt)$/i
|
|
1213
|
+
};
|
|
1214
|
+
var interpolate = (template, vars) => {
|
|
1215
|
+
return template.replace(/\{\{\s*([^}]+)\s*\}\}/g, (match, key) => {
|
|
1216
|
+
key = key.trim();
|
|
1217
|
+
return key in vars ? String(vars[key]) : "";
|
|
1218
|
+
});
|
|
1219
|
+
};
|
|
1220
|
+
var fromTimestampToSqlDatetime = (date) => date.replace("T", " ").replace("Z", "");
|
|
1221
|
+
|
|
1222
|
+
// src/utils/dynamicJoiBuilder.utils.ts
|
|
1010
1223
|
function applyNumberCompare(schema, op, ref) {
|
|
1011
1224
|
const r = Joi.ref(ref);
|
|
1012
1225
|
switch (op) {
|
|
@@ -1060,9 +1273,9 @@ var buildScalar = (f, ctx, op) => {
|
|
|
1060
1273
|
if (typeof rules.min === "number") j = j.min(rules.min);
|
|
1061
1274
|
if (typeof rules.max === "number") j = j.max(rules.max);
|
|
1062
1275
|
const p = resolvePrecision(rules, ctx);
|
|
1063
|
-
if (typeof p === "number")
|
|
1276
|
+
if (typeof p === "number") j = j.precision(p);
|
|
1064
1277
|
if (rules.compare?.ref && rules.compare?.op) {
|
|
1065
|
-
|
|
1278
|
+
j = applyNumberCompare(j, rules.compare.op, rules.compare.ref);
|
|
1066
1279
|
}
|
|
1067
1280
|
s = j;
|
|
1068
1281
|
break;
|
|
@@ -1091,11 +1304,24 @@ var buildScalar = (f, ctx, op) => {
|
|
|
1091
1304
|
case "array":
|
|
1092
1305
|
s = Joi.array();
|
|
1093
1306
|
break;
|
|
1307
|
+
case "file": {
|
|
1308
|
+
let j = Joi.string();
|
|
1309
|
+
if (rules.trim) j = j.trim();
|
|
1310
|
+
const kind = rules.fileKind ?? "image";
|
|
1311
|
+
if (kind === "image") {
|
|
1312
|
+
j = j.pattern(getPattern.imagePattern);
|
|
1313
|
+
} else {
|
|
1314
|
+
j = j.pattern(getPattern.documentPattern);
|
|
1315
|
+
}
|
|
1316
|
+
s = j;
|
|
1317
|
+
break;
|
|
1318
|
+
}
|
|
1094
1319
|
case "json":
|
|
1095
1320
|
default:
|
|
1096
1321
|
s = Joi.any();
|
|
1097
1322
|
}
|
|
1098
1323
|
if (f.allowNull) s = s.allow(null);
|
|
1324
|
+
if (f.allowEmptyString) s = s.allow("");
|
|
1099
1325
|
if (f.default !== void 0) s = s.default(f.default);
|
|
1100
1326
|
if (rules.when?.ref) {
|
|
1101
1327
|
const isVal = Array.isArray(rules.when.is) ? rules.when.is : [rules.when.is];
|
|
@@ -1146,129 +1372,10 @@ var buildJoiSchemaForOp = (cfg, op, ctx) => {
|
|
|
1146
1372
|
});
|
|
1147
1373
|
};
|
|
1148
1374
|
|
|
1149
|
-
// src/utils/helper.utils.ts
|
|
1150
|
-
function customOmit(obj, keys) {
|
|
1151
|
-
const rest = { ...obj };
|
|
1152
|
-
const omitted = {};
|
|
1153
|
-
for (const key of keys) {
|
|
1154
|
-
if (key in obj) {
|
|
1155
|
-
omitted[key] = obj[key];
|
|
1156
|
-
delete rest[key];
|
|
1157
|
-
}
|
|
1158
|
-
}
|
|
1159
|
-
return { rest, omitted };
|
|
1160
|
-
}
|
|
1161
|
-
function getDynamicValue(obj, accessorKey) {
|
|
1162
|
-
if (!accessorKey || obj == null || typeof obj !== "object") {
|
|
1163
|
-
return null;
|
|
1164
|
-
}
|
|
1165
|
-
const keys = accessorKey.split(".");
|
|
1166
|
-
let result = obj;
|
|
1167
|
-
for (const key of keys) {
|
|
1168
|
-
if (result == null || typeof result !== "object" || !(key in result)) {
|
|
1169
|
-
return null;
|
|
1170
|
-
}
|
|
1171
|
-
result = result[key];
|
|
1172
|
-
}
|
|
1173
|
-
return result === void 0 ? null : result;
|
|
1174
|
-
}
|
|
1175
|
-
function objectTo2DArray(obj, maxCols) {
|
|
1176
|
-
if (maxCols < 2) {
|
|
1177
|
-
throw new Error("maxCols must be at least 2");
|
|
1178
|
-
}
|
|
1179
|
-
const rows = [];
|
|
1180
|
-
let currentRow = [];
|
|
1181
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
1182
|
-
const pair = [key, value];
|
|
1183
|
-
if (currentRow.length + pair.length > maxCols) {
|
|
1184
|
-
if (currentRow.length > 0) {
|
|
1185
|
-
rows.push(currentRow);
|
|
1186
|
-
}
|
|
1187
|
-
currentRow = [];
|
|
1188
|
-
}
|
|
1189
|
-
currentRow.push(...pair);
|
|
1190
|
-
}
|
|
1191
|
-
if (currentRow.length > 0) {
|
|
1192
|
-
rows.push(currentRow);
|
|
1193
|
-
}
|
|
1194
|
-
return rows;
|
|
1195
|
-
}
|
|
1196
|
-
function toNumberOrNull(value) {
|
|
1197
|
-
if (typeof value === "number") {
|
|
1198
|
-
return value;
|
|
1199
|
-
}
|
|
1200
|
-
const converted = Number(value);
|
|
1201
|
-
return isNaN(converted) ? null : converted;
|
|
1202
|
-
}
|
|
1203
|
-
var getPattern = {
|
|
1204
|
-
stringBaseNum: /^[1-9][0-9]*$/,
|
|
1205
|
-
licenseTitle: /^(?=.{3,100}$)[A-Za-z0-9][A-Za-z0-9\s\-/&,.()]*$/,
|
|
1206
|
-
categoryName: /^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=[\]{};'":\\|,.<>/?]).{3,30}$/,
|
|
1207
|
-
namePattern: /^[A-Za-z\s]+$/,
|
|
1208
|
-
skuPattern: /^[A-Z0-9_-]+$/i,
|
|
1209
|
-
SlNoPattern: /^[A-Za-z0-9_-]+$/,
|
|
1210
|
-
nameWithNumPattern: /^[A-Za-z0-9\s]+$/,
|
|
1211
|
-
emailPattern: /^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$/,
|
|
1212
|
-
// phonePattern:
|
|
1213
|
-
// /^(?:\+?(\d{1,3})[\s.-]?)?(?:\(?(\d{3})\)?[\s.-]?)?(\d{3})[\s.-]?(\d{4})(?:\s*(?:x|ext)\s*(\d+))?$/,
|
|
1214
|
-
phonePattern: /^\d{9}$/,
|
|
1215
|
-
postalCodePattern: /^[0-9]{5}$/,
|
|
1216
|
-
alphanumericPattern: /^[a-zA-Z0-9]+$/,
|
|
1217
|
-
numericPattern: /^[0-9]+$/,
|
|
1218
|
-
datePattern: /^(0[1-9]|1[0-2])\/(0[1-9]|1\d|2\d|3[01])\/(19|20)\d{2}$/,
|
|
1219
|
-
timePattern: /^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9])$/,
|
|
1220
|
-
uuidPattern: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
|
|
1221
|
-
passwordPattern: /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{8,}$/,
|
|
1222
|
-
jsonPattern: /^(\[.+?\]|\{.+?\})$/,
|
|
1223
|
-
ipPattern: /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/,
|
|
1224
|
-
macAddressPattern: /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/,
|
|
1225
|
-
hexColorPattern: /^#?([a-f0-9]{6}|[a-f0-9]{3})$/,
|
|
1226
|
-
hexPattern: /^[0-9A-Fa-f]+$/,
|
|
1227
|
-
binaryPattern: /^[01]+$/,
|
|
1228
|
-
base64Pattern: /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$/,
|
|
1229
|
-
alphanumericDashPattern: /^[a-zA-Z0-9-]+$/,
|
|
1230
|
-
alphanumericDotPattern: /^[a-zA-Z0-9.]+$/,
|
|
1231
|
-
alphanumericUnderscorePattern: /^[a-zA-Z0-9_]+$/,
|
|
1232
|
-
alphanumericPlusPattern: /^[a-zA-Z0-9+]+$/,
|
|
1233
|
-
alphanumericSlashPattern: /^[a-zA-Z0-9/]+$/,
|
|
1234
|
-
alphanumericColonPattern: /^[a-zA-Z0-9:]+$/,
|
|
1235
|
-
alphanumericQuestionMarkPattern: /^[a-zA-Z0-9?]+$/,
|
|
1236
|
-
alphanumericAtPattern: /^[a-zA-Z0-9@]+$/,
|
|
1237
|
-
alphanumericHashPattern: /^[a-zA-Z0-9#]+$/,
|
|
1238
|
-
alphanumericDollarPattern: /^[a-zA-Z0-9$]+$/,
|
|
1239
|
-
alphanumericPercentPattern: /^[a-zA-Z0-9%]+$/,
|
|
1240
|
-
alphanumericAmpersandPattern: /^[a-zA-Z0-9&]+$/,
|
|
1241
|
-
alphanumericVerticalBarPattern: /^[a-zA-Z0-9|]+$/,
|
|
1242
|
-
alphanumericTildePattern: /^[a-zA-Z0-9~]+$/,
|
|
1243
|
-
alphanumericExclamationPattern: /^[a-zA-Z0-9!]+$/,
|
|
1244
|
-
alphanumericAndPattern: /^[a-zA-Z0-9&]+$/,
|
|
1245
|
-
alphanumericAsteriskPattern: /^[a-zA-Z0-9*]+$/,
|
|
1246
|
-
imagePattern: /^.*\.(jpe?g|png|gif)$/i,
|
|
1247
|
-
videoPattern: /\.(mp4|webm|ogg)$/i,
|
|
1248
|
-
audioPattern: /\.(mp3|wav)$/i,
|
|
1249
|
-
pdfPattern: /\.(pdf)$/i,
|
|
1250
|
-
docPattern: /\.(doc|docx)$/i,
|
|
1251
|
-
xlsPattern: /\.(xls|xlsx)$/i,
|
|
1252
|
-
pptPattern: /\.(ppt|pptx)$/i,
|
|
1253
|
-
zipPattern: /\.(zip)$/i,
|
|
1254
|
-
rarPattern: /\.(rar)$/i,
|
|
1255
|
-
tarPattern: /\.(tar)$/i,
|
|
1256
|
-
gzipPattern: /\.(gz|gzip)$/i,
|
|
1257
|
-
bz2Pattern: /\.(bz2)$/i,
|
|
1258
|
-
isoPattern: /\.(iso)$/i,
|
|
1259
|
-
txtPattern: /\.(txt)$/i
|
|
1260
|
-
};
|
|
1261
|
-
var interpolate = (template, vars) => {
|
|
1262
|
-
return template.replace(/\{\{\s*([^}]+)\s*\}\}/g, (match, key) => {
|
|
1263
|
-
key = key.trim();
|
|
1264
|
-
return key in vars ? String(vars[key]) : "";
|
|
1265
|
-
});
|
|
1266
|
-
};
|
|
1267
|
-
var fromTimestampToSqlDatetime = (date) => date.replace("T", " ").replace("Z", "");
|
|
1268
|
-
|
|
1269
1375
|
// src/services/common.service.ts
|
|
1270
1376
|
import axios from "axios";
|
|
1271
1377
|
import ExcelJs from "exceljs";
|
|
1378
|
+
import Joi2 from "joi";
|
|
1272
1379
|
var commonService = (serviceDeps) => {
|
|
1273
1380
|
const generateErrorMessage = serviceDeps.helpers.generateErrorMessage;
|
|
1274
1381
|
const ErrorHandler = serviceDeps.helpers.ErrorHandler;
|
|
@@ -1614,6 +1721,67 @@ var commonService = (serviceDeps) => {
|
|
|
1614
1721
|
logger.info("exiting::update::service");
|
|
1615
1722
|
return updateResult;
|
|
1616
1723
|
},
|
|
1724
|
+
async commonBulkUpsert(bulkUpsertParams) {
|
|
1725
|
+
logger.info("entering::commonBulkUpsert::service");
|
|
1726
|
+
const store = requestStorage.getStore();
|
|
1727
|
+
const currentUser = store?.user?.id ?? null;
|
|
1728
|
+
const shortCodeData = bulkUpsertParams.shortCodeData;
|
|
1729
|
+
const cfg = shortCodeData.config;
|
|
1730
|
+
if (!cfg) {
|
|
1731
|
+
throw new ErrorHandler(500, `Configuration not found for short code: ${shortCodeData.shortCode}`);
|
|
1732
|
+
}
|
|
1733
|
+
const bulk = cfg.bulk;
|
|
1734
|
+
if (!bulk) throw new ErrorHandler(400, "Bulk config missing for this short code");
|
|
1735
|
+
const ctx = {
|
|
1736
|
+
userId: currentUser ?? void 0,
|
|
1737
|
+
vars: {
|
|
1738
|
+
decimalPrecision: store?.defaultPrecision ?? 2
|
|
1739
|
+
}
|
|
1740
|
+
};
|
|
1741
|
+
const rowSchema = buildJoiSchemaForOp(cfg, "create", {
|
|
1742
|
+
decimalPrecision: ctx.vars?.decimalPrecision ?? 2
|
|
1743
|
+
});
|
|
1744
|
+
const bulkSchema = Joi2.object({
|
|
1745
|
+
[bulk.arrayKey]: Joi2.array().items(rowSchema).min(1).required().messages({
|
|
1746
|
+
"any.required": `"${bulk.arrayKey}" is required`,
|
|
1747
|
+
"array.base": `"${bulk.arrayKey}" must be an array`,
|
|
1748
|
+
"array.min": `"${bulk.arrayKey}" cannot be empty`
|
|
1749
|
+
})
|
|
1750
|
+
}).prefs({
|
|
1751
|
+
abortEarly: false,
|
|
1752
|
+
allowUnknown: cfg.validation.allowUnknown,
|
|
1753
|
+
stripUnknown: cfg.validation.stripUnknown,
|
|
1754
|
+
convert: cfg.validation.convert
|
|
1755
|
+
});
|
|
1756
|
+
const { value: validatedBulk, error } = bulkSchema.validate(bulkUpsertParams.body);
|
|
1757
|
+
if (error) {
|
|
1758
|
+
const messages = error.details.map((d) => d.message.replace(/['"]/g, "")).join(", ");
|
|
1759
|
+
throw new ErrorHandler(400, messages, error.details);
|
|
1760
|
+
}
|
|
1761
|
+
const commonData = await commonCreateUpdateRepositoryFactory.commonBulkUpsertAtomic({
|
|
1762
|
+
body: validatedBulk,
|
|
1763
|
+
shortCodeData,
|
|
1764
|
+
ctx
|
|
1765
|
+
});
|
|
1766
|
+
if (shortCodeData.isCacheable) {
|
|
1767
|
+
for (const row of commonData.createdRows) {
|
|
1768
|
+
await addToCache(
|
|
1769
|
+
`${REDIS_PREFIX}${MASTER_KEY_MODELS.includes(shortCodeData.tableName) ? MASTER_CACHE_KEY_NAME : CACHE_KEY_NAME}:${shortCodeData.tableName}:all`,
|
|
1770
|
+
row[cfg.primaryKey],
|
|
1771
|
+
row
|
|
1772
|
+
);
|
|
1773
|
+
}
|
|
1774
|
+
for (const row of commonData.updatedRows) {
|
|
1775
|
+
await updateCache(
|
|
1776
|
+
`${REDIS_PREFIX}${MASTER_KEY_MODELS.includes(shortCodeData.tableName) ? MASTER_CACHE_KEY_NAME : CACHE_KEY_NAME}:${shortCodeData.tableName}:all`,
|
|
1777
|
+
row.id,
|
|
1778
|
+
row
|
|
1779
|
+
);
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
logger.info("exiting::commonBulkUpsert::service");
|
|
1783
|
+
return commonData;
|
|
1784
|
+
},
|
|
1617
1785
|
async fetchImageStream(imageBaseUrl, fileName) {
|
|
1618
1786
|
const url = imageBaseUrl + fileName;
|
|
1619
1787
|
return axios.get(url, { responseType: "stream" });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "av6-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "dist/index.mjs",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -9,18 +9,20 @@
|
|
|
9
9
|
"license": "ISC",
|
|
10
10
|
"scripts": {
|
|
11
11
|
"build": "npm run format && tsup",
|
|
12
|
+
"p:gen": "prisma generate",
|
|
12
13
|
"format": "prettier --write **/*.ts"
|
|
13
14
|
},
|
|
14
15
|
"devDependencies": {
|
|
16
|
+
"@prisma/client": "^6.19.0",
|
|
15
17
|
"@types/nodemailer": "^7.0.3",
|
|
16
18
|
"tsup": "^8.5.0",
|
|
17
19
|
"typescript": "^5.9.2"
|
|
18
20
|
},
|
|
19
21
|
"peerDependencies": {
|
|
22
|
+
"@prisma/client": "^6.19.0",
|
|
20
23
|
"winston": "^3.17.0"
|
|
21
24
|
},
|
|
22
25
|
"dependencies": {
|
|
23
|
-
"@prisma/client": "^6.19.0",
|
|
24
26
|
"axios": "^1.11.0",
|
|
25
27
|
"exceljs": "^4.4.0",
|
|
26
28
|
"handlebars": "^4.7.8",
|