@simpleapps-com/augur-api 0.4.7 → 0.4.9
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 +96 -141
- package/TIPS-AND-TRICKS.md +887 -0
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/services/agr-info/client.d.ts +9 -9
- package/dist/cjs/services/agr-info/schemas/akashaGenerate.d.ts +1 -1
- package/dist/cjs/services/agr-info/schemas/akashaGenerate.d.ts.map +1 -1
- package/dist/cjs/services/agr-info/schemas/akashaGenerate.js +1 -1
- package/dist/cjs/services/agr-info/schemas/akashaGenerate.js.map +1 -1
- package/dist/cjs/services/agr-info/schemas/joomlaGenerate.d.ts +1 -1
- package/dist/cjs/services/agr-info/schemas/joomlaGenerate.d.ts.map +1 -1
- package/dist/cjs/services/agr-info/schemas/joomlaGenerate.js +1 -1
- package/dist/cjs/services/agr-info/schemas/joomlaGenerate.js.map +1 -1
- package/dist/cjs/services/agr-info/schemas/microservices.d.ts +9 -9
- package/dist/cjs/services/agr-info/schemas/microservices.d.ts.map +1 -1
- package/dist/cjs/services/agr-info/schemas/microservices.js +1 -1
- package/dist/cjs/services/agr-info/schemas/microservices.js.map +1 -1
- package/dist/cjs/services/agr-info/schemas/rubrics.d.ts +1 -1
- package/dist/cjs/services/agr-info/schemas/rubrics.d.ts.map +1 -1
- package/dist/cjs/services/agr-info/schemas/rubrics.js +1 -1
- package/dist/cjs/services/agr-info/schemas/rubrics.js.map +1 -1
- package/dist/cjs/services/agr-info/schemas.d.ts +12 -12
- package/dist/cjs/services/agr-info/schemas.d.ts.map +1 -1
- package/dist/cjs/services/agr-info/schemas.js +4 -4
- package/dist/cjs/services/agr-info/schemas.js.map +1 -1
- package/dist/cjs/services/commerce/client.d.ts +1 -1
- package/dist/cjs/services/commerce/schemas/cart.d.ts +16 -16
- package/dist/cjs/services/items/client.d.ts +4 -36
- package/dist/cjs/services/items/client.d.ts.map +1 -1
- package/dist/cjs/services/items/schemas/invMast.d.ts +17 -17
- package/dist/cjs/services/items/schemas/invMast.js +1 -1
- package/dist/cjs/services/items/schemas/invMast.js.map +1 -1
- package/dist/cjs/services/items/schemas/invMastLocationsBins.d.ts +20 -148
- package/dist/cjs/services/items/schemas/invMastLocationsBins.d.ts.map +1 -1
- package/dist/cjs/services/items/schemas/invMastLocationsBins.js +10 -10
- package/dist/cjs/services/items/schemas/invMastLocationsBins.js.map +1 -1
- package/dist/cjs/services/joomla/client.d.ts +41 -53
- package/dist/cjs/services/joomla/client.d.ts.map +1 -1
- package/dist/cjs/services/joomla/schemas/content.d.ts +15 -15
- package/dist/cjs/services/joomla/schemas/content.d.ts.map +1 -1
- package/dist/cjs/services/joomla/schemas/content.js +1 -1
- package/dist/cjs/services/joomla/schemas/content.js.map +1 -1
- package/dist/cjs/services/joomla/schemas/contentId.d.ts +7 -7
- package/dist/cjs/services/joomla/schemas/contentId.d.ts.map +1 -1
- package/dist/cjs/services/joomla/schemas/contentId.js +1 -1
- package/dist/cjs/services/joomla/schemas/contentId.js.map +1 -1
- package/dist/cjs/services/joomla/schemas/contentIdDoc.d.ts +7 -7
- package/dist/cjs/services/joomla/schemas/contentIdDoc.d.ts.map +1 -1
- package/dist/cjs/services/joomla/schemas/contentIdDoc.js +1 -1
- package/dist/cjs/services/joomla/schemas/contentIdDoc.js.map +1 -1
- package/dist/cjs/services/joomla/schemas/healthCheck.d.ts +22 -14
- package/dist/cjs/services/joomla/schemas/healthCheck.d.ts.map +1 -1
- package/dist/cjs/services/joomla/schemas/healthCheck.js +1 -1
- package/dist/cjs/services/joomla/schemas/healthCheck.js.map +1 -1
- package/dist/cjs/services/joomla/schemas/tags.d.ts +13 -13
- package/dist/cjs/services/joomla/schemas/tags.d.ts.map +1 -1
- package/dist/cjs/services/joomla/schemas/tags.js +1 -1
- package/dist/cjs/services/joomla/schemas/tags.js.map +1 -1
- package/dist/cjs/services/joomla/schemas/userGroups.d.ts +141 -141
- package/dist/cjs/services/joomla/schemas/userGroups.d.ts.map +1 -1
- package/dist/cjs/services/joomla/schemas/userGroups.js +2 -2
- package/dist/cjs/services/joomla/schemas/userGroups.js.map +1 -1
- package/dist/cjs/services/joomla/schemas/users.d.ts +34 -34
- package/dist/cjs/services/joomla/schemas/users.d.ts.map +1 -1
- package/dist/cjs/services/joomla/schemas/users.js +2 -2
- package/dist/cjs/services/joomla/schemas/users.js.map +1 -1
- package/dist/cjs/services/joomla/schemas/usersId.d.ts +87 -250
- package/dist/cjs/services/joomla/schemas/usersId.d.ts.map +1 -1
- package/dist/cjs/services/joomla/schemas/usersId.js +7 -17
- package/dist/cjs/services/joomla/schemas/usersId.js.map +1 -1
- package/dist/cjs/services/joomla/schemas/usersIdDoc.d.ts +133 -180
- package/dist/cjs/services/joomla/schemas/usersIdDoc.d.ts.map +1 -1
- package/dist/cjs/services/joomla/schemas/usersIdDoc.js +8 -15
- package/dist/cjs/services/joomla/schemas/usersIdDoc.js.map +1 -1
- package/dist/cjs/services/joomla/schemas/usersIdGroups.d.ts +14 -14
- package/dist/cjs/services/joomla/schemas/usersIdGroups.d.ts.map +1 -1
- package/dist/cjs/services/joomla/schemas/usersIdGroups.js +2 -2
- package/dist/cjs/services/joomla/schemas/usersIdGroups.js.map +1 -1
- package/dist/cjs/services/joomla/schemas/usersIdTrinity.d.ts +281 -97
- package/dist/cjs/services/joomla/schemas/usersIdTrinity.d.ts.map +1 -1
- package/dist/cjs/services/joomla/schemas/usersIdTrinity.js +2 -2
- package/dist/cjs/services/joomla/schemas/usersIdTrinity.js.map +1 -1
- package/dist/cjs/services/joomla/schemas/usersVerifyPassword.d.ts +43 -35
- package/dist/cjs/services/joomla/schemas/usersVerifyPassword.d.ts.map +1 -1
- package/dist/cjs/services/joomla/schemas/usersVerifyPassword.js +2 -2
- package/dist/cjs/services/joomla/schemas/usersVerifyPassword.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/services/agr-info/client.d.ts +9 -9
- package/dist/esm/services/agr-info/schemas/akashaGenerate.d.ts +1 -1
- package/dist/esm/services/agr-info/schemas/akashaGenerate.d.ts.map +1 -1
- package/dist/esm/services/agr-info/schemas/akashaGenerate.js +1 -1
- package/dist/esm/services/agr-info/schemas/akashaGenerate.js.map +1 -1
- package/dist/esm/services/agr-info/schemas/joomlaGenerate.d.ts +1 -1
- package/dist/esm/services/agr-info/schemas/joomlaGenerate.d.ts.map +1 -1
- package/dist/esm/services/agr-info/schemas/joomlaGenerate.js +1 -1
- package/dist/esm/services/agr-info/schemas/joomlaGenerate.js.map +1 -1
- package/dist/esm/services/agr-info/schemas/microservices.d.ts +9 -9
- package/dist/esm/services/agr-info/schemas/microservices.d.ts.map +1 -1
- package/dist/esm/services/agr-info/schemas/microservices.js +1 -1
- package/dist/esm/services/agr-info/schemas/microservices.js.map +1 -1
- package/dist/esm/services/agr-info/schemas/rubrics.d.ts +1 -1
- package/dist/esm/services/agr-info/schemas/rubrics.d.ts.map +1 -1
- package/dist/esm/services/agr-info/schemas/rubrics.js +1 -1
- package/dist/esm/services/agr-info/schemas/rubrics.js.map +1 -1
- package/dist/esm/services/agr-info/schemas.d.ts +12 -12
- package/dist/esm/services/agr-info/schemas.d.ts.map +1 -1
- package/dist/esm/services/agr-info/schemas.js +4 -4
- package/dist/esm/services/agr-info/schemas.js.map +1 -1
- package/dist/esm/services/commerce/client.d.ts +1 -1
- package/dist/esm/services/commerce/schemas/cart.d.ts +16 -16
- package/dist/esm/services/items/client.d.ts +4 -36
- package/dist/esm/services/items/client.d.ts.map +1 -1
- package/dist/esm/services/items/schemas/invMast.d.ts +17 -17
- package/dist/esm/services/items/schemas/invMast.js +1 -1
- package/dist/esm/services/items/schemas/invMast.js.map +1 -1
- package/dist/esm/services/items/schemas/invMastLocationsBins.d.ts +20 -148
- package/dist/esm/services/items/schemas/invMastLocationsBins.d.ts.map +1 -1
- package/dist/esm/services/items/schemas/invMastLocationsBins.js +10 -10
- package/dist/esm/services/items/schemas/invMastLocationsBins.js.map +1 -1
- package/dist/esm/services/joomla/client.d.ts +41 -53
- package/dist/esm/services/joomla/client.d.ts.map +1 -1
- package/dist/esm/services/joomla/schemas/content.d.ts +15 -15
- package/dist/esm/services/joomla/schemas/content.d.ts.map +1 -1
- package/dist/esm/services/joomla/schemas/content.js +1 -1
- package/dist/esm/services/joomla/schemas/content.js.map +1 -1
- package/dist/esm/services/joomla/schemas/contentId.d.ts +7 -7
- package/dist/esm/services/joomla/schemas/contentId.d.ts.map +1 -1
- package/dist/esm/services/joomla/schemas/contentId.js +1 -1
- package/dist/esm/services/joomla/schemas/contentId.js.map +1 -1
- package/dist/esm/services/joomla/schemas/contentIdDoc.d.ts +7 -7
- package/dist/esm/services/joomla/schemas/contentIdDoc.d.ts.map +1 -1
- package/dist/esm/services/joomla/schemas/contentIdDoc.js +1 -1
- package/dist/esm/services/joomla/schemas/contentIdDoc.js.map +1 -1
- package/dist/esm/services/joomla/schemas/healthCheck.d.ts +22 -14
- package/dist/esm/services/joomla/schemas/healthCheck.d.ts.map +1 -1
- package/dist/esm/services/joomla/schemas/healthCheck.js +1 -1
- package/dist/esm/services/joomla/schemas/healthCheck.js.map +1 -1
- package/dist/esm/services/joomla/schemas/tags.d.ts +13 -13
- package/dist/esm/services/joomla/schemas/tags.d.ts.map +1 -1
- package/dist/esm/services/joomla/schemas/tags.js +1 -1
- package/dist/esm/services/joomla/schemas/tags.js.map +1 -1
- package/dist/esm/services/joomla/schemas/userGroups.d.ts +141 -141
- package/dist/esm/services/joomla/schemas/userGroups.d.ts.map +1 -1
- package/dist/esm/services/joomla/schemas/userGroups.js +2 -2
- package/dist/esm/services/joomla/schemas/userGroups.js.map +1 -1
- package/dist/esm/services/joomla/schemas/users.d.ts +34 -34
- package/dist/esm/services/joomla/schemas/users.d.ts.map +1 -1
- package/dist/esm/services/joomla/schemas/users.js +2 -2
- package/dist/esm/services/joomla/schemas/users.js.map +1 -1
- package/dist/esm/services/joomla/schemas/usersId.d.ts +87 -250
- package/dist/esm/services/joomla/schemas/usersId.d.ts.map +1 -1
- package/dist/esm/services/joomla/schemas/usersId.js +7 -17
- package/dist/esm/services/joomla/schemas/usersId.js.map +1 -1
- package/dist/esm/services/joomla/schemas/usersIdDoc.d.ts +133 -180
- package/dist/esm/services/joomla/schemas/usersIdDoc.d.ts.map +1 -1
- package/dist/esm/services/joomla/schemas/usersIdDoc.js +8 -15
- package/dist/esm/services/joomla/schemas/usersIdDoc.js.map +1 -1
- package/dist/esm/services/joomla/schemas/usersIdGroups.d.ts +14 -14
- package/dist/esm/services/joomla/schemas/usersIdGroups.d.ts.map +1 -1
- package/dist/esm/services/joomla/schemas/usersIdGroups.js +2 -2
- package/dist/esm/services/joomla/schemas/usersIdGroups.js.map +1 -1
- package/dist/esm/services/joomla/schemas/usersIdTrinity.d.ts +281 -97
- package/dist/esm/services/joomla/schemas/usersIdTrinity.d.ts.map +1 -1
- package/dist/esm/services/joomla/schemas/usersIdTrinity.js +2 -2
- package/dist/esm/services/joomla/schemas/usersIdTrinity.js.map +1 -1
- package/dist/esm/services/joomla/schemas/usersVerifyPassword.d.ts +43 -35
- package/dist/esm/services/joomla/schemas/usersVerifyPassword.d.ts.map +1 -1
- package/dist/esm/services/joomla/schemas/usersVerifyPassword.js +2 -2
- package/dist/esm/services/joomla/schemas/usersVerifyPassword.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/services/agr-info/client.d.ts +9 -9
- package/dist/types/services/agr-info/schemas/akashaGenerate.d.ts +1 -1
- package/dist/types/services/agr-info/schemas/akashaGenerate.d.ts.map +1 -1
- package/dist/types/services/agr-info/schemas/joomlaGenerate.d.ts +1 -1
- package/dist/types/services/agr-info/schemas/joomlaGenerate.d.ts.map +1 -1
- package/dist/types/services/agr-info/schemas/microservices.d.ts +9 -9
- package/dist/types/services/agr-info/schemas/microservices.d.ts.map +1 -1
- package/dist/types/services/agr-info/schemas/rubrics.d.ts +1 -1
- package/dist/types/services/agr-info/schemas/rubrics.d.ts.map +1 -1
- package/dist/types/services/agr-info/schemas.d.ts +12 -12
- package/dist/types/services/agr-info/schemas.d.ts.map +1 -1
- package/dist/types/services/commerce/client.d.ts +1 -1
- package/dist/types/services/commerce/schemas/cart.d.ts +16 -16
- package/dist/types/services/items/client.d.ts +4 -36
- package/dist/types/services/items/client.d.ts.map +1 -1
- package/dist/types/services/items/schemas/invMast.d.ts +17 -17
- package/dist/types/services/items/schemas/invMastLocationsBins.d.ts +20 -148
- package/dist/types/services/items/schemas/invMastLocationsBins.d.ts.map +1 -1
- package/dist/types/services/joomla/client.d.ts +41 -53
- package/dist/types/services/joomla/client.d.ts.map +1 -1
- package/dist/types/services/joomla/schemas/content.d.ts +15 -15
- package/dist/types/services/joomla/schemas/content.d.ts.map +1 -1
- package/dist/types/services/joomla/schemas/contentId.d.ts +7 -7
- package/dist/types/services/joomla/schemas/contentId.d.ts.map +1 -1
- package/dist/types/services/joomla/schemas/contentIdDoc.d.ts +7 -7
- package/dist/types/services/joomla/schemas/contentIdDoc.d.ts.map +1 -1
- package/dist/types/services/joomla/schemas/healthCheck.d.ts +22 -14
- package/dist/types/services/joomla/schemas/healthCheck.d.ts.map +1 -1
- package/dist/types/services/joomla/schemas/tags.d.ts +13 -13
- package/dist/types/services/joomla/schemas/tags.d.ts.map +1 -1
- package/dist/types/services/joomla/schemas/userGroups.d.ts +141 -141
- package/dist/types/services/joomla/schemas/userGroups.d.ts.map +1 -1
- package/dist/types/services/joomla/schemas/users.d.ts +34 -34
- package/dist/types/services/joomla/schemas/users.d.ts.map +1 -1
- package/dist/types/services/joomla/schemas/usersId.d.ts +87 -250
- package/dist/types/services/joomla/schemas/usersId.d.ts.map +1 -1
- package/dist/types/services/joomla/schemas/usersIdDoc.d.ts +133 -180
- package/dist/types/services/joomla/schemas/usersIdDoc.d.ts.map +1 -1
- package/dist/types/services/joomla/schemas/usersIdGroups.d.ts +14 -14
- package/dist/types/services/joomla/schemas/usersIdGroups.d.ts.map +1 -1
- package/dist/types/services/joomla/schemas/usersIdTrinity.d.ts +281 -97
- package/dist/types/services/joomla/schemas/usersIdTrinity.d.ts.map +1 -1
- package/dist/types/services/joomla/schemas/usersVerifyPassword.d.ts +43 -35
- package/dist/types/services/joomla/schemas/usersVerifyPassword.d.ts.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,887 @@
|
|
|
1
|
+
# Augur API Tips and Tricks
|
|
2
|
+
|
|
3
|
+
This document contains advanced usage patterns, performance optimizations, and helpful techniques for working with the Augur API client library.
|
|
4
|
+
|
|
5
|
+
## 🔍 Finding Items by ItemId
|
|
6
|
+
|
|
7
|
+
### Problem: You have an itemId but need the invMastUid
|
|
8
|
+
|
|
9
|
+
When you only have a Prophet 21 itemId (like `WIRE-12-AWG-250FT`) but need the internal `invMastUid` for database operations:
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
// ✅ Use invMastUid = 0 with itemId as query pattern
|
|
13
|
+
const itemLookup = await api.items.invMast.doc.get(0, {
|
|
14
|
+
q: 'WIRE-12-AWG-250FT' // Your actual itemId
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
// Extract the invMastUid for future direct lookups
|
|
18
|
+
const invMastUid = itemLookup.data.invMastUid;
|
|
19
|
+
|
|
20
|
+
// Now use the invMastUid for efficient direct access
|
|
21
|
+
const itemDetails = await api.items.invMast.get(invMastUid);
|
|
22
|
+
const locations = await api.items.invMast.locations.list(invMastUid);
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Why this works
|
|
26
|
+
- The Items service recognizes `invMastUid = 0` as a special lookup case
|
|
27
|
+
- It searches the `item_id` field instead of using direct UID lookup
|
|
28
|
+
- Returns the complete document including the actual `invMastUid`
|
|
29
|
+
- This is the most efficient way to bridge itemId → invMastUid
|
|
30
|
+
|
|
31
|
+
## 🚀 Performance Optimization
|
|
32
|
+
|
|
33
|
+
### Smart Caching Strategies
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
// ✅ Cache stable reference data with longer TTL
|
|
37
|
+
const categories = await api.items.categories.list({
|
|
38
|
+
edgeCache: 8 // 8 hours - categories rarely change
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const brands = await api.items.brands.list({
|
|
42
|
+
edgeCache: 12 // 12 hours - brand data is very stable
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// ✅ Shorter cache for semi-dynamic data
|
|
46
|
+
const inventory = await api.items.invMast.get(invMastUid, {
|
|
47
|
+
edgeCache: 2 // 2 hours - inventory levels change regularly
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// ✅ Very short cache for user-specific data
|
|
51
|
+
const userCart = await api.commerce.cartHeaders.list({
|
|
52
|
+
userId: 123,
|
|
53
|
+
edgeCache: 0.5 // 30 minutes - cart changes frequently
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// ❌ Don't cache authentication or real-time operations
|
|
57
|
+
const authCheck = await api.joomla.users.verifyPassword({
|
|
58
|
+
username: 'user',
|
|
59
|
+
password: 'pass'
|
|
60
|
+
// No edgeCache - authentication must be real-time
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Batch Operations for Better Performance
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
// ✅ Get multiple items efficiently
|
|
68
|
+
const itemPromises = invMastUids.map(uid =>
|
|
69
|
+
api.items.invMast.get(uid, { edgeCache: 2 })
|
|
70
|
+
);
|
|
71
|
+
const items = await Promise.all(itemPromises);
|
|
72
|
+
|
|
73
|
+
// ✅ Use parallel requests for independent data
|
|
74
|
+
const [categories, brands, attributes] = await Promise.all([
|
|
75
|
+
api.items.categories.list({ edgeCache: 8 }),
|
|
76
|
+
api.items.brands.list({ edgeCache: 8 }),
|
|
77
|
+
api.items.attributes.list({ edgeCache: 6 })
|
|
78
|
+
]);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## 🔄 Cross-Service Data Patterns
|
|
82
|
+
|
|
83
|
+
### Order → Item Details Workflow
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
// Get order details
|
|
87
|
+
const order = await api.orders.oeHdr.get(orderNo);
|
|
88
|
+
const orderLines = await api.orders.oeHdr.lines.list(orderNo);
|
|
89
|
+
|
|
90
|
+
// Extract item IDs from order lines and get detailed item info
|
|
91
|
+
const itemDetailsPromises = orderLines.data.map(async (line) => {
|
|
92
|
+
// Use the itemId to invMastUid lookup pattern
|
|
93
|
+
const itemLookup = await api.items.invMast.doc.get(0, {
|
|
94
|
+
q: line.itemId
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
orderLine: line,
|
|
99
|
+
itemDetails: await api.items.invMast.get(itemLookup.data.invMastUid),
|
|
100
|
+
locations: await api.items.invMast.locations.list(itemLookup.data.invMastUid)
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const enrichedOrderLines = await Promise.all(itemDetailsPromises);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Customer → Purchased Items → Recommendations
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// Get customer's purchase history
|
|
111
|
+
const customerId = 12345;
|
|
112
|
+
const purchasedItems = await api.customers.customer.purchasedItems.list(customerId, {
|
|
113
|
+
limit: 50,
|
|
114
|
+
edgeCache: 1 // Recent purchases change frequently
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// Find similar items for recommendations using OpenSearch
|
|
118
|
+
const recommendationPromises = purchasedItems.data.slice(0, 5).map(async (item) => {
|
|
119
|
+
return api.openSearch.itemSearch.search({
|
|
120
|
+
q: item.itemId,
|
|
121
|
+
searchType: 'similarity',
|
|
122
|
+
size: 3,
|
|
123
|
+
edgeCache: 4 // Similarity results are relatively stable
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const recommendations = await Promise.all(recommendationPromises);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## 🛠 Error Handling Patterns
|
|
131
|
+
|
|
132
|
+
### Graceful Degradation
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
async function getItemWithFallback(itemIdentifier: string | number) {
|
|
136
|
+
try {
|
|
137
|
+
// Try direct invMastUid lookup first
|
|
138
|
+
if (typeof itemIdentifier === 'number') {
|
|
139
|
+
return await api.items.invMast.get(itemIdentifier);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Fallback to itemId lookup
|
|
143
|
+
const itemLookup = await api.items.invMast.doc.get(0, {
|
|
144
|
+
q: itemIdentifier
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
return await api.items.invMast.get(itemLookup.data.invMastUid);
|
|
148
|
+
|
|
149
|
+
} catch (error) {
|
|
150
|
+
// Final fallback to search
|
|
151
|
+
console.warn(`Direct lookup failed for ${itemIdentifier}, trying search...`);
|
|
152
|
+
|
|
153
|
+
const searchResults = await api.openSearch.itemSearch.search({
|
|
154
|
+
q: itemIdentifier.toString(),
|
|
155
|
+
searchType: 'query',
|
|
156
|
+
size: 1
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
if (searchResults.data.length === 0) {
|
|
160
|
+
throw new Error(`Item not found: ${itemIdentifier}`);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return searchResults.data[0];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Request Timeout Handling
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import { AbortController } from 'node-abort-controller';
|
|
172
|
+
|
|
173
|
+
async function getItemWithTimeout(invMastUid: number, timeoutMs = 5000) {
|
|
174
|
+
const controller = new AbortController();
|
|
175
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
176
|
+
|
|
177
|
+
try {
|
|
178
|
+
const result = await api.items.invMast.get(invMastUid, {}, {
|
|
179
|
+
signal: controller.signal
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
clearTimeout(timeoutId);
|
|
183
|
+
return result;
|
|
184
|
+
|
|
185
|
+
} catch (error) {
|
|
186
|
+
clearTimeout(timeoutId);
|
|
187
|
+
if (error.name === 'AbortError') {
|
|
188
|
+
throw new Error(`Request timed out after ${timeoutMs}ms`);
|
|
189
|
+
}
|
|
190
|
+
throw error;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## 🔐 Authentication Patterns
|
|
196
|
+
|
|
197
|
+
### Cross-Site Authentication
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
// Set up cross-site authentication for multi-tenant scenarios
|
|
201
|
+
const api = createAugurApiClient({
|
|
202
|
+
baseUrl: 'https://api.example.com',
|
|
203
|
+
authToken: 'your-jwt-token',
|
|
204
|
+
siteId: 'site-specific-id' // For cross-site operations
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Use with services that support cross-site operations
|
|
208
|
+
const siteSpecificUsers = await api.joomla.users.list({
|
|
209
|
+
limit: 50
|
|
210
|
+
// siteId is automatically included in headers
|
|
211
|
+
});
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Token Refresh Pattern
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
class ApiManager {
|
|
218
|
+
private client: AugurApiClient;
|
|
219
|
+
private refreshTokenIfNeeded: () => Promise<string>;
|
|
220
|
+
|
|
221
|
+
constructor(refreshCallback: () => Promise<string>) {
|
|
222
|
+
this.refreshTokenIfNeeded = refreshCallback;
|
|
223
|
+
this.client = createAugurApiClient({
|
|
224
|
+
baseUrl: 'https://api.example.com'
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
async makeAuthenticatedRequest<T>(
|
|
229
|
+
request: (client: AugurApiClient) => Promise<T>
|
|
230
|
+
): Promise<T> {
|
|
231
|
+
try {
|
|
232
|
+
return await request(this.client);
|
|
233
|
+
} catch (error) {
|
|
234
|
+
if (error.response?.status === 401) {
|
|
235
|
+
// Token expired, refresh and retry
|
|
236
|
+
const newToken = await this.refreshTokenIfNeeded();
|
|
237
|
+
this.client.updateAuthToken(newToken);
|
|
238
|
+
return await request(this.client);
|
|
239
|
+
}
|
|
240
|
+
throw error;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## 📊 Data Transformation Helpers
|
|
247
|
+
|
|
248
|
+
### Prophet 21 to Application Models
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
// Transform P21 data structures to application-friendly formats
|
|
252
|
+
function transformInventoryItem(p21Item: any) {
|
|
253
|
+
return {
|
|
254
|
+
id: p21Item.invMastUid,
|
|
255
|
+
itemId: p21Item.itemId,
|
|
256
|
+
description: p21Item.itemDesc,
|
|
257
|
+
price: p21Item.listPrice,
|
|
258
|
+
availability: {
|
|
259
|
+
inStock: p21Item.qtyOnHand > 0,
|
|
260
|
+
quantity: p21Item.qtyOnHand,
|
|
261
|
+
locations: p21Item.locations?.map(loc => ({
|
|
262
|
+
warehouse: loc.locationId,
|
|
263
|
+
bin: loc.bin,
|
|
264
|
+
quantity: loc.qtyOnHand
|
|
265
|
+
})) || []
|
|
266
|
+
},
|
|
267
|
+
category: {
|
|
268
|
+
id: p21Item.itemCategoryUid,
|
|
269
|
+
name: p21Item.categoryName
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Use with API responses
|
|
275
|
+
const rawItem = await api.items.invMast.get(invMastUid);
|
|
276
|
+
const transformedItem = transformInventoryItem(rawItem.data);
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## 🧪 Testing Patterns
|
|
280
|
+
|
|
281
|
+
### Mock API Responses
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
// Create mock client for testing
|
|
285
|
+
const mockApi = {
|
|
286
|
+
items: {
|
|
287
|
+
invMast: {
|
|
288
|
+
get: jest.fn().mockResolvedValue({
|
|
289
|
+
status: 200,
|
|
290
|
+
data: { invMastUid: 123, itemId: 'TEST-ITEM' }
|
|
291
|
+
}),
|
|
292
|
+
doc: {
|
|
293
|
+
get: jest.fn().mockResolvedValue({
|
|
294
|
+
status: 200,
|
|
295
|
+
data: { invMastUid: 123, itemId: 'TEST-ITEM' }
|
|
296
|
+
})
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
// Test the itemId lookup pattern
|
|
303
|
+
test('should find item by itemId', async () => {
|
|
304
|
+
const result = await getItemByItemId('TEST-ITEM');
|
|
305
|
+
expect(mockApi.items.invMast.doc.get).toHaveBeenCalledWith(0, {
|
|
306
|
+
q: 'TEST-ITEM'
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## 🎯 Common Use Cases
|
|
312
|
+
|
|
313
|
+
### E-commerce Product Catalog
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
// Build complete product catalog with all necessary data
|
|
317
|
+
async function buildProductCatalog(categoryIds: number[]) {
|
|
318
|
+
const [categories, brands, attributes] = await Promise.all([
|
|
319
|
+
api.items.categories.list({ edgeCache: 8 }),
|
|
320
|
+
api.items.brands.list({ edgeCache: 8 }),
|
|
321
|
+
api.items.attributes.list({ edgeCache: 6 })
|
|
322
|
+
]);
|
|
323
|
+
|
|
324
|
+
const products = [];
|
|
325
|
+
|
|
326
|
+
for (const categoryId of categoryIds) {
|
|
327
|
+
const categoryItems = await api.openSearch.itemSearch.search({
|
|
328
|
+
itemCategoryUidList: categoryId.toString(),
|
|
329
|
+
searchType: 'query',
|
|
330
|
+
size: 100,
|
|
331
|
+
edgeCache: 4
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
const enrichedItems = await Promise.all(
|
|
335
|
+
categoryItems.data.map(async (item) => ({
|
|
336
|
+
...item,
|
|
337
|
+
locations: await api.items.invMast.locations.list(item.invMastUid, {
|
|
338
|
+
edgeCache: 2
|
|
339
|
+
}),
|
|
340
|
+
alternates: await api.items.invMast.alternateCode.list(item.invMastUid, {
|
|
341
|
+
edgeCache: 4
|
|
342
|
+
})
|
|
343
|
+
}))
|
|
344
|
+
);
|
|
345
|
+
|
|
346
|
+
products.push(...enrichedItems);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return { products, categories: categories.data, brands: brands.data };
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Inventory Management Dashboard
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
// Real-time inventory status across multiple locations
|
|
357
|
+
async function getInventoryDashboard(itemIds: string[]) {
|
|
358
|
+
const inventoryData = await Promise.all(
|
|
359
|
+
itemIds.map(async (itemId) => {
|
|
360
|
+
// Use the special lookup pattern
|
|
361
|
+
const itemLookup = await api.items.invMast.doc.get(0, { q: itemId });
|
|
362
|
+
const invMastUid = itemLookup.data.invMastUid;
|
|
363
|
+
|
|
364
|
+
const [details, locations, movements] = await Promise.all([
|
|
365
|
+
api.items.invMast.get(invMastUid, { edgeCache: 1 }),
|
|
366
|
+
api.items.invMast.locations.list(invMastUid, { edgeCache: 0.5 }),
|
|
367
|
+
// Get recent activity (if available in your setup)
|
|
368
|
+
api.legacy.inventory.activity?.(itemId) || Promise.resolve({ data: [] })
|
|
369
|
+
]);
|
|
370
|
+
|
|
371
|
+
return {
|
|
372
|
+
itemId,
|
|
373
|
+
invMastUid,
|
|
374
|
+
details: details.data,
|
|
375
|
+
locations: locations.data,
|
|
376
|
+
totalQuantity: locations.data.reduce((sum, loc) => sum + loc.qtyOnHand, 0),
|
|
377
|
+
recentActivity: movements.data
|
|
378
|
+
};
|
|
379
|
+
})
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
return inventoryData;
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
## 🚀 Advanced Request Patterns
|
|
387
|
+
|
|
388
|
+
### Request Cancellation
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
const controller = new AbortController();
|
|
392
|
+
|
|
393
|
+
// Start a request
|
|
394
|
+
const usersPromise = api.joomla.users.list(
|
|
395
|
+
{ limit: 100 },
|
|
396
|
+
{ signal: controller.signal } // Pass abort signal
|
|
397
|
+
);
|
|
398
|
+
|
|
399
|
+
// Cancel the request if needed
|
|
400
|
+
setTimeout(() => {
|
|
401
|
+
controller.abort();
|
|
402
|
+
}, 5000);
|
|
403
|
+
|
|
404
|
+
try {
|
|
405
|
+
const users = await usersPromise;
|
|
406
|
+
} catch (error) {
|
|
407
|
+
if (error.name === 'AbortError') {
|
|
408
|
+
console.log('Request was cancelled');
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### Custom Headers and Timeouts
|
|
414
|
+
|
|
415
|
+
```typescript
|
|
416
|
+
// Per-request configuration
|
|
417
|
+
const users = await api.joomla.users.list(
|
|
418
|
+
{ limit: 20 },
|
|
419
|
+
{
|
|
420
|
+
timeout: 10000, // 10 second timeout
|
|
421
|
+
headers: {
|
|
422
|
+
'X-Custom-Header': 'value',
|
|
423
|
+
'X-Request-ID': 'unique-id'
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
);
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Middleware Integration
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
// Add global request/response interceptors
|
|
433
|
+
const api = new AugurAPI({
|
|
434
|
+
siteId: 'your-site-id',
|
|
435
|
+
bearerToken: 'your-token',
|
|
436
|
+
|
|
437
|
+
// Request interceptor
|
|
438
|
+
onRequest: (config) => {
|
|
439
|
+
console.log(`Making request to: ${config.url}`);
|
|
440
|
+
config.headers['X-Request-Timestamp'] = Date.now().toString();
|
|
441
|
+
return config;
|
|
442
|
+
},
|
|
443
|
+
|
|
444
|
+
// Response interceptor
|
|
445
|
+
onResponse: (response) => {
|
|
446
|
+
console.log(`Response status: ${response.status}`);
|
|
447
|
+
return response;
|
|
448
|
+
},
|
|
449
|
+
|
|
450
|
+
// Error interceptor
|
|
451
|
+
onError: (error) => {
|
|
452
|
+
console.error('API Error:', error.message);
|
|
453
|
+
// Custom error handling logic
|
|
454
|
+
throw error;
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
## 🏗 Framework Integration Patterns
|
|
460
|
+
|
|
461
|
+
### React Hook Pattern
|
|
462
|
+
|
|
463
|
+
```tsx
|
|
464
|
+
import React, { useState, useEffect } from 'react';
|
|
465
|
+
import { AugurAPI, User, AugurAPIError, type AugurContext } from '@simpleapps-com/augur-api';
|
|
466
|
+
|
|
467
|
+
// Custom hook for Augur API - Context-aware approach
|
|
468
|
+
function useAugurAPI(context?: AugurContext) {
|
|
469
|
+
const [api] = useState(() => {
|
|
470
|
+
if (context) {
|
|
471
|
+
// Use context-aware creation (recommended)
|
|
472
|
+
return AugurAPI.fromContext(context);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Fallback to manual configuration
|
|
476
|
+
return new AugurAPI({
|
|
477
|
+
siteId: process.env.REACT_APP_AUGUR_SITE_ID!,
|
|
478
|
+
bearerToken: getStoredToken()
|
|
479
|
+
});
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
return api;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// Component using the API
|
|
486
|
+
const UserList: React.FC = () => {
|
|
487
|
+
const api = useAugurAPI();
|
|
488
|
+
const [users, setUsers] = useState<User[]>([]);
|
|
489
|
+
const [loading, setLoading] = useState(true);
|
|
490
|
+
const [error, setError] = useState<string | null>(null);
|
|
491
|
+
|
|
492
|
+
useEffect(() => {
|
|
493
|
+
async function fetchUsers() {
|
|
494
|
+
try {
|
|
495
|
+
setLoading(true);
|
|
496
|
+
setError(null);
|
|
497
|
+
|
|
498
|
+
const response = await api.joomla.users.list({
|
|
499
|
+
limit: 50,
|
|
500
|
+
edgeCache: 2 // Cache for 2 hours
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
setUsers(response.data);
|
|
504
|
+
} catch (err) {
|
|
505
|
+
setError(err instanceof Error ? err.message : 'Unknown error');
|
|
506
|
+
} finally {
|
|
507
|
+
setLoading(false);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
fetchUsers();
|
|
512
|
+
}, [api]);
|
|
513
|
+
|
|
514
|
+
if (loading) return <div>Loading...</div>;
|
|
515
|
+
if (error) return <div>Error: {error}</div>;
|
|
516
|
+
|
|
517
|
+
return (
|
|
518
|
+
<ul>
|
|
519
|
+
{users.map(user => (
|
|
520
|
+
<li key={user.id}>{user.username}</li>
|
|
521
|
+
))}
|
|
522
|
+
</ul>
|
|
523
|
+
);
|
|
524
|
+
};
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
### Next.js API Route Integration
|
|
528
|
+
|
|
529
|
+
```typescript
|
|
530
|
+
// pages/api/users.ts
|
|
531
|
+
import type { NextApiRequest, NextApiResponse } from 'next';
|
|
532
|
+
import { AugurAPI } from '@simpleapps-com/augur-api';
|
|
533
|
+
|
|
534
|
+
const api = new AugurAPI({
|
|
535
|
+
siteId: process.env.AUGUR_SITE_ID!,
|
|
536
|
+
bearerToken: process.env.AUGUR_TOKEN!
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
export default async function handler(
|
|
540
|
+
req: NextApiRequest,
|
|
541
|
+
res: NextApiResponse
|
|
542
|
+
) {
|
|
543
|
+
try {
|
|
544
|
+
const { limit = 10, offset = 0 } = req.query;
|
|
545
|
+
|
|
546
|
+
const users = await api.joomla.users.list({
|
|
547
|
+
limit: parseInt(limit as string),
|
|
548
|
+
offset: parseInt(offset as string),
|
|
549
|
+
edgeCache: 4 // 4 hours for server-side caching
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
res.status(200).json(users);
|
|
553
|
+
|
|
554
|
+
} catch (error) {
|
|
555
|
+
console.error('API Error:', error);
|
|
556
|
+
res.status(500).json({ error: 'Failed to fetch users' });
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
### React Native Pattern
|
|
562
|
+
|
|
563
|
+
```typescript
|
|
564
|
+
// useAugurAPI.ts - React Native hook
|
|
565
|
+
import { useState, useEffect } from 'react';
|
|
566
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
567
|
+
import { AugurAPI } from '@simpleapps-com/augur-api';
|
|
568
|
+
|
|
569
|
+
export function useAugurAPI() {
|
|
570
|
+
const [api, setApi] = useState<AugurAPI | null>(null);
|
|
571
|
+
const [isReady, setIsReady] = useState(false);
|
|
572
|
+
|
|
573
|
+
useEffect(() => {
|
|
574
|
+
async function initializeAPI() {
|
|
575
|
+
try {
|
|
576
|
+
const [siteId, token] = await Promise.all([
|
|
577
|
+
AsyncStorage.getItem('augur_site_id'),
|
|
578
|
+
AsyncStorage.getItem('augur_token')
|
|
579
|
+
]);
|
|
580
|
+
|
|
581
|
+
if (siteId && token) {
|
|
582
|
+
const apiInstance = new AugurAPI({
|
|
583
|
+
siteId,
|
|
584
|
+
bearerToken: token
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
setApi(apiInstance);
|
|
588
|
+
}
|
|
589
|
+
} catch (error) {
|
|
590
|
+
console.error('Failed to initialize API:', error);
|
|
591
|
+
} finally {
|
|
592
|
+
setIsReady(true);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
initializeAPI();
|
|
597
|
+
}, []);
|
|
598
|
+
|
|
599
|
+
return { api, isReady };
|
|
600
|
+
}
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
## 🛡️ Advanced Error Handling
|
|
604
|
+
|
|
605
|
+
### Comprehensive Error Handling Pattern
|
|
606
|
+
|
|
607
|
+
```typescript
|
|
608
|
+
import {
|
|
609
|
+
AugurAPIError,
|
|
610
|
+
AuthenticationError,
|
|
611
|
+
ValidationError,
|
|
612
|
+
NotFoundError,
|
|
613
|
+
RateLimitError,
|
|
614
|
+
NetworkError
|
|
615
|
+
} from '@simpleapps-com/augur-api';
|
|
616
|
+
|
|
617
|
+
async function handleAPICall() {
|
|
618
|
+
try {
|
|
619
|
+
const result = await api.joomla.users.list({ limit: 10 });
|
|
620
|
+
return result;
|
|
621
|
+
|
|
622
|
+
} catch (error) {
|
|
623
|
+
// Handle specific error types
|
|
624
|
+
if (error instanceof AuthenticationError) {
|
|
625
|
+
console.error('Authentication failed:', error.message);
|
|
626
|
+
|
|
627
|
+
switch (error.statusCode) {
|
|
628
|
+
case 401:
|
|
629
|
+
await refreshToken();
|
|
630
|
+
break;
|
|
631
|
+
default:
|
|
632
|
+
redirectToLogin();
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
} else if (error instanceof ValidationError) {
|
|
636
|
+
console.error('Request validation failed:', error.validationErrors);
|
|
637
|
+
|
|
638
|
+
error.validationErrors?.forEach(validationError => {
|
|
639
|
+
console.error(`Field ${validationError.path}: ${validationError.message}`);
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
} else if (error instanceof NotFoundError) {
|
|
643
|
+
console.error('Resource not found:', error.message);
|
|
644
|
+
showNotFoundMessage(error.endpoint);
|
|
645
|
+
|
|
646
|
+
} else if (error instanceof RateLimitError) {
|
|
647
|
+
console.error('Rate limit exceeded:', error.message);
|
|
648
|
+
|
|
649
|
+
// Implement exponential backoff
|
|
650
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
651
|
+
return handleAPICall(); // Retry
|
|
652
|
+
|
|
653
|
+
} else if (error instanceof AugurAPIError) {
|
|
654
|
+
console.error('API error:', {
|
|
655
|
+
code: error.code,
|
|
656
|
+
message: error.message,
|
|
657
|
+
service: error.service,
|
|
658
|
+
endpoint: error.endpoint,
|
|
659
|
+
statusCode: error.statusCode,
|
|
660
|
+
requestId: error.requestId
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
switch (error.statusCode) {
|
|
664
|
+
case 500:
|
|
665
|
+
showErrorMessage('Server error. Please try again later.');
|
|
666
|
+
break;
|
|
667
|
+
case 503:
|
|
668
|
+
showErrorMessage('Service temporarily unavailable.');
|
|
669
|
+
break;
|
|
670
|
+
default:
|
|
671
|
+
showErrorMessage(`API error: ${error.message}`);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
throw error; // Re-throw if needed
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
### Retry Logic with Exponential Backoff
|
|
681
|
+
|
|
682
|
+
```typescript
|
|
683
|
+
async function apiCallWithRetry<T>(
|
|
684
|
+
operation: () => Promise<T>,
|
|
685
|
+
maxRetries = 3,
|
|
686
|
+
baseDelay = 1000
|
|
687
|
+
): Promise<T> {
|
|
688
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
689
|
+
try {
|
|
690
|
+
return await operation();
|
|
691
|
+
|
|
692
|
+
} catch (error) {
|
|
693
|
+
// Don't retry on authentication or validation errors
|
|
694
|
+
if (error instanceof AuthenticationError ||
|
|
695
|
+
error instanceof ValidationError) {
|
|
696
|
+
throw error;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// Don't retry on final attempt
|
|
700
|
+
if (attempt === maxRetries) {
|
|
701
|
+
throw error;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// Calculate delay with exponential backoff
|
|
705
|
+
const delay = baseDelay * Math.pow(2, attempt - 1);
|
|
706
|
+
console.log(`Attempt ${attempt} failed, retrying in ${delay}ms...`);
|
|
707
|
+
|
|
708
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
throw new Error('All retry attempts exhausted');
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// Usage
|
|
716
|
+
const users = await apiCallWithRetry(() =>
|
|
717
|
+
api.joomla.users.list({ limit: 10 })
|
|
718
|
+
);
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
### Global Error Handler
|
|
722
|
+
|
|
723
|
+
```typescript
|
|
724
|
+
class ErrorHandler {
|
|
725
|
+
static handle(error: unknown, context?: string): void {
|
|
726
|
+
const contextPrefix = context ? `[${context}] ` : '';
|
|
727
|
+
|
|
728
|
+
if (error instanceof AuthenticationError) {
|
|
729
|
+
console.error(`${contextPrefix}Authentication failed:`, error.message);
|
|
730
|
+
this.handleAuthError(error);
|
|
731
|
+
|
|
732
|
+
} else if (error instanceof ValidationError) {
|
|
733
|
+
console.error(`${contextPrefix}Validation failed:`, error.validationErrors);
|
|
734
|
+
this.handleValidationError(error);
|
|
735
|
+
|
|
736
|
+
} else if (error instanceof AugurAPIError) {
|
|
737
|
+
console.error(`${contextPrefix}API error:`, {
|
|
738
|
+
service: error.service,
|
|
739
|
+
endpoint: error.endpoint,
|
|
740
|
+
status: error.statusCode,
|
|
741
|
+
message: error.message
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
this.handleAPIError(error);
|
|
745
|
+
|
|
746
|
+
} else {
|
|
747
|
+
console.error(`${contextPrefix}Unexpected error:`, error);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
private static handleAuthError(error: AuthenticationError) {
|
|
752
|
+
// Implement token refresh logic
|
|
753
|
+
if (typeof window !== 'undefined') {
|
|
754
|
+
window.location.href = '/login';
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
private static handleValidationError(error: ValidationError) {
|
|
759
|
+
// Show user-friendly validation messages
|
|
760
|
+
if (error.validationErrors) {
|
|
761
|
+
error.validationErrors.forEach(err => {
|
|
762
|
+
showFieldError(err.path, err.message);
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
private static handleAPIError(error: AugurAPIError) {
|
|
768
|
+
// Log to monitoring service
|
|
769
|
+
if (typeof window !== 'undefined' && window.analytics) {
|
|
770
|
+
window.analytics.track('API Error', {
|
|
771
|
+
service: error.service,
|
|
772
|
+
endpoint: error.endpoint,
|
|
773
|
+
statusCode: error.statusCode
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
## 🏎️ Advanced Caching Strategies
|
|
781
|
+
|
|
782
|
+
### Edge Cache Duration Guide
|
|
783
|
+
|
|
784
|
+
| Value | Duration | Best For | Example Use Cases |
|
|
785
|
+
|-------|----------|----------|-------------------|
|
|
786
|
+
| `1` | 1 hour | Frequently changing data | Cart contents, user sessions, real-time pricing |
|
|
787
|
+
| `2` | 2 hours | Moderate volatility | User lists, inventory levels, order status |
|
|
788
|
+
| `3` | 3 hours | Standard business data | Standard pricing, product information, customer data |
|
|
789
|
+
| `4` | 4 hours | Semi-static data | Recommendations, warehouse data, shipping rates |
|
|
790
|
+
| `5` | 5 hours | Reference data | Tags, categories, attribute lists |
|
|
791
|
+
| `8` | 8 hours | Static content | Brand information, distributor details, system configs |
|
|
792
|
+
|
|
793
|
+
### Smart Cache Implementation
|
|
794
|
+
|
|
795
|
+
```typescript
|
|
796
|
+
// Cache strategy based on data volatility
|
|
797
|
+
class CacheStrategy {
|
|
798
|
+
static getOptimalTTL(dataType: string, context?: any): number {
|
|
799
|
+
switch (dataType) {
|
|
800
|
+
case 'user_session':
|
|
801
|
+
case 'cart_contents':
|
|
802
|
+
case 'real_time_pricing':
|
|
803
|
+
return 1; // 1 hour
|
|
804
|
+
|
|
805
|
+
case 'inventory_levels':
|
|
806
|
+
case 'order_status':
|
|
807
|
+
case 'user_profiles':
|
|
808
|
+
return 2; // 2 hours
|
|
809
|
+
|
|
810
|
+
case 'product_catalog':
|
|
811
|
+
case 'standard_pricing':
|
|
812
|
+
case 'customer_data':
|
|
813
|
+
return 3; // 3 hours
|
|
814
|
+
|
|
815
|
+
case 'recommendations':
|
|
816
|
+
case 'warehouse_locations':
|
|
817
|
+
case 'shipping_rates':
|
|
818
|
+
return 4; // 4 hours
|
|
819
|
+
|
|
820
|
+
case 'categories':
|
|
821
|
+
case 'attributes':
|
|
822
|
+
case 'tags':
|
|
823
|
+
return 5; // 5 hours
|
|
824
|
+
|
|
825
|
+
case 'brands':
|
|
826
|
+
case 'system_config':
|
|
827
|
+
case 'distributor_info':
|
|
828
|
+
return 8; // 8 hours
|
|
829
|
+
|
|
830
|
+
default:
|
|
831
|
+
return 2; // Safe default
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
// Usage in API calls
|
|
837
|
+
const categories = await api.items.categories.list({
|
|
838
|
+
edgeCache: CacheStrategy.getOptimalTTL('categories')
|
|
839
|
+
});
|
|
840
|
+
|
|
841
|
+
const userCart = await api.commerce.cartHeaders.list({
|
|
842
|
+
userId: 123,
|
|
843
|
+
edgeCache: CacheStrategy.getOptimalTTL('cart_contents')
|
|
844
|
+
});
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
### Cache Invalidation Patterns
|
|
848
|
+
|
|
849
|
+
```typescript
|
|
850
|
+
// Cache warming for critical data
|
|
851
|
+
async function warmCache() {
|
|
852
|
+
const criticalData = [
|
|
853
|
+
() => api.items.categories.list({ edgeCache: 8 }),
|
|
854
|
+
() => api.items.brands.list({ edgeCache: 8 }),
|
|
855
|
+
() => api.items.attributes.list({ edgeCache: 5 }),
|
|
856
|
+
];
|
|
857
|
+
|
|
858
|
+
// Warm cache in parallel
|
|
859
|
+
await Promise.all(criticalData.map(fn => fn()));
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// Cache busting for updated data
|
|
863
|
+
async function updateProductAndInvalidateCache(productId: number, updates: any) {
|
|
864
|
+
// Update the product
|
|
865
|
+
await api.items.invMast.update(productId, updates);
|
|
866
|
+
|
|
867
|
+
// Force refresh cached data (edgeCache: 0 bypasses cache)
|
|
868
|
+
const freshData = await api.items.invMast.get(productId, { edgeCache: 0 });
|
|
869
|
+
|
|
870
|
+
return freshData;
|
|
871
|
+
}
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
---
|
|
875
|
+
|
|
876
|
+
## 💡 Pro Tips
|
|
877
|
+
|
|
878
|
+
1. **Always cache reference data** - Categories, brands, and attributes change infrequently
|
|
879
|
+
2. **Use the itemId → invMastUid lookup** - It's the bridge between user-facing IDs and internal UIDs
|
|
880
|
+
3. **Batch related requests** - Use `Promise.all()` for independent parallel requests
|
|
881
|
+
4. **Handle 404s gracefully** - Not all items exist in all systems
|
|
882
|
+
5. **Monitor cache hit rates** - Adjust TTL values based on actual usage patterns
|
|
883
|
+
6. **Use TypeScript** - The client provides full type safety for better development experience
|
|
884
|
+
|
|
885
|
+
---
|
|
886
|
+
|
|
887
|
+
*This document is part of the [Augur API Client Library](./README.md) package and is included in npm distributions for offline reference.*
|