@sayren/store-sdk 0.5.0 → 0.6.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/dist/index.d.mts CHANGED
@@ -976,11 +976,14 @@ export declare const claimSchema: z.ZodObject<{
976
976
  }, z.core.$strip>>;
977
977
  requestedAt: z.ZodString;
978
978
  completedAt: z.ZodNullable<z.ZodString>;
979
+ holdExpiresAt: z.ZodNullable<z.ZodString>;
980
+ holdUsed: z.ZodBoolean;
979
981
  }, z.core.$strip>;
980
982
  export type Claim = z.infer<typeof claimSchema>;
981
983
  export interface ClaimListParams extends PageParams {
982
984
  type?: ClaimType;
983
- status?: ClaimStatus;
985
+ /** 여러 상태를 한 번에 거를 수 있다(처리 대기 목록 등) */
986
+ status?: ClaimStatus | ClaimStatus[];
984
987
  orderItemId?: string;
985
988
  requestedFrom?: string;
986
989
  requestedTo?: string;
@@ -994,17 +997,7 @@ export declare const claimListQuerySchema: z.ZodObject<{
994
997
  EXCHANGE: "EXCHANGE";
995
998
  CANCEL: "CANCEL";
996
999
  }>>;
997
- status: z.ZodOptional<z.ZodEnum<{
998
- REQUESTED: "REQUESTED";
999
- HELD: "HELD";
1000
- COLLECTING: "COLLECTING";
1001
- COLLECTED: "COLLECTED";
1002
- REDELIVERING: "REDELIVERING";
1003
- APPROVED: "APPROVED";
1004
- REJECTED: "REJECTED";
1005
- COMPLETED: "COMPLETED";
1006
- WITHDRAWN: "WITHDRAWN";
1007
- }>>;
1000
+ status: z.ZodOptional<z.ZodString>;
1008
1001
  orderItemId: z.ZodOptional<z.ZodString>;
1009
1002
  requestedFrom: z.ZodOptional<z.ZodString>;
1010
1003
  requestedTo: z.ZodOptional<z.ZodString>;
@@ -1061,6 +1054,8 @@ export declare const claimDetailSchema: z.ZodObject<{
1061
1054
  }, z.core.$strip>>;
1062
1055
  requestedAt: z.ZodString;
1063
1056
  completedAt: z.ZodNullable<z.ZodString>;
1057
+ holdExpiresAt: z.ZodNullable<z.ZodString>;
1058
+ holdUsed: z.ZodBoolean;
1064
1059
  histories: z.ZodOptional<z.ZodArray<z.ZodObject<{
1065
1060
  status: z.ZodEnum<{
1066
1061
  REQUESTED: "REQUESTED";
@@ -1245,7 +1240,7 @@ export declare const withdrawCustomerRequestSchema: z.ZodObject<{
1245
1240
  memo: z.ZodOptional<z.ZodString>;
1246
1241
  }, z.core.$strip>;
1247
1242
  export type WithdrawCustomerRequest = z.infer<typeof withdrawCustomerRequestSchema>;
1248
- /** `WITHDRAWAL_BLOCKED`의 `error.details` — 탈퇴를 막는 항목 수(스토어프런트 탈퇴와 같다) */
1243
+ /** `WITHDRAWAL_BLOCKED`의 `error.details` — 탈퇴를 막는 항목 수(스토어프론트 탈퇴와 같다) */
1249
1244
  export declare const customerWithdrawalBlockedDetailsSchema: z.ZodObject<{
1250
1245
  inProgressOrderItems: z.ZodNumber;
1251
1246
  openClaims: z.ZodNumber;
@@ -3542,7 +3537,7 @@ export declare function isReservedStoreCode(code: string): boolean;
3542
3537
  export declare const storeCodeSchema: z.ZodString;
3543
3538
  /** `https://shop.example.com`처럼 경로·쿼리 없는 http(s) 오리진인가 */
3544
3539
  export declare function isWebOrigin(value: string): boolean;
3545
- /** 방문 분석을 보낼 수 있는 스토어프런트 오리진 — 스킴·호스트(·포트)만. 서버가 소문자·끝 슬래시 제거로 정규화한다 */
3540
+ /** 방문 분석을 보낼 수 있는 스토어프론트 오리진 — 스킴·호스트(·포트)만. 서버가 소문자·끝 슬래시 제거로 정규화한다 */
3546
3541
  export declare const analyticsOriginSchema: z.ZodString;
3547
3542
  /** 허용 오리진 상한 */
3548
3543
  export declare const MAX_ANALYTICS_ALLOWED_ORIGINS = 20;
@@ -4589,6 +4584,8 @@ export declare function createStoreClient(options: StoreClientOptions): {
4589
4584
  } | null;
4590
4585
  requestedAt: string;
4591
4586
  completedAt: string | null;
4587
+ holdExpiresAt: string | null;
4588
+ holdUsed: boolean;
4592
4589
  }[];
4593
4590
  }>;
4594
4591
  get: (claimId: string) => Promise<{
@@ -4615,6 +4612,8 @@ export declare function createStoreClient(options: StoreClientOptions): {
4615
4612
  } | null;
4616
4613
  requestedAt: string;
4617
4614
  completedAt: string | null;
4615
+ holdExpiresAt: string | null;
4616
+ holdUsed: boolean;
4618
4617
  histories?: {
4619
4618
  status: "REQUESTED" | "HELD" | "COLLECTING" | "COLLECTED" | "REDELIVERING" | "APPROVED" | "REJECTED" | "COMPLETED" | "WITHDRAWN";
4620
4619
  actor: "BUYER" | "SELLER" | "SYSTEM";
@@ -4639,6 +4638,34 @@ export declare function createStoreClient(options: StoreClientOptions): {
4639
4638
  holdExpiresAt: string;
4640
4639
  }>;
4641
4640
  releaseHold: (claimId: string) => Promise<void>;
4641
+ /** 교환 완료 — 재배송 중인 교환을 셀러가 명시적으로 끝낸다 */
4642
+ completeExchange: (claimId: string) => Promise<{
4643
+ claimId: string;
4644
+ type: "RETURN" | "EXCHANGE" | "CANCEL";
4645
+ status: "REQUESTED" | "HELD" | "COLLECTING" | "COLLECTED" | "REDELIVERING" | "APPROVED" | "REJECTED" | "COMPLETED" | "WITHDRAWN";
4646
+ orderId: string;
4647
+ orderItemId: string;
4648
+ productName: string;
4649
+ quantity: number;
4650
+ reason: "CHANGE_OF_MIND" | "WRONG_ORDER" | "DEFECTIVE" | "WRONG_DELIVERY" | "DIFFERENT_FROM_PAGE" | "DELAY";
4651
+ reasonDetail: string | null;
4652
+ responsibility: "BUYER" | "SELLER";
4653
+ claimDeliveryFee: number;
4654
+ expectedRefundAmount: number | null;
4655
+ exchangeOption: {
4656
+ optionId: string;
4657
+ optionName: string;
4658
+ } | null;
4659
+ collect: {
4660
+ method: "SELLER_PICKUP" | "BUYER_SEND";
4661
+ carrierCode: string | null;
4662
+ trackingNumber: string | null;
4663
+ } | null;
4664
+ requestedAt: string;
4665
+ completedAt: string | null;
4666
+ holdExpiresAt: string | null;
4667
+ holdUsed: boolean;
4668
+ }>;
4642
4669
  };
4643
4670
  inquiries: {
4644
4671
  list: (params?: PageParams & {
@@ -4993,7 +5020,7 @@ export declare function createStoreClient(options: StoreClientOptions): {
4993
5020
  }>;
4994
5021
  };
4995
5022
  /**
4996
- * 방문 분석 — 스코프 `analytics:r`. 스토어프런트가 `@sayren/storefront-sdk`로 수집한 이벤트를 Asia/Seoul 날짜별로
5023
+ * 방문 분석 — 스코프 `analytics:r`. 스토어프론트가 `@sayren/storefront-sdk`로 수집한 이벤트를 Asia/Seoul 날짜별로
4997
5024
  * 집계한 값이다. 집계는 주기적으로 갱신되고 응답 `lastComputedAt`이 마지막 집계 시각이다. 봇 세션은 빠진다.
4998
5025
  * 기간은 양끝 포함 최대 92일이고, 테스트 결제 구매는 `includeTest: "true"`일 때만 포함한다.
4999
5026
  */
@@ -6124,7 +6151,7 @@ export declare function createStoreClient(options: StoreClientOptions): {
6124
6151
  }>;
6125
6152
  /**
6126
6153
  * `PATCH /v1/store` — 스코프 `store:rw`. 바꿀 필드만 보낸다. `analyticsAllowedOrigins`는 방문 분석 수집을 받을
6127
- * 스토어프런트 오리진 목록이다(빈 배열이면 모든 오리진 허용).
6154
+ * 스토어프론트 오리진 목록이다(빈 배열이면 모든 오리진 허용).
6128
6155
  */
6129
6156
  update: (body: UpdateStoreRequest) => Promise<{
6130
6157
  storeId: string;
package/dist/index.mjs CHANGED
@@ -150,7 +150,7 @@ function createHttp(options) {
150
150
  /**
151
151
  * 방문 분석 조회 (관리 API `/v1/analytics/*`, 스코프 `analytics:r`).
152
152
  *
153
- * 스토어프런트가 `@sayren/storefront-sdk`로 수집한 이벤트를 서버가 날짜(Asia/Seoul)별로 집계한 값이다. 집계는 주기적으로
153
+ * 스토어프론트가 `@sayren/storefront-sdk`로 수집한 이벤트를 서버가 날짜(Asia/Seoul)별로 집계한 값이다. 집계는 주기적으로
154
154
  * 갱신되므로 오늘 값은 `lastComputedAt` 시점까지 반영돼 있다. 봇·자동화 브라우저의 세션은 모든 집계에서 빠진다.
155
155
  */
156
156
  const reportDate$1 = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "날짜 형식은 YYYY-MM-DD 입니다");
@@ -654,12 +654,16 @@ const claimSchema = z.object({
654
654
  trackingNumber: z.string().nullable()
655
655
  }).nullable(),
656
656
  requestedAt: z.string(),
657
- completedAt: z.string().nullable()
657
+ completedAt: z.string().nullable(),
658
+ /** 보류 중이면 자동 해제 시각(ISO 8601), 아니면 null */
659
+ holdExpiresAt: z.string().nullable(),
660
+ /** 보류를 이미 썼는지 — 보류는 클레임당 1회라 해제·만료 뒤에도 true */
661
+ holdUsed: z.boolean()
658
662
  });
659
663
  /** `GET /v1/claims` 쿼리 — OpenAPI 문서용 형태(값은 쿼리 문자열) */
660
664
  const claimListQuerySchema = z.object({
661
665
  type: claimTypeSchema.optional().describe("클레임 유형 필터"),
662
- status: claimStatusSchema.optional().describe("클레임 상태 필터"),
666
+ status: z.string().optional().describe("클레임 상태 필터. 쉼표로 여러 개를 줄 수 있다 (예: `REQUESTED,HELD,COLLECTED`)"),
663
667
  orderItemId: z.string().optional().describe("주문상품 id 필터"),
664
668
  requestedFrom: z.string().optional().describe("요청 시각 조회 시작 (ISO 8601, 포함)"),
665
669
  requestedTo: z.string().optional().describe("요청 시각 조회 끝 (ISO 8601, 포함)"),
@@ -798,7 +802,7 @@ const withdrawCustomerRequestSchema = z.object({
798
802
  ]).describe("처리 사유 — 구매자 요청·장기 미이용·부정 이용·기타. 감사 로그에 남는다"),
799
803
  memo: z.string().max(200).optional().describe("사유 보충(선택)")
800
804
  });
801
- /** `WITHDRAWAL_BLOCKED`의 `error.details` — 탈퇴를 막는 항목 수(스토어프런트 탈퇴와 같다) */
805
+ /** `WITHDRAWAL_BLOCKED`의 `error.details` — 탈퇴를 막는 항목 수(스토어프론트 탈퇴와 같다) */
802
806
  const customerWithdrawalBlockedDetailsSchema = z.object({
803
807
  inProgressOrderItems: z.number().int(),
804
808
  openClaims: z.number().int(),
@@ -816,7 +820,7 @@ const loginProviderSchema = z.enum([
816
820
  const loginProviderStatusSchema = z.object({
817
821
  provider: loginProviderSchema,
818
822
  connected: z.boolean(),
819
- /** 스토어프런트에서 사용 중인지. 연결 안 됐으면 false */
823
+ /** 스토어프론트에서 사용 중인지. 연결 안 됐으면 false */
820
824
  enabled: z.boolean(),
821
825
  clientIdPrefix: z.string().nullable().describe("클라이언트 ID(카카오 REST API 키) 앞 4자리"),
822
826
  secretPrefix: z.string().nullable(),
@@ -1600,10 +1604,10 @@ const productSummarySchema = z.object({
1600
1604
  productId: z.string(),
1601
1605
  name: z.string(),
1602
1606
  status: productStatusSchema,
1603
- salePrice: z.number().int(),
1604
- discountedPrice: z.number().int().nullable(),
1607
+ salePrice: z.number().int().describe("판매가. 원(KRW) 단위 정수"),
1608
+ discountedPrice: z.number().int().nullable().describe("즉시 할인 적용가. 원 단위. 할인이 없으면 null"),
1605
1609
  /** usable variant 재고 합계 (서버 계산) */
1606
- stockQuantity: z.number().int(),
1610
+ stockQuantity: z.number().int().describe("판매 가능한 옵션 재고의 합계. 서버가 계산한다"),
1607
1611
  categoryId: z.string().nullable(),
1608
1612
  thumbnailUrl: z.url().optional(),
1609
1613
  /** optionGroups.length > 0 */
@@ -1740,8 +1744,8 @@ const variantStockSchema = z.object({
1740
1744
  const productCreateRequestSchema = z.object({
1741
1745
  name: z.string().min(1).max(100),
1742
1746
  categoryId: z.string().min(1, "카테고리를 선택해주세요"),
1743
- salePrice: z.number().int().min(10).multipleOf(10, "판매가는 10원 단위여야 합니다 (INVALID_PRICE_UNIT)"),
1744
- originalPrice: z.number().int().optional(),
1747
+ salePrice: z.number().int().min(10).multipleOf(10, "판매가는 10원 단위여야 합니다 (INVALID_PRICE_UNIT)").describe("판매가. 원(KRW) 단위 정수, 최소 10원, 10원 단위"),
1748
+ originalPrice: z.number().int().optional().describe("정가(할인 전 표시 가격). 원 단위"),
1745
1749
  description: z.string().optional(),
1746
1750
  /**
1747
1751
  * 상세설명 에디터(@avarlabs/editor)의 직렬화 상태. 재편집 때 이 값으로 문서를 복원한다.
@@ -1753,11 +1757,11 @@ const productCreateRequestSchema = z.object({
1753
1757
  attributeId: z.string(),
1754
1758
  value: z.string()
1755
1759
  })).optional(),
1756
- deliveryType: deliveryTypeSchema.default("PAID"),
1757
- deliveryFee: z.number().int().default(0),
1758
- conditionalFreeAmount: z.number().int().optional(),
1759
- returnFee: z.number().int().default(0),
1760
- exchangeFee: z.number().int().default(0),
1760
+ deliveryType: deliveryTypeSchema.default("PAID").describe("배송비 유형. FREE 무료, PAID 유료, CONDITIONAL_FREE 조건부 무료"),
1761
+ deliveryFee: z.number().int().default(0).describe("배송비. 원 단위"),
1762
+ conditionalFreeAmount: z.number().int().optional().describe("CONDITIONAL_FREE일 때 무료 배송이 되는 주문 금액. 원 단위"),
1763
+ returnFee: z.number().int().default(0).describe("반품 배송비. 원 단위"),
1764
+ exchangeFee: z.number().int().default(0).describe("교환 배송비. 원 단위"),
1761
1765
  shippingAddressId: z.string().optional(),
1762
1766
  returnAddressId: z.string().optional()
1763
1767
  }).extend(optionModelRequestSchema.shape);
@@ -1873,8 +1877,8 @@ function isWebOrigin(value) {
1873
1877
  return false;
1874
1878
  }
1875
1879
  }
1876
- /** 방문 분석을 보낼 수 있는 스토어프런트 오리진 — 스킴·호스트(·포트)만. 서버가 소문자·끝 슬래시 제거로 정규화한다 */
1877
- const analyticsOriginSchema = z.string().trim().max(255).refine(isWebOrigin, "https://shop.example.com 형식(경로 없이)으로 입력해 주세요").describe("스토어프런트 오리진. 예: `https://shop.example.com`");
1880
+ /** 방문 분석을 보낼 수 있는 스토어프론트 오리진 — 스킴·호스트(·포트)만. 서버가 소문자·끝 슬래시 제거로 정규화한다 */
1881
+ const analyticsOriginSchema = z.string().trim().max(255).refine(isWebOrigin, "https://shop.example.com 형식(경로 없이)으로 입력해 주세요").describe("스토어프론트 오리진. 예: `https://shop.example.com`");
1878
1882
  /** 허용 오리진 상한 */
1879
1883
  const MAX_ANALYTICS_ALLOWED_ORIGINS = 20;
1880
1884
  /** `PATCH /v1/store` 본문 — 바꿀 필드만 보낸다 */
@@ -1883,8 +1887,8 @@ const updateStoreRequestSchema = z.object({
1883
1887
  logoUrl: z.url().optional(),
1884
1888
  customerCenterPhone: z.string().optional(),
1885
1889
  businessHours: z.string().max(100).optional(),
1886
- analyticsAllowedOrigins: z.array(analyticsOriginSchema).max(20).optional().describe("@deprecated `storefrontOrigins`를 쓴다(같은 목록). 방문 분석 수집을 받을 스토어프런트 오리진(최대 20개). 비우면 모든 오리진에서 받는다. 넣으면 목록에 없는 오리진의 수집 요청은 403 `ORIGIN_NOT_ALLOWED`이고, 페이지 URL이 목록 밖인 이벤트는 버린다"),
1887
- storefrontOrigins: z.array(analyticsOriginSchema).max(20).optional().describe("스토어프런트 도메인(최대 20개) — 소셜 로그인 뒤 돌아갈 주소와 방문 분석 수집을 함께 제한한다. `analyticsAllowedOrigins`와 같은 목록이다(둘 다 주면 이 값이 이긴다)"),
1890
+ analyticsAllowedOrigins: z.array(analyticsOriginSchema).max(20).optional().describe("@deprecated `storefrontOrigins`를 쓴다(같은 목록). 방문 분석 수집을 받을 스토어프론트 오리진(최대 20개). 비우면 모든 오리진에서 받는다. 넣으면 목록에 없는 오리진의 수집 요청은 403 `ORIGIN_NOT_ALLOWED`이고, 페이지 URL이 목록 밖인 이벤트는 버린다"),
1891
+ storefrontOrigins: z.array(analyticsOriginSchema).max(20).optional().describe("스토어프론트 도메인(최대 20개) — 소셜 로그인 뒤 돌아갈 주소와 방문 분석 수집을 함께 제한한다. `analyticsAllowedOrigins`와 같은 목록이다(둘 다 주면 이 값이 이긴다)"),
1888
1892
  guestCheckoutEnabled: z.boolean().optional().describe("비회원 주문 허용. false(회원만)면 로그인하지 않은 구매자의 주문서 생성·결제 요청이 403 `GUEST_CHECKOUT_DISABLED`다. 장바구니 담기와 이미 받은 비회원 주문의 조회·취소는 막지 않는다")
1889
1893
  }).refine((value) => Object.values(value).some((v) => v !== void 0), { message: "최소 1개 필드가 필요합니다" });
1890
1894
  const storeSchema = z.object({
@@ -1900,8 +1904,8 @@ const storeSchema = z.object({
1900
1904
  logoUrl: z.url().nullable(),
1901
1905
  businessNumber: z.string().nullable(),
1902
1906
  customerCenterPhone: z.string().nullable(),
1903
- analyticsAllowedOrigins: z.array(z.string()).describe("방문 분석 수집을 받는 스토어프런트 오리진. 비어 있으면 모든 오리진에서 받는다"),
1904
- storefrontOrigins: z.array(z.string()).describe("스토어프런트 도메인 — 소셜 로그인 리디렉트와 방문 분석 수집이 함께 쓴다(`analyticsAllowedOrigins`와 같은 값)"),
1907
+ analyticsAllowedOrigins: z.array(z.string()).describe("방문 분석 수집을 받는 스토어프론트 오리진. 비어 있으면 모든 오리진에서 받는다"),
1908
+ storefrontOrigins: z.array(z.string()).describe("스토어프론트 도메인 — 소셜 로그인 리디렉트와 방문 분석 수집이 함께 쓴다(`analyticsAllowedOrigins`와 같은 값)"),
1905
1909
  guestCheckoutEnabled: z.boolean().describe("비회원 주문 허용. false면 회원만 주문할 수 있다"),
1906
1910
  memberCount: z.number().int(),
1907
1911
  createdAt: z.string()
@@ -2188,7 +2192,10 @@ function createStoreClient(options) {
2188
2192
  },
2189
2193
  carriers: { list: () => storeHttp.request("GET", "/carriers", z.array(carrierSchema)) },
2190
2194
  claims: {
2191
- list: (params) => storeHttp.request("GET", "/claims", pageSchema(claimSchema), { query: params }),
2195
+ list: (params) => storeHttp.request("GET", "/claims", pageSchema(claimSchema), { query: {
2196
+ ...params,
2197
+ status: Array.isArray(params?.status) ? params.status.join(",") : params?.status
2198
+ } }),
2192
2199
  get: (claimId) => storeHttp.request("GET", path`/claims/${claimId}`, claimDetailSchema),
2193
2200
  approve: (claimId, deductAmount, idempotencyKey) => storeHttp.request("POST", path`/claims/${claimId}/approve`, approveClaimResultSchema, {
2194
2201
  body: deductAmount !== void 0 ? { deductAmount } : {},
@@ -2202,7 +2209,9 @@ function createStoreClient(options) {
2202
2209
  trackingNumber
2203
2210
  } }),
2204
2211
  hold: (claimId, reason) => storeHttp.request("POST", path`/claims/${claimId}/hold`, claimHoldResultSchema, { body: { reason } }),
2205
- releaseHold: (claimId) => storeHttp.requestVoid("DELETE", path`/claims/${claimId}/hold`)
2212
+ releaseHold: (claimId) => storeHttp.requestVoid("DELETE", path`/claims/${claimId}/hold`),
2213
+ /** 교환 완료 — 재배송 중인 교환을 셀러가 명시적으로 끝낸다 */
2214
+ completeExchange: (claimId) => storeHttp.request("POST", path`/claims/${claimId}/complete-exchange`, claimSchema)
2206
2215
  },
2207
2216
  inquiries: {
2208
2217
  list: (params) => storeHttp.request("GET", "/inquiries", pageSchema(inquirySchema), { query: params }),
@@ -2258,7 +2267,7 @@ function createStoreClient(options) {
2258
2267
  */
2259
2268
  get: (params) => storeHttp.request("GET", "/sales-report", salesReportSchema, { query: salesReportQuerySchema.parse(params) }) },
2260
2269
  /**
2261
- * 방문 분석 — 스코프 `analytics:r`. 스토어프런트가 `@sayren/storefront-sdk`로 수집한 이벤트를 Asia/Seoul 날짜별로
2270
+ * 방문 분석 — 스코프 `analytics:r`. 스토어프론트가 `@sayren/storefront-sdk`로 수집한 이벤트를 Asia/Seoul 날짜별로
2262
2271
  * 집계한 값이다. 집계는 주기적으로 갱신되고 응답 `lastComputedAt`이 마지막 집계 시각이다. 봇 세션은 빠진다.
2263
2272
  * 기간은 양끝 포함 최대 92일이고, 테스트 결제 구매는 `includeTest: "true"`일 때만 포함한다.
2264
2273
  */
@@ -2414,7 +2423,7 @@ get: (params) => storeHttp.request("GET", "/sales-report", salesReportSchema, {
2414
2423
  get: () => storeHttp.request("GET", "/store", storeSchema),
2415
2424
  /**
2416
2425
  * `PATCH /v1/store` — 스코프 `store:rw`. 바꿀 필드만 보낸다. `analyticsAllowedOrigins`는 방문 분석 수집을 받을
2417
- * 스토어프런트 오리진 목록이다(빈 배열이면 모든 오리진 허용).
2426
+ * 스토어프론트 오리진 목록이다(빈 배열이면 모든 오리진 허용).
2418
2427
  */
2419
2428
  update: (body) => storeHttp.request("PATCH", "/store", storeSchema, { body: updateStoreRequestSchema.parse(body) }),
2420
2429
  listMembers: () => storeHttp.request("GET", "/store/members", z.array(storeMemberSchema)),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sayren/store-sdk",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "main": "./dist/index.mjs",
5
5
  "types": "./dist/index.d.mts",
6
6
  "exports": {
package/src/client.ts CHANGED
@@ -533,7 +533,12 @@ export function createStoreClient(options: StoreClientOptions) {
533
533
 
534
534
  claims: {
535
535
  list: (params?: ClaimListParams) =>
536
- storeHttp.request("GET", "/claims", pageSchema(claimSchema), { query: params as Query }),
536
+ storeHttp.request("GET", "/claims", pageSchema(claimSchema), {
537
+ query: {
538
+ ...params,
539
+ status: Array.isArray(params?.status) ? params.status.join(",") : params?.status,
540
+ } as Query,
541
+ }),
537
542
  get: (claimId: string) =>
538
543
  storeHttp.request("GET", path`/claims/${claimId}`, claimDetailSchema),
539
544
  approve: (claimId: string, deductAmount?: number, idempotencyKey?: string) =>
@@ -561,6 +566,9 @@ export function createStoreClient(options: StoreClientOptions) {
561
566
  }),
562
567
  releaseHold: (claimId: string) =>
563
568
  storeHttp.requestVoid("DELETE", path`/claims/${claimId}/hold`),
569
+ /** 교환 완료 — 재배송 중인 교환을 셀러가 명시적으로 끝낸다 */
570
+ completeExchange: (claimId: string) =>
571
+ storeHttp.request("POST", path`/claims/${claimId}/complete-exchange`, claimSchema),
564
572
  },
565
573
 
566
574
  inquiries: {
@@ -691,7 +699,7 @@ export function createStoreClient(options: StoreClientOptions) {
691
699
  },
692
700
 
693
701
  /**
694
- * 방문 분석 — 스코프 `analytics:r`. 스토어프런트가 `@sayren/storefront-sdk`로 수집한 이벤트를 Asia/Seoul 날짜별로
702
+ * 방문 분석 — 스코프 `analytics:r`. 스토어프론트가 `@sayren/storefront-sdk`로 수집한 이벤트를 Asia/Seoul 날짜별로
695
703
  * 집계한 값이다. 집계는 주기적으로 갱신되고 응답 `lastComputedAt`이 마지막 집계 시각이다. 봇 세션은 빠진다.
696
704
  * 기간은 양끝 포함 최대 92일이고, 테스트 결제 구매는 `includeTest: "true"`일 때만 포함한다.
697
705
  */
@@ -944,7 +952,7 @@ export function createStoreClient(options: StoreClientOptions) {
944
952
  get: () => storeHttp.request("GET", "/store", storeSchema),
945
953
  /**
946
954
  * `PATCH /v1/store` — 스코프 `store:rw`. 바꿀 필드만 보낸다. `analyticsAllowedOrigins`는 방문 분석 수집을 받을
947
- * 스토어프런트 오리진 목록이다(빈 배열이면 모든 오리진 허용).
955
+ * 스토어프론트 오리진 목록이다(빈 배열이면 모든 오리진 허용).
948
956
  */
949
957
  update: (body: UpdateStoreRequest) =>
950
958
  storeHttp.request("PATCH", "/store", storeSchema, {
@@ -3,7 +3,7 @@ import { z } from "zod";
3
3
  /**
4
4
  * 방문 분석 조회 (관리 API `/v1/analytics/*`, 스코프 `analytics:r`).
5
5
  *
6
- * 스토어프런트가 `@sayren/storefront-sdk`로 수집한 이벤트를 서버가 날짜(Asia/Seoul)별로 집계한 값이다. 집계는 주기적으로
6
+ * 스토어프론트가 `@sayren/storefront-sdk`로 수집한 이벤트를 서버가 날짜(Asia/Seoul)별로 집계한 값이다. 집계는 주기적으로
7
7
  * 갱신되므로 오늘 값은 `lastComputedAt` 시점까지 반영돼 있다. 봇·자동화 브라우저의 세션은 모든 집계에서 빠진다.
8
8
  */
9
9
 
@@ -53,13 +53,18 @@ export const claimSchema = z.object({
53
53
  .nullable(),
54
54
  requestedAt: z.string(),
55
55
  completedAt: z.string().nullable(),
56
+ /** 보류 중이면 자동 해제 시각(ISO 8601), 아니면 null */
57
+ holdExpiresAt: z.string().nullable(),
58
+ /** 보류를 이미 썼는지 — 보류는 클레임당 1회라 해제·만료 뒤에도 true */
59
+ holdUsed: z.boolean(),
56
60
  });
57
61
 
58
62
  export type Claim = z.infer<typeof claimSchema>;
59
63
 
60
64
  export interface ClaimListParams extends PageParams {
61
65
  type?: ClaimType;
62
- status?: ClaimStatus;
66
+ /** 여러 상태를 한 번에 거를 수 있다(처리 대기 목록 등) */
67
+ status?: ClaimStatus | ClaimStatus[];
63
68
  orderItemId?: string;
64
69
  requestedFrom?: string;
65
70
  requestedTo?: string;
@@ -68,7 +73,10 @@ export interface ClaimListParams extends PageParams {
68
73
  /** `GET /v1/claims` 쿼리 — OpenAPI 문서용 형태(값은 쿼리 문자열) */
69
74
  export const claimListQuerySchema = z.object({
70
75
  type: claimTypeSchema.optional().describe("클레임 유형 필터"),
71
- status: claimStatusSchema.optional().describe("클레임 상태 필터"),
76
+ status: z
77
+ .string()
78
+ .optional()
79
+ .describe("클레임 상태 필터. 쉼표로 여러 개를 줄 수 있다 (예: `REQUESTED,HELD,COLLECTED`)"),
72
80
  orderItemId: z.string().optional().describe("주문상품 id 필터"),
73
81
  requestedFrom: z.string().optional().describe("요청 시각 조회 시작 (ISO 8601, 포함)"),
74
82
  requestedTo: z.string().optional().describe("요청 시각 조회 끝 (ISO 8601, 포함)"),
@@ -115,7 +115,7 @@ export const withdrawCustomerRequestSchema = z.object({
115
115
  });
116
116
  export type WithdrawCustomerRequest = z.infer<typeof withdrawCustomerRequestSchema>;
117
117
 
118
- /** `WITHDRAWAL_BLOCKED`의 `error.details` — 탈퇴를 막는 항목 수(스토어프런트 탈퇴와 같다) */
118
+ /** `WITHDRAWAL_BLOCKED`의 `error.details` — 탈퇴를 막는 항목 수(스토어프론트 탈퇴와 같다) */
119
119
  export const customerWithdrawalBlockedDetailsSchema = z.object({
120
120
  inProgressOrderItems: z.number().int(),
121
121
  openClaims: z.number().int(),
@@ -8,7 +8,7 @@ export type LoginProvider = z.infer<typeof loginProviderSchema>;
8
8
  export const loginProviderStatusSchema = z.object({
9
9
  provider: loginProviderSchema,
10
10
  connected: z.boolean(),
11
- /** 스토어프런트에서 사용 중인지. 연결 안 됐으면 false */
11
+ /** 스토어프론트에서 사용 중인지. 연결 안 됐으면 false */
12
12
  enabled: z.boolean(),
13
13
  clientIdPrefix: z.string().nullable().describe("클라이언트 ID(카카오 REST API 키) 앞 4자리"),
14
14
  secretPrefix: z.string().nullable(),
@@ -13,10 +13,14 @@ export const productSummarySchema = z.object({
13
13
  productId: z.string(),
14
14
  name: z.string(),
15
15
  status: productStatusSchema,
16
- salePrice: z.number().int(),
17
- discountedPrice: z.number().int().nullable(),
16
+ salePrice: z.number().int().describe("판매가. 원(KRW) 단위 정수"),
17
+ discountedPrice: z
18
+ .number()
19
+ .int()
20
+ .nullable()
21
+ .describe("즉시 할인 적용가. 원 단위. 할인이 없으면 null"),
18
22
  /** usable variant 재고 합계 (서버 계산) */
19
- stockQuantity: z.number().int(),
23
+ stockQuantity: z.number().int().describe("판매 가능한 옵션 재고의 합계. 서버가 계산한다"),
20
24
  categoryId: z.string().nullable(),
21
25
  thumbnailUrl: z.url().optional(),
22
26
  /** optionGroups.length > 0 */
@@ -199,8 +203,9 @@ export const productCreateRequestSchema = z
199
203
  .number()
200
204
  .int()
201
205
  .min(10)
202
- .multipleOf(10, "판매가는 10원 단위여야 합니다 (INVALID_PRICE_UNIT)"),
203
- originalPrice: z.number().int().optional(),
206
+ .multipleOf(10, "판매가는 10원 단위여야 합니다 (INVALID_PRICE_UNIT)")
207
+ .describe("판매가. 원(KRW) 단위 정수, 최소 10원, 10원 단위"),
208
+ originalPrice: z.number().int().optional().describe("정가(할인 전 표시 가격). 원 단위"),
204
209
  description: z.string().optional(),
205
210
  /**
206
211
  * 상세설명 에디터(@avarlabs/editor)의 직렬화 상태. 재편집 때 이 값으로 문서를 복원한다.
@@ -209,11 +214,17 @@ export const productCreateRequestSchema = z
209
214
  descriptionJson: z.string().nullable().optional(),
210
215
  images: z.array(z.url()).min(1).max(10).optional(),
211
216
  attributes: z.array(z.object({ attributeId: z.string(), value: z.string() })).optional(),
212
- deliveryType: deliveryTypeSchema.default("PAID"),
213
- deliveryFee: z.number().int().default(0),
214
- conditionalFreeAmount: z.number().int().optional(),
215
- returnFee: z.number().int().default(0),
216
- exchangeFee: z.number().int().default(0),
217
+ deliveryType: deliveryTypeSchema
218
+ .default("PAID")
219
+ .describe("배송비 유형. FREE 무료, PAID 유료, CONDITIONAL_FREE 조건부 무료"),
220
+ deliveryFee: z.number().int().default(0).describe("배송비. 원 단위"),
221
+ conditionalFreeAmount: z
222
+ .number()
223
+ .int()
224
+ .optional()
225
+ .describe("CONDITIONAL_FREE일 때 무료 배송이 되는 주문 금액. 원 단위"),
226
+ returnFee: z.number().int().default(0).describe("반품 배송비. 원 단위"),
227
+ exchangeFee: z.number().int().default(0).describe("교환 배송비. 원 단위"),
217
228
  shippingAddressId: z.string().optional(),
218
229
  returnAddressId: z.string().optional(),
219
230
  })
@@ -91,13 +91,13 @@ export function isWebOrigin(value: string): boolean {
91
91
  }
92
92
  }
93
93
 
94
- /** 방문 분석을 보낼 수 있는 스토어프런트 오리진 — 스킴·호스트(·포트)만. 서버가 소문자·끝 슬래시 제거로 정규화한다 */
94
+ /** 방문 분석을 보낼 수 있는 스토어프론트 오리진 — 스킴·호스트(·포트)만. 서버가 소문자·끝 슬래시 제거로 정규화한다 */
95
95
  export const analyticsOriginSchema = z
96
96
  .string()
97
97
  .trim()
98
98
  .max(255)
99
99
  .refine(isWebOrigin, "https://shop.example.com 형식(경로 없이)으로 입력해 주세요")
100
- .describe("스토어프런트 오리진. 예: `https://shop.example.com`");
100
+ .describe("스토어프론트 오리진. 예: `https://shop.example.com`");
101
101
 
102
102
  /** 허용 오리진 상한 */
103
103
  export const MAX_ANALYTICS_ALLOWED_ORIGINS = 20;
@@ -114,7 +114,7 @@ export const updateStoreRequestSchema = z
114
114
  .max(MAX_ANALYTICS_ALLOWED_ORIGINS)
115
115
  .optional()
116
116
  .describe(
117
- "@deprecated `storefrontOrigins`를 쓴다(같은 목록). 방문 분석 수집을 받을 스토어프런트 오리진(최대 20개). 비우면 모든 오리진에서 받는다. " +
117
+ "@deprecated `storefrontOrigins`를 쓴다(같은 목록). 방문 분석 수집을 받을 스토어프론트 오리진(최대 20개). 비우면 모든 오리진에서 받는다. " +
118
118
  "넣으면 목록에 없는 오리진의 수집 요청은 403 `ORIGIN_NOT_ALLOWED`이고, 페이지 URL이 목록 밖인 이벤트는 버린다",
119
119
  ),
120
120
  storefrontOrigins: z
@@ -122,7 +122,7 @@ export const updateStoreRequestSchema = z
122
122
  .max(MAX_ANALYTICS_ALLOWED_ORIGINS)
123
123
  .optional()
124
124
  .describe(
125
- "스토어프런트 도메인(최대 20개) — 소셜 로그인 뒤 돌아갈 주소와 방문 분석 수집을 함께 제한한다. " +
125
+ "스토어프론트 도메인(최대 20개) — 소셜 로그인 뒤 돌아갈 주소와 방문 분석 수집을 함께 제한한다. " +
126
126
  "`analyticsAllowedOrigins`와 같은 목록이다(둘 다 주면 이 값이 이긴다)",
127
127
  ),
128
128
  guestCheckoutEnabled: z
@@ -149,11 +149,11 @@ export const storeSchema = z.object({
149
149
  customerCenterPhone: z.string().nullable(),
150
150
  analyticsAllowedOrigins: z
151
151
  .array(z.string())
152
- .describe("방문 분석 수집을 받는 스토어프런트 오리진. 비어 있으면 모든 오리진에서 받는다"),
152
+ .describe("방문 분석 수집을 받는 스토어프론트 오리진. 비어 있으면 모든 오리진에서 받는다"),
153
153
  storefrontOrigins: z
154
154
  .array(z.string())
155
155
  .describe(
156
- "스토어프런트 도메인 — 소셜 로그인 리디렉트와 방문 분석 수집이 함께 쓴다(`analyticsAllowedOrigins`와 같은 값)",
156
+ "스토어프론트 도메인 — 소셜 로그인 리디렉트와 방문 분석 수집이 함께 쓴다(`analyticsAllowedOrigins`와 같은 값)",
157
157
  ),
158
158
  guestCheckoutEnabled: z.boolean().describe("비회원 주문 허용. false면 회원만 주문할 수 있다"),
159
159
  memberCount: z.number().int(),