@simpleapps-com/augur-api 0.6.0 → 0.7.1
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 +40 -3740
- package/SKILL.md +160 -0
- package/dist/cjs/client.d.ts +6 -0
- package/dist/cjs/client.d.ts.map +1 -1
- package/dist/cjs/client.js +14 -0
- package/dist/cjs/client.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +4 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/services/agr-site/client.d.ts +9 -1
- package/dist/cjs/services/agr-site/client.d.ts.map +1 -1
- package/dist/cjs/services/agr-site/client.js +4 -0
- package/dist/cjs/services/agr-site/client.js.map +1 -1
- package/dist/cjs/services/agr-site/resources/index.d.ts +2 -0
- package/dist/cjs/services/agr-site/resources/index.d.ts.map +1 -1
- package/dist/cjs/services/agr-site/resources/index.js +7 -1
- package/dist/cjs/services/agr-site/resources/index.js.map +1 -1
- package/dist/cjs/services/agr-site/resources/ping.d.ts +47 -0
- package/dist/cjs/services/agr-site/resources/ping.d.ts.map +1 -0
- package/dist/cjs/services/agr-site/resources/ping.js +57 -0
- package/dist/cjs/services/agr-site/resources/ping.js.map +1 -0
- package/dist/cjs/services/agr-site/resources/whoami.d.ts +45 -0
- package/dist/cjs/services/agr-site/resources/whoami.d.ts.map +1 -0
- package/dist/cjs/services/agr-site/resources/whoami.js +55 -0
- package/dist/cjs/services/agr-site/resources/whoami.js.map +1 -0
- package/dist/cjs/services/agr-site/schemas/index.d.ts +2 -0
- package/dist/cjs/services/agr-site/schemas/index.d.ts.map +1 -1
- package/dist/cjs/services/agr-site/schemas/index.js +2 -0
- package/dist/cjs/services/agr-site/schemas/index.js.map +1 -1
- package/dist/cjs/services/agr-site/schemas/ping.d.ts +16 -0
- package/dist/cjs/services/agr-site/schemas/ping.d.ts.map +1 -0
- package/dist/cjs/services/agr-site/schemas/ping.js +14 -0
- package/dist/cjs/services/agr-site/schemas/ping.js.map +1 -0
- package/dist/cjs/services/agr-site/schemas/whoami.d.ts +16 -0
- package/dist/cjs/services/agr-site/schemas/whoami.d.ts.map +1 -0
- package/dist/cjs/services/agr-site/schemas/whoami.js +14 -0
- package/dist/cjs/services/agr-site/schemas/whoami.js.map +1 -0
- package/dist/cjs/services/basecamp2/client.d.ts +25 -1
- package/dist/cjs/services/basecamp2/client.d.ts.map +1 -1
- package/dist/cjs/services/basecamp2/client.js +14 -2
- package/dist/cjs/services/basecamp2/client.js.map +1 -1
- package/dist/cjs/services/basecamp2/resources/comments.d.ts +107 -0
- package/dist/cjs/services/basecamp2/resources/comments.d.ts.map +1 -0
- package/dist/cjs/services/basecamp2/resources/comments.js +94 -0
- package/dist/cjs/services/basecamp2/resources/comments.js.map +1 -0
- package/dist/cjs/services/basecamp2/resources/events.d.ts +49 -0
- package/dist/cjs/services/basecamp2/resources/events.d.ts.map +1 -0
- package/dist/cjs/services/basecamp2/resources/events.js +50 -0
- package/dist/cjs/services/basecamp2/resources/events.js.map +1 -0
- package/dist/cjs/services/basecamp2/resources/index.d.ts +6 -0
- package/dist/cjs/services/basecamp2/resources/index.d.ts.map +1 -1
- package/dist/cjs/services/basecamp2/resources/index.js +25 -1
- package/dist/cjs/services/basecamp2/resources/index.js.map +1 -1
- package/dist/cjs/services/basecamp2/resources/metrics.d.ts +67 -0
- package/dist/cjs/services/basecamp2/resources/metrics.d.ts.map +1 -0
- package/dist/cjs/services/basecamp2/resources/metrics.js +50 -0
- package/dist/cjs/services/basecamp2/resources/metrics.js.map +1 -0
- package/dist/cjs/services/basecamp2/resources/people.d.ts +190 -0
- package/dist/cjs/services/basecamp2/resources/people.d.ts.map +1 -0
- package/dist/cjs/services/basecamp2/resources/people.js +165 -0
- package/dist/cjs/services/basecamp2/resources/people.js.map +1 -0
- package/dist/cjs/services/basecamp2/resources/projects.d.ts +227 -0
- package/dist/cjs/services/basecamp2/resources/projects.d.ts.map +1 -0
- package/dist/cjs/services/basecamp2/resources/projects.js +194 -0
- package/dist/cjs/services/basecamp2/resources/projects.js.map +1 -0
- package/dist/cjs/services/basecamp2/resources/todolists.d.ts +97 -0
- package/dist/cjs/services/basecamp2/resources/todolists.d.ts.map +1 -0
- package/dist/cjs/services/basecamp2/resources/todolists.js +94 -0
- package/dist/cjs/services/basecamp2/resources/todolists.js.map +1 -0
- package/dist/cjs/services/basecamp2/resources/todos-summary.d.ts +3 -5
- package/dist/cjs/services/basecamp2/resources/todos-summary.d.ts.map +1 -1
- package/dist/cjs/services/basecamp2/resources/todos-summary.js +5 -7
- package/dist/cjs/services/basecamp2/resources/todos-summary.js.map +1 -1
- package/dist/cjs/services/basecamp2/resources/todos.d.ts +151 -5
- package/dist/cjs/services/basecamp2/resources/todos.d.ts.map +1 -1
- package/dist/cjs/services/basecamp2/resources/todos.js +118 -7
- package/dist/cjs/services/basecamp2/resources/todos.js.map +1 -1
- package/dist/cjs/services/basecamp2/schemas/comments.d.ts +432 -0
- package/dist/cjs/services/basecamp2/schemas/comments.d.ts.map +1 -0
- package/dist/cjs/services/basecamp2/schemas/comments.js +52 -0
- package/dist/cjs/services/basecamp2/schemas/comments.js.map +1 -0
- package/dist/cjs/services/basecamp2/schemas/events.d.ts +363 -0
- package/dist/cjs/services/basecamp2/schemas/events.d.ts.map +1 -0
- package/dist/cjs/services/basecamp2/schemas/events.js +53 -0
- package/dist/cjs/services/basecamp2/schemas/events.js.map +1 -0
- package/dist/cjs/services/basecamp2/schemas/healthCheck.d.ts +2 -7
- package/dist/cjs/services/basecamp2/schemas/healthCheck.d.ts.map +1 -1
- package/dist/cjs/services/basecamp2/schemas/healthCheck.js +2 -3
- package/dist/cjs/services/basecamp2/schemas/healthCheck.js.map +1 -1
- package/dist/cjs/services/basecamp2/schemas/index.d.ts +6 -0
- package/dist/cjs/services/basecamp2/schemas/index.d.ts.map +1 -1
- package/dist/cjs/services/basecamp2/schemas/index.js +53 -1
- package/dist/cjs/services/basecamp2/schemas/index.js.map +1 -1
- package/dist/cjs/services/basecamp2/schemas/metrics.d.ts +650 -0
- package/dist/cjs/services/basecamp2/schemas/metrics.d.ts.map +1 -0
- package/dist/cjs/services/basecamp2/schemas/metrics.js +67 -0
- package/dist/cjs/services/basecamp2/schemas/metrics.js.map +1 -0
- package/dist/cjs/services/basecamp2/schemas/people.d.ts +487 -0
- package/dist/cjs/services/basecamp2/schemas/people.d.ts.map +1 -0
- package/dist/cjs/services/basecamp2/schemas/people.js +77 -0
- package/dist/cjs/services/basecamp2/schemas/people.js.map +1 -0
- package/dist/cjs/services/basecamp2/schemas/projects.d.ts +539 -0
- package/dist/cjs/services/basecamp2/schemas/projects.d.ts.map +1 -0
- package/dist/cjs/services/basecamp2/schemas/projects.js +81 -0
- package/dist/cjs/services/basecamp2/schemas/projects.js.map +1 -0
- package/dist/cjs/services/basecamp2/schemas/todolists.d.ts +371 -0
- package/dist/cjs/services/basecamp2/schemas/todolists.d.ts.map +1 -0
- package/dist/cjs/services/basecamp2/schemas/todolists.js +55 -0
- package/dist/cjs/services/basecamp2/schemas/todolists.js.map +1 -0
- package/dist/cjs/services/basecamp2/schemas/todos.d.ts +19 -11
- package/dist/cjs/services/basecamp2/schemas/todos.d.ts.map +1 -1
- package/dist/cjs/services/basecamp2/schemas/todos.js +9 -5
- package/dist/cjs/services/basecamp2/schemas/todos.js.map +1 -1
- package/dist/cjs/services/basecamp2/schemas/todosSummary.d.ts +4 -11
- package/dist/cjs/services/basecamp2/schemas/todosSummary.d.ts.map +1 -1
- package/dist/cjs/services/basecamp2/schemas/todosSummary.js +4 -5
- package/dist/cjs/services/basecamp2/schemas/todosSummary.js.map +1 -1
- package/dist/cjs/services/commerce/schemas/cart.d.ts +3 -0
- package/dist/cjs/services/commerce/schemas/cart.d.ts.map +1 -1
- package/dist/cjs/services/commerce/schemas/cart.js +1 -0
- package/dist/cjs/services/commerce/schemas/cart.js.map +1 -1
- package/dist/cjs/services/customers/client.d.ts +19 -23
- package/dist/cjs/services/customers/client.d.ts.map +1 -1
- package/dist/cjs/services/customers/client.js +16 -16
- package/dist/cjs/services/customers/client.js.map +1 -1
- package/dist/cjs/services/customers/resources/customer.d.ts +232 -122
- package/dist/cjs/services/customers/resources/customer.d.ts.map +1 -1
- package/dist/cjs/services/customers/resources/customer.js +270 -181
- package/dist/cjs/services/customers/resources/customer.js.map +1 -1
- package/dist/cjs/services/customers/resources/index.d.ts +0 -2
- package/dist/cjs/services/customers/resources/index.d.ts.map +1 -1
- package/dist/cjs/services/customers/resources/index.js +1 -7
- package/dist/cjs/services/customers/resources/index.js.map +1 -1
- package/dist/cjs/services/customers/schemas/customerCustomerIdOrders.d.ts +6 -0
- package/dist/cjs/services/customers/schemas/customerCustomerIdOrders.d.ts.map +1 -1
- package/dist/cjs/services/customers/schemas/customerCustomerIdOrders.js +2 -0
- package/dist/cjs/services/customers/schemas/customerCustomerIdOrders.js.map +1 -1
- package/dist/cjs/services/gregorovich/schemas/chatGptAsk.d.ts +8 -2
- package/dist/cjs/services/gregorovich/schemas/chatGptAsk.d.ts.map +1 -1
- package/dist/cjs/services/gregorovich/schemas/chatGptAsk.js +6 -2
- package/dist/cjs/services/gregorovich/schemas/chatGptAsk.js.map +1 -1
- package/dist/cjs/services/items/client.d.ts +3 -1
- package/dist/cjs/services/items/client.d.ts.map +1 -1
- package/dist/cjs/services/items/client.js +9 -3
- package/dist/cjs/services/items/client.js.map +1 -1
- package/dist/cjs/services/items/resources/attribute-groups.d.ts.map +1 -1
- package/dist/cjs/services/items/resources/attribute-groups.js +23 -14
- package/dist/cjs/services/items/resources/attribute-groups.js.map +1 -1
- package/dist/cjs/services/items/resources/attributes.d.ts.map +1 -1
- package/dist/cjs/services/items/resources/attributes.js +23 -14
- package/dist/cjs/services/items/resources/attributes.js.map +1 -1
- package/dist/cjs/services/items/resources/brands.d.ts.map +1 -1
- package/dist/cjs/services/items/resources/brands.js +23 -14
- package/dist/cjs/services/items/resources/brands.js.map +1 -1
- package/dist/cjs/services/items/resources/categories.d.ts.map +1 -1
- package/dist/cjs/services/items/resources/categories.js +8 -8
- package/dist/cjs/services/items/resources/categories.js.map +1 -1
- package/dist/cjs/services/items/resources/contracts.d.ts.map +1 -1
- package/dist/cjs/services/items/resources/contracts.js +4 -4
- package/dist/cjs/services/items/resources/contracts.js.map +1 -1
- package/dist/cjs/services/items/resources/index.d.ts +1 -0
- package/dist/cjs/services/items/resources/index.d.ts.map +1 -1
- package/dist/cjs/services/items/resources/index.js +4 -1
- package/dist/cjs/services/items/resources/index.js.map +1 -1
- package/dist/cjs/services/items/resources/inv-mast-links.d.ts.map +1 -1
- package/dist/cjs/services/items/resources/inv-mast-links.js +2 -2
- package/dist/cjs/services/items/resources/inv-mast-links.js.map +1 -1
- package/dist/cjs/services/items/resources/inv-mast-sub-parts.d.ts.map +1 -1
- package/dist/cjs/services/items/resources/inv-mast-sub-parts.js +2 -2
- package/dist/cjs/services/items/resources/inv-mast-sub-parts.js.map +1 -1
- package/dist/cjs/services/items/resources/inv-mast.d.ts.map +1 -1
- package/dist/cjs/services/items/resources/inv-mast.js +47 -39
- package/dist/cjs/services/items/resources/inv-mast.js.map +1 -1
- package/dist/cjs/services/items/resources/item-category.d.ts.map +1 -1
- package/dist/cjs/services/items/resources/item-category.js +4 -4
- package/dist/cjs/services/items/resources/item-category.js.map +1 -1
- package/dist/cjs/services/items/resources/item-favorites.d.ts.map +1 -1
- package/dist/cjs/services/items/resources/item-favorites.js +8 -8
- package/dist/cjs/services/items/resources/item-favorites.js.map +1 -1
- package/dist/cjs/services/items/resources/item-uom.d.ts.map +1 -1
- package/dist/cjs/services/items/resources/item-uom.js +2 -2
- package/dist/cjs/services/items/resources/item-uom.js.map +1 -1
- package/dist/cjs/services/items/resources/item-wishlist.d.ts.map +1 -1
- package/dist/cjs/services/items/resources/item-wishlist.js +27 -11
- package/dist/cjs/services/items/resources/item-wishlist.js.map +1 -1
- package/dist/cjs/services/items/resources/locations.d.ts.map +1 -1
- package/dist/cjs/services/items/resources/locations.js +4 -4
- package/dist/cjs/services/items/resources/locations.js.map +1 -1
- package/dist/cjs/services/items/resources/variants.d.ts.map +1 -1
- package/dist/cjs/services/items/resources/variants.js +23 -14
- package/dist/cjs/services/items/resources/variants.js.map +1 -1
- package/dist/cjs/services/items/resources/whoami.d.ts +32 -0
- package/dist/cjs/services/items/resources/whoami.d.ts.map +1 -0
- package/dist/cjs/services/items/resources/whoami.js +42 -0
- package/dist/cjs/services/items/resources/whoami.js.map +1 -0
- package/dist/cjs/services/items/schemas/categories.d.ts +6 -0
- package/dist/cjs/services/items/schemas/categories.d.ts.map +1 -1
- package/dist/cjs/services/items/schemas/categories.js +2 -0
- package/dist/cjs/services/items/schemas/categories.js.map +1 -1
- package/dist/cjs/services/items/schemas/index.d.ts +1 -0
- package/dist/cjs/services/items/schemas/index.d.ts.map +1 -1
- package/dist/cjs/services/items/schemas/index.js +1 -0
- package/dist/cjs/services/items/schemas/index.js.map +1 -1
- package/dist/cjs/services/items/schemas/invMastLookup.d.ts +3 -0
- package/dist/cjs/services/items/schemas/invMastLookup.d.ts.map +1 -1
- package/dist/cjs/services/items/schemas/invMastLookup.js +1 -0
- package/dist/cjs/services/items/schemas/invMastLookup.js.map +1 -1
- package/dist/cjs/services/items/schemas/whoami.d.ts +17 -0
- package/dist/cjs/services/items/schemas/whoami.d.ts.map +1 -0
- package/dist/cjs/services/items/schemas/whoami.js +15 -0
- package/dist/cjs/services/items/schemas/whoami.js.map +1 -0
- package/dist/cjs/services/logistics/schemas.d.ts +78 -69
- package/dist/cjs/services/logistics/schemas.d.ts.map +1 -1
- package/dist/cjs/services/logistics/schemas.js +27 -24
- package/dist/cjs/services/logistics/schemas.js.map +1 -1
- package/dist/cjs/services/open-search/schemas/itemSearch.d.ts +9 -0
- package/dist/cjs/services/open-search/schemas/itemSearch.d.ts.map +1 -1
- package/dist/cjs/services/open-search/schemas/itemSearch.js +3 -0
- package/dist/cjs/services/open-search/schemas/itemSearch.js.map +1 -1
- package/dist/cjs/services/orders/resources/invoice-hdr.d.ts.map +1 -1
- package/dist/cjs/services/orders/resources/invoice-hdr.js +2 -2
- package/dist/cjs/services/orders/resources/invoice-hdr.js.map +1 -1
- package/dist/cjs/services/orders/resources/oe-hdr-salesrep.d.ts.map +1 -1
- package/dist/cjs/services/orders/resources/oe-hdr-salesrep.js +4 -4
- package/dist/cjs/services/orders/resources/oe-hdr-salesrep.js.map +1 -1
- package/dist/cjs/services/orders/resources/oe-hdr.d.ts.map +1 -1
- package/dist/cjs/services/orders/resources/oe-hdr.js +2 -2
- package/dist/cjs/services/orders/resources/oe-hdr.js.map +1 -1
- package/dist/cjs/services/orders/resources/pick-tickets.d.ts.map +1 -1
- package/dist/cjs/services/orders/resources/pick-tickets.js +6 -6
- package/dist/cjs/services/orders/resources/pick-tickets.js.map +1 -1
- package/dist/cjs/services/orders/resources/po-hdr.d.ts.map +1 -1
- package/dist/cjs/services/orders/resources/po-hdr.js +2 -2
- package/dist/cjs/services/orders/resources/po-hdr.js.map +1 -1
- package/dist/cjs/services/p21-apis/resources/trans-category.js +6 -6
- package/dist/cjs/services/p21-apis/resources/trans-category.js.map +1 -1
- package/dist/cjs/services/p21-apis/resources/trans-company.js +6 -6
- package/dist/cjs/services/p21-apis/resources/trans-company.js.map +1 -1
- package/dist/cjs/services/p21-apis/resources/trans-purchase-order-receipt.js +4 -4
- package/dist/cjs/services/p21-apis/resources/trans-purchase-order-receipt.js.map +1 -1
- package/dist/cjs/services/p21-apis/resources/trans-user.js +6 -6
- package/dist/cjs/services/p21-apis/resources/trans-user.js.map +1 -1
- package/dist/cjs/services/p21-apis/resources/trans-web-display-type.js +6 -6
- package/dist/cjs/services/p21-apis/resources/trans-web-display-type.js.map +1 -1
- package/dist/cjs/services/p21-apis/schemas.d.ts +6 -24
- package/dist/cjs/services/p21-apis/schemas.d.ts.map +1 -1
- package/dist/cjs/services/p21-apis/schemas.js +6 -12
- package/dist/cjs/services/p21-apis/schemas.js.map +1 -1
- package/dist/cjs/services/p21-pim/resources/items.d.ts.map +1 -1
- package/dist/cjs/services/p21-pim/resources/items.js +4 -4
- package/dist/cjs/services/p21-pim/resources/items.js.map +1 -1
- package/dist/cjs/services/p21-sism/resources/import.d.ts +1 -0
- package/dist/cjs/services/p21-sism/resources/import.d.ts.map +1 -1
- package/dist/cjs/services/p21-sism/schemas/import.d.ts +3 -0
- package/dist/cjs/services/p21-sism/schemas/import.d.ts.map +1 -1
- package/dist/cjs/services/p21-sism/schemas/import.js +1 -0
- package/dist/cjs/services/p21-sism/schemas/import.js.map +1 -1
- package/dist/cjs/services/payments/client.d.ts +5 -1
- package/dist/cjs/services/payments/client.d.ts.map +1 -1
- package/dist/cjs/services/payments/client.js +2 -0
- package/dist/cjs/services/payments/client.js.map +1 -1
- package/dist/cjs/services/payments/resources/index.d.ts +1 -0
- package/dist/cjs/services/payments/resources/index.d.ts.map +1 -1
- package/dist/cjs/services/payments/resources/index.js +4 -1
- package/dist/cjs/services/payments/resources/index.js.map +1 -1
- package/dist/cjs/services/payments/resources/paytrace.d.ts +154 -0
- package/dist/cjs/services/payments/resources/paytrace.d.ts.map +1 -0
- package/dist/cjs/services/payments/resources/paytrace.js +142 -0
- package/dist/cjs/services/payments/resources/paytrace.js.map +1 -0
- package/dist/cjs/services/payments/schemas/index.d.ts +1 -0
- package/dist/cjs/services/payments/schemas/index.d.ts.map +1 -1
- package/dist/cjs/services/payments/schemas/index.js +1 -0
- package/dist/cjs/services/payments/schemas/index.js.map +1 -1
- package/dist/cjs/services/payments/schemas/paytrace.d.ts +73 -0
- package/dist/cjs/services/payments/schemas/paytrace.d.ts.map +1 -0
- package/dist/cjs/services/payments/schemas/paytrace.js +18 -0
- package/dist/cjs/services/payments/schemas/paytrace.js.map +1 -0
- package/dist/cjs/services/pricing/schemas/priceEngine.d.ts +3 -0
- package/dist/cjs/services/pricing/schemas/priceEngine.d.ts.map +1 -1
- package/dist/cjs/services/pricing/schemas/priceEngine.js +1 -0
- package/dist/cjs/services/pricing/schemas/priceEngine.js.map +1 -1
- package/dist/cjs/services/smarty-streets/schemas/usLookup.d.ts +20 -2
- package/dist/cjs/services/smarty-streets/schemas/usLookup.d.ts.map +1 -1
- package/dist/cjs/services/smarty-streets/schemas/usLookup.js +10 -2
- package/dist/cjs/services/smarty-streets/schemas/usLookup.js.map +1 -1
- package/dist/cjs/services/ups/schemas/ratesShop.d.ts +53 -2
- package/dist/cjs/services/ups/schemas/ratesShop.d.ts.map +1 -1
- package/dist/cjs/services/ups/schemas/ratesShop.js +21 -2
- package/dist/cjs/services/ups/schemas/ratesShop.js.map +1 -1
- package/dist/cjs/services/vmi/resources/distributors.d.ts.map +1 -1
- package/dist/cjs/services/vmi/resources/distributors.js +6 -6
- package/dist/cjs/services/vmi/resources/distributors.js.map +1 -1
- package/dist/cjs/services/vmi/resources/inv-profile-hdr.d.ts.map +1 -1
- package/dist/cjs/services/vmi/resources/inv-profile-hdr.js +6 -6
- package/dist/cjs/services/vmi/resources/inv-profile-hdr.js.map +1 -1
- package/dist/cjs/services/vmi/resources/restock-hdr.d.ts.map +1 -1
- package/dist/cjs/services/vmi/resources/restock-hdr.js +6 -6
- package/dist/cjs/services/vmi/resources/restock-hdr.js.map +1 -1
- package/dist/cjs/services/vmi/resources/sections.d.ts.map +1 -1
- package/dist/cjs/services/vmi/resources/sections.js +6 -6
- package/dist/cjs/services/vmi/resources/sections.js.map +1 -1
- package/dist/cjs/services/vmi/resources/warehouse.d.ts.map +1 -1
- package/dist/cjs/services/vmi/resources/warehouse.js +6 -6
- package/dist/cjs/services/vmi/resources/warehouse.js.map +1 -1
- package/dist/esm/client.d.ts +6 -0
- package/dist/esm/client.d.ts.map +1 -1
- package/dist/esm/client.js +14 -0
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/services/agr-site/client.d.ts +9 -1
- package/dist/esm/services/agr-site/client.d.ts.map +1 -1
- package/dist/esm/services/agr-site/client.js +5 -1
- package/dist/esm/services/agr-site/client.js.map +1 -1
- package/dist/esm/services/agr-site/resources/index.d.ts +2 -0
- package/dist/esm/services/agr-site/resources/index.d.ts.map +1 -1
- package/dist/esm/services/agr-site/resources/index.js +2 -0
- package/dist/esm/services/agr-site/resources/index.js.map +1 -1
- package/dist/esm/services/agr-site/resources/ping.d.ts +47 -0
- package/dist/esm/services/agr-site/resources/ping.d.ts.map +1 -0
- package/dist/esm/services/agr-site/resources/ping.js +53 -0
- package/dist/esm/services/agr-site/resources/ping.js.map +1 -0
- package/dist/esm/services/agr-site/resources/whoami.d.ts +45 -0
- package/dist/esm/services/agr-site/resources/whoami.d.ts.map +1 -0
- package/dist/esm/services/agr-site/resources/whoami.js +51 -0
- package/dist/esm/services/agr-site/resources/whoami.js.map +1 -0
- package/dist/esm/services/agr-site/schemas/index.d.ts +2 -0
- package/dist/esm/services/agr-site/schemas/index.d.ts.map +1 -1
- package/dist/esm/services/agr-site/schemas/index.js +2 -0
- package/dist/esm/services/agr-site/schemas/index.js.map +1 -1
- package/dist/esm/services/agr-site/schemas/ping.d.ts +16 -0
- package/dist/esm/services/agr-site/schemas/ping.d.ts.map +1 -0
- package/dist/esm/services/agr-site/schemas/ping.js +11 -0
- package/dist/esm/services/agr-site/schemas/ping.js.map +1 -0
- package/dist/esm/services/agr-site/schemas/whoami.d.ts +16 -0
- package/dist/esm/services/agr-site/schemas/whoami.d.ts.map +1 -0
- package/dist/esm/services/agr-site/schemas/whoami.js +11 -0
- package/dist/esm/services/agr-site/schemas/whoami.js.map +1 -0
- package/dist/esm/services/basecamp2/client.d.ts +25 -1
- package/dist/esm/services/basecamp2/client.d.ts.map +1 -1
- package/dist/esm/services/basecamp2/client.js +15 -3
- package/dist/esm/services/basecamp2/client.js.map +1 -1
- package/dist/esm/services/basecamp2/resources/comments.d.ts +107 -0
- package/dist/esm/services/basecamp2/resources/comments.d.ts.map +1 -0
- package/dist/esm/services/basecamp2/resources/comments.js +90 -0
- package/dist/esm/services/basecamp2/resources/comments.js.map +1 -0
- package/dist/esm/services/basecamp2/resources/events.d.ts +49 -0
- package/dist/esm/services/basecamp2/resources/events.d.ts.map +1 -0
- package/dist/esm/services/basecamp2/resources/events.js +46 -0
- package/dist/esm/services/basecamp2/resources/events.js.map +1 -0
- package/dist/esm/services/basecamp2/resources/index.d.ts +6 -0
- package/dist/esm/services/basecamp2/resources/index.d.ts.map +1 -1
- package/dist/esm/services/basecamp2/resources/index.js +12 -0
- package/dist/esm/services/basecamp2/resources/index.js.map +1 -1
- package/dist/esm/services/basecamp2/resources/metrics.d.ts +67 -0
- package/dist/esm/services/basecamp2/resources/metrics.d.ts.map +1 -0
- package/dist/esm/services/basecamp2/resources/metrics.js +46 -0
- package/dist/esm/services/basecamp2/resources/metrics.js.map +1 -0
- package/dist/esm/services/basecamp2/resources/people.d.ts +190 -0
- package/dist/esm/services/basecamp2/resources/people.d.ts.map +1 -0
- package/dist/esm/services/basecamp2/resources/people.js +161 -0
- package/dist/esm/services/basecamp2/resources/people.js.map +1 -0
- package/dist/esm/services/basecamp2/resources/projects.d.ts +227 -0
- package/dist/esm/services/basecamp2/resources/projects.d.ts.map +1 -0
- package/dist/esm/services/basecamp2/resources/projects.js +190 -0
- package/dist/esm/services/basecamp2/resources/projects.js.map +1 -0
- package/dist/esm/services/basecamp2/resources/todolists.d.ts +97 -0
- package/dist/esm/services/basecamp2/resources/todolists.d.ts.map +1 -0
- package/dist/esm/services/basecamp2/resources/todolists.js +90 -0
- package/dist/esm/services/basecamp2/resources/todolists.js.map +1 -0
- package/dist/esm/services/basecamp2/resources/todos-summary.d.ts +3 -5
- package/dist/esm/services/basecamp2/resources/todos-summary.d.ts.map +1 -1
- package/dist/esm/services/basecamp2/resources/todos-summary.js +5 -7
- package/dist/esm/services/basecamp2/resources/todos-summary.js.map +1 -1
- package/dist/esm/services/basecamp2/resources/todos.d.ts +151 -5
- package/dist/esm/services/basecamp2/resources/todos.d.ts.map +1 -1
- package/dist/esm/services/basecamp2/resources/todos.js +119 -8
- package/dist/esm/services/basecamp2/resources/todos.js.map +1 -1
- package/dist/esm/services/basecamp2/schemas/comments.d.ts +432 -0
- package/dist/esm/services/basecamp2/schemas/comments.d.ts.map +1 -0
- package/dist/esm/services/basecamp2/schemas/comments.js +49 -0
- package/dist/esm/services/basecamp2/schemas/comments.js.map +1 -0
- package/dist/esm/services/basecamp2/schemas/events.d.ts +363 -0
- package/dist/esm/services/basecamp2/schemas/events.d.ts.map +1 -0
- package/dist/esm/services/basecamp2/schemas/events.js +50 -0
- package/dist/esm/services/basecamp2/schemas/events.js.map +1 -0
- package/dist/esm/services/basecamp2/schemas/healthCheck.d.ts +2 -7
- package/dist/esm/services/basecamp2/schemas/healthCheck.d.ts.map +1 -1
- package/dist/esm/services/basecamp2/schemas/healthCheck.js +2 -3
- package/dist/esm/services/basecamp2/schemas/healthCheck.js.map +1 -1
- package/dist/esm/services/basecamp2/schemas/index.d.ts +6 -0
- package/dist/esm/services/basecamp2/schemas/index.d.ts.map +1 -1
- package/dist/esm/services/basecamp2/schemas/index.js +12 -0
- package/dist/esm/services/basecamp2/schemas/index.js.map +1 -1
- package/dist/esm/services/basecamp2/schemas/metrics.d.ts +650 -0
- package/dist/esm/services/basecamp2/schemas/metrics.d.ts.map +1 -0
- package/dist/esm/services/basecamp2/schemas/metrics.js +64 -0
- package/dist/esm/services/basecamp2/schemas/metrics.js.map +1 -0
- package/dist/esm/services/basecamp2/schemas/people.d.ts +487 -0
- package/dist/esm/services/basecamp2/schemas/people.d.ts.map +1 -0
- package/dist/esm/services/basecamp2/schemas/people.js +74 -0
- package/dist/esm/services/basecamp2/schemas/people.js.map +1 -0
- package/dist/esm/services/basecamp2/schemas/projects.d.ts +539 -0
- package/dist/esm/services/basecamp2/schemas/projects.d.ts.map +1 -0
- package/dist/esm/services/basecamp2/schemas/projects.js +78 -0
- package/dist/esm/services/basecamp2/schemas/projects.js.map +1 -0
- package/dist/esm/services/basecamp2/schemas/todolists.d.ts +371 -0
- package/dist/esm/services/basecamp2/schemas/todolists.d.ts.map +1 -0
- package/dist/esm/services/basecamp2/schemas/todolists.js +52 -0
- package/dist/esm/services/basecamp2/schemas/todolists.js.map +1 -0
- package/dist/esm/services/basecamp2/schemas/todos.d.ts +19 -11
- package/dist/esm/services/basecamp2/schemas/todos.d.ts.map +1 -1
- package/dist/esm/services/basecamp2/schemas/todos.js +9 -5
- package/dist/esm/services/basecamp2/schemas/todos.js.map +1 -1
- package/dist/esm/services/basecamp2/schemas/todosSummary.d.ts +4 -11
- package/dist/esm/services/basecamp2/schemas/todosSummary.d.ts.map +1 -1
- package/dist/esm/services/basecamp2/schemas/todosSummary.js +4 -5
- package/dist/esm/services/basecamp2/schemas/todosSummary.js.map +1 -1
- package/dist/esm/services/commerce/schemas/cart.d.ts +3 -0
- package/dist/esm/services/commerce/schemas/cart.d.ts.map +1 -1
- package/dist/esm/services/commerce/schemas/cart.js +1 -0
- package/dist/esm/services/commerce/schemas/cart.js.map +1 -1
- package/dist/esm/services/customers/client.d.ts +19 -23
- package/dist/esm/services/customers/client.d.ts.map +1 -1
- package/dist/esm/services/customers/client.js +17 -17
- package/dist/esm/services/customers/client.js.map +1 -1
- package/dist/esm/services/customers/resources/customer.d.ts +232 -122
- package/dist/esm/services/customers/resources/customer.d.ts.map +1 -1
- package/dist/esm/services/customers/resources/customer.js +271 -182
- package/dist/esm/services/customers/resources/customer.js.map +1 -1
- package/dist/esm/services/customers/resources/index.d.ts +0 -2
- package/dist/esm/services/customers/resources/index.d.ts.map +1 -1
- package/dist/esm/services/customers/resources/index.js +0 -2
- package/dist/esm/services/customers/resources/index.js.map +1 -1
- package/dist/esm/services/customers/schemas/customerCustomerIdOrders.d.ts +6 -0
- package/dist/esm/services/customers/schemas/customerCustomerIdOrders.d.ts.map +1 -1
- package/dist/esm/services/customers/schemas/customerCustomerIdOrders.js +2 -0
- package/dist/esm/services/customers/schemas/customerCustomerIdOrders.js.map +1 -1
- package/dist/esm/services/gregorovich/schemas/chatGptAsk.d.ts +8 -2
- package/dist/esm/services/gregorovich/schemas/chatGptAsk.d.ts.map +1 -1
- package/dist/esm/services/gregorovich/schemas/chatGptAsk.js +6 -2
- package/dist/esm/services/gregorovich/schemas/chatGptAsk.js.map +1 -1
- package/dist/esm/services/items/client.d.ts +3 -1
- package/dist/esm/services/items/client.d.ts.map +1 -1
- package/dist/esm/services/items/client.js +10 -4
- package/dist/esm/services/items/client.js.map +1 -1
- package/dist/esm/services/items/resources/attribute-groups.d.ts.map +1 -1
- package/dist/esm/services/items/resources/attribute-groups.js +23 -14
- package/dist/esm/services/items/resources/attribute-groups.js.map +1 -1
- package/dist/esm/services/items/resources/attributes.d.ts.map +1 -1
- package/dist/esm/services/items/resources/attributes.js +23 -14
- package/dist/esm/services/items/resources/attributes.js.map +1 -1
- package/dist/esm/services/items/resources/brands.d.ts.map +1 -1
- package/dist/esm/services/items/resources/brands.js +23 -14
- package/dist/esm/services/items/resources/brands.js.map +1 -1
- package/dist/esm/services/items/resources/categories.d.ts.map +1 -1
- package/dist/esm/services/items/resources/categories.js +8 -8
- package/dist/esm/services/items/resources/categories.js.map +1 -1
- package/dist/esm/services/items/resources/contracts.d.ts.map +1 -1
- package/dist/esm/services/items/resources/contracts.js +4 -4
- package/dist/esm/services/items/resources/contracts.js.map +1 -1
- package/dist/esm/services/items/resources/index.d.ts +1 -0
- package/dist/esm/services/items/resources/index.d.ts.map +1 -1
- package/dist/esm/services/items/resources/index.js +1 -0
- package/dist/esm/services/items/resources/index.js.map +1 -1
- package/dist/esm/services/items/resources/inv-mast-links.d.ts.map +1 -1
- package/dist/esm/services/items/resources/inv-mast-links.js +2 -2
- package/dist/esm/services/items/resources/inv-mast-links.js.map +1 -1
- package/dist/esm/services/items/resources/inv-mast-sub-parts.d.ts.map +1 -1
- package/dist/esm/services/items/resources/inv-mast-sub-parts.js +2 -2
- package/dist/esm/services/items/resources/inv-mast-sub-parts.js.map +1 -1
- package/dist/esm/services/items/resources/inv-mast.d.ts.map +1 -1
- package/dist/esm/services/items/resources/inv-mast.js +47 -39
- package/dist/esm/services/items/resources/inv-mast.js.map +1 -1
- package/dist/esm/services/items/resources/item-category.d.ts.map +1 -1
- package/dist/esm/services/items/resources/item-category.js +4 -4
- package/dist/esm/services/items/resources/item-category.js.map +1 -1
- package/dist/esm/services/items/resources/item-favorites.d.ts.map +1 -1
- package/dist/esm/services/items/resources/item-favorites.js +8 -8
- package/dist/esm/services/items/resources/item-favorites.js.map +1 -1
- package/dist/esm/services/items/resources/item-uom.d.ts.map +1 -1
- package/dist/esm/services/items/resources/item-uom.js +2 -2
- package/dist/esm/services/items/resources/item-uom.js.map +1 -1
- package/dist/esm/services/items/resources/item-wishlist.d.ts.map +1 -1
- package/dist/esm/services/items/resources/item-wishlist.js +27 -11
- package/dist/esm/services/items/resources/item-wishlist.js.map +1 -1
- package/dist/esm/services/items/resources/locations.d.ts.map +1 -1
- package/dist/esm/services/items/resources/locations.js +4 -4
- package/dist/esm/services/items/resources/locations.js.map +1 -1
- package/dist/esm/services/items/resources/variants.d.ts.map +1 -1
- package/dist/esm/services/items/resources/variants.js +23 -14
- package/dist/esm/services/items/resources/variants.js.map +1 -1
- package/dist/esm/services/items/resources/whoami.d.ts +32 -0
- package/dist/esm/services/items/resources/whoami.d.ts.map +1 -0
- package/dist/esm/services/items/resources/whoami.js +38 -0
- package/dist/esm/services/items/resources/whoami.js.map +1 -0
- package/dist/esm/services/items/schemas/categories.d.ts +6 -0
- package/dist/esm/services/items/schemas/categories.d.ts.map +1 -1
- package/dist/esm/services/items/schemas/categories.js +2 -0
- package/dist/esm/services/items/schemas/categories.js.map +1 -1
- package/dist/esm/services/items/schemas/index.d.ts +1 -0
- package/dist/esm/services/items/schemas/index.d.ts.map +1 -1
- package/dist/esm/services/items/schemas/index.js +1 -0
- package/dist/esm/services/items/schemas/index.js.map +1 -1
- package/dist/esm/services/items/schemas/invMastLookup.d.ts +3 -0
- package/dist/esm/services/items/schemas/invMastLookup.d.ts.map +1 -1
- package/dist/esm/services/items/schemas/invMastLookup.js +1 -0
- package/dist/esm/services/items/schemas/invMastLookup.js.map +1 -1
- package/dist/esm/services/items/schemas/whoami.d.ts +17 -0
- package/dist/esm/services/items/schemas/whoami.d.ts.map +1 -0
- package/dist/esm/services/items/schemas/whoami.js +12 -0
- package/dist/esm/services/items/schemas/whoami.js.map +1 -0
- package/dist/esm/services/logistics/schemas.d.ts +78 -69
- package/dist/esm/services/logistics/schemas.d.ts.map +1 -1
- package/dist/esm/services/logistics/schemas.js +27 -24
- package/dist/esm/services/logistics/schemas.js.map +1 -1
- package/dist/esm/services/open-search/schemas/itemSearch.d.ts +9 -0
- package/dist/esm/services/open-search/schemas/itemSearch.d.ts.map +1 -1
- package/dist/esm/services/open-search/schemas/itemSearch.js +3 -0
- package/dist/esm/services/open-search/schemas/itemSearch.js.map +1 -1
- package/dist/esm/services/orders/resources/invoice-hdr.d.ts.map +1 -1
- package/dist/esm/services/orders/resources/invoice-hdr.js +2 -2
- package/dist/esm/services/orders/resources/invoice-hdr.js.map +1 -1
- package/dist/esm/services/orders/resources/oe-hdr-salesrep.d.ts.map +1 -1
- package/dist/esm/services/orders/resources/oe-hdr-salesrep.js +4 -4
- package/dist/esm/services/orders/resources/oe-hdr-salesrep.js.map +1 -1
- package/dist/esm/services/orders/resources/oe-hdr.d.ts.map +1 -1
- package/dist/esm/services/orders/resources/oe-hdr.js +2 -2
- package/dist/esm/services/orders/resources/oe-hdr.js.map +1 -1
- package/dist/esm/services/orders/resources/pick-tickets.d.ts.map +1 -1
- package/dist/esm/services/orders/resources/pick-tickets.js +6 -6
- package/dist/esm/services/orders/resources/pick-tickets.js.map +1 -1
- package/dist/esm/services/orders/resources/po-hdr.d.ts.map +1 -1
- package/dist/esm/services/orders/resources/po-hdr.js +2 -2
- package/dist/esm/services/orders/resources/po-hdr.js.map +1 -1
- package/dist/esm/services/p21-apis/resources/trans-category.js +6 -6
- package/dist/esm/services/p21-apis/resources/trans-category.js.map +1 -1
- package/dist/esm/services/p21-apis/resources/trans-company.js +6 -6
- package/dist/esm/services/p21-apis/resources/trans-company.js.map +1 -1
- package/dist/esm/services/p21-apis/resources/trans-purchase-order-receipt.js +4 -4
- package/dist/esm/services/p21-apis/resources/trans-purchase-order-receipt.js.map +1 -1
- package/dist/esm/services/p21-apis/resources/trans-user.js +6 -6
- package/dist/esm/services/p21-apis/resources/trans-user.js.map +1 -1
- package/dist/esm/services/p21-apis/resources/trans-web-display-type.js +6 -6
- package/dist/esm/services/p21-apis/resources/trans-web-display-type.js.map +1 -1
- package/dist/esm/services/p21-apis/schemas.d.ts +6 -24
- package/dist/esm/services/p21-apis/schemas.d.ts.map +1 -1
- package/dist/esm/services/p21-apis/schemas.js +6 -12
- package/dist/esm/services/p21-apis/schemas.js.map +1 -1
- package/dist/esm/services/p21-pim/resources/items.d.ts.map +1 -1
- package/dist/esm/services/p21-pim/resources/items.js +4 -4
- package/dist/esm/services/p21-pim/resources/items.js.map +1 -1
- package/dist/esm/services/p21-sism/resources/import.d.ts +1 -0
- package/dist/esm/services/p21-sism/resources/import.d.ts.map +1 -1
- package/dist/esm/services/p21-sism/schemas/import.d.ts +3 -0
- package/dist/esm/services/p21-sism/schemas/import.d.ts.map +1 -1
- package/dist/esm/services/p21-sism/schemas/import.js +1 -0
- package/dist/esm/services/p21-sism/schemas/import.js.map +1 -1
- package/dist/esm/services/payments/client.d.ts +5 -1
- package/dist/esm/services/payments/client.d.ts.map +1 -1
- package/dist/esm/services/payments/client.js +3 -1
- package/dist/esm/services/payments/client.js.map +1 -1
- package/dist/esm/services/payments/resources/index.d.ts +1 -0
- package/dist/esm/services/payments/resources/index.d.ts.map +1 -1
- package/dist/esm/services/payments/resources/index.js +1 -0
- package/dist/esm/services/payments/resources/index.js.map +1 -1
- package/dist/esm/services/payments/resources/paytrace.d.ts +154 -0
- package/dist/esm/services/payments/resources/paytrace.d.ts.map +1 -0
- package/dist/esm/services/payments/resources/paytrace.js +138 -0
- package/dist/esm/services/payments/resources/paytrace.js.map +1 -0
- package/dist/esm/services/payments/schemas/index.d.ts +1 -0
- package/dist/esm/services/payments/schemas/index.d.ts.map +1 -1
- package/dist/esm/services/payments/schemas/index.js +1 -0
- package/dist/esm/services/payments/schemas/index.js.map +1 -1
- package/dist/esm/services/payments/schemas/paytrace.d.ts +73 -0
- package/dist/esm/services/payments/schemas/paytrace.d.ts.map +1 -0
- package/dist/esm/services/payments/schemas/paytrace.js +15 -0
- package/dist/esm/services/payments/schemas/paytrace.js.map +1 -0
- package/dist/esm/services/pricing/schemas/priceEngine.d.ts +3 -0
- package/dist/esm/services/pricing/schemas/priceEngine.d.ts.map +1 -1
- package/dist/esm/services/pricing/schemas/priceEngine.js +1 -0
- package/dist/esm/services/pricing/schemas/priceEngine.js.map +1 -1
- package/dist/esm/services/smarty-streets/schemas/usLookup.d.ts +20 -2
- package/dist/esm/services/smarty-streets/schemas/usLookup.d.ts.map +1 -1
- package/dist/esm/services/smarty-streets/schemas/usLookup.js +10 -2
- package/dist/esm/services/smarty-streets/schemas/usLookup.js.map +1 -1
- package/dist/esm/services/ups/schemas/ratesShop.d.ts +53 -2
- package/dist/esm/services/ups/schemas/ratesShop.d.ts.map +1 -1
- package/dist/esm/services/ups/schemas/ratesShop.js +21 -2
- package/dist/esm/services/ups/schemas/ratesShop.js.map +1 -1
- package/dist/esm/services/vmi/resources/distributors.d.ts.map +1 -1
- package/dist/esm/services/vmi/resources/distributors.js +6 -6
- package/dist/esm/services/vmi/resources/distributors.js.map +1 -1
- package/dist/esm/services/vmi/resources/inv-profile-hdr.d.ts.map +1 -1
- package/dist/esm/services/vmi/resources/inv-profile-hdr.js +6 -6
- package/dist/esm/services/vmi/resources/inv-profile-hdr.js.map +1 -1
- package/dist/esm/services/vmi/resources/restock-hdr.d.ts.map +1 -1
- package/dist/esm/services/vmi/resources/restock-hdr.js +6 -6
- package/dist/esm/services/vmi/resources/restock-hdr.js.map +1 -1
- package/dist/esm/services/vmi/resources/sections.d.ts.map +1 -1
- package/dist/esm/services/vmi/resources/sections.js +6 -6
- package/dist/esm/services/vmi/resources/sections.js.map +1 -1
- package/dist/esm/services/vmi/resources/warehouse.d.ts.map +1 -1
- package/dist/esm/services/vmi/resources/warehouse.js +6 -6
- package/dist/esm/services/vmi/resources/warehouse.js.map +1 -1
- package/dist/types/client.d.ts +6 -0
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/services/agr-site/client.d.ts +9 -1
- package/dist/types/services/agr-site/client.d.ts.map +1 -1
- package/dist/types/services/agr-site/resources/index.d.ts +2 -0
- package/dist/types/services/agr-site/resources/index.d.ts.map +1 -1
- package/dist/types/services/agr-site/resources/ping.d.ts +47 -0
- package/dist/types/services/agr-site/resources/ping.d.ts.map +1 -0
- package/dist/types/services/agr-site/resources/whoami.d.ts +45 -0
- package/dist/types/services/agr-site/resources/whoami.d.ts.map +1 -0
- package/dist/types/services/agr-site/schemas/index.d.ts +2 -0
- package/dist/types/services/agr-site/schemas/index.d.ts.map +1 -1
- package/dist/types/services/agr-site/schemas/ping.d.ts +16 -0
- package/dist/types/services/agr-site/schemas/ping.d.ts.map +1 -0
- package/dist/types/services/agr-site/schemas/whoami.d.ts +16 -0
- package/dist/types/services/agr-site/schemas/whoami.d.ts.map +1 -0
- package/dist/types/services/basecamp2/client.d.ts +25 -1
- package/dist/types/services/basecamp2/client.d.ts.map +1 -1
- package/dist/types/services/basecamp2/resources/comments.d.ts +107 -0
- package/dist/types/services/basecamp2/resources/comments.d.ts.map +1 -0
- package/dist/types/services/basecamp2/resources/events.d.ts +49 -0
- package/dist/types/services/basecamp2/resources/events.d.ts.map +1 -0
- package/dist/types/services/basecamp2/resources/index.d.ts +6 -0
- package/dist/types/services/basecamp2/resources/index.d.ts.map +1 -1
- package/dist/types/services/basecamp2/resources/metrics.d.ts +67 -0
- package/dist/types/services/basecamp2/resources/metrics.d.ts.map +1 -0
- package/dist/types/services/basecamp2/resources/people.d.ts +190 -0
- package/dist/types/services/basecamp2/resources/people.d.ts.map +1 -0
- package/dist/types/services/basecamp2/resources/projects.d.ts +227 -0
- package/dist/types/services/basecamp2/resources/projects.d.ts.map +1 -0
- package/dist/types/services/basecamp2/resources/todolists.d.ts +97 -0
- package/dist/types/services/basecamp2/resources/todolists.d.ts.map +1 -0
- package/dist/types/services/basecamp2/resources/todos-summary.d.ts +3 -5
- package/dist/types/services/basecamp2/resources/todos-summary.d.ts.map +1 -1
- package/dist/types/services/basecamp2/resources/todos.d.ts +151 -5
- package/dist/types/services/basecamp2/resources/todos.d.ts.map +1 -1
- package/dist/types/services/basecamp2/schemas/comments.d.ts +432 -0
- package/dist/types/services/basecamp2/schemas/comments.d.ts.map +1 -0
- package/dist/types/services/basecamp2/schemas/events.d.ts +363 -0
- package/dist/types/services/basecamp2/schemas/events.d.ts.map +1 -0
- package/dist/types/services/basecamp2/schemas/healthCheck.d.ts +2 -7
- package/dist/types/services/basecamp2/schemas/healthCheck.d.ts.map +1 -1
- package/dist/types/services/basecamp2/schemas/index.d.ts +6 -0
- package/dist/types/services/basecamp2/schemas/index.d.ts.map +1 -1
- package/dist/types/services/basecamp2/schemas/metrics.d.ts +650 -0
- package/dist/types/services/basecamp2/schemas/metrics.d.ts.map +1 -0
- package/dist/types/services/basecamp2/schemas/people.d.ts +487 -0
- package/dist/types/services/basecamp2/schemas/people.d.ts.map +1 -0
- package/dist/types/services/basecamp2/schemas/projects.d.ts +539 -0
- package/dist/types/services/basecamp2/schemas/projects.d.ts.map +1 -0
- package/dist/types/services/basecamp2/schemas/todolists.d.ts +371 -0
- package/dist/types/services/basecamp2/schemas/todolists.d.ts.map +1 -0
- package/dist/types/services/basecamp2/schemas/todos.d.ts +19 -11
- package/dist/types/services/basecamp2/schemas/todos.d.ts.map +1 -1
- package/dist/types/services/basecamp2/schemas/todosSummary.d.ts +4 -11
- package/dist/types/services/basecamp2/schemas/todosSummary.d.ts.map +1 -1
- package/dist/types/services/commerce/schemas/cart.d.ts +3 -0
- package/dist/types/services/commerce/schemas/cart.d.ts.map +1 -1
- package/dist/types/services/customers/client.d.ts +19 -23
- package/dist/types/services/customers/client.d.ts.map +1 -1
- package/dist/types/services/customers/resources/customer.d.ts +232 -122
- package/dist/types/services/customers/resources/customer.d.ts.map +1 -1
- package/dist/types/services/customers/resources/index.d.ts +0 -2
- package/dist/types/services/customers/resources/index.d.ts.map +1 -1
- package/dist/types/services/customers/schemas/customerCustomerIdOrders.d.ts +6 -0
- package/dist/types/services/customers/schemas/customerCustomerIdOrders.d.ts.map +1 -1
- package/dist/types/services/gregorovich/schemas/chatGptAsk.d.ts +8 -2
- package/dist/types/services/gregorovich/schemas/chatGptAsk.d.ts.map +1 -1
- package/dist/types/services/items/client.d.ts +3 -1
- package/dist/types/services/items/client.d.ts.map +1 -1
- package/dist/types/services/items/resources/attribute-groups.d.ts.map +1 -1
- package/dist/types/services/items/resources/attributes.d.ts.map +1 -1
- package/dist/types/services/items/resources/brands.d.ts.map +1 -1
- package/dist/types/services/items/resources/categories.d.ts.map +1 -1
- package/dist/types/services/items/resources/contracts.d.ts.map +1 -1
- package/dist/types/services/items/resources/index.d.ts +1 -0
- package/dist/types/services/items/resources/index.d.ts.map +1 -1
- package/dist/types/services/items/resources/inv-mast-links.d.ts.map +1 -1
- package/dist/types/services/items/resources/inv-mast-sub-parts.d.ts.map +1 -1
- package/dist/types/services/items/resources/inv-mast.d.ts.map +1 -1
- package/dist/types/services/items/resources/item-category.d.ts.map +1 -1
- package/dist/types/services/items/resources/item-favorites.d.ts.map +1 -1
- package/dist/types/services/items/resources/item-uom.d.ts.map +1 -1
- package/dist/types/services/items/resources/item-wishlist.d.ts.map +1 -1
- package/dist/types/services/items/resources/locations.d.ts.map +1 -1
- package/dist/types/services/items/resources/variants.d.ts.map +1 -1
- package/dist/types/services/items/resources/whoami.d.ts +32 -0
- package/dist/types/services/items/resources/whoami.d.ts.map +1 -0
- package/dist/types/services/items/schemas/categories.d.ts +6 -0
- package/dist/types/services/items/schemas/categories.d.ts.map +1 -1
- package/dist/types/services/items/schemas/index.d.ts +1 -0
- package/dist/types/services/items/schemas/index.d.ts.map +1 -1
- package/dist/types/services/items/schemas/invMastLookup.d.ts +3 -0
- package/dist/types/services/items/schemas/invMastLookup.d.ts.map +1 -1
- package/dist/types/services/items/schemas/whoami.d.ts +17 -0
- package/dist/types/services/items/schemas/whoami.d.ts.map +1 -0
- package/dist/types/services/logistics/schemas.d.ts +78 -69
- package/dist/types/services/logistics/schemas.d.ts.map +1 -1
- package/dist/types/services/open-search/schemas/itemSearch.d.ts +9 -0
- package/dist/types/services/open-search/schemas/itemSearch.d.ts.map +1 -1
- package/dist/types/services/orders/resources/invoice-hdr.d.ts.map +1 -1
- package/dist/types/services/orders/resources/oe-hdr-salesrep.d.ts.map +1 -1
- package/dist/types/services/orders/resources/oe-hdr.d.ts.map +1 -1
- package/dist/types/services/orders/resources/pick-tickets.d.ts.map +1 -1
- package/dist/types/services/orders/resources/po-hdr.d.ts.map +1 -1
- package/dist/types/services/p21-apis/schemas.d.ts +6 -24
- package/dist/types/services/p21-apis/schemas.d.ts.map +1 -1
- package/dist/types/services/p21-pim/resources/items.d.ts.map +1 -1
- package/dist/types/services/p21-sism/resources/import.d.ts +1 -0
- package/dist/types/services/p21-sism/resources/import.d.ts.map +1 -1
- package/dist/types/services/p21-sism/schemas/import.d.ts +3 -0
- package/dist/types/services/p21-sism/schemas/import.d.ts.map +1 -1
- package/dist/types/services/payments/client.d.ts +5 -1
- package/dist/types/services/payments/client.d.ts.map +1 -1
- package/dist/types/services/payments/resources/index.d.ts +1 -0
- package/dist/types/services/payments/resources/index.d.ts.map +1 -1
- package/dist/types/services/payments/resources/paytrace.d.ts +154 -0
- package/dist/types/services/payments/resources/paytrace.d.ts.map +1 -0
- package/dist/types/services/payments/schemas/index.d.ts +1 -0
- package/dist/types/services/payments/schemas/index.d.ts.map +1 -1
- package/dist/types/services/payments/schemas/paytrace.d.ts +73 -0
- package/dist/types/services/payments/schemas/paytrace.d.ts.map +1 -0
- package/dist/types/services/pricing/schemas/priceEngine.d.ts +3 -0
- package/dist/types/services/pricing/schemas/priceEngine.d.ts.map +1 -1
- package/dist/types/services/smarty-streets/schemas/usLookup.d.ts +20 -2
- package/dist/types/services/smarty-streets/schemas/usLookup.d.ts.map +1 -1
- package/dist/types/services/ups/schemas/ratesShop.d.ts +53 -2
- package/dist/types/services/ups/schemas/ratesShop.d.ts.map +1 -1
- package/dist/types/services/vmi/resources/distributors.d.ts.map +1 -1
- package/dist/types/services/vmi/resources/inv-profile-hdr.d.ts.map +1 -1
- package/dist/types/services/vmi/resources/restock-hdr.d.ts.map +1 -1
- package/dist/types/services/vmi/resources/sections.d.ts.map +1 -1
- package/dist/types/services/vmi/resources/warehouse.d.ts.map +1 -1
- package/package.json +2 -7
- package/API-DISCOVERY.md +0 -255
- package/API-SERVICES.md +0 -227
- package/AUTHENTICATION.md +0 -371
- package/PERFORMANCE.md +0 -816
- package/QUICKSTART.md +0 -352
- package/TIPS-AND-TRICKS.md +0 -887
- package/dist/cjs/services/customers/resources/customer-list.d.ts +0 -42
- package/dist/cjs/services/customers/resources/customer-list.d.ts.map +0 -1
- package/dist/cjs/services/customers/resources/customer-list.js +0 -42
- package/dist/cjs/services/customers/resources/customer-list.js.map +0 -1
- package/dist/cjs/services/customers/resources/customer-lookup.d.ts +0 -42
- package/dist/cjs/services/customers/resources/customer-lookup.d.ts.map +0 -1
- package/dist/cjs/services/customers/resources/customer-lookup.js +0 -42
- package/dist/cjs/services/customers/resources/customer-lookup.js.map +0 -1
- package/dist/esm/services/customers/resources/customer-list.d.ts +0 -42
- package/dist/esm/services/customers/resources/customer-list.d.ts.map +0 -1
- package/dist/esm/services/customers/resources/customer-list.js +0 -38
- package/dist/esm/services/customers/resources/customer-list.js.map +0 -1
- package/dist/esm/services/customers/resources/customer-lookup.d.ts +0 -42
- package/dist/esm/services/customers/resources/customer-lookup.d.ts.map +0 -1
- package/dist/esm/services/customers/resources/customer-lookup.js +0 -38
- package/dist/esm/services/customers/resources/customer-lookup.js.map +0 -1
- package/dist/types/services/customers/resources/customer-list.d.ts +0 -42
- package/dist/types/services/customers/resources/customer-list.d.ts.map +0 -1
- package/dist/types/services/customers/resources/customer-lookup.d.ts +0 -42
- package/dist/types/services/customers/resources/customer-lookup.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,3776 +1,76 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @simpleapps-com/augur-api
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
TypeScript client library for Augur microservices.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Experience the Magic in 30 Seconds
|
|
8
|
-
|
|
9
|
-
```typescript
|
|
10
|
-
// Before: 35+ lines of authentication boilerplate
|
|
11
|
-
const userJwt = await getToken({ req: request });
|
|
12
|
-
if (!userJwt?.jwtToken) throw new Error('Authentication failed');
|
|
13
|
-
const api = new AugurAPI({ siteId: context.siteId, bearerToken: userJwt.jwtToken });
|
|
14
|
-
|
|
15
|
-
// After: Pure business intent ✨
|
|
16
|
-
const api = AugurAPI.fromContext(context);
|
|
17
|
-
|
|
18
|
-
// Ask for anything and find it instantly
|
|
19
|
-
const userOps = await api.findEndpoint('user management');
|
|
20
|
-
const inventory = await api.findEndpoint('stock levels');
|
|
21
|
-
const pricing = await api.findEndpoint('product pricing');
|
|
22
|
-
|
|
23
|
-
// Code that understands your business domain (v0.4.0 Path Mirroring)
|
|
24
|
-
const users = await api.joomla.users.list({ limit: 10 });
|
|
25
|
-
const content = await api.joomla.content.list({ categoryId: 1 });
|
|
26
|
-
const userGroups = await api.joomla.userGroups.list();
|
|
27
|
-
|
|
28
|
-
// NEW: OpenAPI path mirroring - exact path-to-client structure mapping
|
|
29
|
-
const aiAnswer = await api.gregorovich.chatGpt.ask.get({ question: "What is AI?" });
|
|
30
|
-
const searchResults = await api.openSearch.itemSearch.list({ query: "widgets" });
|
|
31
|
-
const attributes = await api.openSearch.itemSearch.attributes.list({ category: "tools" });
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Table of Contents
|
|
35
|
-
|
|
36
|
-
- [🚀 Quick Start Guide](./QUICKSTART.md) - **Experience the magic in under 5 minutes**
|
|
37
|
-
- [🆕 OpenAPI Path Mirroring (v0.4.0)](#-openapi-path-mirroring-v040) - **Revolutionary client structure mapping**
|
|
38
|
-
- [The Five Ideals in Action](#the-five-ideals-in-action)
|
|
39
|
-
- [🎯 AI-Powered Discovery System](#-ai-powered-discovery-system)
|
|
40
|
-
- [📖 API Discovery Guide](./API-DISCOVERY.md) - Natural language API navigation
|
|
41
|
-
- [Developer Experience Revolution](#developer-experience-revolution)
|
|
42
|
-
- [Context-Aware Architecture](#context-aware-architecture)
|
|
43
|
-
- [Prophet 21 Data Source Integration](#prophet-21-data-source-integration) - **ERP naming conventions and business context**
|
|
44
|
-
- [Service Architecture & Roadmap](#service-architecture--roadmap) - **Currently available and upcoming services**
|
|
45
|
-
- [Installation & First Steps](#installation--first-steps)
|
|
46
|
-
- [Intelligent Discovery Examples](#intelligent-discovery-examples)
|
|
47
|
-
- [Cross-Service Intelligence](#cross-service-intelligence)
|
|
48
|
-
- [Advanced Capabilities](#advanced-capabilities)
|
|
49
|
-
- [Platform Integration](#platform-integration)
|
|
50
|
-
- [Performance & Caching](#performance--caching)
|
|
51
|
-
- [Troubleshooting & Support](#troubleshooting--support)
|
|
52
|
-
|
|
53
|
-
## 🆕 OpenAPI Path Mirroring (v0.4.0)
|
|
54
|
-
|
|
55
|
-
**Revolutionary client architecture**: Every OpenAPI path segment maps directly to client structure, making API navigation intuitive and predictable.
|
|
56
|
-
|
|
57
|
-
### Path-to-Client Structure Magic ✨
|
|
58
|
-
|
|
59
|
-
```typescript
|
|
60
|
-
// OpenAPI Path → Client Structure (Exact Mapping)
|
|
61
|
-
// /chat-gpt/ask → client.chatGpt.ask.get()
|
|
62
|
-
// /documents → client.documents.list()
|
|
63
|
-
// /item-search → client.itemSearch.list()
|
|
64
|
-
// /item-search/attributes → client.itemSearch.attributes.list()
|
|
65
|
-
// /items/{invMastUid}/refresh → client.items.refresh.get(invMastUid)
|
|
66
|
-
|
|
67
|
-
const api = AugurAPI.fromContext(context);
|
|
68
|
-
|
|
69
|
-
// AI and Document Management (Gregorovich Service)
|
|
70
|
-
const aiResponse = await api.gregorovich.chatGpt.ask.get({
|
|
71
|
-
question: "How do I optimize inventory?"
|
|
72
|
-
});
|
|
73
|
-
const documents = await api.gregorovich.documents.list();
|
|
74
|
-
const ollamaResult = await api.gregorovich.ollama.generate.create({
|
|
75
|
-
prompt: "Generate product description"
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
// Advanced Search (OpenSearch Service)
|
|
79
|
-
const ping = await api.openSearch.ping.get();
|
|
80
|
-
const health = await api.openSearch.healthCheck.get();
|
|
81
|
-
const searchResults = await api.openSearch.itemSearch.list({ query: "tools" });
|
|
82
|
-
const searchAttrs = await api.openSearch.itemSearch.attributes.list({ query: "power" });
|
|
83
|
-
const refreshStatus = await api.openSearch.items.refresh.update({ force: true });
|
|
84
|
-
|
|
85
|
-
// Specific item operations with path parameters
|
|
86
|
-
const item = await api.openSearch.items.get(invMastUid);
|
|
87
|
-
const itemRefresh = await api.openSearch.items.refresh.get(invMastUid);
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### Dual API Pattern (Standard + Data Methods)
|
|
91
|
-
|
|
92
|
-
**Every endpoint provides two access patterns** for maximum flexibility:
|
|
93
|
-
|
|
94
|
-
```typescript
|
|
95
|
-
// Standard method - complete BaseResponse with metadata
|
|
96
|
-
const response = await api.gregorovich.chatGpt.ask.get({ question: "What is AI?" });
|
|
97
|
-
console.log(response.data.answer); // AI answer
|
|
98
|
-
console.log(response.status); // HTTP status
|
|
99
|
-
console.log(response.message); // Response message
|
|
100
|
-
|
|
101
|
-
// Data method - direct access to data only
|
|
102
|
-
const userData = await api.joomla.users.listData({ limit: 10 });
|
|
103
|
-
console.log(userData); // Direct access to users array
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### Schema Organization Revolution
|
|
107
|
-
|
|
108
|
-
**Path-based schema files** mirror the client structure:
|
|
109
|
-
|
|
110
|
-
```
|
|
111
|
-
services/gregorovich/schemas/
|
|
112
|
-
├── index.ts # Central exports with path-based aliases
|
|
113
|
-
├── chatGptAsk.ts # /chat-gpt/ask endpoint schemas
|
|
114
|
-
├── documents.ts # /documents endpoint schemas
|
|
115
|
-
├── healthCheck.ts # /health-check endpoint schemas
|
|
116
|
-
└── ollamaGenerate.ts # /ollama/generate endpoint schemas
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
**Benefits:**
|
|
120
|
-
- **Predictable Navigation**: OpenAPI paths = client structure
|
|
121
|
-
- **AI-Friendly**: Rich semantic metadata for intelligent suggestions
|
|
122
|
-
- **Type Safety**: Full TypeScript coverage with Zod validation
|
|
123
|
-
- **Dual Access**: Choose between full response or data-only patterns
|
|
124
|
-
- **Scalable Architecture**: Consistent patterns across 20+ microservices
|
|
125
|
-
|
|
126
|
-
## The Five Ideals in Action
|
|
127
|
-
|
|
128
|
-
This platform embodies the Five Ideals from The Unicorn Project, transforming how developers interact with enterprise APIs:
|
|
129
|
-
|
|
130
|
-
### Locality and Simplicity ✨
|
|
131
|
-
**No more coordination across 13 different APIs.** One unified interface eliminates architectural complexity.
|
|
132
|
-
|
|
133
|
-
```typescript
|
|
134
|
-
// Instead of learning 13 different authentication patterns
|
|
135
|
-
await joomlaAPI.authenticate(token);
|
|
136
|
-
await commerceAPI.setAuth(bearer);
|
|
137
|
-
await pricingAPI.login(credentials);
|
|
138
|
-
|
|
139
|
-
// One pattern rules them all
|
|
140
|
-
const api = AugurAPI.fromContext(context);
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### Focus, Flow, and Joy 🎯
|
|
144
|
-
**Zero context switching.** Intelligent discovery means never leaving your flow state.
|
|
145
|
-
|
|
146
|
-
```typescript
|
|
147
|
-
// No documentation hunting, no API reference browsing
|
|
148
|
-
const results = await api.findEndpoint('inventory management');
|
|
149
|
-
// Instantly find: api.vmi.warehouses.list, api.vmi.invProfileHdr.checkAvailability
|
|
150
|
-
|
|
151
|
-
// Your IDE becomes clairvoyant with comprehensive semantic JSDoc
|
|
152
|
-
api.vmi.invProfileHdr. // ← Auto-complete shows exactly what you need
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
### Improvement of Daily Work 🔄
|
|
156
|
-
**The platform learns your patterns** and suggests related operations across services.
|
|
157
|
-
|
|
158
|
-
```typescript
|
|
159
|
-
// When you work with users, it suggests related customer operations
|
|
160
|
-
const user = await api.joomla.users.get('123');
|
|
161
|
-
// Related suggestions: api.customers.customer.get, api.orders.salesRep.getOrders
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
### Psychological Safety 🛡️
|
|
165
|
-
**Fail fast with clear, actionable errors.** No more guessing what went wrong.
|
|
166
|
-
|
|
167
|
-
```typescript
|
|
168
|
-
try {
|
|
169
|
-
const api = AugurAPI.fromContext(context);
|
|
170
|
-
} catch (error) {
|
|
171
|
-
// Clear guidance: "Context missing siteId - check your context.siteId property"
|
|
172
|
-
// No blame, just solutions
|
|
173
|
-
}
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
### Customer Focus 📊
|
|
177
|
-
**Business context embedded** in every endpoint. Search by business intent, not technical implementation.
|
|
178
|
-
|
|
179
|
-
```typescript
|
|
180
|
-
// Search by what you're trying to accomplish
|
|
181
|
-
await api.findEndpoint('customer order history');
|
|
182
|
-
await api.findEndpoint('product recommendations');
|
|
183
|
-
await api.findEndpoint('inventory replenishment');
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
## AI-Powered Discovery System
|
|
187
|
-
|
|
188
|
-
**Never memorize API endpoints again.** The discovery system understands business context and finds functionality through natural language.
|
|
189
|
-
|
|
190
|
-
### Semantic Intelligence
|
|
191
|
-
|
|
192
|
-
Every endpoint includes AI-readable metadata:
|
|
193
|
-
|
|
194
|
-
```typescript
|
|
195
|
-
/**
|
|
196
|
-
* @searchTerms ["users", "authentication", "user management", "login"]
|
|
197
|
-
* @relatedEndpoints ["api.customers.customer.get", "api.joomla.userGroups.list"]
|
|
198
|
-
* @workflow ["user-onboarding", "authentication-flow", "user-administration"]
|
|
199
|
-
* @commonPatterns ["Get user profile", "List active users", "Create new account"]
|
|
200
|
-
*/
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
### Cross-Service Awareness
|
|
204
|
-
|
|
205
|
-
The system maps relationships between all active microservices (13 currently available, 26 total in development):
|
|
206
|
-
|
|
207
|
-
```typescript
|
|
208
|
-
// Working with users? It knows you might need customers too
|
|
209
|
-
const userEndpoints = await api.findEndpoint('user management');
|
|
210
|
-
// Suggests: joomla.users.list, customers.customer.get, orders.salesRep.getOrders
|
|
211
|
-
|
|
212
|
-
// Working with inventory? It connects you to pricing
|
|
213
|
-
const inventoryOps = await api.findEndpoint('stock management');
|
|
214
|
-
// Suggests: vmi.warehouses.list, pricing.getPrice, items.products.get
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
## Developer Experience Revolution
|
|
218
|
-
|
|
219
|
-
### Context-Aware Creation
|
|
220
|
-
Eliminate 70% of setup boilerplate with intelligent context extraction:
|
|
221
|
-
|
|
222
|
-
```typescript
|
|
223
|
-
// Traditional enterprise pattern (35+ lines)
|
|
224
|
-
const authentication = await authenticateUser(request);
|
|
225
|
-
if (!authentication.success) {
|
|
226
|
-
return handleAuthFailure(authentication.error);
|
|
227
|
-
}
|
|
228
|
-
const siteContext = await resolveSiteContext(authentication.user);
|
|
229
|
-
const apiConfig = {
|
|
230
|
-
siteId: siteContext.siteId,
|
|
231
|
-
bearerToken: authentication.jwtToken,
|
|
232
|
-
timeout: getConfiguredTimeout(),
|
|
233
|
-
retries: getRetryPolicy()
|
|
234
|
-
};
|
|
235
|
-
const api = new AugurAPI(apiConfig);
|
|
236
|
-
|
|
237
|
-
// Context-aware magic (1 line)
|
|
238
|
-
const api = AugurAPI.fromContext(context);
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
### Intelligent Method Discovery
|
|
242
|
-
Every method includes rich semantic metadata for AI assistants:
|
|
243
|
-
|
|
244
|
-
```typescript
|
|
245
|
-
// Ask your AI assistant: "Help me manage warehouse inventory"
|
|
246
|
-
// It instantly finds and suggests:
|
|
247
|
-
await api.vmi.warehouses.list({ customerId: 12345 });
|
|
248
|
-
await api.vmi.invProfileHdr.checkAvailability(warehouseId);
|
|
249
|
-
await api.vmi.invProfileHdr.replenish(warehouseId, { items });
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
### Factory Pattern Excellence
|
|
253
|
-
Sophisticated factory patterns create consistent, discoverable APIs:
|
|
254
|
-
|
|
255
|
-
```typescript
|
|
256
|
-
// Auto-generated from OpenAPI specs with semantic enhancement
|
|
257
|
-
export class VMIClient extends BaseServiceClient {
|
|
258
|
-
get warehouses() { return this.createWarehouseOperations(); }
|
|
259
|
-
get inventory() { return this.createInventoryOperations(); }
|
|
260
|
-
get distributors() { return this.createDistributorOperations(); }
|
|
261
|
-
}
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
## Installation & First Steps
|
|
5
|
+
## Installation
|
|
265
6
|
|
|
266
7
|
```bash
|
|
267
8
|
npm install @simpleapps-com/augur-api
|
|
268
9
|
```
|
|
269
10
|
|
|
270
|
-
|
|
11
|
+
## Quick Start
|
|
271
12
|
|
|
272
13
|
```typescript
|
|
273
14
|
import { AugurAPI } from '@simpleapps-com/augur-api';
|
|
274
15
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
// Discover capabilities (no documentation needed)
|
|
279
|
-
const services = await api.discover();
|
|
280
|
-
console.log(`Connected to ${services.length} active business services`);
|
|
281
|
-
|
|
282
|
-
// Find what you need (natural language)
|
|
283
|
-
const userStuff = await api.findEndpoint('user management');
|
|
284
|
-
const inventoryStuff = await api.findEndpoint('stock levels');
|
|
285
|
-
|
|
286
|
-
// Work with the actual Joomla API
|
|
287
|
-
const users = await api.joomla.users.list({
|
|
288
|
-
limit: 10
|
|
289
|
-
});
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
## Intelligent Discovery Examples
|
|
293
|
-
|
|
294
|
-
### Business Context Understanding
|
|
295
|
-
|
|
296
|
-
The platform knows your business domain and connects related operations:
|
|
297
|
-
|
|
298
|
-
```typescript
|
|
299
|
-
// Search by business intent, not technical endpoints
|
|
300
|
-
const userOps = await api.findEndpoint('customer account management');
|
|
301
|
-
// Returns:
|
|
302
|
-
// - api.joomla.users.list (user authentication)
|
|
303
|
-
// - api.customers.customer.get (customer profiles)
|
|
304
|
-
// - api.orders.salesRep.getOrders (order history)
|
|
305
|
-
|
|
306
|
-
const inventoryOps = await api.findEndpoint('stock replenishment');
|
|
307
|
-
// Returns:
|
|
308
|
-
// - api.vmi.invProfileHdr.checkAvailability (current levels)
|
|
309
|
-
// - api.vmi.invProfileHdr.replenish (automated ordering)
|
|
310
|
-
// - api.pricing.getPrice (cost calculations)
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
### Workflow-Aware Suggestions
|
|
314
|
-
|
|
315
|
-
Working on one task? The system suggests the next logical steps:
|
|
316
|
-
|
|
317
|
-
```typescript
|
|
318
|
-
// Create a user account
|
|
319
|
-
const newUser = await api.joomla.users.create({
|
|
320
|
-
username: 'john.doe',
|
|
321
|
-
email: 'john@company.com'
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
// System knows you might need to:
|
|
325
|
-
// 1. Set up customer profile: api.customers.customer.create()
|
|
326
|
-
// 2. Assign user groups: api.joomla.userGroups.createMapping()
|
|
327
|
-
// 3. Check permissions: api.joomla.users.groups.list()
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
### Cross-Service Intelligence
|
|
331
|
-
|
|
332
|
-
The discovery system maps business workflows across all active microservices:
|
|
333
|
-
|
|
334
|
-
```typescript
|
|
335
|
-
// E-commerce workflow discovery
|
|
336
|
-
const ecommerceFlow = await api.findEndpoint('online shopping');
|
|
337
|
-
// Suggests complete customer journey:
|
|
338
|
-
// - Product search: api.opensearch.itemSearch.search()
|
|
339
|
-
// - Pricing: api.pricing.getPrice()
|
|
340
|
-
// - Cart management: api.commerce.cartHeaders.lookup()
|
|
341
|
-
// - Checkout: api.commerce.checkout.get()
|
|
342
|
-
// - Payment: api.payments.unified.transactionSetup()
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
## Context-Aware Architecture
|
|
346
|
-
|
|
347
|
-
### Intelligent Context Extraction
|
|
348
|
-
|
|
349
|
-
The `fromContext()` method understands various context patterns:
|
|
350
|
-
|
|
351
|
-
```typescript
|
|
352
|
-
// Middleware context
|
|
353
|
-
const api = AugurAPI.fromContext({
|
|
354
|
-
siteId: req.headers['x-site-id'],
|
|
355
|
-
jwt: req.headers.authorization?.replace('Bearer ', ''),
|
|
356
|
-
userId: req.user.id
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
// Tool handler context
|
|
360
|
-
const api = AugurAPI.fromContext({
|
|
361
|
-
siteId: context.siteId,
|
|
362
|
-
bearerToken: context.authentication.token,
|
|
363
|
-
parameters: context.requestParams
|
|
364
|
-
});
|
|
365
|
-
|
|
366
|
-
// Next.js context
|
|
367
|
-
const api = AugurAPI.fromContext({
|
|
368
|
-
siteId: process.env.NEXT_PUBLIC_SITE_ID,
|
|
369
|
-
jwt: session.accessToken
|
|
370
|
-
});
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
### Factory Pattern Excellence
|
|
374
|
-
|
|
375
|
-
Each service client is lazily instantiated with sophisticated caching:
|
|
376
|
-
|
|
377
|
-
```typescript
|
|
378
|
-
// Clients are created on-demand and cached
|
|
379
|
-
const joomla1 = api.joomla; // Creates new instance
|
|
380
|
-
const joomla2 = api.joomla; // Returns cached instance
|
|
381
|
-
console.log(joomla1 === joomla2); // true
|
|
382
|
-
|
|
383
|
-
// Token changes invalidate all clients automatically
|
|
384
|
-
api.setAuthToken('new-token');
|
|
385
|
-
const joomla3 = api.joomla; // Creates fresh instance with new token
|
|
386
|
-
console.log(joomla1 === joomla3); // false
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
### Semantic Method Generation
|
|
390
|
-
|
|
391
|
-
Every endpoint includes rich semantic metadata for AI discovery:
|
|
392
|
-
|
|
393
|
-
```typescript
|
|
394
|
-
/**
|
|
395
|
-
* List site settings with intelligent filtering and caching
|
|
396
|
-
* @fullPath api.agrSite.settings.list
|
|
397
|
-
* @service agr-site
|
|
398
|
-
* @domain site-content-management
|
|
399
|
-
* @searchTerms ["settings", "configuration", "site management", "admin"]
|
|
400
|
-
* @relatedEndpoints ["api.agrSite.settings.get", "api.agrSite.settings.update"]
|
|
401
|
-
* @workflow ["site-administration", "configuration-management"]
|
|
402
|
-
* @commonPatterns ["Get all settings", "Filter by service", "Cache configuration"]
|
|
403
|
-
* @discoverable true
|
|
404
|
-
*/
|
|
405
|
-
async list(params?: SettingListParams): Promise<SettingListResponse> {
|
|
406
|
-
// Implementation uses sophisticated base class patterns
|
|
407
|
-
}
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
## Advanced Capabilities
|
|
411
|
-
|
|
412
|
-
### Intelligent Service Discovery
|
|
413
|
-
|
|
414
|
-
The discovery system provides both exploration and targeted search:
|
|
415
|
-
|
|
416
|
-
```typescript
|
|
417
|
-
// Comprehensive service topology
|
|
418
|
-
const services = await api.discover();
|
|
419
|
-
console.log(`Platform connected to ${services.length} active business services`);
|
|
420
|
-
|
|
421
|
-
// Each service reveals its capabilities
|
|
422
|
-
services.forEach(service => {
|
|
423
|
-
console.log(`${service.serviceName}: ${service.endpointCount} operations available`);
|
|
424
|
-
console.log(`Business domain: ${service.description}`);
|
|
425
|
-
});
|
|
426
|
-
|
|
427
|
-
// Targeted functionality search with intelligent scoring
|
|
428
|
-
const results = await api.findEndpoint('inventory management', {
|
|
429
|
-
minScore: 0.1, // Relevance threshold
|
|
430
|
-
maxResults: 10, // Limit results
|
|
431
|
-
service: 'vmi', // Optional service filter
|
|
432
|
-
domain: 'inventory-management', // Business domain filter
|
|
433
|
-
readOnly: true // Only read operations
|
|
434
|
-
});
|
|
435
|
-
|
|
436
|
-
// Results include relevance scores and match reasoning
|
|
437
|
-
results.forEach(result => {
|
|
438
|
-
console.log(`${result.endpoint.fullPath} (score: ${result.score})`);
|
|
439
|
-
console.log(`Match reason: ${result.matchReason}`);
|
|
440
|
-
});
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
### Multi-Method Pattern Innovation
|
|
444
|
-
|
|
445
|
-
Every endpoint offers dual access patterns for maximum flexibility:
|
|
446
|
-
|
|
447
|
-
```typescript
|
|
448
|
-
// Full response with metadata (standard pattern)
|
|
449
|
-
const response = await api.joomla.users.list({ limit: 10 });
|
|
450
|
-
console.log(`Found ${response.data.length} users`);
|
|
451
|
-
console.log(`Total available: ${response.totalResults}`);
|
|
452
|
-
console.log(`Status: ${response.message}`);
|
|
453
|
-
|
|
454
|
-
// Data-only access (streamlined pattern)
|
|
455
|
-
const users = await api.joomla.users.listData({ limit: 10 });
|
|
456
|
-
console.log(users); // Direct array access, no wrapper
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
## Prophet 21 Data Source Integration
|
|
460
|
-
|
|
461
|
-
Many API endpoints reflect Prophet 21 ERP system naming conventions and table structures. This provides direct mapping from your business processes to API operations.
|
|
462
|
-
|
|
463
|
-
### Understanding Prophet 21 Naming Patterns
|
|
464
|
-
|
|
465
|
-
The Path-Function Alignment Pattern preserves Prophet 21 table naming for user recognition:
|
|
466
|
-
|
|
467
|
-
```typescript
|
|
468
|
-
// Prophet 21 Table → API Endpoint → Client Structure
|
|
469
|
-
// inv_mast table → /inv-mast → api.items.invMast
|
|
470
|
-
// oe_hdr table → /oe-hdr → api.orders.oeHdr
|
|
471
|
-
// job_price_hdr table → /job-price-hdr → api.pricing.jobPriceHdr
|
|
472
|
-
// restock_hdr table → /restock-hdr → api.vmi.restockHdr
|
|
473
|
-
// inv_profile_hdr table → /inv-profile-hdr → api.vmi.invProfileHdr
|
|
474
|
-
|
|
475
|
-
// Examples with Prophet 21 context:
|
|
476
|
-
const inventory = await api.items.invMast.get(12345); // Inventory master record
|
|
477
|
-
const order = await api.orders.oeHdr.get(67890); // Order entry header
|
|
478
|
-
const pricing = await api.pricing.jobPriceHdr.get(111); // Job pricing header
|
|
479
|
-
const restock = await api.vmi.restockHdr.get(222); // Restocking header
|
|
480
|
-
const profile = await api.vmi.invProfileHdr.get(333); // Inventory profile header
|
|
481
|
-
```
|
|
482
|
-
|
|
483
|
-
### Prophet 21 Business Context
|
|
484
|
-
|
|
485
|
-
Understanding the ERP context helps predict API behavior:
|
|
486
|
-
|
|
487
|
-
```typescript
|
|
488
|
-
// Inventory Management (Prophet 21 inv_mast context)
|
|
489
|
-
const itemDetails = await api.items.invMast.get(itemId);
|
|
490
|
-
const locations = await api.items.invMast.locations.list(itemId); // Physical locations
|
|
491
|
-
const alternates = await api.items.invMast.alternateCode.list(itemId); // Alternate part numbers
|
|
492
|
-
|
|
493
|
-
// Order Processing (Prophet 21 oe_hdr context)
|
|
494
|
-
const orderHeader = await api.orders.oeHdr.get(orderId);
|
|
495
|
-
const salesRep = await api.orders.oeHdrSalesrep.get(orderId); // Sales representative info
|
|
496
|
-
const lineItems = await api.orders.oeHdr.lines.list(orderId); // Order line details
|
|
497
|
-
|
|
498
|
-
// VMI Operations (Prophet 21 inventory management context)
|
|
499
|
-
const profileHeader = await api.vmi.invProfileHdr.get(profileId); // VMI profile setup
|
|
500
|
-
const restockInfo = await api.vmi.restockHdr.get(restockId); // Restocking instructions
|
|
501
|
-
const warehouseData = await api.vmi.warehouse.get(warehouseId); // Warehouse details
|
|
502
|
-
```
|
|
503
|
-
|
|
504
|
-
### Migration from Legacy Naming
|
|
505
|
-
|
|
506
|
-
If you're familiar with conceptual API naming, here's the Prophet 21 mapping:
|
|
507
|
-
|
|
508
|
-
```typescript
|
|
509
|
-
// Legacy Conceptual → Prophet 21 Aligned
|
|
510
|
-
client.inventory → client.invMast // Inventory master
|
|
511
|
-
client.categories → client.itemCategory // Item categories
|
|
512
|
-
client.orders → client.oeHdr // Order entry header
|
|
513
|
-
client.salesRep → client.oeHdrSalesrep // Order header sales rep
|
|
514
|
-
client.purchaseOrders → client.poHdr // Purchase order header
|
|
515
|
-
client.invoices → client.invoiceHdr // Invoice header
|
|
516
|
-
client.inventoryProfiles → client.invProfileHdr // Inventory profile header
|
|
517
|
-
client.restocking → client.restockHdr // Restock header
|
|
518
|
-
client.calculateTax → client.taxEngine.calculate // Tax calculation engine
|
|
519
|
-
client.jobPriceHeaders → client.jobPriceHdr // Job price header
|
|
520
|
-
```
|
|
521
|
-
|
|
522
|
-
This alignment ensures that developers familiar with Prophet 21 can immediately understand the API structure and predict endpoint behavior based on their ERP knowledge.
|
|
523
|
-
|
|
524
|
-
### Sophisticated Caching Architecture
|
|
525
|
-
|
|
526
|
-
Intelligent edge caching with business-aware TTL policies:
|
|
527
|
-
|
|
528
|
-
```typescript
|
|
529
|
-
// Cache strategy varies by data volatility
|
|
530
|
-
const categories = await api.items.categories.list({
|
|
531
|
-
edgeCache: 8 // Static reference data - 8 hours
|
|
532
|
-
});
|
|
533
|
-
|
|
534
|
-
const pricing = await api.pricing.getPrice({
|
|
535
|
-
customerId: 12345,
|
|
536
|
-
itemId: 'STANDARD-ITEM',
|
|
537
|
-
quantity: 10,
|
|
538
|
-
edgeCache: 3 // Standard pricing - 3 hours
|
|
539
|
-
});
|
|
540
|
-
|
|
541
|
-
const cart = await api.commerce.cartHeaders.list({
|
|
542
|
-
userId: 123,
|
|
543
|
-
edgeCache: 1 // Volatile user data - 1 hour only
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
// Real-time operations never cached
|
|
547
|
-
const auth = await api.joomla.users.verifyPassword({
|
|
548
|
-
username: 'user',
|
|
549
|
-
password: 'pass'
|
|
550
|
-
// No edgeCache - authentication must be real-time
|
|
551
|
-
});
|
|
552
|
-
```
|
|
553
|
-
|
|
554
|
-
## Service Architecture & Roadmap
|
|
555
|
-
|
|
556
|
-
### Available Services (26 Active)
|
|
557
|
-
|
|
558
|
-
The Augur Platform exposes 26 fully-integrated business services with comprehensive AI discovery and semantic documentation:
|
|
559
|
-
|
|
560
|
-
| Service | Business Domain | Key Capabilities | Status |
|
|
561
|
-
|---------|----------------|------------------|--------|
|
|
562
|
-
| **joomla** | Content & User Management | User authentication, content management, permissions | ✅ Active |
|
|
563
|
-
| **commerce** | E-commerce Operations | Shopping cart, checkout, recommendations | ✅ Active |
|
|
564
|
-
| **pricing** | Price Calculations | Dynamic pricing, job pricing, tax calculations | ✅ Active |
|
|
565
|
-
| **vmi** | Vendor Managed Inventory | Warehouse operations, inventory profiles, restocking | ✅ Active |
|
|
566
|
-
| **opensearch** | Search & Discovery | Product search, faceted navigation, search analytics | ✅ Active |
|
|
567
|
-
| **items** | Product Catalog | Product management, categories, attributes, variants | ✅ Active |
|
|
568
|
-
| **legacy** | Legacy Integration | State lookups, order history, also-bought recommendations | ✅ Active |
|
|
569
|
-
| **nexus** | Warehouse Management | Bin transfers, receiving, shipping operations | ✅ Active |
|
|
570
|
-
| **agrSite** | AGR Site Operations | Transcripts, notifications, settings management | ✅ Active |
|
|
571
|
-
| **customers** | Customer Management | Customer profiles, contacts, addresses, order history | ✅ Active |
|
|
572
|
-
| **orders** | Order Processing | Order management, invoices, purchase orders, sales rep | ✅ Active |
|
|
573
|
-
| **p21Pim** | Product Information | AI suggestions, inventory extensions, product data | ✅ Active |
|
|
574
|
-
| **payments** | Payment Processing | Payment methods, unified payments, element integration | ✅ Active |
|
|
575
|
-
|
|
576
|
-
### Additional Services (13 More Active)
|
|
577
|
-
|
|
578
|
-
The platform also includes these specialized and integration services:
|
|
579
|
-
|
|
580
|
-
| Service | Business Domain | Key Capabilities | Status |
|
|
581
|
-
|---------|----------------|------------------|--------|
|
|
582
|
-
| **agrInfo** | AGR Information Services | Business intelligence, reporting | ✅ Active |
|
|
583
|
-
| **agrWork** | AGR Workflow Services | Workflow automation, task management | ✅ Active |
|
|
584
|
-
| **avalara** | Tax Calculation | Advanced tax calculations, compliance | ✅ Active |
|
|
585
|
-
| **brandFolder** | Brand Asset Management | Brand assets, marketing materials | ✅ Active |
|
|
586
|
-
| **gregorovich** | Gregorovich Integration | Third-party system integration | ✅ Active |
|
|
587
|
-
| **logistics** | Logistics & Shipping | Advanced shipping, logistics optimization | ✅ Active |
|
|
588
|
-
| **p21Apis** | P21 API Integration | Direct P21 system integration | ✅ Active |
|
|
589
|
-
| **p21Core** | P21 Core Services | Core P21 business objects | ✅ Active |
|
|
590
|
-
| **p21Sism** | P21 SISM Integration | P21 system integration & synchronization | ✅ Active |
|
|
591
|
-
| **shipping** | Shipping Services | Shipping calculations, carrier integration | ✅ Active |
|
|
592
|
-
| **slack** | Slack Integration | Team notifications, workflow integration | ✅ Active |
|
|
593
|
-
| **smartyStreets** | Address Validation | Address verification, standardization | ✅ Active |
|
|
594
|
-
| **ups** | UPS Integration | UPS shipping, tracking, rate calculations | ✅ Active |
|
|
595
|
-
|
|
596
|
-
### Architecture Benefits
|
|
597
|
-
|
|
598
|
-
With all 26 services active, the platform provides:
|
|
599
|
-
- **Complete Business Coverage**: From user management to shipping integration
|
|
600
|
-
- **Unified API Surface**: Consistent patterns across all business domains
|
|
601
|
-
- **AI-Powered Discovery**: Natural language navigation across 26+ service endpoints
|
|
602
|
-
- **Cross-Service Intelligence**: Business workflows that span multiple services
|
|
603
|
-
|
|
604
|
-
## Power Features (Hidden Gems)
|
|
605
|
-
|
|
606
|
-
**Unlock the full potential** of the Augur API with these advanced features that dramatically improve your development experience:
|
|
607
|
-
|
|
608
|
-
### Data Methods Pattern ⭐ NEW!
|
|
609
|
-
|
|
610
|
-
Every endpoint provides both complete responses AND streamlined data-only access:
|
|
611
|
-
|
|
612
|
-
```typescript
|
|
613
|
-
// Standard pattern - full response with metadata
|
|
614
|
-
const response = await api.joomla.users.list({ limit: 10 });
|
|
615
|
-
console.log(`Found ${response.data.length} users`);
|
|
616
|
-
console.log(`Total available: ${response.totalResults}`);
|
|
617
|
-
console.log(`Response status: ${response.status}`);
|
|
618
|
-
|
|
619
|
-
// Data-only pattern - direct access to the data array ⚡
|
|
620
|
-
const users = await api.joomla.users.listData({ limit: 10 });
|
|
621
|
-
console.log(users); // Direct User[] array, no wrapper
|
|
622
|
-
|
|
623
|
-
// Single item data access
|
|
624
|
-
const user = await api.joomla.users.getData('123');
|
|
625
|
-
console.log(user); // Direct User object, no response wrapper
|
|
626
|
-
|
|
627
|
-
// Works across ALL services
|
|
628
|
-
const products = await api.opensearch.itemSearch.searchData({
|
|
629
|
-
q: 'electrical wire',
|
|
630
|
-
searchType: 'query',
|
|
631
|
-
size: 20
|
|
632
|
-
}); // Direct item array
|
|
633
|
-
|
|
634
|
-
const pricing = await api.pricing.getPriceData({
|
|
635
|
-
customerId: 12345,
|
|
636
|
-
itemId: 'WIRE-123',
|
|
637
|
-
quantity: 10
|
|
638
|
-
}); // Direct pricing object
|
|
639
|
-
```
|
|
640
|
-
|
|
641
|
-
**Benefits:**
|
|
642
|
-
- **50% less code** for data extraction
|
|
643
|
-
- **Cleaner business logic** without response unwrapping
|
|
644
|
-
- **Same caching and validation** as standard methods
|
|
645
|
-
- **Consistent pattern** across all active microservices
|
|
646
|
-
|
|
647
|
-
### Advanced Discovery Filtering
|
|
648
|
-
|
|
649
|
-
Go beyond basic search with sophisticated filtering options:
|
|
650
|
-
|
|
651
|
-
```typescript
|
|
652
|
-
// Precision search with advanced filtering
|
|
653
|
-
const endpoints = await api.findEndpoint('user management', {
|
|
654
|
-
// Relevance threshold (0.0 to 1.0)
|
|
655
|
-
minScore: 0.7, // Only highly relevant matches
|
|
656
|
-
|
|
657
|
-
// Limit results
|
|
658
|
-
maxResults: 5, // Top 5 matches only
|
|
659
|
-
|
|
660
|
-
// Service-specific filtering
|
|
661
|
-
service: 'joomla', // Only Joomla service endpoints
|
|
662
|
-
|
|
663
|
-
// Business domain filtering
|
|
664
|
-
domain: 'user-management', // Only user management domain
|
|
665
|
-
|
|
666
|
-
// Operation type filtering
|
|
667
|
-
readOnly: true, // Only read operations (GET requests)
|
|
668
|
-
writeOnly: false, // Exclude write operations
|
|
669
|
-
|
|
670
|
-
// Response format preferences
|
|
671
|
-
includeMetadata: true, // Include match reasoning and scores
|
|
672
|
-
sortBy: 'relevance' // Sort by relevance score (default: 'relevance' | 'alphabetical')
|
|
673
|
-
});
|
|
674
|
-
|
|
675
|
-
// Rich result information
|
|
676
|
-
endpoints.forEach(result => {
|
|
677
|
-
console.log(`🔍 ${result.endpoint.fullPath}`);
|
|
678
|
-
console.log(` Score: ${result.score} | Reason: ${result.matchReason}`);
|
|
679
|
-
console.log(` Domain: ${result.endpoint.domain} | Service: ${result.endpoint.service}`);
|
|
680
|
-
console.log(` Method: ${result.endpoint.method} | Read-only: ${result.endpoint.readOnly}`);
|
|
681
|
-
});
|
|
682
|
-
|
|
683
|
-
// Cross-service workflow discovery
|
|
684
|
-
const ecommerceFlow = await api.findEndpoint('complete customer order', {
|
|
685
|
-
domain: ['commerce', 'pricing', 'inventory'], // Multiple domains
|
|
686
|
-
includeWorkflow: true, // Include workflow relationships
|
|
687
|
-
minScore: 0.5
|
|
688
|
-
});
|
|
689
|
-
|
|
690
|
-
// Results include cross-service relationships
|
|
691
|
-
ecommerceFlow.forEach(result => {
|
|
692
|
-
console.log(`${result.endpoint.fullPath} → Related: ${result.relatedEndpoints?.join(', ')}`);
|
|
693
|
-
});
|
|
694
|
-
```
|
|
695
|
-
|
|
696
|
-
### Debug Utilities and Troubleshooting
|
|
697
|
-
|
|
698
|
-
Built-in debugging tools help you understand what's happening under the hood:
|
|
699
|
-
|
|
700
|
-
```typescript
|
|
701
|
-
// Create detailed debug information for any request
|
|
702
|
-
const debugInfo = api.joomla.users.createDebugInfo(
|
|
703
|
-
{ limit: 10, offset: 0 }, // Your parameters
|
|
704
|
-
{ edgeCache: 2 } // Request config
|
|
705
|
-
);
|
|
706
|
-
|
|
707
|
-
console.log('🔧 Debug Information:');
|
|
708
|
-
console.log('Expected Parameters:', debugInfo.expectedParams);
|
|
709
|
-
console.log('Provided Parameters:', debugInfo.providedParams);
|
|
710
|
-
console.log('Validation Results:', debugInfo.validation);
|
|
711
|
-
console.log('Cache Strategy:', debugInfo.cacheInfo);
|
|
712
|
-
console.log('Generated URL:', debugInfo.finalURL);
|
|
713
|
-
|
|
714
|
-
// Validate parameters before making requests
|
|
715
|
-
const validation = api.pricing.validatePriceParams({
|
|
716
|
-
customerId: 12345,
|
|
717
|
-
itemId: 'INVALID', // This might fail validation
|
|
718
|
-
quantity: -5 // Negative quantity should fail
|
|
16
|
+
const api = new AugurAPI({
|
|
17
|
+
siteId: process.env.AUGUR_SITE_ID,
|
|
18
|
+
bearerToken: process.env.AUGUR_TOKEN,
|
|
719
19
|
});
|
|
720
20
|
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
console.log(` Expected: ${error.expected} | Received: ${error.received}`);
|
|
726
|
-
});
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
// Request tracing for performance analysis
|
|
730
|
-
api.enableRequestTracing(true);
|
|
731
|
-
|
|
732
|
-
const users = await api.joomla.users.list({ limit: 10 });
|
|
733
|
-
|
|
734
|
-
// Get trace information
|
|
735
|
-
const trace = api.getLastRequestTrace();
|
|
736
|
-
console.log('🚀 Performance Trace:');
|
|
737
|
-
console.log(` Total Time: ${trace.totalTime}ms`);
|
|
738
|
-
console.log(` Network Time: ${trace.networkTime}ms`);
|
|
739
|
-
console.log(` Validation Time: ${trace.validationTime}ms`);
|
|
740
|
-
console.log(` Cache Status: ${trace.cacheStatus}`);
|
|
741
|
-
console.log(` Request ID: ${trace.requestId}`);
|
|
742
|
-
```
|
|
743
|
-
|
|
744
|
-
### Automatic Parameter Extraction
|
|
745
|
-
|
|
746
|
-
The system intelligently maps URL templates to method parameters:
|
|
747
|
-
|
|
748
|
-
```typescript
|
|
749
|
-
// URL template: /bin-transfer/{binTransferHdrUid}
|
|
750
|
-
// Automatically creates: (id) => { binTransferHdrUid: id }
|
|
751
|
-
const binTransfer = await api.nexus.binTransfers.get(12345);
|
|
752
|
-
// Internally maps: 12345 → { binTransferHdrUid: 12345 }
|
|
753
|
-
|
|
754
|
-
// URL template: /customer/{customerId}/orders/{orderId}
|
|
755
|
-
// Automatically creates: (customerId, orderId) => { customerId, orderId }
|
|
756
|
-
const order = await api.customers.customer.orders.get(123, 456);
|
|
757
|
-
// Internally maps: (123, 456) → { customerId: 123, orderId: 456 }
|
|
758
|
-
|
|
759
|
-
// Complex URL templates with multiple parameters
|
|
760
|
-
// URL template: /pricing/job/{jobPriceHdrUid}/lines/{jobPriceLineUid}
|
|
761
|
-
const jobPriceLine = await api.pricing.jobPriceLines.get(123, 456);
|
|
762
|
-
// Internally maps: (123, 456) → { jobPriceHdrUid: 123, jobPriceLineUid: 456 }
|
|
763
|
-
|
|
764
|
-
// See the mapping for any endpoint
|
|
765
|
-
const mapping = api.nexus.binTransfers.getParameterMapping();
|
|
766
|
-
console.log('URL Template:', mapping.urlTemplate);
|
|
767
|
-
console.log('Parameter Map:', mapping.parameterMap);
|
|
768
|
-
console.log('Required Params:', mapping.requiredParams);
|
|
769
|
-
console.log('Optional Params:', mapping.optionalParams);
|
|
770
|
-
|
|
771
|
-
// Validate parameter mapping before calling
|
|
772
|
-
const isValid = api.nexus.binTransfers.validateParameterMapping(12345);
|
|
773
|
-
if (!isValid.valid) {
|
|
774
|
-
console.log('Parameter mapping issues:', isValid.errors);
|
|
775
|
-
}
|
|
21
|
+
// Access any service via api.{serviceName}
|
|
22
|
+
const items = await api.items.invMast.list({ limit: 10 });
|
|
23
|
+
const customers = await api.customers.customer.list({ limit: 10 });
|
|
24
|
+
const orders = await api.orders.orders.lookup({ limit: 10 });
|
|
776
25
|
```
|
|
777
26
|
|
|
778
|
-
|
|
27
|
+
## Service Access Pattern
|
|
779
28
|
|
|
780
|
-
|
|
29
|
+
All services are accessed through the unified `AugurAPI` client:
|
|
781
30
|
|
|
782
31
|
```typescript
|
|
783
|
-
//
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
// - request ID for tracing
|
|
790
|
-
});
|
|
791
|
-
|
|
792
|
-
console.log('Generated request:', smartRequest);
|
|
793
|
-
// {
|
|
794
|
-
// userId: 123,
|
|
795
|
-
// siteId: 'your-site-id',
|
|
796
|
-
// _timestamp: 1693934400000,
|
|
797
|
-
// _requestId: 'req_abc123',
|
|
798
|
-
// _cacheKey: 'cart_headers_123_your-site-id'
|
|
799
|
-
// }
|
|
800
|
-
|
|
801
|
-
// Request templating for repeated operations
|
|
802
|
-
const userTemplate = api.joomla.users.createRequestTemplate({
|
|
803
|
-
limit: 50,
|
|
804
|
-
orderBy: 'username|ASC'
|
|
805
|
-
});
|
|
806
|
-
|
|
807
|
-
// Reuse template with variations
|
|
808
|
-
const activeUsers = await userTemplate.execute({ q: 'active' });
|
|
809
|
-
const adminUsers = await userTemplate.execute({ groupId: 1 });
|
|
810
|
-
const recentUsers = await userTemplate.execute({
|
|
811
|
-
createdSince: '2024-01-01',
|
|
812
|
-
limit: 20 // Override template default
|
|
813
|
-
});
|
|
32
|
+
api.items // Items service
|
|
33
|
+
api.customers // Customers service
|
|
34
|
+
api.orders // Orders service
|
|
35
|
+
api.pricing // Pricing service
|
|
36
|
+
api.commerce // Commerce service
|
|
37
|
+
// ... 27 services total
|
|
814
38
|
```
|
|
815
39
|
|
|
816
|
-
##
|
|
40
|
+
## Documentation
|
|
817
41
|
|
|
818
|
-
|
|
|
819
|
-
|
|
820
|
-
| **
|
|
821
|
-
| **
|
|
822
|
-
| **
|
|
823
|
-
| **
|
|
824
|
-
| **Cross-Service Intelligence** | Business workflow awareness | Relationship mapping across all active microservices |
|
|
825
|
-
| **AI Assistant Integration** | Code that almost writes itself | Rich semantic metadata in every endpoint |
|
|
826
|
-
| **Type Safety** | Runtime validation guarantee | Zod schema validation on all requests/responses |
|
|
827
|
-
| **Multi-Platform Support** | Universal JavaScript compatibility | React, React Native, Next.js, Node.js, Electron |
|
|
828
|
-
|
|
829
|
-
## Installation
|
|
42
|
+
| Resource | URL |
|
|
43
|
+
|----------|-----|
|
|
44
|
+
| **Full API Reference** | https://augur-api.info |
|
|
45
|
+
| **Endpoint Hints** | `https://{service}.augur-api.com/llms.txt` |
|
|
46
|
+
| **Parameters** | `https://{service}.augur-api.com/endpoints.jsonl` |
|
|
47
|
+
| **OpenAPI Spec** | `https://{service}.augur-api.com/openapi.json` |
|
|
830
48
|
|
|
831
|
-
|
|
832
|
-
npm install @simpleapps-com/augur-api
|
|
833
|
-
# or
|
|
834
|
-
yarn add @simpleapps-com/augur-api
|
|
835
|
-
# or
|
|
836
|
-
pnpm add @simpleapps-com/augur-api
|
|
837
|
-
```
|
|
49
|
+
### Example: Items Service
|
|
838
50
|
|
|
839
|
-
|
|
51
|
+
- https://items.augur-api.com/llms.txt
|
|
52
|
+
- https://items.augur-api.com/endpoints.jsonl
|
|
53
|
+
- https://items.augur-api.com/openapi.json
|
|
840
54
|
|
|
841
|
-
|
|
842
|
-
- TypeScript >= 4.5.0 (for TypeScript projects)
|
|
55
|
+
Each `llms.txt` lists all other available services for discovery.
|
|
843
56
|
|
|
844
|
-
##
|
|
57
|
+
## Authentication
|
|
845
58
|
|
|
846
|
-
|
|
59
|
+
All endpoints require:
|
|
60
|
+
- `siteId` - Site identifier
|
|
61
|
+
- `bearerToken` - Bearer authentication token
|
|
847
62
|
|
|
848
63
|
```typescript
|
|
849
|
-
import { AugurAPI } from '@simpleapps-com/augur-api';
|
|
850
|
-
|
|
851
|
-
// Traditional approach - manual configuration
|
|
852
64
|
const api = new AugurAPI({
|
|
853
|
-
siteId: 'your-site-id',
|
|
854
|
-
bearerToken: 'your-
|
|
855
|
-
});
|
|
856
|
-
|
|
857
|
-
// Context-aware approach (recommended) - eliminates boilerplate
|
|
858
|
-
const api = AugurAPI.fromContext(context);
|
|
859
|
-
|
|
860
|
-
// Make your first API call
|
|
861
|
-
const users = await api.joomla.users.list({
|
|
862
|
-
limit: 10,
|
|
863
|
-
edgeCache: 2 // Cache for 2 hours
|
|
65
|
+
siteId: 'your-site-id',
|
|
66
|
+
bearerToken: 'your-bearer-token',
|
|
864
67
|
});
|
|
865
|
-
|
|
866
|
-
console.log(`Found ${users.data.length} users`);
|
|
867
68
|
```
|
|
868
69
|
|
|
869
|
-
|
|
70
|
+
## For AI Agents
|
|
870
71
|
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
```typescript
|
|
874
|
-
import { AugurAPI, type AugurContext } from '@simpleapps-com/augur-api';
|
|
875
|
-
|
|
876
|
-
// Your context object (common in tool handlers, middleware, etc.)
|
|
877
|
-
const context: AugurContext = {
|
|
878
|
-
siteId: 'my-site-123',
|
|
879
|
-
jwt: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
|
|
880
|
-
parameters: { limit: 10 },
|
|
881
|
-
filters: { search: 'electrical' },
|
|
882
|
-
userId: 456
|
|
883
|
-
};
|
|
884
|
-
|
|
885
|
-
// Before: 35+ lines of boilerplate
|
|
886
|
-
const userJwt = await getToken({ req: request });
|
|
887
|
-
if (!userJwt?.jwtToken) {
|
|
888
|
-
throw new Error('Authentication failed');
|
|
889
|
-
}
|
|
890
|
-
const api = new AugurAPI({
|
|
891
|
-
siteId: context.siteId,
|
|
892
|
-
bearerToken: userJwt.jwtToken
|
|
893
|
-
});
|
|
894
|
-
|
|
895
|
-
// After: 1 line of business intent ✨
|
|
896
|
-
const api = AugurAPI.fromContext(context);
|
|
897
|
-
|
|
898
|
-
// Optional configuration overrides
|
|
899
|
-
const api = AugurAPI.fromContext(context, {
|
|
900
|
-
timeout: 10000,
|
|
901
|
-
retries: 1
|
|
902
|
-
});
|
|
903
|
-
```
|
|
904
|
-
|
|
905
|
-
#### Context Interface
|
|
906
|
-
|
|
907
|
-
```typescript
|
|
908
|
-
interface AugurContext {
|
|
909
|
-
siteId: string; // Required: Site identifier
|
|
910
|
-
jwt?: string; // JWT token (preferred)
|
|
911
|
-
bearerToken?: string; // Alternative token field
|
|
912
|
-
parameters?: Record<string, unknown>; // Request parameters
|
|
913
|
-
filters?: Record<string, unknown>; // Filter parameters
|
|
914
|
-
userId?: string | number; // User identifier
|
|
915
|
-
}
|
|
916
|
-
```
|
|
917
|
-
|
|
918
|
-
#### Error Handling
|
|
919
|
-
|
|
920
|
-
The `fromContext()` method provides clear, actionable error messages:
|
|
921
|
-
|
|
922
|
-
```typescript
|
|
923
|
-
import { ContextCreationError } from '@simpleapps-com/augur-api';
|
|
924
|
-
|
|
925
|
-
try {
|
|
926
|
-
const api = AugurAPI.fromContext(context);
|
|
927
|
-
} catch (error) {
|
|
928
|
-
if (error instanceof ContextCreationError) {
|
|
929
|
-
console.error(`Context validation failed: ${error.message}`);
|
|
930
|
-
console.error(`Problem field: ${error.field}`);
|
|
931
|
-
|
|
932
|
-
// Handle specific issues
|
|
933
|
-
switch (error.field) {
|
|
934
|
-
case 'siteId':
|
|
935
|
-
// Handle missing site ID
|
|
936
|
-
break;
|
|
937
|
-
case 'bearerToken':
|
|
938
|
-
// Handle missing authentication
|
|
939
|
-
break;
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
```
|
|
944
|
-
|
|
945
|
-
### Environment Setup
|
|
946
|
-
|
|
947
|
-
```typescript
|
|
948
|
-
// .env file
|
|
949
|
-
AUGUR_SITE_ID=your-site-id
|
|
950
|
-
AUGUR_JWT_TOKEN=your-jwt-token
|
|
951
|
-
|
|
952
|
-
// app.ts
|
|
953
|
-
const api = new AugurAPI({
|
|
954
|
-
siteId: process.env.AUGUR_SITE_ID!,
|
|
955
|
-
bearerToken: process.env.AUGUR_JWT_TOKEN!,
|
|
956
|
-
});
|
|
957
|
-
```
|
|
958
|
-
|
|
959
|
-
### Quick Example: E-commerce Operations
|
|
960
|
-
|
|
961
|
-
```typescript
|
|
962
|
-
// Get product recommendations
|
|
963
|
-
const recommendations = await api.commerce.alsoBought.get({
|
|
964
|
-
itemId: 'WIRE-123',
|
|
965
|
-
customerId: 12345,
|
|
966
|
-
edgeCache: 4 // Cache recommendations for 4 hours
|
|
967
|
-
});
|
|
968
|
-
|
|
969
|
-
// Get real-time pricing
|
|
970
|
-
const pricing = await api.pricing.getPrice({
|
|
971
|
-
customerId: 12345,
|
|
972
|
-
itemId: 'WIRE-123',
|
|
973
|
-
quantity: 100,
|
|
974
|
-
edgeCache: 3 // Cache standard pricing for 3 hours
|
|
975
|
-
});
|
|
976
|
-
|
|
977
|
-
// Search for products
|
|
978
|
-
const searchResults = await api.opensearch.itemSearch.search({
|
|
979
|
-
q: 'electrical wire 12 AWG',
|
|
980
|
-
searchType: 'query',
|
|
981
|
-
size: 20,
|
|
982
|
-
edgeCache: 2 // Cache search results for 2 hours
|
|
983
|
-
});
|
|
984
|
-
```
|
|
985
|
-
|
|
986
|
-
## Authentication & Security
|
|
987
|
-
|
|
988
|
-
> 📋 **[Complete Authentication Guide](./AUTHENTICATION.md)** - Comprehensive guide including cross-site authentication for multi-tenant applications.
|
|
989
|
-
|
|
990
|
-
### Standard Authentication (Most Common)
|
|
991
|
-
|
|
992
|
-
The Augur API uses a dual authentication system:
|
|
993
|
-
|
|
994
|
-
1. **Site ID** (`x-site-id` header) - Required for ALL endpoints
|
|
995
|
-
2. **Bearer Token** (JWT) - Required for all endpoints EXCEPT health checks
|
|
996
|
-
|
|
997
|
-
```typescript
|
|
998
|
-
const api = new AugurAPI({
|
|
999
|
-
siteId: 'your-site-id', // Always required
|
|
1000
|
-
bearerToken: 'your-jwt-token', // Required except for health checks
|
|
1001
|
-
});
|
|
1002
|
-
```
|
|
1003
|
-
|
|
1004
|
-
### Health Checks (No Authentication Required)
|
|
1005
|
-
|
|
1006
|
-
```typescript
|
|
1007
|
-
// Health checks work without bearer token
|
|
1008
|
-
const api = new AugurAPI({
|
|
1009
|
-
siteId: 'your-site-id',
|
|
1010
|
-
// No bearerToken needed
|
|
1011
|
-
});
|
|
1012
|
-
|
|
1013
|
-
const health = await api.joomla.getHealthCheck();
|
|
1014
|
-
const pricing = await api.pricing.getHealthCheck();
|
|
1015
|
-
const vmiPing = await api.vmi.health.ping();
|
|
1016
|
-
```
|
|
1017
|
-
|
|
1018
|
-
### Environment Variables Setup
|
|
1019
|
-
|
|
1020
|
-
```typescript
|
|
1021
|
-
// .env file
|
|
1022
|
-
AUGUR_SITE_ID=your-site-id
|
|
1023
|
-
AUGUR_JWT_TOKEN=your-jwt-token
|
|
1024
|
-
|
|
1025
|
-
// app.ts
|
|
1026
|
-
const api = new AugurAPI({
|
|
1027
|
-
siteId: process.env.AUGUR_SITE_ID!,
|
|
1028
|
-
bearerToken: process.env.AUGUR_JWT_TOKEN!,
|
|
1029
|
-
});
|
|
1030
|
-
```
|
|
1031
|
-
|
|
1032
|
-
### Dynamic Authentication Updates
|
|
1033
|
-
|
|
1034
|
-
```typescript
|
|
1035
|
-
// Update credentials at runtime
|
|
1036
|
-
api.setAuthToken('new-jwt-token');
|
|
1037
|
-
api.setSiteId('new-site-id');
|
|
1038
|
-
|
|
1039
|
-
// Useful for token refresh scenarios
|
|
1040
|
-
async function refreshTokenIfNeeded() {
|
|
1041
|
-
try {
|
|
1042
|
-
await api.joomla.users.list({ limit: 1 });
|
|
1043
|
-
} catch (error) {
|
|
1044
|
-
if (error instanceof AuthenticationError) {
|
|
1045
|
-
const newToken = await refreshJWTToken();
|
|
1046
|
-
api.setAuthToken(newToken);
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
```
|
|
1051
|
-
|
|
1052
|
-
### Advanced: Cross-Site Authentication
|
|
1053
|
-
|
|
1054
|
-
For multi-tenant applications that need to authenticate users across different sites:
|
|
1055
|
-
|
|
1056
|
-
```typescript
|
|
1057
|
-
import { authenticateUserForSite } from '@simpleapps-com/augur-api';
|
|
1058
|
-
|
|
1059
|
-
const result = await authenticateUserForSite({
|
|
1060
|
-
targetSiteId: 'tenant_site_1',
|
|
1061
|
-
username: 'user@tenant.com',
|
|
1062
|
-
password: 'user-password',
|
|
1063
|
-
augurInfoToken: 'admin-jwt-token'
|
|
1064
|
-
});
|
|
1065
|
-
|
|
1066
|
-
if (result.success) {
|
|
1067
|
-
const userData = await result.targetSiteAPI!.joomla.users.get(result.userId!);
|
|
1068
|
-
}
|
|
1069
|
-
```
|
|
1070
|
-
|
|
1071
|
-
> ⚠️ **Cross-site authentication is an advanced feature.** See the [Complete Authentication Guide](./AUTHENTICATION.md) for detailed implementation patterns, security considerations, and troubleshooting.
|
|
1072
|
-
|
|
1073
|
-
## API Documentation
|
|
1074
|
-
|
|
1075
|
-
### Service Overview
|
|
1076
|
-
|
|
1077
|
-
| Service | Purpose | Key Features |
|
|
1078
|
-
|---------|---------|--------------|
|
|
1079
|
-
| **Joomla** | Content & User Management | Articles, users, groups, tags, menu items |
|
|
1080
|
-
| **Commerce** | E-commerce Operations | Cart management, checkout, recommendations |
|
|
1081
|
-
| **Pricing** | Dynamic Pricing | Price calculations, job pricing, tax engine |
|
|
1082
|
-
| **VMI** | Inventory Management | Warehouses, stock levels, replenishment |
|
|
1083
|
-
| **OpenSearch** | Product Search | Full-text search, faceting, similarity matching |
|
|
1084
|
-
| **Items** | Product Catalog | Products, categories, attributes, brands |
|
|
1085
|
-
| **Customers** | Customer Data | Customer profiles, contacts, addresses, orders |
|
|
1086
|
-
| **Orders** | Order Management | Order lookup, documents, purchase orders |
|
|
1087
|
-
| **Payments** | Payment Processing | Transaction setup, payment validation |
|
|
1088
|
-
| **Legacy** | Legacy Systems | State data, inventory lookups |
|
|
1089
|
-
| **Nexus** | Warehouse Operations | Bin transfers, receiving, shipping |
|
|
1090
|
-
| **P21 PIM** | Product Information | Product data management, AI suggestions |
|
|
1091
|
-
| **AGR Site** | Site Management | Settings, notifications, transcripts |
|
|
1092
|
-
|
|
1093
|
-
📋 **[Complete API Services Reference](./API-SERVICES.md)** - Detailed catalog of all 26 services with descriptions, OpenAPI specifications, and Postman collections.
|
|
1094
|
-
|
|
1095
|
-
💡 **[Tips and Tricks Guide](./TIPS-AND-TRICKS.md)** - Advanced usage patterns, performance optimizations, and helpful techniques including the itemId → invMastUid lookup pattern.
|
|
1096
|
-
|
|
1097
|
-
### Complete Endpoint Reference
|
|
1098
|
-
|
|
1099
|
-
#### Joomla Service
|
|
1100
|
-
|
|
1101
|
-
```typescript
|
|
1102
|
-
// Content Management - OpenAPI Compliant
|
|
1103
|
-
const articles = await api.joomla.content.list({
|
|
1104
|
-
limit: 20
|
|
1105
|
-
});
|
|
1106
|
-
|
|
1107
|
-
const article = await api.joomla.content.get('123');
|
|
1108
|
-
|
|
1109
|
-
const articleDoc = await api.joomla.content.doc.get('123');
|
|
1110
|
-
|
|
1111
|
-
// User Management
|
|
1112
|
-
const users = await api.joomla.users.list({
|
|
1113
|
-
limit: 50,
|
|
1114
|
-
offset: 0,
|
|
1115
|
-
orderBy: 'username|ASC',
|
|
1116
|
-
q: 'john',
|
|
1117
|
-
edgeCache: 2 // Cache user lists for 2 hours
|
|
1118
|
-
});
|
|
1119
|
-
|
|
1120
|
-
const user = await api.joomla.users.get('456');
|
|
1121
|
-
const userDoc = await api.joomla.users.getDoc('456');
|
|
1122
|
-
|
|
1123
|
-
// Create new user
|
|
1124
|
-
const newUser = await api.joomla.users.create({
|
|
1125
|
-
username: 'newuser',
|
|
1126
|
-
email: 'user@example.com',
|
|
1127
|
-
name: 'New User',
|
|
1128
|
-
password: 'securepassword'
|
|
1129
|
-
});
|
|
1130
|
-
|
|
1131
|
-
// Update user
|
|
1132
|
-
const updatedUser = await api.joomla.users.update('456', {
|
|
1133
|
-
email: 'newemail@example.com'
|
|
1134
|
-
});
|
|
1135
|
-
|
|
1136
|
-
// Block/unblock user
|
|
1137
|
-
await api.joomla.users.block('456');
|
|
1138
|
-
|
|
1139
|
-
// User Groups
|
|
1140
|
-
const userGroups = await api.joomla.users.groups.list('456', {
|
|
1141
|
-
limit: 10,
|
|
1142
|
-
edgeCache: 4 // Cache group memberships for 4 hours
|
|
1143
|
-
});
|
|
1144
|
-
|
|
1145
|
-
const groupMapping = await api.joomla.users.groups.createMapping('456', {
|
|
1146
|
-
groupId: 789
|
|
1147
|
-
});
|
|
1148
|
-
|
|
1149
|
-
// System Groups
|
|
1150
|
-
const allGroups = await api.joomla.userGroups.list({
|
|
1151
|
-
orderBy: 'title|ASC',
|
|
1152
|
-
parentIdList: '1,2',
|
|
1153
|
-
edgeCache: 8 // Cache group hierarchy for 8 hours
|
|
1154
|
-
});
|
|
1155
|
-
|
|
1156
|
-
const groupDetails = await api.joomla.userGroups.get('789');
|
|
1157
|
-
|
|
1158
|
-
// Tags
|
|
1159
|
-
const tags = await api.joomla.tags.list({
|
|
1160
|
-
categoryId: 1,
|
|
1161
|
-
parentId: 0,
|
|
1162
|
-
q: 'tech',
|
|
1163
|
-
limit: 50,
|
|
1164
|
-
edgeCache: 6 // Cache tags for 6 hours
|
|
1165
|
-
});
|
|
1166
|
-
|
|
1167
|
-
// Authentication
|
|
1168
|
-
const authResult = await api.joomla.users.verifyPassword({
|
|
1169
|
-
username: 'user@example.com',
|
|
1170
|
-
password: 'userpassword',
|
|
1171
|
-
siteId: 'optional-cross-site-id' // For cross-site auth when using augur_info
|
|
1172
|
-
});
|
|
1173
|
-
|
|
1174
|
-
if (authResult.data.isVerified) {
|
|
1175
|
-
console.log('User authenticated:', authResult.data.username);
|
|
1176
|
-
console.log('User ID:', authResult.data.id);
|
|
1177
|
-
console.log('JWT Token:', authResult.data.token);
|
|
1178
|
-
}
|
|
1179
|
-
|
|
1180
|
-
// Health Check
|
|
1181
|
-
const health = await api.joomla.getHealthCheck();
|
|
1182
|
-
```
|
|
1183
|
-
|
|
1184
|
-
#### Commerce Service
|
|
1185
|
-
|
|
1186
|
-
```typescript
|
|
1187
|
-
// Cart Management
|
|
1188
|
-
const carts = await api.commerce.cartHeaders.list({
|
|
1189
|
-
userId: 123,
|
|
1190
|
-
edgeCache: 1 // Cache cart data for 1 hour max
|
|
1191
|
-
});
|
|
1192
|
-
|
|
1193
|
-
const cart = await api.commerce.cartHeaders.lookup({
|
|
1194
|
-
userId: 123,
|
|
1195
|
-
customerId: 456,
|
|
1196
|
-
contactId: 789
|
|
1197
|
-
});
|
|
1198
|
-
|
|
1199
|
-
const cartLines = await api.commerce.cartLines.get(cart.data.cart_hdr_uid);
|
|
1200
|
-
|
|
1201
|
-
// Product Recommendations
|
|
1202
|
-
const alsoBought = await api.commerce.alsoBought.get({
|
|
1203
|
-
itemId: 'WIRE-123',
|
|
1204
|
-
customerId: 12345,
|
|
1205
|
-
edgeCache: 6 // Cache recommendations for 6 hours
|
|
1206
|
-
});
|
|
1207
|
-
|
|
1208
|
-
// Checkout Operations
|
|
1209
|
-
const checkout = await api.commerce.checkout.get(checkoutUid, {
|
|
1210
|
-
edgeCache: 2 // Cache checkout data for 2 hours
|
|
1211
|
-
});
|
|
1212
|
-
|
|
1213
|
-
const checkoutDoc = await api.commerce.checkout.getDoc(checkoutUid, {
|
|
1214
|
-
cartHdrUid: cart.data.cart_hdr_uid,
|
|
1215
|
-
edgeCache: 4 // Cache checkout documents for 4 hours
|
|
1216
|
-
});
|
|
1217
|
-
|
|
1218
|
-
// Health Check
|
|
1219
|
-
const health = await api.commerce.getHealthCheck();
|
|
1220
|
-
```
|
|
1221
|
-
|
|
1222
|
-
#### Pricing Service
|
|
1223
|
-
|
|
1224
|
-
```typescript
|
|
1225
|
-
// Price Engine
|
|
1226
|
-
const pricing = await api.pricing.getPrice({
|
|
1227
|
-
customerId: 12345,
|
|
1228
|
-
itemId: 'ITEM-001',
|
|
1229
|
-
quantity: 10,
|
|
1230
|
-
shipToId: 'SHIP-001', // Optional
|
|
1231
|
-
unitOfMeasure: 'EA', // Optional
|
|
1232
|
-
edgeCache: 3 // Cache standard pricing for 3 hours
|
|
1233
|
-
});
|
|
1234
|
-
|
|
1235
|
-
// Job Price Management
|
|
1236
|
-
const jobPriceHeaders = await api.pricing.jobPriceHeaders.list({
|
|
1237
|
-
limit: 20,
|
|
1238
|
-
orderBy: 'job_price_hdr_uid|DESC',
|
|
1239
|
-
edgeCache: 4 // Cache job listings for 4 hours
|
|
1240
|
-
});
|
|
1241
|
-
|
|
1242
|
-
const jobPriceHeader = await api.pricing.jobPriceHeaders.get(12345);
|
|
1243
|
-
|
|
1244
|
-
const jobPriceLines = await api.pricing.jobPriceLines.list(12345, {
|
|
1245
|
-
limit: 50,
|
|
1246
|
-
edgeCache: 4 // Cache price lines for 4 hours
|
|
1247
|
-
});
|
|
1248
|
-
|
|
1249
|
-
const jobPriceLine = await api.pricing.jobPriceLines.get(12345, 67890);
|
|
1250
|
-
|
|
1251
|
-
// Tax Engine
|
|
1252
|
-
const taxCalculation = await api.pricing.calculateTax({
|
|
1253
|
-
customer_id: 12345,
|
|
1254
|
-
ship_to_id: 'SHIP-001',
|
|
1255
|
-
items: [
|
|
1256
|
-
{
|
|
1257
|
-
item_id: 'ITEM-001',
|
|
1258
|
-
quantity: 10,
|
|
1259
|
-
unit_price: 25.50,
|
|
1260
|
-
extended_price: 255.00
|
|
1261
|
-
}
|
|
1262
|
-
],
|
|
1263
|
-
addresses: {
|
|
1264
|
-
origin: {
|
|
1265
|
-
street: '123 Main St',
|
|
1266
|
-
city: 'Anytown',
|
|
1267
|
-
state: 'CA',
|
|
1268
|
-
zip: '90210'
|
|
1269
|
-
},
|
|
1270
|
-
destination: {
|
|
1271
|
-
street: '456 Oak Ave',
|
|
1272
|
-
city: 'Other City',
|
|
1273
|
-
state: 'NY',
|
|
1274
|
-
zip: '10001'
|
|
1275
|
-
}
|
|
1276
|
-
},
|
|
1277
|
-
edgeCache: 1 // Cache tax calculations for 1 hour
|
|
1278
|
-
});
|
|
1279
|
-
|
|
1280
|
-
// Health Checks
|
|
1281
|
-
const ping = await api.pricing.ping();
|
|
1282
|
-
const health = await api.pricing.getHealthCheck();
|
|
1283
|
-
```
|
|
1284
|
-
|
|
1285
|
-
#### VMI (Vendor Managed Inventory) Service
|
|
1286
|
-
|
|
1287
|
-
```typescript
|
|
1288
|
-
// Warehouse Management
|
|
1289
|
-
const warehouses = await api.vmi.warehouses.list({
|
|
1290
|
-
customerId: 12345,
|
|
1291
|
-
limit: 10,
|
|
1292
|
-
q: 'distribution',
|
|
1293
|
-
usersId: 456,
|
|
1294
|
-
edgeCache: 4 // Cache warehouse data for 4 hours
|
|
1295
|
-
});
|
|
1296
|
-
|
|
1297
|
-
const warehouse = await api.vmi.warehouses.get(123);
|
|
1298
|
-
|
|
1299
|
-
const newWarehouse = await api.vmi.warehouses.create({
|
|
1300
|
-
warehouse_name: 'New Distribution Center',
|
|
1301
|
-
warehouse_desc: 'Primary warehouse for west coast operations',
|
|
1302
|
-
customer_id: 12345,
|
|
1303
|
-
inv_profile_hdr_uid: 1
|
|
1304
|
-
});
|
|
1305
|
-
|
|
1306
|
-
const updatedWarehouse = await api.vmi.warehouses.update(123, {
|
|
1307
|
-
warehouse_name: 'Updated Warehouse Name'
|
|
1308
|
-
});
|
|
1309
|
-
|
|
1310
|
-
// Enable/disable warehouse
|
|
1311
|
-
await api.vmi.warehouses.enable(123, { status_cd: 704 }); // Enable
|
|
1312
|
-
await api.vmi.warehouses.enable(123, { status_cd: 705 }); // Disable
|
|
1313
|
-
|
|
1314
|
-
// Inventory Operations
|
|
1315
|
-
const availability = await api.vmi.invProfileHdr.checkAvailability(123, {
|
|
1316
|
-
q: 'wire' // Search for items containing 'wire'
|
|
1317
|
-
});
|
|
1318
|
-
|
|
1319
|
-
// Adjust inventory (sets absolute values)
|
|
1320
|
-
await api.vmi.invProfileHdr.adjust(123, {
|
|
1321
|
-
adjustments: [
|
|
1322
|
-
{
|
|
1323
|
-
inv_mast_uid: 456,
|
|
1324
|
-
qty_on_hand: 200.0,
|
|
1325
|
-
reason: 'Physical count adjustment'
|
|
1326
|
-
}
|
|
1327
|
-
]
|
|
1328
|
-
});
|
|
1329
|
-
|
|
1330
|
-
// Receive inventory
|
|
1331
|
-
await api.vmi.invProfileHdr.receive(123, {
|
|
1332
|
-
receipts: [
|
|
1333
|
-
{
|
|
1334
|
-
inv_mast_uid: 456,
|
|
1335
|
-
qty_received: 50.0,
|
|
1336
|
-
po_number: 'PO-2024-001',
|
|
1337
|
-
lot_number: 'LOT-456'
|
|
1338
|
-
}
|
|
1339
|
-
]
|
|
1340
|
-
});
|
|
1341
|
-
|
|
1342
|
-
// Get replenishment information
|
|
1343
|
-
const replenishment = await api.vmi.invProfileHdr.getReplenishmentInfo(123, {
|
|
1344
|
-
distributorsUid: 789,
|
|
1345
|
-
edgeCache: 2 // Cache replenishment info for 2 hours
|
|
1346
|
-
});
|
|
1347
|
-
|
|
1348
|
-
// Execute replenishment
|
|
1349
|
-
await api.vmi.invProfileHdr.replenish(123, {
|
|
1350
|
-
distributor_uid: 789,
|
|
1351
|
-
restock_items: [
|
|
1352
|
-
{ inv_mast_uid: 456, qty_to_order: 100.0 }
|
|
1353
|
-
]
|
|
1354
|
-
});
|
|
1355
|
-
|
|
1356
|
-
// Transfer inventory between warehouses
|
|
1357
|
-
await api.vmi.invProfileHdr.transfer(123, {
|
|
1358
|
-
to_warehouse_uid: 124,
|
|
1359
|
-
transfers: [
|
|
1360
|
-
{
|
|
1361
|
-
inv_mast_uid: 456,
|
|
1362
|
-
qty_to_transfer: 25.0,
|
|
1363
|
-
reason: 'Stock balancing'
|
|
1364
|
-
}
|
|
1365
|
-
]
|
|
1366
|
-
});
|
|
1367
|
-
|
|
1368
|
-
// Record inventory usage (with warranty tracking)
|
|
1369
|
-
await api.vmi.invProfileHdr.recordUsage(123, {
|
|
1370
|
-
job_description: 'Office Renovation - Building A',
|
|
1371
|
-
department: 'Facilities',
|
|
1372
|
-
usage_items: [
|
|
1373
|
-
{
|
|
1374
|
-
inv_mast_uid: 456,
|
|
1375
|
-
inv_profile_line_type: 'prophet21',
|
|
1376
|
-
qty_used: 5.0
|
|
1377
|
-
},
|
|
1378
|
-
{
|
|
1379
|
-
inv_mast_uid: 789,
|
|
1380
|
-
inv_profile_line_type: 'products',
|
|
1381
|
-
qty_used: 2.0,
|
|
1382
|
-
warranty: {
|
|
1383
|
-
model_no: 'MDL-123',
|
|
1384
|
-
serial_no: 'SN-456789',
|
|
1385
|
-
warranty_type: 'Standard',
|
|
1386
|
-
notes: 'Installed in conference room'
|
|
1387
|
-
}
|
|
1388
|
-
}
|
|
1389
|
-
]
|
|
1390
|
-
});
|
|
1391
|
-
|
|
1392
|
-
// Distributor Management
|
|
1393
|
-
const distributors = await api.vmi.distributors.list({
|
|
1394
|
-
customerId: 12345,
|
|
1395
|
-
statusCd: 704, // Active distributors only
|
|
1396
|
-
edgeCache: 8 // Cache distributor data for 8 hours
|
|
1397
|
-
});
|
|
1398
|
-
|
|
1399
|
-
const distributor = await api.vmi.distributors.get(789);
|
|
1400
|
-
|
|
1401
|
-
const newDistributor = await api.vmi.distributors.create({
|
|
1402
|
-
distributor_name: 'ABC Supply Co',
|
|
1403
|
-
distributor_desc: 'Primary electrical supplier',
|
|
1404
|
-
customer_id: 12345,
|
|
1405
|
-
contact_email: 'orders@abcsupply.com',
|
|
1406
|
-
contact_phone: '555-1234'
|
|
1407
|
-
});
|
|
1408
|
-
|
|
1409
|
-
// Product Management
|
|
1410
|
-
const products = await api.vmi.products.find({
|
|
1411
|
-
customerId: 12345,
|
|
1412
|
-
prefix: 'WIRE',
|
|
1413
|
-
edgeCache: 6 // Cache product catalogs for 6 hours
|
|
1414
|
-
});
|
|
1415
|
-
|
|
1416
|
-
const productList = await api.vmi.products.list({
|
|
1417
|
-
customerId: 12345,
|
|
1418
|
-
distributorsUid: 789,
|
|
1419
|
-
prefix: 'WIRE',
|
|
1420
|
-
limit: 20,
|
|
1421
|
-
edgeCache: 6
|
|
1422
|
-
});
|
|
1423
|
-
|
|
1424
|
-
// Health Monitoring
|
|
1425
|
-
const ping = await api.vmi.health.ping();
|
|
1426
|
-
const health = await api.vmi.health.check();
|
|
1427
|
-
```
|
|
1428
|
-
|
|
1429
|
-
#### OpenSearch Service
|
|
1430
|
-
|
|
1431
|
-
```typescript
|
|
1432
|
-
// Item Search
|
|
1433
|
-
const searchResults = await api.opensearch.itemSearch.search({
|
|
1434
|
-
q: 'electrical wire 12 AWG',
|
|
1435
|
-
searchType: 'query', // 'query' | 'similarity'
|
|
1436
|
-
size: 20,
|
|
1437
|
-
operator: 'AND', // 'AND' | 'OR'
|
|
1438
|
-
itemCategoryUidList: '123,456,789',
|
|
1439
|
-
filters: JSON.stringify([
|
|
1440
|
-
{ attributeUid: 123, attributeValueUid: 456 }
|
|
1441
|
-
]),
|
|
1442
|
-
edgeCache: 2 // Cache search results for 2 hours
|
|
1443
|
-
});
|
|
1444
|
-
|
|
1445
|
-
// Similarity search for recommendations
|
|
1446
|
-
const similarItems = await api.opensearch.itemSearch.search({
|
|
1447
|
-
q: 'CAT5e network cable 100ft blue',
|
|
1448
|
-
searchType: 'similarity',
|
|
1449
|
-
size: 15,
|
|
1450
|
-
edgeCache: 4 // Cache similarity results for 4 hours
|
|
1451
|
-
});
|
|
1452
|
-
|
|
1453
|
-
// Get search facets for filtering
|
|
1454
|
-
const attributes = await api.opensearch.itemSearch.getAttributes({
|
|
1455
|
-
q: 'LED bulbs',
|
|
1456
|
-
searchType: 'query',
|
|
1457
|
-
edgeCache: 6 // Cache facet structure for 6 hours
|
|
1458
|
-
});
|
|
1459
|
-
|
|
1460
|
-
// Items Management
|
|
1461
|
-
const items = await api.opensearch.items.list({
|
|
1462
|
-
itemId: 'WIRE', // Prefix filter
|
|
1463
|
-
online: 'Y', // Only online items
|
|
1464
|
-
statusCd: 704, // Active items only
|
|
1465
|
-
limit: 100,
|
|
1466
|
-
offset: 0,
|
|
1467
|
-
edgeCache: 3 // Cache item data for 3 hours
|
|
1468
|
-
});
|
|
1469
|
-
|
|
1470
|
-
const itemDetail = await api.opensearch.items.get(123456);
|
|
1471
|
-
|
|
1472
|
-
// Index management operations (no caching for real-time operations)
|
|
1473
|
-
const refreshResult = await api.opensearch.items.refresh(123456);
|
|
1474
|
-
const updateResult = await api.opensearch.items.update(123456);
|
|
1475
|
-
const batchRefresh = await api.opensearch.items.refreshAll();
|
|
1476
|
-
|
|
1477
|
-
// Health Monitoring
|
|
1478
|
-
const ping = await api.opensearch.health.ping();
|
|
1479
|
-
const health = await api.opensearch.health.check();
|
|
1480
|
-
```
|
|
1481
|
-
|
|
1482
|
-
#### Items Service
|
|
1483
|
-
|
|
1484
|
-
```typescript
|
|
1485
|
-
// Inventory Master Records
|
|
1486
|
-
const itemDetails = await api.items.invMast.get(invMastUid);
|
|
1487
|
-
|
|
1488
|
-
// Document retrieval for invMast records
|
|
1489
|
-
const itemDoc = await api.items.invMast.doc.get(invMastUid, {
|
|
1490
|
-
q: 'optional-query-pattern' // Search pattern for document filtering
|
|
1491
|
-
});
|
|
1492
|
-
|
|
1493
|
-
// Special lookup pattern: Find invMastUid by itemId
|
|
1494
|
-
// When you only have an itemId but need the invMastUid, use invMastUid = 0
|
|
1495
|
-
// and provide the itemId as the query pattern. This will look up the itemId
|
|
1496
|
-
// and return the full document including the correct invMastUid.
|
|
1497
|
-
const itemByItemId = await api.items.invMast.doc.get(0, {
|
|
1498
|
-
q: 'YOUR-ITEM-ID' // Replace with actual itemId (e.g., 'WIRE-12-AWG-250FT')
|
|
1499
|
-
});
|
|
1500
|
-
// Response includes the actual invMastUid for future direct lookups
|
|
1501
|
-
|
|
1502
|
-
// Categories and attributes
|
|
1503
|
-
const categories = await api.items.categories.list({
|
|
1504
|
-
limit: 50,
|
|
1505
|
-
edgeCache: 8 // Categories rarely change
|
|
1506
|
-
});
|
|
1507
|
-
|
|
1508
|
-
// Product locations and bins
|
|
1509
|
-
const locations = await api.items.invMast.locations.list(invMastUid);
|
|
1510
|
-
const bins = await api.items.invMast.locations.bins.list(invMastUid, locationId);
|
|
1511
|
-
|
|
1512
|
-
// Alternate codes and variants
|
|
1513
|
-
const alternates = await api.items.invMast.alternateCode.list(invMastUid);
|
|
1514
|
-
const variants = await api.items.variants.list({
|
|
1515
|
-
invMastUid: invMastUid,
|
|
1516
|
-
edgeCache: 4 // Variants change occasionally
|
|
1517
|
-
});
|
|
1518
|
-
|
|
1519
|
-
// Attributes and values
|
|
1520
|
-
const attributes = await api.items.attributes.list({
|
|
1521
|
-
edgeCache: 6 // Attribute structure is relatively stable
|
|
1522
|
-
});
|
|
1523
|
-
|
|
1524
|
-
const attributeValues = await api.items.attributes.values.list(attributeUid);
|
|
1525
|
-
|
|
1526
|
-
// Brands and product links
|
|
1527
|
-
const brands = await api.items.brands.list({
|
|
1528
|
-
edgeCache: 8 // Brand data is very stable
|
|
1529
|
-
});
|
|
1530
|
-
|
|
1531
|
-
const productLinks = await api.items.productLinks.list({
|
|
1532
|
-
invMastUid: invMastUid,
|
|
1533
|
-
edgeCache: 2 // Product links may change
|
|
1534
|
-
});
|
|
1535
|
-
|
|
1536
|
-
// Health Monitoring
|
|
1537
|
-
const ping = await api.items.ping();
|
|
1538
|
-
const health = await api.items.healthCheck.get();
|
|
1539
|
-
```
|
|
1540
|
-
|
|
1541
|
-
### Response Format
|
|
1542
|
-
|
|
1543
|
-
All Augur microservices follow a unified response pattern:
|
|
1544
|
-
|
|
1545
|
-
```typescript
|
|
1546
|
-
interface BaseResponse<T> {
|
|
1547
|
-
status: number; // HTTP status code (200 for success)
|
|
1548
|
-
message?: string; // Status message (optional - omitted in health checks)
|
|
1549
|
-
data: T; // Response data of type T
|
|
1550
|
-
totalResults?: number; // Total count (optional - present in paginated responses)
|
|
1551
|
-
count?: number; // Item count (optional - present in some responses)
|
|
1552
|
-
options?: Array<Record<string, unknown>>; // Optional array of key-value pairs
|
|
1553
|
-
}
|
|
1554
|
-
|
|
1555
|
-
// Example response
|
|
1556
|
-
const usersResponse = await api.joomla.users.list({ limit: 10 });
|
|
1557
|
-
// usersResponse = {
|
|
1558
|
-
// status: 200,
|
|
1559
|
-
// message: "Ok",
|
|
1560
|
-
// data: [...users...],
|
|
1561
|
-
// totalResults: 150
|
|
1562
|
-
// }
|
|
1563
|
-
|
|
1564
|
-
// Access the actual data
|
|
1565
|
-
const users = usersResponse.data;
|
|
1566
|
-
const totalCount = usersResponse.totalResults;
|
|
1567
|
-
```
|
|
1568
|
-
|
|
1569
|
-
#### Important: Query Parameter Handling
|
|
1570
|
-
|
|
1571
|
-
HTTP query parameters are always transmitted as strings. The library uses Zod's coercion to automatically handle numeric parameters:
|
|
1572
|
-
|
|
1573
|
-
```typescript
|
|
1574
|
-
// You pass numbers
|
|
1575
|
-
await api.customers.customer.orders.list(12345, {
|
|
1576
|
-
limit: 10, // number
|
|
1577
|
-
offset: 0 // number
|
|
1578
|
-
});
|
|
1579
|
-
|
|
1580
|
-
// They become strings in the URL: ?limit=10&offset=0
|
|
1581
|
-
// The API might echo them back as strings
|
|
1582
|
-
// But Zod coercion handles this automatically!
|
|
1583
|
-
```
|
|
1584
|
-
|
|
1585
|
-
### HTTP Methods and URL Patterns
|
|
1586
|
-
|
|
1587
|
-
| Method | Pattern | Client Method | Example |
|
|
1588
|
-
|--------|---------|---------------|---------|
|
|
1589
|
-
| GET | `/users` | `listUsers()` | List multiple resources |
|
|
1590
|
-
| GET | `/user/{id}` | `getUser()` | Get single resource |
|
|
1591
|
-
| POST | `/user` | `createUser()` | Create new resource |
|
|
1592
|
-
| PUT | `/user/{id}` | `updateUser()` | Update existing resource |
|
|
1593
|
-
| DELETE | `/user/{id}` | `deleteUser()` | Delete resource |
|
|
1594
|
-
|
|
1595
|
-
### Error Handling
|
|
1596
|
-
|
|
1597
|
-
```typescript
|
|
1598
|
-
import {
|
|
1599
|
-
AugurAPIError,
|
|
1600
|
-
AuthenticationError,
|
|
1601
|
-
ValidationError,
|
|
1602
|
-
NotFoundError,
|
|
1603
|
-
RateLimitError
|
|
1604
|
-
} from '@simpleapps-com/augur-api';
|
|
1605
|
-
|
|
1606
|
-
try {
|
|
1607
|
-
const user = await api.joomla.users.get('user-id');
|
|
1608
|
-
} catch (error) {
|
|
1609
|
-
if (error instanceof AuthenticationError) {
|
|
1610
|
-
console.error('Authentication failed:', error.message);
|
|
1611
|
-
// Handle auth error - refresh token or redirect to login
|
|
1612
|
-
|
|
1613
|
-
} else if (error instanceof ValidationError) {
|
|
1614
|
-
console.error('Request validation failed:', error.validationErrors);
|
|
1615
|
-
// Handle validation errors - check request parameters
|
|
1616
|
-
|
|
1617
|
-
} else if (error instanceof NotFoundError) {
|
|
1618
|
-
console.error('Resource not found:', error.message);
|
|
1619
|
-
// Handle not found - show user-friendly message
|
|
1620
|
-
|
|
1621
|
-
} else if (error instanceof RateLimitError) {
|
|
1622
|
-
console.error('Rate limit exceeded:', error.message);
|
|
1623
|
-
// Handle rate limiting - implement backoff strategy
|
|
1624
|
-
|
|
1625
|
-
} else if (error instanceof AugurAPIError) {
|
|
1626
|
-
console.error('API error:', error.code, error.message);
|
|
1627
|
-
// Handle other API errors
|
|
1628
|
-
}
|
|
1629
|
-
}
|
|
1630
|
-
```
|
|
1631
|
-
|
|
1632
|
-
## Advanced Features
|
|
1633
|
-
|
|
1634
|
-
💡 **[Complete Tips and Tricks Guide](./TIPS-AND-TRICKS.md)** - Comprehensive advanced patterns including edge caching, request cancellation, middleware integration, framework integrations, and error handling strategies.
|
|
1635
|
-
|
|
1636
|
-
**Quick Advanced Features:**
|
|
1637
|
-
- **Edge Caching**: Built-in Cloudflare caching with configurable TTL (1-8 hours)
|
|
1638
|
-
- **Request Cancellation**: AbortController support for request timeout
|
|
1639
|
-
- **Custom Headers**: Per-request configuration and timeouts
|
|
1640
|
-
- **Batch Operations**: Parallel request execution with Promise.all
|
|
1641
|
-
- **Middleware**: Global request/response/error interceptors
|
|
1642
|
-
|
|
1643
|
-
## Integration Guides
|
|
1644
|
-
|
|
1645
|
-
💡 **[Complete Framework Integration Examples](./TIPS-AND-TRICKS.md#-framework-integration-patterns)** - Detailed React, Next.js, React Native, and Node.js integration patterns with custom hooks, error handling, and best practices.
|
|
1646
|
-
|
|
1647
|
-
**Quick Integration Examples:**
|
|
1648
|
-
- **React**: Custom `useAugurAPI()` hook with context-aware API creation
|
|
1649
|
-
- **Next.js**: Server-side API routes with proper caching and error handling
|
|
1650
|
-
- **React Native**: AsyncStorage integration for offline-first patterns
|
|
1651
|
-
- **Node.js**: Service layer integration with middleware and monitoring
|
|
1652
|
-
|
|
1653
|
-
## Framework-Specific Features
|
|
1654
|
-
|
|
1655
|
-
### React/Next.js
|
|
1656
|
-
```typescript
|
|
1657
|
-
// Context-aware API creation
|
|
1658
|
-
const api = AugurAPI.fromContext(context);
|
|
1659
|
-
|
|
1660
|
-
// Custom hook pattern
|
|
1661
|
-
const { api, isReady } = useAugurAPI();
|
|
1662
|
-
```
|
|
1663
|
-
|
|
1664
|
-
### Error Handling Integration
|
|
1665
|
-
```typescript
|
|
1666
|
-
// Framework-agnostic error handling
|
|
1667
|
-
try {
|
|
1668
|
-
const result = await api.joomla.users.list({ limit: 10 });
|
|
1669
|
-
} catch (error) {
|
|
1670
|
-
ErrorHandler.handle(error, 'UserList Component');
|
|
1671
|
-
}
|
|
1672
|
-
```
|
|
1673
|
-
|
|
1674
|
-
## Error Handling
|
|
1675
|
-
|
|
1676
|
-
💡 **[Complete Error Handling Guide](./TIPS-AND-TRICKS.md#️-advanced-error-handling)** - Comprehensive error handling patterns including retry logic, exponential backoff, global error handlers, and framework-specific error boundaries.
|
|
1677
|
-
|
|
1678
|
-
**Quick Error Types:**
|
|
1679
|
-
```typescript
|
|
1680
|
-
import {
|
|
1681
|
-
AugurAPIError, // Base error class
|
|
1682
|
-
AuthenticationError, // 401 errors
|
|
1683
|
-
ValidationError, // Request validation failures
|
|
1684
|
-
NotFoundError, // 404 errors
|
|
1685
|
-
RateLimitError, // 429 errors
|
|
1686
|
-
NetworkError // Network/connectivity issues
|
|
1687
|
-
} from '@simpleapps-com/augur-api';
|
|
1688
|
-
|
|
1689
|
-
// Custom hook for Augur API - Context-aware approach
|
|
1690
|
-
function useAugurAPI(context?: AugurContext) {
|
|
1691
|
-
const [api] = useState(() => {
|
|
1692
|
-
if (context) {
|
|
1693
|
-
// Use context-aware creation (recommended)
|
|
1694
|
-
return AugurAPI.fromContext(context);
|
|
1695
|
-
}
|
|
1696
|
-
|
|
1697
|
-
// Fallback to manual configuration
|
|
1698
|
-
return new AugurAPI({
|
|
1699
|
-
siteId: process.env.REACT_APP_AUGUR_SITE_ID!,
|
|
1700
|
-
bearerToken: getStoredToken()
|
|
1701
|
-
});
|
|
1702
|
-
});
|
|
1703
|
-
|
|
1704
|
-
return api;
|
|
1705
|
-
}
|
|
1706
|
-
|
|
1707
|
-
// Component using the API
|
|
1708
|
-
const UserList: React.FC = () => {
|
|
1709
|
-
const api = useAugurAPI();
|
|
1710
|
-
const [users, setUsers] = useState<User[]>([]);
|
|
1711
|
-
const [loading, setLoading] = useState(true);
|
|
1712
|
-
const [error, setError] = useState<string | null>(null);
|
|
1713
|
-
|
|
1714
|
-
useEffect(() => {
|
|
1715
|
-
async function fetchUsers() {
|
|
1716
|
-
try {
|
|
1717
|
-
setLoading(true);
|
|
1718
|
-
setError(null);
|
|
1719
|
-
|
|
1720
|
-
const response = await api.joomla.users.list({
|
|
1721
|
-
limit: 50,
|
|
1722
|
-
edgeCache: 2 // Cache for 2 hours
|
|
1723
|
-
});
|
|
1724
|
-
|
|
1725
|
-
setUsers(response.data);
|
|
1726
|
-
} catch (err) {
|
|
1727
|
-
if (err instanceof AugurAPIError) {
|
|
1728
|
-
setError(`API Error: ${err.message}`);
|
|
1729
|
-
} else {
|
|
1730
|
-
setError('An unexpected error occurred');
|
|
1731
|
-
}
|
|
1732
|
-
} finally {
|
|
1733
|
-
setLoading(false);
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
|
|
1737
|
-
fetchUsers();
|
|
1738
|
-
}, [api]);
|
|
1739
|
-
|
|
1740
|
-
if (loading) return <div>Loading users...</div>;
|
|
1741
|
-
if (error) return <div>Error: {error}</div>;
|
|
1742
|
-
|
|
1743
|
-
return (
|
|
1744
|
-
<div>
|
|
1745
|
-
<h2>Users ({users.length})</h2>
|
|
1746
|
-
<ul>
|
|
1747
|
-
{users.map(user => (
|
|
1748
|
-
<li key={user.id}>
|
|
1749
|
-
{user.name} ({user.username}) - {user.email}
|
|
1750
|
-
</li>
|
|
1751
|
-
))}
|
|
1752
|
-
</ul>
|
|
1753
|
-
</div>
|
|
1754
|
-
);
|
|
1755
|
-
};
|
|
1756
|
-
|
|
1757
|
-
export default UserList;
|
|
1758
|
-
```
|
|
1759
|
-
|
|
1760
|
-
### React Native Integration
|
|
1761
|
-
|
|
1762
|
-
```typescript
|
|
1763
|
-
import { AugurAPI } from '@simpleapps-com/augur-api';
|
|
1764
|
-
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
1765
|
-
|
|
1766
|
-
class AugurService {
|
|
1767
|
-
private api: AugurAPI;
|
|
1768
|
-
|
|
1769
|
-
constructor() {
|
|
1770
|
-
this.api = new AugurAPI({
|
|
1771
|
-
siteId: 'your-site-id',
|
|
1772
|
-
bearerToken: '', // Will be set after loading from storage
|
|
1773
|
-
});
|
|
1774
|
-
|
|
1775
|
-
this.loadCredentials();
|
|
1776
|
-
}
|
|
1777
|
-
|
|
1778
|
-
private async loadCredentials() {
|
|
1779
|
-
try {
|
|
1780
|
-
const token = await AsyncStorage.getItem('augur_token');
|
|
1781
|
-
const siteId = await AsyncStorage.getItem('augur_site_id');
|
|
1782
|
-
|
|
1783
|
-
if (token) this.api.setAuthToken(token);
|
|
1784
|
-
if (siteId) this.api.setSiteId(siteId);
|
|
1785
|
-
} catch (error) {
|
|
1786
|
-
console.error('Failed to load credentials:', error);
|
|
1787
|
-
}
|
|
1788
|
-
}
|
|
1789
|
-
|
|
1790
|
-
async login(username: string, password: string): Promise<boolean> {
|
|
1791
|
-
try {
|
|
1792
|
-
const response = await this.api.joomla.users.verifyPassword({
|
|
1793
|
-
username,
|
|
1794
|
-
password
|
|
1795
|
-
});
|
|
1796
|
-
|
|
1797
|
-
if (response.data.isVerified && response.data.token) {
|
|
1798
|
-
await AsyncStorage.setItem('augur_token', response.data.token);
|
|
1799
|
-
this.api.setAuthToken(response.data.token);
|
|
1800
|
-
return true;
|
|
1801
|
-
}
|
|
1802
|
-
} catch (error) {
|
|
1803
|
-
console.error('Login failed:', error);
|
|
1804
|
-
}
|
|
1805
|
-
|
|
1806
|
-
return false;
|
|
1807
|
-
}
|
|
1808
|
-
|
|
1809
|
-
async getProducts(searchTerm: string) {
|
|
1810
|
-
return this.api.opensearch.itemSearch.search({
|
|
1811
|
-
q: searchTerm,
|
|
1812
|
-
searchType: 'query',
|
|
1813
|
-
size: 20,
|
|
1814
|
-
edgeCache: 3 // Cache search results
|
|
1815
|
-
});
|
|
1816
|
-
}
|
|
1817
|
-
|
|
1818
|
-
async logout() {
|
|
1819
|
-
await AsyncStorage.multiRemove(['augur_token', 'augur_site_id']);
|
|
1820
|
-
this.api.setAuthToken('');
|
|
1821
|
-
}
|
|
1822
|
-
}
|
|
1823
|
-
|
|
1824
|
-
export const augurService = new AugurService();
|
|
1825
|
-
```
|
|
1826
|
-
|
|
1827
|
-
### Next.js Integration
|
|
1828
|
-
|
|
1829
|
-
```typescript
|
|
1830
|
-
// lib/augur.ts
|
|
1831
|
-
import { AugurAPI } from '@simpleapps-com/augur-api';
|
|
1832
|
-
|
|
1833
|
-
// Server-side API instance
|
|
1834
|
-
export function createServerAPI() {
|
|
1835
|
-
return new AugurAPI({
|
|
1836
|
-
siteId: process.env.AUGUR_SITE_ID!,
|
|
1837
|
-
bearerToken: process.env.AUGUR_SERVICE_TOKEN!, // Service token for server-side
|
|
1838
|
-
});
|
|
1839
|
-
}
|
|
1840
|
-
|
|
1841
|
-
// Client-side API instance
|
|
1842
|
-
export function createClientAPI(userToken: string) {
|
|
1843
|
-
return new AugurAPI({
|
|
1844
|
-
siteId: process.env.NEXT_PUBLIC_AUGUR_SITE_ID!,
|
|
1845
|
-
bearerToken: userToken, // User token for client-side
|
|
1846
|
-
});
|
|
1847
|
-
}
|
|
1848
|
-
|
|
1849
|
-
// pages/api/products/search.ts
|
|
1850
|
-
import type { NextApiRequest, NextApiResponse } from 'next';
|
|
1851
|
-
import { createServerAPI } from '../../../lib/augur';
|
|
1852
|
-
|
|
1853
|
-
export default async function handler(
|
|
1854
|
-
req: NextApiRequest,
|
|
1855
|
-
res: NextApiResponse
|
|
1856
|
-
) {
|
|
1857
|
-
if (req.method !== 'GET') {
|
|
1858
|
-
return res.status(405).json({ error: 'Method not allowed' });
|
|
1859
|
-
}
|
|
1860
|
-
|
|
1861
|
-
const { q } = req.query;
|
|
1862
|
-
if (!q || typeof q !== 'string') {
|
|
1863
|
-
return res.status(400).json({ error: 'Search query required' });
|
|
1864
|
-
}
|
|
1865
|
-
|
|
1866
|
-
try {
|
|
1867
|
-
const api = createServerAPI();
|
|
1868
|
-
const searchResults = await api.opensearch.itemSearch.search({
|
|
1869
|
-
q,
|
|
1870
|
-
searchType: 'query',
|
|
1871
|
-
size: 20,
|
|
1872
|
-
edgeCache: 4 // Cache search results for 4 hours
|
|
1873
|
-
});
|
|
1874
|
-
|
|
1875
|
-
res.status(200).json(searchResults);
|
|
1876
|
-
} catch (error) {
|
|
1877
|
-
console.error('Search failed:', error);
|
|
1878
|
-
res.status(500).json({ error: 'Search failed' });
|
|
1879
|
-
}
|
|
1880
|
-
}
|
|
1881
|
-
|
|
1882
|
-
// pages/products.tsx
|
|
1883
|
-
import { GetServerSideProps } from 'next';
|
|
1884
|
-
import { createServerAPI } from '../lib/augur';
|
|
1885
|
-
import type { ItemSearchResponse } from '@simpleapps-com/augur-api';
|
|
1886
|
-
|
|
1887
|
-
interface ProductsPageProps {
|
|
1888
|
-
initialProducts: ItemSearchResponse;
|
|
1889
|
-
}
|
|
1890
|
-
|
|
1891
|
-
export default function ProductsPage({ initialProducts }: ProductsPageProps) {
|
|
1892
|
-
return (
|
|
1893
|
-
<div>
|
|
1894
|
-
<h1>Products</h1>
|
|
1895
|
-
<div>
|
|
1896
|
-
{initialProducts.data.items.map(item => (
|
|
1897
|
-
<div key={item.inv_mast_uid}>
|
|
1898
|
-
{item.item_id} - {item.item_desc}
|
|
1899
|
-
</div>
|
|
1900
|
-
))}
|
|
1901
|
-
</div>
|
|
1902
|
-
</div>
|
|
1903
|
-
);
|
|
1904
|
-
}
|
|
1905
|
-
|
|
1906
|
-
export const getServerSideProps: GetServerSideProps = async () => {
|
|
1907
|
-
try {
|
|
1908
|
-
const api = createServerAPI();
|
|
1909
|
-
const products = await api.opensearch.itemSearch.search({
|
|
1910
|
-
q: 'electrical',
|
|
1911
|
-
searchType: 'query',
|
|
1912
|
-
size: 20,
|
|
1913
|
-
edgeCache: 6 // Cache for 6 hours
|
|
1914
|
-
});
|
|
1915
|
-
|
|
1916
|
-
return {
|
|
1917
|
-
props: {
|
|
1918
|
-
initialProducts: products,
|
|
1919
|
-
},
|
|
1920
|
-
};
|
|
1921
|
-
} catch (error) {
|
|
1922
|
-
console.error('Failed to fetch products:', error);
|
|
1923
|
-
return {
|
|
1924
|
-
props: {
|
|
1925
|
-
initialProducts: { data: { items: [] }, status: 500 },
|
|
1926
|
-
},
|
|
1927
|
-
};
|
|
1928
|
-
}
|
|
1929
|
-
};
|
|
1930
|
-
```
|
|
1931
|
-
|
|
1932
|
-
### Node.js Service Integration
|
|
1933
|
-
|
|
1934
|
-
```typescript
|
|
1935
|
-
// services/AugurService.ts
|
|
1936
|
-
import { AugurAPI, AugurAPIError } from '@simpleapps-com/augur-api';
|
|
1937
|
-
|
|
1938
|
-
export class AugurService {
|
|
1939
|
-
private api: AugurAPI;
|
|
1940
|
-
|
|
1941
|
-
constructor() {
|
|
1942
|
-
const siteId = process.env.AUGUR_SITE_ID;
|
|
1943
|
-
const bearerToken = process.env.AUGUR_SERVICE_TOKEN;
|
|
1944
|
-
|
|
1945
|
-
if (!siteId || !bearerToken) {
|
|
1946
|
-
throw new Error('Augur credentials not configured');
|
|
1947
|
-
}
|
|
1948
|
-
|
|
1949
|
-
this.api = new AugurAPI({
|
|
1950
|
-
siteId,
|
|
1951
|
-
bearerToken,
|
|
1952
|
-
timeout: 30000,
|
|
1953
|
-
retries: 3,
|
|
1954
|
-
retryDelay: 1000,
|
|
1955
|
-
|
|
1956
|
-
// Add comprehensive logging
|
|
1957
|
-
onRequest: (config) => {
|
|
1958
|
-
console.log(`[Augur] ${config.method?.toUpperCase()} ${config.url}`, {
|
|
1959
|
-
headers: config.headers,
|
|
1960
|
-
params: config.params
|
|
1961
|
-
});
|
|
1962
|
-
return config;
|
|
1963
|
-
},
|
|
1964
|
-
|
|
1965
|
-
onResponse: (response) => {
|
|
1966
|
-
console.log(`[Augur] Response ${response.status}`, {
|
|
1967
|
-
url: response.config?.url,
|
|
1968
|
-
cached: response.headers?.['cf-cache-status'] === 'HIT'
|
|
1969
|
-
});
|
|
1970
|
-
return response;
|
|
1971
|
-
},
|
|
1972
|
-
|
|
1973
|
-
onError: (error) => {
|
|
1974
|
-
if (error instanceof AugurAPIError) {
|
|
1975
|
-
console.error(`[Augur] API Error ${error.code}:`, {
|
|
1976
|
-
message: error.message,
|
|
1977
|
-
service: error.service,
|
|
1978
|
-
endpoint: error.endpoint,
|
|
1979
|
-
statusCode: error.statusCode
|
|
1980
|
-
});
|
|
1981
|
-
}
|
|
1982
|
-
throw error;
|
|
1983
|
-
}
|
|
1984
|
-
});
|
|
1985
|
-
}
|
|
1986
|
-
|
|
1987
|
-
// User management
|
|
1988
|
-
async getUsers(limit = 50) {
|
|
1989
|
-
return this.api.joomla.users.list({
|
|
1990
|
-
limit,
|
|
1991
|
-
edgeCache: 2
|
|
1992
|
-
});
|
|
1993
|
-
}
|
|
1994
|
-
|
|
1995
|
-
async getUserById(id: string) {
|
|
1996
|
-
return this.api.joomla.users.get(id);
|
|
1997
|
-
}
|
|
1998
|
-
|
|
1999
|
-
// Product search
|
|
2000
|
-
async searchProducts(query: string, size = 20) {
|
|
2001
|
-
return this.api.opensearch.itemSearch.search({
|
|
2002
|
-
q: query,
|
|
2003
|
-
searchType: 'query',
|
|
2004
|
-
size,
|
|
2005
|
-
edgeCache: 3
|
|
2006
|
-
});
|
|
2007
|
-
}
|
|
2008
|
-
|
|
2009
|
-
// Inventory management
|
|
2010
|
-
async getWarehouseInventory(warehouseId: number, searchTerm?: string) {
|
|
2011
|
-
return this.api.vmi.invProfileHdr.checkAvailability(warehouseId, {
|
|
2012
|
-
q: searchTerm
|
|
2013
|
-
});
|
|
2014
|
-
}
|
|
2015
|
-
|
|
2016
|
-
async replenishInventory(warehouseId: number, items: Array<{
|
|
2017
|
-
inv_mast_uid: number;
|
|
2018
|
-
qty_to_order: number;
|
|
2019
|
-
}>) {
|
|
2020
|
-
return this.api.vmi.invProfileHdr.replenish(warehouseId, {
|
|
2021
|
-
distributor_uid: 1, // Default distributor
|
|
2022
|
-
restock_items: items
|
|
2023
|
-
});
|
|
2024
|
-
}
|
|
2025
|
-
|
|
2026
|
-
// Pricing
|
|
2027
|
-
async getProductPrice(customerId: number, itemId: string, quantity: number) {
|
|
2028
|
-
return this.api.pricing.getPrice({
|
|
2029
|
-
customerId,
|
|
2030
|
-
itemId,
|
|
2031
|
-
quantity,
|
|
2032
|
-
edgeCache: 3 // Cache pricing for 3 hours
|
|
2033
|
-
});
|
|
2034
|
-
}
|
|
2035
|
-
|
|
2036
|
-
// Health monitoring
|
|
2037
|
-
async checkAllServices() {
|
|
2038
|
-
const services = [
|
|
2039
|
-
'joomla', 'commerce', 'pricing', 'vmi', 'opensearch',
|
|
2040
|
-
'items', 'customers', 'orders', 'payments'
|
|
2041
|
-
];
|
|
2042
|
-
|
|
2043
|
-
const healthChecks = await Promise.allSettled(
|
|
2044
|
-
services.map(async (service) => {
|
|
2045
|
-
try {
|
|
2046
|
-
// Different services have different health check methods
|
|
2047
|
-
let health;
|
|
2048
|
-
if (service === 'vmi') {
|
|
2049
|
-
health = await this.api.vmi.health.check();
|
|
2050
|
-
} else if (service === 'opensearch') {
|
|
2051
|
-
health = await this.api.opensearch.health.check();
|
|
2052
|
-
} else {
|
|
2053
|
-
health = await (this.api as any)[service].getHealthCheck();
|
|
2054
|
-
}
|
|
2055
|
-
|
|
2056
|
-
return { service, status: 'healthy', data: health };
|
|
2057
|
-
} catch (error) {
|
|
2058
|
-
return {
|
|
2059
|
-
service,
|
|
2060
|
-
status: 'unhealthy',
|
|
2061
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
2062
|
-
};
|
|
2063
|
-
}
|
|
2064
|
-
})
|
|
2065
|
-
);
|
|
2066
|
-
|
|
2067
|
-
return healthChecks.map((result, index) => ({
|
|
2068
|
-
service: services[index],
|
|
2069
|
-
...(result.status === 'fulfilled' ? result.value : result.reason)
|
|
2070
|
-
}));
|
|
2071
|
-
}
|
|
2072
|
-
}
|
|
2073
|
-
|
|
2074
|
-
// Usage in Express.js app
|
|
2075
|
-
import express from 'express';
|
|
2076
|
-
import { AugurService } from './services/AugurService';
|
|
2077
|
-
|
|
2078
|
-
const app = express();
|
|
2079
|
-
const augurService = new AugurService();
|
|
2080
|
-
|
|
2081
|
-
// Get users endpoint
|
|
2082
|
-
app.get('/api/users', async (req, res) => {
|
|
2083
|
-
try {
|
|
2084
|
-
const users = await augurService.getUsers();
|
|
2085
|
-
res.json(users);
|
|
2086
|
-
} catch (error) {
|
|
2087
|
-
console.error('Failed to fetch users:', error);
|
|
2088
|
-
res.status(500).json({ error: 'Failed to fetch users' });
|
|
2089
|
-
}
|
|
2090
|
-
});
|
|
2091
|
-
|
|
2092
|
-
// Product search endpoint
|
|
2093
|
-
app.get('/api/products/search', async (req, res) => {
|
|
2094
|
-
const { q } = req.query;
|
|
2095
|
-
if (!q || typeof q !== 'string') {
|
|
2096
|
-
return res.status(400).json({ error: 'Search query required' });
|
|
2097
|
-
}
|
|
2098
|
-
|
|
2099
|
-
try {
|
|
2100
|
-
const products = await augurService.searchProducts(q);
|
|
2101
|
-
res.json(products);
|
|
2102
|
-
} catch (error) {
|
|
2103
|
-
console.error('Product search failed:', error);
|
|
2104
|
-
res.status(500).json({ error: 'Product search failed' });
|
|
2105
|
-
}
|
|
2106
|
-
});
|
|
2107
|
-
|
|
2108
|
-
// Health check endpoint
|
|
2109
|
-
app.get('/api/health', async (req, res) => {
|
|
2110
|
-
try {
|
|
2111
|
-
const healthStatus = await augurService.checkAllServices();
|
|
2112
|
-
const allHealthy = healthStatus.every(service => service.status === 'healthy');
|
|
2113
|
-
|
|
2114
|
-
res.status(allHealthy ? 200 : 503).json({
|
|
2115
|
-
status: allHealthy ? 'healthy' : 'degraded',
|
|
2116
|
-
services: healthStatus,
|
|
2117
|
-
timestamp: new Date().toISOString()
|
|
2118
|
-
});
|
|
2119
|
-
} catch (error) {
|
|
2120
|
-
console.error('Health check failed:', error);
|
|
2121
|
-
res.status(500).json({
|
|
2122
|
-
status: 'error',
|
|
2123
|
-
error: 'Health check failed'
|
|
2124
|
-
});
|
|
2125
|
-
}
|
|
2126
|
-
});
|
|
2127
|
-
|
|
2128
|
-
app.listen(3000, () => {
|
|
2129
|
-
console.log('Server running on port 3000');
|
|
2130
|
-
});
|
|
2131
|
-
```
|
|
2132
|
-
|
|
2133
|
-
### Electron Integration
|
|
2134
|
-
|
|
2135
|
-
```typescript
|
|
2136
|
-
// main/services/AugurService.ts
|
|
2137
|
-
import { AugurAPI } from '@simpleapps-com/augur-api';
|
|
2138
|
-
import { app } from 'electron';
|
|
2139
|
-
import path from 'path';
|
|
2140
|
-
import fs from 'fs';
|
|
2141
|
-
|
|
2142
|
-
export class ElectronAugurService {
|
|
2143
|
-
private api: AugurAPI;
|
|
2144
|
-
private configPath: string;
|
|
2145
|
-
|
|
2146
|
-
constructor() {
|
|
2147
|
-
this.configPath = path.join(app.getPath('userData'), 'augur-config.json');
|
|
2148
|
-
this.api = this.initializeAPI();
|
|
2149
|
-
}
|
|
2150
|
-
|
|
2151
|
-
private initializeAPI(): AugurAPI {
|
|
2152
|
-
const config = this.loadConfig();
|
|
2153
|
-
|
|
2154
|
-
return new AugurAPI({
|
|
2155
|
-
siteId: config.siteId,
|
|
2156
|
-
bearerToken: config.bearerToken,
|
|
2157
|
-
|
|
2158
|
-
// Electron-specific configuration
|
|
2159
|
-
timeout: 45000, // Longer timeout for desktop app
|
|
2160
|
-
|
|
2161
|
-
onRequest: (config) => {
|
|
2162
|
-
console.log(`[Augur Desktop] ${config.method} ${config.url}`);
|
|
2163
|
-
return config;
|
|
2164
|
-
},
|
|
2165
|
-
|
|
2166
|
-
onError: (error) => {
|
|
2167
|
-
// Show desktop notification for errors
|
|
2168
|
-
this.showErrorNotification(error.message);
|
|
2169
|
-
throw error;
|
|
2170
|
-
}
|
|
2171
|
-
});
|
|
2172
|
-
}
|
|
2173
|
-
|
|
2174
|
-
private loadConfig() {
|
|
2175
|
-
try {
|
|
2176
|
-
if (fs.existsSync(this.configPath)) {
|
|
2177
|
-
return JSON.parse(fs.readFileSync(this.configPath, 'utf8'));
|
|
2178
|
-
}
|
|
2179
|
-
} catch (error) {
|
|
2180
|
-
console.error('Failed to load config:', error);
|
|
2181
|
-
}
|
|
2182
|
-
|
|
2183
|
-
// Default configuration
|
|
2184
|
-
return {
|
|
2185
|
-
siteId: process.env.AUGUR_SITE_ID || '',
|
|
2186
|
-
bearerToken: process.env.AUGUR_BEARER_TOKEN || ''
|
|
2187
|
-
};
|
|
2188
|
-
}
|
|
2189
|
-
|
|
2190
|
-
saveConfig(config: { siteId: string; bearerToken: string }) {
|
|
2191
|
-
try {
|
|
2192
|
-
fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2));
|
|
2193
|
-
this.api.setSiteId(config.siteId);
|
|
2194
|
-
this.api.setAuthToken(config.bearerToken);
|
|
2195
|
-
} catch (error) {
|
|
2196
|
-
console.error('Failed to save config:', error);
|
|
2197
|
-
throw error;
|
|
2198
|
-
}
|
|
2199
|
-
}
|
|
2200
|
-
|
|
2201
|
-
private showErrorNotification(message: string) {
|
|
2202
|
-
// Implementation depends on your notification system
|
|
2203
|
-
console.error('Augur API Error:', message);
|
|
2204
|
-
}
|
|
2205
|
-
|
|
2206
|
-
// Exposed API methods
|
|
2207
|
-
async getUsers() {
|
|
2208
|
-
return this.api.joomla.users.list({
|
|
2209
|
-
limit: 100,
|
|
2210
|
-
edgeCache: 2
|
|
2211
|
-
});
|
|
2212
|
-
}
|
|
2213
|
-
|
|
2214
|
-
async searchProducts(query: string) {
|
|
2215
|
-
return this.api.opensearch.itemSearch.search({
|
|
2216
|
-
q: query,
|
|
2217
|
-
searchType: 'query',
|
|
2218
|
-
size: 50,
|
|
2219
|
-
edgeCache: 4
|
|
2220
|
-
});
|
|
2221
|
-
}
|
|
2222
|
-
|
|
2223
|
-
async getWarehouseData() {
|
|
2224
|
-
return this.api.vmi.warehouses.list({
|
|
2225
|
-
customerId: 12345,
|
|
2226
|
-
edgeCache: 4
|
|
2227
|
-
});
|
|
2228
|
-
}
|
|
2229
|
-
}
|
|
2230
|
-
|
|
2231
|
-
// renderer/hooks/useAugur.ts
|
|
2232
|
-
import { useEffect, useState } from 'react';
|
|
2233
|
-
|
|
2234
|
-
export function useAugur() {
|
|
2235
|
-
const [augurService, setAugurService] = useState(null);
|
|
2236
|
-
|
|
2237
|
-
useEffect(() => {
|
|
2238
|
-
// Get service from main process via IPC
|
|
2239
|
-
window.electronAPI.getAugurService().then(setAugurService);
|
|
2240
|
-
}, []);
|
|
2241
|
-
|
|
2242
|
-
return augurService;
|
|
2243
|
-
}
|
|
2244
|
-
```
|
|
2245
|
-
|
|
2246
|
-
## Error Handling
|
|
2247
|
-
|
|
2248
|
-
### Error Types
|
|
2249
|
-
|
|
2250
|
-
The library provides specific error types for different failure scenarios:
|
|
2251
|
-
|
|
2252
|
-
```typescript
|
|
2253
|
-
import {
|
|
2254
|
-
AugurAPIError, // Base error class
|
|
2255
|
-
AuthenticationError, // 401 errors
|
|
2256
|
-
ValidationError, // Request validation failures
|
|
2257
|
-
NotFoundError, // 404 errors
|
|
2258
|
-
RateLimitError, // 429 errors
|
|
2259
|
-
NetworkError // Network/connectivity issues
|
|
2260
|
-
} from '@simpleapps-com/augur-api';
|
|
2261
|
-
```
|
|
2262
|
-
|
|
2263
|
-
### Comprehensive Error Handling
|
|
2264
|
-
|
|
2265
|
-
```typescript
|
|
2266
|
-
async function handleAPICall() {
|
|
2267
|
-
try {
|
|
2268
|
-
const result = await api.joomla.users.list({ limit: 10 });
|
|
2269
|
-
return result;
|
|
2270
|
-
|
|
2271
|
-
} catch (error) {
|
|
2272
|
-
// Handle specific error types
|
|
2273
|
-
if (error instanceof AuthenticationError) {
|
|
2274
|
-
console.error('Authentication failed:', error.message);
|
|
2275
|
-
|
|
2276
|
-
// Specific auth error scenarios
|
|
2277
|
-
switch (error.statusCode) {
|
|
2278
|
-
case 401:
|
|
2279
|
-
// Token expired or invalid
|
|
2280
|
-
await refreshToken();
|
|
2281
|
-
break;
|
|
2282
|
-
default:
|
|
2283
|
-
redirectToLogin();
|
|
2284
|
-
}
|
|
2285
|
-
|
|
2286
|
-
} else if (error instanceof ValidationError) {
|
|
2287
|
-
console.error('Request validation failed:', error.validationErrors);
|
|
2288
|
-
|
|
2289
|
-
// Handle field-specific validation errors
|
|
2290
|
-
error.validationErrors?.forEach(validationError => {
|
|
2291
|
-
console.error(`Field ${validationError.path}: ${validationError.message}`);
|
|
2292
|
-
});
|
|
2293
|
-
|
|
2294
|
-
} else if (error instanceof NotFoundError) {
|
|
2295
|
-
console.error('Resource not found:', error.message);
|
|
2296
|
-
|
|
2297
|
-
// Show user-friendly not found message
|
|
2298
|
-
showNotFoundMessage(error.endpoint);
|
|
2299
|
-
|
|
2300
|
-
} else if (error instanceof RateLimitError) {
|
|
2301
|
-
console.error('Rate limit exceeded:', error.message);
|
|
2302
|
-
|
|
2303
|
-
// Implement exponential backoff
|
|
2304
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
2305
|
-
return handleAPICall(); // Retry
|
|
2306
|
-
|
|
2307
|
-
} else if (error instanceof AugurAPIError) {
|
|
2308
|
-
console.error('API error:', {
|
|
2309
|
-
code: error.code,
|
|
2310
|
-
message: error.message,
|
|
2311
|
-
service: error.service,
|
|
2312
|
-
endpoint: error.endpoint,
|
|
2313
|
-
statusCode: error.statusCode,
|
|
2314
|
-
requestId: error.requestId
|
|
2315
|
-
});
|
|
2316
|
-
|
|
2317
|
-
// Handle by status code
|
|
2318
|
-
switch (error.statusCode) {
|
|
2319
|
-
case 500:
|
|
2320
|
-
showErrorMessage('Server error. Please try again later.');
|
|
2321
|
-
break;
|
|
2322
|
-
case 503:
|
|
2323
|
-
showErrorMessage('Service temporarily unavailable.');
|
|
2324
|
-
break;
|
|
2325
|
-
default:
|
|
2326
|
-
showErrorMessage(`API error: ${error.message}`);
|
|
2327
|
-
}
|
|
2328
|
-
|
|
2329
|
-
} else {
|
|
2330
|
-
console.error('Unexpected error:', error);
|
|
2331
|
-
showErrorMessage('An unexpected error occurred.');
|
|
2332
|
-
}
|
|
2333
|
-
|
|
2334
|
-
throw error; // Re-throw if needed
|
|
2335
|
-
}
|
|
2336
|
-
}
|
|
2337
|
-
```
|
|
2338
|
-
|
|
2339
|
-
### Retry Logic with Exponential Backoff
|
|
2340
|
-
|
|
2341
|
-
```typescript
|
|
2342
|
-
async function apiCallWithRetry<T>(
|
|
2343
|
-
operation: () => Promise<T>,
|
|
2344
|
-
maxRetries = 3,
|
|
2345
|
-
baseDelay = 1000
|
|
2346
|
-
): Promise<T> {
|
|
2347
|
-
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
2348
|
-
try {
|
|
2349
|
-
return await operation();
|
|
2350
|
-
|
|
2351
|
-
} catch (error) {
|
|
2352
|
-
// Don't retry on authentication or validation errors
|
|
2353
|
-
if (error instanceof AuthenticationError ||
|
|
2354
|
-
error instanceof ValidationError) {
|
|
2355
|
-
throw error;
|
|
2356
|
-
}
|
|
2357
|
-
|
|
2358
|
-
// Don't retry on final attempt
|
|
2359
|
-
if (attempt === maxRetries) {
|
|
2360
|
-
throw error;
|
|
2361
|
-
}
|
|
2362
|
-
|
|
2363
|
-
// Calculate delay with exponential backoff
|
|
2364
|
-
const delay = baseDelay * Math.pow(2, attempt - 1);
|
|
2365
|
-
console.log(`Attempt ${attempt} failed, retrying in ${delay}ms...`);
|
|
2366
|
-
|
|
2367
|
-
await new Promise(resolve => setTimeout(resolve, delay));
|
|
2368
|
-
}
|
|
2369
|
-
}
|
|
2370
|
-
|
|
2371
|
-
throw new Error('All retry attempts exhausted');
|
|
2372
|
-
}
|
|
2373
|
-
|
|
2374
|
-
// Usage
|
|
2375
|
-
const users = await apiCallWithRetry(() =>
|
|
2376
|
-
api.joomla.users.list({ limit: 10 })
|
|
2377
|
-
);
|
|
2378
|
-
```
|
|
2379
|
-
|
|
2380
|
-
### Global Error Handler
|
|
2381
|
-
|
|
2382
|
-
```typescript
|
|
2383
|
-
class ErrorHandler {
|
|
2384
|
-
static handle(error: unknown, context?: string): void {
|
|
2385
|
-
const contextPrefix = context ? `[${context}] ` : '';
|
|
2386
|
-
|
|
2387
|
-
if (error instanceof AuthenticationError) {
|
|
2388
|
-
console.error(`${contextPrefix}Authentication failed:`, error.message);
|
|
2389
|
-
this.handleAuthError(error);
|
|
2390
|
-
|
|
2391
|
-
} else if (error instanceof ValidationError) {
|
|
2392
|
-
console.error(`${contextPrefix}Validation failed:`, error.validationErrors);
|
|
2393
|
-
this.handleValidationError(error);
|
|
2394
|
-
|
|
2395
|
-
} else if (error instanceof AugurAPIError) {
|
|
2396
|
-
console.error(`${contextPrefix}API error:`, {
|
|
2397
|
-
service: error.service,
|
|
2398
|
-
endpoint: error.endpoint,
|
|
2399
|
-
code: error.code,
|
|
2400
|
-
message: error.message
|
|
2401
|
-
});
|
|
2402
|
-
this.handleAPIError(error);
|
|
2403
|
-
|
|
2404
|
-
} else {
|
|
2405
|
-
console.error(`${contextPrefix}Unexpected error:`, error);
|
|
2406
|
-
this.handleUnknownError(error);
|
|
2407
|
-
}
|
|
2408
|
-
}
|
|
2409
|
-
|
|
2410
|
-
private static handleAuthError(error: AuthenticationError): void {
|
|
2411
|
-
// Implement auth error handling
|
|
2412
|
-
if (typeof window !== 'undefined') {
|
|
2413
|
-
// Browser environment
|
|
2414
|
-
localStorage.removeItem('authToken');
|
|
2415
|
-
window.location.href = '/login';
|
|
2416
|
-
} else {
|
|
2417
|
-
// Node.js environment
|
|
2418
|
-
process.exit(1);
|
|
2419
|
-
}
|
|
2420
|
-
}
|
|
2421
|
-
|
|
2422
|
-
private static handleValidationError(error: ValidationError): void {
|
|
2423
|
-
// Show validation errors to user
|
|
2424
|
-
console.error('Please check your input:', error.validationErrors);
|
|
2425
|
-
}
|
|
2426
|
-
|
|
2427
|
-
private static handleAPIError(error: AugurAPIError): void {
|
|
2428
|
-
// Handle different API error codes
|
|
2429
|
-
switch (error.code) {
|
|
2430
|
-
case 'RATE_LIMIT_EXCEEDED':
|
|
2431
|
-
console.log('Please wait before making more requests');
|
|
2432
|
-
break;
|
|
2433
|
-
case 'SERVICE_UNAVAILABLE':
|
|
2434
|
-
console.log('Service is temporarily unavailable');
|
|
2435
|
-
break;
|
|
2436
|
-
default:
|
|
2437
|
-
console.log(`Service error: ${error.message}`);
|
|
2438
|
-
}
|
|
2439
|
-
}
|
|
2440
|
-
|
|
2441
|
-
private static handleUnknownError(error: unknown): void {
|
|
2442
|
-
console.error('An unexpected error occurred:', error);
|
|
2443
|
-
}
|
|
2444
|
-
}
|
|
2445
|
-
|
|
2446
|
-
// Use in API calls
|
|
2447
|
-
try {
|
|
2448
|
-
const result = await api.joomla.users.list();
|
|
2449
|
-
} catch (error) {
|
|
2450
|
-
ErrorHandler.handle(error, 'UserList');
|
|
2451
|
-
}
|
|
2452
|
-
```
|
|
2453
|
-
|
|
2454
|
-
## Configuration
|
|
2455
|
-
|
|
2456
|
-
### Basic Configuration
|
|
2457
|
-
|
|
2458
|
-
```typescript
|
|
2459
|
-
import { AugurAPI } from '@simpleapps-com/augur-api';
|
|
2460
|
-
|
|
2461
|
-
const api = new AugurAPI({
|
|
2462
|
-
// Required
|
|
2463
|
-
siteId: 'your-site-id',
|
|
2464
|
-
|
|
2465
|
-
// Authentication (required for most endpoints)
|
|
2466
|
-
bearerToken: 'your-jwt-token',
|
|
2467
|
-
|
|
2468
|
-
// Optional HTTP settings
|
|
2469
|
-
timeout: 30000, // Request timeout in ms (default: 30000)
|
|
2470
|
-
retries: 3, // Number of retries (default: 3)
|
|
2471
|
-
retryDelay: 1000, // Delay between retries in ms (default: 1000)
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
// Request/Response interceptors
|
|
2475
|
-
onRequest: (config) => {
|
|
2476
|
-
console.log('Making request:', config.url);
|
|
2477
|
-
return config;
|
|
2478
|
-
},
|
|
2479
|
-
|
|
2480
|
-
onResponse: (response) => {
|
|
2481
|
-
console.log('Received response:', response.status);
|
|
2482
|
-
return response;
|
|
2483
|
-
},
|
|
2484
|
-
|
|
2485
|
-
onError: (error) => {
|
|
2486
|
-
console.error('Request failed:', error.message);
|
|
2487
|
-
throw error;
|
|
2488
|
-
}
|
|
2489
|
-
});
|
|
2490
|
-
```
|
|
2491
|
-
|
|
2492
|
-
### Environment-Based Configuration
|
|
2493
|
-
|
|
2494
|
-
```typescript
|
|
2495
|
-
// config/augur.ts
|
|
2496
|
-
interface AugurConfig {
|
|
2497
|
-
siteId: string;
|
|
2498
|
-
bearerToken?: string;
|
|
2499
|
-
timeout: number;
|
|
2500
|
-
retries: number;
|
|
2501
|
-
}
|
|
2502
|
-
|
|
2503
|
-
const environments = {
|
|
2504
|
-
development: {
|
|
2505
|
-
siteId: process.env.AUGUR_DEV_SITE_ID!,
|
|
2506
|
-
bearerToken: process.env.AUGUR_DEV_TOKEN,
|
|
2507
|
-
timeout: 45000, // Longer timeout for dev
|
|
2508
|
-
retries: 1, // Fewer retries for faster feedback
|
|
2509
|
-
},
|
|
2510
|
-
|
|
2511
|
-
staging: {
|
|
2512
|
-
siteId: process.env.AUGUR_STAGING_SITE_ID!,
|
|
2513
|
-
bearerToken: process.env.AUGUR_STAGING_TOKEN,
|
|
2514
|
-
timeout: 30000,
|
|
2515
|
-
retries: 2,
|
|
2516
|
-
},
|
|
2517
|
-
|
|
2518
|
-
production: {
|
|
2519
|
-
siteId: process.env.AUGUR_PROD_SITE_ID!,
|
|
2520
|
-
bearerToken: process.env.AUGUR_PROD_TOKEN,
|
|
2521
|
-
timeout: 30000,
|
|
2522
|
-
retries: 3,
|
|
2523
|
-
}
|
|
2524
|
-
} as const;
|
|
2525
|
-
|
|
2526
|
-
export function getAugurConfig(): AugurConfig {
|
|
2527
|
-
const env = process.env.NODE_ENV || 'development';
|
|
2528
|
-
const config = environments[env as keyof typeof environments];
|
|
2529
|
-
|
|
2530
|
-
if (!config) {
|
|
2531
|
-
throw new Error(`No Augur configuration found for environment: ${env}`);
|
|
2532
|
-
}
|
|
2533
|
-
|
|
2534
|
-
if (!config.siteId) {
|
|
2535
|
-
throw new Error(`Augur site ID not configured for environment: ${env}`);
|
|
2536
|
-
}
|
|
2537
|
-
|
|
2538
|
-
return config;
|
|
2539
|
-
}
|
|
2540
|
-
|
|
2541
|
-
// Usage
|
|
2542
|
-
import { getAugurConfig } from './config/augur';
|
|
2543
|
-
|
|
2544
|
-
const api = new AugurAPI(getAugurConfig());
|
|
2545
|
-
```
|
|
2546
|
-
|
|
2547
|
-
### Configuration Validation
|
|
2548
|
-
|
|
2549
|
-
```typescript
|
|
2550
|
-
import { z } from 'zod';
|
|
2551
|
-
|
|
2552
|
-
const AugurConfigSchema = z.object({
|
|
2553
|
-
siteId: z.string().min(1, 'Site ID is required'),
|
|
2554
|
-
bearerToken: z.string().optional(),
|
|
2555
|
-
timeout: z.number().positive().optional(),
|
|
2556
|
-
retries: z.number().int().min(0).max(10).optional(),
|
|
2557
|
-
});
|
|
2558
|
-
|
|
2559
|
-
export function createValidatedAugurAPI(config: unknown): AugurAPI {
|
|
2560
|
-
const validatedConfig = AugurConfigSchema.parse(config);
|
|
2561
|
-
return new AugurAPI(validatedConfig);
|
|
2562
|
-
}
|
|
2563
|
-
|
|
2564
|
-
// Usage with validation
|
|
2565
|
-
try {
|
|
2566
|
-
const api = createValidatedAugurAPI({
|
|
2567
|
-
siteId: process.env.AUGUR_SITE_ID,
|
|
2568
|
-
bearerToken: process.env.AUGUR_TOKEN,
|
|
2569
|
-
timeout: 30000,
|
|
2570
|
-
retries: 3
|
|
2571
|
-
});
|
|
2572
|
-
} catch (error) {
|
|
2573
|
-
if (error instanceof z.ZodError) {
|
|
2574
|
-
console.error('Configuration validation failed:', error.errors);
|
|
2575
|
-
process.exit(1);
|
|
2576
|
-
}
|
|
2577
|
-
}
|
|
2578
|
-
```
|
|
2579
|
-
|
|
2580
|
-
### Dynamic Configuration Updates
|
|
2581
|
-
|
|
2582
|
-
```typescript
|
|
2583
|
-
class ManagedAugurAPI {
|
|
2584
|
-
private api: AugurAPI;
|
|
2585
|
-
private config: AugurConfig;
|
|
2586
|
-
|
|
2587
|
-
constructor(initialConfig: AugurConfig) {
|
|
2588
|
-
this.config = initialConfig;
|
|
2589
|
-
this.api = new AugurAPI(initialConfig);
|
|
2590
|
-
}
|
|
2591
|
-
|
|
2592
|
-
updateConfig(newConfig: Partial<AugurConfig>): void {
|
|
2593
|
-
this.config = { ...this.config, ...newConfig };
|
|
2594
|
-
|
|
2595
|
-
// Update specific properties that can be changed at runtime
|
|
2596
|
-
if (newConfig.bearerToken !== undefined) {
|
|
2597
|
-
this.api.setAuthToken(newConfig.bearerToken);
|
|
2598
|
-
}
|
|
2599
|
-
|
|
2600
|
-
if (newConfig.siteId !== undefined) {
|
|
2601
|
-
this.api.setSiteId(newConfig.siteId);
|
|
2602
|
-
}
|
|
2603
|
-
|
|
2604
|
-
// For other config changes, recreate the API instance
|
|
2605
|
-
if (newConfig.timeout || newConfig.retries) {
|
|
2606
|
-
this.api = new AugurAPI(this.config);
|
|
2607
|
-
}
|
|
2608
|
-
}
|
|
2609
|
-
|
|
2610
|
-
getAPI(): AugurAPI {
|
|
2611
|
-
return this.api;
|
|
2612
|
-
}
|
|
2613
|
-
|
|
2614
|
-
getCurrentConfig(): AugurConfig {
|
|
2615
|
-
return { ...this.config };
|
|
2616
|
-
}
|
|
2617
|
-
}
|
|
2618
|
-
|
|
2619
|
-
// Usage
|
|
2620
|
-
const managedAPI = new ManagedAugurAPI({
|
|
2621
|
-
siteId: 'initial-site',
|
|
2622
|
-
bearerToken: 'initial-token'
|
|
2623
|
-
});
|
|
2624
|
-
|
|
2625
|
-
// Update token after authentication
|
|
2626
|
-
managedAPI.updateConfig({
|
|
2627
|
-
bearerToken: 'new-token-after-auth'
|
|
2628
|
-
});
|
|
2629
|
-
|
|
2630
|
-
// Switch to different site
|
|
2631
|
-
managedAPI.updateConfig({
|
|
2632
|
-
siteId: 'different-site',
|
|
2633
|
-
bearerToken: 'site-specific-token'
|
|
2634
|
-
});
|
|
2635
|
-
```
|
|
2636
|
-
|
|
2637
|
-
## Performance Optimization
|
|
2638
|
-
|
|
2639
|
-
> 📋 **[Complete Performance Guide](./PERFORMANCE.md)** - Comprehensive strategies for edge caching, batch operations, pagination optimization, and performance monitoring.
|
|
2640
|
-
|
|
2641
|
-
**Quick Performance Tips:**
|
|
2642
|
-
|
|
2643
|
-
```typescript
|
|
2644
|
-
// ⚡ Edge caching with Cloudflare CDN
|
|
2645
|
-
const categories = await api.items.categories.list({ edgeCache: 8 }); // Static data: 8 hours
|
|
2646
|
-
const pricing = await api.pricing.getPrice({ customerId: 123, edgeCache: 3 }); // Dynamic: 3 hours
|
|
2647
|
-
const inventory = await api.vmi.invProfileHdr.checkAvailability(123, { edgeCache: 1 }); // Volatile: 1 hour
|
|
2648
|
-
|
|
2649
|
-
// 🚀 Batch operations for multiple requests
|
|
2650
|
-
const [users, groups, content] = await Promise.allSettled([
|
|
2651
|
-
api.joomla.users.list({ limit: 50, edgeCache: 2 }),
|
|
2652
|
-
api.joomla.userGroups.list({ edgeCache: 8 }),
|
|
2653
|
-
api.joomla.content.list({ categoryIdList: '1,2,3', edgeCache: 6 })
|
|
2654
|
-
]);
|
|
2655
|
-
|
|
2656
|
-
// 📄 Smart pagination with prefetching
|
|
2657
|
-
class SmartPagination {
|
|
2658
|
-
async loadPage(fetcher, page, pageSize = 50) {
|
|
2659
|
-
// Automatic prefetching and caching
|
|
2660
|
-
return this.loadWithPrefetch(fetcher, page, pageSize);
|
|
2661
|
-
}
|
|
2662
|
-
}
|
|
2663
|
-
```
|
|
2664
|
-
|
|
2665
|
-
**Key Performance Features:**
|
|
2666
|
-
- **Edge Cache Decision Tree** - Choose optimal cache duration by data volatility
|
|
2667
|
-
- **Service-Specific Batching** - Parallel operations tailored to each microservice
|
|
2668
|
-
- **Advanced Pagination** - Prefetching, infinite scroll, and streaming patterns
|
|
2669
|
-
- **Performance Analytics** - Monitor cache hit rates, response times, and optimization opportunities
|
|
2670
|
-
|
|
2671
|
-
For complete implementation details, see [Performance Optimization Guide](./PERFORMANCE.md).
|
|
2672
|
-
|
|
2673
|
-
## Enterprise Integration Patterns
|
|
2674
|
-
|
|
2675
|
-
**Scale your enterprise applications** with proven patterns for multi-tenant architectures, cross-site authentication, and production deployment.
|
|
2676
|
-
|
|
2677
|
-
### Cross-Site Authentication Architecture
|
|
2678
|
-
|
|
2679
|
-
> 📋 **[Complete Authentication Guide](./AUTHENTICATION.md)** - Detailed implementation patterns, security considerations, and troubleshooting.
|
|
2680
|
-
|
|
2681
|
-
**Enterprise Authentication Flow:**
|
|
2682
|
-
|
|
2683
|
-
```typescript
|
|
2684
|
-
/**
|
|
2685
|
-
* 🏢 ENTERPRISE MULTI-TENANT AUTHENTICATION
|
|
2686
|
-
*
|
|
2687
|
-
* Supports authenticating users across multiple tenant sites
|
|
2688
|
-
* from a centralized application or admin dashboard.
|
|
2689
|
-
*/
|
|
2690
|
-
|
|
2691
|
-
import { createCrossSiteAuthenticator, authenticateUserForSite } from '@simpleapps-com/augur-api';
|
|
2692
|
-
|
|
2693
|
-
// 🎯 Option 1: Single Authentication (Recommended for most cases)
|
|
2694
|
-
const authResult = await authenticateUserForSite({
|
|
2695
|
-
targetSiteId: 'tenant_site_alpha',
|
|
2696
|
-
username: 'user@tenant.com',
|
|
2697
|
-
password: 'user_password',
|
|
2698
|
-
augurInfoToken: process.env.AUGUR_ADMIN_TOKEN! // Admin token with augur_info privileges
|
|
2699
|
-
});
|
|
2700
|
-
|
|
2701
|
-
if (authResult.success) {
|
|
2702
|
-
// Ready-to-use API client for the tenant
|
|
2703
|
-
const tenantAPI = authResult.targetSiteAPI!;
|
|
2704
|
-
const userData = await tenantAPI.joomla.users.get(authResult.userId!);
|
|
2705
|
-
console.log(`✅ Authenticated: ${authResult.username} on ${targetSiteId}`);
|
|
2706
|
-
}
|
|
2707
|
-
|
|
2708
|
-
// 🎯 Option 2: Reusable Authenticator (For multiple sites)
|
|
2709
|
-
const crossSiteAuth = createCrossSiteAuthenticator(process.env.AUGUR_ADMIN_TOKEN!);
|
|
2710
|
-
|
|
2711
|
-
const tenantResults = await Promise.allSettled([
|
|
2712
|
-
crossSiteAuth('tenant_alpha', 'user@alpha.com', 'pass1'),
|
|
2713
|
-
crossSiteAuth('tenant_beta', 'user@beta.com', 'pass2'),
|
|
2714
|
-
crossSiteAuth('tenant_gamma', 'user@gamma.com', 'pass3')
|
|
2715
|
-
]);
|
|
2716
|
-
|
|
2717
|
-
// Process results for each tenant
|
|
2718
|
-
tenantResults.forEach((result, index) => {
|
|
2719
|
-
const tenantId = ['tenant_alpha', 'tenant_beta', 'tenant_gamma'][index];
|
|
2720
|
-
if (result.status === 'fulfilled' && result.value.success) {
|
|
2721
|
-
console.log(`✅ ${tenantId}: User authenticated`);
|
|
2722
|
-
}
|
|
2723
|
-
});
|
|
2724
|
-
```
|
|
2725
|
-
|
|
2726
|
-
**Authentication Flow Diagram:**
|
|
2727
|
-
```
|
|
2728
|
-
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
2729
|
-
│ Your App │───▶│ augur_info │───▶│ Target Site │───▶│ User Token │
|
|
2730
|
-
│ │ │ (Admin) │ │ (Tenant) │ │ (Scoped) │
|
|
2731
|
-
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
|
|
2732
|
-
│ │ │ │
|
|
2733
|
-
Admin JWT Verify User Check Password Return Scoped
|
|
2734
|
-
Token Credentials Against Site JWT for Site
|
|
2735
|
-
```
|
|
2736
|
-
|
|
2737
|
-
### Multi-Tenant Setup Patterns
|
|
2738
|
-
|
|
2739
|
-
**Configure your application** for enterprise multi-tenancy with these proven patterns:
|
|
2740
|
-
|
|
2741
|
-
```typescript
|
|
2742
|
-
/**
|
|
2743
|
-
* 🏗️ MULTI-TENANT ARCHITECTURE PATTERNS
|
|
2744
|
-
*
|
|
2745
|
-
* Choose the pattern that best fits your enterprise requirements:
|
|
2746
|
-
* - Shared Infrastructure, Isolated Data
|
|
2747
|
-
* - Complete Tenant Isolation
|
|
2748
|
-
* - Hybrid Multi-Tenant Model
|
|
2749
|
-
*/
|
|
2750
|
-
|
|
2751
|
-
// 🏢 Pattern 1: Tenant Context Manager (Recommended)
|
|
2752
|
-
class TenantContextManager {
|
|
2753
|
-
private tenantAPIs = new Map<string, AugurAPI>();
|
|
2754
|
-
private currentTenant: string | null = null;
|
|
2755
|
-
|
|
2756
|
-
async initializeTenant(
|
|
2757
|
-
tenantId: string,
|
|
2758
|
-
userCredentials: { username: string; password: string },
|
|
2759
|
-
adminToken: string
|
|
2760
|
-
): Promise<boolean> {
|
|
2761
|
-
try {
|
|
2762
|
-
const authResult = await authenticateUserForSite({
|
|
2763
|
-
targetSiteId: tenantId,
|
|
2764
|
-
username: userCredentials.username,
|
|
2765
|
-
password: userCredentials.password,
|
|
2766
|
-
augurInfoToken: adminToken
|
|
2767
|
-
});
|
|
2768
|
-
|
|
2769
|
-
if (authResult.success) {
|
|
2770
|
-
// Store authenticated API client for tenant
|
|
2771
|
-
this.tenantAPIs.set(tenantId, authResult.targetSiteAPI!);
|
|
2772
|
-
this.currentTenant = tenantId;
|
|
2773
|
-
|
|
2774
|
-
console.log(`✅ Tenant ${tenantId} initialized successfully`);
|
|
2775
|
-
return true;
|
|
2776
|
-
}
|
|
2777
|
-
|
|
2778
|
-
console.error(`❌ Failed to initialize tenant ${tenantId}: ${authResult.error}`);
|
|
2779
|
-
return false;
|
|
2780
|
-
} catch (error) {
|
|
2781
|
-
console.error(`❌ Tenant initialization error:`, error);
|
|
2782
|
-
return false;
|
|
2783
|
-
}
|
|
2784
|
-
}
|
|
2785
|
-
|
|
2786
|
-
// Switch between tenants seamlessly
|
|
2787
|
-
switchTenant(tenantId: string): AugurAPI | null {
|
|
2788
|
-
if (this.tenantAPIs.has(tenantId)) {
|
|
2789
|
-
this.currentTenant = tenantId;
|
|
2790
|
-
return this.tenantAPIs.get(tenantId)!;
|
|
2791
|
-
}
|
|
2792
|
-
|
|
2793
|
-
console.warn(`⚠️ Tenant ${tenantId} not initialized`);
|
|
2794
|
-
return null;
|
|
2795
|
-
}
|
|
2796
|
-
|
|
2797
|
-
// Get current tenant's API client
|
|
2798
|
-
getCurrentAPI(): AugurAPI | null {
|
|
2799
|
-
return this.currentTenant ? this.tenantAPIs.get(this.currentTenant) || null : null;
|
|
2800
|
-
}
|
|
2801
|
-
|
|
2802
|
-
// Bulk operations across all tenants
|
|
2803
|
-
async executeAcrossAllTenants<T>(
|
|
2804
|
-
operation: (api: AugurAPI, tenantId: string) => Promise<T>
|
|
2805
|
-
): Promise<Array<{ tenantId: string; result: T; success: boolean; error?: string }>> {
|
|
2806
|
-
const results: Array<{ tenantId: string; result: T; success: boolean; error?: string }> = [];
|
|
2807
|
-
|
|
2808
|
-
for (const [tenantId, api] of this.tenantAPIs.entries()) {
|
|
2809
|
-
try {
|
|
2810
|
-
const result = await operation(api, tenantId);
|
|
2811
|
-
results.push({ tenantId, result, success: true });
|
|
2812
|
-
} catch (error) {
|
|
2813
|
-
results.push({
|
|
2814
|
-
tenantId,
|
|
2815
|
-
result: null as any,
|
|
2816
|
-
success: false,
|
|
2817
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
2818
|
-
});
|
|
2819
|
-
}
|
|
2820
|
-
}
|
|
2821
|
-
|
|
2822
|
-
return results;
|
|
2823
|
-
}
|
|
2824
|
-
}
|
|
2825
|
-
|
|
2826
|
-
// 🏢 Pattern 2: Tenant Factory (For dynamic tenant creation)
|
|
2827
|
-
class TenantAPIFactory {
|
|
2828
|
-
constructor(private adminToken: string) {}
|
|
2829
|
-
|
|
2830
|
-
async createTenantAPI(
|
|
2831
|
-
tenantId: string,
|
|
2832
|
-
userCredentials: { username: string; password: string }
|
|
2833
|
-
): Promise<AugurAPI | null> {
|
|
2834
|
-
const authResult = await authenticateUserForSite({
|
|
2835
|
-
targetSiteId: tenantId,
|
|
2836
|
-
username: userCredentials.username,
|
|
2837
|
-
password: userCredentials.password,
|
|
2838
|
-
augurInfoToken: this.adminToken
|
|
2839
|
-
});
|
|
2840
|
-
|
|
2841
|
-
return authResult.success ? authResult.targetSiteAPI! : null;
|
|
2842
|
-
}
|
|
2843
|
-
|
|
2844
|
-
// Create multiple tenant APIs in parallel
|
|
2845
|
-
async createMultipleTenantAPIs(
|
|
2846
|
-
tenantConfigs: Array<{
|
|
2847
|
-
tenantId: string;
|
|
2848
|
-
credentials: { username: string; password: string };
|
|
2849
|
-
}>
|
|
2850
|
-
): Promise<Map<string, AugurAPI>> {
|
|
2851
|
-
const results = await Promise.allSettled(
|
|
2852
|
-
tenantConfigs.map(async ({ tenantId, credentials }) => ({
|
|
2853
|
-
tenantId,
|
|
2854
|
-
api: await this.createTenantAPI(tenantId, credentials)
|
|
2855
|
-
}))
|
|
2856
|
-
);
|
|
2857
|
-
|
|
2858
|
-
const tenantAPIs = new Map<string, AugurAPI>();
|
|
2859
|
-
|
|
2860
|
-
results.forEach((result, index) => {
|
|
2861
|
-
if (result.status === 'fulfilled' && result.value.api) {
|
|
2862
|
-
tenantAPIs.set(result.value.tenantId, result.value.api);
|
|
2863
|
-
} else {
|
|
2864
|
-
const tenantId = tenantConfigs[index].tenantId;
|
|
2865
|
-
console.error(`❌ Failed to create API for tenant: ${tenantId}`);
|
|
2866
|
-
}
|
|
2867
|
-
});
|
|
2868
|
-
|
|
2869
|
-
return tenantAPIs;
|
|
2870
|
-
}
|
|
2871
|
-
}
|
|
2872
|
-
|
|
2873
|
-
// 🏢 Pattern 3: Multi-Tenant Dashboard Implementation
|
|
2874
|
-
class MultiTenantDashboard {
|
|
2875
|
-
private tenantManager = new TenantContextManager();
|
|
2876
|
-
private tenantFactory: TenantAPIFactory;
|
|
2877
|
-
|
|
2878
|
-
constructor(adminToken: string) {
|
|
2879
|
-
this.tenantFactory = new TenantAPIFactory(adminToken);
|
|
2880
|
-
}
|
|
2881
|
-
|
|
2882
|
-
async initializeDashboard(
|
|
2883
|
-
userCredentials: { username: string; password: string },
|
|
2884
|
-
tenantIds: string[]
|
|
2885
|
-
): Promise<void> {
|
|
2886
|
-
console.log(`🚀 Initializing dashboard for ${tenantIds.length} tenants...`);
|
|
2887
|
-
|
|
2888
|
-
// Initialize all tenants in parallel
|
|
2889
|
-
const initResults = await Promise.allSettled(
|
|
2890
|
-
tenantIds.map(tenantId =>
|
|
2891
|
-
this.tenantManager.initializeTenant(
|
|
2892
|
-
tenantId,
|
|
2893
|
-
userCredentials,
|
|
2894
|
-
process.env.AUGUR_ADMIN_TOKEN!
|
|
2895
|
-
)
|
|
2896
|
-
)
|
|
2897
|
-
);
|
|
2898
|
-
|
|
2899
|
-
const successCount = initResults.filter(r =>
|
|
2900
|
-
r.status === 'fulfilled' && r.value === true
|
|
2901
|
-
).length;
|
|
2902
|
-
|
|
2903
|
-
console.log(`✅ Dashboard initialized: ${successCount}/${tenantIds.length} tenants ready`);
|
|
2904
|
-
}
|
|
2905
|
-
|
|
2906
|
-
// Get aggregated data across all tenants
|
|
2907
|
-
async getAggregatedUserData(): Promise<Record<string, any[]>> {
|
|
2908
|
-
const results = await this.tenantManager.executeAcrossAllTenants(
|
|
2909
|
-
async (api, tenantId) => {
|
|
2910
|
-
const users = await api.joomla.users.listData({ limit: 100 });
|
|
2911
|
-
return { tenantId, userCount: users.length, users };
|
|
2912
|
-
}
|
|
2913
|
-
);
|
|
2914
|
-
|
|
2915
|
-
const aggregatedData: Record<string, any[]> = {};
|
|
2916
|
-
results.forEach(({ tenantId, result, success }) => {
|
|
2917
|
-
if (success) {
|
|
2918
|
-
aggregatedData[tenantId] = result.users;
|
|
2919
|
-
}
|
|
2920
|
-
});
|
|
2921
|
-
|
|
2922
|
-
return aggregatedData;
|
|
2923
|
-
}
|
|
2924
|
-
|
|
2925
|
-
// Bulk operations example
|
|
2926
|
-
async bulkUpdateAcrossTenants(updates: Record<string, any>): Promise<void> {
|
|
2927
|
-
const results = await this.tenantManager.executeAcrossAllTenants(
|
|
2928
|
-
async (api, tenantId) => {
|
|
2929
|
-
// Example: Update site settings across all tenants
|
|
2930
|
-
return await api.agrsite.settings.update(updates);
|
|
2931
|
-
}
|
|
2932
|
-
);
|
|
2933
|
-
|
|
2934
|
-
const successCount = results.filter(r => r.success).length;
|
|
2935
|
-
console.log(`✅ Bulk update completed: ${successCount}/${results.length} tenants updated`);
|
|
2936
|
-
}
|
|
2937
|
-
}
|
|
2938
|
-
|
|
2939
|
-
// 🎮 USAGE EXAMPLES
|
|
2940
|
-
|
|
2941
|
-
// Initialize multi-tenant dashboard
|
|
2942
|
-
const dashboard = new MultiTenantDashboard(process.env.AUGUR_ADMIN_TOKEN!);
|
|
2943
|
-
|
|
2944
|
-
await dashboard.initializeDashboard(
|
|
2945
|
-
{ username: 'admin@company.com', password: 'admin_password' },
|
|
2946
|
-
['tenant_alpha', 'tenant_beta', 'tenant_gamma']
|
|
2947
|
-
);
|
|
2948
|
-
|
|
2949
|
-
// Get aggregated data from all tenants
|
|
2950
|
-
const userData = await dashboard.getAggregatedUserData();
|
|
2951
|
-
console.log('User data across all tenants:', userData);
|
|
2952
|
-
|
|
2953
|
-
// Execute bulk operations
|
|
2954
|
-
await dashboard.bulkUpdateAcrossTenants({
|
|
2955
|
-
maintenanceMode: false,
|
|
2956
|
-
themeColor: '#2563eb'
|
|
2957
|
-
});
|
|
2958
|
-
```
|
|
2959
|
-
|
|
2960
|
-
### Security Configuration Best Practices
|
|
2961
|
-
|
|
2962
|
-
**Secure your enterprise deployment** with comprehensive security measures:
|
|
2963
|
-
|
|
2964
|
-
```typescript
|
|
2965
|
-
/**
|
|
2966
|
-
* 🔒 ENTERPRISE SECURITY CONFIGURATION
|
|
2967
|
-
*
|
|
2968
|
-
* Implement defense-in-depth security practices for production
|
|
2969
|
-
* environments with comprehensive monitoring and access control.
|
|
2970
|
-
*/
|
|
2971
|
-
|
|
2972
|
-
// 🛡️ Secure Configuration Manager
|
|
2973
|
-
class SecureConfigManager {
|
|
2974
|
-
private static readonly SECURITY_CONFIG = {
|
|
2975
|
-
// Token rotation intervals (in milliseconds)
|
|
2976
|
-
TOKEN_ROTATION_INTERVAL: 4 * 60 * 60 * 1000, // 4 hours
|
|
2977
|
-
ADMIN_TOKEN_ROTATION_INTERVAL: 2 * 60 * 60 * 1000, // 2 hours
|
|
2978
|
-
|
|
2979
|
-
// Rate limiting
|
|
2980
|
-
MAX_REQUESTS_PER_MINUTE: 100,
|
|
2981
|
-
MAX_CROSS_SITE_AUTH_PER_HOUR: 50,
|
|
2982
|
-
|
|
2983
|
-
// Session management
|
|
2984
|
-
SESSION_TIMEOUT: 30 * 60 * 1000, // 30 minutes
|
|
2985
|
-
MAX_CONCURRENT_SESSIONS: 5,
|
|
2986
|
-
|
|
2987
|
-
// Network security
|
|
2988
|
-
ALLOWED_ORIGINS: process.env.ALLOWED_ORIGINS?.split(',') || [],
|
|
2989
|
-
REQUIRE_HTTPS: process.env.NODE_ENV === 'production',
|
|
2990
|
-
};
|
|
2991
|
-
|
|
2992
|
-
// 🔑 Secure token management
|
|
2993
|
-
static createSecureAPIClient(config: {
|
|
2994
|
-
siteId: string;
|
|
2995
|
-
tokenProvider: () => Promise<string>;
|
|
2996
|
-
onTokenRefresh?: (newToken: string) => void;
|
|
2997
|
-
securityLogger?: (event: string, details: any) => void;
|
|
2998
|
-
}): AugurAPI {
|
|
2999
|
-
|
|
3000
|
-
let currentToken: string | null = null;
|
|
3001
|
-
let lastTokenRefresh = 0;
|
|
3002
|
-
|
|
3003
|
-
return new AugurAPI({
|
|
3004
|
-
siteId: config.siteId,
|
|
3005
|
-
|
|
3006
|
-
// Dynamic token provider with automatic rotation
|
|
3007
|
-
get bearerToken() {
|
|
3008
|
-
return currentToken;
|
|
3009
|
-
},
|
|
3010
|
-
|
|
3011
|
-
// Request interceptor for security
|
|
3012
|
-
onRequest: async (requestConfig) => {
|
|
3013
|
-
const now = Date.now();
|
|
3014
|
-
|
|
3015
|
-
// Auto-refresh token if needed
|
|
3016
|
-
if (!currentToken || (now - lastTokenRefresh) > SecureConfigManager.SECURITY_CONFIG.TOKEN_ROTATION_INTERVAL) {
|
|
3017
|
-
try {
|
|
3018
|
-
currentToken = await config.tokenProvider();
|
|
3019
|
-
lastTokenRefresh = now;
|
|
3020
|
-
config.onTokenRefresh?.(currentToken);
|
|
3021
|
-
|
|
3022
|
-
config.securityLogger?.('token_refreshed', {
|
|
3023
|
-
siteId: config.siteId,
|
|
3024
|
-
timestamp: new Date().toISOString()
|
|
3025
|
-
});
|
|
3026
|
-
} catch (error) {
|
|
3027
|
-
config.securityLogger?.('token_refresh_failed', {
|
|
3028
|
-
siteId: config.siteId,
|
|
3029
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
3030
|
-
});
|
|
3031
|
-
throw new Error('Token refresh failed');
|
|
3032
|
-
}
|
|
3033
|
-
}
|
|
3034
|
-
|
|
3035
|
-
// Add security headers
|
|
3036
|
-
requestConfig.headers = {
|
|
3037
|
-
...requestConfig.headers,
|
|
3038
|
-
'X-Request-ID': crypto.randomUUID(),
|
|
3039
|
-
'X-Timestamp': new Date().toISOString(),
|
|
3040
|
-
'User-Agent': `AugurAPI-Client/1.0 (Enterprise; ${process.env.NODE_ENV || 'development'})`
|
|
3041
|
-
};
|
|
3042
|
-
|
|
3043
|
-
// Log security events
|
|
3044
|
-
config.securityLogger?.('api_request', {
|
|
3045
|
-
siteId: config.siteId,
|
|
3046
|
-
url: requestConfig.url,
|
|
3047
|
-
method: requestConfig.method,
|
|
3048
|
-
requestId: requestConfig.headers['X-Request-ID']
|
|
3049
|
-
});
|
|
3050
|
-
|
|
3051
|
-
return requestConfig;
|
|
3052
|
-
},
|
|
3053
|
-
|
|
3054
|
-
// Response interceptor for security monitoring
|
|
3055
|
-
onResponse: (response) => {
|
|
3056
|
-
config.securityLogger?.('api_response', {
|
|
3057
|
-
siteId: config.siteId,
|
|
3058
|
-
status: response.status,
|
|
3059
|
-
requestId: response.config.headers?.['X-Request-ID'],
|
|
3060
|
-
responseTime: Date.now() - (response.config as any)?.startTime
|
|
3061
|
-
});
|
|
3062
|
-
|
|
3063
|
-
return response;
|
|
3064
|
-
},
|
|
3065
|
-
|
|
3066
|
-
// Error interceptor for security logging
|
|
3067
|
-
onError: (error) => {
|
|
3068
|
-
config.securityLogger?.('api_error', {
|
|
3069
|
-
siteId: config.siteId,
|
|
3070
|
-
error: error.message,
|
|
3071
|
-
status: error.response?.status,
|
|
3072
|
-
requestId: error.config?.headers?.['X-Request-ID']
|
|
3073
|
-
});
|
|
3074
|
-
|
|
3075
|
-
// Don't expose sensitive errors in production
|
|
3076
|
-
if (process.env.NODE_ENV === 'production') {
|
|
3077
|
-
throw new Error('API request failed');
|
|
3078
|
-
}
|
|
3079
|
-
|
|
3080
|
-
throw error;
|
|
3081
|
-
}
|
|
3082
|
-
});
|
|
3083
|
-
}
|
|
3084
|
-
|
|
3085
|
-
// 🔐 Cross-site authentication with security controls
|
|
3086
|
-
static createSecureCrossSiteAuthenticator(config: {
|
|
3087
|
-
adminTokenProvider: () => Promise<string>;
|
|
3088
|
-
auditLogger: (event: string, details: any) => void;
|
|
3089
|
-
rateLimiter?: (key: string) => Promise<boolean>;
|
|
3090
|
-
}) {
|
|
3091
|
-
return async (
|
|
3092
|
-
targetSiteId: string,
|
|
3093
|
-
username: string,
|
|
3094
|
-
password: string
|
|
3095
|
-
): Promise<CrossSiteAuthResult> => {
|
|
3096
|
-
const startTime = Date.now();
|
|
3097
|
-
const requestId = crypto.randomUUID();
|
|
3098
|
-
|
|
3099
|
-
try {
|
|
3100
|
-
// Rate limiting check
|
|
3101
|
-
if (config.rateLimiter) {
|
|
3102
|
-
const rateLimitKey = `cross_site_auth:${username}:${targetSiteId}`;
|
|
3103
|
-
const allowed = await config.rateLimiter(rateLimitKey);
|
|
3104
|
-
if (!allowed) {
|
|
3105
|
-
config.auditLogger('cross_site_auth_rate_limited', {
|
|
3106
|
-
username,
|
|
3107
|
-
targetSiteId,
|
|
3108
|
-
requestId,
|
|
3109
|
-
timestamp: new Date().toISOString()
|
|
3110
|
-
});
|
|
3111
|
-
return { success: false, error: 'Rate limit exceeded' };
|
|
3112
|
-
}
|
|
3113
|
-
}
|
|
3114
|
-
|
|
3115
|
-
// Get fresh admin token
|
|
3116
|
-
const adminToken = await config.adminTokenProvider();
|
|
3117
|
-
|
|
3118
|
-
// Perform authentication with audit logging
|
|
3119
|
-
config.auditLogger('cross_site_auth_attempt', {
|
|
3120
|
-
username,
|
|
3121
|
-
targetSiteId,
|
|
3122
|
-
requestId,
|
|
3123
|
-
timestamp: new Date().toISOString()
|
|
3124
|
-
});
|
|
3125
|
-
|
|
3126
|
-
const result = await authenticateUserForSite({
|
|
3127
|
-
targetSiteId,
|
|
3128
|
-
username,
|
|
3129
|
-
password,
|
|
3130
|
-
augurInfoToken: adminToken
|
|
3131
|
-
});
|
|
3132
|
-
|
|
3133
|
-
// Log result
|
|
3134
|
-
config.auditLogger('cross_site_auth_result', {
|
|
3135
|
-
username,
|
|
3136
|
-
targetSiteId,
|
|
3137
|
-
requestId,
|
|
3138
|
-
success: result.success,
|
|
3139
|
-
error: result.error,
|
|
3140
|
-
duration: Date.now() - startTime,
|
|
3141
|
-
timestamp: new Date().toISOString()
|
|
3142
|
-
});
|
|
3143
|
-
|
|
3144
|
-
return result;
|
|
3145
|
-
|
|
3146
|
-
} catch (error) {
|
|
3147
|
-
config.auditLogger('cross_site_auth_error', {
|
|
3148
|
-
username,
|
|
3149
|
-
targetSiteId,
|
|
3150
|
-
requestId,
|
|
3151
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
3152
|
-
duration: Date.now() - startTime,
|
|
3153
|
-
timestamp: new Date().toISOString()
|
|
3154
|
-
});
|
|
3155
|
-
|
|
3156
|
-
return {
|
|
3157
|
-
success: false,
|
|
3158
|
-
error: 'Authentication service unavailable'
|
|
3159
|
-
};
|
|
3160
|
-
}
|
|
3161
|
-
};
|
|
3162
|
-
}
|
|
3163
|
-
}
|
|
3164
|
-
|
|
3165
|
-
// 📊 Security monitoring and alerting
|
|
3166
|
-
class SecurityMonitor {
|
|
3167
|
-
private suspiciousActivity = new Map<string, number>();
|
|
3168
|
-
private readonly MAX_FAILED_ATTEMPTS = 5;
|
|
3169
|
-
private readonly MONITORING_WINDOW = 60 * 60 * 1000; // 1 hour
|
|
3170
|
-
|
|
3171
|
-
logSecurityEvent(event: string, details: any): void {
|
|
3172
|
-
const timestamp = new Date().toISOString();
|
|
3173
|
-
const logEntry = {
|
|
3174
|
-
timestamp,
|
|
3175
|
-
event,
|
|
3176
|
-
...details,
|
|
3177
|
-
severity: this.getEventSeverity(event)
|
|
3178
|
-
};
|
|
3179
|
-
|
|
3180
|
-
// Log to security system (console for example)
|
|
3181
|
-
console.log('🔒 SECURITY EVENT:', JSON.stringify(logEntry));
|
|
3182
|
-
|
|
3183
|
-
// Check for suspicious patterns
|
|
3184
|
-
this.detectSuspiciousActivity(event, details);
|
|
3185
|
-
|
|
3186
|
-
// Alert on high-severity events
|
|
3187
|
-
if (logEntry.severity === 'HIGH') {
|
|
3188
|
-
this.triggerSecurityAlert(logEntry);
|
|
3189
|
-
}
|
|
3190
|
-
}
|
|
3191
|
-
|
|
3192
|
-
private getEventSeverity(event: string): 'LOW' | 'MEDIUM' | 'HIGH' {
|
|
3193
|
-
const highSeverityEvents = [
|
|
3194
|
-
'cross_site_auth_rate_limited',
|
|
3195
|
-
'token_refresh_failed',
|
|
3196
|
-
'multiple_failed_attempts'
|
|
3197
|
-
];
|
|
3198
|
-
|
|
3199
|
-
const mediumSeverityEvents = [
|
|
3200
|
-
'cross_site_auth_result',
|
|
3201
|
-
'api_error'
|
|
3202
|
-
];
|
|
3203
|
-
|
|
3204
|
-
if (highSeverityEvents.includes(event)) return 'HIGH';
|
|
3205
|
-
if (mediumSeverityEvents.includes(event)) return 'MEDIUM';
|
|
3206
|
-
return 'LOW';
|
|
3207
|
-
}
|
|
3208
|
-
|
|
3209
|
-
private detectSuspiciousActivity(event: string, details: any): void {
|
|
3210
|
-
if (event === 'cross_site_auth_result' && !details.success) {
|
|
3211
|
-
const key = `failed_auth:${details.username}:${details.targetSiteId}`;
|
|
3212
|
-
const count = (this.suspiciousActivity.get(key) || 0) + 1;
|
|
3213
|
-
this.suspiciousActivity.set(key, count);
|
|
3214
|
-
|
|
3215
|
-
if (count >= this.MAX_FAILED_ATTEMPTS) {
|
|
3216
|
-
this.logSecurityEvent('multiple_failed_attempts', {
|
|
3217
|
-
username: details.username,
|
|
3218
|
-
targetSiteId: details.targetSiteId,
|
|
3219
|
-
attemptCount: count,
|
|
3220
|
-
windowStart: new Date(Date.now() - this.MONITORING_WINDOW).toISOString()
|
|
3221
|
-
});
|
|
3222
|
-
}
|
|
3223
|
-
}
|
|
3224
|
-
}
|
|
3225
|
-
|
|
3226
|
-
private triggerSecurityAlert(logEntry: any): void {
|
|
3227
|
-
// Implement your alerting system here
|
|
3228
|
-
console.warn('🚨 SECURITY ALERT:', logEntry);
|
|
3229
|
-
|
|
3230
|
-
// Example integrations:
|
|
3231
|
-
// - Send to SIEM system
|
|
3232
|
-
// - Slack/Teams notification
|
|
3233
|
-
// - Email security team
|
|
3234
|
-
// - Trigger automated response
|
|
3235
|
-
}
|
|
3236
|
-
}
|
|
3237
|
-
|
|
3238
|
-
// 🎮 USAGE EXAMPLE
|
|
3239
|
-
const securityMonitor = new SecurityMonitor();
|
|
3240
|
-
|
|
3241
|
-
// Create secure API client with monitoring
|
|
3242
|
-
const secureAPI = SecureConfigManager.createSecureAPIClient({
|
|
3243
|
-
siteId: 'production-site',
|
|
3244
|
-
tokenProvider: async () => {
|
|
3245
|
-
// Your secure token provider implementation
|
|
3246
|
-
return await getTokenFromSecureVault();
|
|
3247
|
-
},
|
|
3248
|
-
onTokenRefresh: (newToken) => {
|
|
3249
|
-
// Store token securely
|
|
3250
|
-
storeTokenInSecureVault(newToken);
|
|
3251
|
-
},
|
|
3252
|
-
securityLogger: (event, details) => {
|
|
3253
|
-
securityMonitor.logSecurityEvent(event, details);
|
|
3254
|
-
}
|
|
3255
|
-
});
|
|
3256
|
-
|
|
3257
|
-
// Create secure cross-site authenticator
|
|
3258
|
-
const secureCrossSiteAuth = SecureConfigManager.createSecureCrossSiteAuthenticator({
|
|
3259
|
-
adminTokenProvider: async () => await getAdminTokenFromVault(),
|
|
3260
|
-
auditLogger: (event, details) => securityMonitor.logSecurityEvent(event, details),
|
|
3261
|
-
rateLimiter: async (key) => {
|
|
3262
|
-
// Implement rate limiting logic
|
|
3263
|
-
return await checkRateLimit(key);
|
|
3264
|
-
}
|
|
3265
|
-
});
|
|
3266
|
-
```
|
|
3267
|
-
|
|
3268
|
-
### Production Deployment Guidelines
|
|
3269
|
-
|
|
3270
|
-
**Deploy with confidence** using enterprise-grade deployment practices:
|
|
3271
|
-
|
|
3272
|
-
```typescript
|
|
3273
|
-
/**
|
|
3274
|
-
* 🚀 PRODUCTION DEPLOYMENT CHECKLIST
|
|
3275
|
-
*
|
|
3276
|
-
* Complete guide for deploying Augur API clients in enterprise
|
|
3277
|
-
* production environments with monitoring and reliability.
|
|
3278
|
-
*/
|
|
3279
|
-
|
|
3280
|
-
// 🏗️ Production Configuration Template
|
|
3281
|
-
class ProductionConfig {
|
|
3282
|
-
static readonly ENVIRONMENT_CONFIG = {
|
|
3283
|
-
development: {
|
|
3284
|
-
logLevel: 'debug',
|
|
3285
|
-
requestTimeout: 30000,
|
|
3286
|
-
retryAttempts: 2,
|
|
3287
|
-
enableDetailedErrors: true,
|
|
3288
|
-
cacheEnabled: false
|
|
3289
|
-
},
|
|
3290
|
-
staging: {
|
|
3291
|
-
logLevel: 'info',
|
|
3292
|
-
requestTimeout: 15000,
|
|
3293
|
-
retryAttempts: 3,
|
|
3294
|
-
enableDetailedErrors: true,
|
|
3295
|
-
cacheEnabled: true
|
|
3296
|
-
},
|
|
3297
|
-
production: {
|
|
3298
|
-
logLevel: 'warn',
|
|
3299
|
-
requestTimeout: 10000,
|
|
3300
|
-
retryAttempts: 5,
|
|
3301
|
-
enableDetailedErrors: false,
|
|
3302
|
-
cacheEnabled: true
|
|
3303
|
-
}
|
|
3304
|
-
};
|
|
3305
|
-
|
|
3306
|
-
static createProductionAPI(environment: 'development' | 'staging' | 'production'): AugurAPI {
|
|
3307
|
-
const config = ProductionConfig.ENVIRONMENT_CONFIG[environment];
|
|
3308
|
-
|
|
3309
|
-
return new AugurAPI({
|
|
3310
|
-
siteId: process.env.AUGUR_SITE_ID!,
|
|
3311
|
-
bearerToken: process.env.AUGUR_JWT_TOKEN!,
|
|
3312
|
-
|
|
3313
|
-
// Production timeouts and retries
|
|
3314
|
-
timeout: config.requestTimeout,
|
|
3315
|
-
retries: config.retryAttempts,
|
|
3316
|
-
|
|
3317
|
-
// Environment-specific request handling
|
|
3318
|
-
onRequest: (requestConfig) => {
|
|
3319
|
-
// Add request ID for tracing
|
|
3320
|
-
requestConfig.headers = {
|
|
3321
|
-
...requestConfig.headers,
|
|
3322
|
-
'X-Environment': environment,
|
|
3323
|
-
'X-Request-ID': crypto.randomUUID(),
|
|
3324
|
-
'X-Deployment-Version': process.env.DEPLOYMENT_VERSION || 'unknown'
|
|
3325
|
-
};
|
|
3326
|
-
|
|
3327
|
-
if (config.logLevel === 'debug') {
|
|
3328
|
-
console.log(`🔍 API Request: ${requestConfig.method?.toUpperCase()} ${requestConfig.url}`);
|
|
3329
|
-
}
|
|
3330
|
-
|
|
3331
|
-
return requestConfig;
|
|
3332
|
-
},
|
|
3333
|
-
|
|
3334
|
-
onResponse: (response) => {
|
|
3335
|
-
if (config.logLevel === 'debug') {
|
|
3336
|
-
console.log(`✅ API Response: ${response.status} for ${response.config.url}`);
|
|
3337
|
-
}
|
|
3338
|
-
return response;
|
|
3339
|
-
},
|
|
3340
|
-
|
|
3341
|
-
onError: (error) => {
|
|
3342
|
-
// Production error handling
|
|
3343
|
-
const sanitizedError = config.enableDetailedErrors
|
|
3344
|
-
? error
|
|
3345
|
-
: new Error('API request failed - check logs for details');
|
|
3346
|
-
|
|
3347
|
-
// Log error details for debugging (always log internally)
|
|
3348
|
-
console.error('❌ API Error:', {
|
|
3349
|
-
url: error.config?.url,
|
|
3350
|
-
method: error.config?.method,
|
|
3351
|
-
status: error.response?.status,
|
|
3352
|
-
message: error.message,
|
|
3353
|
-
requestId: error.config?.headers?.['X-Request-ID'],
|
|
3354
|
-
environment
|
|
3355
|
-
});
|
|
3356
|
-
|
|
3357
|
-
throw sanitizedError;
|
|
3358
|
-
}
|
|
3359
|
-
});
|
|
3360
|
-
}
|
|
3361
|
-
}
|
|
3362
|
-
|
|
3363
|
-
// 📊 Health Check & Monitoring System
|
|
3364
|
-
class ProductionHealthMonitor {
|
|
3365
|
-
private healthCheckInterval: NodeJS.Timer | null = null;
|
|
3366
|
-
private lastHealthCheck: Record<string, any> = {};
|
|
3367
|
-
|
|
3368
|
-
async initializeHealthChecks(apis: Map<string, AugurAPI>): Promise<void> {
|
|
3369
|
-
console.log('🏥 Initializing health monitoring...');
|
|
3370
|
-
|
|
3371
|
-
// Initial health check
|
|
3372
|
-
await this.performHealthChecks(apis);
|
|
3373
|
-
|
|
3374
|
-
// Periodic health checks (every 5 minutes)
|
|
3375
|
-
this.healthCheckInterval = setInterval(async () => {
|
|
3376
|
-
await this.performHealthChecks(apis);
|
|
3377
|
-
}, 5 * 60 * 1000);
|
|
3378
|
-
|
|
3379
|
-
console.log('✅ Health monitoring initialized');
|
|
3380
|
-
}
|
|
3381
|
-
|
|
3382
|
-
private async performHealthChecks(apis: Map<string, AugurAPI>): Promise<void> {
|
|
3383
|
-
const timestamp = new Date().toISOString();
|
|
3384
|
-
const healthResults: Record<string, any> = {};
|
|
3385
|
-
|
|
3386
|
-
for (const [siteId, api] of apis.entries()) {
|
|
3387
|
-
try {
|
|
3388
|
-
const startTime = Date.now();
|
|
3389
|
-
|
|
3390
|
-
// Test core services
|
|
3391
|
-
const [joomlaHealth, pricingHealth, vmiHealth] = await Promise.allSettled([
|
|
3392
|
-
api.joomla.getHealthCheck(),
|
|
3393
|
-
api.pricing.getHealthCheck(),
|
|
3394
|
-
api.vmi.health.ping()
|
|
3395
|
-
]);
|
|
3396
|
-
|
|
3397
|
-
const responseTime = Date.now() - startTime;
|
|
3398
|
-
|
|
3399
|
-
healthResults[siteId] = {
|
|
3400
|
-
status: 'healthy',
|
|
3401
|
-
responseTime,
|
|
3402
|
-
services: {
|
|
3403
|
-
joomla: joomlaHealth.status === 'fulfilled' ? 'healthy' : 'unhealthy',
|
|
3404
|
-
pricing: pricingHealth.status === 'fulfilled' ? 'healthy' : 'unhealthy',
|
|
3405
|
-
vmi: vmiHealth.status === 'fulfilled' ? 'healthy' : 'unhealthy'
|
|
3406
|
-
},
|
|
3407
|
-
timestamp
|
|
3408
|
-
};
|
|
3409
|
-
|
|
3410
|
-
console.log(`✅ Health check passed for ${siteId} (${responseTime}ms)`);
|
|
3411
|
-
|
|
3412
|
-
} catch (error) {
|
|
3413
|
-
healthResults[siteId] = {
|
|
3414
|
-
status: 'unhealthy',
|
|
3415
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
3416
|
-
timestamp
|
|
3417
|
-
};
|
|
3418
|
-
|
|
3419
|
-
console.error(`❌ Health check failed for ${siteId}:`, error);
|
|
3420
|
-
|
|
3421
|
-
// Trigger alert for unhealthy sites
|
|
3422
|
-
await this.alertUnhealthySite(siteId, error);
|
|
3423
|
-
}
|
|
3424
|
-
}
|
|
3425
|
-
|
|
3426
|
-
this.lastHealthCheck = healthResults;
|
|
3427
|
-
}
|
|
3428
|
-
|
|
3429
|
-
private async alertUnhealthySite(siteId: string, error: any): Promise<void> {
|
|
3430
|
-
// Implement your alerting system
|
|
3431
|
-
console.warn(`🚨 HEALTH ALERT: Site ${siteId} is unhealthy`, error);
|
|
3432
|
-
|
|
3433
|
-
// Example integrations:
|
|
3434
|
-
// - PagerDuty incident
|
|
3435
|
-
// - Slack notification
|
|
3436
|
-
// - Email alert
|
|
3437
|
-
// - Automated failover
|
|
3438
|
-
}
|
|
3439
|
-
|
|
3440
|
-
getHealthStatus(): Record<string, any> {
|
|
3441
|
-
return this.lastHealthCheck;
|
|
3442
|
-
}
|
|
3443
|
-
|
|
3444
|
-
destroy(): void {
|
|
3445
|
-
if (this.healthCheckInterval) {
|
|
3446
|
-
clearInterval(this.healthCheckInterval);
|
|
3447
|
-
this.healthCheckInterval = null;
|
|
3448
|
-
}
|
|
3449
|
-
}
|
|
3450
|
-
}
|
|
3451
|
-
|
|
3452
|
-
// 🔄 Graceful Shutdown Manager
|
|
3453
|
-
class GracefulShutdownManager {
|
|
3454
|
-
private isShuttingDown = false;
|
|
3455
|
-
private activeRequests = new Set<Promise<any>>();
|
|
3456
|
-
|
|
3457
|
-
initialize(): void {
|
|
3458
|
-
// Handle shutdown signals
|
|
3459
|
-
process.on('SIGTERM', () => this.handleShutdown('SIGTERM'));
|
|
3460
|
-
process.on('SIGINT', () => this.handleShutdown('SIGINT'));
|
|
3461
|
-
process.on('SIGHUP', () => this.handleShutdown('SIGHUP'));
|
|
3462
|
-
|
|
3463
|
-
console.log('🛡️ Graceful shutdown handler initialized');
|
|
3464
|
-
}
|
|
3465
|
-
|
|
3466
|
-
private async handleShutdown(signal: string): Promise<void> {
|
|
3467
|
-
if (this.isShuttingDown) return;
|
|
3468
|
-
|
|
3469
|
-
console.log(`🛑 Received ${signal}, starting graceful shutdown...`);
|
|
3470
|
-
this.isShuttingDown = true;
|
|
3471
|
-
|
|
3472
|
-
try {
|
|
3473
|
-
// Wait for active requests to complete (with timeout)
|
|
3474
|
-
const shutdownTimeout = 30000; // 30 seconds
|
|
3475
|
-
const shutdownPromise = Promise.all(this.activeRequests);
|
|
3476
|
-
|
|
3477
|
-
await Promise.race([
|
|
3478
|
-
shutdownPromise,
|
|
3479
|
-
new Promise(resolve => setTimeout(resolve, shutdownTimeout))
|
|
3480
|
-
]);
|
|
3481
|
-
|
|
3482
|
-
console.log('✅ Graceful shutdown completed');
|
|
3483
|
-
process.exit(0);
|
|
3484
|
-
|
|
3485
|
-
} catch (error) {
|
|
3486
|
-
console.error('❌ Error during shutdown:', error);
|
|
3487
|
-
process.exit(1);
|
|
3488
|
-
}
|
|
3489
|
-
}
|
|
3490
|
-
|
|
3491
|
-
trackRequest<T>(request: Promise<T>): Promise<T> {
|
|
3492
|
-
if (this.isShuttingDown) {
|
|
3493
|
-
throw new Error('Service is shutting down');
|
|
3494
|
-
}
|
|
3495
|
-
|
|
3496
|
-
this.activeRequests.add(request);
|
|
3497
|
-
|
|
3498
|
-
return request.finally(() => {
|
|
3499
|
-
this.activeRequests.delete(request);
|
|
3500
|
-
});
|
|
3501
|
-
}
|
|
3502
|
-
|
|
3503
|
-
isShutdown(): boolean {
|
|
3504
|
-
return this.isShuttingDown;
|
|
3505
|
-
}
|
|
3506
|
-
}
|
|
3507
|
-
|
|
3508
|
-
// 🎮 PRODUCTION DEPLOYMENT EXAMPLE
|
|
3509
|
-
async function deployProductionApplication() {
|
|
3510
|
-
console.log('🚀 Starting production application...');
|
|
3511
|
-
|
|
3512
|
-
// 1. Initialize graceful shutdown
|
|
3513
|
-
const shutdownManager = new GracefulShutdownManager();
|
|
3514
|
-
shutdownManager.initialize();
|
|
3515
|
-
|
|
3516
|
-
// 2. Create production API clients
|
|
3517
|
-
const environment = process.env.NODE_ENV as 'development' | 'staging' | 'production' || 'production';
|
|
3518
|
-
const apis = new Map<string, AugurAPI>();
|
|
3519
|
-
|
|
3520
|
-
// Multiple tenant sites
|
|
3521
|
-
const tenantSites = process.env.TENANT_SITES?.split(',') || ['main-site'];
|
|
3522
|
-
|
|
3523
|
-
for (const siteId of tenantSites) {
|
|
3524
|
-
const api = ProductionConfig.createProductionAPI(environment);
|
|
3525
|
-
apis.set(siteId, api);
|
|
3526
|
-
}
|
|
3527
|
-
|
|
3528
|
-
// 3. Initialize health monitoring
|
|
3529
|
-
const healthMonitor = new ProductionHealthMonitor();
|
|
3530
|
-
await healthMonitor.initializeHealthChecks(apis);
|
|
3531
|
-
|
|
3532
|
-
// 4. Start application logic
|
|
3533
|
-
console.log(`✅ Production application started with ${apis.size} tenant site(s)`);
|
|
3534
|
-
|
|
3535
|
-
// 5. Cleanup on shutdown
|
|
3536
|
-
process.on('exit', () => {
|
|
3537
|
-
healthMonitor.destroy();
|
|
3538
|
-
console.log('🧹 Cleanup completed');
|
|
3539
|
-
});
|
|
3540
|
-
|
|
3541
|
-
return { apis, healthMonitor, shutdownManager };
|
|
3542
|
-
}
|
|
3543
|
-
|
|
3544
|
-
// Environment Variables Checklist for Production:
|
|
3545
|
-
/*
|
|
3546
|
-
REQUIRED ENVIRONMENT VARIABLES:
|
|
3547
|
-
- AUGUR_SITE_ID: Primary site identifier
|
|
3548
|
-
- AUGUR_JWT_TOKEN: Authentication token
|
|
3549
|
-
- AUGUR_ADMIN_TOKEN: Admin token for cross-site operations
|
|
3550
|
-
- NODE_ENV: production|staging|development
|
|
3551
|
-
- TENANT_SITES: Comma-separated list of tenant site IDs
|
|
3552
|
-
- DEPLOYMENT_VERSION: Current deployment version
|
|
3553
|
-
- ALLOWED_ORIGINS: Comma-separated list of allowed origins
|
|
3554
|
-
|
|
3555
|
-
OPTIONAL ENVIRONMENT VARIABLES:
|
|
3556
|
-
- LOG_LEVEL: error|warn|info|debug
|
|
3557
|
-
- REQUEST_TIMEOUT: Request timeout in milliseconds
|
|
3558
|
-
- MAX_RETRIES: Maximum retry attempts
|
|
3559
|
-
- HEALTH_CHECK_INTERVAL: Health check interval in minutes
|
|
3560
|
-
*/
|
|
3561
|
-
```
|
|
3562
|
-
|
|
3563
|
-
**Production Deployment Checklist:**
|
|
3564
|
-
|
|
3565
|
-
- ✅ **Environment Variables**: All required variables set and verified
|
|
3566
|
-
- ✅ **Security Configuration**: Tokens secured, HTTPS enforced, rate limiting enabled
|
|
3567
|
-
- ✅ **Health Monitoring**: Health checks configured with alerting
|
|
3568
|
-
- ✅ **Error Handling**: Production error handling with proper logging
|
|
3569
|
-
- ✅ **Graceful Shutdown**: Proper cleanup on application termination
|
|
3570
|
-
- ✅ **Multi-Tenant Support**: Tenant isolation and cross-site authentication
|
|
3571
|
-
- ✅ **Performance Optimization**: Edge caching and batch operations configured
|
|
3572
|
-
- ✅ **Monitoring & Alerting**: Security events, API performance, and health status tracking
|
|
3573
|
-
|
|
3574
|
-
For detailed authentication patterns, see [Authentication Guide](./AUTHENTICATION.md).
|
|
3575
|
-
For performance optimization strategies, see [Performance Guide](./PERFORMANCE.md).
|
|
3576
|
-
|
|
3577
|
-
## Development
|
|
3578
|
-
|
|
3579
|
-
### Building from Source
|
|
3580
|
-
|
|
3581
|
-
```bash
|
|
3582
|
-
# Clone the repository
|
|
3583
|
-
git clone https://github.com/your-org/augur-api-client.git
|
|
3584
|
-
cd augur-api-client/packages/augur-api
|
|
3585
|
-
|
|
3586
|
-
# Install dependencies
|
|
3587
|
-
npm install
|
|
3588
|
-
|
|
3589
|
-
# Build the library
|
|
3590
|
-
npm run build
|
|
3591
|
-
|
|
3592
|
-
# Run tests
|
|
3593
|
-
npm test
|
|
3594
|
-
|
|
3595
|
-
# Run tests with coverage
|
|
3596
|
-
npm run test:coverage
|
|
3597
|
-
|
|
3598
|
-
# Run E2E tests (requires API credentials)
|
|
3599
|
-
npm run test:e2e
|
|
3600
|
-
|
|
3601
|
-
# Lint code
|
|
3602
|
-
npm run lint
|
|
3603
|
-
|
|
3604
|
-
# Type check
|
|
3605
|
-
npm run typecheck
|
|
3606
|
-
```
|
|
3607
|
-
|
|
3608
|
-
### Development Scripts
|
|
3609
|
-
|
|
3610
|
-
```bash
|
|
3611
|
-
# Development workflow
|
|
3612
|
-
npm run dev # Watch mode for development
|
|
3613
|
-
npm run test:watch # Watch mode for tests
|
|
3614
|
-
npm run build:watch # Watch mode for building
|
|
3615
|
-
|
|
3616
|
-
# Code quality
|
|
3617
|
-
npm run lint:fix # Auto-fix linting issues
|
|
3618
|
-
npm run format # Format code with Prettier
|
|
3619
|
-
npm run format:check # Check code formatting
|
|
3620
|
-
|
|
3621
|
-
# Release workflow
|
|
3622
|
-
npm run clean # Clean build artifacts
|
|
3623
|
-
npm run prepublish # Build and prepare for publishing
|
|
3624
|
-
```
|
|
3625
|
-
|
|
3626
|
-
### Testing
|
|
3627
|
-
|
|
3628
|
-
The library maintains 100% test coverage across all components:
|
|
3629
|
-
|
|
3630
|
-
```typescript
|
|
3631
|
-
// Example test
|
|
3632
|
-
import { AugurAPI, AuthenticationError } from '../src';
|
|
3633
|
-
|
|
3634
|
-
describe('AugurAPI', () => {
|
|
3635
|
-
let api: AugurAPI;
|
|
3636
|
-
|
|
3637
|
-
beforeEach(() => {
|
|
3638
|
-
api = new AugurAPI({
|
|
3639
|
-
siteId: 'test-site',
|
|
3640
|
-
bearerToken: 'test-token'
|
|
3641
|
-
});
|
|
3642
|
-
});
|
|
3643
|
-
|
|
3644
|
-
it('should create service clients lazily', () => {
|
|
3645
|
-
// Service clients are created on first access
|
|
3646
|
-
const joomla1 = api.joomla;
|
|
3647
|
-
const joomla2 = api.joomla;
|
|
3648
|
-
|
|
3649
|
-
expect(joomla1).toBe(joomla2); // Same instance
|
|
3650
|
-
});
|
|
3651
|
-
|
|
3652
|
-
it('should reset clients when auth token changes', () => {
|
|
3653
|
-
const joomla1 = api.joomla;
|
|
3654
|
-
|
|
3655
|
-
api.setAuthToken('new-token');
|
|
3656
|
-
|
|
3657
|
-
const joomla2 = api.joomla;
|
|
3658
|
-
expect(joomla1).not.toBe(joomla2); // Different instances
|
|
3659
|
-
});
|
|
3660
|
-
|
|
3661
|
-
it('should handle authentication errors', async () => {
|
|
3662
|
-
// Mock failed authentication
|
|
3663
|
-
mockAPI.joomla.users.list.mockRejectedValue(
|
|
3664
|
-
new AuthenticationError({
|
|
3665
|
-
message: 'Invalid token',
|
|
3666
|
-
service: 'joomla',
|
|
3667
|
-
endpoint: '/users'
|
|
3668
|
-
})
|
|
3669
|
-
);
|
|
3670
|
-
|
|
3671
|
-
await expect(api.joomla.users.list()).rejects.toThrow(AuthenticationError);
|
|
3672
|
-
});
|
|
3673
|
-
});
|
|
3674
|
-
```
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
### Code Generation
|
|
3678
|
-
|
|
3679
|
-
The library uses code generation from Postman collections:
|
|
3680
|
-
|
|
3681
|
-
```bash
|
|
3682
|
-
# Generate client code from Postman collections
|
|
3683
|
-
npm run generate:clients
|
|
3684
|
-
|
|
3685
|
-
# Update schemas from API responses
|
|
3686
|
-
npm run generate:schemas
|
|
3687
|
-
|
|
3688
|
-
# Generate TypeScript types
|
|
3689
|
-
npm run generate:types
|
|
3690
|
-
```
|
|
3691
|
-
|
|
3692
|
-
### Contributing Guidelines
|
|
3693
|
-
|
|
3694
|
-
1. **Follow TypeScript best practices**
|
|
3695
|
-
2. **Maintain 100% test coverage**
|
|
3696
|
-
3. **Add comprehensive JSDoc documentation**
|
|
3697
|
-
4. **Follow existing naming conventions**
|
|
3698
|
-
5. **Update documentation for new features**
|
|
3699
|
-
6. **Run all tests before submitting PRs**
|
|
3700
|
-
|
|
3701
|
-
```typescript
|
|
3702
|
-
// Example contribution - adding a new method
|
|
3703
|
-
/**
|
|
3704
|
-
* Get user profile with additional details
|
|
3705
|
-
* @description Retrieves comprehensive user profile including preferences and settings
|
|
3706
|
-
*
|
|
3707
|
-
* @param userId - The unique identifier for the user
|
|
3708
|
-
* @param options - Additional options for profile retrieval
|
|
3709
|
-
* @returns Promise resolving to user profile data
|
|
3710
|
-
* @throws AuthenticationError When user token is invalid
|
|
3711
|
-
* @throws NotFoundError When user does not exist
|
|
3712
|
-
*
|
|
3713
|
-
* @example
|
|
3714
|
-
* ```typescript
|
|
3715
|
-
* const profile = await api.joomla.users.getProfile('user-123', {
|
|
3716
|
-
* includePreferences: true,
|
|
3717
|
-
* edgeCache: 2
|
|
3718
|
-
* });
|
|
3719
|
-
*
|
|
3720
|
-
* console.log(profile.data.username);
|
|
3721
|
-
* console.log(profile.data.preferences);
|
|
3722
|
-
* ```
|
|
3723
|
-
*/
|
|
3724
|
-
async getProfile(userId: string, options?: ProfileOptions): Promise<UserProfileResponse> {
|
|
3725
|
-
const params = ProfileOptionsSchema.parse(options || {});
|
|
3726
|
-
const response = await this.http.get(`/user/${userId}/profile`, params);
|
|
3727
|
-
return UserProfileResponseSchema.parse(response);
|
|
3728
|
-
}
|
|
3729
|
-
```
|
|
3730
|
-
|
|
3731
|
-
## Contributing
|
|
3732
|
-
|
|
3733
|
-
We welcome contributions! Please see our [Contributing Guide](./CONTRIBUTING.md) for details.
|
|
3734
|
-
|
|
3735
|
-
### Quick Contributing Steps
|
|
3736
|
-
|
|
3737
|
-
1. Fork the repository
|
|
3738
|
-
2. Create a feature branch: `git checkout -b feature/amazing-feature`
|
|
3739
|
-
3. Make your changes with tests
|
|
3740
|
-
4. Ensure all tests pass: `npm test`
|
|
3741
|
-
5. Commit changes: `git commit -m 'Add amazing feature'`
|
|
3742
|
-
6. Push to branch: `git push origin feature/amazing-feature`
|
|
3743
|
-
7. Submit a Pull Request
|
|
3744
|
-
|
|
3745
|
-
### Development Setup
|
|
3746
|
-
|
|
3747
|
-
```bash
|
|
3748
|
-
# Clone your fork
|
|
3749
|
-
git clone https://github.com/your-username/augur-api-client.git
|
|
3750
|
-
cd augur-api-client/packages/augur-api
|
|
3751
|
-
|
|
3752
|
-
# Install dependencies
|
|
3753
|
-
npm install
|
|
3754
|
-
|
|
3755
|
-
# Set up development credentials
|
|
3756
|
-
cp .env.example .env
|
|
3757
|
-
# Edit .env with your API credentials
|
|
3758
|
-
|
|
3759
|
-
# Run tests to verify setup
|
|
3760
|
-
npm test
|
|
3761
|
-
```
|
|
72
|
+
See [SKILL.md](./SKILL.md) for guidance on using this package with AI assistance.
|
|
3762
73
|
|
|
3763
74
|
## License
|
|
3764
75
|
|
|
3765
|
-
MIT
|
|
3766
|
-
|
|
3767
|
-
## Support
|
|
3768
|
-
|
|
3769
|
-
- **Documentation**: [User Guide](https://www.notion.so/2324fc202fd181c5880fe659f3ad2c3f)
|
|
3770
|
-
- **Developer Docs**: [Developer Guide](https://www.notion.so/2324fc202fd181a58e77e8ca876a1c6f)
|
|
3771
|
-
- **Issues**: [GitHub Issues](https://github.com/your-org/augur-api-client/issues)
|
|
3772
|
-
- **Discord**: [Community Chat](https://discord.gg/augur-api)
|
|
3773
|
-
|
|
3774
|
-
---
|
|
3775
|
-
|
|
3776
|
-
**Built with ❤️ by the Augur team**
|
|
76
|
+
MIT
|