@amboras-dev/hive 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -0
- package/dist/chunk-BADYBNR7.mjs +61 -0
- package/dist/chunk-BADYBNR7.mjs.map +1 -0
- package/dist/client/index.d.mts +28 -0
- package/dist/client/index.d.ts +28 -0
- package/dist/client/index.js +86 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/index.mjs +47 -0
- package/dist/client/index.mjs.map +1 -0
- package/dist/index.d.mts +244 -0
- package/dist/index.d.ts +244 -0
- package/dist/index.js +95 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +23 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# @amboras-dev/hive
|
|
2
|
+
|
|
3
|
+
Hive 3PL fulfillment integration for Amboras — shared wire types and a storefront shipment-tracking hook.
|
|
4
|
+
|
|
5
|
+
## What lives where
|
|
6
|
+
|
|
7
|
+
Hive's API key is a bearer token that must stay server-side, and Hive rate-limits at **100 requests/minute per merchant**. So nothing in this package talks to `app.hive.app`. All Hive HTTP, HMAC webhook verification, and order routing live in `medusa-backend-orchestrator` under `/store/hive/*`; this package ships the typed surface around those routes.
|
|
8
|
+
|
|
9
|
+
| Entrypoint | Contents |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| `@amboras-dev/hive` | every wire type; no React |
|
|
12
|
+
| `@amboras-dev/hive/client` | `useHiveTracking` + shipment types |
|
|
13
|
+
|
|
14
|
+
The admin settings UI lives in the orchestrator admin app, not here — the same split meta-ads uses.
|
|
15
|
+
|
|
16
|
+
## Hive Merchant API v1
|
|
17
|
+
|
|
18
|
+
Base URLs — production `https://app.hive.app/merchant_api/v1`, staging `https://staging.app.hive.app/merchant_api/v1`. Auth is `Authorization: Bearer <api_key>`; the key is issued by the merchant's Hive account manager, not self-serve.
|
|
19
|
+
|
|
20
|
+
| Resource | Endpoints |
|
|
21
|
+
| --- | --- |
|
|
22
|
+
| Orders | `GET/POST /orders`, `GET/PATCH /orders/{id}`, `PUT /orders/{id}/cancel` |
|
|
23
|
+
| Shipments | `GET /shipments?order_id=` |
|
|
24
|
+
| Warehouses | `GET /warehouses` (list only) |
|
|
25
|
+
|
|
26
|
+
List responses are `{ data, pagination }` with `page` / `limit` (default 20, max 100). Errors are `{ success: false, errors: string[] }` — no machine-readable codes, so branch on the HTTP status.
|
|
27
|
+
|
|
28
|
+
## Webhooks
|
|
29
|
+
|
|
30
|
+
Four events: `delivery_status_updated`, `shipment_status_updated`, `restocking_shipment_status_updated`, `return_status_updated`. The destination URL is registered by the merchant's account manager — the settings form displays it read-only for them to hand over.
|
|
31
|
+
|
|
32
|
+
Two things the backend handler must get right:
|
|
33
|
+
|
|
34
|
+
- **Signature.** `x-hive-signature` is a hex HMAC-SHA256 of the raw body keyed by the API token. Verify with a constant-time compare and ignore any request without the header.
|
|
35
|
+
- **Ordering.** Hive guarantees neither ordering nor exactly-once delivery. Compare the payload's `updated_at` against the last stored value and drop anything older.
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
// Storefront
|
|
41
|
+
import { useHiveTracking } from '@amboras-dev/hive/client'
|
|
42
|
+
|
|
43
|
+
const { shipments, isPending, error } = useHiveTracking(order.id)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`useHiveTracking` accepts `baseUrl` / `publishableKey` overrides, falling back to `NEXT_PUBLIC_MEDUSA_BACKEND_URL` and `NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY`.
|
|
47
|
+
|
|
48
|
+
## Types
|
|
49
|
+
|
|
50
|
+
`src/types.ts` mirrors Hive's snake_case field names exactly so a backend route can pass a Hive payload straight through. It must stay byte-compatible with the DTOs in `medusa-backend-orchestrator`.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
var SECRET_SET_SENTINEL = "__SECRET_SET__";
|
|
3
|
+
var HIVE_BASE_URLS = {
|
|
4
|
+
production: "https://app.hive.app/merchant_api/v1",
|
|
5
|
+
staging: "https://staging.app.hive.app/merchant_api/v1"
|
|
6
|
+
};
|
|
7
|
+
var HIVE_RATE_LIMIT_PER_MINUTE = 100;
|
|
8
|
+
var HiveOrderStatus = /* @__PURE__ */ ((HiveOrderStatus2) => {
|
|
9
|
+
HiveOrderStatus2["Fulfillable"] = "fulfillable";
|
|
10
|
+
HiveOrderStatus2["Unfulfillable"] = "unfulfillable";
|
|
11
|
+
HiveOrderStatus2["Fulfilled"] = "fulfilled";
|
|
12
|
+
return HiveOrderStatus2;
|
|
13
|
+
})(HiveOrderStatus || {});
|
|
14
|
+
var HiveFinancialStatus = /* @__PURE__ */ ((HiveFinancialStatus2) => {
|
|
15
|
+
HiveFinancialStatus2["Paid"] = "paid";
|
|
16
|
+
HiveFinancialStatus2["Refunded"] = "refunded";
|
|
17
|
+
HiveFinancialStatus2["Pending"] = "pending";
|
|
18
|
+
HiveFinancialStatus2["Failed"] = "failed";
|
|
19
|
+
return HiveFinancialStatus2;
|
|
20
|
+
})(HiveFinancialStatus || {});
|
|
21
|
+
var HiveShipmentStatus = /* @__PURE__ */ ((HiveShipmentStatus2) => {
|
|
22
|
+
HiveShipmentStatus2["WaitingForPicking"] = "waiting_for_picking";
|
|
23
|
+
HiveShipmentStatus2["OnHold"] = "on_hold";
|
|
24
|
+
HiveShipmentStatus2["PickingAssigned"] = "picking_assigned";
|
|
25
|
+
HiveShipmentStatus2["InPicking"] = "in_picking";
|
|
26
|
+
HiveShipmentStatus2["Picked"] = "picked";
|
|
27
|
+
HiveShipmentStatus2["InPacking"] = "in_packing";
|
|
28
|
+
HiveShipmentStatus2["Packed"] = "packed";
|
|
29
|
+
HiveShipmentStatus2["InShipping"] = "in_shipping";
|
|
30
|
+
HiveShipmentStatus2["Shipped"] = "shipped";
|
|
31
|
+
HiveShipmentStatus2["Cancelled"] = "cancelled";
|
|
32
|
+
return HiveShipmentStatus2;
|
|
33
|
+
})(HiveShipmentStatus || {});
|
|
34
|
+
var HiveWebhookEvent = /* @__PURE__ */ ((HiveWebhookEvent2) => {
|
|
35
|
+
HiveWebhookEvent2["DeliveryStatusUpdated"] = "delivery_status_updated";
|
|
36
|
+
HiveWebhookEvent2["ShipmentStatusUpdated"] = "shipment_status_updated";
|
|
37
|
+
HiveWebhookEvent2["RestockingShipmentStatusUpdated"] = "restocking_shipment_status_updated";
|
|
38
|
+
HiveWebhookEvent2["ReturnStatusUpdated"] = "return_status_updated";
|
|
39
|
+
return HiveWebhookEvent2;
|
|
40
|
+
})(HiveWebhookEvent || {});
|
|
41
|
+
var HIVE_SIGNATURE_HEADER = "x-hive-signature";
|
|
42
|
+
var HiveConnectionError = /* @__PURE__ */ ((HiveConnectionError2) => {
|
|
43
|
+
HiveConnectionError2["MissingApiKey"] = "missing_api_key";
|
|
44
|
+
HiveConnectionError2["Unauthorized"] = "unauthorized";
|
|
45
|
+
HiveConnectionError2["RateLimited"] = "rate_limited";
|
|
46
|
+
HiveConnectionError2["Unreachable"] = "unreachable";
|
|
47
|
+
return HiveConnectionError2;
|
|
48
|
+
})(HiveConnectionError || {});
|
|
49
|
+
|
|
50
|
+
export {
|
|
51
|
+
SECRET_SET_SENTINEL,
|
|
52
|
+
HIVE_BASE_URLS,
|
|
53
|
+
HIVE_RATE_LIMIT_PER_MINUTE,
|
|
54
|
+
HiveOrderStatus,
|
|
55
|
+
HiveFinancialStatus,
|
|
56
|
+
HiveShipmentStatus,
|
|
57
|
+
HiveWebhookEvent,
|
|
58
|
+
HIVE_SIGNATURE_HEADER,
|
|
59
|
+
HiveConnectionError
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=chunk-BADYBNR7.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["/**\n * Public types for @amboras-dev/hive.\n *\n * Single source of truth for the wire shape between the Amboras admin /\n * storefront and the medusa-backend-orchestrator Store API routes under\n * `/store/hive/*`. The DTO files on the Medusa side must stay\n * byte-compatible with these.\n *\n * Field names mirror the Hive Merchant API v1\n * (https://developers.hive.app/reference/api-reference) exactly, including\n * its snake_case, so a backend route can pass a Hive payload straight\n * through without a rename layer.\n *\n * The Hive API key is a server-side secret and Hive enforces a\n * 100 req/min per-merchant rate limit, so nothing in this package ever\n * calls app.hive.app directly - every hook here talks to our own Medusa\n * routes, which own the Hive HTTP client.\n */\n\n/**\n * Sentinel returned in place of a stored secret when the settings form\n * reads back current config. Matches the pattern used by meta-ads,\n * pinterest and aliexpress-dropshipping so the admin never sees the\n * plaintext API key after write.\n */\nexport const SECRET_SET_SENTINEL = '__SECRET_SET__' as const\nexport type SecretSetSentinel = typeof SECRET_SET_SENTINEL\n\n/** Hive base URLs, keyed by the environment chosen in the settings form. */\nexport const HIVE_BASE_URLS = {\n production: 'https://app.hive.app/merchant_api/v1',\n staging: 'https://staging.app.hive.app/merchant_api/v1',\n} as const\n\nexport type HiveEnvironment = keyof typeof HIVE_BASE_URLS\n\n/** Hive allows 100 requests per minute per merchant. */\nexport const HIVE_RATE_LIMIT_PER_MINUTE = 100\n\n/* -------------------------------------------------------------------------\n * Envelope\n * ---------------------------------------------------------------------- */\n\n/**\n * Pagination block attached to every Hive list response.\n * Requests page through with `page` (default 1) and `limit`\n * (default 20, max 100).\n */\nexport interface HivePagination {\n current_page: number\n item_count: number\n page_count: number\n items_per_page: number\n}\n\n/** Shape of every Hive list endpoint: `{ data, pagination }`. */\nexport interface HiveListResponse<T> {\n data: T[]\n pagination: HivePagination\n}\n\n/**\n * Hive error body. Every failure carries `success: false` and an array of\n * human-readable messages; there are no machine-readable error codes, so\n * the HTTP status is the only thing worth branching on.\n */\nexport interface HiveErrorResponse {\n success: false\n errors: string[]\n}\n\n/* -------------------------------------------------------------------------\n * Warehouses\n * ---------------------------------------------------------------------- */\n\n/** `GET /warehouses` is list-only and every field is read-only. */\nexport interface HiveWarehouseDto {\n id: number\n name: string\n /** 2-letter ISO 3166-1 country code. */\n country: string\n city: string\n}\n\n/* -------------------------------------------------------------------------\n * Orders\n * ---------------------------------------------------------------------- */\n\n/** Whether Hive can pick the order with the stock it currently holds. */\nexport enum HiveOrderStatus {\n Fulfillable = 'fulfillable',\n Unfulfillable = 'unfulfillable',\n Fulfilled = 'fulfilled',\n}\n\nexport enum HiveFinancialStatus {\n Paid = 'paid',\n Refunded = 'refunded',\n Pending = 'pending',\n Failed = 'failed',\n}\n\nexport interface HiveAddressDto {\n first_name: string | null\n last_name: string | null\n company: string | null\n address_1: string\n address_2: string | null\n city: string\n province: string | null\n zip: string\n /** 2-letter ISO 3166-1 country code. */\n country_code: string\n phone: string | null\n email: string | null\n}\n\nexport interface HiveOrderItemDto {\n id: number\n merchant_item_id: string | null\n merchant_sku_id: string\n quantity: number\n}\n\n/** Body item for `POST /orders` - references a SKU the merchant already created. */\nexport interface HiveOrderItemInput {\n merchant_sku_id: string\n quantity: number\n merchant_item_id?: string\n}\n\nexport interface HiveOrderDto {\n id: number\n merchant_order_id: string\n status: HiveOrderStatus\n financial_status: HiveFinancialStatus | null\n shipping_address: HiveAddressDto\n billing_address: HiveAddressDto | null\n items: HiveOrderItemDto[]\n created_at: string\n updated_at: string\n}\n\n/** Body for `POST /orders`. */\nexport interface HiveOrderInput {\n merchant_order_id: string\n shipping_address: HiveAddressDto\n items: HiveOrderItemInput[]\n billing_address?: HiveAddressDto\n financial_status?: HiveFinancialStatus\n}\n\n/* -------------------------------------------------------------------------\n * Shipments\n * ---------------------------------------------------------------------- */\n\n/** Warehouse-side progress of a shipment. */\nexport enum HiveShipmentStatus {\n WaitingForPicking = 'waiting_for_picking',\n OnHold = 'on_hold',\n PickingAssigned = 'picking_assigned',\n InPicking = 'in_picking',\n Picked = 'picked',\n InPacking = 'in_packing',\n Packed = 'packed',\n InShipping = 'in_shipping',\n Shipped = 'shipped',\n Cancelled = 'cancelled',\n}\n\n/**\n * Carrier-side progress. Hive sends these as human-readable strings\n * rather than slugs, so they are typed as a literal union of the exact\n * values the API returns.\n */\nexport type HiveDeliveryStatus =\n | 'Information transmitted to the carrier'\n | 'In transit'\n | 'Out for delivery'\n | 'Delivered'\n | 'Returned to sender'\n | 'Action required'\n\nexport interface HiveShipmentItemSkuDto {\n id: number\n merchant_sku_id: string\n}\n\nexport interface HiveShipmentItemDto {\n id: number\n merchant_item_id: string | null\n quantity: number\n sku: HiveShipmentItemSkuDto\n}\n\nexport interface HiveShipmentDto {\n id: number\n order_id: number\n merchant_order_id: string\n status: HiveShipmentStatus\n delivery_status: HiveDeliveryStatus | null\n shipment_provider: string | null\n tracking_number: string | null\n tracking_url: string | null\n items: HiveShipmentItemDto[]\n shipped_at: string | null\n delivered_at: string | null\n created_at: string\n updated_at: string\n}\n\n/* -------------------------------------------------------------------------\n * Webhooks\n * ---------------------------------------------------------------------- */\n\n/**\n * The four events Hive can push. Registration is not self-serve - the\n * merchant's Hive account manager configures the destination URL.\n */\nexport enum HiveWebhookEvent {\n DeliveryStatusUpdated = 'delivery_status_updated',\n ShipmentStatusUpdated = 'shipment_status_updated',\n RestockingShipmentStatusUpdated = 'restocking_shipment_status_updated',\n ReturnStatusUpdated = 'return_status_updated',\n}\n\n/**\n * HTTP header carrying the hex-encoded HMAC-SHA256 digest of the raw\n * request body, keyed by the merchant's API token. Requests without it\n * must be ignored, and the comparison must be constant-time.\n */\nexport const HIVE_SIGNATURE_HEADER = 'x-hive-signature'\n\n/**\n * Hive does not guarantee ordering or exactly-once delivery, so a\n * consumer must compare the payload's `updated_at` against the last\n * value it stored and drop anything older.\n */\nexport interface HiveWebhookPayload<T = unknown> {\n event: HiveWebhookEvent\n data: T\n}\n\nexport type HiveShipmentWebhookPayload = HiveWebhookPayload<HiveShipmentDto>\n\n/* -------------------------------------------------------------------------\n * Plugin config + admin surface\n * ---------------------------------------------------------------------- */\n\n/**\n * Per-store Hive plugin configuration.\n *\n * - `apiKey` is issued by the merchant's Hive account manager. The admin\n * form receives `SECRET_SET_SENTINEL` on read and only sends a real\n * value when the merchant types a new one.\n * - `environment` selects between the production and staging domains.\n * - `defaultWarehouseId` is the warehouse orders route to when the\n * multi-3PL rules do not name one.\n * - `lastSuccessfulCallAt` is an ISO-8601 timestamp for the status card.\n */\nexport interface HivePluginConfig {\n enabled: boolean\n apiKey: string | SecretSetSentinel | null\n environment: HiveEnvironment\n defaultWarehouseId: number | null\n lastSuccessfulCallAt: string | null\n}\n\n/** Why the backend considers the stored credential unusable. */\nexport enum HiveConnectionError {\n MissingApiKey = 'missing_api_key',\n Unauthorized = 'unauthorized',\n RateLimited = 'rate_limited',\n Unreachable = 'unreachable',\n}\n\n/** `GET /store/hive/status`. */\nexport interface HiveConnectionStatusDto {\n connected: boolean\n environment: HiveEnvironment\n /** Populated from `GET /warehouses` on the last successful call. */\n warehouses: HiveWarehouseDto[]\n lastSuccessfulCallAt: string | null\n error: HiveConnectionError | null\n /**\n * Where the merchant's Hive account manager should point webhooks.\n * Rendered read-only in the settings form.\n */\n webhookUrl: string | null\n}\n\n/** `POST /store/hive/test-connection`. */\nexport type HiveTestConnectionResult =\n | { ok: true; warehouses: HiveWarehouseDto[] }\n | { ok: false; code: HiveConnectionError | 'UNKNOWN'; msg: string }\n"],"mappings":";AAyBO,IAAM,sBAAsB;AAI5B,IAAM,iBAAiB;AAAA,EAC5B,YAAY;AAAA,EACZ,SAAS;AACX;AAKO,IAAM,6BAA6B;AAoDnC,IAAK,kBAAL,kBAAKA,qBAAL;AACL,EAAAA,iBAAA,iBAAc;AACd,EAAAA,iBAAA,mBAAgB;AAChB,EAAAA,iBAAA,eAAY;AAHF,SAAAA;AAAA,GAAA;AAML,IAAK,sBAAL,kBAAKC,yBAAL;AACL,EAAAA,qBAAA,UAAO;AACP,EAAAA,qBAAA,cAAW;AACX,EAAAA,qBAAA,aAAU;AACV,EAAAA,qBAAA,YAAS;AAJC,SAAAA;AAAA,GAAA;AA8DL,IAAK,qBAAL,kBAAKC,wBAAL;AACL,EAAAA,oBAAA,uBAAoB;AACpB,EAAAA,oBAAA,YAAS;AACT,EAAAA,oBAAA,qBAAkB;AAClB,EAAAA,oBAAA,eAAY;AACZ,EAAAA,oBAAA,YAAS;AACT,EAAAA,oBAAA,eAAY;AACZ,EAAAA,oBAAA,YAAS;AACT,EAAAA,oBAAA,gBAAa;AACb,EAAAA,oBAAA,aAAU;AACV,EAAAA,oBAAA,eAAY;AAVF,SAAAA;AAAA,GAAA;AA8DL,IAAK,mBAAL,kBAAKC,sBAAL;AACL,EAAAA,kBAAA,2BAAwB;AACxB,EAAAA,kBAAA,2BAAwB;AACxB,EAAAA,kBAAA,qCAAkC;AAClC,EAAAA,kBAAA,yBAAsB;AAJZ,SAAAA;AAAA,GAAA;AAYL,IAAM,wBAAwB;AAsC9B,IAAK,sBAAL,kBAAKC,yBAAL;AACL,EAAAA,qBAAA,mBAAgB;AAChB,EAAAA,qBAAA,kBAAe;AACf,EAAAA,qBAAA,iBAAc;AACd,EAAAA,qBAAA,iBAAc;AAJJ,SAAAA;AAAA,GAAA;","names":["HiveOrderStatus","HiveFinancialStatus","HiveShipmentStatus","HiveWebhookEvent","HiveConnectionError"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { HiveShipmentDto } from '../index.mjs';
|
|
2
|
+
export { HiveDeliveryStatus, HiveShipmentItemDto, HiveShipmentStatus } from '../index.mjs';
|
|
3
|
+
|
|
4
|
+
interface UseHiveTrackingOptions {
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
publishableKey?: string;
|
|
7
|
+
/** Skip the initial fetch - useful while the order id is still loading. */
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
interface UseHiveTrackingResult {
|
|
11
|
+
shipments: HiveShipmentDto[];
|
|
12
|
+
isPending: boolean;
|
|
13
|
+
error: Error | null;
|
|
14
|
+
refetch: () => Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Reads the Hive shipments for one Medusa order.
|
|
18
|
+
*
|
|
19
|
+
* Hits our own `/store/hive/shipments` route rather than Hive directly:
|
|
20
|
+
* the API key is server-side only and Hive rate-limits at 100 req/min per
|
|
21
|
+
* merchant, so the backend owns the call and the caching.
|
|
22
|
+
*
|
|
23
|
+
* `orderId` is the Medusa order id; the backend maps it to Hive's
|
|
24
|
+
* `merchant_order_id`.
|
|
25
|
+
*/
|
|
26
|
+
declare function useHiveTracking(orderId: string, options?: UseHiveTrackingOptions): UseHiveTrackingResult;
|
|
27
|
+
|
|
28
|
+
export { HiveShipmentDto, type UseHiveTrackingOptions, type UseHiveTrackingResult, useHiveTracking };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { HiveShipmentDto } from '../index.js';
|
|
2
|
+
export { HiveDeliveryStatus, HiveShipmentItemDto, HiveShipmentStatus } from '../index.js';
|
|
3
|
+
|
|
4
|
+
interface UseHiveTrackingOptions {
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
publishableKey?: string;
|
|
7
|
+
/** Skip the initial fetch - useful while the order id is still loading. */
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
interface UseHiveTrackingResult {
|
|
11
|
+
shipments: HiveShipmentDto[];
|
|
12
|
+
isPending: boolean;
|
|
13
|
+
error: Error | null;
|
|
14
|
+
refetch: () => Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Reads the Hive shipments for one Medusa order.
|
|
18
|
+
*
|
|
19
|
+
* Hits our own `/store/hive/shipments` route rather than Hive directly:
|
|
20
|
+
* the API key is server-side only and Hive rate-limits at 100 req/min per
|
|
21
|
+
* merchant, so the backend owns the call and the caching.
|
|
22
|
+
*
|
|
23
|
+
* `orderId` is the Medusa order id; the backend maps it to Hive's
|
|
24
|
+
* `merchant_order_id`.
|
|
25
|
+
*/
|
|
26
|
+
declare function useHiveTracking(orderId: string, options?: UseHiveTrackingOptions): UseHiveTrackingResult;
|
|
27
|
+
|
|
28
|
+
export { HiveShipmentDto, type UseHiveTrackingOptions, type UseHiveTrackingResult, useHiveTracking };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/client/index.ts
|
|
21
|
+
var client_exports = {};
|
|
22
|
+
__export(client_exports, {
|
|
23
|
+
HiveShipmentStatus: () => HiveShipmentStatus,
|
|
24
|
+
useHiveTracking: () => useHiveTracking
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(client_exports);
|
|
27
|
+
|
|
28
|
+
// src/client/use-hive-tracking.ts
|
|
29
|
+
var import_react = require("react");
|
|
30
|
+
function useHiveTracking(orderId, options = {}) {
|
|
31
|
+
const { baseUrl, publishableKey, enabled = true } = options;
|
|
32
|
+
const [shipments, setShipments] = (0, import_react.useState)([]);
|
|
33
|
+
const [isPending, setIsPending] = (0, import_react.useState)(false);
|
|
34
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
35
|
+
const refetch = (0, import_react.useCallback)(async () => {
|
|
36
|
+
if (!orderId) return;
|
|
37
|
+
setIsPending(true);
|
|
38
|
+
setError(null);
|
|
39
|
+
try {
|
|
40
|
+
const resolvedBaseUrl = baseUrl ?? process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL ?? "";
|
|
41
|
+
const resolvedKey = publishableKey ?? process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY ?? "";
|
|
42
|
+
const url = `${resolvedBaseUrl.replace(/\/$/, "")}/store/hive/shipments?order_id=${encodeURIComponent(orderId)}`;
|
|
43
|
+
const response = await fetch(url, {
|
|
44
|
+
headers: {
|
|
45
|
+
"Content-Type": "application/json",
|
|
46
|
+
...resolvedKey ? { "x-publishable-api-key": resolvedKey } : {}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
if (!response.ok) {
|
|
50
|
+
throw new Error(`Hive shipment lookup failed: ${response.status}`);
|
|
51
|
+
}
|
|
52
|
+
const body = await response.json();
|
|
53
|
+
setShipments(body.shipments ?? []);
|
|
54
|
+
} catch (err) {
|
|
55
|
+
setError(err instanceof Error ? err : new Error("Hive shipment lookup failed"));
|
|
56
|
+
} finally {
|
|
57
|
+
setIsPending(false);
|
|
58
|
+
}
|
|
59
|
+
}, [orderId, baseUrl, publishableKey]);
|
|
60
|
+
(0, import_react.useEffect)(() => {
|
|
61
|
+
if (!enabled) return;
|
|
62
|
+
void refetch();
|
|
63
|
+
}, [enabled, refetch]);
|
|
64
|
+
return { shipments, isPending, error, refetch };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/types.ts
|
|
68
|
+
var HiveShipmentStatus = /* @__PURE__ */ ((HiveShipmentStatus2) => {
|
|
69
|
+
HiveShipmentStatus2["WaitingForPicking"] = "waiting_for_picking";
|
|
70
|
+
HiveShipmentStatus2["OnHold"] = "on_hold";
|
|
71
|
+
HiveShipmentStatus2["PickingAssigned"] = "picking_assigned";
|
|
72
|
+
HiveShipmentStatus2["InPicking"] = "in_picking";
|
|
73
|
+
HiveShipmentStatus2["Picked"] = "picked";
|
|
74
|
+
HiveShipmentStatus2["InPacking"] = "in_packing";
|
|
75
|
+
HiveShipmentStatus2["Packed"] = "packed";
|
|
76
|
+
HiveShipmentStatus2["InShipping"] = "in_shipping";
|
|
77
|
+
HiveShipmentStatus2["Shipped"] = "shipped";
|
|
78
|
+
HiveShipmentStatus2["Cancelled"] = "cancelled";
|
|
79
|
+
return HiveShipmentStatus2;
|
|
80
|
+
})(HiveShipmentStatus || {});
|
|
81
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
82
|
+
0 && (module.exports = {
|
|
83
|
+
HiveShipmentStatus,
|
|
84
|
+
useHiveTracking
|
|
85
|
+
});
|
|
86
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/client/index.ts","../../src/client/use-hive-tracking.ts","../../src/types.ts"],"sourcesContent":["export {\n useHiveTracking,\n type UseHiveTrackingOptions,\n type UseHiveTrackingResult,\n} from './use-hive-tracking'\nexport type {\n HiveShipmentDto,\n HiveShipmentItemDto,\n HiveDeliveryStatus,\n} from '../types'\nexport { HiveShipmentStatus } from '../types'\n","'use client'\n\nimport { useCallback, useEffect, useState } from 'react'\nimport type { HiveShipmentDto } from '../types'\n\nexport interface UseHiveTrackingOptions {\n baseUrl?: string\n publishableKey?: string\n /** Skip the initial fetch - useful while the order id is still loading. */\n enabled?: boolean\n}\n\nexport interface UseHiveTrackingResult {\n shipments: HiveShipmentDto[]\n isPending: boolean\n error: Error | null\n refetch: () => Promise<void>\n}\n\n/**\n * Reads the Hive shipments for one Medusa order.\n *\n * Hits our own `/store/hive/shipments` route rather than Hive directly:\n * the API key is server-side only and Hive rate-limits at 100 req/min per\n * merchant, so the backend owns the call and the caching.\n *\n * `orderId` is the Medusa order id; the backend maps it to Hive's\n * `merchant_order_id`.\n */\nexport function useHiveTracking(\n orderId: string,\n options: UseHiveTrackingOptions = {},\n): UseHiveTrackingResult {\n const { baseUrl, publishableKey, enabled = true } = options\n\n const [shipments, setShipments] = useState<HiveShipmentDto[]>([])\n const [isPending, setIsPending] = useState<boolean>(false)\n const [error, setError] = useState<Error | null>(null)\n\n const refetch = useCallback(async (): Promise<void> => {\n if (!orderId) return\n setIsPending(true)\n setError(null)\n try {\n const resolvedBaseUrl =\n baseUrl ?? process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL ?? ''\n const resolvedKey =\n publishableKey ?? process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY ?? ''\n const url = `${resolvedBaseUrl.replace(/\\/$/, '')}/store/hive/shipments?order_id=${encodeURIComponent(orderId)}`\n const response = await fetch(url, {\n headers: {\n 'Content-Type': 'application/json',\n ...(resolvedKey ? { 'x-publishable-api-key': resolvedKey } : {}),\n },\n })\n if (!response.ok) {\n throw new Error(`Hive shipment lookup failed: ${response.status}`)\n }\n const body = (await response.json()) as { shipments?: HiveShipmentDto[] }\n setShipments(body.shipments ?? [])\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Hive shipment lookup failed'))\n } finally {\n setIsPending(false)\n }\n }, [orderId, baseUrl, publishableKey])\n\n useEffect(() => {\n if (!enabled) return\n void refetch()\n }, [enabled, refetch])\n\n return { shipments, isPending, error, refetch }\n}\n","/**\n * Public types for @amboras-dev/hive.\n *\n * Single source of truth for the wire shape between the Amboras admin /\n * storefront and the medusa-backend-orchestrator Store API routes under\n * `/store/hive/*`. The DTO files on the Medusa side must stay\n * byte-compatible with these.\n *\n * Field names mirror the Hive Merchant API v1\n * (https://developers.hive.app/reference/api-reference) exactly, including\n * its snake_case, so a backend route can pass a Hive payload straight\n * through without a rename layer.\n *\n * The Hive API key is a server-side secret and Hive enforces a\n * 100 req/min per-merchant rate limit, so nothing in this package ever\n * calls app.hive.app directly - every hook here talks to our own Medusa\n * routes, which own the Hive HTTP client.\n */\n\n/**\n * Sentinel returned in place of a stored secret when the settings form\n * reads back current config. Matches the pattern used by meta-ads,\n * pinterest and aliexpress-dropshipping so the admin never sees the\n * plaintext API key after write.\n */\nexport const SECRET_SET_SENTINEL = '__SECRET_SET__' as const\nexport type SecretSetSentinel = typeof SECRET_SET_SENTINEL\n\n/** Hive base URLs, keyed by the environment chosen in the settings form. */\nexport const HIVE_BASE_URLS = {\n production: 'https://app.hive.app/merchant_api/v1',\n staging: 'https://staging.app.hive.app/merchant_api/v1',\n} as const\n\nexport type HiveEnvironment = keyof typeof HIVE_BASE_URLS\n\n/** Hive allows 100 requests per minute per merchant. */\nexport const HIVE_RATE_LIMIT_PER_MINUTE = 100\n\n/* -------------------------------------------------------------------------\n * Envelope\n * ---------------------------------------------------------------------- */\n\n/**\n * Pagination block attached to every Hive list response.\n * Requests page through with `page` (default 1) and `limit`\n * (default 20, max 100).\n */\nexport interface HivePagination {\n current_page: number\n item_count: number\n page_count: number\n items_per_page: number\n}\n\n/** Shape of every Hive list endpoint: `{ data, pagination }`. */\nexport interface HiveListResponse<T> {\n data: T[]\n pagination: HivePagination\n}\n\n/**\n * Hive error body. Every failure carries `success: false` and an array of\n * human-readable messages; there are no machine-readable error codes, so\n * the HTTP status is the only thing worth branching on.\n */\nexport interface HiveErrorResponse {\n success: false\n errors: string[]\n}\n\n/* -------------------------------------------------------------------------\n * Warehouses\n * ---------------------------------------------------------------------- */\n\n/** `GET /warehouses` is list-only and every field is read-only. */\nexport interface HiveWarehouseDto {\n id: number\n name: string\n /** 2-letter ISO 3166-1 country code. */\n country: string\n city: string\n}\n\n/* -------------------------------------------------------------------------\n * Orders\n * ---------------------------------------------------------------------- */\n\n/** Whether Hive can pick the order with the stock it currently holds. */\nexport enum HiveOrderStatus {\n Fulfillable = 'fulfillable',\n Unfulfillable = 'unfulfillable',\n Fulfilled = 'fulfilled',\n}\n\nexport enum HiveFinancialStatus {\n Paid = 'paid',\n Refunded = 'refunded',\n Pending = 'pending',\n Failed = 'failed',\n}\n\nexport interface HiveAddressDto {\n first_name: string | null\n last_name: string | null\n company: string | null\n address_1: string\n address_2: string | null\n city: string\n province: string | null\n zip: string\n /** 2-letter ISO 3166-1 country code. */\n country_code: string\n phone: string | null\n email: string | null\n}\n\nexport interface HiveOrderItemDto {\n id: number\n merchant_item_id: string | null\n merchant_sku_id: string\n quantity: number\n}\n\n/** Body item for `POST /orders` - references a SKU the merchant already created. */\nexport interface HiveOrderItemInput {\n merchant_sku_id: string\n quantity: number\n merchant_item_id?: string\n}\n\nexport interface HiveOrderDto {\n id: number\n merchant_order_id: string\n status: HiveOrderStatus\n financial_status: HiveFinancialStatus | null\n shipping_address: HiveAddressDto\n billing_address: HiveAddressDto | null\n items: HiveOrderItemDto[]\n created_at: string\n updated_at: string\n}\n\n/** Body for `POST /orders`. */\nexport interface HiveOrderInput {\n merchant_order_id: string\n shipping_address: HiveAddressDto\n items: HiveOrderItemInput[]\n billing_address?: HiveAddressDto\n financial_status?: HiveFinancialStatus\n}\n\n/* -------------------------------------------------------------------------\n * Shipments\n * ---------------------------------------------------------------------- */\n\n/** Warehouse-side progress of a shipment. */\nexport enum HiveShipmentStatus {\n WaitingForPicking = 'waiting_for_picking',\n OnHold = 'on_hold',\n PickingAssigned = 'picking_assigned',\n InPicking = 'in_picking',\n Picked = 'picked',\n InPacking = 'in_packing',\n Packed = 'packed',\n InShipping = 'in_shipping',\n Shipped = 'shipped',\n Cancelled = 'cancelled',\n}\n\n/**\n * Carrier-side progress. Hive sends these as human-readable strings\n * rather than slugs, so they are typed as a literal union of the exact\n * values the API returns.\n */\nexport type HiveDeliveryStatus =\n | 'Information transmitted to the carrier'\n | 'In transit'\n | 'Out for delivery'\n | 'Delivered'\n | 'Returned to sender'\n | 'Action required'\n\nexport interface HiveShipmentItemSkuDto {\n id: number\n merchant_sku_id: string\n}\n\nexport interface HiveShipmentItemDto {\n id: number\n merchant_item_id: string | null\n quantity: number\n sku: HiveShipmentItemSkuDto\n}\n\nexport interface HiveShipmentDto {\n id: number\n order_id: number\n merchant_order_id: string\n status: HiveShipmentStatus\n delivery_status: HiveDeliveryStatus | null\n shipment_provider: string | null\n tracking_number: string | null\n tracking_url: string | null\n items: HiveShipmentItemDto[]\n shipped_at: string | null\n delivered_at: string | null\n created_at: string\n updated_at: string\n}\n\n/* -------------------------------------------------------------------------\n * Webhooks\n * ---------------------------------------------------------------------- */\n\n/**\n * The four events Hive can push. Registration is not self-serve - the\n * merchant's Hive account manager configures the destination URL.\n */\nexport enum HiveWebhookEvent {\n DeliveryStatusUpdated = 'delivery_status_updated',\n ShipmentStatusUpdated = 'shipment_status_updated',\n RestockingShipmentStatusUpdated = 'restocking_shipment_status_updated',\n ReturnStatusUpdated = 'return_status_updated',\n}\n\n/**\n * HTTP header carrying the hex-encoded HMAC-SHA256 digest of the raw\n * request body, keyed by the merchant's API token. Requests without it\n * must be ignored, and the comparison must be constant-time.\n */\nexport const HIVE_SIGNATURE_HEADER = 'x-hive-signature'\n\n/**\n * Hive does not guarantee ordering or exactly-once delivery, so a\n * consumer must compare the payload's `updated_at` against the last\n * value it stored and drop anything older.\n */\nexport interface HiveWebhookPayload<T = unknown> {\n event: HiveWebhookEvent\n data: T\n}\n\nexport type HiveShipmentWebhookPayload = HiveWebhookPayload<HiveShipmentDto>\n\n/* -------------------------------------------------------------------------\n * Plugin config + admin surface\n * ---------------------------------------------------------------------- */\n\n/**\n * Per-store Hive plugin configuration.\n *\n * - `apiKey` is issued by the merchant's Hive account manager. The admin\n * form receives `SECRET_SET_SENTINEL` on read and only sends a real\n * value when the merchant types a new one.\n * - `environment` selects between the production and staging domains.\n * - `defaultWarehouseId` is the warehouse orders route to when the\n * multi-3PL rules do not name one.\n * - `lastSuccessfulCallAt` is an ISO-8601 timestamp for the status card.\n */\nexport interface HivePluginConfig {\n enabled: boolean\n apiKey: string | SecretSetSentinel | null\n environment: HiveEnvironment\n defaultWarehouseId: number | null\n lastSuccessfulCallAt: string | null\n}\n\n/** Why the backend considers the stored credential unusable. */\nexport enum HiveConnectionError {\n MissingApiKey = 'missing_api_key',\n Unauthorized = 'unauthorized',\n RateLimited = 'rate_limited',\n Unreachable = 'unreachable',\n}\n\n/** `GET /store/hive/status`. */\nexport interface HiveConnectionStatusDto {\n connected: boolean\n environment: HiveEnvironment\n /** Populated from `GET /warehouses` on the last successful call. */\n warehouses: HiveWarehouseDto[]\n lastSuccessfulCallAt: string | null\n error: HiveConnectionError | null\n /**\n * Where the merchant's Hive account manager should point webhooks.\n * Rendered read-only in the settings form.\n */\n webhookUrl: string | null\n}\n\n/** `POST /store/hive/test-connection`. */\nexport type HiveTestConnectionResult =\n | { ok: true; warehouses: HiveWarehouseDto[] }\n | { ok: false; code: HiveConnectionError | 'UNKNOWN'; msg: string }\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,mBAAiD;AA2B1C,SAAS,gBACd,SACA,UAAkC,CAAC,GACZ;AACvB,QAAM,EAAE,SAAS,gBAAgB,UAAU,KAAK,IAAI;AAEpD,QAAM,CAAC,WAAW,YAAY,QAAI,uBAA4B,CAAC,CAAC;AAChE,QAAM,CAAC,WAAW,YAAY,QAAI,uBAAkB,KAAK;AACzD,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAuB,IAAI;AAErD,QAAM,cAAU,0BAAY,YAA2B;AACrD,QAAI,CAAC,QAAS;AACd,iBAAa,IAAI;AACjB,aAAS,IAAI;AACb,QAAI;AACF,YAAM,kBACJ,WAAW,QAAQ,IAAI,kCAAkC;AAC3D,YAAM,cACJ,kBAAkB,QAAQ,IAAI,sCAAsC;AACtE,YAAM,MAAM,GAAG,gBAAgB,QAAQ,OAAO,EAAE,CAAC,kCAAkC,mBAAmB,OAAO,CAAC;AAC9G,YAAM,WAAW,MAAM,MAAM,KAAK;AAAA,QAChC,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,GAAI,cAAc,EAAE,yBAAyB,YAAY,IAAI,CAAC;AAAA,QAChE;AAAA,MACF,CAAC;AACD,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,gCAAgC,SAAS,MAAM,EAAE;AAAA,MACnE;AACA,YAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,mBAAa,KAAK,aAAa,CAAC,CAAC;AAAA,IACnC,SAAS,KAAK;AACZ,eAAS,eAAe,QAAQ,MAAM,IAAI,MAAM,6BAA6B,CAAC;AAAA,IAChF,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,SAAS,SAAS,cAAc,CAAC;AAErC,8BAAU,MAAM;AACd,QAAI,CAAC,QAAS;AACd,SAAK,QAAQ;AAAA,EACf,GAAG,CAAC,SAAS,OAAO,CAAC;AAErB,SAAO,EAAE,WAAW,WAAW,OAAO,QAAQ;AAChD;;;ACoFO,IAAK,qBAAL,kBAAKA,wBAAL;AACL,EAAAA,oBAAA,uBAAoB;AACpB,EAAAA,oBAAA,YAAS;AACT,EAAAA,oBAAA,qBAAkB;AAClB,EAAAA,oBAAA,eAAY;AACZ,EAAAA,oBAAA,YAAS;AACT,EAAAA,oBAAA,eAAY;AACZ,EAAAA,oBAAA,YAAS;AACT,EAAAA,oBAAA,gBAAa;AACb,EAAAA,oBAAA,aAAU;AACV,EAAAA,oBAAA,eAAY;AAVF,SAAAA;AAAA,GAAA;","names":["HiveShipmentStatus"]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HiveShipmentStatus
|
|
3
|
+
} from "../chunk-BADYBNR7.mjs";
|
|
4
|
+
|
|
5
|
+
// src/client/use-hive-tracking.ts
|
|
6
|
+
import { useCallback, useEffect, useState } from "react";
|
|
7
|
+
function useHiveTracking(orderId, options = {}) {
|
|
8
|
+
const { baseUrl, publishableKey, enabled = true } = options;
|
|
9
|
+
const [shipments, setShipments] = useState([]);
|
|
10
|
+
const [isPending, setIsPending] = useState(false);
|
|
11
|
+
const [error, setError] = useState(null);
|
|
12
|
+
const refetch = useCallback(async () => {
|
|
13
|
+
if (!orderId) return;
|
|
14
|
+
setIsPending(true);
|
|
15
|
+
setError(null);
|
|
16
|
+
try {
|
|
17
|
+
const resolvedBaseUrl = baseUrl ?? process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL ?? "";
|
|
18
|
+
const resolvedKey = publishableKey ?? process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY ?? "";
|
|
19
|
+
const url = `${resolvedBaseUrl.replace(/\/$/, "")}/store/hive/shipments?order_id=${encodeURIComponent(orderId)}`;
|
|
20
|
+
const response = await fetch(url, {
|
|
21
|
+
headers: {
|
|
22
|
+
"Content-Type": "application/json",
|
|
23
|
+
...resolvedKey ? { "x-publishable-api-key": resolvedKey } : {}
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
throw new Error(`Hive shipment lookup failed: ${response.status}`);
|
|
28
|
+
}
|
|
29
|
+
const body = await response.json();
|
|
30
|
+
setShipments(body.shipments ?? []);
|
|
31
|
+
} catch (err) {
|
|
32
|
+
setError(err instanceof Error ? err : new Error("Hive shipment lookup failed"));
|
|
33
|
+
} finally {
|
|
34
|
+
setIsPending(false);
|
|
35
|
+
}
|
|
36
|
+
}, [orderId, baseUrl, publishableKey]);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (!enabled) return;
|
|
39
|
+
void refetch();
|
|
40
|
+
}, [enabled, refetch]);
|
|
41
|
+
return { shipments, isPending, error, refetch };
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
HiveShipmentStatus,
|
|
45
|
+
useHiveTracking
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/client/use-hive-tracking.ts"],"sourcesContent":["'use client'\n\nimport { useCallback, useEffect, useState } from 'react'\nimport type { HiveShipmentDto } from '../types'\n\nexport interface UseHiveTrackingOptions {\n baseUrl?: string\n publishableKey?: string\n /** Skip the initial fetch - useful while the order id is still loading. */\n enabled?: boolean\n}\n\nexport interface UseHiveTrackingResult {\n shipments: HiveShipmentDto[]\n isPending: boolean\n error: Error | null\n refetch: () => Promise<void>\n}\n\n/**\n * Reads the Hive shipments for one Medusa order.\n *\n * Hits our own `/store/hive/shipments` route rather than Hive directly:\n * the API key is server-side only and Hive rate-limits at 100 req/min per\n * merchant, so the backend owns the call and the caching.\n *\n * `orderId` is the Medusa order id; the backend maps it to Hive's\n * `merchant_order_id`.\n */\nexport function useHiveTracking(\n orderId: string,\n options: UseHiveTrackingOptions = {},\n): UseHiveTrackingResult {\n const { baseUrl, publishableKey, enabled = true } = options\n\n const [shipments, setShipments] = useState<HiveShipmentDto[]>([])\n const [isPending, setIsPending] = useState<boolean>(false)\n const [error, setError] = useState<Error | null>(null)\n\n const refetch = useCallback(async (): Promise<void> => {\n if (!orderId) return\n setIsPending(true)\n setError(null)\n try {\n const resolvedBaseUrl =\n baseUrl ?? process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL ?? ''\n const resolvedKey =\n publishableKey ?? process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY ?? ''\n const url = `${resolvedBaseUrl.replace(/\\/$/, '')}/store/hive/shipments?order_id=${encodeURIComponent(orderId)}`\n const response = await fetch(url, {\n headers: {\n 'Content-Type': 'application/json',\n ...(resolvedKey ? { 'x-publishable-api-key': resolvedKey } : {}),\n },\n })\n if (!response.ok) {\n throw new Error(`Hive shipment lookup failed: ${response.status}`)\n }\n const body = (await response.json()) as { shipments?: HiveShipmentDto[] }\n setShipments(body.shipments ?? [])\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Hive shipment lookup failed'))\n } finally {\n setIsPending(false)\n }\n }, [orderId, baseUrl, publishableKey])\n\n useEffect(() => {\n if (!enabled) return\n void refetch()\n }, [enabled, refetch])\n\n return { shipments, isPending, error, refetch }\n}\n"],"mappings":";;;;;AAEA,SAAS,aAAa,WAAW,gBAAgB;AA2B1C,SAAS,gBACd,SACA,UAAkC,CAAC,GACZ;AACvB,QAAM,EAAE,SAAS,gBAAgB,UAAU,KAAK,IAAI;AAEpD,QAAM,CAAC,WAAW,YAAY,IAAI,SAA4B,CAAC,CAAC;AAChE,QAAM,CAAC,WAAW,YAAY,IAAI,SAAkB,KAAK;AACzD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAuB,IAAI;AAErD,QAAM,UAAU,YAAY,YAA2B;AACrD,QAAI,CAAC,QAAS;AACd,iBAAa,IAAI;AACjB,aAAS,IAAI;AACb,QAAI;AACF,YAAM,kBACJ,WAAW,QAAQ,IAAI,kCAAkC;AAC3D,YAAM,cACJ,kBAAkB,QAAQ,IAAI,sCAAsC;AACtE,YAAM,MAAM,GAAG,gBAAgB,QAAQ,OAAO,EAAE,CAAC,kCAAkC,mBAAmB,OAAO,CAAC;AAC9G,YAAM,WAAW,MAAM,MAAM,KAAK;AAAA,QAChC,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,GAAI,cAAc,EAAE,yBAAyB,YAAY,IAAI,CAAC;AAAA,QAChE;AAAA,MACF,CAAC;AACD,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,gCAAgC,SAAS,MAAM,EAAE;AAAA,MACnE;AACA,YAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,mBAAa,KAAK,aAAa,CAAC,CAAC;AAAA,IACnC,SAAS,KAAK;AACZ,eAAS,eAAe,QAAQ,MAAM,IAAI,MAAM,6BAA6B,CAAC;AAAA,IAChF,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,SAAS,SAAS,cAAc,CAAC;AAErC,YAAU,MAAM;AACd,QAAI,CAAC,QAAS;AACd,SAAK,QAAQ;AAAA,EACf,GAAG,CAAC,SAAS,OAAO,CAAC;AAErB,SAAO,EAAE,WAAW,WAAW,OAAO,QAAQ;AAChD;","names":[]}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public types for @amboras-dev/hive.
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for the wire shape between the Amboras admin /
|
|
5
|
+
* storefront and the medusa-backend-orchestrator Store API routes under
|
|
6
|
+
* `/store/hive/*`. The DTO files on the Medusa side must stay
|
|
7
|
+
* byte-compatible with these.
|
|
8
|
+
*
|
|
9
|
+
* Field names mirror the Hive Merchant API v1
|
|
10
|
+
* (https://developers.hive.app/reference/api-reference) exactly, including
|
|
11
|
+
* its snake_case, so a backend route can pass a Hive payload straight
|
|
12
|
+
* through without a rename layer.
|
|
13
|
+
*
|
|
14
|
+
* The Hive API key is a server-side secret and Hive enforces a
|
|
15
|
+
* 100 req/min per-merchant rate limit, so nothing in this package ever
|
|
16
|
+
* calls app.hive.app directly - every hook here talks to our own Medusa
|
|
17
|
+
* routes, which own the Hive HTTP client.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Sentinel returned in place of a stored secret when the settings form
|
|
21
|
+
* reads back current config. Matches the pattern used by meta-ads,
|
|
22
|
+
* pinterest and aliexpress-dropshipping so the admin never sees the
|
|
23
|
+
* plaintext API key after write.
|
|
24
|
+
*/
|
|
25
|
+
declare const SECRET_SET_SENTINEL: "__SECRET_SET__";
|
|
26
|
+
type SecretSetSentinel = typeof SECRET_SET_SENTINEL;
|
|
27
|
+
/** Hive base URLs, keyed by the environment chosen in the settings form. */
|
|
28
|
+
declare const HIVE_BASE_URLS: {
|
|
29
|
+
readonly production: "https://app.hive.app/merchant_api/v1";
|
|
30
|
+
readonly staging: "https://staging.app.hive.app/merchant_api/v1";
|
|
31
|
+
};
|
|
32
|
+
type HiveEnvironment = keyof typeof HIVE_BASE_URLS;
|
|
33
|
+
/** Hive allows 100 requests per minute per merchant. */
|
|
34
|
+
declare const HIVE_RATE_LIMIT_PER_MINUTE = 100;
|
|
35
|
+
/**
|
|
36
|
+
* Pagination block attached to every Hive list response.
|
|
37
|
+
* Requests page through with `page` (default 1) and `limit`
|
|
38
|
+
* (default 20, max 100).
|
|
39
|
+
*/
|
|
40
|
+
interface HivePagination {
|
|
41
|
+
current_page: number;
|
|
42
|
+
item_count: number;
|
|
43
|
+
page_count: number;
|
|
44
|
+
items_per_page: number;
|
|
45
|
+
}
|
|
46
|
+
/** Shape of every Hive list endpoint: `{ data, pagination }`. */
|
|
47
|
+
interface HiveListResponse<T> {
|
|
48
|
+
data: T[];
|
|
49
|
+
pagination: HivePagination;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Hive error body. Every failure carries `success: false` and an array of
|
|
53
|
+
* human-readable messages; there are no machine-readable error codes, so
|
|
54
|
+
* the HTTP status is the only thing worth branching on.
|
|
55
|
+
*/
|
|
56
|
+
interface HiveErrorResponse {
|
|
57
|
+
success: false;
|
|
58
|
+
errors: string[];
|
|
59
|
+
}
|
|
60
|
+
/** `GET /warehouses` is list-only and every field is read-only. */
|
|
61
|
+
interface HiveWarehouseDto {
|
|
62
|
+
id: number;
|
|
63
|
+
name: string;
|
|
64
|
+
/** 2-letter ISO 3166-1 country code. */
|
|
65
|
+
country: string;
|
|
66
|
+
city: string;
|
|
67
|
+
}
|
|
68
|
+
/** Whether Hive can pick the order with the stock it currently holds. */
|
|
69
|
+
declare enum HiveOrderStatus {
|
|
70
|
+
Fulfillable = "fulfillable",
|
|
71
|
+
Unfulfillable = "unfulfillable",
|
|
72
|
+
Fulfilled = "fulfilled"
|
|
73
|
+
}
|
|
74
|
+
declare enum HiveFinancialStatus {
|
|
75
|
+
Paid = "paid",
|
|
76
|
+
Refunded = "refunded",
|
|
77
|
+
Pending = "pending",
|
|
78
|
+
Failed = "failed"
|
|
79
|
+
}
|
|
80
|
+
interface HiveAddressDto {
|
|
81
|
+
first_name: string | null;
|
|
82
|
+
last_name: string | null;
|
|
83
|
+
company: string | null;
|
|
84
|
+
address_1: string;
|
|
85
|
+
address_2: string | null;
|
|
86
|
+
city: string;
|
|
87
|
+
province: string | null;
|
|
88
|
+
zip: string;
|
|
89
|
+
/** 2-letter ISO 3166-1 country code. */
|
|
90
|
+
country_code: string;
|
|
91
|
+
phone: string | null;
|
|
92
|
+
email: string | null;
|
|
93
|
+
}
|
|
94
|
+
interface HiveOrderItemDto {
|
|
95
|
+
id: number;
|
|
96
|
+
merchant_item_id: string | null;
|
|
97
|
+
merchant_sku_id: string;
|
|
98
|
+
quantity: number;
|
|
99
|
+
}
|
|
100
|
+
/** Body item for `POST /orders` - references a SKU the merchant already created. */
|
|
101
|
+
interface HiveOrderItemInput {
|
|
102
|
+
merchant_sku_id: string;
|
|
103
|
+
quantity: number;
|
|
104
|
+
merchant_item_id?: string;
|
|
105
|
+
}
|
|
106
|
+
interface HiveOrderDto {
|
|
107
|
+
id: number;
|
|
108
|
+
merchant_order_id: string;
|
|
109
|
+
status: HiveOrderStatus;
|
|
110
|
+
financial_status: HiveFinancialStatus | null;
|
|
111
|
+
shipping_address: HiveAddressDto;
|
|
112
|
+
billing_address: HiveAddressDto | null;
|
|
113
|
+
items: HiveOrderItemDto[];
|
|
114
|
+
created_at: string;
|
|
115
|
+
updated_at: string;
|
|
116
|
+
}
|
|
117
|
+
/** Body for `POST /orders`. */
|
|
118
|
+
interface HiveOrderInput {
|
|
119
|
+
merchant_order_id: string;
|
|
120
|
+
shipping_address: HiveAddressDto;
|
|
121
|
+
items: HiveOrderItemInput[];
|
|
122
|
+
billing_address?: HiveAddressDto;
|
|
123
|
+
financial_status?: HiveFinancialStatus;
|
|
124
|
+
}
|
|
125
|
+
/** Warehouse-side progress of a shipment. */
|
|
126
|
+
declare enum HiveShipmentStatus {
|
|
127
|
+
WaitingForPicking = "waiting_for_picking",
|
|
128
|
+
OnHold = "on_hold",
|
|
129
|
+
PickingAssigned = "picking_assigned",
|
|
130
|
+
InPicking = "in_picking",
|
|
131
|
+
Picked = "picked",
|
|
132
|
+
InPacking = "in_packing",
|
|
133
|
+
Packed = "packed",
|
|
134
|
+
InShipping = "in_shipping",
|
|
135
|
+
Shipped = "shipped",
|
|
136
|
+
Cancelled = "cancelled"
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Carrier-side progress. Hive sends these as human-readable strings
|
|
140
|
+
* rather than slugs, so they are typed as a literal union of the exact
|
|
141
|
+
* values the API returns.
|
|
142
|
+
*/
|
|
143
|
+
type HiveDeliveryStatus = 'Information transmitted to the carrier' | 'In transit' | 'Out for delivery' | 'Delivered' | 'Returned to sender' | 'Action required';
|
|
144
|
+
interface HiveShipmentItemSkuDto {
|
|
145
|
+
id: number;
|
|
146
|
+
merchant_sku_id: string;
|
|
147
|
+
}
|
|
148
|
+
interface HiveShipmentItemDto {
|
|
149
|
+
id: number;
|
|
150
|
+
merchant_item_id: string | null;
|
|
151
|
+
quantity: number;
|
|
152
|
+
sku: HiveShipmentItemSkuDto;
|
|
153
|
+
}
|
|
154
|
+
interface HiveShipmentDto {
|
|
155
|
+
id: number;
|
|
156
|
+
order_id: number;
|
|
157
|
+
merchant_order_id: string;
|
|
158
|
+
status: HiveShipmentStatus;
|
|
159
|
+
delivery_status: HiveDeliveryStatus | null;
|
|
160
|
+
shipment_provider: string | null;
|
|
161
|
+
tracking_number: string | null;
|
|
162
|
+
tracking_url: string | null;
|
|
163
|
+
items: HiveShipmentItemDto[];
|
|
164
|
+
shipped_at: string | null;
|
|
165
|
+
delivered_at: string | null;
|
|
166
|
+
created_at: string;
|
|
167
|
+
updated_at: string;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* The four events Hive can push. Registration is not self-serve - the
|
|
171
|
+
* merchant's Hive account manager configures the destination URL.
|
|
172
|
+
*/
|
|
173
|
+
declare enum HiveWebhookEvent {
|
|
174
|
+
DeliveryStatusUpdated = "delivery_status_updated",
|
|
175
|
+
ShipmentStatusUpdated = "shipment_status_updated",
|
|
176
|
+
RestockingShipmentStatusUpdated = "restocking_shipment_status_updated",
|
|
177
|
+
ReturnStatusUpdated = "return_status_updated"
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* HTTP header carrying the hex-encoded HMAC-SHA256 digest of the raw
|
|
181
|
+
* request body, keyed by the merchant's API token. Requests without it
|
|
182
|
+
* must be ignored, and the comparison must be constant-time.
|
|
183
|
+
*/
|
|
184
|
+
declare const HIVE_SIGNATURE_HEADER = "x-hive-signature";
|
|
185
|
+
/**
|
|
186
|
+
* Hive does not guarantee ordering or exactly-once delivery, so a
|
|
187
|
+
* consumer must compare the payload's `updated_at` against the last
|
|
188
|
+
* value it stored and drop anything older.
|
|
189
|
+
*/
|
|
190
|
+
interface HiveWebhookPayload<T = unknown> {
|
|
191
|
+
event: HiveWebhookEvent;
|
|
192
|
+
data: T;
|
|
193
|
+
}
|
|
194
|
+
type HiveShipmentWebhookPayload = HiveWebhookPayload<HiveShipmentDto>;
|
|
195
|
+
/**
|
|
196
|
+
* Per-store Hive plugin configuration.
|
|
197
|
+
*
|
|
198
|
+
* - `apiKey` is issued by the merchant's Hive account manager. The admin
|
|
199
|
+
* form receives `SECRET_SET_SENTINEL` on read and only sends a real
|
|
200
|
+
* value when the merchant types a new one.
|
|
201
|
+
* - `environment` selects between the production and staging domains.
|
|
202
|
+
* - `defaultWarehouseId` is the warehouse orders route to when the
|
|
203
|
+
* multi-3PL rules do not name one.
|
|
204
|
+
* - `lastSuccessfulCallAt` is an ISO-8601 timestamp for the status card.
|
|
205
|
+
*/
|
|
206
|
+
interface HivePluginConfig {
|
|
207
|
+
enabled: boolean;
|
|
208
|
+
apiKey: string | SecretSetSentinel | null;
|
|
209
|
+
environment: HiveEnvironment;
|
|
210
|
+
defaultWarehouseId: number | null;
|
|
211
|
+
lastSuccessfulCallAt: string | null;
|
|
212
|
+
}
|
|
213
|
+
/** Why the backend considers the stored credential unusable. */
|
|
214
|
+
declare enum HiveConnectionError {
|
|
215
|
+
MissingApiKey = "missing_api_key",
|
|
216
|
+
Unauthorized = "unauthorized",
|
|
217
|
+
RateLimited = "rate_limited",
|
|
218
|
+
Unreachable = "unreachable"
|
|
219
|
+
}
|
|
220
|
+
/** `GET /store/hive/status`. */
|
|
221
|
+
interface HiveConnectionStatusDto {
|
|
222
|
+
connected: boolean;
|
|
223
|
+
environment: HiveEnvironment;
|
|
224
|
+
/** Populated from `GET /warehouses` on the last successful call. */
|
|
225
|
+
warehouses: HiveWarehouseDto[];
|
|
226
|
+
lastSuccessfulCallAt: string | null;
|
|
227
|
+
error: HiveConnectionError | null;
|
|
228
|
+
/**
|
|
229
|
+
* Where the merchant's Hive account manager should point webhooks.
|
|
230
|
+
* Rendered read-only in the settings form.
|
|
231
|
+
*/
|
|
232
|
+
webhookUrl: string | null;
|
|
233
|
+
}
|
|
234
|
+
/** `POST /store/hive/test-connection`. */
|
|
235
|
+
type HiveTestConnectionResult = {
|
|
236
|
+
ok: true;
|
|
237
|
+
warehouses: HiveWarehouseDto[];
|
|
238
|
+
} | {
|
|
239
|
+
ok: false;
|
|
240
|
+
code: HiveConnectionError | 'UNKNOWN';
|
|
241
|
+
msg: string;
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
export { HIVE_BASE_URLS, HIVE_RATE_LIMIT_PER_MINUTE, HIVE_SIGNATURE_HEADER, type HiveAddressDto, HiveConnectionError, type HiveConnectionStatusDto, type HiveDeliveryStatus, type HiveEnvironment, type HiveErrorResponse, HiveFinancialStatus, type HiveListResponse, type HiveOrderDto, type HiveOrderInput, type HiveOrderItemDto, type HiveOrderItemInput, HiveOrderStatus, type HivePagination, type HivePluginConfig, type HiveShipmentDto, type HiveShipmentItemDto, type HiveShipmentItemSkuDto, HiveShipmentStatus, type HiveShipmentWebhookPayload, type HiveTestConnectionResult, type HiveWarehouseDto, HiveWebhookEvent, type HiveWebhookPayload, SECRET_SET_SENTINEL, type SecretSetSentinel };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public types for @amboras-dev/hive.
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for the wire shape between the Amboras admin /
|
|
5
|
+
* storefront and the medusa-backend-orchestrator Store API routes under
|
|
6
|
+
* `/store/hive/*`. The DTO files on the Medusa side must stay
|
|
7
|
+
* byte-compatible with these.
|
|
8
|
+
*
|
|
9
|
+
* Field names mirror the Hive Merchant API v1
|
|
10
|
+
* (https://developers.hive.app/reference/api-reference) exactly, including
|
|
11
|
+
* its snake_case, so a backend route can pass a Hive payload straight
|
|
12
|
+
* through without a rename layer.
|
|
13
|
+
*
|
|
14
|
+
* The Hive API key is a server-side secret and Hive enforces a
|
|
15
|
+
* 100 req/min per-merchant rate limit, so nothing in this package ever
|
|
16
|
+
* calls app.hive.app directly - every hook here talks to our own Medusa
|
|
17
|
+
* routes, which own the Hive HTTP client.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Sentinel returned in place of a stored secret when the settings form
|
|
21
|
+
* reads back current config. Matches the pattern used by meta-ads,
|
|
22
|
+
* pinterest and aliexpress-dropshipping so the admin never sees the
|
|
23
|
+
* plaintext API key after write.
|
|
24
|
+
*/
|
|
25
|
+
declare const SECRET_SET_SENTINEL: "__SECRET_SET__";
|
|
26
|
+
type SecretSetSentinel = typeof SECRET_SET_SENTINEL;
|
|
27
|
+
/** Hive base URLs, keyed by the environment chosen in the settings form. */
|
|
28
|
+
declare const HIVE_BASE_URLS: {
|
|
29
|
+
readonly production: "https://app.hive.app/merchant_api/v1";
|
|
30
|
+
readonly staging: "https://staging.app.hive.app/merchant_api/v1";
|
|
31
|
+
};
|
|
32
|
+
type HiveEnvironment = keyof typeof HIVE_BASE_URLS;
|
|
33
|
+
/** Hive allows 100 requests per minute per merchant. */
|
|
34
|
+
declare const HIVE_RATE_LIMIT_PER_MINUTE = 100;
|
|
35
|
+
/**
|
|
36
|
+
* Pagination block attached to every Hive list response.
|
|
37
|
+
* Requests page through with `page` (default 1) and `limit`
|
|
38
|
+
* (default 20, max 100).
|
|
39
|
+
*/
|
|
40
|
+
interface HivePagination {
|
|
41
|
+
current_page: number;
|
|
42
|
+
item_count: number;
|
|
43
|
+
page_count: number;
|
|
44
|
+
items_per_page: number;
|
|
45
|
+
}
|
|
46
|
+
/** Shape of every Hive list endpoint: `{ data, pagination }`. */
|
|
47
|
+
interface HiveListResponse<T> {
|
|
48
|
+
data: T[];
|
|
49
|
+
pagination: HivePagination;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Hive error body. Every failure carries `success: false` and an array of
|
|
53
|
+
* human-readable messages; there are no machine-readable error codes, so
|
|
54
|
+
* the HTTP status is the only thing worth branching on.
|
|
55
|
+
*/
|
|
56
|
+
interface HiveErrorResponse {
|
|
57
|
+
success: false;
|
|
58
|
+
errors: string[];
|
|
59
|
+
}
|
|
60
|
+
/** `GET /warehouses` is list-only and every field is read-only. */
|
|
61
|
+
interface HiveWarehouseDto {
|
|
62
|
+
id: number;
|
|
63
|
+
name: string;
|
|
64
|
+
/** 2-letter ISO 3166-1 country code. */
|
|
65
|
+
country: string;
|
|
66
|
+
city: string;
|
|
67
|
+
}
|
|
68
|
+
/** Whether Hive can pick the order with the stock it currently holds. */
|
|
69
|
+
declare enum HiveOrderStatus {
|
|
70
|
+
Fulfillable = "fulfillable",
|
|
71
|
+
Unfulfillable = "unfulfillable",
|
|
72
|
+
Fulfilled = "fulfilled"
|
|
73
|
+
}
|
|
74
|
+
declare enum HiveFinancialStatus {
|
|
75
|
+
Paid = "paid",
|
|
76
|
+
Refunded = "refunded",
|
|
77
|
+
Pending = "pending",
|
|
78
|
+
Failed = "failed"
|
|
79
|
+
}
|
|
80
|
+
interface HiveAddressDto {
|
|
81
|
+
first_name: string | null;
|
|
82
|
+
last_name: string | null;
|
|
83
|
+
company: string | null;
|
|
84
|
+
address_1: string;
|
|
85
|
+
address_2: string | null;
|
|
86
|
+
city: string;
|
|
87
|
+
province: string | null;
|
|
88
|
+
zip: string;
|
|
89
|
+
/** 2-letter ISO 3166-1 country code. */
|
|
90
|
+
country_code: string;
|
|
91
|
+
phone: string | null;
|
|
92
|
+
email: string | null;
|
|
93
|
+
}
|
|
94
|
+
interface HiveOrderItemDto {
|
|
95
|
+
id: number;
|
|
96
|
+
merchant_item_id: string | null;
|
|
97
|
+
merchant_sku_id: string;
|
|
98
|
+
quantity: number;
|
|
99
|
+
}
|
|
100
|
+
/** Body item for `POST /orders` - references a SKU the merchant already created. */
|
|
101
|
+
interface HiveOrderItemInput {
|
|
102
|
+
merchant_sku_id: string;
|
|
103
|
+
quantity: number;
|
|
104
|
+
merchant_item_id?: string;
|
|
105
|
+
}
|
|
106
|
+
interface HiveOrderDto {
|
|
107
|
+
id: number;
|
|
108
|
+
merchant_order_id: string;
|
|
109
|
+
status: HiveOrderStatus;
|
|
110
|
+
financial_status: HiveFinancialStatus | null;
|
|
111
|
+
shipping_address: HiveAddressDto;
|
|
112
|
+
billing_address: HiveAddressDto | null;
|
|
113
|
+
items: HiveOrderItemDto[];
|
|
114
|
+
created_at: string;
|
|
115
|
+
updated_at: string;
|
|
116
|
+
}
|
|
117
|
+
/** Body for `POST /orders`. */
|
|
118
|
+
interface HiveOrderInput {
|
|
119
|
+
merchant_order_id: string;
|
|
120
|
+
shipping_address: HiveAddressDto;
|
|
121
|
+
items: HiveOrderItemInput[];
|
|
122
|
+
billing_address?: HiveAddressDto;
|
|
123
|
+
financial_status?: HiveFinancialStatus;
|
|
124
|
+
}
|
|
125
|
+
/** Warehouse-side progress of a shipment. */
|
|
126
|
+
declare enum HiveShipmentStatus {
|
|
127
|
+
WaitingForPicking = "waiting_for_picking",
|
|
128
|
+
OnHold = "on_hold",
|
|
129
|
+
PickingAssigned = "picking_assigned",
|
|
130
|
+
InPicking = "in_picking",
|
|
131
|
+
Picked = "picked",
|
|
132
|
+
InPacking = "in_packing",
|
|
133
|
+
Packed = "packed",
|
|
134
|
+
InShipping = "in_shipping",
|
|
135
|
+
Shipped = "shipped",
|
|
136
|
+
Cancelled = "cancelled"
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Carrier-side progress. Hive sends these as human-readable strings
|
|
140
|
+
* rather than slugs, so they are typed as a literal union of the exact
|
|
141
|
+
* values the API returns.
|
|
142
|
+
*/
|
|
143
|
+
type HiveDeliveryStatus = 'Information transmitted to the carrier' | 'In transit' | 'Out for delivery' | 'Delivered' | 'Returned to sender' | 'Action required';
|
|
144
|
+
interface HiveShipmentItemSkuDto {
|
|
145
|
+
id: number;
|
|
146
|
+
merchant_sku_id: string;
|
|
147
|
+
}
|
|
148
|
+
interface HiveShipmentItemDto {
|
|
149
|
+
id: number;
|
|
150
|
+
merchant_item_id: string | null;
|
|
151
|
+
quantity: number;
|
|
152
|
+
sku: HiveShipmentItemSkuDto;
|
|
153
|
+
}
|
|
154
|
+
interface HiveShipmentDto {
|
|
155
|
+
id: number;
|
|
156
|
+
order_id: number;
|
|
157
|
+
merchant_order_id: string;
|
|
158
|
+
status: HiveShipmentStatus;
|
|
159
|
+
delivery_status: HiveDeliveryStatus | null;
|
|
160
|
+
shipment_provider: string | null;
|
|
161
|
+
tracking_number: string | null;
|
|
162
|
+
tracking_url: string | null;
|
|
163
|
+
items: HiveShipmentItemDto[];
|
|
164
|
+
shipped_at: string | null;
|
|
165
|
+
delivered_at: string | null;
|
|
166
|
+
created_at: string;
|
|
167
|
+
updated_at: string;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* The four events Hive can push. Registration is not self-serve - the
|
|
171
|
+
* merchant's Hive account manager configures the destination URL.
|
|
172
|
+
*/
|
|
173
|
+
declare enum HiveWebhookEvent {
|
|
174
|
+
DeliveryStatusUpdated = "delivery_status_updated",
|
|
175
|
+
ShipmentStatusUpdated = "shipment_status_updated",
|
|
176
|
+
RestockingShipmentStatusUpdated = "restocking_shipment_status_updated",
|
|
177
|
+
ReturnStatusUpdated = "return_status_updated"
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* HTTP header carrying the hex-encoded HMAC-SHA256 digest of the raw
|
|
181
|
+
* request body, keyed by the merchant's API token. Requests without it
|
|
182
|
+
* must be ignored, and the comparison must be constant-time.
|
|
183
|
+
*/
|
|
184
|
+
declare const HIVE_SIGNATURE_HEADER = "x-hive-signature";
|
|
185
|
+
/**
|
|
186
|
+
* Hive does not guarantee ordering or exactly-once delivery, so a
|
|
187
|
+
* consumer must compare the payload's `updated_at` against the last
|
|
188
|
+
* value it stored and drop anything older.
|
|
189
|
+
*/
|
|
190
|
+
interface HiveWebhookPayload<T = unknown> {
|
|
191
|
+
event: HiveWebhookEvent;
|
|
192
|
+
data: T;
|
|
193
|
+
}
|
|
194
|
+
type HiveShipmentWebhookPayload = HiveWebhookPayload<HiveShipmentDto>;
|
|
195
|
+
/**
|
|
196
|
+
* Per-store Hive plugin configuration.
|
|
197
|
+
*
|
|
198
|
+
* - `apiKey` is issued by the merchant's Hive account manager. The admin
|
|
199
|
+
* form receives `SECRET_SET_SENTINEL` on read and only sends a real
|
|
200
|
+
* value when the merchant types a new one.
|
|
201
|
+
* - `environment` selects between the production and staging domains.
|
|
202
|
+
* - `defaultWarehouseId` is the warehouse orders route to when the
|
|
203
|
+
* multi-3PL rules do not name one.
|
|
204
|
+
* - `lastSuccessfulCallAt` is an ISO-8601 timestamp for the status card.
|
|
205
|
+
*/
|
|
206
|
+
interface HivePluginConfig {
|
|
207
|
+
enabled: boolean;
|
|
208
|
+
apiKey: string | SecretSetSentinel | null;
|
|
209
|
+
environment: HiveEnvironment;
|
|
210
|
+
defaultWarehouseId: number | null;
|
|
211
|
+
lastSuccessfulCallAt: string | null;
|
|
212
|
+
}
|
|
213
|
+
/** Why the backend considers the stored credential unusable. */
|
|
214
|
+
declare enum HiveConnectionError {
|
|
215
|
+
MissingApiKey = "missing_api_key",
|
|
216
|
+
Unauthorized = "unauthorized",
|
|
217
|
+
RateLimited = "rate_limited",
|
|
218
|
+
Unreachable = "unreachable"
|
|
219
|
+
}
|
|
220
|
+
/** `GET /store/hive/status`. */
|
|
221
|
+
interface HiveConnectionStatusDto {
|
|
222
|
+
connected: boolean;
|
|
223
|
+
environment: HiveEnvironment;
|
|
224
|
+
/** Populated from `GET /warehouses` on the last successful call. */
|
|
225
|
+
warehouses: HiveWarehouseDto[];
|
|
226
|
+
lastSuccessfulCallAt: string | null;
|
|
227
|
+
error: HiveConnectionError | null;
|
|
228
|
+
/**
|
|
229
|
+
* Where the merchant's Hive account manager should point webhooks.
|
|
230
|
+
* Rendered read-only in the settings form.
|
|
231
|
+
*/
|
|
232
|
+
webhookUrl: string | null;
|
|
233
|
+
}
|
|
234
|
+
/** `POST /store/hive/test-connection`. */
|
|
235
|
+
type HiveTestConnectionResult = {
|
|
236
|
+
ok: true;
|
|
237
|
+
warehouses: HiveWarehouseDto[];
|
|
238
|
+
} | {
|
|
239
|
+
ok: false;
|
|
240
|
+
code: HiveConnectionError | 'UNKNOWN';
|
|
241
|
+
msg: string;
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
export { HIVE_BASE_URLS, HIVE_RATE_LIMIT_PER_MINUTE, HIVE_SIGNATURE_HEADER, type HiveAddressDto, HiveConnectionError, type HiveConnectionStatusDto, type HiveDeliveryStatus, type HiveEnvironment, type HiveErrorResponse, HiveFinancialStatus, type HiveListResponse, type HiveOrderDto, type HiveOrderInput, type HiveOrderItemDto, type HiveOrderItemInput, HiveOrderStatus, type HivePagination, type HivePluginConfig, type HiveShipmentDto, type HiveShipmentItemDto, type HiveShipmentItemSkuDto, HiveShipmentStatus, type HiveShipmentWebhookPayload, type HiveTestConnectionResult, type HiveWarehouseDto, HiveWebhookEvent, type HiveWebhookPayload, SECRET_SET_SENTINEL, type SecretSetSentinel };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
HIVE_BASE_URLS: () => HIVE_BASE_URLS,
|
|
24
|
+
HIVE_RATE_LIMIT_PER_MINUTE: () => HIVE_RATE_LIMIT_PER_MINUTE,
|
|
25
|
+
HIVE_SIGNATURE_HEADER: () => HIVE_SIGNATURE_HEADER,
|
|
26
|
+
HiveConnectionError: () => HiveConnectionError,
|
|
27
|
+
HiveFinancialStatus: () => HiveFinancialStatus,
|
|
28
|
+
HiveOrderStatus: () => HiveOrderStatus,
|
|
29
|
+
HiveShipmentStatus: () => HiveShipmentStatus,
|
|
30
|
+
HiveWebhookEvent: () => HiveWebhookEvent,
|
|
31
|
+
SECRET_SET_SENTINEL: () => SECRET_SET_SENTINEL
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(src_exports);
|
|
34
|
+
|
|
35
|
+
// src/types.ts
|
|
36
|
+
var SECRET_SET_SENTINEL = "__SECRET_SET__";
|
|
37
|
+
var HIVE_BASE_URLS = {
|
|
38
|
+
production: "https://app.hive.app/merchant_api/v1",
|
|
39
|
+
staging: "https://staging.app.hive.app/merchant_api/v1"
|
|
40
|
+
};
|
|
41
|
+
var HIVE_RATE_LIMIT_PER_MINUTE = 100;
|
|
42
|
+
var HiveOrderStatus = /* @__PURE__ */ ((HiveOrderStatus2) => {
|
|
43
|
+
HiveOrderStatus2["Fulfillable"] = "fulfillable";
|
|
44
|
+
HiveOrderStatus2["Unfulfillable"] = "unfulfillable";
|
|
45
|
+
HiveOrderStatus2["Fulfilled"] = "fulfilled";
|
|
46
|
+
return HiveOrderStatus2;
|
|
47
|
+
})(HiveOrderStatus || {});
|
|
48
|
+
var HiveFinancialStatus = /* @__PURE__ */ ((HiveFinancialStatus2) => {
|
|
49
|
+
HiveFinancialStatus2["Paid"] = "paid";
|
|
50
|
+
HiveFinancialStatus2["Refunded"] = "refunded";
|
|
51
|
+
HiveFinancialStatus2["Pending"] = "pending";
|
|
52
|
+
HiveFinancialStatus2["Failed"] = "failed";
|
|
53
|
+
return HiveFinancialStatus2;
|
|
54
|
+
})(HiveFinancialStatus || {});
|
|
55
|
+
var HiveShipmentStatus = /* @__PURE__ */ ((HiveShipmentStatus2) => {
|
|
56
|
+
HiveShipmentStatus2["WaitingForPicking"] = "waiting_for_picking";
|
|
57
|
+
HiveShipmentStatus2["OnHold"] = "on_hold";
|
|
58
|
+
HiveShipmentStatus2["PickingAssigned"] = "picking_assigned";
|
|
59
|
+
HiveShipmentStatus2["InPicking"] = "in_picking";
|
|
60
|
+
HiveShipmentStatus2["Picked"] = "picked";
|
|
61
|
+
HiveShipmentStatus2["InPacking"] = "in_packing";
|
|
62
|
+
HiveShipmentStatus2["Packed"] = "packed";
|
|
63
|
+
HiveShipmentStatus2["InShipping"] = "in_shipping";
|
|
64
|
+
HiveShipmentStatus2["Shipped"] = "shipped";
|
|
65
|
+
HiveShipmentStatus2["Cancelled"] = "cancelled";
|
|
66
|
+
return HiveShipmentStatus2;
|
|
67
|
+
})(HiveShipmentStatus || {});
|
|
68
|
+
var HiveWebhookEvent = /* @__PURE__ */ ((HiveWebhookEvent2) => {
|
|
69
|
+
HiveWebhookEvent2["DeliveryStatusUpdated"] = "delivery_status_updated";
|
|
70
|
+
HiveWebhookEvent2["ShipmentStatusUpdated"] = "shipment_status_updated";
|
|
71
|
+
HiveWebhookEvent2["RestockingShipmentStatusUpdated"] = "restocking_shipment_status_updated";
|
|
72
|
+
HiveWebhookEvent2["ReturnStatusUpdated"] = "return_status_updated";
|
|
73
|
+
return HiveWebhookEvent2;
|
|
74
|
+
})(HiveWebhookEvent || {});
|
|
75
|
+
var HIVE_SIGNATURE_HEADER = "x-hive-signature";
|
|
76
|
+
var HiveConnectionError = /* @__PURE__ */ ((HiveConnectionError2) => {
|
|
77
|
+
HiveConnectionError2["MissingApiKey"] = "missing_api_key";
|
|
78
|
+
HiveConnectionError2["Unauthorized"] = "unauthorized";
|
|
79
|
+
HiveConnectionError2["RateLimited"] = "rate_limited";
|
|
80
|
+
HiveConnectionError2["Unreachable"] = "unreachable";
|
|
81
|
+
return HiveConnectionError2;
|
|
82
|
+
})(HiveConnectionError || {});
|
|
83
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
84
|
+
0 && (module.exports = {
|
|
85
|
+
HIVE_BASE_URLS,
|
|
86
|
+
HIVE_RATE_LIMIT_PER_MINUTE,
|
|
87
|
+
HIVE_SIGNATURE_HEADER,
|
|
88
|
+
HiveConnectionError,
|
|
89
|
+
HiveFinancialStatus,
|
|
90
|
+
HiveOrderStatus,
|
|
91
|
+
HiveShipmentStatus,
|
|
92
|
+
HiveWebhookEvent,
|
|
93
|
+
SECRET_SET_SENTINEL
|
|
94
|
+
});
|
|
95
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types.ts"],"sourcesContent":["// Shared wire types for the Hive 3PL integration — kept byte-compatible\n// with the DTOs in medusa-backend-orchestrator's `src/modules/hive/types.ts`.\n//\n// There is no React surface on this entrypoint. The storefront tracking\n// hook lives on `@amboras-dev/hive/client`; the admin settings UI lives in\n// the orchestrator admin app. Same split as meta-ads.\nexport {\n SECRET_SET_SENTINEL,\n HIVE_BASE_URLS,\n HIVE_RATE_LIMIT_PER_MINUTE,\n HIVE_SIGNATURE_HEADER,\n HiveOrderStatus,\n HiveFinancialStatus,\n HiveShipmentStatus,\n HiveWebhookEvent,\n HiveConnectionError,\n} from './types'\nexport type {\n SecretSetSentinel,\n HiveEnvironment,\n HivePagination,\n HiveListResponse,\n HiveErrorResponse,\n HiveWarehouseDto,\n HiveAddressDto,\n HiveOrderItemDto,\n HiveOrderItemInput,\n HiveOrderDto,\n HiveOrderInput,\n HiveDeliveryStatus,\n HiveShipmentItemSkuDto,\n HiveShipmentItemDto,\n HiveShipmentDto,\n HiveWebhookPayload,\n HiveShipmentWebhookPayload,\n HivePluginConfig,\n HiveConnectionStatusDto,\n HiveTestConnectionResult,\n} from './types'\n","/**\n * Public types for @amboras-dev/hive.\n *\n * Single source of truth for the wire shape between the Amboras admin /\n * storefront and the medusa-backend-orchestrator Store API routes under\n * `/store/hive/*`. The DTO files on the Medusa side must stay\n * byte-compatible with these.\n *\n * Field names mirror the Hive Merchant API v1\n * (https://developers.hive.app/reference/api-reference) exactly, including\n * its snake_case, so a backend route can pass a Hive payload straight\n * through without a rename layer.\n *\n * The Hive API key is a server-side secret and Hive enforces a\n * 100 req/min per-merchant rate limit, so nothing in this package ever\n * calls app.hive.app directly - every hook here talks to our own Medusa\n * routes, which own the Hive HTTP client.\n */\n\n/**\n * Sentinel returned in place of a stored secret when the settings form\n * reads back current config. Matches the pattern used by meta-ads,\n * pinterest and aliexpress-dropshipping so the admin never sees the\n * plaintext API key after write.\n */\nexport const SECRET_SET_SENTINEL = '__SECRET_SET__' as const\nexport type SecretSetSentinel = typeof SECRET_SET_SENTINEL\n\n/** Hive base URLs, keyed by the environment chosen in the settings form. */\nexport const HIVE_BASE_URLS = {\n production: 'https://app.hive.app/merchant_api/v1',\n staging: 'https://staging.app.hive.app/merchant_api/v1',\n} as const\n\nexport type HiveEnvironment = keyof typeof HIVE_BASE_URLS\n\n/** Hive allows 100 requests per minute per merchant. */\nexport const HIVE_RATE_LIMIT_PER_MINUTE = 100\n\n/* -------------------------------------------------------------------------\n * Envelope\n * ---------------------------------------------------------------------- */\n\n/**\n * Pagination block attached to every Hive list response.\n * Requests page through with `page` (default 1) and `limit`\n * (default 20, max 100).\n */\nexport interface HivePagination {\n current_page: number\n item_count: number\n page_count: number\n items_per_page: number\n}\n\n/** Shape of every Hive list endpoint: `{ data, pagination }`. */\nexport interface HiveListResponse<T> {\n data: T[]\n pagination: HivePagination\n}\n\n/**\n * Hive error body. Every failure carries `success: false` and an array of\n * human-readable messages; there are no machine-readable error codes, so\n * the HTTP status is the only thing worth branching on.\n */\nexport interface HiveErrorResponse {\n success: false\n errors: string[]\n}\n\n/* -------------------------------------------------------------------------\n * Warehouses\n * ---------------------------------------------------------------------- */\n\n/** `GET /warehouses` is list-only and every field is read-only. */\nexport interface HiveWarehouseDto {\n id: number\n name: string\n /** 2-letter ISO 3166-1 country code. */\n country: string\n city: string\n}\n\n/* -------------------------------------------------------------------------\n * Orders\n * ---------------------------------------------------------------------- */\n\n/** Whether Hive can pick the order with the stock it currently holds. */\nexport enum HiveOrderStatus {\n Fulfillable = 'fulfillable',\n Unfulfillable = 'unfulfillable',\n Fulfilled = 'fulfilled',\n}\n\nexport enum HiveFinancialStatus {\n Paid = 'paid',\n Refunded = 'refunded',\n Pending = 'pending',\n Failed = 'failed',\n}\n\nexport interface HiveAddressDto {\n first_name: string | null\n last_name: string | null\n company: string | null\n address_1: string\n address_2: string | null\n city: string\n province: string | null\n zip: string\n /** 2-letter ISO 3166-1 country code. */\n country_code: string\n phone: string | null\n email: string | null\n}\n\nexport interface HiveOrderItemDto {\n id: number\n merchant_item_id: string | null\n merchant_sku_id: string\n quantity: number\n}\n\n/** Body item for `POST /orders` - references a SKU the merchant already created. */\nexport interface HiveOrderItemInput {\n merchant_sku_id: string\n quantity: number\n merchant_item_id?: string\n}\n\nexport interface HiveOrderDto {\n id: number\n merchant_order_id: string\n status: HiveOrderStatus\n financial_status: HiveFinancialStatus | null\n shipping_address: HiveAddressDto\n billing_address: HiveAddressDto | null\n items: HiveOrderItemDto[]\n created_at: string\n updated_at: string\n}\n\n/** Body for `POST /orders`. */\nexport interface HiveOrderInput {\n merchant_order_id: string\n shipping_address: HiveAddressDto\n items: HiveOrderItemInput[]\n billing_address?: HiveAddressDto\n financial_status?: HiveFinancialStatus\n}\n\n/* -------------------------------------------------------------------------\n * Shipments\n * ---------------------------------------------------------------------- */\n\n/** Warehouse-side progress of a shipment. */\nexport enum HiveShipmentStatus {\n WaitingForPicking = 'waiting_for_picking',\n OnHold = 'on_hold',\n PickingAssigned = 'picking_assigned',\n InPicking = 'in_picking',\n Picked = 'picked',\n InPacking = 'in_packing',\n Packed = 'packed',\n InShipping = 'in_shipping',\n Shipped = 'shipped',\n Cancelled = 'cancelled',\n}\n\n/**\n * Carrier-side progress. Hive sends these as human-readable strings\n * rather than slugs, so they are typed as a literal union of the exact\n * values the API returns.\n */\nexport type HiveDeliveryStatus =\n | 'Information transmitted to the carrier'\n | 'In transit'\n | 'Out for delivery'\n | 'Delivered'\n | 'Returned to sender'\n | 'Action required'\n\nexport interface HiveShipmentItemSkuDto {\n id: number\n merchant_sku_id: string\n}\n\nexport interface HiveShipmentItemDto {\n id: number\n merchant_item_id: string | null\n quantity: number\n sku: HiveShipmentItemSkuDto\n}\n\nexport interface HiveShipmentDto {\n id: number\n order_id: number\n merchant_order_id: string\n status: HiveShipmentStatus\n delivery_status: HiveDeliveryStatus | null\n shipment_provider: string | null\n tracking_number: string | null\n tracking_url: string | null\n items: HiveShipmentItemDto[]\n shipped_at: string | null\n delivered_at: string | null\n created_at: string\n updated_at: string\n}\n\n/* -------------------------------------------------------------------------\n * Webhooks\n * ---------------------------------------------------------------------- */\n\n/**\n * The four events Hive can push. Registration is not self-serve - the\n * merchant's Hive account manager configures the destination URL.\n */\nexport enum HiveWebhookEvent {\n DeliveryStatusUpdated = 'delivery_status_updated',\n ShipmentStatusUpdated = 'shipment_status_updated',\n RestockingShipmentStatusUpdated = 'restocking_shipment_status_updated',\n ReturnStatusUpdated = 'return_status_updated',\n}\n\n/**\n * HTTP header carrying the hex-encoded HMAC-SHA256 digest of the raw\n * request body, keyed by the merchant's API token. Requests without it\n * must be ignored, and the comparison must be constant-time.\n */\nexport const HIVE_SIGNATURE_HEADER = 'x-hive-signature'\n\n/**\n * Hive does not guarantee ordering or exactly-once delivery, so a\n * consumer must compare the payload's `updated_at` against the last\n * value it stored and drop anything older.\n */\nexport interface HiveWebhookPayload<T = unknown> {\n event: HiveWebhookEvent\n data: T\n}\n\nexport type HiveShipmentWebhookPayload = HiveWebhookPayload<HiveShipmentDto>\n\n/* -------------------------------------------------------------------------\n * Plugin config + admin surface\n * ---------------------------------------------------------------------- */\n\n/**\n * Per-store Hive plugin configuration.\n *\n * - `apiKey` is issued by the merchant's Hive account manager. The admin\n * form receives `SECRET_SET_SENTINEL` on read and only sends a real\n * value when the merchant types a new one.\n * - `environment` selects between the production and staging domains.\n * - `defaultWarehouseId` is the warehouse orders route to when the\n * multi-3PL rules do not name one.\n * - `lastSuccessfulCallAt` is an ISO-8601 timestamp for the status card.\n */\nexport interface HivePluginConfig {\n enabled: boolean\n apiKey: string | SecretSetSentinel | null\n environment: HiveEnvironment\n defaultWarehouseId: number | null\n lastSuccessfulCallAt: string | null\n}\n\n/** Why the backend considers the stored credential unusable. */\nexport enum HiveConnectionError {\n MissingApiKey = 'missing_api_key',\n Unauthorized = 'unauthorized',\n RateLimited = 'rate_limited',\n Unreachable = 'unreachable',\n}\n\n/** `GET /store/hive/status`. */\nexport interface HiveConnectionStatusDto {\n connected: boolean\n environment: HiveEnvironment\n /** Populated from `GET /warehouses` on the last successful call. */\n warehouses: HiveWarehouseDto[]\n lastSuccessfulCallAt: string | null\n error: HiveConnectionError | null\n /**\n * Where the merchant's Hive account manager should point webhooks.\n * Rendered read-only in the settings form.\n */\n webhookUrl: string | null\n}\n\n/** `POST /store/hive/test-connection`. */\nexport type HiveTestConnectionResult =\n | { ok: true; warehouses: HiveWarehouseDto[] }\n | { ok: false; code: HiveConnectionError | 'UNKNOWN'; msg: string }\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACyBO,IAAM,sBAAsB;AAI5B,IAAM,iBAAiB;AAAA,EAC5B,YAAY;AAAA,EACZ,SAAS;AACX;AAKO,IAAM,6BAA6B;AAoDnC,IAAK,kBAAL,kBAAKA,qBAAL;AACL,EAAAA,iBAAA,iBAAc;AACd,EAAAA,iBAAA,mBAAgB;AAChB,EAAAA,iBAAA,eAAY;AAHF,SAAAA;AAAA,GAAA;AAML,IAAK,sBAAL,kBAAKC,yBAAL;AACL,EAAAA,qBAAA,UAAO;AACP,EAAAA,qBAAA,cAAW;AACX,EAAAA,qBAAA,aAAU;AACV,EAAAA,qBAAA,YAAS;AAJC,SAAAA;AAAA,GAAA;AA8DL,IAAK,qBAAL,kBAAKC,wBAAL;AACL,EAAAA,oBAAA,uBAAoB;AACpB,EAAAA,oBAAA,YAAS;AACT,EAAAA,oBAAA,qBAAkB;AAClB,EAAAA,oBAAA,eAAY;AACZ,EAAAA,oBAAA,YAAS;AACT,EAAAA,oBAAA,eAAY;AACZ,EAAAA,oBAAA,YAAS;AACT,EAAAA,oBAAA,gBAAa;AACb,EAAAA,oBAAA,aAAU;AACV,EAAAA,oBAAA,eAAY;AAVF,SAAAA;AAAA,GAAA;AA8DL,IAAK,mBAAL,kBAAKC,sBAAL;AACL,EAAAA,kBAAA,2BAAwB;AACxB,EAAAA,kBAAA,2BAAwB;AACxB,EAAAA,kBAAA,qCAAkC;AAClC,EAAAA,kBAAA,yBAAsB;AAJZ,SAAAA;AAAA,GAAA;AAYL,IAAM,wBAAwB;AAsC9B,IAAK,sBAAL,kBAAKC,yBAAL;AACL,EAAAA,qBAAA,mBAAgB;AAChB,EAAAA,qBAAA,kBAAe;AACf,EAAAA,qBAAA,iBAAc;AACd,EAAAA,qBAAA,iBAAc;AAJJ,SAAAA;AAAA,GAAA;","names":["HiveOrderStatus","HiveFinancialStatus","HiveShipmentStatus","HiveWebhookEvent","HiveConnectionError"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HIVE_BASE_URLS,
|
|
3
|
+
HIVE_RATE_LIMIT_PER_MINUTE,
|
|
4
|
+
HIVE_SIGNATURE_HEADER,
|
|
5
|
+
HiveConnectionError,
|
|
6
|
+
HiveFinancialStatus,
|
|
7
|
+
HiveOrderStatus,
|
|
8
|
+
HiveShipmentStatus,
|
|
9
|
+
HiveWebhookEvent,
|
|
10
|
+
SECRET_SET_SENTINEL
|
|
11
|
+
} from "./chunk-BADYBNR7.mjs";
|
|
12
|
+
export {
|
|
13
|
+
HIVE_BASE_URLS,
|
|
14
|
+
HIVE_RATE_LIMIT_PER_MINUTE,
|
|
15
|
+
HIVE_SIGNATURE_HEADER,
|
|
16
|
+
HiveConnectionError,
|
|
17
|
+
HiveFinancialStatus,
|
|
18
|
+
HiveOrderStatus,
|
|
19
|
+
HiveShipmentStatus,
|
|
20
|
+
HiveWebhookEvent,
|
|
21
|
+
SECRET_SET_SENTINEL
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@amboras-dev/hive",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Hive 3PL fulfillment integration for Amboras - shared wire types and storefront shipment tracking",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./client": {
|
|
15
|
+
"types": "./dist/client/index.d.ts",
|
|
16
|
+
"import": "./dist/client/index.mjs",
|
|
17
|
+
"require": "./dist/client/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./package.json": "./package.json"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"react": ">=18",
|
|
26
|
+
"next": ">=15"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/node": "^20.0.0",
|
|
30
|
+
"@types/react": "^19.0.0",
|
|
31
|
+
"next": "^15.0.0",
|
|
32
|
+
"react": "^19.0.0",
|
|
33
|
+
"tsup": "^8.0.0",
|
|
34
|
+
"typescript": "^5.0.0"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsup",
|
|
41
|
+
"typecheck": "tsc --noEmit"
|
|
42
|
+
}
|
|
43
|
+
}
|