@sales-planner/http-client 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +302 -277
- package/dist/clients/api-keys-client.d.ts +2 -2
- package/dist/clients/api-keys-client.d.ts.map +1 -1
- package/dist/clients/api-keys-client.js +2 -2
- package/dist/clients/brands-client.d.ts +12 -11
- package/dist/clients/brands-client.d.ts.map +1 -1
- package/dist/clients/brands-client.js +15 -12
- package/dist/clients/categories-client.d.ts +12 -11
- package/dist/clients/categories-client.d.ts.map +1 -1
- package/dist/clients/categories-client.js +15 -12
- package/dist/clients/groups-client.d.ts +12 -11
- package/dist/clients/groups-client.d.ts.map +1 -1
- package/dist/clients/groups-client.js +15 -12
- package/dist/clients/marketplaces-client.d.ts +12 -11
- package/dist/clients/marketplaces-client.d.ts.map +1 -1
- package/dist/clients/marketplaces-client.js +15 -12
- package/dist/clients/roles-client.d.ts +3 -3
- package/dist/clients/roles-client.d.ts.map +1 -1
- package/dist/clients/roles-client.js +4 -4
- package/dist/clients/sales-history-client.d.ts +11 -11
- package/dist/clients/sales-history-client.d.ts.map +1 -1
- package/dist/clients/sales-history-client.js +12 -12
- package/dist/clients/sales-planner-client.d.ts +0 -109
- package/dist/clients/sales-planner-client.d.ts.map +1 -1
- package/dist/clients/sales-planner-client.js +1 -109
- package/dist/clients/shops-client.d.ts +3 -3
- package/dist/clients/shops-client.d.ts.map +1 -1
- package/dist/clients/shops-client.js +4 -4
- package/dist/clients/skus-client.d.ts +12 -11
- package/dist/clients/skus-client.d.ts.map +1 -1
- package/dist/clients/skus-client.js +15 -12
- package/dist/clients/statuses-client.d.ts +12 -11
- package/dist/clients/statuses-client.d.ts.map +1 -1
- package/dist/clients/statuses-client.js +15 -12
- package/dist/clients/suppliers-client.d.ts +12 -36
- package/dist/clients/suppliers-client.d.ts.map +1 -1
- package/dist/clients/suppliers-client.js +16 -13
- package/dist/clients/tenants-client.d.ts +4 -4
- package/dist/clients/tenants-client.d.ts.map +1 -1
- package/dist/clients/tenants-client.js +6 -6
- package/dist/clients/user-roles-client.d.ts +4 -2
- package/dist/clients/user-roles-client.d.ts.map +1 -1
- package/dist/clients/user-roles-client.js +16 -2
- package/dist/clients/users-client.d.ts +2 -2
- package/dist/clients/users-client.d.ts.map +1 -1
- package/dist/clients/users-client.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ import { SalesPlannerClient } from '@sales-planner/http-client';
|
|
|
17
17
|
|
|
18
18
|
const client = new SalesPlannerClient({
|
|
19
19
|
baseUrl: 'https://sales-planner-back.vercel.app',
|
|
20
|
-
|
|
20
|
+
apiKey: 'your-api-key',
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
// Check if API is healthy
|
|
@@ -25,339 +25,314 @@ const health = await client.getHealth();
|
|
|
25
25
|
console.log(health); // { status: 'ok', version: '1.0.0' }
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
###
|
|
28
|
+
### Shop Context
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
Most operations require a shop context (`ctx`) as the **first argument**:
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
```typescript
|
|
33
|
+
const ctx = { tenant_id: 1, shop_id: 1 };
|
|
34
|
+
|
|
35
|
+
// All entity methods follow: client.<entity>.<method>(ctx, ...args)
|
|
36
|
+
const skus = await client.skus.getSkus(ctx);
|
|
37
|
+
const sku = await client.skus.getSku(ctx, 123);
|
|
38
|
+
const brand = await client.brands.getBrandByCode(ctx, 'apple');
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Namespaced Sub-Clients
|
|
33
42
|
|
|
34
43
|
Access resources through domain-specific sub-clients:
|
|
35
44
|
|
|
36
45
|
```typescript
|
|
37
|
-
// Users
|
|
46
|
+
// Users (system-level, no ctx)
|
|
38
47
|
const users = await client.users.getUsers();
|
|
39
48
|
const user = await client.users.getUser(1);
|
|
40
49
|
|
|
41
|
-
// Tenants
|
|
50
|
+
// Tenants (system-level, no ctx)
|
|
42
51
|
const tenants = await client.tenants.getTenants();
|
|
43
|
-
const shops = await client.shops.getShops(tenantId);
|
|
44
52
|
|
|
45
|
-
//
|
|
46
|
-
const
|
|
47
|
-
await client.skus.importSkusJson(items, { tenantId, shopId });
|
|
48
|
-
const csv = await client.skus.exportSkusCsv({ tenantId, shopId });
|
|
49
|
-
|
|
50
|
-
// Brands with import/export
|
|
51
|
-
const brands = await client.brands.getBrands({ tenantId, shopId });
|
|
52
|
-
await client.brands.importBrandsJson(items, { tenantId, shopId });
|
|
53
|
-
const brandsCsv = await client.brands.exportBrandsCsv({ tenantId, shopId });
|
|
53
|
+
// Shops (tenant-level)
|
|
54
|
+
const shops = await client.shops.getShops(tenantId);
|
|
54
55
|
|
|
55
|
-
//
|
|
56
|
-
const
|
|
57
|
-
await client.categories.importCategoriesJson(items, { tenantId, shopId });
|
|
56
|
+
// Shop-scoped entities (require ctx)
|
|
57
|
+
const ctx = { tenant_id: 1, shop_id: 1 };
|
|
58
58
|
|
|
59
|
-
//
|
|
60
|
-
const
|
|
61
|
-
await client.
|
|
59
|
+
// SKUs
|
|
60
|
+
const skus = await client.skus.getSkus(ctx);
|
|
61
|
+
await client.skus.createSku(ctx, { code: 'SKU-001', title: 'Product 1' });
|
|
62
|
+
await client.skus.importJson(ctx, items);
|
|
63
|
+
const csv = await client.skus.exportCsv(ctx);
|
|
62
64
|
|
|
63
|
-
//
|
|
64
|
-
const
|
|
65
|
-
await client.
|
|
65
|
+
// Brands
|
|
66
|
+
const brands = await client.brands.getBrands(ctx);
|
|
67
|
+
await client.brands.importJson(ctx, [{ code: 'apple', title: 'Apple' }]);
|
|
66
68
|
|
|
67
|
-
//
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
);
|
|
69
|
+
// Categories, Groups, Statuses, Suppliers - same pattern
|
|
70
|
+
const categories = await client.categories.getCategories(ctx);
|
|
71
|
+
const groups = await client.groups.getGroups(ctx);
|
|
72
|
+
const statuses = await client.statuses.getStatuses(ctx);
|
|
73
|
+
const suppliers = await client.suppliers.getSuppliers(ctx);
|
|
72
74
|
|
|
73
75
|
// Marketplaces
|
|
74
|
-
const marketplaces = await client.marketplaces.getMarketplaces(
|
|
76
|
+
const marketplaces = await client.marketplaces.getMarketplaces(ctx);
|
|
75
77
|
|
|
76
|
-
//
|
|
78
|
+
// Sales History (with optional period filter)
|
|
79
|
+
const history = await client.salesHistory.getSalesHistory(ctx, {
|
|
80
|
+
start: '2024-01',
|
|
81
|
+
end: '2024-12',
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Entity Metadata (no auth required)
|
|
77
85
|
const metadata = await client.metadata.getEntitiesMetadata();
|
|
78
|
-
// Returns field definitions for brands, categories, groups, statuses, marketplaces, skus, sales history
|
|
79
86
|
```
|
|
80
87
|
|
|
81
|
-
|
|
82
|
-
- Clear domain separation
|
|
83
|
-
- IDE autocomplete by domain
|
|
84
|
-
- Easier to discover related methods
|
|
88
|
+
## API Conventions
|
|
85
89
|
|
|
86
|
-
|
|
90
|
+
### Argument Order
|
|
87
91
|
|
|
88
|
-
|
|
92
|
+
All methods follow a consistent pattern: **context first, then other arguments**.
|
|
89
93
|
|
|
90
94
|
```typescript
|
|
91
|
-
//
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const skus = await client.getSkus({ tenantId, shopId });
|
|
95
|
-
```
|
|
95
|
+
// Get by ID
|
|
96
|
+
await client.skus.getSku(ctx, id);
|
|
97
|
+
await client.brands.getBrand(ctx, id);
|
|
96
98
|
|
|
97
|
-
|
|
99
|
+
// Get by code
|
|
100
|
+
await client.skus.getSkuByCode(ctx, code);
|
|
101
|
+
await client.brands.getBrandByCode(ctx, code);
|
|
98
102
|
|
|
99
|
-
|
|
103
|
+
// Create
|
|
104
|
+
await client.skus.createSku(ctx, request);
|
|
105
|
+
await client.brands.createBrand(ctx, request);
|
|
100
106
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
[
|
|
105
|
-
{ code: 'SKU-001', title: 'Product 1' },
|
|
106
|
-
{ code: 'SKU-002', title: 'Product 2' },
|
|
107
|
-
],
|
|
108
|
-
{ tenantId, shopId }
|
|
109
|
-
);
|
|
110
|
-
// Returns: { inserted: 2, updated: 0, errors: [] }
|
|
111
|
-
|
|
112
|
-
// Import from CSV file
|
|
113
|
-
const csvContent = await fs.readFile('skus.csv', 'utf-8');
|
|
114
|
-
const result = await client.skus.importSkusCsv(csvContent, { tenantId, shopId });
|
|
107
|
+
// Update
|
|
108
|
+
await client.skus.updateSku(ctx, id, request);
|
|
109
|
+
await client.brands.updateBrand(ctx, id, request);
|
|
115
110
|
|
|
116
|
-
//
|
|
117
|
-
|
|
111
|
+
// Delete
|
|
112
|
+
await client.skus.deleteSku(ctx, id);
|
|
113
|
+
await client.brands.deleteBrand(ctx, id);
|
|
118
114
|
|
|
119
|
-
//
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
const categoryResult = await client.categories.importCategoriesJson(
|
|
129
|
-
[{ code: 'electronics', title: 'Electronics' }],
|
|
130
|
-
{ tenantId, shopId }
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
const groupResult = await client.groups.importGroupsJson(
|
|
134
|
-
[{ code: 'smartphones', title: 'Smartphones' }],
|
|
135
|
-
{ tenantId, shopId }
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
const statusResult = await client.statuses.importStatusesJson(
|
|
139
|
-
[{ code: 'active', title: 'Active' }],
|
|
140
|
-
{ tenantId, shopId }
|
|
141
|
-
);
|
|
115
|
+
// Import
|
|
116
|
+
await client.skus.importJson(ctx, items);
|
|
117
|
+
await client.skus.importCsv(ctx, csvContent);
|
|
118
|
+
|
|
119
|
+
// Export
|
|
120
|
+
await client.skus.exportJson(ctx);
|
|
121
|
+
await client.skus.exportCsv(ctx);
|
|
142
122
|
```
|
|
143
123
|
|
|
144
|
-
|
|
124
|
+
### IDs vs Codes
|
|
145
125
|
|
|
146
|
-
|
|
126
|
+
- **Create/Update operations** use numeric IDs for references (e.g., `marketplace_id`)
|
|
127
|
+
- **Import/Export operations** use string codes for human readability (e.g., `marketplace: 'amazon'`)
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
// Create uses IDs
|
|
131
|
+
await client.salesHistory.createSalesHistory(ctx, {
|
|
132
|
+
sku_id: 123,
|
|
133
|
+
marketplace_id: 1,
|
|
134
|
+
period: '2026-01',
|
|
135
|
+
quantity: 100,
|
|
136
|
+
});
|
|
147
137
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
-
|
|
138
|
+
// Import uses codes (auto-resolves to IDs)
|
|
139
|
+
await client.salesHistory.importJson(ctx, [
|
|
140
|
+
{ sku: 'SKU-001', marketplace: 'amazon', period: '2026-01', quantity: 100 },
|
|
141
|
+
]);
|
|
151
142
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
143
|
+
// Export returns codes
|
|
144
|
+
const exported = await client.salesHistory.exportJson(ctx);
|
|
145
|
+
// [{ sku: 'SKU-001', marketplace: 'amazon', period: '2026-01', quantity: 100 }]
|
|
146
|
+
```
|
|
155
147
|
|
|
156
|
-
|
|
148
|
+
## Import/Export Pattern
|
|
157
149
|
|
|
158
|
-
|
|
159
|
-
- `code` (required): String, 1-100 characters, unique per shop
|
|
160
|
-
- `title` (required): String, 1-200 characters
|
|
150
|
+
All shop-scoped entities support bulk import/export:
|
|
161
151
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
- `title` (optional): String, 1-200 characters
|
|
152
|
+
```typescript
|
|
153
|
+
const ctx = { tenant_id: 1, shop_id: 1 };
|
|
165
154
|
|
|
166
|
-
|
|
155
|
+
// Import from JSON array
|
|
156
|
+
const result = await client.skus.importJson(ctx, [
|
|
157
|
+
{ code: 'SKU-001', title: 'Product 1' },
|
|
158
|
+
{ code: 'SKU-002', title: 'Product 2' },
|
|
159
|
+
]);
|
|
160
|
+
console.log(result); // { created: 2, updated: 0, errors: [] }
|
|
167
161
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
-
|
|
162
|
+
// Import from CSV string
|
|
163
|
+
const csvContent = `code,title
|
|
164
|
+
SKU-001,Product 1
|
|
165
|
+
SKU-002,Product 2`;
|
|
166
|
+
const result = await client.skus.importCsv(ctx, csvContent);
|
|
171
167
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
- `title` (optional): String, 1-200 characters
|
|
168
|
+
// Export to JSON
|
|
169
|
+
const items = await client.skus.exportJson(ctx);
|
|
175
170
|
|
|
176
|
-
|
|
171
|
+
// Export to CSV
|
|
172
|
+
const csv = await client.skus.exportCsv(ctx);
|
|
177
173
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
174
|
+
// Get example templates (no auth required)
|
|
175
|
+
const exampleJson = await client.skus.getExampleJson();
|
|
176
|
+
const exampleCsv = await client.skus.getExampleCsv();
|
|
177
|
+
```
|
|
181
178
|
|
|
182
|
-
**
|
|
183
|
-
- `code` (optional): String, 1-100 characters
|
|
184
|
-
- `title` (optional): String, 1-200 characters
|
|
179
|
+
**Supported entities:** SKUs, Brands, Categories, Groups, Statuses, Suppliers, Marketplaces, Sales History
|
|
185
180
|
|
|
186
|
-
|
|
181
|
+
## Data Requirements
|
|
187
182
|
|
|
188
|
-
|
|
189
|
-
- `code` (required): String, 1-100 characters, unique per shop
|
|
190
|
-
- `title` (required): String, 1-200 characters
|
|
183
|
+
### SKUs
|
|
191
184
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
185
|
+
| Field | Create/Import | Update | Export |
|
|
186
|
+
|-------|---------------|--------|--------|
|
|
187
|
+
| `code` | Required, unique per shop | Optional | ✓ |
|
|
188
|
+
| `title` | Required | Optional | ✓ |
|
|
189
|
+
| `title2` | Optional | Optional | ✓ |
|
|
190
|
+
| `category` | Optional (code) | - | code |
|
|
191
|
+
| `group` | Optional (code) | - | code |
|
|
192
|
+
| `status` | Optional (code) | - | code |
|
|
193
|
+
| `supplier` | Optional (code) | - | code |
|
|
195
194
|
|
|
196
|
-
###
|
|
195
|
+
### Brands, Categories, Groups, Statuses, Suppliers
|
|
197
196
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
- `marketplace_id` (required): Number, must reference existing marketplace
|
|
197
|
+
| Field | Create/Import | Update | Export |
|
|
198
|
+
|-------|---------------|--------|--------|
|
|
199
|
+
| `code` | Required, unique per shop | Optional | ✓ |
|
|
200
|
+
| `title` | Required | Optional | ✓ |
|
|
203
201
|
|
|
204
|
-
|
|
205
|
-
- `sku_code` (required): String, must match existing SKU or will be auto-created
|
|
206
|
-
- `period` (required): String, format `YYYY-MM` (e.g., "2026-01")
|
|
207
|
-
- `quantity` (required): Number, integer
|
|
208
|
-
- `marketplace` (required): String (marketplace code), must match existing marketplace or will be auto-created
|
|
202
|
+
### Marketplaces
|
|
209
203
|
|
|
210
|
-
|
|
204
|
+
| Field | Create/Import | Update | Export |
|
|
205
|
+
|-------|---------------|--------|--------|
|
|
206
|
+
| `code` | Required, unique per shop | Optional | ✓ |
|
|
207
|
+
| `title` | Required | Optional | ✓ |
|
|
211
208
|
|
|
212
|
-
|
|
213
|
-
- `sku_id` (optional): Number
|
|
214
|
-
- `period` (optional): String, format `YYYY-MM`
|
|
215
|
-
- `quantity` (optional): Number
|
|
216
|
-
- `marketplace_id` (optional): Number
|
|
209
|
+
### Sales History
|
|
217
210
|
|
|
218
|
-
|
|
211
|
+
| Field | Create | Import | Update | Export |
|
|
212
|
+
|-------|--------|--------|--------|--------|
|
|
213
|
+
| `sku_id` | Required | - | Optional | - |
|
|
214
|
+
| `sku` | - | Required (code) | - | code |
|
|
215
|
+
| `marketplace_id` | Required | - | Optional | - |
|
|
216
|
+
| `marketplace` | - | Required (code) | - | code |
|
|
217
|
+
| `period` | Required (YYYY-MM) | Required | Optional | ✓ |
|
|
218
|
+
| `quantity` | Required | Required | Optional | ✓ |
|
|
219
219
|
|
|
220
|
-
|
|
221
|
-
- `email` (required): String, valid email format, unique
|
|
222
|
-
- `name` (required): String, 1-200 characters
|
|
223
|
-
- `default_shop_id` (optional): Number
|
|
220
|
+
### Users
|
|
224
221
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
222
|
+
| Field | Create | Update |
|
|
223
|
+
|-------|--------|--------|
|
|
224
|
+
| `email` | Required, unique | Optional |
|
|
225
|
+
| `name` | Required | Optional |
|
|
226
|
+
| `default_shop_id` | Optional | Optional (null to clear) |
|
|
229
227
|
|
|
230
228
|
### Tenants
|
|
231
229
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
**Update:**
|
|
237
|
-
- `title` (optional): String, 1-200 characters
|
|
238
|
-
- `owner_id` (optional): Number or null
|
|
230
|
+
| Field | Create | Update |
|
|
231
|
+
|-------|--------|--------|
|
|
232
|
+
| `title` | Required | Optional |
|
|
233
|
+
| `owner_id` | Optional | Optional (null to clear) |
|
|
239
234
|
|
|
240
235
|
### Shops
|
|
241
236
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
**Update:**
|
|
247
|
-
- `title` (optional): String, 1-200 characters
|
|
248
|
-
|
|
249
|
-
### Marketplaces
|
|
250
|
-
|
|
251
|
-
**Create:**
|
|
252
|
-
- `code` (required): String, 1-100 characters, unique (e.g., "amazon", "ebay")
|
|
253
|
-
- `title` (required): String, 1-200 characters
|
|
237
|
+
| Field | Create | Update |
|
|
238
|
+
|-------|--------|--------|
|
|
239
|
+
| `title` | Required | Optional |
|
|
240
|
+
| `tenant_id` | Required | - |
|
|
254
241
|
|
|
255
|
-
|
|
256
|
-
- `code` (optional): String, 1-100 characters
|
|
257
|
-
- `title` (optional): String, 1-200 characters
|
|
242
|
+
## Available Sub-Clients
|
|
258
243
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
```typescript
|
|
262
|
-
import { ApiError } from '@sales-planner/http-client';
|
|
263
|
-
|
|
264
|
-
try {
|
|
265
|
-
await client.users.getUser(999);
|
|
266
|
-
} catch (error) {
|
|
267
|
-
if (error instanceof ApiError) {
|
|
268
|
-
console.error(`API Error ${error.status}: ${error.message}`);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
Common HTTP status codes:
|
|
274
|
-
- `409 Conflict` - Duplicate resource (email, SKU code, sales period)
|
|
275
|
-
- `404 Not Found` - Resource not found
|
|
276
|
-
- `403 Forbidden` - Insufficient permissions
|
|
277
|
-
- `400 Bad Request` - Validation error
|
|
278
|
-
|
|
279
|
-
```typescript
|
|
280
|
-
try {
|
|
281
|
-
await client.createUser({ email: 'user@example.com', name: 'John' });
|
|
282
|
-
} catch (error) {
|
|
283
|
-
if (error.response?.status === 409) {
|
|
284
|
-
console.error('User with this email already exists');
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
## Available Methods
|
|
244
|
+
### System-Level (no context required)
|
|
290
245
|
|
|
291
|
-
|
|
246
|
+
#### `client.me`
|
|
292
247
|
- `getMe()` - Get current user with roles and tenants
|
|
293
248
|
|
|
294
|
-
|
|
295
|
-
- `getUsers()
|
|
296
|
-
- `
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
- `
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
- `
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
- `
|
|
249
|
+
#### `client.users`
|
|
250
|
+
- `getUsers()` - List users (system admin sees all, tenant admin sees their tenants)
|
|
251
|
+
- `getUser(id)` - Get user by ID
|
|
252
|
+
- `createUser(request)` - Create user
|
|
253
|
+
- `updateUser(id, request)` - Update user
|
|
254
|
+
- `deleteUser(id)` - Delete user
|
|
255
|
+
|
|
256
|
+
#### `client.tenants`
|
|
257
|
+
- `getTenants()` - List tenants
|
|
258
|
+
- `getTenant(id)` - Get tenant by ID
|
|
259
|
+
- `createTenant(request)` - Create tenant (system admin only)
|
|
260
|
+
- `updateTenant(id, request)` - Update tenant
|
|
261
|
+
- `deleteTenant(id)` - Delete tenant
|
|
262
|
+
- `createTenantWithShopAndUser(request)` - Create tenant with initial shop and user
|
|
263
|
+
|
|
264
|
+
#### `client.shops`
|
|
265
|
+
- `getShops(tenantId?)` - List shops (optionally filtered by tenant)
|
|
266
|
+
- `getShop(id)` - Get shop by ID
|
|
267
|
+
- `createShop(request)` - Create shop
|
|
268
|
+
- `updateShop(id, request)` - Update shop
|
|
269
|
+
- `deleteShop(id)` - Delete shop
|
|
306
270
|
- `deleteShopData(id)` - Delete all data (SKUs, sales history) for a shop
|
|
307
271
|
|
|
308
|
-
|
|
309
|
-
- `
|
|
310
|
-
- `
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
- `
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
- `
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
- `
|
|
320
|
-
- `
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
- `
|
|
325
|
-
|
|
326
|
-
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
- `
|
|
332
|
-
- `
|
|
333
|
-
- `
|
|
334
|
-
- `
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
- `
|
|
338
|
-
- `
|
|
339
|
-
- `
|
|
340
|
-
- `
|
|
341
|
-
- `
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
- `
|
|
348
|
-
- `
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
- `
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
- `
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
- `
|
|
360
|
-
- `
|
|
272
|
+
#### `client.roles`
|
|
273
|
+
- `getRoles()` - List roles (system admin only)
|
|
274
|
+
- `getRole(id)` - Get role by ID
|
|
275
|
+
|
|
276
|
+
#### `client.userRoles`
|
|
277
|
+
- `getUserRoles(query)` - List user roles
|
|
278
|
+
- `getUserRole(id)` - Get user role by ID
|
|
279
|
+
- `createUserRole(request)` - Create user role
|
|
280
|
+
- `deleteUserRole(id)` - Delete user role
|
|
281
|
+
|
|
282
|
+
#### `client.apiKeys`
|
|
283
|
+
- `getApiKeys()` - List API keys (system admin only)
|
|
284
|
+
- `createApiKey(request)` - Create API key
|
|
285
|
+
- `deleteApiKey(id)` - Delete API key
|
|
286
|
+
|
|
287
|
+
#### `client.metadata`
|
|
288
|
+
- `getEntitiesMetadata()` - Get field definitions for all entities (no auth)
|
|
289
|
+
|
|
290
|
+
### Shop-Scoped (context required)
|
|
291
|
+
|
|
292
|
+
All shop-scoped clients follow the same pattern:
|
|
293
|
+
|
|
294
|
+
#### `client.skus`
|
|
295
|
+
- `getSkus(ctx)` - List SKUs
|
|
296
|
+
- `getSku(ctx, id)` - Get SKU by ID
|
|
297
|
+
- `getSkuByCode(ctx, code)` - Get SKU by code
|
|
298
|
+
- `createSku(ctx, request)` - Create SKU
|
|
299
|
+
- `updateSku(ctx, id, request)` - Update SKU
|
|
300
|
+
- `deleteSku(ctx, id)` - Delete SKU
|
|
301
|
+
- `importJson(ctx, items)` - Import from JSON array
|
|
302
|
+
- `importCsv(ctx, csvContent)` - Import from CSV string
|
|
303
|
+
- `exportJson(ctx)` - Export to JSON
|
|
304
|
+
- `exportCsv(ctx)` - Export to CSV
|
|
305
|
+
- `getExampleJson()` - Get JSON import example (no auth)
|
|
306
|
+
- `getExampleCsv()` - Get CSV import example (no auth)
|
|
307
|
+
|
|
308
|
+
#### `client.brands`, `client.categories`, `client.groups`, `client.statuses`, `client.suppliers`
|
|
309
|
+
|
|
310
|
+
Same methods as `client.skus`:
|
|
311
|
+
- `get<Entity>s(ctx)`, `get<Entity>(ctx, id)`, `get<Entity>ByCode(ctx, code)`
|
|
312
|
+
- `create<Entity>(ctx, request)`, `update<Entity>(ctx, id, request)`, `delete<Entity>(ctx, id)`
|
|
313
|
+
- `importJson(ctx, items)`, `importCsv(ctx, csvContent)`
|
|
314
|
+
- `exportJson(ctx)`, `exportCsv(ctx)`
|
|
315
|
+
- `getExampleJson()`, `getExampleCsv()`
|
|
316
|
+
|
|
317
|
+
#### `client.marketplaces`
|
|
318
|
+
- `getMarketplaces(ctx)` - List marketplaces
|
|
319
|
+
- `getMarketplace(ctx, id)` - Get marketplace by ID
|
|
320
|
+
- `getMarketplaceByCode(ctx, code)` - Get marketplace by code
|
|
321
|
+
- `createMarketplace(ctx, request)` - Create marketplace
|
|
322
|
+
- `updateMarketplace(ctx, id, request)` - Update marketplace
|
|
323
|
+
- `deleteMarketplace(ctx, id)` - Delete marketplace
|
|
324
|
+
- `importJson(ctx, items)`, `importCsv(ctx, csvContent)` - Import
|
|
325
|
+
- `exportJson(ctx)`, `exportCsv(ctx)` - Export
|
|
326
|
+
|
|
327
|
+
#### `client.salesHistory`
|
|
328
|
+
- `getSalesHistory(ctx, query?)` - List sales history (optional period filter)
|
|
329
|
+
- `getSalesHistoryItem(ctx, id)` - Get sales history item by ID
|
|
330
|
+
- `createSalesHistory(ctx, request)` - Create sales history
|
|
331
|
+
- `updateSalesHistory(ctx, id, request)` - Update sales history
|
|
332
|
+
- `deleteSalesHistory(ctx, id)` - Delete sales history
|
|
333
|
+
- `importJson(ctx, items)`, `importCsv(ctx, csvContent)` - Import
|
|
334
|
+
- `exportJson(ctx, query?)`, `exportCsv(ctx, query?)` - Export (optional period filter)
|
|
335
|
+
- `getExampleJson()`, `getExampleCsv()` - Examples (no auth)
|
|
361
336
|
|
|
362
337
|
## Error Handling
|
|
363
338
|
|
|
@@ -365,7 +340,7 @@ try {
|
|
|
365
340
|
import { SalesPlannerClient, ApiError } from '@sales-planner/http-client';
|
|
366
341
|
|
|
367
342
|
try {
|
|
368
|
-
const user = await client.getUser(999);
|
|
343
|
+
const user = await client.users.getUser(999);
|
|
369
344
|
} catch (error) {
|
|
370
345
|
if (error instanceof ApiError) {
|
|
371
346
|
console.log(error.status); // 404
|
|
@@ -374,20 +349,70 @@ try {
|
|
|
374
349
|
}
|
|
375
350
|
```
|
|
376
351
|
|
|
352
|
+
**Common HTTP status codes:**
|
|
353
|
+
- `400 Bad Request` - Validation error
|
|
354
|
+
- `401 Unauthorized` - Missing or invalid API key
|
|
355
|
+
- `403 Forbidden` - Insufficient permissions
|
|
356
|
+
- `404 Not Found` - Resource not found
|
|
357
|
+
- `409 Conflict` - Duplicate resource (email, code, period)
|
|
358
|
+
|
|
377
359
|
## Types
|
|
378
360
|
|
|
379
|
-
|
|
361
|
+
Types are re-exported from `@sales-planner/shared`:
|
|
380
362
|
|
|
381
363
|
```typescript
|
|
382
|
-
import type {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
364
|
+
import type {
|
|
365
|
+
// Context
|
|
366
|
+
ShopContextParams,
|
|
367
|
+
PeriodQuery,
|
|
368
|
+
|
|
369
|
+
// Entities
|
|
370
|
+
User,
|
|
371
|
+
Tenant,
|
|
372
|
+
Shop,
|
|
373
|
+
Sku,
|
|
374
|
+
Brand,
|
|
375
|
+
Category,
|
|
376
|
+
Group,
|
|
377
|
+
Status,
|
|
378
|
+
Supplier,
|
|
379
|
+
Marketplace,
|
|
380
|
+
SalesHistory,
|
|
381
|
+
Role,
|
|
382
|
+
UserRole,
|
|
383
|
+
ApiKey,
|
|
384
|
+
|
|
385
|
+
// Request types (for create/update)
|
|
386
|
+
CreateUserRequest,
|
|
387
|
+
UpdateUserRequest,
|
|
388
|
+
CreateTenantRequest,
|
|
389
|
+
UpdateTenantRequest,
|
|
390
|
+
CreateShopRequest,
|
|
391
|
+
UpdateShopRequest,
|
|
392
|
+
CreateSkuRequest,
|
|
393
|
+
UpdateSkuRequest,
|
|
394
|
+
CreateBrandRequest,
|
|
395
|
+
UpdateBrandRequest,
|
|
396
|
+
CreateSalesHistoryRequest,
|
|
397
|
+
UpdateSalesHistoryRequest,
|
|
398
|
+
// ... etc
|
|
399
|
+
|
|
400
|
+
// Import types (for import operations)
|
|
401
|
+
ImportSkuItem,
|
|
402
|
+
ImportBrandItem,
|
|
403
|
+
ImportSalesHistoryItem,
|
|
404
|
+
// ... etc
|
|
405
|
+
|
|
406
|
+
// Response types
|
|
407
|
+
UserWithRolesAndTenants,
|
|
408
|
+
TenantWithShopAndApiKey,
|
|
409
|
+
ImportResult,
|
|
410
|
+
SkuImportResult,
|
|
411
|
+
DeleteDataResult,
|
|
412
|
+
|
|
413
|
+
// Export types
|
|
414
|
+
SkuExportItem,
|
|
415
|
+
SalesHistoryExportItem,
|
|
391
416
|
} from '@sales-planner/http-client';
|
|
392
417
|
```
|
|
393
418
|
|