@solidxai/core 0.1.11-beta.0 → 0.1.11-beta.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/CLAUDE.md +26 -0
- package/dist/controllers/service.controller.d.ts +1 -0
- package/dist/controllers/service.controller.d.ts.map +1 -1
- package/dist/controllers/service.controller.js +2 -2
- package/dist/controllers/service.controller.js.map +1 -1
- package/dist/helpers/field-crud-managers/IntFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/IntFieldCrudManager.js +4 -1
- package/dist/helpers/field-crud-managers/IntFieldCrudManager.js.map +1 -1
- package/dist/helpers/solid-registry.d.ts +2 -1
- package/dist/helpers/solid-registry.d.ts.map +1 -1
- package/dist/helpers/solid-registry.js.map +1 -1
- package/dist/repository/scheduled-job.repository.d.ts +3 -0
- package/dist/repository/scheduled-job.repository.d.ts.map +1 -1
- package/dist/repository/scheduled-job.repository.js +60 -0
- package/dist/repository/scheduled-job.repository.js.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.d.ts +37 -2
- package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.js +1071 -232
- package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
- package/dist/seeders/seed-data/solid-core-metadata.json +7 -0
- package/dist/services/action-metadata.service.d.ts +7 -0
- package/dist/services/action-metadata.service.d.ts.map +1 -1
- package/dist/services/action-metadata.service.js +76 -3
- package/dist/services/action-metadata.service.js.map +1 -1
- package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.d.ts.map +1 -1
- package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js +6 -5
- package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js.map +1 -1
- package/dist/services/locale.service.d.ts +14 -0
- package/dist/services/locale.service.d.ts.map +1 -1
- package/dist/services/locale.service.js +83 -0
- package/dist/services/locale.service.js.map +1 -1
- package/dist/services/role-metadata.service.d.ts +5 -0
- package/dist/services/role-metadata.service.d.ts.map +1 -1
- package/dist/services/role-metadata.service.js +95 -33
- package/dist/services/role-metadata.service.js.map +1 -1
- package/dist/services/view-metadata.service.d.ts +6 -0
- package/dist/services/view-metadata.service.d.ts.map +1 -1
- package/dist/services/view-metadata.service.js +70 -8
- package/dist/services/view-metadata.service.js.map +1 -1
- package/dist/subscribers/audit.subscriber.d.ts +2 -0
- package/dist/subscribers/audit.subscriber.d.ts.map +1 -1
- package/dist/subscribers/audit.subscriber.js +25 -6
- package/dist/subscribers/audit.subscriber.js.map +1 -1
- package/dist/subscribers/computed-entity-field.subscriber.d.ts.map +1 -1
- package/dist/subscribers/computed-entity-field.subscriber.js +1 -0
- package/dist/subscribers/computed-entity-field.subscriber.js.map +1 -1
- package/dist/subscribers/created-by-updated-by.subscriber.d.ts.map +1 -1
- package/dist/subscribers/created-by-updated-by.subscriber.js.map +1 -1
- package/dist/subscribers/field-metadata.subscriber.d.ts.map +1 -1
- package/dist/subscribers/field-metadata.subscriber.js.map +1 -1
- package/package.json +1 -1
- package/src/controllers/service.controller.ts +3 -2
- package/src/helpers/field-crud-managers/IntFieldCrudManager.ts +4 -1
- package/src/helpers/solid-registry.ts +7 -1
- package/src/repository/scheduled-job.repository.ts +73 -0
- package/src/seeders/module-metadata-seeder.service.ts +1295 -264
- package/src/seeders/seed-data/solid-core-metadata.json +7 -0
- package/src/services/action-metadata.service.ts +87 -2
- package/src/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.ts +10 -5
- package/src/services/locale.service.ts +111 -3
- package/src/services/role-metadata.service.ts +112 -49
- package/src/services/view-metadata.service.ts +83 -9
- package/src/subscribers/audit.subscriber.ts +34 -14
- package/src/subscribers/computed-entity-field.subscriber.ts +1 -0
- package/src/subscribers/created-by-updated-by.subscriber.ts +3 -0
- package/src/subscribers/field-metadata.subscriber.ts +3 -0
|
@@ -7,6 +7,13 @@ export declare class ActionMetadataService extends CRUDService<ActionMetadata> {
|
|
|
7
7
|
readonly entityManager: EntityManager;
|
|
8
8
|
readonly repo: ActionMetadataRepository;
|
|
9
9
|
readonly moduleRef: ModuleRef;
|
|
10
|
+
private readonly logger;
|
|
11
|
+
private readonly comparableFields;
|
|
12
|
+
private readonly relationCompareFields;
|
|
13
|
+
private readonly jsonCompareFields;
|
|
14
|
+
private normalizeJsonFieldValue;
|
|
15
|
+
private getCanonicalJsonFieldString;
|
|
16
|
+
private hasChanges;
|
|
10
17
|
constructor(entityManager: EntityManager, repo: ActionMetadataRepository, moduleRef: ModuleRef);
|
|
11
18
|
findOneByUserKey(name: string, relations?: {}): Promise<ActionMetadata>;
|
|
12
19
|
upsert(updateSolidActionDto: any): Promise<any>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-metadata.service.d.ts","sourceRoot":"","sources":["../../src/services/action-metadata.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxC,OAAO,EAAE,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AACrF,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEpE,qBACa,qBAAsB,SAAQ,WAAW,CAAC,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"action-metadata.service.d.ts","sourceRoot":"","sources":["../../src/services/action-metadata.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxC,OAAO,EAAE,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AACrF,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEpE,qBACa,qBAAsB,SAAQ,WAAW,CAAC,cAAc,CAAC;IA4ElE,QAAQ,CAAC,aAAa,EAAE,aAAa;IAGrC,QAAQ,CAAC,IAAI,EAAE,wBAAwB;IACvC,QAAQ,CAAC,SAAS,EAAE,SAAS;IA/E/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IACjE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAYtB;IACX,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAwC;IAC9E,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAkC;IAEpE,OAAO,CAAC,uBAAuB;IAgC/B,OAAO,CAAC,2BAA2B;IAInC,OAAO,CAAC,UAAU;gBAsBP,aAAa,EAAE,aAAa,EAG5B,IAAI,EAAE,wBAAwB,EAC9B,SAAS,EAAE,SAAS;IAMzB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,KAAK;IAU7C,MAAM,CAAC,oBAAoB,EAAE,GAAG;CAgCvC"}
|
|
@@ -11,6 +11,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
12
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
13
|
};
|
|
14
|
+
var ActionMetadataService_1;
|
|
14
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
16
|
exports.ActionMetadataService = void 0;
|
|
16
17
|
const common_1 = require("@nestjs/common");
|
|
@@ -19,12 +20,74 @@ const typeorm_1 = require("@nestjs/typeorm");
|
|
|
19
20
|
const crud_service_1 = require("./crud.service");
|
|
20
21
|
const typeorm_2 = require("typeorm");
|
|
21
22
|
const action_metadata_repository_1 = require("../repository/action-metadata.repository");
|
|
22
|
-
let ActionMetadataService = class ActionMetadataService extends crud_service_1.CRUDService {
|
|
23
|
+
let ActionMetadataService = ActionMetadataService_1 = class ActionMetadataService extends crud_service_1.CRUDService {
|
|
24
|
+
normalizeJsonFieldValue(value) {
|
|
25
|
+
if (typeof value === 'string') {
|
|
26
|
+
const trimmedValue = value.trim();
|
|
27
|
+
if ((trimmedValue.startsWith('{') && trimmedValue.endsWith('}')) ||
|
|
28
|
+
(trimmedValue.startsWith('[') && trimmedValue.endsWith(']'))) {
|
|
29
|
+
try {
|
|
30
|
+
return this.normalizeJsonFieldValue(JSON.parse(trimmedValue));
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
if (Array.isArray(value)) {
|
|
39
|
+
return value.map((item) => this.normalizeJsonFieldValue(item));
|
|
40
|
+
}
|
|
41
|
+
if (value && typeof value === 'object') {
|
|
42
|
+
return Object.keys(value)
|
|
43
|
+
.sort()
|
|
44
|
+
.reduce((result, key) => {
|
|
45
|
+
result[key] = this.normalizeJsonFieldValue(value[key]);
|
|
46
|
+
return result;
|
|
47
|
+
}, {});
|
|
48
|
+
}
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
getCanonicalJsonFieldString(value) {
|
|
52
|
+
return JSON.stringify(this.normalizeJsonFieldValue(value) ?? null);
|
|
53
|
+
}
|
|
54
|
+
hasChanges(existingSolidAction, updateSolidActionDto) {
|
|
55
|
+
return this.comparableFields.some((key) => {
|
|
56
|
+
const value = updateSolidActionDto[key];
|
|
57
|
+
if (typeof value === 'undefined') {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
if (this.relationCompareFields.has(key)) {
|
|
61
|
+
const relationValue = value;
|
|
62
|
+
return existingSolidAction[key]?.id !== relationValue?.id;
|
|
63
|
+
}
|
|
64
|
+
if (this.jsonCompareFields.has(key)) {
|
|
65
|
+
return this.getCanonicalJsonFieldString(existingSolidAction[key]) !== this.getCanonicalJsonFieldString(value);
|
|
66
|
+
}
|
|
67
|
+
return existingSolidAction[key] !== value;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
23
70
|
constructor(entityManager, repo, moduleRef) {
|
|
24
71
|
super(entityManager, repo, 'actionMetadata', 'solid-core', moduleRef);
|
|
25
72
|
this.entityManager = entityManager;
|
|
26
73
|
this.repo = repo;
|
|
27
74
|
this.moduleRef = moduleRef;
|
|
75
|
+
this.logger = new common_1.Logger(ActionMetadataService_1.name);
|
|
76
|
+
this.comparableFields = [
|
|
77
|
+
'name',
|
|
78
|
+
'displayName',
|
|
79
|
+
'type',
|
|
80
|
+
'domain',
|
|
81
|
+
'context',
|
|
82
|
+
'customComponent',
|
|
83
|
+
'customIsModal',
|
|
84
|
+
'serverEndpoint',
|
|
85
|
+
'module',
|
|
86
|
+
'model',
|
|
87
|
+
'view',
|
|
88
|
+
];
|
|
89
|
+
this.relationCompareFields = new Set(['module', 'model', 'view']);
|
|
90
|
+
this.jsonCompareFields = new Set(['domain', 'context']);
|
|
28
91
|
}
|
|
29
92
|
async findOneByUserKey(name, relations = {}) {
|
|
30
93
|
const entity = await this.repo.findOne({
|
|
@@ -39,9 +102,19 @@ let ActionMetadataService = class ActionMetadataService extends crud_service_1.C
|
|
|
39
102
|
const existingSolidAction = await this.repo.findOne({
|
|
40
103
|
where: {
|
|
41
104
|
name: updateSolidActionDto.name
|
|
42
|
-
}
|
|
105
|
+
},
|
|
106
|
+
relations: {
|
|
107
|
+
module: true,
|
|
108
|
+
model: true,
|
|
109
|
+
view: true,
|
|
110
|
+
},
|
|
43
111
|
});
|
|
44
112
|
if (existingSolidAction) {
|
|
113
|
+
const hasChanges = this.hasChanges(existingSolidAction, updateSolidActionDto);
|
|
114
|
+
if (!hasChanges) {
|
|
115
|
+
this.logger.debug(`Skipping action upsert for ${updateSolidActionDto.name}; no changes detected.`);
|
|
116
|
+
return existingSolidAction;
|
|
117
|
+
}
|
|
45
118
|
const updatedSolidActionDto = { ...existingSolidAction, ...updateSolidActionDto };
|
|
46
119
|
return this.repo.save(updatedSolidActionDto);
|
|
47
120
|
}
|
|
@@ -52,7 +125,7 @@ let ActionMetadataService = class ActionMetadataService extends crud_service_1.C
|
|
|
52
125
|
}
|
|
53
126
|
};
|
|
54
127
|
exports.ActionMetadataService = ActionMetadataService;
|
|
55
|
-
exports.ActionMetadataService = ActionMetadataService = __decorate([
|
|
128
|
+
exports.ActionMetadataService = ActionMetadataService = ActionMetadataService_1 = __decorate([
|
|
56
129
|
(0, common_1.Injectable)(),
|
|
57
130
|
__param(0, (0, typeorm_1.InjectEntityManager)()),
|
|
58
131
|
__metadata("design:paramtypes", [typeorm_2.EntityManager,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-metadata.service.js","sourceRoot":"","sources":["../../src/services/action-metadata.service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"action-metadata.service.js","sourceRoot":"","sources":["../../src/services/action-metadata.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Logger } from '@nestjs/common';\nimport { ModuleRef } from \"@nestjs/core\";\nimport { InjectEntityManager } from '@nestjs/typeorm';\nimport { CRUDService } from 'src/services/crud.service';\nimport { EntityManager } from 'typeorm';\n\n\nimport { ActionMetadataRepository } from 'src/repository/action-metadata.repository';\nimport { ActionMetadata } from '../entities/action-metadata.entity';\n\n@Injectable()\nexport class ActionMetadataService extends CRUDService<ActionMetadata> {\n private readonly logger = new Logger(ActionMetadataService.name);\n private readonly comparableFields = [\n 'name',\n 'displayName',\n 'type',\n 'domain',\n 'context',\n 'customComponent',\n 'customIsModal',\n 'serverEndpoint',\n 'module',\n 'model',\n 'view',\n ] as const;\n private readonly relationCompareFields = new Set(['module', 'model', 'view']);\n private readonly jsonCompareFields = new Set(['domain', 'context']);\n\n private normalizeJsonFieldValue(value: any): any {\n if (typeof value === 'string') {\n const trimmedValue = value.trim();\n if (\n (trimmedValue.startsWith('{') && trimmedValue.endsWith('}')) ||\n (trimmedValue.startsWith('[') && trimmedValue.endsWith(']'))\n ) {\n try {\n return this.normalizeJsonFieldValue(JSON.parse(trimmedValue));\n } catch {\n return value;\n }\n }\n return value;\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => this.normalizeJsonFieldValue(item));\n }\n\n if (value && typeof value === 'object') {\n return Object.keys(value)\n .sort()\n .reduce((result, key) => {\n result[key] = this.normalizeJsonFieldValue(value[key]);\n return result;\n }, {} as Record<string, any>);\n }\n\n return value;\n }\n\n private getCanonicalJsonFieldString(value: any): string {\n return JSON.stringify(this.normalizeJsonFieldValue(value) ?? null);\n }\n\n private hasChanges(existingSolidAction: ActionMetadata, updateSolidActionDto: any): boolean {\n return this.comparableFields.some((key) => {\n const value = updateSolidActionDto[key];\n if (typeof value === 'undefined') {\n return false;\n }\n\n if (this.relationCompareFields.has(key)) {\n const relationValue = value as any;\n return (existingSolidAction as any)[key]?.id !== relationValue?.id;\n }\n\n if (this.jsonCompareFields.has(key)) {\n return this.getCanonicalJsonFieldString((existingSolidAction as any)[key]) !== this.getCanonicalJsonFieldString(value);\n }\n\n return (existingSolidAction as any)[key] !== value;\n });\n }\n\n constructor(\n @InjectEntityManager()\n readonly entityManager: EntityManager,\n // @InjectRepository(ActionMetadata, 'default')\n // readonly repo: Repository<ActionMetadata>,\n readonly repo: ActionMetadataRepository,\n readonly moduleRef: ModuleRef\n\n ) {\n super(entityManager, repo, 'actionMetadata', 'solid-core', moduleRef);\n }\n\n async findOneByUserKey(name: string, relations = {}) {\n const entity = await this.repo.findOne({\n where: {\n name: name,\n },\n relations: relations,\n });\n return entity;\n }\n\n async upsert(updateSolidActionDto: any) {\n // First check if module already exists using name\n const existingSolidAction = await this.repo.findOne({\n where: {\n name: updateSolidActionDto.name\n },\n relations: {\n module: true,\n model: true,\n view: true,\n },\n })\n\n // if found\n if (existingSolidAction) {\n const hasChanges = this.hasChanges(existingSolidAction, updateSolidActionDto);\n\n if (!hasChanges) {\n this.logger.debug(`Skipping action upsert for ${updateSolidActionDto.name}; no changes detected.`);\n return existingSolidAction;\n }\n\n const updatedSolidActionDto = { ...existingSolidAction, ...updateSolidActionDto };\n return this.repo.save(updatedSolidActionDto);\n }\n // if not found - create new \n else {\n const moduleMetadata = this.repo.create(updateSolidActionDto);\n return this.repo.save(moduleMetadata);\n }\n }\n\n}\n"]}
|
package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alpha-num-external-id-computed-field-provider.d.ts","sourceRoot":"","sources":["../../../../src/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,8BAA8B,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,WAAW,yBAAyB;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,qBAEa,qCAAqC,CAAC,CAAC,SAAS,YAAY,CAAE,YAAW,8BAA8B,CAAC,CAAC,EAAE,yBAAyB,CAAC;IAG9I,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAAb,aAAa,EAAE,aAAa;IAG/C,IAAI,IAAI,MAAM;IAId,IAAI,IAAI,MAAM;IAIR,eAAe,CAAC,aAAa,EAAE,CAAC,EAAE,qBAAqB,EAAE,qBAAqB,CAAC,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"alpha-num-external-id-computed-field-provider.d.ts","sourceRoot":"","sources":["../../../../src/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,8BAA8B,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,WAAW,yBAAyB;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,qBAEa,qCAAqC,CAAC,CAAC,SAAS,YAAY,CAAE,YAAW,8BAA8B,CAAC,CAAC,EAAE,yBAAyB,CAAC;IAG9I,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAAb,aAAa,EAAE,aAAa;IAG/C,IAAI,IAAI,MAAM;IAId,IAAI,IAAI,MAAM;IAIR,eAAe,CAAC,aAAa,EAAE,CAAC,EAAE,qBAAqB,EAAE,qBAAqB,CAAC,yBAAyB,CAAC;IA4B/G,OAAO,CAAC,kBAAkB;YASZ,kBAAkB;YASlB,wBAAwB;CAkBvC"}
|
package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js
CHANGED
|
@@ -40,7 +40,8 @@ let AlphaNumExternalIdComputationProvider = class AlphaNumExternalIdComputationP
|
|
|
40
40
|
resolvedPrefix = String(dynamicValue).trim().toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9\-]/g, '');
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
const
|
|
43
|
+
const manager = eventContext?.manager ?? this.entityManager;
|
|
44
|
+
const uniqueCode = await this.generateUniqueExternalId(manager, resolvedPrefix, codeLength, computedFieldMetadata.fieldName, entityName);
|
|
44
45
|
const finalExternalId = resolvedPrefix ? `${resolvedPrefix}-${uniqueCode}` : uniqueCode;
|
|
45
46
|
triggerEntity[computedFieldMetadata.fieldName] = finalExternalId;
|
|
46
47
|
}
|
|
@@ -52,18 +53,18 @@ let AlphaNumExternalIdComputationProvider = class AlphaNumExternalIdComputationP
|
|
|
52
53
|
}
|
|
53
54
|
return result;
|
|
54
55
|
}
|
|
55
|
-
async isExternalIdUnique(externalId, fieldName, entityName) {
|
|
56
|
-
const count = await
|
|
56
|
+
async isExternalIdUnique(manager, externalId, fieldName, entityName) {
|
|
57
|
+
const count = await manager.count(entityName, {
|
|
57
58
|
where: { [fieldName]: externalId },
|
|
58
59
|
});
|
|
59
60
|
return count === 0;
|
|
60
61
|
}
|
|
61
|
-
async generateUniqueExternalId(resolvedPrefix, codeLength, fieldName, entityName) {
|
|
62
|
+
async generateUniqueExternalId(manager, resolvedPrefix, codeLength, fieldName, entityName) {
|
|
62
63
|
const maxAttempts = 10;
|
|
63
64
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
64
65
|
const newId = this.generateRandomCode(codeLength);
|
|
65
66
|
const fullId = resolvedPrefix ? `${resolvedPrefix}-${newId}` : newId;
|
|
66
|
-
const isUnique = await this.isExternalIdUnique(fullId, fieldName, entityName);
|
|
67
|
+
const isUnique = await this.isExternalIdUnique(manager, fullId, fieldName, entityName);
|
|
67
68
|
if (isUnique) {
|
|
68
69
|
return newId;
|
|
69
70
|
}
|
package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alpha-num-external-id-computed-field-provider.js","sourceRoot":"","sources":["../../../../src/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAA4C;AAC5C,6CAAsD;AACtD,6GAAyF;AAIzF,qCAAwC;AACxC,mCAA6B;AAStB,IAAM,qCAAqC,GAA3C,MAAM,qCAAqC;IAChD,YAEmB,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;IAC3C,CAAC;IAEL,IAAI;QACF,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;IAC/B,CAAC;IAED,IAAI;QACF,OAAO,oGAAoG,CAAC;IAC9G,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,aAAgB,EAAE,qBAAuE;QAC7G,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE,GAAG,qBAAqB,CAAC,8BAA8B,CAAC;QACpG,MAAM,YAAY,GAAG,qBAAqB,CAAC,YAAY,CAAC;QACxD,MAAM,UAAU,GAAG,YAAY,EAAE,YAAY,IAAI,YAAY,CAAC,cAAc,EAAE,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC;QAEtG,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,CAAC;QAG/B,IAAI,cAAc,GAAG,MAAM,IAAI,EAAE,CAAC;QAElC,IAAI,kBAAkB,EAAE,CAAC;YACvB,MAAM,YAAY,GAAG,IAAA,YAAG,EAAC,aAAoB,EAAE,kBAAkB,CAAC,CAAC;YACnE,IAAI,YAAY,EAAE,CAAC;gBACjB,cAAc,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;YAC9G,CAAC;QACH,CAAC;
|
|
1
|
+
{"version":3,"file":"alpha-num-external-id-computed-field-provider.js","sourceRoot":"","sources":["../../../../src/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@nestjs/common';\nimport { InjectEntityManager } from '@nestjs/typeorm';\nimport { ComputedFieldProvider } from 'src/decorators/computed-field-provider.decorator';\nimport { CommonEntity } from 'src/entities/common.entity';\nimport { ComputedFieldMetadata } from 'src/helpers/solid-registry';\nimport { IEntityPreComputeFieldProvider } from 'src/interfaces';\nimport { EntityManager } from 'typeorm';\nimport { get } from \"lodash\";\nexport interface AlphaNumExternalIdContext {\n prefix?: string; // alias -> staticPrefix\n length?: number; // Optional: length of the unique code to generate, default is 5\n dynamicFieldPrefix?: string; // NEW: field name on the entity\n}\n\n@ComputedFieldProvider()\n@Injectable()\nexport class AlphaNumExternalIdComputationProvider<T extends CommonEntity> implements IEntityPreComputeFieldProvider<T, AlphaNumExternalIdContext> {\n constructor(\n @InjectEntityManager()\n private readonly entityManager: EntityManager\n ) { }\n\n name(): string {\n return this.constructor.name;\n }\n\n help(): string {\n return 'Provider used to compute external ID for a CommonEntity with support for static or dynamic prefix.';\n }\n\n async preComputeValue(triggerEntity: T, computedFieldMetadata: ComputedFieldMetadata<AlphaNumExternalIdContext>) {\n const { prefix, length, dynamicFieldPrefix } = computedFieldMetadata.computedFieldValueProviderCtxt;\n const eventContext = computedFieldMetadata.eventContext;\n const entityName = eventContext?.metadataName ?? eventContext.databaseEntity?.constructor?.name ?? '';\n\n const codeLength = length || 5;\n\n // Determine prefix\n let resolvedPrefix = prefix || '';\n\n if (dynamicFieldPrefix) {\n const dynamicValue = get(triggerEntity as any, dynamicFieldPrefix);\n if (dynamicValue) {\n resolvedPrefix = String(dynamicValue).trim().toLowerCase().replace(/\\s+/g, '-').replace(/[^a-z0-9\\-]/g, '');\n }\n }\n\n // Use the originating transaction's EntityManager so the uniqueness check runs on the\n // active connection. Falls back to the injected manager only when no event context is\n // available (e.g. direct invocation outside a TypeORM lifecycle event).\n const manager = eventContext?.manager ?? this.entityManager;\n\n const uniqueCode = await this.generateUniqueExternalId(manager, resolvedPrefix, codeLength, computedFieldMetadata.fieldName, entityName);\n const finalExternalId = resolvedPrefix ? `${resolvedPrefix}-${uniqueCode}` : uniqueCode;\n\n triggerEntity[computedFieldMetadata.fieldName] = finalExternalId;\n }\n\n private generateRandomCode(length = 5): string {\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n let result = '';\n for (let i = 0; i < length; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n return result;\n }\n\n private async isExternalIdUnique(manager: EntityManager, externalId: string, fieldName: string, entityName: string): Promise<boolean> {\n const count = await manager.count(entityName as any,\n {\n where: { [fieldName]: externalId },\n }\n );\n return count === 0;\n }\n\n private async generateUniqueExternalId(manager: EntityManager, resolvedPrefix: string, codeLength: number, fieldName: string, entityName: string): Promise<string> {\n const maxAttempts = 10;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n\n const newId = this.generateRandomCode(codeLength);\n\n const fullId = resolvedPrefix ? `${resolvedPrefix}-${newId}` : newId;\n\n const isUnique = await this.isExternalIdUnique(manager, fullId, fieldName, entityName);\n\n if (isUnique) {\n return newId;\n }\n }\n\n throw new Error('Failed to generate a unique external ID after multiple attempts');\n }\n}\n"]}
|
|
@@ -15,6 +15,20 @@ export declare class LocaleService extends CRUDService<Locale> implements OnAppl
|
|
|
15
15
|
constructor(entityManager: EntityManager, repo: LocaleRepository, moduleRef: ModuleRef, requestContextService: RequestContextService, solidRegistry: SolidRegistry);
|
|
16
16
|
private readonly logger;
|
|
17
17
|
onApplicationBootstrap(): void;
|
|
18
|
+
private assertCanSetAsDefault;
|
|
19
|
+
create(createDto: any, files?: Express.Multer.File[], solidRequestContext?: any): Promise<Locale>;
|
|
20
|
+
insertMany(createDtos: any[], filesArray?: Express.Multer.File[][], solidRequestContext?: any): Promise<Locale[]>;
|
|
21
|
+
update(id: number, updateDto: any, files?: Express.Multer.File[], isPartialUpdate?: boolean, solidRequestContext?: any, isUpdate?: boolean): Promise<Locale>;
|
|
22
|
+
recover(id: number, solidRequestContext?: any): Promise<{
|
|
23
|
+
message: string;
|
|
24
|
+
data: Locale;
|
|
25
|
+
}>;
|
|
26
|
+
recoverMany(ids: number[], solidRequestContext?: any): Promise<{
|
|
27
|
+
message: string;
|
|
28
|
+
recoveredIds: number[];
|
|
29
|
+
}>;
|
|
30
|
+
delete(id: number, solidRequestContext?: any): Promise<Locale>;
|
|
31
|
+
deleteMany(ids: number[], solidRequestContext?: any): Promise<any>;
|
|
18
32
|
loadLocales(): Promise<void>;
|
|
19
33
|
}
|
|
20
34
|
//# sourceMappingURL=locale.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locale.service.d.ts","sourceRoot":"","sources":["../../src/services/locale.service.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"locale.service.d.ts","sourceRoot":"","sources":["../../src/services/locale.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2C,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACjG,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAmB,MAAM,SAAS,CAAC;AAEzD,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,qBACa,aAAc,SAAQ,WAAW,CAAC,MAAM,CAAE,YAAW,sBAAsB;IAGpF,QAAQ,CAAC,aAAa,EAAE,aAAa;IAGrC,QAAQ,CAAC,IAAI,EAAE,gBAAgB;IAE/B,QAAQ,CAAC,SAAS,EAAE,SAAS;IAI7B,QAAQ,CAAC,qBAAqB,EAAE,qBAAqB;IACrD,QAAQ,CAAC,aAAa,EAAE,aAAa;gBAV5B,aAAa,EAAE,aAAa,EAG5B,IAAI,EAAE,gBAAgB,EAEtB,SAAS,EAAE,SAAS,EAIpB,qBAAqB,EAAE,qBAAqB,EAC5C,aAAa,EAAE,aAAa;IAIvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiC;IACxD,sBAAsB;YAKR,qBAAqB;IAkBpB,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,KAAK,GAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EAAO,EAAE,mBAAmB,GAAE,GAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IAUzG,UAAU,CAAC,UAAU,EAAE,GAAG,EAAE,EAAE,UAAU,GAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,EAAO,EAAE,mBAAmB,GAAE,GAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAgBzH,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,GAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EAAO,EAAE,eAAe,GAAE,OAAe,EAAE,mBAAmB,GAAE,GAAQ,EAAE,QAAQ,GAAE,OAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAUlL,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,mBAAmB,GAAE,GAAQ;;;;IAkBjD,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,mBAAmB,GAAE,GAAQ;;;;IAuBxD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,mBAAmB,GAAE,GAAQ;IAMhD,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,mBAAmB,GAAE,GAAQ;IAMhE,WAAW;CAKlB"}
|
|
@@ -35,6 +35,89 @@ let LocaleService = LocaleService_1 = class LocaleService extends crud_service_1
|
|
|
35
35
|
onApplicationBootstrap() {
|
|
36
36
|
this.loadLocales();
|
|
37
37
|
}
|
|
38
|
+
async assertCanSetAsDefault(currentLocaleId) {
|
|
39
|
+
const defaultLocales = await this.repo.find({
|
|
40
|
+
where: {
|
|
41
|
+
isDefault: true,
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
const conflictingDefaultLocale = defaultLocales.find((locale) => locale.id !== currentLocaleId);
|
|
45
|
+
if (conflictingDefaultLocale) {
|
|
46
|
+
throw new common_1.BadRequestException(`Locale "${conflictingDefaultLocale.displayName}" is already marked as default. Mark it as non-default first.`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async create(createDto, files = [], solidRequestContext = {}) {
|
|
50
|
+
if (createDto?.isDefault === true) {
|
|
51
|
+
await this.assertCanSetAsDefault();
|
|
52
|
+
}
|
|
53
|
+
const savedLocale = await super.create(createDto, files, solidRequestContext);
|
|
54
|
+
await this.loadLocales();
|
|
55
|
+
return savedLocale;
|
|
56
|
+
}
|
|
57
|
+
async insertMany(createDtos, filesArray = [], solidRequestContext = {}) {
|
|
58
|
+
const defaultLocalesInPayload = (createDtos || []).filter((dto) => dto?.isDefault === true);
|
|
59
|
+
if (defaultLocalesInPayload.length > 1) {
|
|
60
|
+
throw new common_1.BadRequestException(`Only one locale can be marked as default.`);
|
|
61
|
+
}
|
|
62
|
+
if (defaultLocalesInPayload.length === 1) {
|
|
63
|
+
await this.assertCanSetAsDefault();
|
|
64
|
+
}
|
|
65
|
+
const savedLocales = await super.insertMany(createDtos, filesArray, solidRequestContext);
|
|
66
|
+
await this.loadLocales();
|
|
67
|
+
return savedLocales;
|
|
68
|
+
}
|
|
69
|
+
async update(id, updateDto, files = [], isPartialUpdate = false, solidRequestContext = {}, isUpdate = false) {
|
|
70
|
+
if (updateDto?.isDefault === true) {
|
|
71
|
+
await this.assertCanSetAsDefault(id);
|
|
72
|
+
}
|
|
73
|
+
const savedLocale = await super.update(id, updateDto, files, isPartialUpdate, solidRequestContext, isUpdate);
|
|
74
|
+
await this.loadLocales();
|
|
75
|
+
return savedLocale;
|
|
76
|
+
}
|
|
77
|
+
async recover(id, solidRequestContext = {}) {
|
|
78
|
+
const localeToRecover = await this.repo.findOne({
|
|
79
|
+
where: {
|
|
80
|
+
id,
|
|
81
|
+
deletedAt: (0, typeorm_2.Not)((0, typeorm_2.IsNull)()),
|
|
82
|
+
},
|
|
83
|
+
withDeleted: true,
|
|
84
|
+
});
|
|
85
|
+
if (localeToRecover?.isDefault) {
|
|
86
|
+
await this.assertCanSetAsDefault(id);
|
|
87
|
+
}
|
|
88
|
+
const recoveredLocale = await super.recover(id, solidRequestContext);
|
|
89
|
+
await this.loadLocales();
|
|
90
|
+
return recoveredLocale;
|
|
91
|
+
}
|
|
92
|
+
async recoverMany(ids, solidRequestContext = {}) {
|
|
93
|
+
const localesToRecover = await this.repo.find({
|
|
94
|
+
where: {
|
|
95
|
+
id: (0, typeorm_2.In)(ids),
|
|
96
|
+
deletedAt: (0, typeorm_2.Not)((0, typeorm_2.IsNull)()),
|
|
97
|
+
},
|
|
98
|
+
withDeleted: true,
|
|
99
|
+
});
|
|
100
|
+
const defaultLocalesToRecover = localesToRecover.filter((locale) => locale.isDefault);
|
|
101
|
+
if (defaultLocalesToRecover.length > 1) {
|
|
102
|
+
throw new common_1.BadRequestException(`Only one locale can be marked as default.`);
|
|
103
|
+
}
|
|
104
|
+
if (defaultLocalesToRecover.length === 1) {
|
|
105
|
+
await this.assertCanSetAsDefault(defaultLocalesToRecover[0].id);
|
|
106
|
+
}
|
|
107
|
+
const recoveredLocales = await super.recoverMany(ids, solidRequestContext);
|
|
108
|
+
await this.loadLocales();
|
|
109
|
+
return recoveredLocales;
|
|
110
|
+
}
|
|
111
|
+
async delete(id, solidRequestContext = {}) {
|
|
112
|
+
const deletedLocale = await super.delete(id, solidRequestContext);
|
|
113
|
+
await this.loadLocales();
|
|
114
|
+
return deletedLocale;
|
|
115
|
+
}
|
|
116
|
+
async deleteMany(ids, solidRequestContext = {}) {
|
|
117
|
+
const deletedLocales = await super.deleteMany(ids, solidRequestContext);
|
|
118
|
+
await this.loadLocales();
|
|
119
|
+
return deletedLocales;
|
|
120
|
+
}
|
|
38
121
|
async loadLocales() {
|
|
39
122
|
const locales = await this.repo.find();
|
|
40
123
|
this.logger.debug(`Loaded ${locales.length} locales into registry`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locale.service.js","sourceRoot":"","sources":["../../src/services/locale.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"locale.service.js","sourceRoot":"","sources":["../../src/services/locale.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { BadRequestException, Injectable, Logger, OnApplicationBootstrap } from '@nestjs/common';\nimport { ModuleRef } from \"@nestjs/core\";\nimport { InjectEntityManager } from '@nestjs/typeorm';\nimport { EntityManager, In, IsNull, Not } from 'typeorm';\n\nimport { Locale } from 'src/entities/locale.entity';\nimport { SolidRegistry } from 'src/helpers/solid-registry';\nimport { LocaleRepository } from 'src/repository/locale.repository';\nimport { CRUDService } from 'src/services/crud.service';\nimport { RequestContextService } from './request-context.service';\n@Injectable()\nexport class LocaleService extends CRUDService<Locale> implements OnApplicationBootstrap{\n constructor(\n @InjectEntityManager()\n readonly entityManager: EntityManager,\n // @InjectRepository(Locale, 'default')\n // readonly repo: Repository<Locale>,\n readonly repo: LocaleRepository,\n // @InjectRepository(Locale, 'default')\n readonly moduleRef: ModuleRef,\n // @InjectRepository(ModelMetadata)\n // private readonly modelMetadataRepo: Repository<ModelMetadata>,\n // private readonly modelMetadataRepo: ModelMetadataRepository,\n readonly requestContextService: RequestContextService,\n readonly solidRegistry: SolidRegistry,\n ) {\n super(entityManager, repo, 'locale', 'solid-core', moduleRef);\n }\n private readonly logger = new Logger(LocaleService.name)\n onApplicationBootstrap() {\n // Load the security rules from the database\n this.loadLocales();\n }\n\n private async assertCanSetAsDefault(currentLocaleId?: number) {\n const defaultLocales = await this.repo.find({\n where: {\n isDefault: true,\n } as any,\n });\n\n const conflictingDefaultLocale = defaultLocales.find(\n (locale) => locale.id !== currentLocaleId\n );\n\n if (conflictingDefaultLocale) {\n throw new BadRequestException(\n `Locale \"${conflictingDefaultLocale.displayName}\" is already marked as default. Mark it as non-default first.`\n );\n }\n }\n\n override async create(createDto: any, files: Express.Multer.File[] = [], solidRequestContext: any = {}): Promise<Locale> {\n if (createDto?.isDefault === true) {\n await this.assertCanSetAsDefault();\n }\n\n const savedLocale = await super.create(createDto, files, solidRequestContext);\n await this.loadLocales();\n return savedLocale;\n }\n\n override async insertMany(createDtos: any[], filesArray: Express.Multer.File[][] = [], solidRequestContext: any = {}): Promise<Locale[]> {\n const defaultLocalesInPayload = (createDtos || []).filter((dto) => dto?.isDefault === true);\n\n if (defaultLocalesInPayload.length > 1) {\n throw new BadRequestException(`Only one locale can be marked as default.`);\n }\n\n if (defaultLocalesInPayload.length === 1) {\n await this.assertCanSetAsDefault();\n }\n\n const savedLocales = await super.insertMany(createDtos, filesArray, solidRequestContext);\n await this.loadLocales();\n return savedLocales;\n }\n\n override async update(id: number, updateDto: any, files: Express.Multer.File[] = [], isPartialUpdate: boolean = false, solidRequestContext: any = {}, isUpdate: boolean = false): Promise<Locale> {\n if (updateDto?.isDefault === true) {\n await this.assertCanSetAsDefault(id);\n }\n\n const savedLocale = await super.update(id, updateDto, files, isPartialUpdate, solidRequestContext, isUpdate);\n await this.loadLocales();\n return savedLocale;\n }\n\n override async recover(id: number, solidRequestContext: any = {}) {\n const localeToRecover = await this.repo.findOne({\n where: {\n id,\n deletedAt: Not(IsNull()),\n } as any,\n withDeleted: true,\n });\n\n if (localeToRecover?.isDefault) {\n await this.assertCanSetAsDefault(id);\n }\n\n const recoveredLocale = await super.recover(id, solidRequestContext);\n await this.loadLocales();\n return recoveredLocale;\n }\n\n override async recoverMany(ids: number[], solidRequestContext: any = {}) {\n const localesToRecover = await this.repo.find({\n where: {\n id: In(ids),\n deletedAt: Not(IsNull()),\n } as any,\n withDeleted: true,\n });\n\n const defaultLocalesToRecover = localesToRecover.filter((locale) => locale.isDefault);\n if (defaultLocalesToRecover.length > 1) {\n throw new BadRequestException(`Only one locale can be marked as default.`);\n }\n\n if (defaultLocalesToRecover.length === 1) {\n await this.assertCanSetAsDefault(defaultLocalesToRecover[0].id);\n }\n\n const recoveredLocales = await super.recoverMany(ids, solidRequestContext);\n await this.loadLocales();\n return recoveredLocales;\n }\n\n override async delete(id: number, solidRequestContext: any = {}) {\n const deletedLocale = await super.delete(id, solidRequestContext);\n await this.loadLocales();\n return deletedLocale;\n }\n\n override async deleteMany(ids: number[], solidRequestContext: any = {}) {\n const deletedLocales = await super.deleteMany(ids, solidRequestContext);\n await this.loadLocales();\n return deletedLocales;\n }\n\n async loadLocales() {\n const locales = await this.repo.find();\n this.logger.debug(`Loaded ${locales.length} locales into registry`);\n this.solidRegistry.registerlocales(locales);\n }\n}\n"]}
|
|
@@ -11,15 +11,20 @@ export declare class RoleMetadataService extends CRUDService<RoleMetadata> {
|
|
|
11
11
|
readonly permissionRepository: PermissionMetadataRepository;
|
|
12
12
|
readonly moduleRef: ModuleRef;
|
|
13
13
|
private readonly logger;
|
|
14
|
+
private readonly permissionAssignmentBatchSize;
|
|
14
15
|
constructor(entityManager: EntityManager, repo: RoleMetadataRepository, permissionRepository: PermissionMetadataRepository, moduleRef: ModuleRef);
|
|
15
16
|
findRoleByName(roleName: string): Promise<RoleMetadata>;
|
|
16
17
|
assertRoleExistsByName(roleName: string): Promise<void>;
|
|
17
18
|
createRolesIfNotExists(roles: CreateRoleMetadataDto[]): Promise<void>;
|
|
19
|
+
private resolveRoleModule;
|
|
18
20
|
addAllPermissionsToRole(roleName: string): Promise<RoleMetadata>;
|
|
19
21
|
addPermissionsToRole(roleName: string, permissionNames: string[]): Promise<RoleMetadata>;
|
|
20
22
|
addPermissionToRole(roleName: string, permissionName: string[]): Promise<RoleMetadata>;
|
|
21
23
|
private _addPermissionsToRole;
|
|
22
24
|
removePermissionsFromRole(roleName: string, permissionNames: string[]): Promise<RoleMetadata>;
|
|
23
25
|
private preloadPermissionByName;
|
|
26
|
+
private loadTargetPermissions;
|
|
27
|
+
private getRolePermissionJoinInfo;
|
|
28
|
+
private insertRolePermissionMappings;
|
|
24
29
|
}
|
|
25
30
|
//# sourceMappingURL=role-metadata.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"role-metadata.service.d.ts","sourceRoot":"","sources":["../../src/services/role-metadata.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,aAAa,EAAM,MAAM,SAAS,CAAC;AAG5C,OAAO,EAAE,4BAA4B,EAAE,MAAM,+CAA+C,CAAC;AAC7F,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"role-metadata.service.d.ts","sourceRoot":"","sources":["../../src/services/role-metadata.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,aAAa,EAAM,MAAM,SAAS,CAAC;AAG5C,OAAO,EAAE,4BAA4B,EAAE,MAAM,+CAA+C,CAAC;AAC7F,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAGzE,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAEhE,qBACa,mBAAoB,SAAQ,WAAW,CAAC,YAAY,CAAC;IAM9D,QAAQ,CAAC,aAAa,EAAE,aAAa;IAGrC,QAAQ,CAAC,IAAI,EAAE,sBAAsB;IAGrC,QAAQ,CAAC,oBAAoB,EAAE,4BAA4B;IAC3D,QAAQ,CAAC,SAAS,EAAE,SAAS;IAZ/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwC;IAC/D,OAAO,CAAC,QAAQ,CAAC,6BAA6B,CAAO;gBAI1C,aAAa,EAAE,aAAa,EAG5B,IAAI,EAAE,sBAAsB,EAG5B,oBAAoB,EAAE,4BAA4B,EAClD,SAAS,EAAE,SAAS;IAMzB,cAAc,CAAC,QAAQ,EAAE,MAAM;IAe/B,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAevD,sBAAsB,CAAC,KAAK,EAAE,qBAAqB,EAAE;YA0D7C,iBAAiB;IAgBzB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAIhE,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;IAIxF,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE;YAItD,qBAAqB;IA8C7B,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;YAsBrF,uBAAuB;YAUvB,qBAAqB;IAiBnC,OAAO,CAAC,yBAAyB;YAmBnB,4BAA4B;CAsB3C"}
|
|
@@ -22,6 +22,7 @@ const typeorm_2 = require("typeorm");
|
|
|
22
22
|
const error_messages_1 = require("../constants/error-messages");
|
|
23
23
|
const permission_metadata_repository_1 = require("../repository/permission-metadata.repository");
|
|
24
24
|
const role_metadata_repository_1 = require("../repository/role-metadata.repository");
|
|
25
|
+
const module_metadata_entity_1 = require("../entities/module-metadata.entity");
|
|
25
26
|
let RoleMetadataService = RoleMetadataService_1 = class RoleMetadataService extends crud_service_1.CRUDService {
|
|
26
27
|
constructor(entityManager, repo, permissionRepository, moduleRef) {
|
|
27
28
|
super(entityManager, repo, 'roleMetadata', 'solid-core', moduleRef);
|
|
@@ -30,6 +31,7 @@ let RoleMetadataService = RoleMetadataService_1 = class RoleMetadataService exte
|
|
|
30
31
|
this.permissionRepository = permissionRepository;
|
|
31
32
|
this.moduleRef = moduleRef;
|
|
32
33
|
this.logger = new common_1.Logger(RoleMetadataService_1.name);
|
|
34
|
+
this.permissionAssignmentBatchSize = 500;
|
|
33
35
|
}
|
|
34
36
|
async findRoleByName(roleName) {
|
|
35
37
|
const entity = await this.repo.findOne({
|
|
@@ -62,11 +64,14 @@ let RoleMetadataService = RoleMetadataService_1 = class RoleMetadataService exte
|
|
|
62
64
|
for (let id = 0; id < roles.length; id++) {
|
|
63
65
|
try {
|
|
64
66
|
const roleObj = roles[id];
|
|
67
|
+
const module = await this.resolveRoleModule(roleObj);
|
|
65
68
|
const existingRole = await this.repo.findOne({
|
|
66
69
|
where: {
|
|
67
70
|
name: roleObj.name,
|
|
68
71
|
},
|
|
69
|
-
relations: {
|
|
72
|
+
relations: {
|
|
73
|
+
module: true,
|
|
74
|
+
},
|
|
70
75
|
});
|
|
71
76
|
if (!existingRole) {
|
|
72
77
|
this.logger.debug(`Role ${roleObj.name} does not exist, hence creating`);
|
|
@@ -74,10 +79,14 @@ let RoleMetadataService = RoleMetadataService_1 = class RoleMetadataService exte
|
|
|
74
79
|
if (roleObj.permissions && roleObj.permissions.length > 0) {
|
|
75
80
|
await Promise.all(roleObj.permissions.map(permission => this.preloadPermissionByName(permission.name)));
|
|
76
81
|
}
|
|
77
|
-
const role = this.repo.create({ ...roleObj });
|
|
82
|
+
const role = this.repo.create({ ...roleObj, ...(module ? { module } : {}) });
|
|
78
83
|
await this.repo.save(role);
|
|
79
84
|
}
|
|
80
85
|
else {
|
|
86
|
+
if (module && existingRole.module?.id !== module.id) {
|
|
87
|
+
existingRole.module = module;
|
|
88
|
+
await this.repo.save(existingRole);
|
|
89
|
+
}
|
|
81
90
|
}
|
|
82
91
|
}
|
|
83
92
|
catch (error) {
|
|
@@ -85,6 +94,19 @@ let RoleMetadataService = RoleMetadataService_1 = class RoleMetadataService exte
|
|
|
85
94
|
}
|
|
86
95
|
}
|
|
87
96
|
}
|
|
97
|
+
async resolveRoleModule(roleObj) {
|
|
98
|
+
if (roleObj.moduleId) {
|
|
99
|
+
return await this.entityManager.getRepository(module_metadata_entity_1.ModuleMetadata).findOne({
|
|
100
|
+
where: { id: roleObj.moduleId },
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
if (roleObj.moduleUserKey) {
|
|
104
|
+
return await this.entityManager.getRepository(module_metadata_entity_1.ModuleMetadata).findOne({
|
|
105
|
+
where: { name: roleObj.moduleUserKey },
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
88
110
|
async addAllPermissionsToRole(roleName) {
|
|
89
111
|
return await this._addPermissionsToRole(roleName, null);
|
|
90
112
|
}
|
|
@@ -97,46 +119,41 @@ let RoleMetadataService = RoleMetadataService_1 = class RoleMetadataService exte
|
|
|
97
119
|
async _addPermissionsToRole(roleName, permissionNames) {
|
|
98
120
|
const role = await this.repo.findOne({
|
|
99
121
|
where: { name: roleName },
|
|
100
|
-
|
|
101
|
-
|
|
122
|
+
select: {
|
|
123
|
+
id: true,
|
|
124
|
+
name: true,
|
|
102
125
|
}
|
|
103
126
|
});
|
|
104
127
|
if (!role) {
|
|
105
128
|
throw new Error(`Role '${roleName}' not found.`);
|
|
106
129
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
130
|
+
const joinInfo = this.getRolePermissionJoinInfo();
|
|
131
|
+
const targetPermissions = await this.loadTargetPermissions(permissionNames);
|
|
132
|
+
if (!permissionNames || permissionNames.length === 0) {
|
|
133
|
+
await this.entityManager
|
|
134
|
+
.createQueryBuilder()
|
|
135
|
+
.delete()
|
|
136
|
+
.from(joinInfo.tableName)
|
|
137
|
+
.where(`${joinInfo.roleIdColumn} = :roleId`, { roleId: role.id })
|
|
138
|
+
.execute();
|
|
139
|
+
await this.insertRolePermissionMappings(role.id, targetPermissions.map((permission) => permission.id), joinInfo);
|
|
113
140
|
}
|
|
114
141
|
else {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
newPermissionFound = false;
|
|
128
|
-
break;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
if (newPermissionFound) {
|
|
132
|
-
role.permissions.push(newPermission);
|
|
133
|
-
}
|
|
142
|
+
const existingRows = await this.entityManager
|
|
143
|
+
.createQueryBuilder()
|
|
144
|
+
.select(joinInfo.permissionIdColumn, 'permissionId')
|
|
145
|
+
.from(joinInfo.tableName, 'role_permission')
|
|
146
|
+
.where(`${joinInfo.roleIdColumn} = :roleId`, { roleId: role.id })
|
|
147
|
+
.getRawMany();
|
|
148
|
+
const existingPermissionIds = new Set(existingRows.map((row) => Number(row.permissionId)));
|
|
149
|
+
const missingPermissionIds = targetPermissions
|
|
150
|
+
.map((permission) => permission.id)
|
|
151
|
+
.filter((permissionId) => !existingPermissionIds.has(permissionId));
|
|
152
|
+
if (missingPermissionIds.length > 0) {
|
|
153
|
+
await this.insertRolePermissionMappings(role.id, missingPermissionIds, joinInfo);
|
|
134
154
|
}
|
|
135
155
|
}
|
|
136
|
-
|
|
137
|
-
role.permissions = newPermissions;
|
|
138
|
-
}
|
|
139
|
-
return await this.repo.save(role);
|
|
156
|
+
return await this.findRoleByName(roleName);
|
|
140
157
|
}
|
|
141
158
|
async removePermissionsFromRole(roleName, permissionNames) {
|
|
142
159
|
const role = await this.repo.findOne({
|
|
@@ -162,6 +179,51 @@ let RoleMetadataService = RoleMetadataService_1 = class RoleMetadataService exte
|
|
|
162
179
|
}
|
|
163
180
|
return existingPermission;
|
|
164
181
|
}
|
|
182
|
+
async loadTargetPermissions(permissionNames) {
|
|
183
|
+
if (permissionNames && permissionNames.length !== 0) {
|
|
184
|
+
const uniquePermissionNames = [...new Set(permissionNames)];
|
|
185
|
+
const permissions = await this.permissionRepository.find({ where: { name: (0, typeorm_2.In)(uniquePermissionNames) } });
|
|
186
|
+
if (permissions.length !== uniquePermissionNames.length) {
|
|
187
|
+
throw new Error(`One or more permissions not found.`);
|
|
188
|
+
}
|
|
189
|
+
return permissions;
|
|
190
|
+
}
|
|
191
|
+
const permissions = await this.permissionRepository.find();
|
|
192
|
+
if (permissions.length === 0) {
|
|
193
|
+
throw new Error(`No permissions configured in the system. Did you forget to run the PermissionSeederService?`);
|
|
194
|
+
}
|
|
195
|
+
return permissions;
|
|
196
|
+
}
|
|
197
|
+
getRolePermissionJoinInfo() {
|
|
198
|
+
const relation = this.repo.metadata.relations.find((candidate) => candidate.propertyName === 'permissions');
|
|
199
|
+
if (!relation?.junctionEntityMetadata) {
|
|
200
|
+
throw new Error('Role-permission join table metadata not found.');
|
|
201
|
+
}
|
|
202
|
+
const roleIdColumn = relation.joinColumns[0]?.databaseName;
|
|
203
|
+
const permissionIdColumn = relation.inverseJoinColumns[0]?.databaseName;
|
|
204
|
+
if (!roleIdColumn || !permissionIdColumn) {
|
|
205
|
+
throw new Error('Role-permission join table column metadata not found.');
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
tableName: relation.junctionEntityMetadata.tableName,
|
|
209
|
+
roleIdColumn,
|
|
210
|
+
permissionIdColumn,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
async insertRolePermissionMappings(roleId, permissionIds, joinInfo) {
|
|
214
|
+
for (let index = 0; index < permissionIds.length; index += this.permissionAssignmentBatchSize) {
|
|
215
|
+
const batch = permissionIds.slice(index, index + this.permissionAssignmentBatchSize);
|
|
216
|
+
await this.entityManager
|
|
217
|
+
.createQueryBuilder()
|
|
218
|
+
.insert()
|
|
219
|
+
.into(joinInfo.tableName)
|
|
220
|
+
.values(batch.map((permissionId) => ({
|
|
221
|
+
[joinInfo.roleIdColumn]: roleId,
|
|
222
|
+
[joinInfo.permissionIdColumn]: permissionId,
|
|
223
|
+
})))
|
|
224
|
+
.execute();
|
|
225
|
+
}
|
|
226
|
+
}
|
|
165
227
|
};
|
|
166
228
|
exports.RoleMetadataService = RoleMetadataService;
|
|
167
229
|
exports.RoleMetadataService = RoleMetadataService = RoleMetadataService_1 = __decorate([
|