@develemit/commerce-admin 0.7.0 → 0.8.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +7 -4
  3. package/dist/client/admin-client.d.ts +1 -0
  4. package/dist/client/errors.d.ts +4 -0
  5. package/dist/client/index.js +1 -1
  6. package/dist/{client-DCL5DSHP.js → client-ClTCzt-p.js} +34 -28
  7. package/dist/client-ClTCzt-p.js.map +1 -0
  8. package/dist/components/admin-layout/admin-layout.d.ts +2 -1
  9. package/dist/components/admin-layout/current-item.d.ts +1 -0
  10. package/dist/components/admin-layout/nav-items.d.ts +3 -0
  11. package/dist/components/admin-layout/use-current-href.d.ts +1 -0
  12. package/dist/components/empty-state/empty-state.d.ts +1 -1
  13. package/dist/index.js +1255 -912
  14. package/dist/index.js.map +1 -1
  15. package/dist/lib/admin-labels.d.ts +3 -0
  16. package/dist/lib/currency-symbol.d.ts +1 -0
  17. package/dist/lib/order-action-labels.d.ts +2 -0
  18. package/dist/lib/order-labels.d.ts +1 -1
  19. package/dist/lib/product-draft.d.ts +3 -0
  20. package/dist/lib/product-flow-labels.d.ts +9 -0
  21. package/dist/lib/product-labels.d.ts +8 -0
  22. package/dist/lib/provider.d.ts +2 -0
  23. package/dist/lib/stock-labels.d.ts +2 -0
  24. package/dist/lib/use-batch-upload.d.ts +1 -0
  25. package/dist/lib/use-product-autosave.d.ts +4 -0
  26. package/dist/lib/use-product-pages.d.ts +1 -0
  27. package/dist/styles.css +470 -29
  28. package/dist/views/orders/admin-order-detail.d.ts +2 -1
  29. package/dist/views/orders/order-actions.d.ts +2 -1
  30. package/dist/views/orders/resolve-button.d.ts +3 -1
  31. package/dist/views/orders/ship-form.d.ts +4 -1
  32. package/dist/views/products/add-several/photo-picker.d.ts +3 -1
  33. package/dist/views/products/admin-product-images.d.ts +2 -0
  34. package/dist/views/products/finish-drafts/piece-summary.d.ts +2 -1
  35. package/dist/views/products/finish-drafts/use-publish-pieces.d.ts +2 -0
  36. package/dist/views/products/product-flow/flow-actions.d.ts +3 -0
  37. package/dist/views/products/product-flow/flow-frame.d.ts +4 -2
  38. package/dist/views/products/product-flow/materials-field.d.ts +6 -0
  39. package/dist/views/products/product-flow/use-product-flow.d.ts +5 -0
  40. package/dist/views/products/product-sheet/delete-draft-button.d.ts +9 -0
  41. package/dist/views/shipping/shipping-rate-row.d.ts +2 -1
  42. package/package.json +2 -2
  43. package/dist/client-DCL5DSHP.js.map +0 -1
@@ -2,9 +2,10 @@ import { ReactNode } from 'react';
2
2
  import { AdminOrderDetail as OrderDetail } from '@develemit/commerce-contracts';
3
3
  export interface AdminOrderDetailProps {
4
4
  orderId: string;
5
+ requireTracking?: boolean;
5
6
  actions?: (ctx: {
6
7
  order: OrderDetail;
7
8
  reload: () => void;
8
9
  }) => ReactNode;
9
10
  }
10
- export declare function AdminOrderDetail({ orderId, actions }: AdminOrderDetailProps): import('react').JSX.Element;
11
+ export declare function AdminOrderDetail({ orderId, actions, requireTracking, }: AdminOrderDetailProps): import('react').JSX.Element;
@@ -2,6 +2,7 @@ import { AdminOrderDetail } from '@develemit/commerce-contracts';
2
2
  interface OrderActionsProps {
3
3
  order: AdminOrderDetail;
4
4
  reload: () => void;
5
+ requireTracking?: boolean;
5
6
  }
6
- export declare function OrderActions({ order, reload }: OrderActionsProps): import('react').JSX.Element;
7
+ export declare function OrderActions({ order, reload, requireTracking, }: OrderActionsProps): import('react').JSX.Element;
7
8
  export {};
@@ -1,7 +1,9 @@
1
+ import { ReactNode } from 'react';
1
2
  import { AdminOrderDetail } from '@develemit/commerce-contracts';
2
3
  interface ResolveButtonProps {
3
4
  order: AdminOrderDetail;
4
5
  onDone: (message: string) => void;
6
+ notice?: ReactNode;
5
7
  }
6
- export declare function ResolveButton({ order, onDone }: ResolveButtonProps): import('react').JSX.Element;
8
+ export declare function ResolveButton({ order, onDone, notice }: ResolveButtonProps): import('react').JSX.Element;
7
9
  export {};
@@ -1,7 +1,10 @@
1
+ import { ReactNode } from 'react';
1
2
  import { AdminOrderDetail } from '@develemit/commerce-contracts';
2
3
  interface ShipFormProps {
3
4
  order: AdminOrderDetail;
4
5
  onDone: (message: string) => void;
6
+ requireTracking?: boolean;
7
+ notice?: ReactNode;
5
8
  }
6
- export declare function ShipForm({ order, onDone }: ShipFormProps): import('react').JSX.Element;
9
+ export declare function ShipForm({ order, onDone, requireTracking, notice, }: ShipFormProps): import('react').JSX.Element;
7
10
  export {};
@@ -3,5 +3,7 @@ export interface PhotoPickerProps {
3
3
  onFiles: (files: File[]) => void;
4
4
  multiple?: boolean;
5
5
  primary?: boolean;
6
+ zone?: boolean;
7
+ hint?: string;
6
8
  }
7
- export declare function PhotoPicker({ label, onFiles, multiple, primary, }: PhotoPickerProps): import('react').JSX.Element;
9
+ export declare function PhotoPicker({ label, onFiles, multiple, primary, zone, hint, }: PhotoPickerProps): import('react').JSX.Element;
@@ -1,6 +1,8 @@
1
1
  import { AdminProductImage } from './image-tile';
2
+ /** @deprecated Use `AdminProductFlow`, which has its own Photos step. Removed in the next major. */
2
3
  export interface AdminProductImagesProps {
3
4
  productId: string;
4
5
  images: AdminProductImage[];
5
6
  }
7
+ /** @deprecated Use `AdminProductFlow`, which has its own Photos step. Removed in the next major. */
6
8
  export declare function AdminProductImages({ productId, images: initial, }: AdminProductImagesProps): import('react').JSX.Element;
@@ -4,7 +4,8 @@ export interface PieceSummaryProps {
4
4
  pending: boolean;
5
5
  failure: unknown;
6
6
  onPublish: (ready: AdminProduct[], rest: AdminProduct[]) => void;
7
+ onOpenPiece: (index: number) => void;
7
8
  onKeepDrafts: () => void;
8
9
  }
9
10
  export declare function isReady(piece: AdminProduct): boolean;
10
- export declare function PieceSummary({ pieces, pending, failure, onPublish, onKeepDrafts, }: PieceSummaryProps): import('react').JSX.Element;
11
+ export declare function PieceSummary({ pieces, pending, failure, onPublish, onOpenPiece, onKeepDrafts, }: PieceSummaryProps): import('react').JSX.Element;
@@ -18,6 +18,7 @@ export declare function usePublishPieces(): {
18
18
  quantity: number;
19
19
  status: "draft" | "active" | "archived";
20
20
  featured: boolean;
21
+ everPublished: boolean;
21
22
  images: {
22
23
  id: string;
23
24
  url: string;
@@ -38,6 +39,7 @@ export declare function usePublishPieces(): {
38
39
  quantity: number;
39
40
  status: "draft" | "active" | "archived";
40
41
  featured: boolean;
42
+ everPublished: boolean;
41
43
  images: {
42
44
  id: string;
43
45
  url: string;
@@ -8,3 +8,6 @@ export declare function FinishActions({ flow }: {
8
8
  export declare function StepActions({ flow }: {
9
9
  flow: ProductFlowState;
10
10
  }): import('react').JSX.Element;
11
+ export declare function ContinueHint({ flow }: {
12
+ flow: ProductFlowState;
13
+ }): import('react').JSX.Element | null;
@@ -3,11 +3,12 @@ import { ProductFlowStep } from '../../../lib/product-flow-labels';
3
3
  import { AutosaveState } from '../../../lib/use-product-autosave';
4
4
  export interface FlowHeadProps {
5
5
  title: string;
6
+ step: ProductFlowStep;
6
7
  onBack: () => void;
7
8
  canGoBack: boolean;
8
9
  close: ReactNode;
9
10
  }
10
- export declare function FlowHead({ title, onBack, canGoBack, close }: FlowHeadProps): import('react').JSX.Element;
11
+ export declare function FlowHead({ title, step, onBack, canGoBack, close, }: FlowHeadProps): import('react').JSX.Element;
11
12
  export interface StepBarProps {
12
13
  step: ProductFlowStep;
13
14
  allOpen: boolean;
@@ -23,6 +24,7 @@ export declare function SaveNote({ state, isNew, onRetry }: SaveNoteProps): impo
23
24
  export interface FlowSectionFrameProps {
24
25
  step: ProductFlowStep;
25
26
  active: boolean;
27
+ live?: boolean;
26
28
  children: ReactNode;
27
29
  }
28
- export declare function FlowSectionFrame({ step, active, children, }: FlowSectionFrameProps): import('react').JSX.Element;
30
+ export declare function FlowSectionFrame({ step, active, live, children, }: FlowSectionFrameProps): import('react').JSX.Element;
@@ -0,0 +1,6 @@
1
+ export interface MaterialsFieldProps {
2
+ value: string;
3
+ suggestions?: string[];
4
+ onChange: (value: string) => void;
5
+ }
6
+ export declare function MaterialsField({ value, suggestions, onChange, }: MaterialsFieldProps): import('react').JSX.Element;
@@ -30,6 +30,7 @@ export declare function useProductFlow({ initial, initialStep, isFirstProduct, o
30
30
  quantity: number;
31
31
  status: "draft" | "active" | "archived";
32
32
  featured: boolean;
33
+ everPublished: boolean;
33
34
  images: {
34
35
  id: string;
35
36
  url: string;
@@ -52,6 +53,7 @@ export declare function useProductFlow({ initial, initialStep, isFirstProduct, o
52
53
  quantity: number;
53
54
  status: "draft" | "active" | "archived";
54
55
  featured: boolean;
56
+ everPublished: boolean;
55
57
  images: {
56
58
  id: string;
57
59
  url: string;
@@ -75,6 +77,7 @@ export declare function useProductFlow({ initial, initialStep, isFirstProduct, o
75
77
  quantity: number;
76
78
  status: "draft" | "active" | "archived";
77
79
  featured: boolean;
80
+ everPublished: boolean;
78
81
  images: {
79
82
  id: string;
80
83
  url: string;
@@ -95,6 +98,7 @@ export declare function useProductFlow({ initial, initialStep, isFirstProduct, o
95
98
  quantity: number;
96
99
  status: "draft" | "active" | "archived";
97
100
  featured: boolean;
101
+ everPublished: boolean;
98
102
  images: {
99
103
  id: string;
100
104
  url: string;
@@ -115,6 +119,7 @@ export declare function useProductFlow({ initial, initialStep, isFirstProduct, o
115
119
  quantity: number;
116
120
  status: "draft" | "active" | "archived";
117
121
  featured: boolean;
122
+ everPublished: boolean;
118
123
  images: {
119
124
  id: string;
120
125
  url: string;
@@ -0,0 +1,9 @@
1
+ import { AdminProduct } from '@develemit/commerce-contracts';
2
+ export declare function canDeleteDraft(product: AdminProduct): boolean;
3
+ interface Props {
4
+ product: AdminProduct;
5
+ disabled?: boolean;
6
+ onDeleted: () => void;
7
+ }
8
+ export declare function DeleteDraftButton({ product, disabled, onDeleted }: Props): import('react').JSX.Element;
9
+ export {};
@@ -8,8 +8,9 @@ export interface ShippingRateRowProps {
8
8
  errors: RateErrors;
9
9
  disabled: boolean;
10
10
  labels: ShippingLabels;
11
+ locale: string;
11
12
  onChange: (patch: Partial<RateDraft>) => void;
12
13
  onMove: (direction: RateMove) => void;
13
14
  onRemove: () => void;
14
15
  }
15
- export declare function ShippingRateRow({ draft, index, total, errors, disabled, labels, onChange, onMove, onRemove, }: ShippingRateRowProps): import('react').JSX.Element;
16
+ export declare function ShippingRateRow({ draft, index, total, errors, disabled, labels, locale, onChange, onMove, onRemove, }: ShippingRateRowProps): import('react').JSX.Element;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@develemit/commerce-admin",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "React admin UI for products, orders, discounts and shipping rates, backed by the commerce-server admin API.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -47,7 +47,7 @@
47
47
  "access": "public"
48
48
  },
49
49
  "dependencies": {
50
- "@develemit/commerce-contracts": "0.7.0"
50
+ "@develemit/commerce-contracts": "0.8.0"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@testing-library/user-event": "^14.6.8"
@@ -1 +0,0 @@
1
- {"version":3,"file":"client-DCL5DSHP.js","names":["AdminApiError","message","status","code","url","AdminUnauthorizedError","AdminNotFoundError","AdminInvalidInputError","issues","InvalidOrderStateError","orderStatus","InsufficientStockError","productIds","RefundExceedsBalanceError","balanceCents","RefundGatewayError","RefundOutcomeUnknownError","InvalidImageError","ImageTooLargeError","DiscountCodeTakenError","DiscountInUseError","MaxRedemptionsBelowUsageError","ProductIncompleteError","missing","readBody","body","res","mapError","createTransport","fetchImpl","args","getHeaders","root","baseUrl","path","merged","name","value","headers","form","error","schema","enc","queryString","params","key","query","qs","createAdminClient","options","product","adminProductSchema","discount","discountSchema","rates","shippingRateSchema","request","adminProductPageSchema","adminProductCountsSchema","id","input","patch","alt","file","imageId","adminDiscountPageSchema","adminOrderPageSchema","adminOrderDetailSchema","refund","err"],"sources":["../src/client/errors.ts","../src/client/map-error.ts","../src/client/transport.ts","../src/client/admin-client.ts"],"sourcesContent":["import type { ProductIncompleteField } from '@develemit/commerce-contracts';\n\nexport class AdminApiError extends Error {\n idempotencyKey?: string;\n\n constructor(\n readonly status: number,\n readonly url: string,\n readonly code?: string,\n message?: string,\n ) {\n super(\n message ??\n `Admin API request failed (${status}${code ? ` ${code}` : ''}): ${url}`,\n );\n this.name = 'AdminApiError';\n }\n}\n\nexport class AdminUnauthorizedError extends AdminApiError {\n constructor(url: string) {\n super(401, url, 'UNAUTHORIZED', `Not authorized: ${url}`);\n this.name = 'AdminUnauthorizedError';\n }\n}\n\nexport class AdminNotFoundError extends AdminApiError {\n constructor(url: string, code?: string, message?: string) {\n super(404, url, code, message ?? `Not found: ${url}`);\n this.name = 'AdminNotFoundError';\n }\n}\n\nexport class AdminInvalidInputError extends AdminApiError {\n constructor(\n url: string,\n readonly issues: unknown[],\n ) {\n super(400, url, 'INVALID_INPUT', `Invalid input: ${url}`);\n this.name = 'AdminInvalidInputError';\n }\n}\n\nexport class InvalidOrderStateError extends AdminApiError {\n constructor(\n url: string,\n readonly orderStatus: string,\n message?: string,\n ) {\n super(409, url, 'INVALID_ORDER_STATE', message);\n this.name = 'InvalidOrderStateError';\n }\n}\n\nexport class InsufficientStockError extends AdminApiError {\n constructor(\n url: string,\n readonly productIds: string[],\n message?: string,\n ) {\n super(409, url, 'INSUFFICIENT_STOCK', message);\n this.name = 'InsufficientStockError';\n }\n}\n\nexport class RefundExceedsBalanceError extends AdminApiError {\n constructor(\n url: string,\n readonly balanceCents: number | undefined,\n message?: string,\n ) {\n super(400, url, 'REFUND_EXCEEDS_BALANCE', message);\n this.name = 'RefundExceedsBalanceError';\n }\n}\n\nexport class RefundGatewayError extends AdminApiError {\n constructor(url: string, message?: string) {\n super(502, url, 'REFUND_GATEWAY_ERROR', message);\n this.name = 'RefundGatewayError';\n }\n}\n\nexport class RefundOutcomeUnknownError extends AdminApiError {\n constructor(url: string, message?: string) {\n super(502, url, 'REFUND_OUTCOME_UNKNOWN', message);\n this.name = 'RefundOutcomeUnknownError';\n }\n}\n\nexport class InvalidImageError extends AdminApiError {\n constructor(url: string, code: string, message?: string) {\n super(400, url, code, message);\n this.name = 'InvalidImageError';\n }\n}\n\nexport class ImageTooLargeError extends AdminApiError {\n constructor(url: string) {\n super(413, url, 'IMAGE_TOO_LARGE', `Image is too large: ${url}`);\n this.name = 'ImageTooLargeError';\n }\n}\n\nexport class DiscountCodeTakenError extends AdminApiError {\n constructor(url: string, message?: string) {\n super(409, url, 'DISCOUNT_CODE_TAKEN', message);\n this.name = 'DiscountCodeTakenError';\n }\n}\n\nexport class DiscountInUseError extends AdminApiError {\n constructor(url: string, message?: string) {\n super(409, url, 'DISCOUNT_IN_USE', message);\n this.name = 'DiscountInUseError';\n }\n}\n\nexport class MaxRedemptionsBelowUsageError extends AdminApiError {\n constructor(url: string, message?: string) {\n super(400, url, 'MAX_REDEMPTIONS_BELOW_USAGE', message);\n this.name = 'MaxRedemptionsBelowUsageError';\n }\n}\n\nexport class ProductIncompleteError extends AdminApiError {\n constructor(\n url: string,\n readonly missing: ProductIncompleteField[],\n message?: string,\n ) {\n super(422, url, 'PRODUCT_INCOMPLETE', message);\n this.name = 'ProductIncompleteError';\n }\n}\n","import type { ProductIncompleteField } from '@develemit/commerce-contracts';\nimport {\n AdminApiError,\n AdminInvalidInputError,\n AdminNotFoundError,\n AdminUnauthorizedError,\n DiscountCodeTakenError,\n DiscountInUseError,\n ImageTooLargeError,\n InsufficientStockError,\n InvalidImageError,\n InvalidOrderStateError,\n MaxRedemptionsBelowUsageError,\n ProductIncompleteError,\n RefundExceedsBalanceError,\n RefundGatewayError,\n RefundOutcomeUnknownError,\n} from './errors';\n\ninterface ErrorBody {\n error?: string;\n message?: string;\n issues?: unknown[];\n status?: string;\n productIds?: string[];\n missing?: ProductIncompleteField[];\n balanceCents?: number;\n}\n\nasync function readBody(res: Response): Promise<ErrorBody> {\n try {\n const body: unknown = await res.json();\n return body && typeof body === 'object' ? (body as ErrorBody) : {};\n } catch {\n return {};\n }\n}\n\nexport async function mapError(\n url: string,\n res: Response,\n): Promise<AdminApiError> {\n const body = await readBody(res);\n const { error: code, message } = body;\n if (res.status === 401) return new AdminUnauthorizedError(url);\n if (res.status === 404) return new AdminNotFoundError(url, code, message);\n if (res.status === 413) return new ImageTooLargeError(url);\n if (code === 'INVALID_INPUT') {\n return new AdminInvalidInputError(url, body.issues ?? []);\n }\n if (code === 'INVALID_ORDER_STATE') {\n return new InvalidOrderStateError(url, body.status ?? '', message);\n }\n if (code === 'INSUFFICIENT_STOCK') {\n return new InsufficientStockError(url, body.productIds ?? [], message);\n }\n if (code === 'REFUND_EXCEEDS_BALANCE') {\n return new RefundExceedsBalanceError(url, body.balanceCents, message);\n }\n if (code === 'REFUND_GATEWAY_ERROR')\n return new RefundGatewayError(url, message);\n if (code === 'REFUND_OUTCOME_UNKNOWN') {\n return new RefundOutcomeUnknownError(url, message);\n }\n if (code === 'DISCOUNT_CODE_TAKEN') {\n return new DiscountCodeTakenError(url, message);\n }\n if (code === 'MAX_REDEMPTIONS_BELOW_USAGE') {\n return new MaxRedemptionsBelowUsageError(url, message);\n }\n if (code === 'DISCOUNT_IN_USE') return new DiscountInUseError(url, message);\n if (code === 'PRODUCT_INCOMPLETE') {\n return new ProductIncompleteError(url, body.missing ?? [], message);\n }\n if (code === 'INVALID_IMAGE' || code === 'INVALID_IMAGE_ORDER') {\n return new InvalidImageError(url, code, message);\n }\n return new AdminApiError(res.status, url, code, message);\n}\n","import { AdminUnauthorizedError } from './errors';\nimport { mapError } from './map-error';\n\nexport interface AdminClientOptions {\n baseUrl: string;\n fetch?: typeof fetch;\n headers?: () => HeadersInit | Promise<HeadersInit>;\n onUnauthorized?: (error: AdminUnauthorizedError) => void;\n}\n\ntype Schema<T> = { parse(data: unknown): T };\n\nexport interface RequestOptions {\n method?: string;\n body?: unknown;\n form?: FormData;\n headers?: Record<string, string>;\n}\n\nexport interface Transport {\n request<T>(\n path: string,\n schema: Schema<T>,\n options?: RequestOptions,\n ): Promise<T>;\n}\n\nexport function createTransport({\n baseUrl,\n fetch: fetchImpl = (...args) => globalThis.fetch(...args),\n headers: getHeaders,\n onUnauthorized,\n}: AdminClientOptions): Transport {\n const root = baseUrl.replace(/\\/+$/, '');\n\n return {\n async request(path, schema, { method = 'GET', body, form, headers } = {}) {\n const url = `${root}${path}`;\n const merged = new Headers(getHeaders ? await getHeaders() : undefined);\n merged.set('accept', 'application/json');\n if (body !== undefined) merged.set('content-type', 'application/json');\n for (const [name, value] of Object.entries(headers ?? {})) {\n merged.set(name, value);\n }\n const res = await fetchImpl(url, {\n method,\n headers: merged,\n body: form ?? (body === undefined ? undefined : JSON.stringify(body)),\n });\n if (!res.ok) {\n const error = await mapError(url, res);\n if (error instanceof AdminUnauthorizedError) {\n try {\n onUnauthorized?.(error);\n } catch {\n // A host callback failure must not replace the 401 the caller expects.\n }\n }\n throw error;\n }\n return schema.parse(await res.json());\n },\n };\n}\n","import {\n adminDiscountPageSchema,\n adminOrderDetailSchema,\n adminOrderPageSchema,\n adminProductCountsSchema,\n adminProductPageSchema,\n adminProductSchema,\n discountSchema,\n shippingRateSchema,\n type AdminDiscountListQuery,\n type AdminDiscountPage,\n type AdminOrderDetail,\n type AdminOrderListQuery,\n type AdminProductCounts,\n type AdminOrderPage,\n type AdminProduct,\n type AdminProductListQuery,\n type AdminProductPage,\n type AdminProductInput,\n type AdminProductPatch,\n type Discount,\n type DiscountInput,\n type DiscountPatch,\n type RefundOrderInput,\n type ProductImagePatch,\n type ShippingRate,\n type ShippingRateInput,\n type ShipOrderInput,\n} from '@develemit/commerce-contracts';\nimport { createTransport, type AdminClientOptions } from './transport';\n\nexport type AdminOrderQuery = Partial<\n Pick<AdminOrderListQuery, 'status' | 'q' | 'hasPendingRefund' | 'cursor'>\n> & { limit?: number };\n\nexport type AdminProductQuery = Pick<\n AdminProductListQuery,\n | 'status'\n | 'excludeArchived'\n | 'incomplete'\n | 'stock'\n | 'q'\n | 'cursor'\n | 'limit'\n>;\n\nexport type AdminDiscountQuery = Partial<\n Pick<AdminDiscountListQuery, 'status' | 'q' | 'cursor' | 'limit'>\n>;\n\nexport interface RefundOptions {\n idempotencyKey?: string;\n}\n\nexport interface AdminClient {\n listProducts(query?: AdminProductQuery): Promise<AdminProductPage>;\n getProductCounts(): Promise<AdminProductCounts>;\n getProduct(id: string): Promise<AdminProduct>;\n createProduct(input: AdminProductInput): Promise<AdminProduct>;\n updateProduct(id: string, patch: AdminProductPatch): Promise<AdminProduct>;\n uploadProductImage(\n id: string,\n file: Blob,\n alt?: string,\n ): Promise<AdminProduct>;\n reorderProductImages(id: string, imageIds: string[]): Promise<AdminProduct>;\n updateProductImage(\n id: string,\n imageId: string,\n patch: ProductImagePatch,\n ): Promise<AdminProduct>;\n deleteProductImage(id: string, imageId: string): Promise<AdminProduct>;\n listDiscounts(query?: AdminDiscountQuery): Promise<AdminDiscountPage>;\n getDiscount(id: string): Promise<Discount>;\n createDiscount(input: DiscountInput): Promise<Discount>;\n updateDiscount(id: string, patch: DiscountPatch): Promise<Discount>;\n listShippingRates(): Promise<ShippingRate[]>;\n replaceShippingRates(rates: ShippingRateInput[]): Promise<ShippingRate[]>;\n listOrders(query?: AdminOrderQuery): Promise<AdminOrderPage>;\n getOrder(id: string): Promise<AdminOrderDetail>;\n shipOrder(id: string, input?: ShipOrderInput): Promise<AdminOrderDetail>;\n resolveOrder(id: string): Promise<AdminOrderDetail>;\n /**\n * Retrying the same intent must reuse the same key. When none is passed one\n * is generated, and it is set on any thrown error as `idempotencyKey` so the\n * caller can pass it back on retry.\n */\n refundOrder(\n id: string,\n input?: RefundOrderInput,\n options?: RefundOptions,\n ): Promise<AdminOrderDetail>;\n}\n\nconst enc = encodeURIComponent;\n\nfunction queryString(query: object): string {\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined) params.set(key, String(value));\n }\n const qs = params.toString();\n return qs ? `?${qs}` : '';\n}\n\nexport function createAdminClient(options: AdminClientOptions): AdminClient {\n const { request } = createTransport(options);\n const product = adminProductSchema;\n const discount = discountSchema;\n const rates = shippingRateSchema.array();\n\n return {\n listProducts: (query = {}) =>\n request(`/admin/products${queryString(query)}`, adminProductPageSchema),\n getProductCounts: () =>\n request('/admin/products/counts', adminProductCountsSchema),\n getProduct: (id) => request(`/admin/products/${enc(id)}`, product),\n createProduct: (input) =>\n request('/admin/products', product, { method: 'POST', body: input }),\n updateProduct: (id, patch) =>\n request(`/admin/products/${enc(id)}`, product, {\n method: 'PATCH',\n body: patch,\n }),\n uploadProductImage(id, file, alt) {\n const form = new FormData();\n if (alt !== undefined) form.append('alt', alt);\n form.append('file', file);\n return request(`/admin/products/${enc(id)}/images`, product, {\n method: 'POST',\n form,\n });\n },\n reorderProductImages: (id, imageIds) =>\n request(`/admin/products/${enc(id)}/images/order`, product, {\n method: 'PATCH',\n body: { imageIds },\n }),\n updateProductImage: (id, imageId, patch) =>\n request(`/admin/products/${enc(id)}/images/${enc(imageId)}`, product, {\n method: 'PATCH',\n body: patch,\n }),\n deleteProductImage: (id, imageId) =>\n request(`/admin/products/${enc(id)}/images/${enc(imageId)}`, product, {\n method: 'DELETE',\n }),\n listDiscounts: (query = {}) =>\n request(`/admin/discounts${queryString(query)}`, adminDiscountPageSchema),\n getDiscount: (id) => request(`/admin/discounts/${enc(id)}`, discount),\n createDiscount: (input) =>\n request('/admin/discounts', discount, { method: 'POST', body: input }),\n updateDiscount: (id, patch) =>\n request(`/admin/discounts/${enc(id)}`, discount, {\n method: 'PATCH',\n body: patch,\n }),\n listShippingRates: () => request('/admin/shipping-rates', rates),\n replaceShippingRates: (input) =>\n request('/admin/shipping-rates', rates, { method: 'PUT', body: input }),\n listOrders: (query = {}) =>\n request(`/admin/orders${queryString(query)}`, adminOrderPageSchema),\n getOrder: (id) =>\n request(`/admin/orders/${enc(id)}`, adminOrderDetailSchema),\n shipOrder: (id, input = {}) =>\n request(`/admin/orders/${enc(id)}/ship`, adminOrderDetailSchema, {\n method: 'POST',\n body: input,\n }),\n resolveOrder: (id) =>\n request(`/admin/orders/${enc(id)}/resolve`, adminOrderDetailSchema, {\n method: 'POST',\n }),\n async refundOrder(id, input = { restock: false }, refund = {}) {\n const key = refund.idempotencyKey ?? crypto.randomUUID();\n try {\n return await request(\n `/admin/orders/${enc(id)}/refunds`,\n adminOrderDetailSchema,\n {\n method: 'POST',\n body: input,\n headers: { 'idempotency-key': key },\n },\n );\n } catch (err) {\n if (err instanceof Error) {\n (err as Error & { idempotencyKey?: string }).idempotencyKey = key;\n }\n throw err;\n }\n },\n };\n}\n"],"mappings":"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"}