@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidstarters/solid-core",
3
- "version": "1.2.132",
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
- // return this.applyValidations(fieldValue);
26
- // Handle multi-select scenario
27
- if (isMultiSelect) {
28
- let values: any[];
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
- try {
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
- // Apply validations to each value asynchronously
39
- const allErrors = await Promise.all(values.map(value => this.applyValidations(value)));
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
- // Flatten the array of errors and return
42
- return allErrors.flat();
43
- } else {
44
- // For non-multi-select, apply validations to the single field value
45
- return this.applyValidations(fieldValue);
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
- const fieldValue: any = dto[this.options.fieldName];
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
- let values: any[];
24
-
25
- try {
26
- // Try to parse the field value, which should be a JSON stringified array
27
- values = JSON.parse(fieldValue);
28
- } catch {
29
- // If parsing fails, fallback to a single value
30
- values = [fieldValue];
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
- // Apply validations to each value asynchronously
34
- const allErrors = await Promise.all(values.map(value => this.applyValidations(value)));
35
-
36
- // Flatten the array of errors and return
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.${templateFormat}`,
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}