@carecard/validate 3.18.0 → 3.20.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/.agents/skills/carecard-workspace-standards/SKILL.md +49 -20
- package/.agents/skills/github-pr-create-update/SKILL.md +22 -1
- package/.agents/skills/github-pr-merge-cleanup/SKILL.md +22 -1
- package/.agents/skills/logged-in-user-profile-page/SKILL.md +22 -1
- package/.agents/skills/pkg-publish/SKILL.md +22 -1
- package/.agents/skills/pkg-validate-coding-standards-and-best-practices/SKILL.md +47 -9
- package/.agents/skills/pkg-validate-validation-library/SKILL.md +45 -14
- package/.agents/skills/software-design-patterns-and-clean-code/SKILL.md +23 -3
- package/.codex/AGENTS.md +41 -10
- package/.github/workflows/auto-draft-pr.yml +173 -151
- package/.github/workflows/ci.yml +35 -32
- package/.husky/pre-commit +4 -4
- package/.prettierrc.js +10 -9
- package/AGENTS.md +19 -0
- package/eslint.config.mjs +60 -8
- package/index.d.ts +108 -107
- package/index.js +6 -6
- package/lib/validate.js +262 -158
- package/lib/validateNewUserRoleRequest.js +86 -60
- package/lib/validateProperties.js +326 -326
- package/lib/validateWhitelistProperties.js +182 -142
- package/lint-staged.config.mjs +36 -0
- package/package.json +66 -60
- package/readme.md +22 -1
- package/scripts/canonicalTestCommand.test.mjs +32 -0
- package/scripts/packageTaskRunner.audit.mjs +37 -0
- package/scripts/packageTaskRunner.test.mjs +50 -72
- package/scripts/runPackageTask.mjs +103 -58
- package/scripts/testOrder/randomizeTestOrder.cjs +35 -25
- package/scripts/testOrder/randomizeTestOrder.test.mjs +19 -19
- package/scripts/testOrder/testOrderPolicy.audit.mjs +54 -0
- package/scripts/testParallel/parallelTestPolicy.audit.mjs +63 -0
- package/scripts/testParallel/runIndexedMochaTests.cjs +45 -43
- package/scripts/testParallel/runIndexedMochaTests.test.mjs +13 -7
- package/scripts/testOrder/testOrderPolicy.test.mjs +0 -48
- package/scripts/testParallel/parallelTestPolicy.test.mjs +0 -43
|
@@ -1,87 +1,113 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const {
|
|
4
|
-
|
|
4
|
+
error: { throwBadInputError },
|
|
5
5
|
} = require('@carecard/common-util');
|
|
6
6
|
const { isUserRoleRequestRoleString } = require('./validate');
|
|
7
7
|
|
|
8
8
|
const DEFAULT_USER_ROLE_REQUEST_ROLE = 'student';
|
|
9
9
|
const REQUIRE_SCOPE_WHEN_ROLE_OR_SCOPE_PRESENT = 'whenRoleOrScopePresent';
|
|
10
10
|
|
|
11
|
+
// Pattern: Boundary Normalizer - returns canonical persisted fields for supported caller shapes.
|
|
11
12
|
function validateNewUserRoleRequestObject(roleRequest = {}, options = {}) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
13
|
+
const normalized = normalizeNewUserRoleRequestObject(roleRequest);
|
|
14
|
+
const { defaultRole, requireScope } = readNewUserRoleRequestOptions(options);
|
|
15
|
+
|
|
16
|
+
if (normalized.role_name === undefined && defaultRole !== undefined) {
|
|
17
|
+
normalized.role_name = defaultRole;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
normalizeNewUserRoleRequestRole(normalized);
|
|
21
|
+
|
|
22
|
+
if (shouldRequireScope(normalized, requireScope)) {
|
|
23
|
+
requireNewUserRoleRequestScope(normalized);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return normalized;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Pattern: Options Object - supplies stable defaults for untyped JavaScript callers.
|
|
30
|
+
function readNewUserRoleRequestOptions(options) {
|
|
31
|
+
const validatedOptions = options && typeof options === 'object' ? options : {};
|
|
32
|
+
return {
|
|
33
|
+
defaultRole: Object.hasOwn(validatedOptions, 'defaultRole')
|
|
34
|
+
? validatedOptions.defaultRole
|
|
35
|
+
: DEFAULT_USER_ROLE_REQUEST_ROLE,
|
|
36
|
+
requireScope: Object.hasOwn(validatedOptions, 'requireScope')
|
|
37
|
+
? validatedOptions.requireScope
|
|
38
|
+
: true,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Pattern: Canonicalization - validates and normalizes the persisted role enum in one boundary.
|
|
43
|
+
function normalizeNewUserRoleRequestRole(roleRequest) {
|
|
44
|
+
if (roleRequest.role_name === undefined) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (!isUserRoleRequestRoleString(roleRequest.role_name)) {
|
|
48
|
+
throwBadInputError({
|
|
49
|
+
userMessage: 'Invalid property: role.role',
|
|
50
|
+
details: { role: 'Role requests are limited to student, intern, or volunteer' },
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
roleRequest.role_name = roleRequest.role_name.trim().toLowerCase();
|
|
32
54
|
}
|
|
33
55
|
|
|
34
56
|
function normalizeNewUserRoleRequestObject(roleRequest) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
57
|
+
const normalized = { ...roleRequest };
|
|
58
|
+
|
|
59
|
+
assignAlias(normalized, 'role_name', 'roleName');
|
|
60
|
+
assignAlias(normalized, 'role_name', 'role');
|
|
61
|
+
assignAlias(normalized, 'institution_id', 'institutionId');
|
|
62
|
+
assignAlias(normalized, 'campus_id', 'campusId');
|
|
63
|
+
assignAlias(normalized, 'program_id', 'programId');
|
|
64
|
+
assignAlias(normalized, 'program_term_id', 'programTermId');
|
|
65
|
+
|
|
66
|
+
delete normalized.roleName;
|
|
67
|
+
delete normalized.role;
|
|
68
|
+
delete normalized.institutionId;
|
|
69
|
+
delete normalized.campusId;
|
|
70
|
+
delete normalized.programId;
|
|
71
|
+
delete normalized.programTermId;
|
|
72
|
+
|
|
73
|
+
return normalized;
|
|
52
74
|
}
|
|
53
75
|
|
|
54
76
|
function assignAlias(target, canonicalKey, aliasKey) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
77
|
+
if (target[canonicalKey] === undefined && target[aliasKey] !== undefined) {
|
|
78
|
+
target[canonicalKey] = target[aliasKey];
|
|
79
|
+
}
|
|
58
80
|
}
|
|
59
81
|
|
|
60
82
|
function shouldRequireScope(roleRequest, requireScope) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
83
|
+
if (requireScope === true) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
if (requireScope !== REQUIRE_SCOPE_WHEN_ROLE_OR_SCOPE_PRESENT) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
roleRequest.role_name !== undefined ||
|
|
92
|
+
roleRequest.institution_id !== undefined ||
|
|
93
|
+
roleRequest.campus_id !== undefined ||
|
|
94
|
+
roleRequest.program_id !== undefined ||
|
|
95
|
+
roleRequest.program_term_id !== undefined
|
|
96
|
+
);
|
|
71
97
|
}
|
|
72
98
|
|
|
73
99
|
function requireNewUserRoleRequestScope(roleRequest) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
100
|
+
if (!roleRequest.institution_id) {
|
|
101
|
+
throwBadInputError({ userMessage: 'Missing property: role.institutionId' });
|
|
102
|
+
}
|
|
77
103
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
104
|
+
if (!roleRequest.campus_id) {
|
|
105
|
+
throwBadInputError({ userMessage: 'Missing property: role.campusId' });
|
|
106
|
+
}
|
|
81
107
|
}
|
|
82
108
|
|
|
83
109
|
module.exports = {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
110
|
+
DEFAULT_USER_ROLE_REQUEST_ROLE,
|
|
111
|
+
REQUIRE_SCOPE_WHEN_ROLE_OR_SCOPE_PRESENT,
|
|
112
|
+
validateNewUserRoleRequestObject,
|
|
87
113
|
};
|