piper-utils 1.1.62 → 1.1.63

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/CLAUDE.md CHANGED
@@ -1,5 +1,107 @@
1
1
  # CLAUDE.md
2
2
 
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
3
5
  ## Forbidden Cognito Operations
4
6
 
5
7
  NEVER use `UpdateUserPoolClient` or `DescribeUserPoolClient` from the AWS Cognito SDK or AWS CLI. The `UpdateUserPoolClient` API is a full replacement — any omitted property resets to its default. This has caused production outages twice (March 4 and March 17, 2026) by wiping `ExplicitAuthFlows` (removing `ALLOW_USER_SRP_AUTH`) and `ReadAttributes` from both dev and prod app clients. Cognito app client configuration must only be managed via the AWS Console (where all fields are visible) or via IaC that specifies every property.
8
+
9
+ ## Build & Test Commands
10
+
11
+ ```bash
12
+ npm test # Unit tests (BUILD_ENV=test) with NYC coverage
13
+ npm run itest # Integration tests (BUILD_ENV=development)
14
+ npm run build # Dev build via webpack -> bin/main.js
15
+ npm run build-prod # Production build (BUILD_ENV=production, minified)
16
+ ```
17
+
18
+ Run a single test file by passing `--filter`:
19
+ ```bash
20
+ npx cross-env BUILD_ENV='test' nyc jasmine JASMINE_CONFIG_PATH=jasmine.json --filter="**/accessRightsUtils.test*"
21
+ ```
22
+
23
+ Tests use **Jasmine 5** with **NYC** coverage. Coverage thresholds: branches ≥ 70%, functions ≥ 70%, statements ≥ 85%, lines ≥ 80%. Test files live next to their source files as `*.test.js`.
24
+
25
+ ## Architecture
26
+
27
+ This is a shared utility library (`piper-utils`) consumed by AWS Lambda microservices via npm. It is built with Babel (targeting Node 22) and bundled with webpack into `bin/main.js` (CommonJS output).
28
+
29
+ ### Source Layout (`src/`)
30
+
31
+ - **`index.js`** — Single barrel export file. Every public function is re-exported here. Internal modules (S3Utils, SNSUtils, dynamoUtils) are NOT exported.
32
+ - **`requestResponse/`** — API Gateway Lambda proxy response formatting (`success`, `failure`, `successHtml`, `parseBody`, `parseEvent`, `getCurrentUser`). Includes security headers (HSTS, CSP, etc.) and auto-detection of Joi/Sequelize/Dynamoose errors in `failure()`.
33
+ - **`database/dbUtils/queryStringUtils/`** — Core query DSL translating API query strings into Sequelize queries:
34
+ - `defaultFilters.js` — Maps Sequelize column types to operators (iLike for strings, Op.between for dates, etc.)
35
+ - `createFilters.js` — Builds WHERE clauses with automatic business ID scoping, active-record filtering, date ranges, and full-text search
36
+ - `createSort.js` — Converts `sort` query param to ORDER BY arrays
37
+ - `createIncludes.js` — Auto-detects relation includes from dot-notation in filters/sort
38
+ - `findAll.js` — Paginated findAll (fetches limit+1 to detect `hasMore`)
39
+ - `accessRightsUtils.js` — All auth/access control functions (accessRightsUtils, checkWriteAccess, checkModule, checkIsSuper, isSuperUser, isSystemUser, partner functions, getCompanySettings). Reads JWT claims from `event.requestContext.authorizer.claims`.
40
+ - **`database/dbSetUp/migrations.js`** — Umzug-based migration runner with auto-rollback on failure.
41
+ - **`eventManager/`** — S3 file processing pipeline: `watchBucket` routes events (SNS/S3/cron) → `publishEvents` scans S3 and publishes file batches to SNS → `handleEvents` processes files in parallel via `handleFile`. Failed files move through `failed-once/` → `failed-twice/` → `error/` retry folders.
42
+ - **`s3/S3Utils/`**, **`sns/SNSUtils.js`**, **`dynamo/dynamoUtils.js`** — Internal AWS SDK v3 wrappers (not publicly exported).
43
+
44
+ ### Key Design Patterns
45
+
46
+ - **`BUILD_ENV` gating**: Auth checks are relaxed when `BUILD_ENV=local` (injects default business ID `'1'` with admin access). Tests use `BUILD_ENV=test`.
47
+ - **Synchronous access control**: All access control functions are synchronous (read JWT claims from the event). The `enrichEventWithPartnerAccess` function mutates the event in-memory before calling sync auth functions — this avoids making the entire auth stack async.
48
+ - **Error convention**: Errors are plain objects with `{ statusCode, errorCode, message }`. Built-in error codes are in `requestResponse/errorCodes.js`. The `failure()` function auto-detects error types (Joi, Sequelize, etc.) and formats them.
49
+
50
+ ## CI
51
+
52
+ Bitbucket Pipelines runs `npm test` on the `master` branch using a Node 22 image (`kevinlbatchelor/flow-22`).
53
+
54
+ ## Peer Dependencies
55
+
56
+ Consuming projects must provide: `bluebird` (≥3.7.0), `dayjs` (^1.11.13), `lodash` (≥4.17.15), `sequelize` (≥6.6.2), `umzug` (≥3.2.1).
57
+
58
+ ## Testing Guidelines
59
+
60
+ ### Spy rules — only mock external boundaries
61
+
62
+ **DO spy on:** database model methods (`Model.findOne`, `Model.create`, `Model.findAll`, `Model.update`, `Model.destroy`), HTTP calls (`axios.get/post/put`), AWS SDK clients (S3, SNS), and external services.
63
+
64
+ **DO NOT spy on** auth/access functions (`checkModule`, `checkWriteAccess`, `accessRightsUtils`, `getCurrentUser`, `parseBody`, `createFilters`, `createSort`). Instead, build a proper mock event with `requestContext.authorizer.claims['custom:AR']`:
65
+
66
+ ```javascript
67
+ const mockEvent = {
68
+ body: { /* ... */ },
69
+ pathParameters: { id: 1 },
70
+ queryStringParameters: { businessId: 'ABC' },
71
+ requestContext: {
72
+ authorizer: {
73
+ claims: {
74
+ 'custom:AR': JSON.stringify({
75
+ businessIds: { 'ABC': 'A' },
76
+ module: { payment: { read: true, write: true } }
77
+ })
78
+ }
79
+ }
80
+ },
81
+ headers: { Authorization: 'Bearer mock-jwt-token' }
82
+ };
83
+ ```
84
+
85
+ ### Test structure rules
86
+
87
+ - **No `beforeEach`** — define all spies and setup inline within each `it()` block so tests are self-contained
88
+ - **Inline spies per test** — each test creates its own spies, not shared across tests
89
+ - Use `jasmine.createSpy()` for standalone function spies, `spyOn(obj, 'method')` for existing objects
90
+ - Verify spy calls with `toHaveBeenCalledWith()` for important arguments
91
+
92
+ ### Spy patterns
93
+
94
+ ```javascript
95
+ // Success
96
+ spyOn(Model, 'findOne').and.returnValue(Promise.resolve(mockData));
97
+ // Failure
98
+ spyOn(Model, 'findOne').and.returnValue(Promise.reject(new Error('DB Error')));
99
+ // Null/empty
100
+ spyOn(Model, 'findOne').and.returnValue(Promise.resolve(null));
101
+ ```
102
+
103
+ ## Code Style
104
+
105
+ - 4-space indentation, single quotes, trailing semicolons, no trailing commas
106
+ - No `lodash.get` — use optional chaining instead
107
+ - No nested ternaries — use if/else