washday-sdk 1.6.32 → 1.6.34

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 ADDED
@@ -0,0 +1,139 @@
1
+ # CLAUDE.md - washday-sdk
2
+
3
+ ## Purpose
4
+ Guide Claude when working inside `washday-sdk`.
5
+
6
+ This repo is a **typed client abstraction layer** between frontend apps and backend.
7
+
8
+ ---
9
+
10
+ ## Ecosystem
11
+
12
+ - `washday-backend` — source of truth, business rules, API
13
+ - `washday-frontend` — main web app
14
+ - `washday-pos-v2` — React Native mobile app (iOS/Android)
15
+
16
+ Both `washday-frontend` and `washday-pos-v2` consume this SDK. Do not suggest they call the backend directly.
17
+
18
+ ---
19
+
20
+ ## Before Starting Any Task
21
+
22
+ 1. Read `docs/patterns.md` if you haven't in this session
23
+ 2. Read the relevant `src/api/<domain>/` files before proposing changes
24
+ 3. Never propose changes to code you haven't read
25
+
26
+ ---
27
+
28
+ ## Key File Locations
29
+
30
+ - `src/api/index.ts` — client aggregator, where all modules are bound
31
+ - `src/api/axiosInstance.ts` — axios config, base URLs, request interceptor
32
+ - `src/interfaces/Api.ts` — `WashdayClientInstance` type (update when adding modules)
33
+ - `src/interfaces/` — entity types (`IOrder`, `ICustomer`, `IProduct`, `IStore`, etc.)
34
+ - `src/utils/apiUtils.ts` — `generateQueryParamsStr()`
35
+ - `src/enum/index.ts` — `PaymentMethodsEnum`, `DiscountCodeTypes`
36
+
37
+ ---
38
+
39
+ ## Core Role of this Repo
40
+
41
+ - Wrap backend endpoints into typed methods
42
+ - Centralize request logic (auth, headers, errors)
43
+ - Provide a stable contract for frontend apps
44
+ - Ensure consistency across all consumers
45
+
46
+ ---
47
+
48
+ ## Core Principles
49
+
50
+ - Do NOT introduce backend business logic here
51
+ - Do NOT bypass SDK abstraction
52
+ - Backward compatibility is critical
53
+ - Keep method contracts stable and predictable
54
+ - Prefer additive changes over breaking ones
55
+
56
+ ---
57
+
58
+ ## Context Usage Rules
59
+
60
+ ### When to use backend architecture knowledge
61
+ Use backend context ONLY when:
62
+ - mapping new SDK methods to backend endpoints
63
+ - understanding request/response shapes
64
+ - handling changes in backend contracts
65
+
66
+ Do NOT:
67
+ - re-design backend logic here
68
+ - duplicate backend rules
69
+
70
+ ### When to use `docs/architecture.md`
71
+ Read it when:
72
+ - you need to understand the full system context (dependency chain, module inventory, auth model, error shape)
73
+ - you are adding a new domain or making structural changes
74
+
75
+ ### When to use `docs/patterns.md`
76
+ Read it when:
77
+ - creating new SDK methods or modules
78
+ - organizing domains or namespaces
79
+ - defining typing, error handling, or compatibility behavior
80
+ - evaluating whether a change is additive or breaking
81
+
82
+ ---
83
+
84
+ ## SDK-Specific Rules
85
+
86
+ - All frontend apps must consume backend through the SDK
87
+ - Do NOT suggest raw `fetch` or `axios` from consumer apps for endpoints already modeled in the SDK
88
+ - When backend changes → evaluate SDK impact before touching consumer apps
89
+ - Keep endpoint URL details abstracted inside SDK methods — callers never see raw paths
90
+ - Every new method follows the standard shape: `bindMethods()`, explicit `Authorization` header, `generateQueryParamsStr()` for query params, try/catch + re-throw
91
+
92
+ ---
93
+
94
+ ## Typing Policy
95
+
96
+ - Request params must always be typed explicitly
97
+ - Response types are currently `Promise<any>` — this is a known gap
98
+ - When adding new methods, add explicit response types if the shape is known
99
+ - Do not widen existing types to `any` to make things compile
100
+
101
+ ---
102
+
103
+ ## Testing
104
+
105
+ - Tests live in `test/`
106
+ - Use Jest with `.call(mockClient, ...)` to bind `this` context
107
+ - Mock `axiosInstance` methods — do not make real HTTP calls in tests
108
+ - Assert the `Authorization` header and URL construction, not just the return value
109
+
110
+ ---
111
+
112
+ ## Before Publishing
113
+
114
+ - Bump `package.json` version following semver (patch / minor / major)
115
+ - Run `npm run publishVersion` (runs `tsc` + `npm publish`)
116
+ - Breaking changes = major bump — notify consumer app teams before releasing
117
+
118
+ ---
119
+
120
+ ## Expected Response Style
121
+
122
+ - Focus on API abstraction and typing
123
+ - Keep solutions practical and consistent with existing patterns
124
+ - Avoid generic SDK theory — reference actual patterns in this codebase
125
+ - Prefer concrete examples using real module names and method shapes
126
+
127
+ ---
128
+
129
+ ## Engineering Mindset
130
+
131
+ Think like:
132
+ - API client designer
133
+ - contract maintainer
134
+ - integration layer owner
135
+
136
+ Always optimize for:
137
+ - consistency
138
+ - stability
139
+ - clarity
package/dist/api/index.js CHANGED
@@ -10,7 +10,7 @@ import { getAutomaticDiscountById, getAutomaticDiscounts, getAvailableAutomaticD
10
10
  import { createAutomaticDiscount, createDiscountCode } from "./discounts/post";
11
11
  import { deleteAutomaticDiscountById, deleteDiscountCodeById, updateAutomaticDiscountById, updateDiscountCodeById } from "./discounts/put";
12
12
  import { deleteStoreStaffById } from "./staff/delete";
13
- import { getStoreStaff, getStoreStaffById } from "./staff/get";
13
+ import { getStoreAssignableStaffs, getStoreStaff, getStoreStaffById } from "./staff/get";
14
14
  import { createStoreStaff } from "./staff/post";
15
15
  import { updateStoreStaffById, updateStoreStaffStores } from "./staff/put";
16
16
  import { getOrderSequence, getPaymentFees, getPickupScheduleCustomersApp, getStoreById, getStoreImages, getStoreReviewLink, getStores, getStoresByIdCustomersApp, getStoresByName } from "./stores/get";
@@ -264,6 +264,7 @@ const WashdayClient = function WashdayClient(apiToken, env = 'PROD', clientId, c
264
264
  });
265
265
  this.staff = bindMethods(this, {
266
266
  getStoreStaff: getStoreStaff,
267
+ getStoreAssignableStaffs: getStoreAssignableStaffs,
267
268
  getStoreStaffById: getStoreStaffById,
268
269
  updateStoreStaffById: updateStoreStaffById,
269
270
  updateStoreStaffStores: updateStoreStaffStores,
@@ -8,6 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  const GET_SET_STAFF = (storeId) => `api/store/${storeId}/staff`;
11
+ const GET_ASSIGNABLE_STAFF = (storeId) => `api/store/${storeId}/assignable-staffs`;
11
12
  export const getStoreStaff = function (storeId, queryParams) {
12
13
  return __awaiter(this, void 0, void 0, function* () {
13
14
  try {
@@ -23,6 +24,22 @@ export const getStoreStaff = function (storeId, queryParams) {
23
24
  }
24
25
  });
25
26
  };
27
+ export const getStoreAssignableStaffs = function (storeId, queryParams) {
28
+ return __awaiter(this, void 0, void 0, function* () {
29
+ try {
30
+ const config = {
31
+ headers: { Authorization: `Bearer ${this.apiToken}` }
32
+ };
33
+ const suffix = queryParams ? `?${queryParams}` : "";
34
+ const response = yield this.axiosInstance.get(`${GET_ASSIGNABLE_STAFF(storeId)}${suffix}`, config);
35
+ return response;
36
+ }
37
+ catch (error) {
38
+ console.error('Error fetching getStoreAssignableStaffs:', error);
39
+ throw error;
40
+ }
41
+ });
42
+ };
26
43
  export const getStoreStaffById = function (storeId, staffId) {
27
44
  return __awaiter(this, void 0, void 0, function* () {
28
45
  try {
@@ -0,0 +1,337 @@
1
+ # washday-sdk Architecture
2
+
3
+ ## 1. System Overview
4
+
5
+ `washday-sdk` is the typed client library that Washday frontend applications use to communicate with `washday-backend`. It is published as an npm package (ESM, TypeScript) and consumed as a dependency by any app that needs to interact with the Washday backend API.
6
+
7
+ - **Package name**: `washday-sdk`
8
+ - **Current version**: `1.6.33`
9
+ - **Module format**: ESM (`"type": "module"`)
10
+ - **Main entry**: `dist/index.js` (compiled from `src/index.ts`)
11
+ - **Primary export**: `WashdayClient` class + `utils` namespace
12
+
13
+ Known consumers:
14
+ - `washday-frontend` — main web application
15
+ - `washday-pos-v2` — React Native mobile app (iOS/Android)
16
+ - Any other Washday app that needs backend access
17
+
18
+ ---
19
+
20
+ ## 2. Role in the Architecture
21
+
22
+ ```
23
+ washday-frontend
24
+ washday-pos-v2
25
+ (other apps)
26
+
27
+
28
+ washday-sdk ← this repo
29
+
30
+
31
+ washday-backend ← source of truth for business rules, entities, payments, integrations
32
+ ```
33
+
34
+ **Ownership boundaries:**
35
+
36
+ | Layer | Owns |
37
+ |---|---|
38
+ | `washday-backend` | Business rules, entity validation, database, payments, integrations |
39
+ | `washday-sdk` | HTTP client abstraction, typed request/response methods, auth token forwarding, env routing |
40
+ | Frontend apps | UI state, rendering, user interaction, app-specific logic |
41
+
42
+ Frontend apps **do not** call `washday-backend` directly with raw `fetch` or `axios`. All backend communication goes through `washday-sdk`.
43
+
44
+ ---
45
+
46
+ ## 3. Core Responsibilities
47
+
48
+ - **Typed API methods**: Every backend endpoint has a corresponding typed method on the client. Callers get predictable parameter shapes and autocomplete.
49
+ - **Centralized auth**: Bearer token is injected into every request from a single place (`this.apiToken`). Apps initialize the client once with a token; individual method calls don't manage auth.
50
+ - **Environment routing**: The client routes requests to the correct backend URL based on the `env` constructor parameter (`DEV`, `STAGE`, `PROD`).
51
+ - **Request tracking**: Every request is stamped with a unique `x-request-id` UUID header at the axios instance level, enabling backend log correlation.
52
+ - **Request cancellation**: List endpoints accept an `AbortSignal` (via `options.signal` or `params.signal`) so consumers can cancel in-flight requests.
53
+ - **File download support**: Export endpoints override `Content-Type` and set `responseType: 'blob'` per-request for binary responses (CSV, XLSX, PDF).
54
+ - **Domain organization**: All methods are grouped into domain namespaces on the client instance (e.g., `client.orders`, `client.customers`), making the API surface discoverable.
55
+ - **Shared calculation utilities**: Complex order total/tax/discount computation logic lives in `src/utils/orders/` to avoid duplication across apps.
56
+
57
+ ---
58
+
59
+ ## 4. Boundaries / Non-Responsibilities
60
+
61
+ The SDK must **not** own:
62
+
63
+ - **Backend business rules**: Validation logic, pricing rules, status transition rules — these belong in `washday-backend`. The SDK passes data through; it does not re-implement business logic.
64
+ - **UI logic**: No rendering, no component state, no routing. The SDK is framework-agnostic.
65
+ - **Feature-specific concerns**: App-level flows (checkout wizard steps, POS screen state) are owned by the consuming app, not the SDK.
66
+ - **Duplicate validation**: If `washday-backend` validates an email format or required field, the SDK does not need to re-validate it before sending. Input validation in the SDK should be limited to preventing obviously malformed HTTP requests.
67
+ - **Session management**: The SDK does not manage token lifecycle (refresh, expiry, storage). It receives a token and uses it. The consuming app manages when to acquire or replace the token.
68
+
69
+ ---
70
+
71
+ ## 5. API Consumption Model
72
+
73
+ ### Initialization
74
+
75
+ ```typescript
76
+ import { WashdayClient } from 'washday-sdk';
77
+
78
+ const client = new WashdayClient(
79
+ apiToken, // string (required) — Bearer token
80
+ env, // string (optional, default: 'PROD') — 'DEV' | 'STAGE' | 'PROD'
81
+ clientId, // string (optional) — sent as x-client-id header
82
+ clientSecret // string (optional) — sent as x-client-secret header
83
+ );
84
+ ```
85
+
86
+ ### Base URLs by environment
87
+
88
+ | `env` value | Base URL |
89
+ |---|---|
90
+ | `DEV` | `http://localhost:5555/` |
91
+ | `STAGE` | `https://washday-backend-development.herokuapp.com/` |
92
+ | `PROD` | `https://washday-backend.herokuapp.com/` |
93
+
94
+ ### Request pipeline
95
+
96
+ 1. Consumer calls a method: `client.orders.getList({ storeId, status })`
97
+ 2. The method constructs query params using `generateQueryParamsStr()` from `src/utils/apiUtils.ts`
98
+ 3. The method sets `Authorization: Bearer <apiToken>` in the request config
99
+ 4. The request is sent through the shared `axiosInstance`
100
+ 5. The axios request interceptor applies `x-request-id`, `x-client-id`, `x-client-secret`, and overrides `responseType` or `Content-Type` when needed
101
+ 6. The response (or error) is returned to the caller
102
+
103
+ ### Auth header injection
104
+
105
+ Auth is set explicitly per method call, not as an axios default header:
106
+
107
+ ```typescript
108
+ const config = {
109
+ headers: { Authorization: `Bearer ${this.apiToken}` }
110
+ };
111
+ return await this.axiosInstance.get(`api/v2/order?${queryParams}`, config);
112
+ ```
113
+
114
+ This means every method has direct visibility into how auth is applied, at the cost of some repetition.
115
+
116
+ ### Calling the SDK
117
+
118
+ ```typescript
119
+ // List orders
120
+ const response = await client.orders.getList({ storeId: 'abc', status: 'pending' });
121
+
122
+ // Get customer
123
+ const customer = await client.customers.getCustomerById('customer-id');
124
+
125
+ // Create order
126
+ const newOrder = await client.orders.create({ ... });
127
+
128
+ // With cancellation
129
+ const controller = new AbortController();
130
+ const orders = await client.orders.getList({ storeId: 'abc' }, { signal: controller.signal });
131
+ ```
132
+
133
+ ---
134
+
135
+ ## 6. Domain Structure
136
+
137
+ The client exposes 30+ module namespaces, each mapping to a set of backend endpoints:
138
+
139
+ ### Core Business
140
+ | Namespace | Responsibility |
141
+ |---|---|
142
+ | `client.orders` | Order lifecycle: create, list, update, status transitions, payment lines |
143
+ | `client.customers` | Customer records: CRUD, bulk create |
144
+ | `client.products` | Product catalog: CRUD, pricing, bulk create |
145
+ | `client.stores` | Store configuration: CRUD, settings |
146
+ | `client.sections` | Store sections/zones: CRUD |
147
+
148
+ ### Personnel & Time
149
+ | Namespace | Responsibility |
150
+ |---|---|
151
+ | `client.attendance` | Clock-in/out, history, store reports, export |
152
+ | `client.staff` | Staff management: list, CRUD |
153
+ | `client.users` | User accounts: update, store access, PIN validation |
154
+
155
+ ### Financial & Transactions
156
+ | Namespace | Responsibility |
157
+ |---|---|
158
+ | `client.cashup` | Cash register sessions: CRUD |
159
+ | `client.cashierboxes` | Cashier box tracking: CRUD, movement history |
160
+ | `client.discountCodes` | Discount codes: list, verify, CRUD |
161
+ | `client.automaticDiscount` | Automatic discount rules |
162
+ | `client.cfdi` | Mexican tax invoices (CFDI): list, create, cancel, download |
163
+ | `client.stripe` | Stripe subscription checkout, customer portal |
164
+
165
+ ### Inventory & Supplies
166
+ | Namespace | Responsibility |
167
+ |---|---|
168
+ | `client.inventory` | Stock management: CRUD, stock additions, history |
169
+ | `client.supplies` | Supply tracking: CRUD, stock additions |
170
+
171
+ ### Reporting & Export
172
+ | Namespace | Responsibility |
173
+ |---|---|
174
+ | `client.reports` | Sales, customers, supplies, cashup, payment method statistics |
175
+ | `client.csv` | CSV exports: customers, orders, reports |
176
+ | `client.pdf` | PDF exports: unpaid orders report |
177
+
178
+ ### Logistics & Fulfillment
179
+ | Namespace | Responsibility |
180
+ |---|---|
181
+ | `client.routes` | Delivery routes: create, close, update, order assignment |
182
+ | `client.outsourcedOrders` | External fulfillment orders: CRUD |
183
+
184
+ ### Customer-Facing
185
+ | Namespace | Responsibility |
186
+ |---|---|
187
+ | `client.auth` | Login (token, email, Google, Apple, Facebook, PIN), signup, password |
188
+ | `client.publics` | Public endpoints: order receipts, POS/Hub app config (no auth required) |
189
+ | `client.reviews` | Customer reviews: list, request review |
190
+
191
+ ### Company & Platform
192
+ | Namespace | Responsibility |
193
+ |---|---|
194
+ | `client.companies` | Company settings: get, update, logo, subscription billing, tax info |
195
+ | `client.partners` | Partner accounts: CRUD |
196
+ | `client.countries` | Country reference data |
197
+ | `client.updates` | System update notifications: list, mark as seen |
198
+
199
+ ### Integrations
200
+ | Namespace | Responsibility |
201
+ |---|---|
202
+ | `client.integrations` | MercadoPago OAuth status, OAuth flow |
203
+ | `client.integrations.mercadoPago` | Terminal discovery, import, disconnect, payment attempts |
204
+
205
+ ### Source layout
206
+
207
+ Each domain follows this file structure under `src/api/<domain>/`:
208
+
209
+ ```
210
+ customers/
211
+ ├── index.ts # re-exports get/post/put/delete modules
212
+ ├── get.ts # GET endpoints
213
+ ├── post.ts # POST endpoints
214
+ ├── put.ts # PUT/PATCH endpoints
215
+ └── delete.ts # DELETE endpoints
216
+ ```
217
+
218
+ All methods are bound to the client instance in `src/api/index.ts` using a `bindMethods()` utility so they have access to `this.apiToken` and `this.axiosInstance`.
219
+
220
+ ---
221
+
222
+ ## 7. Typing Strategy
223
+
224
+ ### TypeScript configuration
225
+
226
+ - Strict mode enabled (`"strict": true` in `tsconfig.json`)
227
+ - Target: ES6, module: ESNext
228
+ - All source in `src/`, compiled to `dist/`
229
+
230
+ ### Entity interfaces
231
+
232
+ Core entity interfaces live in `src/interfaces/`:
233
+
234
+ | File | Interfaces |
235
+ |---|---|
236
+ | `Order.ts` | `IOrder`, `IOrderProduct`, `IOrderPaymentLines`, `IDeliveryInfo`, `IPickupInfo` |
237
+ | `Customer.ts` | `ICustomer`, `IAddress`, `IPaymentMethod`, `IInvoiceInfo` |
238
+ | `Product.ts` | `IProduct`, `IPriceOption`, `IProductSupplies` |
239
+ | `Store.ts` | `IStore`, `ITax`, `IPaymentConfig`, `IOrderPageConfig`, `IPrintingConfig`, `ISchedule` |
240
+ | `User.ts` | `IUser`, `IStaff` |
241
+ | `Company.ts` | `ICompany` |
242
+ | `Section.ts` | `ISection` |
243
+ | `Attendance.ts` | `IAttendance` |
244
+ | `Permission.ts` | `IPermission` |
245
+ | `Api.ts` | `WashdayClientInstance` — the full client interface with all module namespaces typed |
246
+
247
+ ### Enums
248
+
249
+ Defined in `src/enum/index.ts`:
250
+
251
+ ```typescript
252
+ enum PaymentMethodsEnum { Cash, Card, Delivery, Transfer }
253
+ enum DiscountCodeTypes { PERCENTAGE, NUMBER, FREE_DELIVERY, BUY_X_GET_Y, FREE_ITEM }
254
+ enum BuyAndGetConditionsTypes { PERCENTAGE, FREE }
255
+ ```
256
+
257
+ ### Current limitation: `Promise<any>` returns
258
+
259
+ Most endpoint methods currently return `Promise<any>`. This means callers do not get typed response shapes — only request parameters are typed. This is a known gap. When adding new methods or updating existing ones, prefer adding explicit response types.
260
+
261
+ ---
262
+
263
+ ## 8. Error Handling Strategy
264
+
265
+ ### Pattern in every endpoint
266
+
267
+ All methods wrap the axios call in try/catch and re-throw:
268
+
269
+ ```typescript
270
+ try {
271
+ const config = { headers: { Authorization: `Bearer ${this.apiToken}` } };
272
+ return await this.axiosInstance.get(`api/some/endpoint`, config);
273
+ } catch (error) {
274
+ console.error('Washday SDK - Error description:', error);
275
+ throw error;
276
+ }
277
+ ```
278
+
279
+ The SDK logs to `console.error` and re-throws. It does not swallow errors or transform them into custom error classes.
280
+
281
+ ### Abort/cancel handling
282
+
283
+ List endpoints detect cancellation explicitly:
284
+
285
+ ```typescript
286
+ } catch (error) {
287
+ if (error instanceof Error && (error.name === 'AbortError' || error.name === 'CanceledError')) {
288
+ console.log('Request was cancelled');
289
+ throw error;
290
+ }
291
+ console.error('...', error);
292
+ throw error;
293
+ }
294
+ ```
295
+
296
+ ### What consumers receive
297
+
298
+ When an error is thrown, it is an axios error with this shape:
299
+
300
+ ```typescript
301
+ error.response // present if the server replied (4xx, 5xx)
302
+ error.response.status // HTTP status code
303
+ error.response.data // backend error body (may contain validation messages)
304
+
305
+ error.request // present if request was sent but no response received
306
+ error.message // network-level error description
307
+ ```
308
+
309
+ Consumers are responsible for distinguishing application errors (`error.response`) from transport errors (no `error.response`).
310
+
311
+ ---
312
+
313
+ ## 9. Versioning / Compatibility
314
+
315
+ - The SDK uses **semver**. Current version: `1.6.33`.
316
+ - Frontend apps pin to a specific SDK version in their `package.json`. Upgrading requires deliberate action.
317
+ - When `washday-backend` changes a response shape or adds/removes an endpoint, the SDK must be updated and re-published before consuming apps can use the new behavior.
318
+ - There is currently no automated contract generation (e.g., OpenAPI → SDK types). SDK changes are written manually to match backend changes.
319
+ - **Backward-incompatible backend changes** (removed fields, changed response structures) are high risk because frontend apps may be on older SDK versions. Coordinate SDK and backend releases.
320
+
321
+ **Release flow:**
322
+
323
+ ```
324
+ Update src/ → bump version in package.json → npm run publishVersion (runs tsc + npm publish)
325
+ ```
326
+
327
+ ---
328
+
329
+ ## 10. Future Considerations
330
+
331
+ - **Typed response generics**: Replace `Promise<any>` returns with typed response interfaces (e.g., `Promise<{ data: IOrder[] }>`). This is the highest-impact improvement for catching integration bugs at compile time.
332
+ - **Contract generation**: Generate SDK types automatically from a backend OpenAPI spec or shared schema source to eliminate manual drift.
333
+ - **Shared validation schemas**: Use `joi` (already a dependency) to define shared request schemas that can be validated client-side before sending.
334
+ - **Structured error types**: Introduce a typed `WashdaySDKError` class that normalizes axios error shapes so consumers don't need to understand axios internals.
335
+ - **Observability hooks**: Allow consumers to inject request/response interceptors (e.g., for logging, metrics, or auth token refresh) without forking axios configuration.
336
+ - **Monorepo**: As the ecosystem grows, co-locating `washday-sdk` with shared entity types in a monorepo would reduce the latency between backend changes and SDK updates.
337
+ - **Pagination helpers**: Standardize list endpoint pagination patterns (currently ad-hoc via `pageNum` / `limit` query params).