@solidstarters/solid-core 1.2.132 → 1.2.134
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.d.ts +1 -0
- package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.js +32 -7
- package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.js.map +1 -1
- package/dist/helpers/field-crud-managers/SelectionStaticFieldCrudManager.d.ts +1 -0
- package/dist/helpers/field-crud-managers/SelectionStaticFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/SelectionStaticFieldCrudManager.js +32 -7
- package/dist/helpers/field-crud-managers/SelectionStaticFieldCrudManager.js.map +1 -1
- package/dist/services/authentication.service.js +16 -1
- package/dist/services/authentication.service.js.map +1 -1
- package/dist/services/import-transaction.service.d.ts.map +1 -1
- package/dist/services/import-transaction.service.js +2 -1
- package/dist/services/import-transaction.service.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.ts +44 -18
- package/src/helpers/field-crud-managers/SelectionStaticFieldCrudManager.ts +43 -15
- package/src/services/authentication.service.ts +17 -1
- package/src/services/import-transaction.service.ts +2 -1
- package/test.json +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidstarters/solid-core",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.134",
|
|
4
4
|
"description": "This module is a NestJS module containing all the required core providers required by a Solid application",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -20,31 +20,57 @@ export class SelectionDynamicFieldCrudManager implements FieldCrudManager {
|
|
|
20
20
|
|
|
21
21
|
async validate(dto: any): Promise<ValidationError[]> {
|
|
22
22
|
const fieldValue: any = dto[this.options.fieldName];
|
|
23
|
+
// return this.applyValidations(fieldValue);
|
|
23
24
|
const isMultiSelect = this.options?.isMultiSelect;
|
|
25
|
+
if (isMultiSelect && fieldValue) {
|
|
26
|
+
const arrayCheck = this.parseAndValidateArray(fieldValue);
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
if (!arrayCheck.isValid) {
|
|
29
|
+
return [
|
|
30
|
+
{
|
|
31
|
+
field: this.options.fieldName,
|
|
32
|
+
error: `Field: ${this.options.fieldName} must be a valid array`,
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
}
|
|
29
36
|
|
|
30
|
-
|
|
31
|
-
// Try to parse the field value, which should be a JSON stringified array
|
|
32
|
-
values = JSON.parse(fieldValue);
|
|
33
|
-
} catch {
|
|
34
|
-
// If parsing fails, fallback to a single value
|
|
35
|
-
values = [fieldValue];
|
|
36
|
-
}
|
|
37
|
+
const values = arrayCheck.values;
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
if (this.isApplyRequiredValidation() && values.length === 0) {
|
|
40
|
+
return [
|
|
41
|
+
{
|
|
42
|
+
field: this.options.fieldName,
|
|
43
|
+
error: `Field: ${this.options.fieldName} is required`,
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
}
|
|
40
47
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
// Apply validations to each value
|
|
49
|
+
const allErrors = await Promise.all(values.map((val) => this.applyValidations(val)));
|
|
50
|
+
return allErrors.flat();
|
|
51
|
+
} else {
|
|
52
|
+
// For non-multi-select, apply validations to the single field value
|
|
53
|
+
return this.applyValidations(fieldValue);
|
|
54
|
+
}
|
|
46
55
|
}
|
|
56
|
+
|
|
57
|
+
private parseAndValidateArray(fieldValue: any): { isValid: boolean; values: any[] } {
|
|
58
|
+
if (Array.isArray(fieldValue)) {
|
|
59
|
+
return { isValid: true, values: fieldValue };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
const parsed = typeof fieldValue === 'string' ? JSON.parse(fieldValue) : null;
|
|
64
|
+
if (Array.isArray(parsed)) {
|
|
65
|
+
return { isValid: true, values: parsed };
|
|
66
|
+
}
|
|
67
|
+
} catch {
|
|
68
|
+
// fall through
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return { isValid: false, values: [] };
|
|
47
72
|
}
|
|
73
|
+
|
|
48
74
|
|
|
49
75
|
private async applyValidations(fieldValue: any): Promise<ValidationError[]> {
|
|
50
76
|
const errors: ValidationError[] = [];
|
|
@@ -16,24 +16,34 @@ export class SelectionStaticFieldCrudManager implements FieldCrudManager {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
async validate(dto: any): Promise<ValidationError[]> {
|
|
19
|
-
|
|
19
|
+
const fieldValue: any = dto[this.options.fieldName];
|
|
20
20
|
// return this.applyValidations(fieldValue);
|
|
21
21
|
const isMultiSelect = this.options?.isMultiSelect;
|
|
22
|
-
if (isMultiSelect) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
if (isMultiSelect && fieldValue) {
|
|
23
|
+
const arrayCheck = this.parseAndValidateArray(fieldValue);
|
|
24
|
+
|
|
25
|
+
if (!arrayCheck.isValid) {
|
|
26
|
+
return [
|
|
27
|
+
{
|
|
28
|
+
field: this.options.fieldName,
|
|
29
|
+
error: `Field: ${this.options.fieldName} must be a valid array`,
|
|
30
|
+
},
|
|
31
|
+
];
|
|
31
32
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
|
|
34
|
+
const values = arrayCheck.values;
|
|
35
|
+
|
|
36
|
+
if (this.isApplyRequiredValidation() && values.length === 0) {
|
|
37
|
+
return [
|
|
38
|
+
{
|
|
39
|
+
field: this.options.fieldName,
|
|
40
|
+
error: `Field: ${this.options.fieldName} is required`,
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Apply validations to each value
|
|
46
|
+
const allErrors = await Promise.all(values.map((val) => this.applyValidations(val)));
|
|
37
47
|
return allErrors.flat();
|
|
38
48
|
} else {
|
|
39
49
|
// For non-multi-select, apply validations to the single field value
|
|
@@ -41,6 +51,24 @@ export class SelectionStaticFieldCrudManager implements FieldCrudManager {
|
|
|
41
51
|
}
|
|
42
52
|
}
|
|
43
53
|
|
|
54
|
+
private parseAndValidateArray(fieldValue: any): { isValid: boolean; values: any[] } {
|
|
55
|
+
if (Array.isArray(fieldValue)) {
|
|
56
|
+
return { isValid: true, values: fieldValue };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
const parsed = typeof fieldValue === 'string' ? JSON.parse(fieldValue) : null;
|
|
61
|
+
if (Array.isArray(parsed)) {
|
|
62
|
+
return { isValid: true, values: parsed };
|
|
63
|
+
}
|
|
64
|
+
} catch {
|
|
65
|
+
// fall through
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return { isValid: false, values: [] };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
44
72
|
private applyValidations(fieldValue: any): ValidationError[] {
|
|
45
73
|
const errors: ValidationError[] = [];
|
|
46
74
|
this.isApplyRequiredValidation() && isEmpty(fieldValue) ? errors.push({ field: this.options.fieldName, error: `Field: ${this.options.fieldName} is required` }) : "no errors";
|
|
@@ -172,7 +172,7 @@ export class AuthenticationService {
|
|
|
172
172
|
catch (err) {
|
|
173
173
|
const pgUniqueViolationErrorCode = '23505';
|
|
174
174
|
if (err.code === pgUniqueViolationErrorCode) {
|
|
175
|
-
throw new ConflictException();
|
|
175
|
+
throw new ConflictException(parseUniqueConstraintError(err.detail || 'A unique constraint violation occurred.'));
|
|
176
176
|
}
|
|
177
177
|
throw err;
|
|
178
178
|
}
|
|
@@ -1115,3 +1115,19 @@ export class AuthenticationService {
|
|
|
1115
1115
|
}
|
|
1116
1116
|
|
|
1117
1117
|
}
|
|
1118
|
+
|
|
1119
|
+
function parseUniqueConstraintError(detail: string): string {
|
|
1120
|
+
const match = detail.match(/Key \(([^)]+)\)=\(([^)]+)\) already exists\./);
|
|
1121
|
+
if (match) {
|
|
1122
|
+
const field = match[1];
|
|
1123
|
+
const value = match[2];
|
|
1124
|
+
const fieldMap: Record<string, string> = {
|
|
1125
|
+
username: 'username',
|
|
1126
|
+
email: 'email address',
|
|
1127
|
+
full_name_user_key: 'full name',
|
|
1128
|
+
};
|
|
1129
|
+
const friendlyField = fieldMap[field] || field;
|
|
1130
|
+
return `A user with ${friendlyField} "${value}" already exists.`;
|
|
1131
|
+
}
|
|
1132
|
+
return detail;
|
|
1133
|
+
}
|
|
@@ -339,9 +339,10 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
|
|
|
339
339
|
throw new BadRequestException(`Failed to create export stream for import transaction ID ${importTransactionId}.`);
|
|
340
340
|
}
|
|
341
341
|
// Return the export stream
|
|
342
|
+
const extension = templateFormat === "excel" ? 'xlsx' : 'csv';
|
|
342
343
|
return {
|
|
343
344
|
stream: exportStream,
|
|
344
|
-
fileName: `${importTransaction.modelMetadata.singularName}-failed-imports.${
|
|
345
|
+
fileName: `${importTransaction.modelMetadata.singularName}-failed-imports.${extension}`,
|
|
345
346
|
mimeType: templateFormat === "excel" ? ImportMimeTypes.EXCEL : ImportMimeTypes.CSV,
|
|
346
347
|
};
|
|
347
348
|
|
package/test.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"selectionValueType":"string","id":1367,"createdAt":"2025-06-26T23:41:13.508Z","updatedAt":"2025-06-26T23:41:13.508Z","deletedAt":null,"deletedTracker":"not-deleted","publishedAt":null,"localeName":null,"defaultEntityLocaleId":null,"name":"variableName","displayName":"Variable Name","description":null,"type":"shortText","ormType":"varchar","defaultValue":null,"regexPattern":null,"regexPatternNotMatchingErrorMsg":null,"required":true,"unique":true,"encrypt":false,"encryptionType":null,"decryptWhen":null,"index":true,"length":256,"max":null,"min":null,"private":false,"mediaTypes":null,"mediaMaxSizeKb":null,"relationType":null,"relationCoModelSingularName":null,"relationCreateInverse":false,"relationCascade":null,"relationModelModuleName":null,"relationCoModelFieldName":null,"isRelationManyToManyOwner":null,"relationFieldFixedFilter":null,"selectionDynamicProvider":null,"selectionDynamicProviderCtxt":null,"selectionStaticValues":null,"computedFieldValueProvider":null,"computedFieldValueProviderCtxt":null,"computedFieldValueType":null,"computedFieldTriggerConfig":null,"uuid":null,"isSystem":true,"isMarkedForRemoval":false,"columnName":null,"relationCoModelColumnName":null,"isUserKey":true,"relationJoinTableName":null,"enableAuditTracking":false,"isMultiSelect":false}' --fields='{"selectionValueType":"string","id":1368,"createdAt":"2025-06-26T23:41:13.515Z","updatedAt":"2025-06-26T23:41:13.515Z","deletedAt":null,"deletedTracker":"not-deleted","publishedAt":null,"localeName":null,"defaultEntityLocaleId":null,"name":"variableType","displayName":"Variable Type","description":null,"type":"selectionStatic","ormType":"varchar","defaultValue":null,"regexPattern":null,"regexPatternNotMatchingErrorMsg":null,"required":true,"unique":false,"encrypt":false,"encryptionType":null,"decryptWhen":null,"index":true,"length":256,"max":null,"min":null,"private":false,"mediaTypes":null,"mediaMaxSizeKb":null,"relationType":null,"relationCoModelSingularName":null,"relationCreateInverse":false,"relationCascade":null,"relationModelModuleName":null,"relationCoModelFieldName":null,"isRelationManyToManyOwner":null,"relationFieldFixedFilter":null,"selectionDynamicProvider":null,"selectionDynamicProviderCtxt":null,"selectionStaticValues":["date:Date","selectionStatic:Selection Static","selectionDynamic:Selection Dynamic"],"computedFieldValueProvider":null,"computedFieldValueProviderCtxt":null,"computedFieldValueType":null,"computedFieldTriggerConfig":null,"uuid":null,"isSystem":true,"isMarkedForRemoval":false,"columnName":null,"relationCoModelColumnName":null,"isUserKey":false,"relationJoinTableName":null,"enableAuditTracking":false,"isMultiSelect":false}' --fields='{"selectionValueType":"string","id":1369,"createdAt":"2025-06-26T23:41:13.521Z","updatedAt":"2025-06-26T23:41:13.521Z","deletedAt":null,"deletedTracker":"not-deleted","publishedAt":null,"localeName":null,"defaultEntityLocaleId":null,"name":"selectionStaticValues","displayName":"Selection Static Values","description":null,"type":"json","ormType":"jsonb","defaultValue":null,"regexPattern":null,"regexPatternNotMatchingErrorMsg":null,"required":false,"unique":false,"encrypt":false,"encryptionType":null,"decryptWhen":null,"index":false,"length":null,"max":null,"min":null,"private":false,"mediaTypes":null,"mediaMaxSizeKb":null,"relationType":null,"relationCoModelSingularName":null,"relationCreateInverse":false,"relationCascade":null,"relationModelModuleName":null,"relationCoModelFieldName":null,"isRelationManyToManyOwner":null,"relationFieldFixedFilter":null,"selectionDynamicProvider":null,"selectionDynamicProviderCtxt":null,"selectionStaticValues":null,"computedFieldValueProvider":null,"computedFieldValueProviderCtxt":null,"computedFieldValueType":null,"computedFieldTriggerConfig":null,"uuid":null,"isSystem":true,"isMarkedForRemoval":false,"columnName":null,"relationCoModelColumnName":null,"isUserKey":false,"relationJoinTableName":null,"enableAuditTracking":false,"isMultiSelect":false}' --fields='{"selectionValueType":"string","id":1370,"createdAt":"2025-06-26T23:41:13.527Z","updatedAt":"2025-06-26T23:41:13.527Z","deletedAt":null,"deletedTracker":"not-deleted","publishedAt":null,"localeName":null,"defaultEntityLocaleId":null,"name":"selectionDynamicSourceType","displayName":"Selection Dynamic Source Type","description":null,"type":"selectionStatic","ormType":"","defaultValue":null,"regexPattern":null,"regexPatternNotMatchingErrorMsg":null,"required":false,"unique":false,"encrypt":false,"encryptionType":null,"decryptWhen":null,"index":false,"length":256,"max":null,"min":null,"private":false,"mediaTypes":null,"mediaMaxSizeKb":null,"relationType":null,"relationCoModelSingularName":null,"relationCreateInverse":false,"relationCascade":null,"relationModelModuleName":null,"relationCoModelFieldName":null,"isRelationManyToManyOwner":null,"relationFieldFixedFilter":null,"selectionDynamicProvider":null,"selectionDynamicProviderCtxt":null,"selectionStaticValues":["sql:SQL","provider:Provider"],"computedFieldValueProvider":null,"computedFieldValueProviderCtxt":null,"computedFieldValueType":null,"computedFieldTriggerConfig":null,"uuid":null,"isSystem":true,"isMarkedForRemoval":false,"columnName":null,"relationCoModelColumnName":null,"isUserKey":false,"relationJoinTableName":null,"enableAuditTracking":false,"isMultiSelect":false}' --fields='{"selectionValueType":"string","id":1371,"createdAt":"2025-06-26T23:41:13.535Z","updatedAt":"2025-06-26T23:41:13.535Z","deletedAt":null,"deletedTracker":"not-deleted","publishedAt":null,"localeName":null,"defaultEntityLocaleId":null,"name":"selectionDynamicSQL","displayName":"Selection Dynamic SQL","description":"SQL query to fetch the data for this variable when it is rendered at runtime. This is only applicable when selectionDynamicSourceType is set to SQL.","type":"longText","ormType":"text","defaultValue":null,"regexPattern":null,"regexPatternNotMatchingErrorMsg":null,"required":false,"unique":false,"encrypt":false,"encryptionType":null,"decryptWhen":null,"index":false,"length":null,"max":null,"min":null,"private":false,"mediaTypes":null,"mediaMaxSizeKb":null,"relationType":null,"relationCoModelSingularName":null,"relationCreateInverse":false,"relationCascade":null,"relationModelModuleName":null,"relationCoModelFieldName":null,"isRelationManyToManyOwner":null,"relationFieldFixedFilter":null,"selectionDynamicProvider":null,"selectionDynamicProviderCtxt":null,"selectionStaticValues":null,"computedFieldValueProvider":null,"computedFieldValueProviderCtxt":null,"computedFieldValueType":null,"computedFieldTriggerConfig":null,"uuid":null,"isSystem":true,"isMarkedForRemoval":false,"columnName":null,"relationCoModelColumnName":null,"isUserKey":false,"relationJoinTableName":null,"enableAuditTracking":false,"isMultiSelect":false}' --fields='{"selectionValueType":"string","id":1372,"createdAt":"2025-06-26T23:41:13.541Z","updatedAt":"2025-06-26T23:41:13.541Z","deletedAt":null,"deletedTracker":"not-deleted","publishedAt":null,"localeName":null,"defaultEntityLocaleId":null,"name":"selectionDynamicProviderName","displayName":"Selection Dynamic Provider Name","description":"This is only applicable when selectionDynamicSourceType is set to provider. It allows the user to select any pre-existing SelectionDynamicProvider implementation used to fetch a dynamic dropdown of values to choose from when this variable is presented to the user.","type":"selectionDynamic","ormType":"varchar","defaultValue":null,"regexPattern":null,"regexPatternNotMatchingErrorMsg":null,"required":false,"unique":false,"encrypt":false,"encryptionType":null,"decryptWhen":null,"index":false,"length":256,"max":null,"min":null,"private":false,"mediaTypes":null,"mediaMaxSizeKb":null,"relationType":null,"relationCoModelSingularName":null,"relationCreateInverse":false,"relationCascade":null,"relationModelModuleName":null,"relationCoModelFieldName":null,"isRelationManyToManyOwner":null,"relationFieldFixedFilter":null,"selectionDynamicProvider":"SelectionDynamicProvider","selectionDynamicProviderCtxt":"{}","selectionStaticValues":null,"computedFieldValueProvider":null,"computedFieldValueProviderCtxt":null,"computedFieldValueType":null,"computedFieldTriggerConfig":null,"uuid":null,"isSystem":true,"isMarkedForRemoval":false,"columnName":null,"relationCoModelColumnName":null,"isUserKey":false,"relationJoinTableName":null,"enableAuditTracking":false,"isMultiSelect":false}' --fields='{"selectionValueType":"string","id":1373,"createdAt":"2025-06-26T23:41:13.548Z","updatedAt":"2025-06-26T23:41:13.548Z","deletedAt":null,"deletedTracker":"not-deleted","publishedAt":null,"localeName":null,"defaultEntityLocaleId":null,"name":"isMultiSelect","displayName":"Is Multi Select","description":"This is relevant only for variables of type \'selectionStatic\' or \'selectionDynamic\'. When set to true, it allows the user to select multiple values from the dropdown.","type":"boolean","ormType":"boolean","defaultValue":"false","regexPattern":null,"regexPatternNotMatchingErrorMsg":null,"required":false,"unique":false,"encrypt":false,"encryptionType":null,"decryptWhen":null,"index":false,"length":null,"max":null,"min":null,"private":false,"mediaTypes":null,"mediaMaxSizeKb":null,"relationType":null,"relationCoModelSingularName":null,"relationCreateInverse":false,"relationCascade":null,"relationModelModuleName":null,"relationCoModelFieldName":null,"isRelationManyToManyOwner":null,"relationFieldFixedFilter":null,"selectionDynamicProvider":null,"selectionDynamicProviderCtxt":null,"selectionStaticValues":null,"computedFieldValueProvider":null,"computedFieldValueProviderCtxt":null,"computedFieldValueType":null,"computedFieldTriggerConfig":null,"uuid":null,"isSystem":true,"isMarkedForRemoval":false,"columnName":null,"relationCoModelColumnName":null,"isUserKey":false,"relationJoinTableName":null,"enableAuditTracking":false,"isMultiSelect":false}' --fields='{"selectionValueType":"string","id":1374,"createdAt":"2025-06-26T23:41:13.554Z","updatedAt":"2025-06-26T23:41:13.554Z","deletedAt":null,"deletedTracker":"not-deleted","publishedAt":null,"localeName":null,"defaultEntityLocaleId":null,"name":"dashboard","displayName":"Dashboard","description":"Related Dashboard Model","type":"relation","ormType":"integer","defaultValue":null,"regexPattern":null,"regexPatternNotMatchingErrorMsg":null,"required":false,"unique":false,"encrypt":false,"encryptionType":null,"decryptWhen":null,"index":false,"length":null,"max":null,"min":null,"private":false,"mediaTypes":null,"mediaMaxSizeKb":null,"relationType":"many-to-one","relationCoModelSingularName":"dashboard","relationCreateInverse":true,"relationCascade":"cascade","relationModelModuleName":"solid-core","relationCoModelFieldName":"dashboardVariables","isRelationManyToManyOwner":null,"relationFieldFixedFilter":null,"selectionDynamicProvider":null,"selectionDynamicProviderCtxt":null,"selectionStaticValues":null,"computedFieldValueProvider":null,"computedFieldValueProviderCtxt":null,"computedFieldValueType":null,"computedFieldTriggerConfig":null,"uuid":null,"isSystem":true,"isMarkedForRemoval":false,"columnName":null,"relationCoModelColumnName":null,"isUserKey":false,"relationJoinTableName":null,"enableAuditTracking":false,"isMultiSelect":false}
|