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 +139 -0
- package/dist/api/index.js +2 -1
- package/dist/api/staff/get.js +17 -0
- package/docs/architecture.md +337 -0
- package/docs/patterns.md +505 -0
- package/package.json +1 -1
- package/src/api/index.ts +2 -1
- package/src/api/staff/get.ts +15 -0
- package/src/interfaces/Api.ts +2 -1
- package/test/staff.getStoreAssignableStaffs.test.ts +37 -0
- package/docs/README.md +0 -67
- package/docs/examples/common-use-cases.md +0 -488
- package/docs/getting-started.md +0 -237
- package/docs/modules/attendance.md +0 -404
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,
|
package/dist/api/staff/get.js
CHANGED
|
@@ -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).
|