@adobe/spacecat-shared-data-access 3.47.0 → 3.49.0

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/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## [@adobe/spacecat-shared-data-access-v3.49.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v3.48.0...@adobe/spacecat-shared-data-access-v3.49.0) (2026-04-10)
2
+
3
+ ### Features
4
+
5
+ * **audit-url:** add moneyPages source to auditTargetURLs config ([#1496](https://github.com/adobe/spacecat-shared/issues/1496)) ([78df8f9](https://github.com/adobe/spacecat-shared/commit/78df8f91008e739bfd67e2277858523a276d70b2))
6
+
7
+ ## [@adobe/spacecat-shared-data-access-v3.48.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v3.47.0...@adobe/spacecat-shared-data-access-v3.48.0) (2026-04-08)
8
+
9
+ ### Features
10
+
11
+ * **data-access:** add INACTIVE status, reviews field, and REVIEW_DECISIONS to PlgOnboarding ([#1516](https://github.com/adobe/spacecat-shared/issues/1516)) ([8f038e9](https://github.com/adobe/spacecat-shared/commit/8f038e93287da51acf0e586f3e786aeb00d4a0d3))
12
+
1
13
  ## [@adobe/spacecat-shared-data-access-v3.47.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v3.46.0...@adobe/spacecat-shared-data-access-v3.47.0) (2026-04-07)
2
14
 
3
15
  ### Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/spacecat-shared-data-access",
3
- "version": "3.47.0",
3
+ "version": "3.49.0",
4
4
  "description": "Shared modules of the Spacecat Services - Data Access",
5
5
  "type": "module",
6
6
  "engines": {
@@ -60,9 +60,16 @@ class AuditUrlCollection extends BaseCollection {
60
60
  }
61
61
 
62
62
  // Handle null/undefined values (push to end)
63
- if (aValue == null && bValue == null) return 0;
64
- if (aValue == null) return 1;
65
- if (bValue == null) return -1;
63
+ /* c8 ignore next 6 */
64
+ if (aValue == null && bValue == null) {
65
+ return 0;
66
+ }
67
+ if (aValue == null) {
68
+ return 1;
69
+ }
70
+ if (bValue == null) {
71
+ return -1;
72
+ }
66
73
 
67
74
  // Compare values
68
75
  let comparison = 0;
@@ -75,7 +75,10 @@ class BaseCollection {
75
75
 
76
76
  // eslint-disable-next-line class-methods-use-this
77
77
  #resolveBulkKeyField(keys) {
78
- if (!isNonEmptyArray(keys)) return null;
78
+ /* c8 ignore next 3 */
79
+ if (!isNonEmptyArray(keys)) {
80
+ return null;
81
+ }
79
82
 
80
83
  const [firstKey] = keys;
81
84
  const fields = Object.keys(firstKey);
@@ -93,9 +96,13 @@ class BaseCollection {
93
96
  }
94
97
 
95
98
  #normalizeEnumValue(key, value) {
96
- if (typeof value !== 'string') return value;
99
+ if (typeof value !== 'string') {
100
+ return value;
101
+ }
97
102
  const attr = this.schema.getAttribute(key);
98
- if (!Array.isArray(attr?.type)) return value;
103
+ if (!Array.isArray(attr?.type)) {
104
+ return value;
105
+ }
99
106
  const match = attr.type.find((v) => v.toLowerCase() === value.toLowerCase());
100
107
  return match ?? value;
101
108
  }
@@ -104,7 +111,9 @@ class BaseCollection {
104
111
  #isInvalidInputError(error) {
105
112
  let current = error;
106
113
  while (current) {
107
- if (current?.code === '22P02') return true;
114
+ if (current?.code === '22P02') {
115
+ return true;
116
+ }
108
117
  current = current.cause;
109
118
  }
110
119
  return false;
@@ -112,9 +121,16 @@ class BaseCollection {
112
121
 
113
122
  #logAndThrowError(message, cause) {
114
123
  const parts = [message];
115
- if (cause?.code) parts.push(`[${cause.code}] ${cause.message}`);
116
- if (cause?.details) parts.push(cause.details);
117
- if (cause?.hint) parts.push(`hint: ${cause.hint}`);
124
+ if (cause?.code) {
125
+ parts.push(`[${cause.code}] ${cause.message}`);
126
+ }
127
+ if (cause?.details) {
128
+ parts.push(cause.details);
129
+ }
130
+ /* c8 ignore next 3 */
131
+ if (cause?.hint) {
132
+ parts.push(`hint: ${cause.hint}`);
133
+ }
118
134
 
119
135
  this.log.error(`[${this.entityName}] ${parts.join(' - ')}`);
120
136
 
@@ -595,7 +611,10 @@ class BaseCollection {
595
611
  * @returns {object|null} A model instance, or null if the row is empty/invalid.
596
612
  */
597
613
  createInstanceFromRow(row) {
598
- if (!isNonEmptyObject(row)) return null;
614
+ /* c8 ignore next 3 */
615
+ if (!isNonEmptyObject(row)) {
616
+ return null;
617
+ }
599
618
  return this.#createInstance(this.#toModelRecord(row));
600
619
  }
601
620
 
@@ -748,7 +767,9 @@ class BaseCollection {
748
767
  return instance;
749
768
  } catch (error) {
750
769
  /* c8 ignore next -- re-throw guard (exact match; excludes ValidationError subclass) */
751
- if (error.constructor === DataAccessError) throw error;
770
+ if (error.constructor === DataAccessError) {
771
+ throw error;
772
+ }
752
773
  return this.#logAndThrowError('Failed to create', error);
753
774
  }
754
775
  }
@@ -862,7 +883,9 @@ class BaseCollection {
862
883
  return { createdItems, errorItems };
863
884
  } catch (error) {
864
885
  /* c8 ignore next -- re-throw guard (exact match; excludes ValidationError subclass) */
865
- if (error.constructor === DataAccessError) throw error;
886
+ if (error.constructor === DataAccessError) {
887
+ throw error;
888
+ }
866
889
  return this.#logAndThrowError('Failed to create many', error);
867
890
  }
868
891
  }
@@ -990,7 +1013,9 @@ class BaseCollection {
990
1013
  return undefined;
991
1014
  } catch (error) {
992
1015
  /* c8 ignore next -- re-throw guard (exact match; excludes ValidationError subclass) */
993
- if (error.constructor === DataAccessError) throw error;
1016
+ if (error.constructor === DataAccessError) {
1017
+ throw error;
1018
+ }
994
1019
  return this.#logAndThrowError('Failed to save many', error);
995
1020
  }
996
1021
  }
@@ -1022,7 +1047,9 @@ class BaseCollection {
1022
1047
  return undefined;
1023
1048
  } catch (error) {
1024
1049
  /* c8 ignore next -- re-throw guard (exact match; excludes ValidationError subclass) */
1025
- if (error.constructor === DataAccessError) throw error;
1050
+ if (error.constructor === DataAccessError) {
1051
+ throw error;
1052
+ }
1026
1053
  return this.#logAndThrowError('Failed to remove by IDs', error);
1027
1054
  }
1028
1055
  }
@@ -143,7 +143,9 @@ class Schema {
143
143
  Object.keys(indexes).forEach((indexName) => {
144
144
  const indexKeys = this.getIndexKeys(indexName);
145
145
 
146
- if (!isNonEmptyArray(indexKeys)) return;
146
+ if (!isNonEmptyArray(indexKeys)) {
147
+ return;
148
+ }
147
149
 
148
150
  const keySets = [];
149
151
  for (let i = 1; i <= indexKeys.length; i += 1) {
@@ -176,7 +176,9 @@ class Configuration {
176
176
 
177
177
  isHandlerEnabledForSite(type, site) {
178
178
  const handler = this.getHandlers()?.[type];
179
- if (!handler) return false;
179
+ if (!handler) {
180
+ return false;
181
+ }
180
182
 
181
183
  const siteId = site.getId();
182
184
  const orgId = site.getOrganizationId();
@@ -203,7 +205,9 @@ class Configuration {
203
205
 
204
206
  isHandlerEnabledForOrg(type, org) {
205
207
  const handler = this.getHandlers()?.[type];
206
- if (!handler) return false;
208
+ if (!handler) {
209
+ return false;
210
+ }
207
211
 
208
212
  const orgId = org.getId();
209
213
 
@@ -226,7 +230,9 @@ class Configuration {
226
230
  const handlers = this.getHandlers();
227
231
  const handler = handlers?.[type];
228
232
 
229
- if (!isNonEmptyObject(handler)) return;
233
+ if (!isNonEmptyObject(handler)) {
234
+ return;
235
+ }
230
236
 
231
237
  if (!isNonEmptyObject(handler.disabled)) {
232
238
  handler.disabled = { orgs: [], sites: [] };
@@ -267,7 +273,9 @@ class Configuration {
267
273
 
268
274
  enableHandlerForSite(type, site) {
269
275
  const siteId = site.getId();
270
- if (this.isHandlerEnabledForSite(type, site)) return;
276
+ if (this.isHandlerEnabledForSite(type, site)) {
277
+ return;
278
+ }
271
279
 
272
280
  const deps = this.isHandlerDependencyMetForSite(type, site);
273
281
  if (deps !== true) {
@@ -287,7 +295,9 @@ class Configuration {
287
295
  isHandlerDependencyMetForOrg(type, org) {
288
296
  const handler = this.getHandler(type);
289
297
 
290
- if (!handler || !isNonEmptyArray(handler?.dependencies)) return true;
298
+ if (!handler || !isNonEmptyArray(handler?.dependencies)) {
299
+ return true;
300
+ }
291
301
 
292
302
  const unmetDependencies = handler.dependencies
293
303
  .filter(({ handler: depHandler }) => !this.isHandlerEnabledForOrg(depHandler, org))
@@ -305,7 +315,9 @@ class Configuration {
305
315
  */
306
316
  isHandlerDependencyMetForSite(type, site) {
307
317
  const handler = this.getHandler(type);
308
- if (!handler || !isNonEmptyArray(handler?.dependencies)) return true;
318
+ if (!handler || !isNonEmptyArray(handler?.dependencies)) {
319
+ return true;
320
+ }
309
321
 
310
322
  const unmetDependencies = handler.dependencies
311
323
  .filter(({ handler: depHandler }) => !this.isHandlerEnabledForSite(depHandler, site))
@@ -316,7 +328,9 @@ class Configuration {
316
328
 
317
329
  enableHandlerForOrg(type, org) {
318
330
  const orgId = org.getId();
319
- if (this.isHandlerEnabledForOrg(type, org)) return;
331
+ if (this.isHandlerEnabledForOrg(type, org)) {
332
+ return;
333
+ }
320
334
  const deps = this.isHandlerDependencyMetForOrg(type, org);
321
335
  if (deps !== true) {
322
336
  throw new Error(`Cannot enable handler ${type} for org ${orgId} because of missing dependencies: ${deps}`);
@@ -327,14 +341,18 @@ class Configuration {
327
341
 
328
342
  disableHandlerForSite(type, site) {
329
343
  const siteId = site.getId();
330
- if (!this.isHandlerEnabledForSite(type, site)) return;
344
+ if (!this.isHandlerEnabledForSite(type, site)) {
345
+ return;
346
+ }
331
347
 
332
348
  this.updateHandlerSites(type, siteId, false);
333
349
  }
334
350
 
335
351
  disableHandlerForOrg(type, org) {
336
352
  const orgId = org.getId();
337
- if (!this.isHandlerEnabledForOrg(type, org)) return;
353
+ if (!this.isHandlerEnabledForOrg(type, org)) {
354
+ return;
355
+ }
338
356
 
339
357
  this.updateHandlerOrgs(type, orgId, false);
340
358
  }
@@ -18,7 +18,18 @@ export type PlgOnboardingStatus =
18
18
  | 'ONBOARDED'
19
19
  | 'ERROR'
20
20
  | 'WAITING_FOR_IP_ALLOWLISTING'
21
- | 'WAITLISTED';
21
+ | 'WAITLISTED'
22
+ | 'INACTIVE';
23
+
24
+ export type PlgOnboardingReviewDecision = 'BYPASSED' | 'UPHELD';
25
+
26
+ export interface PlgOnboardingReview {
27
+ reason: string;
28
+ decision: PlgOnboardingReviewDecision;
29
+ reviewedBy: string;
30
+ reviewedAt: string;
31
+ justification: string;
32
+ }
22
33
 
23
34
  export interface PlgOnboarding extends BaseModel {
24
35
  getImsOrgId(): string;
@@ -31,6 +42,7 @@ export interface PlgOnboarding extends BaseModel {
31
42
  getError(): object | null;
32
43
  getBotBlocker(): object | null;
33
44
  getWaitlistReason(): string | null;
45
+ getReviews(): PlgOnboardingReview[] | null;
34
46
  getCompletedAt(): string | null;
35
47
  setStatus(status: PlgOnboardingStatus): PlgOnboarding;
36
48
  setSiteId(siteId: string): PlgOnboarding;
@@ -39,6 +51,7 @@ export interface PlgOnboarding extends BaseModel {
39
51
  setError(error: object): PlgOnboarding;
40
52
  setBotBlocker(botBlocker: object): PlgOnboarding;
41
53
  setWaitlistReason(waitlistReason: string): PlgOnboarding;
54
+ setReviews(reviews: PlgOnboardingReview[]): PlgOnboarding;
42
55
  setCompletedAt(completedAt: string): PlgOnboarding;
43
56
  }
44
57
 
@@ -33,6 +33,12 @@ class PlgOnboarding extends BaseModel {
33
33
  ERROR: 'ERROR',
34
34
  WAITING_FOR_IP_ALLOWLISTING: 'WAITING_FOR_IP_ALLOWLISTING',
35
35
  WAITLISTED: 'WAITLISTED',
36
+ INACTIVE: 'INACTIVE',
37
+ };
38
+
39
+ static REVIEW_DECISIONS = {
40
+ BYPASSED: 'BYPASSED',
41
+ UPHELD: 'UPHELD',
36
42
  };
37
43
  }
38
44
 
@@ -80,6 +80,27 @@ const schema = new SchemaBuilder(PlgOnboarding, PlgOnboardingCollection)
80
80
  type: 'string',
81
81
  required: false,
82
82
  })
83
+ .addAttribute('reviews', {
84
+ type: 'list',
85
+ required: false,
86
+ items: {
87
+ type: 'map',
88
+ properties: {
89
+ reason: { type: 'string' },
90
+ decision: { type: 'string' },
91
+ reviewedBy: { type: 'string' },
92
+ reviewedAt: { type: 'string' },
93
+ justification: { type: 'string' },
94
+ },
95
+ },
96
+ validate: (value) => {
97
+ if (!Array.isArray(value)) {
98
+ return false;
99
+ }
100
+ const valid = Object.values(PlgOnboarding.REVIEW_DECISIONS);
101
+ return value.every((r) => valid.includes(r.decision) && isIsoDate(r.reviewedAt));
102
+ },
103
+ })
83
104
  .addAttribute('completedAt', {
84
105
  type: 'string',
85
106
  validate: (value) => !value || isIsoDate(value),
@@ -404,6 +404,9 @@ export const configSchema = Joi.object({
404
404
  manual: Joi.array().items(Joi.object({
405
405
  url: Joi.string().uri().required(),
406
406
  })).optional().default([]),
407
+ moneyPages: Joi.array().items(Joi.object({
408
+ url: Joi.string().uri().required(),
409
+ })).optional().default([]),
407
410
  }).options({ stripUnknown: true }).optional(),
408
411
  handlers: Joi.object().pattern(Joi.string(), Joi.object({
409
412
  mentions: Joi.object().pattern(Joi.string(), Joi.array().items(Joi.string())),
@@ -515,7 +518,7 @@ export const Config = (data = {}) => {
515
518
  self.getEdgeOptimizeConfig = () => state?.edgeOptimizeConfig;
516
519
  self.getOnboardConfig = () => state?.onboardConfig;
517
520
  self.getCommerceLlmoConfig = () => state?.commerceLlmoConfig;
518
- const AUDIT_TARGET_SOURCES = ['manual'];
521
+ const AUDIT_TARGET_SOURCES = ['manual', 'moneyPages'];
519
522
  const auditTargetEntrySchema = Joi.object({
520
523
  url: Joi.string().uri().required(),
521
524
  });
@@ -530,7 +533,9 @@ export const Config = (data = {}) => {
530
533
 
531
534
  self.getAuditTargetURLs = () => {
532
535
  const targets = state?.auditTargetURLs;
533
- if (!targets) return [];
536
+ if (!targets) {
537
+ return [];
538
+ }
534
539
  return AUDIT_TARGET_SOURCES.flatMap(
535
540
  (source) => (targets[source] || []).map((entry) => ({ ...entry, source })),
536
541
  );
@@ -564,7 +569,9 @@ export const Config = (data = {}) => {
564
569
 
565
570
  self.removeAuditTargetURL = (source, url) => {
566
571
  validateAuditTargetSource(source);
567
- if (!state.auditTargetURLs?.[source]) return;
572
+ if (!state.auditTargetURLs?.[source]) {
573
+ return;
574
+ }
568
575
  state.auditTargetURLs[source] = state.auditTargetURLs[source]
569
576
  .filter((t) => t.url !== url);
570
577
  };
@@ -702,7 +709,10 @@ export const Config = (data = {}) => {
702
709
 
703
710
  self.removeLlmoUrlPattern = (urlPattern) => {
704
711
  const urlPatterns = state.llmo?.urlPatterns;
705
- if (!urlPatterns) return;
712
+ /* c8 ignore next 3 */
713
+ if (!urlPatterns) {
714
+ return;
715
+ }
706
716
 
707
717
  state.llmo.urlPatterns = urlPatterns.filter(
708
718
  (pattern) => pattern.urlPattern !== urlPattern,
@@ -733,7 +743,9 @@ export const Config = (data = {}) => {
733
743
  };
734
744
 
735
745
  self.removeLlmoTag = (tag) => {
736
- if (!state.llmo?.tags) return;
746
+ if (!state.llmo?.tags) {
747
+ return;
748
+ }
737
749
  state.llmo.tags = state.llmo.tags.filter((t) => t !== tag);
738
750
  };
739
751
 
@@ -803,7 +815,10 @@ export const Config = (data = {}) => {
803
815
  const prior = state.brandProfile || {};
804
816
  // compute hash over all content except functional fields
805
817
  const stripFunctional = (p) => {
806
- if (!isNonEmptyObject(p)) return {};
818
+ /* c8 ignore next 3 */
819
+ if (!isNonEmptyObject(p)) {
820
+ return {};
821
+ }
807
822
  const {
808
823
  /* eslint-disable no-unused-vars */
809
824
  version, updatedAt, contentHash, ...rest
@@ -861,7 +876,9 @@ export const Config = (data = {}) => {
861
876
  };
862
877
 
863
878
  self.disableImport = (type) => {
864
- if (!state.imports) return;
879
+ if (!state.imports) {
880
+ return;
881
+ }
865
882
 
866
883
  state.imports = state.imports.map(
867
884
  (imp) => (imp.type === type ? { ...imp, enabled: false } : imp),
@@ -110,7 +110,7 @@ export interface LlmoCustomerIntent {
110
110
  value: string;
111
111
  }
112
112
 
113
- export type AuditTargetSource = 'manual';
113
+ export type AuditTargetSource = 'manual' | 'moneyPages';
114
114
 
115
115
  export interface AuditTargetEntry {
116
116
  url: string;
@@ -122,6 +122,7 @@ export interface AuditTargetEntryWithSource extends AuditTargetEntry {
122
122
 
123
123
  export interface AuditTargetURLs {
124
124
  manual?: AuditTargetEntry[];
125
+ moneyPages?: AuditTargetEntry[];
125
126
  }
126
127
 
127
128
  export interface SiteConfig {
@@ -53,7 +53,9 @@ class SiteEnrollmentCollection extends BaseCollection {
53
53
  siteId: item.siteId,
54
54
  entitlementId: item.entitlementId,
55
55
  });
56
- if (existing) return existing;
56
+ if (existing) {
57
+ return existing;
58
+ }
57
59
  }
58
60
 
59
61
  return super.create(item, options);
@@ -37,7 +37,9 @@ export const FIELD_TRANSFORMERS = {
37
37
  * Used for accessibility-related opportunity types.
38
38
  */
39
39
  filterIssuesOccurrences: (issues) => {
40
- if (!Array.isArray(issues)) return issues;
40
+ if (!Array.isArray(issues)) {
41
+ return issues;
42
+ }
41
43
  return issues.map((issue) => ({
42
44
  occurrences: issue.occurrences,
43
45
  }));
@@ -47,7 +49,9 @@ export const FIELD_TRANSFORMERS = {
47
49
  * Used for Core Web Vitals opportunity type.
48
50
  */
49
51
  filterCwvMetrics: (metrics) => {
50
- if (!Array.isArray(metrics)) return metrics;
52
+ if (!Array.isArray(metrics)) {
53
+ return metrics;
54
+ }
51
55
  return metrics.map((metric) => ({
52
56
  deviceType: metric.deviceType,
53
57
  lcp: metric.lcp,
@@ -65,7 +69,9 @@ export const FIELD_TRANSFORMERS = {
65
69
  * /AltText/handlers/AltTextOpportunityAdapter.tsx
66
70
  */
67
71
  extractPageUrlFromRecommendations: (recommendations) => {
68
- if (!Array.isArray(recommendations)) return recommendations;
72
+ if (!Array.isArray(recommendations)) {
73
+ return recommendations;
74
+ }
69
75
  return recommendations.map((rec) => ({
70
76
  pageUrl: rec.pageUrl,
71
77
  ...(rec.isDecorative !== undefined && { isDecorative: rec.isDecorative }),
@@ -77,7 +83,9 @@ export const FIELD_TRANSFORMERS = {
77
83
  * Used for security vulnerability opportunity types.
78
84
  */
79
85
  extractCveUrls: (cves) => {
80
- if (!Array.isArray(cves)) return cves;
86
+ if (!Array.isArray(cves)) {
87
+ return cves;
88
+ }
81
89
  return cves.map((cve) => ({
82
90
  url: cve.url,
83
91
  }));
@@ -100,7 +100,9 @@ class SuggestionGrantCollection extends BaseCollection {
100
100
 
101
101
  return { grantedIds, notGrantedIds, grantIds };
102
102
  } catch (err) {
103
- if (err instanceof DataAccessError) throw err;
103
+ if (err instanceof DataAccessError) {
104
+ throw err;
105
+ }
104
106
  this.log.error('splitSuggestionsByGrantStatus failed', err);
105
107
  throw new DataAccessError('Failed to split suggestions by grant status', this, err);
106
108
  }
@@ -115,7 +117,9 @@ class SuggestionGrantCollection extends BaseCollection {
115
117
  * false otherwise or if id is empty.
116
118
  */
117
119
  async isSuggestionGranted(suggestionId) {
118
- if (!hasText(suggestionId)) return false;
120
+ if (!hasText(suggestionId)) {
121
+ return false;
122
+ }
119
123
  const { grantedIds } = await this.splitSuggestionsByGrantStatus([suggestionId]);
120
124
  return grantedIds.length > 0;
121
125
  }
@@ -74,14 +74,18 @@ export const guardAny = (propertyName, value, entityName, nullable = false) => {
74
74
  * @throws Will throw an error if the value is not a valid boolean.
75
75
  */
76
76
  export const guardBoolean = (propertyName, value, entityName, nullable = false) => {
77
- if (checkNullable(value, nullable)) return;
77
+ if (checkNullable(value, nullable)) {
78
+ return;
79
+ }
78
80
  if (typeof value !== 'boolean') {
79
81
  throw new ValidationError(`Validation failed in ${entityName}: ${propertyName} must be a boolean`);
80
82
  }
81
83
  };
82
84
 
83
85
  export const guardArray = (propertyName, value, entityName, type = 'string', nullable = false) => {
84
- if (checkNullable(value, nullable)) return;
86
+ if (checkNullable(value, nullable)) {
87
+ return;
88
+ }
85
89
  if (!Array.isArray(value)) {
86
90
  throw new ValidationError(`Validation failed in ${entityName}: ${propertyName} must be an array`);
87
91
  }
@@ -100,7 +104,9 @@ export const guardArray = (propertyName, value, entityName, type = 'string', nul
100
104
  * @throws Will throw an error if the value is not a valid set (unique array) of a given type.
101
105
  */
102
106
  export const guardSet = (propertyName, value, entityName, type = 'string', nullable = false) => {
103
- if (checkNullable(value, nullable)) return;
107
+ if (checkNullable(value, nullable)) {
108
+ return;
109
+ }
104
110
  if (!Array.isArray(value) || new Set(value).size !== value.length) {
105
111
  throw new ValidationError(`Validation failed in ${entityName}: ${propertyName} must be a unique array (set)`);
106
112
  }
@@ -118,7 +124,9 @@ export const guardSet = (propertyName, value, entityName, type = 'string', nulla
118
124
  * @throws Will throw an error if the value is not a valid string.
119
125
  */
120
126
  export const guardString = (propertyName, value, entityName, nullable = false) => {
121
- if (checkNullable(value, nullable)) return;
127
+ if (checkNullable(value, nullable)) {
128
+ return;
129
+ }
122
130
  if (!hasText(value)) {
123
131
  throw new ValidationError(`Validation failed in ${entityName}: ${propertyName} is required`);
124
132
  }
@@ -134,7 +142,9 @@ export const guardString = (propertyName, value, entityName, nullable = false) =
134
142
  * @throws Will throw an error if the value is not a valid enum value.
135
143
  */
136
144
  export const guardEnum = (propertyName, value, enumValues, entityName, nullable = false) => {
137
- if (checkNullable(value, nullable)) return;
145
+ if (checkNullable(value, nullable)) {
146
+ return;
147
+ }
138
148
  if (!enumValues.includes(value)) {
139
149
  throw new ValidationError(`Validation failed in ${entityName}: ${propertyName} must be one of ${enumValues}`);
140
150
  }
@@ -149,7 +159,9 @@ export const guardEnum = (propertyName, value, enumValues, entityName, nullable
149
159
  * @throws Will throw an error if the value is not a valid ID.
150
160
  */
151
161
  export const guardId = (propertyName, value, entityName, nullable = false) => {
152
- if (checkNullable(value, nullable)) return;
162
+ if (checkNullable(value, nullable)) {
163
+ return;
164
+ }
153
165
  if (!isValidUUID(value)) {
154
166
  throw new ValidationError(`Validation failed in ${entityName}: ${propertyName} must be a valid UUID`);
155
167
  }
@@ -164,7 +176,9 @@ export const guardId = (propertyName, value, entityName, nullable = false) => {
164
176
  * @throws Will throw an error if the value is not a valid map (object).
165
177
  */
166
178
  export const guardMap = (propertyName, value, entityName, nullable = false) => {
167
- if (checkNullable(value, nullable)) return;
179
+ if (checkNullable(value, nullable)) {
180
+ return;
181
+ }
168
182
  if (!isObject(value)) {
169
183
  throw new ValidationError(`Validation failed in ${entityName}: ${propertyName} must be an object`);
170
184
  }
@@ -179,7 +193,9 @@ export const guardMap = (propertyName, value, entityName, nullable = false) => {
179
193
  * @throws Will throw an error if the value is not a valid number.
180
194
  */
181
195
  export const guardNumber = (propertyName, value, entityName, nullable = false) => {
182
- if (checkNullable(value, nullable)) return;
196
+ if (checkNullable(value, nullable)) {
197
+ return;
198
+ }
183
199
  if (!isNumber(value)) {
184
200
  throw new ValidationError(`Validation failed in ${entityName}: ${propertyName} must be a number`);
185
201
  }