@carecard/validate 3.9.0 → 3.11.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.
@@ -7,6 +7,10 @@ description: 'Follow the shared SO_CareCardCa/CareCard workspace coding, testing
7
7
 
8
8
  Non-negotiable TDD rule: Always write the failing test first, run it to confirm it fails for the intended reason, then implement the code and rerun the test until it passes. Test Driven Development is required for all coding work and must not be skipped. For documentation- or skill-only edits, add or update the relevant validation check before changing the prose.
9
9
 
10
+ Non-negotiable repository isolation rule: Every repository must run its Husky hooks and tests using only files, code, fixtures, dependencies, and services contained within that repository. Tests and Husky scripts must not import, require, read, execute, or otherwise depend on sibling repositories or paths outside the repository root. app-e2e-tests is the only exception because cross-repository end-to-end testing is its explicit responsibility.
11
+
12
+ Non-negotiable error and warning rule: Never suppress, silence, hide, downgrade, filter, ignore, skip, or bypass errors or warnings from code, tests, tools, compilers, linters, or validation. Fix the root cause, then rerun the affected check and require a clean result. Expected error-path tests may assert errors, but must not conceal unexpected failures.
13
+
10
14
  Non-negotiable code organization rule: Functions with the same or equivalent behavior must use the same or clearly corresponding descriptive names across CareCard repositories, and equivalent functionality must live in files with the same names within each repository's established architecture. No backward compatibility names, aliases, or duplicate locations are allowed.
11
15
 
12
16
  ## Purpose
@@ -83,7 +87,7 @@ config.
83
87
  - Never suppress errors, TypeScript errors, linter warnings, authorization
84
88
  failures, RLS failures, build failures, hydration issues, or failing tests.
85
89
  Do not add `eslint-disable`, `@ts-ignore`, broad catches, empty catches, or
86
- similar suppression unless explicitly requested.
90
+ similar suppression. Fix the root cause.
87
91
  - Do not add dependencies unless clearly necessary. If one might be needed, ask
88
92
  first with the reason, tradeoff, and why existing code cannot solve it.
89
93
  - Before finalizing repository work, run the affected repository's relevant
@@ -212,8 +216,8 @@ build artifacts, logs, or `.DS_Store`.
212
216
 
213
217
  Most JavaScript `ms-*` services use CommonJS, Mocha, Supertest, Docker Compose
214
218
  database tests, `@carecard/*` packages, and `sub-apps`
215
- controller/router/model patterns. TypeScript services such as `ms-contact-us`
216
- and `ms-template-ts` use Jest or TypeScript tooling and should keep their
219
+ controller/router/model patterns. TypeScript services such as `ms-messages`
220
+ use Jest or TypeScript tooling and should keep their
217
221
  existing TypeScript style.
218
222
 
219
223
  - Keep environment-specific files explicit: `.env.development`, `.env.test`,
@@ -311,7 +315,7 @@ existing TypeScript style.
311
315
 
312
316
  `app-dashboard` is a Next.js App Router TypeScript app using MUI, React Query,
313
317
  `next-intl`, and shared CareCard utilities. It consumes `ms-auth`,
314
- `ms-institutions`, `ms-contact-us`, and `ms-user-profiles` through service
318
+ `ms-institutions`, `ms-messages`, and `ms-user-profiles` through service
315
319
  modules.
316
320
 
317
321
  - Keep backend URL definitions centralized in `src/services/api.routes.ts`.
@@ -378,7 +382,7 @@ the authenticated dashboard.
378
382
 
379
383
  ## Auth Service RLS Contract
380
384
 
381
- - `ms-auth` follows the shared PostgreSQL/RLS pattern from `ms-template-js`: auth tables live in the `carecard` schema, RLS is enabled and forced on every auth table, and application runtime queries use the unprivileged database role.
385
+ - `ms-auth` follows the shared PostgreSQL/RLS pattern: auth tables live in the `carecard` schema, RLS is enabled and forced on every auth table, and application runtime queries use the unprivileged database role.
382
386
  - Auth table policies allow normal JWT users to access only self-owned rows. Do not add redundant `user_id = <jwt sub>` SQL predicates to duplicate self-row checks when RLS owns the authorization decision.
383
387
  - A JWT payload containing `roles: ["ad"]` is the auth-service super-admin signal and can perform any action on auth tables. Dashboard code may map that role to `super_admin`, but backend auth RLS must not require a separate database role row for that bypass.
384
388
  - Public auth flows such as registration, login, confirmation, recovery, visitor creation, and service user lookup must use narrow system contexts (`system_create`, `system_login`, `system_confirm`, `system_recovery`, `system_visitor`, `system_service`) instead of privileged runtime queries.
@@ -7,6 +7,10 @@ description: 'Use only when the user explicitly asks for remote Git or GitHub PR
7
7
 
8
8
  Non-negotiable TDD rule: Always write the failing test first, run it to confirm it fails for the intended reason, then implement the code and rerun the test until it passes. Test Driven Development is required for all coding work and must not be skipped. For documentation- or skill-only edits, add or update the relevant validation check before changing the prose.
9
9
 
10
+ Non-negotiable repository isolation rule: Every repository must run its Husky hooks and tests using only files, code, fixtures, dependencies, and services contained within that repository. Tests and Husky scripts must not import, require, read, execute, or otherwise depend on sibling repositories or paths outside the repository root. app-e2e-tests is the only exception because cross-repository end-to-end testing is its explicit responsibility.
11
+
12
+ Non-negotiable error and warning rule: Never suppress, silence, hide, downgrade, filter, ignore, skip, or bypass errors or warnings from code, tests, tools, compilers, linters, or validation. Fix the root cause, then rerun the affected check and require a clean result. Expected error-path tests may assert errors, but must not conceal unexpected failures.
13
+
10
14
  Non-negotiable code organization rule: Functions with the same or equivalent behavior must use the same or clearly corresponding descriptive names across CareCard repositories, and equivalent functionality must live in files with the same names within each repository's established architecture. No backward compatibility names, aliases, or duplicate locations are allowed.
11
15
 
12
16
  ## Purpose
@@ -75,14 +79,20 @@ Do not continue automatically when:
75
79
  when `origin/development` is absent:
76
80
 
77
81
  ```sh
78
- if git ls-remote --exit-code --heads origin development >/dev/null 2>&1; then
79
- base="development"
80
- elif git ls-remote --exit-code --heads origin main >/dev/null 2>&1; then
81
- base="main"
82
- else
83
- echo "No origin/development or origin/main branch exists."
84
- exit 1
82
+ remote_base_refs="$(git ls-remote --heads origin development main)"
83
+ remote_query_status=$?
84
+ if [ "$remote_query_status" -ne 0 ]; then
85
+ printf 'Unable to inspect origin base branches (exit %s).\n' "$remote_query_status" >&2
86
+ exit "$remote_query_status"
85
87
  fi
88
+ case "$remote_base_refs" in
89
+ *"refs/heads/development") base="development" ;;
90
+ *"refs/heads/main") base="main" ;;
91
+ *)
92
+ printf '%s\n' "No origin/development or origin/main branch exists." >&2
93
+ exit 1
94
+ ;;
95
+ esac
86
96
  git fetch origin "$base" --prune
87
97
  ```
88
98
 
@@ -7,6 +7,10 @@ description: 'Use only when the user explicitly asks for remote Git or GitHub PR
7
7
 
8
8
  Non-negotiable TDD rule: Always write the failing test first, run it to confirm it fails for the intended reason, then implement the code and rerun the test until it passes. Test Driven Development is required for all coding work and must not be skipped. For documentation- or skill-only edits, add or update the relevant validation check before changing the prose.
9
9
 
10
+ Non-negotiable repository isolation rule: Every repository must run its Husky hooks and tests using only files, code, fixtures, dependencies, and services contained within that repository. Tests and Husky scripts must not import, require, read, execute, or otherwise depend on sibling repositories or paths outside the repository root. app-e2e-tests is the only exception because cross-repository end-to-end testing is its explicit responsibility.
11
+
12
+ Non-negotiable error and warning rule: Never suppress, silence, hide, downgrade, filter, ignore, skip, or bypass errors or warnings from code, tests, tools, compilers, linters, or validation. Fix the root cause, then rerun the affected check and require a clean result. Expected error-path tests may assert errors, but must not conceal unexpected failures.
13
+
10
14
  Non-negotiable code organization rule: Functions with the same or equivalent behavior must use the same or clearly corresponding descriptive names across CareCard repositories, and equivalent functionality must live in files with the same names within each repository's established architecture. No backward compatibility names, aliases, or duplicate locations are allowed.
11
15
 
12
16
  ## Purpose
@@ -72,14 +76,20 @@ completion.
72
76
 
73
77
  ```sh
74
78
  gh auth status
75
- if git ls-remote --exit-code --heads origin development >/dev/null 2>&1; then
76
- base="development"
77
- elif git ls-remote --exit-code --heads origin main >/dev/null 2>&1; then
78
- base="main"
79
- else
80
- echo "No origin/development or origin/main branch exists."
81
- exit 1
79
+ remote_base_refs="$(git ls-remote --heads origin development main)"
80
+ remote_query_status=$?
81
+ if [ "$remote_query_status" -ne 0 ]; then
82
+ printf 'Unable to inspect origin base branches (exit %s).\n' "$remote_query_status" >&2
83
+ exit "$remote_query_status"
82
84
  fi
85
+ case "$remote_base_refs" in
86
+ *"refs/heads/development") base="development" ;;
87
+ *"refs/heads/main") base="main" ;;
88
+ *)
89
+ printf '%s\n' "No origin/development or origin/main branch exists." >&2
90
+ exit 1
91
+ ;;
92
+ esac
83
93
  target_branch="$(git branch --show-current)"
84
94
  test -n "$target_branch"
85
95
  test "$target_branch" != "$base"
@@ -169,7 +179,19 @@ completion.
169
179
  not protected:
170
180
 
171
181
  ```sh
172
- protected="$(gh api "repos/{owner}/{repo}/branches/$target_branch" --jq '.protected' 2>/dev/null || echo false)"
182
+ protected="$(gh api "repos/{owner}/{repo}/branches/$target_branch" --jq '.protected')"
183
+ protection_query_status=$?
184
+ if [ "$protection_query_status" -ne 0 ]; then
185
+ printf 'Unable to inspect branch protection (exit %s).\n' "$protection_query_status" >&2
186
+ exit "$protection_query_status"
187
+ fi
188
+ case "$protected" in
189
+ true|false) ;;
190
+ *)
191
+ printf 'Unexpected branch protection value: %s\n' "$protected" >&2
192
+ exit 1
193
+ ;;
194
+ esac
173
195
  if [ "$protected" = true ]; then
174
196
  gh pr merge "$pr_number" --squash --admin
175
197
  else
@@ -181,8 +203,16 @@ completion.
181
203
  delete it explicitly:
182
204
 
183
205
  ```sh
184
- if [ "$protected" != true ] && git ls-remote --exit-code --heads origin "$target_branch" >/dev/null 2>&1; then
185
- git push origin --delete "$target_branch"
206
+ if [ "$protected" != true ]; then
207
+ remote_target_ref="$(git ls-remote --heads origin "$target_branch")"
208
+ remote_query_status=$?
209
+ if [ "$remote_query_status" -ne 0 ]; then
210
+ printf 'Unable to inspect the remote target branch (exit %s).\n' "$remote_query_status" >&2
211
+ exit "$remote_query_status"
212
+ fi
213
+ if [ -n "$remote_target_ref" ]; then
214
+ git push origin --delete "$target_branch"
215
+ fi
186
216
  fi
187
217
  ```
188
218
 
@@ -7,6 +7,10 @@ description: 'Use when changing shared validation behavior for app-dashboard log
7
7
 
8
8
  Non-negotiable TDD rule: Always write the failing test first, run it to confirm it fails for the intended reason, then implement the code and rerun the test until it passes. Test Driven Development is required for all coding work and must not be skipped. For documentation- or skill-only edits, add or update the relevant validation check before changing the prose.
9
9
 
10
+ Non-negotiable repository isolation rule: Every repository must run its Husky hooks and tests using only files, code, fixtures, dependencies, and services contained within that repository. Tests and Husky scripts must not import, require, read, execute, or otherwise depend on sibling repositories or paths outside the repository root. app-e2e-tests is the only exception because cross-repository end-to-end testing is its explicit responsibility.
11
+
12
+ Non-negotiable error and warning rule: Never suppress, silence, hide, downgrade, filter, ignore, skip, or bypass errors or warnings from code, tests, tools, compilers, linters, or validation. Fix the root cause, then rerun the affected check and require a clean result. Expected error-path tests may assert errors, but must not conceal unexpected failures.
13
+
10
14
  Non-negotiable code organization rule: Functions with the same or equivalent behavior must use the same or clearly corresponding descriptive names across CareCard repositories, and equivalent functionality must live in files with the same names within each repository's established architecture. No backward compatibility names, aliases, or duplicate locations are allowed.
11
15
 
12
16
  ## Scope
@@ -7,6 +7,10 @@ description: 'Use when any pkg-* repository has non-Markdown package changes, in
7
7
 
8
8
  Non-negotiable TDD rule: Always write the failing test first, run it to confirm it fails for the intended reason, then implement the code and rerun the test until it passes. Test Driven Development is required for all coding work and must not be skipped. For documentation- or skill-only edits, add or update the relevant validation check before changing the prose.
9
9
 
10
+ Non-negotiable repository isolation rule: Every repository must run its Husky hooks and tests using only files, code, fixtures, dependencies, and services contained within that repository. Tests and Husky scripts must not import, require, read, execute, or otherwise depend on sibling repositories or paths outside the repository root. app-e2e-tests is the only exception because cross-repository end-to-end testing is its explicit responsibility.
11
+
12
+ Non-negotiable error and warning rule: Never suppress, silence, hide, downgrade, filter, ignore, skip, or bypass errors or warnings from code, tests, tools, compilers, linters, or validation. Fix the root cause, then rerun the affected check and require a clean result. Expected error-path tests may assert errors, but must not conceal unexpected failures.
13
+
10
14
  Non-negotiable code organization rule: Functions with the same or equivalent behavior must use the same or clearly corresponding descriptive names across CareCard repositories, and equivalent functionality must live in files with the same names within each repository's established architecture. No backward compatibility names, aliases, or duplicate locations are allowed.
11
15
 
12
16
  ## Trigger
@@ -7,6 +7,10 @@ description: 'Use when changing pkg-validate validators, sanitizers, whitelist b
7
7
 
8
8
  Non-negotiable TDD rule: Always write the failing test first, run it to confirm it fails for the intended reason, then implement the code and rerun the test until it passes. Test Driven Development is required for all coding work and must not be skipped. For documentation- or skill-only edits, add or update the relevant validation check before changing the prose.
9
9
 
10
+ Non-negotiable repository isolation rule: Every repository must run its Husky hooks and tests using only files, code, fixtures, dependencies, and services contained within that repository. Tests and Husky scripts must not import, require, read, execute, or otherwise depend on sibling repositories or paths outside the repository root. app-e2e-tests is the only exception because cross-repository end-to-end testing is its explicit responsibility.
11
+
12
+ Non-negotiable error and warning rule: Never suppress, silence, hide, downgrade, filter, ignore, skip, or bypass errors or warnings from code, tests, tools, compilers, linters, or validation. Fix the root cause, then rerun the affected check and require a clean result. Expected error-path tests may assert errors, but must not conceal unexpected failures.
13
+
10
14
  Non-negotiable code organization rule: Functions with the same or equivalent behavior must use the same or clearly corresponding descriptive names across CareCard repositories, and equivalent functionality must live in files with the same names within each repository's established architecture. No backward compatibility names, aliases, or duplicate locations are allowed.
11
15
 
12
16
  ## Purpose
@@ -7,6 +7,10 @@ description: 'Use every time before coding, refactoring, debugging, or reviewing
7
7
 
8
8
  Non-negotiable TDD rule: Always write the failing test first, run it to confirm it fails for the intended reason, then implement the code and rerun the test until it passes. Test Driven Development is required for all coding work and must not be skipped. For documentation- or skill-only edits, add or update the relevant validation check before changing the prose.
9
9
 
10
+ Non-negotiable repository isolation rule: Every repository must run its Husky hooks and tests using only files, code, fixtures, dependencies, and services contained within that repository. Tests and Husky scripts must not import, require, read, execute, or otherwise depend on sibling repositories or paths outside the repository root. app-e2e-tests is the only exception because cross-repository end-to-end testing is its explicit responsibility.
11
+
12
+ Non-negotiable error and warning rule: Never suppress, silence, hide, downgrade, filter, ignore, skip, or bypass errors or warnings from code, tests, tools, compilers, linters, or validation. Fix the root cause, then rerun the affected check and require a clean result. Expected error-path tests may assert errors, but must not conceal unexpected failures.
13
+
10
14
  Non-negotiable code organization rule: Functions with the same or equivalent behavior must use the same or clearly corresponding descriptive names across CareCard repositories, and equivalent functionality must live in files with the same names within each repository's established architecture. No backward compatibility names, aliases, or duplicate locations are allowed.
11
15
 
12
16
  ## Purpose
package/.codex/AGENTS.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  Non-negotiable code organization rule: Functions with the same or equivalent behavior must use the same or clearly corresponding descriptive names across CareCard repositories, and equivalent functionality must live in files with the same names within each repository's established architecture. No backward compatibility names, aliases, or duplicate locations are allowed.
4
4
 
5
+ Non-negotiable repository isolation rule: Every repository must run its Husky hooks and tests using only files, code, fixtures, dependencies, and services contained within that repository. Tests and Husky scripts must not import, require, read, execute, or otherwise depend on sibling repositories or paths outside the repository root. app-e2e-tests is the only exception because cross-repository end-to-end testing is its explicit responsibility.
6
+
7
+ Non-negotiable error and warning rule: Never suppress, silence, hide, downgrade, filter, ignore, skip, or bypass errors or warnings from code, tests, tools, compilers, linters, or validation. Fix the root cause, then rerun the affected check and require a clean result. Expected error-path tests may assert errors, but must not conceal unexpected failures.
8
+
5
9
  These instructions apply to the `pkg-validate` repository. This file is self-contained:
6
10
  it includes the workspace-level instructions that were previously read from
7
11
  `/Users/pankajpriscilla/SO_CareCardCa/.codex/AGENTS.md`, followed by
@@ -19,7 +23,7 @@ These instructions apply to the whole workspace. The workspace is a collection o
19
23
  - **Always follow the owner's naming conventions.** Use meaningful function, variable, file, test, and type names that match the surrounding code.
20
24
  - **Always follow the existing project structure.** Put code, tests, docs, services, validation, transforms, components, and helpers where the current repository already expects them.
21
25
  - **Always use Test-Driven Development.** Write or update focused tests first, verify they fail for the missing behavior when practical, then implement the code.
22
- - **Never suppress errors, TypeScript errors, linter warnings, or failing tests.** Do not add `eslint-disable`, `@ts-ignore`, broad catches, empty catches, or other suppression unless the user explicitly requests it. Handle the issue properly.
26
+ - **Never suppress errors, TypeScript errors, linter warnings, or failing tests.** Do not add `eslint-disable`, `@ts-ignore`, broad catches, empty catches, or other suppression. Fix the root cause.
23
27
  - **Do not add new dependencies unless they are clearly necessary.** If a dependency might be needed, stop and ask for confirmation first, with a clear reason, tradeoff, and why existing code cannot reasonably solve it.
24
28
  - **Before finalizing any response for a repository, run every script in that repository's `.husky` directory.** Do not bypass hooks. If a `.husky` script fails, fix the underlying issue and rerun it. If it cannot run because of environment constraints, report the exact script and reason.
25
29
 
@@ -41,7 +45,7 @@ These instructions apply to the whole workspace. The workspace is a collection o
41
45
 
42
46
  ### Repo Workflow
43
47
 
44
- - Work from the specific project directory you are changing, such as `api-auth`, `api-contact-us`, `api-institutions`, `pkg-common-util`, or `app-dashboard`.
48
+ - Work from the specific project directory you are changing, such as `api-auth`, `api-messages`, `api-institutions`, `pkg-common-util`, or `app-dashboard`.
45
49
  - Check local status inside the affected project before editing. These directories are independent Git repositories.
46
50
  - Do not revert or overwrite changes you did not make.
47
51
  - Before finishing a code change, run the relevant tests and lint/format checks for the affected project.
@@ -53,7 +57,7 @@ These instructions apply to the whole workspace. The workspace is a collection o
53
57
 
54
58
  ### Backend Microservices
55
59
 
56
- The `api-*` directories are independent Express/Postgres backend services. Most JavaScript services use CommonJS, Mocha, Supertest, Docker Compose database tests, `@carecard/*` packages, and `sub-apps` controller/router/model patterns. TypeScript services such as `api-contact-us` and `api-template-ts` use Jest or TypeScript tooling and should keep their existing TS style.
60
+ The `api-*` directories are independent Express/Postgres backend services. Most JavaScript services use CommonJS, Mocha, Supertest, Docker Compose database tests, `@carecard/*` packages, and `sub-apps` controller/router/model patterns. TypeScript services such as `api-messages` and `api-template-ts` use Jest or TypeScript tooling and should keep their existing TS style.
57
61
 
58
62
  - Keep service-specific controllers thin. Controllers should read as a clear workflow: parse input, authorize, validate, call domain/model logic, build response, and pass errors to `next`.
59
63
  - Extract multiline chunks into descriptively named functions in the appropriate `controllerLib`, `commonLib`, `sub-apps/lib`, model helper, or shared `pkg-*` package.
@@ -108,7 +112,7 @@ The `pkg-*` directories are reusable CareCard packages. Shared API response, err
108
112
 
109
113
  ### Dashboard Frontend
110
114
 
111
- `app-dashboard` is a Next.js App Router TypeScript app using MUI, React Query, `next-intl`, and shared CareCard utilities. It consumes `api-auth`, `api-institutions`, `api-contact-us`, and `api-user-profiles` through service modules.
115
+ `app-dashboard` is a Next.js App Router TypeScript app using MUI, React Query, `next-intl`, and shared CareCard utilities. It consumes `api-auth`, `api-institutions`, `api-messages`, and `api-user-profiles` through service modules.
112
116
 
113
117
  - Keep backend URL definitions centralized in `src/services/api.routes.ts`.
114
118
  - Keep fetch behavior centralized in `src/services/common/api`, especially `appFetch`, `api.client`, and `parseApiResponse`.
@@ -102,7 +102,7 @@ jobs:
102
102
  --head "$HEAD" \
103
103
  --base "$BASE" \
104
104
  --json number \
105
- --jq '.[0].number' || true)
105
+ --jq '.[0].number')
106
106
 
107
107
  if [[ -n "${EXISTING:-}" ]]; then
108
108
  echo "An open PR already exists for $HEAD -> $BASE (#$EXISTING). Updating PR metadata."
@@ -165,7 +165,7 @@ jobs:
165
165
  exit 0
166
166
  fi
167
167
 
168
- if ! gh issue view "$TICKET_NUMBER" --repo "$REPO" --json number >/dev/null 2>&1; then
168
+ if ! gh issue view "$TICKET_NUMBER" --repo "$REPO" --json number; then
169
169
  echo "GitHub issue #$TICKET_NUMBER was not found. Skipping ticket assignment."
170
170
  exit 0
171
171
  fi
@@ -1,57 +1,35 @@
1
- name: CI
1
+ name: CI_Tests
2
2
 
3
3
  on:
4
4
  push:
5
5
  branches:
6
- - main
7
- - develop
8
6
  - development
9
- - dev*
10
- - feature/**
11
- - feat/**
12
- - improvement/**
13
- - releases/**
14
- - release*
15
- - hotfix/**
16
- - iss/**
17
- - fix/**
18
- - data**
19
- - data/**
20
- paths-ignore:
21
- - '**.md'
7
+ - main
22
8
  pull_request:
23
- types: [closed]
24
9
  branches:
25
- - main
26
- - develop
27
10
  - development
28
- - dev*
29
- - feature/**
30
- - feat/**
31
- - improvement/**
32
- - releases/**
33
- - release*
34
- - hotfix/**
35
- - iss/**
36
- - fix/**
37
- - data**
38
- - data/**
11
+ - main
12
+ types:
13
+ - opened
14
+ - reopened
15
+ - synchronize
16
+ - ready_for_review
39
17
  paths-ignore:
40
18
  - '**.md'
41
19
 
42
20
  jobs:
43
21
  test:
44
- if: github.event_name == 'push' || github.event.pull_request.merged == true
22
+ name: CI_Tests
45
23
  runs-on: ubuntu-latest
46
24
 
47
25
  steps:
48
26
  - name: Checkout repository
49
- uses: actions/checkout@v5
27
+ uses: actions/checkout@v7
50
28
 
51
29
  - name: Set up Node.js
52
- uses: actions/setup-node@v4
30
+ uses: actions/setup-node@v6
53
31
  with:
54
- node-version: '25'
32
+ node-version: 24.18.0
55
33
  cache: 'npm'
56
34
 
57
35
  - name: Install dependencies
@@ -45,7 +45,8 @@ jobs:
45
45
  echo "package_name=${package_name}" >> "$GITHUB_OUTPUT"
46
46
  echo "package_version=${package_version}" >> "$GITHUB_OUTPUT"
47
47
 
48
- if npm view "${package_name}@${package_version}" version >/dev/null 2>&1; then
48
+ published_versions="$(npm view "${package_name}" versions --json)"
49
+ if node -e 'const value=JSON.parse(process.argv[1]); const versions=Array.isArray(value) ? value : [value]; process.exit(versions.includes(process.argv[2]) ? 0 : 1);' "$published_versions" "$package_version"; then
49
50
  echo "${package_name}@${package_version} is already published."
50
51
  echo "should_publish=false" >> "$GITHUB_OUTPUT"
51
52
  else
package/.husky/pre-commit CHANGED
@@ -1,5 +1,10 @@
1
+ set -eu
2
+
3
+ repository_root="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)"
4
+ cd "$repository_root"
5
+
1
6
  npm run lint:fix
2
7
  npm run format
3
8
 
4
9
  # Run tests
5
- npm run test:All
10
+ npm run test:All
package/lib/validate.js CHANGED
@@ -15,7 +15,8 @@ const isValidJsonString = str => {
15
15
  try {
16
16
  const json = JSON.parse(str);
17
17
  return typeof json === 'object' && json !== null;
18
- } catch {
18
+ } catch (error) {
19
+ if (!(error instanceof SyntaxError)) throw error;
19
20
  return false;
20
21
  }
21
22
  };
@@ -229,12 +230,10 @@ const isValidDateString = str => {
229
230
 
230
231
  const isValidUrl = url => {
231
232
  if (typeof url !== 'string' || url.length === 0 || url.length > 2048) return false;
232
- try {
233
- const parsedUrl = new URL(url);
234
- return parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:';
235
- } catch {
236
- return false;
237
- }
233
+ if (!URL.canParse(url)) return false;
234
+
235
+ const parsedUrl = new URL(url);
236
+ return parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:';
238
237
  };
239
238
  const isValidArrayOfStrings = arr => {
240
239
  if (!Array.isArray(arr)) return false;
@@ -151,10 +151,8 @@ function validateProperties(obj = {}) {
151
151
  case 'user_id':
152
152
  case 'address_id':
153
153
  case 'addressId':
154
- case 'image_id':
155
154
  case 'itemId':
156
155
  case 'userId':
157
- case 'imageId':
158
156
  case 'order_id':
159
157
  case 'orderId':
160
158
  case 'category_id':
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@carecard/validate",
3
- "version": "3.9.0",
3
+ "version": "3.11.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/CareCard-ca/pkg-validate.git"
@@ -38,7 +38,7 @@
38
38
  "typescript": "6.0.3"
39
39
  },
40
40
  "dependencies": {
41
- "@carecard/common-util": "3.9.0"
41
+ "@carecard/common-util": "3.11.0"
42
42
  },
43
43
  "nyc": {
44
44
  "all": true,
@@ -54,6 +54,7 @@
54
54
  },
55
55
  "overrides": {
56
56
  "diff": "8.0.4",
57
+ "glob": "13.0.6",
57
58
  "serialize-javascript": "7.0.5",
58
59
  "js-yaml": "4.2.0"
59
60
  }
package/readme.md CHANGED
@@ -13,6 +13,10 @@ not pass validation.
13
13
 
14
14
  Non-negotiable TDD rule: Always write the failing test first, run it to confirm it fails for the intended reason, then implement the code and rerun the test until it passes. Test Driven Development is required for all coding work and must not be skipped. For documentation- or skill-only edits, add or update the relevant validation check before changing the prose.
15
15
 
16
+ Non-negotiable repository isolation rule: Every repository must run its Husky hooks and tests using only files, code, fixtures, dependencies, and services contained within that repository. Tests and Husky scripts must not import, require, read, execute, or otherwise depend on sibling repositories or paths outside the repository root. app-e2e-tests is the only exception because cross-repository end-to-end testing is its explicit responsibility.
17
+
18
+ Non-negotiable error and warning rule: Never suppress, silence, hide, downgrade, filter, ignore, skip, or bypass errors or warnings from code, tests, tools, compilers, linters, or validation. Fix the root cause, then rerun the affected check and require a clean result. Expected error-path tests may assert errors, but must not conceal unexpected failures.
19
+
16
20
  Non-negotiable code organization rule: Functions with the same or equivalent behavior must use the same or clearly corresponding descriptive names across CareCard repositories, and equivalent functionality must live in files with the same names within each repository's established architecture. No backward compatibility names, aliases, or duplicate locations are allowed.
17
21
 
18
22
  ## Installation
@@ -102,30 +106,30 @@ validateProperties(input);
102
106
  Keys are matched exactly. Both snake_case and camelCase variants are listed
103
107
  where the package supports both.
104
108
 
105
- | Validator | Keys |
106
- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
107
- | `isNameString` | `first_name`, `firstName`, `last_name`, `lastName`, `username`, `new_status`, `newStatus`, `description`, `comment`, `status`, `name`, `title`, `brand`, `short_description`, `shortDescription`, `college_name`, `collegeName`, `campus_name`, `campusName`, `role`, `role_id`, `roleId`, `campus`, `institution_name`, `institutionName`, `program_name`, `programName`, `role_name`, `roleName`, `document_name`, `documentName`, `document_required_for_role_name`, `documentRequiredForRoleName`, `reason`, `entity_type`, `entityType`, `action_type`, `actionType`, `city`, `state`, `country`, `type` |
108
- | `isStreetString` | `street` |
109
- | `isCharactersString` | `postal_code`, `postalCode`, `period` |
110
- | `isBoolValue` | `is_primary`, `isPrimary`, `active`, `document_optional`, `documentOptional` |
111
- | `isSafeSearchString` | `search_string`, `searchString` |
112
- | `isString6To16CharacterLong` and `isSimplePasswordString` | `password`, `new_password`, `newPassword` |
113
- | `isString6To16CharacterLong` and `isPasswordString` | `strong_password`, `strongPassword` |
114
- | `isEmailString` | `email` |
115
- | `isPhoneNumber` | `phone_number`, `phoneNumber` |
116
- | `isCountryCodeString` | `country_code`, `countryCode` |
117
- | `isUrlSafeString` | `token`, `email_confirm_token`, `emailConfirmToken`, `verification_token`, `verificationToken` |
118
- | `isValidUuidString` | `uuid`, `item_id`, `itemId`, `user_id`, `userId`, `address_id`, `addressId`, `image_id`, `imageId`, `order_id`, `orderId`, `category_id`, `categoryId`, `parent_id`, `parentId`, `college_id`, `collegeId`, `campus_id`, `campusId`, `program_id`, `programId`, `program_term_id`, `programTermId`, `template_id`, `templateId`, `program_template_id`, `programTemplateId`, `user_item_id`, `userItemId`, `user_item_status_id`, `userItemStatusId`, `requirement_item_id`, `requirementItemId`, `program_document_id`, `programDocumentId`, `id`, `institution_id`, `institutionId`, `role_assignment_id`, `roleAssignmentId`, `user_role_id`, `userRoleId`, `phone_number_id`, `phoneNumberId`, `entity_id`, `entityId`, `changed_by`, `changedBy`, `request_id`, `requestId` |
119
- | `isCcIdString` | `cc_id`, `ccId` |
120
- | `isValidIntegerString` | `offset_number`, `offsetNumber`, `number_of_orders`, `numberOfOrders`, `price`, `from`, `number`, `limit`, `offset` |
121
- | `isValidJsonString` on the raw value | `about` |
122
- | `isValidJsonString(JSON.stringify(value))` | `weight`, `dimensions`, `permission`, `scope_data`, `scopeData`, `meta_data`, `metaData`, `metadata` |
123
- | `isTextString` | `document_description`, `documentDescription`, `nick_name`, `nickName`, `requested_by_name`, `requestedByName`, `requested_by_email`, `requestedByEmail`, `requested_by_phone`, `requestedByPhone`, `approved_by_name`, `approvedByName`, `approved_by_email`, `approvedByEmail`, `approved_by_phone`, `approvedByPhone` |
124
- | `isValidArrayOfStrings` | `aliases` |
125
- | `isImageUrl` or `isValidUrl` | `image_url`, `imageUrl`, `website`, `file_url`, `fileUrl` |
126
- | `isValidDomainName` | `domain_name`, `domainName`, `domain`, `email_domain`, `emailDomain`, `email_domain_name`, `emailDomainName` |
127
- | `isValidTimestampzString` or `isValidTimestampString` | `expires_at`, `expiresAt`, `start_time`, `startTime`, `end_time`, `endTime` |
128
- | `isValidDateString` | `effective_start_date`, `effectiveStartDate`, `effective_end_date`, `effectiveEndDate`, `valid_until_date`, `validUntilDate`, `renew_date`, `renewDate` |
109
+ | Validator | Keys |
110
+ | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
111
+ | `isNameString` | `first_name`, `firstName`, `last_name`, `lastName`, `username`, `new_status`, `newStatus`, `description`, `comment`, `status`, `name`, `title`, `brand`, `short_description`, `shortDescription`, `college_name`, `collegeName`, `campus_name`, `campusName`, `role`, `role_id`, `roleId`, `campus`, `institution_name`, `institutionName`, `program_name`, `programName`, `role_name`, `roleName`, `document_name`, `documentName`, `document_required_for_role_name`, `documentRequiredForRoleName`, `reason`, `entity_type`, `entityType`, `action_type`, `actionType`, `city`, `state`, `country`, `type` |
112
+ | `isStreetString` | `street` |
113
+ | `isCharactersString` | `postal_code`, `postalCode`, `period` |
114
+ | `isBoolValue` | `is_primary`, `isPrimary`, `active`, `document_optional`, `documentOptional` |
115
+ | `isSafeSearchString` | `search_string`, `searchString` |
116
+ | `isString6To16CharacterLong` and `isSimplePasswordString` | `password`, `new_password`, `newPassword` |
117
+ | `isString6To16CharacterLong` and `isPasswordString` | `strong_password`, `strongPassword` |
118
+ | `isEmailString` | `email` |
119
+ | `isPhoneNumber` | `phone_number`, `phoneNumber` |
120
+ | `isCountryCodeString` | `country_code`, `countryCode` |
121
+ | `isUrlSafeString` | `token`, `email_confirm_token`, `emailConfirmToken`, `verification_token`, `verificationToken` |
122
+ | `isValidUuidString` | `uuid`, `item_id`, `itemId`, `user_id`, `userId`, `address_id`, `addressId`, `order_id`, `orderId`, `category_id`, `categoryId`, `parent_id`, `parentId`, `college_id`, `collegeId`, `campus_id`, `campusId`, `program_id`, `programId`, `program_term_id`, `programTermId`, `template_id`, `templateId`, `program_template_id`, `programTemplateId`, `user_item_id`, `userItemId`, `user_item_status_id`, `userItemStatusId`, `requirement_item_id`, `requirementItemId`, `program_document_id`, `programDocumentId`, `id`, `institution_id`, `institutionId`, `role_assignment_id`, `roleAssignmentId`, `user_role_id`, `userRoleId`, `phone_number_id`, `phoneNumberId`, `entity_id`, `entityId`, `changed_by`, `changedBy`, `request_id`, `requestId` |
123
+ | `isCcIdString` | `cc_id`, `ccId` |
124
+ | `isValidIntegerString` | `offset_number`, `offsetNumber`, `number_of_orders`, `numberOfOrders`, `price`, `from`, `number`, `limit`, `offset` |
125
+ | `isValidJsonString` on the raw value | `about` |
126
+ | `isValidJsonString(JSON.stringify(value))` | `weight`, `dimensions`, `permission`, `scope_data`, `scopeData`, `meta_data`, `metaData`, `metadata` |
127
+ | `isTextString` | `document_description`, `documentDescription`, `nick_name`, `nickName`, `requested_by_name`, `requestedByName`, `requested_by_email`, `requestedByEmail`, `requested_by_phone`, `requestedByPhone`, `approved_by_name`, `approvedByName`, `approved_by_email`, `approvedByEmail`, `approved_by_phone`, `approvedByPhone` |
128
+ | `isValidArrayOfStrings` | `aliases` |
129
+ | `isImageUrl` or `isValidUrl` | `image_url`, `imageUrl`, `website`, `file_url`, `fileUrl` |
130
+ | `isValidDomainName` | `domain_name`, `domainName`, `domain`, `email_domain`, `emailDomain`, `email_domain_name`, `emailDomainName` |
131
+ | `isValidTimestampzString` or `isValidTimestampString` | `expires_at`, `expiresAt`, `start_time`, `startTime`, `end_time`, `endTime` |
132
+ | `isValidDateString` | `effective_start_date`, `effectiveStartDate`, `effective_end_date`, `effectiveEndDate`, `valid_until_date`, `validUntilDate`, `renew_date`, `renewDate` |
129
133
 
130
134
  ## `validateWhitelistProperties(inputObject, requiredProperties, options)`
131
135