@carecard/validate 3.17.0 → 3.19.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.
Files changed (36) hide show
  1. package/.agents/skills/carecard-workspace-standards/SKILL.md +49 -20
  2. package/.agents/skills/github-pr-create-update/SKILL.md +22 -1
  3. package/.agents/skills/github-pr-merge-cleanup/SKILL.md +22 -1
  4. package/.agents/skills/logged-in-user-profile-page/SKILL.md +22 -1
  5. package/.agents/skills/pkg-publish/SKILL.md +22 -1
  6. package/.agents/skills/pkg-validate-coding-standards-and-best-practices/SKILL.md +47 -9
  7. package/.agents/skills/pkg-validate-validation-library/SKILL.md +45 -14
  8. package/.agents/skills/software-design-patterns-and-clean-code/SKILL.md +23 -3
  9. package/.codex/AGENTS.md +41 -10
  10. package/.github/workflows/auto-draft-pr.yml +173 -151
  11. package/.github/workflows/ci.yml +35 -32
  12. package/.husky/pre-commit +4 -4
  13. package/.prettierrc.js +10 -9
  14. package/AGENTS.md +19 -0
  15. package/eslint.config.mjs +60 -8
  16. package/index.d.ts +108 -107
  17. package/index.js +6 -6
  18. package/lib/validate.js +230 -157
  19. package/lib/validateNewUserRoleRequest.js +68 -60
  20. package/lib/validateProperties.js +326 -326
  21. package/lib/validateWhitelistProperties.js +182 -142
  22. package/lint-staged.config.mjs +36 -0
  23. package/package.json +66 -60
  24. package/readme.md +22 -1
  25. package/scripts/canonicalTestCommand.test.mjs +32 -0
  26. package/scripts/packageTaskRunner.audit.mjs +37 -0
  27. package/scripts/packageTaskRunner.test.mjs +64 -0
  28. package/scripts/runPackageTask.mjs +135 -0
  29. package/scripts/testOrder/randomizeTestOrder.cjs +35 -25
  30. package/scripts/testOrder/randomizeTestOrder.test.mjs +19 -19
  31. package/scripts/testOrder/testOrderPolicy.audit.mjs +54 -0
  32. package/scripts/testParallel/parallelTestPolicy.audit.mjs +63 -0
  33. package/scripts/testParallel/runIndexedMochaTests.cjs +45 -43
  34. package/scripts/testParallel/runIndexedMochaTests.test.mjs +13 -7
  35. package/scripts/testOrder/testOrderPolicy.test.mjs +0 -48
  36. package/scripts/testParallel/parallelTestPolicy.test.mjs +0 -39
package/index.d.ts CHANGED
@@ -20,94 +20,95 @@ export type ValidateWhitelistFlattenKeyStyle = 'path' | 'leaf';
20
20
  * Options for {@link validateWhitelistProperties}.
21
21
  */
22
22
  export interface ValidateWhitelistPropertiesOptions {
23
- /** Properties allowed in the input but not required. */
24
- optionalProperties?: readonly string[] | null;
25
- /** When true, the returned object's keys are converted to snake_case. */
26
- convertToSnakeCase?: boolean;
27
- /**
28
- * When true, the returned object is flattened so that every validated leaf
29
- * becomes a top-level key. No nested objects remain in the output. Applied
30
- * after snake_case conversion.
31
- */
32
- flattenOutput?: boolean;
33
- /**
34
- * Controls flattened key naming when `flattenOutput` is true.
35
- * - `path` uses full dot-notation paths, e.g. `{ "user.email": "Jane" }`.
36
- * - `leaf` uses only leaf names, e.g. `{ email: "Jane" }`.
37
- *
38
- * Defaults to `path`.
39
- */
40
- flattenKeyStyle?: ValidateWhitelistFlattenKeyStyle;
23
+ /** Properties allowed in the input but not required. */
24
+ optionalProperties?: readonly string[] | null;
25
+ /** When true, the returned object's keys are converted to snake_case. */
26
+ convertToSnakeCase?: boolean;
27
+ /**
28
+ * When true, the returned object is flattened so that every validated leaf
29
+ * becomes a top-level key. No nested objects remain in the output. Applied
30
+ * after snake_case conversion.
31
+ */
32
+ flattenOutput?: boolean;
33
+ /**
34
+ * Controls flattened key naming when `flattenOutput` is true.
35
+ * - `path` uses full dot-notation paths, e.g. `{ "user.email": "Jane" }`.
36
+ * - `leaf` uses only leaf names, e.g. `{ email: "Jane" }`.
37
+ *
38
+ * Defaults to `path`.
39
+ */
40
+ flattenKeyStyle?: ValidateWhitelistFlattenKeyStyle;
41
41
  }
42
42
 
43
43
  export interface ValidateWhitelistPropertiesFunction {
44
- /**
45
- * Validates and transforms whitelisted properties from an input object.
46
- *
47
- * - Supports nested objects via dot-notation paths (e.g. `"address.city"`),
48
- * up to 5 levels deep. The function checks that each path resolves to an
49
- * existing leaf property and validates the leaf value by its leaf segment.
50
- * - Extracts only the whitelisted (required + optional) leaf properties and
51
- * rebuilds the same nested shape in the result.
52
- * - Validates values via {@link validateProperties}.
53
- * - Throws a "Bad_Input" error when any required property is missing/invalid,
54
- * when a provided optional property has an invalid value, when a path
55
- * exceeds 5 levels of nesting, or when the combined count of
56
- * `requiredProperties` and `options.optionalProperties` exceeds 5000.
57
- * - Array values are supported: if a leaf value is an array, the per-leaf
58
- * validator is applied to each element. The leaf is accepted only when every
59
- * element passes validation, and the returned value is an array of the
60
- * validated elements.
61
- * - Optionally converts the resulting keys, including nested keys, to snake_case.
62
- * - Optionally flattens the result after snake_case conversion.
63
- *
64
- * @param inputObject The input object, for example `req.body` or `req.params`.
65
- * @param requiredProperties Leaf paths that must be present and valid. Dot notation is supported.
66
- * @param options Optional additional leaf paths plus output transformation flags.
67
- */
68
- (
69
- inputObject?: ValidatePropertiesInput,
70
- requiredProperties?: readonly string[] | null,
71
- options?: ValidateWhitelistPropertiesOptions | null,
72
- ): Promise<ValidatePropertiesResult>;
73
- validateWhitelistProperties: ValidateWhitelistPropertiesFunction;
74
- MAX_NESTING_DEPTH: 5;
75
- MAX_KEYS_PER_CALL: 5000;
44
+ /**
45
+ * Validates and transforms whitelisted properties from an input object.
46
+ *
47
+ * - Supports nested objects via dot-notation paths (e.g. `"address.city"`),
48
+ * up to 5 levels deep. The function checks that each path resolves to an
49
+ * existing leaf property and validates the leaf value by its leaf segment.
50
+ * - Extracts only the whitelisted (required + optional) leaf properties and
51
+ * rebuilds the same nested shape in the result.
52
+ * - Validates values via {@link validateProperties}.
53
+ * - Throws a "Bad_Input" error when any required property is missing/invalid,
54
+ * when a provided optional property has an invalid value, when a path
55
+ * exceeds 5 levels of nesting, or when the combined count of
56
+ * `requiredProperties` and `options.optionalProperties` exceeds 5000.
57
+ * - Array values are supported: if a leaf value is an array, the per-leaf
58
+ * validator is applied to each element. The leaf is accepted only when every
59
+ * element passes validation, and the returned value is an array of the
60
+ * validated elements.
61
+ * - Optionally converts the resulting keys, including nested keys, to snake_case.
62
+ * - Optionally flattens the result after snake_case conversion.
63
+ *
64
+ * @param inputObject The input object, for example `req.body` or `req.params`.
65
+ * @param requiredProperties Leaf paths that must be present and valid. Dot notation is supported.
66
+ * @param options Optional additional leaf paths plus output transformation flags.
67
+ */
68
+ (
69
+ inputObject?: ValidatePropertiesInput,
70
+ requiredProperties?: readonly string[] | null,
71
+ options?: ValidateWhitelistPropertiesOptions | null,
72
+ ): Promise<ValidatePropertiesResult>;
73
+ validateWhitelistProperties: ValidateWhitelistPropertiesFunction;
74
+ MAX_NESTING_DEPTH: 5;
75
+ MAX_KEYS_PER_CALL: 5000;
76
76
  }
77
77
 
78
78
  export const validateWhitelistProperties: ValidateWhitelistPropertiesFunction;
79
79
 
80
80
  export type UserRoleRequestRole = 'student' | 'intern' | 'volunteer';
81
- export type UserRoleRequestScopeRequirement = boolean | typeof REQUIRE_SCOPE_WHEN_ROLE_OR_SCOPE_PRESENT;
81
+ export type UserRoleRequestScopeRequirement =
82
+ boolean | typeof REQUIRE_SCOPE_WHEN_ROLE_OR_SCOPE_PRESENT;
82
83
 
83
84
  export const DEFAULT_USER_ROLE_REQUEST_ROLE: 'student';
84
85
  export const REQUIRE_SCOPE_WHEN_ROLE_OR_SCOPE_PRESENT: 'whenRoleOrScopePresent';
85
86
 
86
87
  export interface ValidateNewUserRoleRequestOptions {
87
- defaultRole?: UserRoleRequestRole | undefined;
88
- requireScope?: UserRoleRequestScopeRequirement;
88
+ defaultRole?: UserRoleRequestRole | undefined;
89
+ requireScope?: UserRoleRequestScopeRequirement;
89
90
  }
90
91
 
91
92
  export interface ValidateNewUserRoleRequestInput extends Record<string, unknown> {
92
- role_name?: unknown;
93
- roleName?: unknown;
94
- role?: unknown;
95
- institution_id?: unknown;
96
- institutionId?: unknown;
97
- campus_id?: unknown;
98
- campusId?: unknown;
99
- program_id?: unknown;
100
- programId?: unknown;
101
- program_term_id?: unknown;
102
- programTermId?: unknown;
93
+ role_name?: unknown;
94
+ roleName?: unknown;
95
+ role?: unknown;
96
+ institution_id?: unknown;
97
+ institutionId?: unknown;
98
+ campus_id?: unknown;
99
+ campusId?: unknown;
100
+ program_id?: unknown;
101
+ programId?: unknown;
102
+ program_term_id?: unknown;
103
+ programTermId?: unknown;
103
104
  }
104
105
 
105
106
  export interface ValidateNewUserRoleRequestPayload extends Record<string, unknown> {
106
- role_name?: string;
107
- institution_id?: string;
108
- campus_id?: string;
109
- program_id?: string;
110
- program_term_id?: string;
107
+ role_name?: string;
108
+ institution_id?: string;
109
+ campus_id?: string;
110
+ program_id?: string;
111
+ program_term_id?: string;
111
112
  }
112
113
 
113
114
  /**
@@ -116,8 +117,8 @@ export interface ValidateNewUserRoleRequestPayload extends Record<string, unknow
116
117
  * both institution_id and campus_id must be provided.
117
118
  */
118
119
  export function validateNewUserRoleRequestObject(
119
- roleRequest?: ValidateNewUserRoleRequestInput | null,
120
- options?: ValidateNewUserRoleRequestOptions | null,
120
+ roleRequest?: ValidateNewUserRoleRequestInput | null,
121
+ options?: ValidateNewUserRoleRequestOptions | null,
121
122
  ): ValidateNewUserRoleRequestPayload;
122
123
 
123
124
  /** Checks if the string is a valid image URL format. */
@@ -198,40 +199,40 @@ export const isValidArrayOfStrings: BoolValidator;
198
199
  * @deprecated Use direct imports instead.
199
200
  */
200
201
  export const validate: {
201
- isImageUrl: typeof isImageUrl;
202
- isInteger: typeof isInteger;
203
- isValidJsonString: typeof isValidJsonString;
204
- isValidIntegerString: typeof isValidIntegerString;
205
- isValidUuidString: typeof isValidUuidString;
206
- isCcIdString: typeof isCcIdString;
207
- isCharactersString: typeof isCharactersString;
208
- isStreetString: typeof isStreetString;
209
- isNameString: typeof isNameString;
210
- isSafeSearchString: typeof isSafeSearchString;
211
- isEmailString: typeof isEmailString;
212
- isJwtString: typeof isJwtString;
213
- isPasswordString: typeof isPasswordString;
214
- isSimplePasswordString: typeof isSimplePasswordString;
215
- isPasswordStringFailureMessage: typeof isPasswordStringFailureMessage;
216
- isSimplePasswordStringFailureMessage: typeof isSimplePasswordStringFailureMessage;
217
- isUsernameString: typeof isUsernameString;
218
- isPhoneNumber: typeof isPhoneNumber;
219
- isUrlSafeString: typeof isUrlSafeString;
220
- isString6To24CharacterLong: typeof isString6To24CharacterLong;
221
- isString6To16CharacterLong: typeof isString6To16CharacterLong;
222
- isProvinceString: typeof isProvinceString;
223
- isBoolValue: typeof isBoolValue;
224
- isPostalCodeString: typeof isPostalCodeString;
225
- isSafeString: typeof isSafeString;
226
- isTextString: typeof isTextString;
227
- isInStringArray: typeof isInStringArray;
228
- isUserRoleRequestStatusString: typeof isUserRoleRequestStatusString;
229
- isUserRoleRequestRoleString: typeof isUserRoleRequestRoleString;
230
- isCountryCodeString: typeof isCountryCodeString;
231
- isValidDomainName: typeof isValidDomainName;
232
- isValidTimestampzString: typeof isValidTimestampzString;
233
- isValidTimestampString: typeof isValidTimestampString;
234
- isValidDateString: typeof isValidDateString;
235
- isValidUrl: typeof isValidUrl;
236
- isValidArrayOfStrings: typeof isValidArrayOfStrings;
202
+ isImageUrl: typeof isImageUrl;
203
+ isInteger: typeof isInteger;
204
+ isValidJsonString: typeof isValidJsonString;
205
+ isValidIntegerString: typeof isValidIntegerString;
206
+ isValidUuidString: typeof isValidUuidString;
207
+ isCcIdString: typeof isCcIdString;
208
+ isCharactersString: typeof isCharactersString;
209
+ isStreetString: typeof isStreetString;
210
+ isNameString: typeof isNameString;
211
+ isSafeSearchString: typeof isSafeSearchString;
212
+ isEmailString: typeof isEmailString;
213
+ isJwtString: typeof isJwtString;
214
+ isPasswordString: typeof isPasswordString;
215
+ isSimplePasswordString: typeof isSimplePasswordString;
216
+ isPasswordStringFailureMessage: typeof isPasswordStringFailureMessage;
217
+ isSimplePasswordStringFailureMessage: typeof isSimplePasswordStringFailureMessage;
218
+ isUsernameString: typeof isUsernameString;
219
+ isPhoneNumber: typeof isPhoneNumber;
220
+ isUrlSafeString: typeof isUrlSafeString;
221
+ isString6To24CharacterLong: typeof isString6To24CharacterLong;
222
+ isString6To16CharacterLong: typeof isString6To16CharacterLong;
223
+ isProvinceString: typeof isProvinceString;
224
+ isBoolValue: typeof isBoolValue;
225
+ isPostalCodeString: typeof isPostalCodeString;
226
+ isSafeString: typeof isSafeString;
227
+ isTextString: typeof isTextString;
228
+ isInStringArray: typeof isInStringArray;
229
+ isUserRoleRequestStatusString: typeof isUserRoleRequestStatusString;
230
+ isUserRoleRequestRoleString: typeof isUserRoleRequestRoleString;
231
+ isCountryCodeString: typeof isCountryCodeString;
232
+ isValidDomainName: typeof isValidDomainName;
233
+ isValidTimestampzString: typeof isValidTimestampzString;
234
+ isValidTimestampString: typeof isValidTimestampString;
235
+ isValidDateString: typeof isValidDateString;
236
+ isValidUrl: typeof isValidUrl;
237
+ isValidArrayOfStrings: typeof isValidArrayOfStrings;
237
238
  };
package/index.js CHANGED
@@ -4,10 +4,10 @@ const validateWhitelistProperties = require('./lib/validateWhitelistProperties')
4
4
  const validateNewUserRoleRequest = require('./lib/validateNewUserRoleRequest');
5
5
 
6
6
  module.exports = {
7
- validate,
8
- validateProperties,
9
- validateWhitelistProperties,
10
- ...validateNewUserRoleRequest,
11
- ...validate,
12
- ...validateProperties,
7
+ validate,
8
+ validateProperties,
9
+ validateWhitelistProperties,
10
+ ...validateNewUserRoleRequest,
11
+ ...validate,
12
+ ...validateProperties,
13
13
  };