@sayren/store-sdk 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,6 +13,18 @@ export function pageSchema<T extends z.ZodType>(item: T) {
13
13
  return pageInfoSchema.extend({ contents: z.array(item) });
14
14
  }
15
15
 
16
+ /**
17
+ * 목록 쿼리의 `page`·`size` — OpenAPI 문서용 형태(값은 쿼리 문자열). 서버는 숫자가 아니거나 범위를 벗어난
18
+ * 값을 기본값·상한으로 보정한다.
19
+ */
20
+ export function pageQueryShape(options: { defaultSize?: number; maxSize?: number } = {}) {
21
+ const { defaultSize = 20, maxSize = 100 } = options;
22
+ return {
23
+ page: z.string().optional().describe("페이지 번호 (1부터, 기본 1)"),
24
+ size: z.string().optional().describe(`페이지 크기 (기본 ${defaultSize}, 최대 ${maxSize})`),
25
+ };
26
+ }
27
+
16
28
  export interface PageParams {
17
29
  page?: number;
18
30
  size?: number;
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import type { PageParams } from "./common";
2
+ import { type PageParams, pageQueryShape } from "./common";
3
3
 
4
4
  export const inquirySchema = z.object({
5
5
  inquiryId: z.string(),
@@ -54,6 +54,27 @@ export const sellerCustomerInquirySchema = z.object({
54
54
 
55
55
  export type SellerCustomerInquiry = z.infer<typeof sellerCustomerInquirySchema>;
56
56
 
57
+ const answeredQuery = z
58
+ .enum(["true", "false"])
59
+ .optional()
60
+ .describe("답변 여부 필터. `true`면 답변된 문의만, `false`면 미답변만, 생략하면 전부");
61
+
62
+ /** `GET /v1/inquiries` 쿼리(상품 문의) — OpenAPI 문서용 형태(값은 쿼리 문자열). 최신순이다 */
63
+ export const inquiryListQuerySchema = z.object({
64
+ answered: answeredQuery,
65
+ productId: z.string().optional().describe("상품 id 필터"),
66
+ from: z.string().optional().describe("작성 시각 조회 시작 (ISO 8601, 포함)"),
67
+ ...pageQueryShape(),
68
+ });
69
+
70
+ /** `GET /v1/customer-inquiries` 쿼리(1:1 문의) — OpenAPI 문서용 형태(값은 쿼리 문자열). 최신순이다 */
71
+ export const customerInquiryListQuerySchema = z.object({
72
+ answered: answeredQuery,
73
+ category: customerInquiryCategorySchema.optional().describe("문의 유형 필터"),
74
+ from: z.string().optional().describe("작성 시각 조회 시작 (ISO 8601, 포함)"),
75
+ ...pageQueryShape(),
76
+ });
77
+
57
78
  export const settlementStatusSchema = z.enum(["SCHEDULED", "PAID", "HELD"]);
58
79
 
59
80
  export type SettlementStatus = z.infer<typeof settlementStatusSchema>;
@@ -88,6 +109,29 @@ export const settlementDetailSchema = z.object({
88
109
 
89
110
  export type SettlementDetail = z.infer<typeof settlementDetailSchema>;
90
111
 
112
+ /** `GET /v1/settlements/{settlementId}` 응답 — 정산 요약 + 상세 내역(`size`건까지) */
113
+ export const settlementWithDetailsSchema = settlementSummarySchema.extend({
114
+ details: z.array(settlementDetailSchema).optional(),
115
+ });
116
+
117
+ export type SettlementWithDetails = z.infer<typeof settlementWithDetailsSchema>;
118
+
119
+ /** `GET /v1/settlements` 쿼리 — OpenAPI 문서용 형태(값은 쿼리 문자열). 정산일 최신순이다 */
120
+ export const settlementListQuerySchema = z.object({
121
+ from: z.string().describe("정산일 조회 시작 (ISO 8601, 포함). 필수"),
122
+ to: z
123
+ .string()
124
+ .optional()
125
+ .describe("정산일 조회 끝 (ISO 8601, 포함). 생략하면 from부터 31일. 기간은 최대 31일"),
126
+ status: settlementStatusSchema.optional().describe("정산 상태 필터"),
127
+ ...pageQueryShape(),
128
+ });
129
+
130
+ /** `GET /v1/settlements/{settlementId}` 쿼리 — `size`는 돌려줄 상세 내역 건수다(`page`는 무시) */
131
+ export const settlementDetailQuerySchema = z.object(
132
+ pageQueryShape({ defaultSize: 100, maxSize: 300 }),
133
+ );
134
+
91
135
  export interface SettlementListParams extends PageParams {
92
136
  from: string;
93
137
  to?: string;
@@ -288,11 +332,42 @@ export const reviewSchema = z.object({
288
332
 
289
333
  export type Review = z.infer<typeof reviewSchema>;
290
334
 
335
+ export const reviewSortSchema = z.enum([
336
+ "createdAt.desc",
337
+ "createdAt.asc",
338
+ "rating.asc",
339
+ "rating.desc",
340
+ ]);
341
+
342
+ export type ReviewSort = z.infer<typeof reviewSortSchema>;
343
+
291
344
  export interface ReviewListParams extends PageParams {
292
345
  productId?: string;
293
346
  rating?: number;
294
347
  replied?: boolean;
295
348
  hasImage?: boolean;
296
349
  from?: string;
297
- sort?: "createdAt.desc" | "createdAt.asc" | "rating.asc" | "rating.desc";
350
+ sort?: ReviewSort;
298
351
  }
352
+
353
+ /** `GET /v1/reviews` 쿼리 — OpenAPI 문서용 형태(값은 쿼리 문자열) */
354
+ export const reviewListQuerySchema = z.object({
355
+ productId: z.string().optional().describe("상품 id 필터"),
356
+ rating: z.enum(["1", "2", "3", "4", "5"]).optional().describe("별점 필터 (일치)"),
357
+ replied: z
358
+ .enum(["true", "false"])
359
+ .optional()
360
+ .describe("답글 여부 필터. `true`면 답글 단 리뷰만, `false`면 답글 없는 리뷰만"),
361
+ hasImage: z.enum(["true", "false"]).optional().describe("`true`면 이미지가 있는 리뷰만"),
362
+ from: z.string().optional().describe("작성 시각 조회 시작 (ISO 8601, 포함)"),
363
+ sort: reviewSortSchema.optional().describe("정렬 (기본 createdAt.desc)"),
364
+ ...pageQueryShape(),
365
+ });
366
+
367
+ /** `POST /v1/reviews/{reviewId}/report` 응답(202) — 신고 접수 */
368
+ export const reviewReportResultSchema = z.object({
369
+ reviewId: z.string(),
370
+ status: z.literal("PENDING_REVIEW"),
371
+ });
372
+
373
+ export type ReviewReportResult = z.infer<typeof reviewReportResultSchema>;
@@ -209,6 +209,24 @@ export const deliveryInfoSchema = z.object({
209
209
 
210
210
  export type DeliveryInfo = z.infer<typeof deliveryInfoSchema>;
211
211
 
212
+ /** `GET /v1/order-items/{orderItemId}/delivery` 응답 — 배송 정보 + 배송 추적 이벤트 */
213
+ export const deliveryStatusSchema = deliveryInfoSchema.extend({
214
+ trackingEvents: z
215
+ .array(z.object({ status: z.string(), location: z.string(), occurredAt: z.string() }))
216
+ .optional(),
217
+ });
218
+
219
+ export type DeliveryStatus = z.infer<typeof deliveryStatusSchema>;
220
+
221
+ /** `PUT /v1/order-items/{orderItemId}/dispatch/tracking` 응답 — 바뀐 송장 */
222
+ export const trackingUpdateResultSchema = z.object({
223
+ orderItemId: z.string(),
224
+ carrierCode: z.string(),
225
+ trackingNumber: z.string(),
226
+ });
227
+
228
+ export type TrackingUpdateResult = z.infer<typeof trackingUpdateResultSchema>;
229
+
212
230
  export const carrierSchema = z.object({
213
231
  carrierCode: z.string(),
214
232
  name: z.string(),
@@ -231,3 +249,45 @@ export const cancelBySellerRequestSchema = z.object({
231
249
  });
232
250
 
233
251
  export type CancelBySellerRequest = z.infer<typeof cancelBySellerRequestSchema>;
252
+
253
+ /** `POST /v1/order-items/{orderItemId}/cancel` 응답 — 셀러 직권취소 환불 결과 */
254
+ export const cancelBySellerResultSchema = z.object({
255
+ orderItemId: z.string(),
256
+ refundAmount: z.number().int(),
257
+ refundedAt: z.string(),
258
+ });
259
+
260
+ export type CancelBySellerResult = z.infer<typeof cancelBySellerResultSchema>;
261
+
262
+ /** `PUT /v1/order-items/{orderItemId}/memo` 응답 — 빈 문자열로 저장하면 메모가 지워져 `null`이다 */
263
+ export const orderItemMemoResultSchema = z.object({
264
+ orderItemId: z.string(),
265
+ sellerMemo: z.string().nullable(),
266
+ });
267
+
268
+ export type OrderItemMemoResult = z.infer<typeof orderItemMemoResultSchema>;
269
+
270
+ /** `POST /v1/order-items/{orderItemId}/purchase-decision/request` 응답 */
271
+ export const purchaseDecisionRequestResultSchema = z.object({
272
+ orderItemId: z.string(),
273
+ requestedAt: z.string(),
274
+ });
275
+
276
+ export type PurchaseDecisionRequestResult = z.infer<typeof purchaseDecisionRequestResultSchema>;
277
+
278
+ /** `POST /v1/order-items/{orderItemId}/purchase-decision/extend` 응답 — 연장은 최대 2회 */
279
+ export const purchaseDecisionExtendResultSchema = z.object({
280
+ orderItemId: z.string(),
281
+ autoDecisionDate: z.string(),
282
+ extendCount: z.number().int().max(2),
283
+ });
284
+
285
+ export type PurchaseDecisionExtendResult = z.infer<typeof purchaseDecisionExtendResultSchema>;
286
+
287
+ /**
288
+ * `GET /v1/orders/{orderId}/address-change-requests` 응답 — 배송지 변경 요청 플로우는 아직 제공하지 않아
289
+ * 현재는 항상 빈 배열이다
290
+ */
291
+ export const addressChangeRequestListSchema = z
292
+ .array(z.record(z.string(), z.unknown()))
293
+ .describe("배송지 변경 요청 목록 (현재 항상 빈 배열)");
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import type { PageParams } from "./common";
2
+ import { type PageParams, pageQueryShape } from "./common";
3
3
 
4
4
  export const productStatusSchema = z.enum(["SALE", "SUSPENDED", "OUT_OF_STOCK", "CLOSED"]);
5
5
 
@@ -234,12 +234,15 @@ export const productPatchRequestSchema = z
234
234
 
235
235
  export type ProductPatchRequest = z.infer<typeof productPatchRequestSchema>;
236
236
 
237
- export type ProductSort =
238
- | "createdAt.desc"
239
- | "createdAt.asc"
240
- | "salePrice.asc"
241
- | "salePrice.desc"
242
- | "updatedAt.desc";
237
+ export const productSortSchema = z.enum([
238
+ "createdAt.desc",
239
+ "createdAt.asc",
240
+ "salePrice.asc",
241
+ "salePrice.desc",
242
+ "updatedAt.desc",
243
+ ]);
244
+
245
+ export type ProductSort = z.infer<typeof productSortSchema>;
243
246
 
244
247
  export interface ProductListParams extends PageParams {
245
248
  status?: ProductStatus;
@@ -249,6 +252,26 @@ export interface ProductListParams extends PageParams {
249
252
  sort?: ProductSort;
250
253
  }
251
254
 
255
+ /** `GET /v1/products` 쿼리 — OpenAPI 문서용 형태(값은 쿼리 문자열) */
256
+ export const productListQuerySchema = z.object({
257
+ status: productStatusSchema.optional().describe("판매 상태 필터"),
258
+ categoryId: z.string().optional().describe("카테고리 필터 — 하위 카테고리의 상품도 포함"),
259
+ keyword: z.string().optional().describe("상품명 검색 (포함)"),
260
+ sellerCode: z
261
+ .string()
262
+ .optional()
263
+ .describe("판매자 상품코드 — 이 코드가 붙은 variant를 가진 상품"),
264
+ sort: productSortSchema.optional().describe("정렬 (기본 createdAt.desc)"),
265
+ ...pageQueryShape(),
266
+ });
267
+
268
+ /** `POST /v1/product-images` 응답 — 업로드된 이미지의 CDN 주소 */
269
+ export const productImageUploadResultSchema = z.object({
270
+ images: z.array(z.object({ url: z.url(), width: z.number().int(), height: z.number().int() })),
271
+ });
272
+
273
+ export type ProductImageUploadResult = z.infer<typeof productImageUploadResultSchema>;
274
+
252
275
  export const discountSchema = z.object({
253
276
  productId: z.string(),
254
277
  discountType: z.enum(["RATE", "AMOUNT"]),
@@ -111,10 +111,28 @@ export const invitationSchema = z.object({
111
111
 
112
112
  export type Invitation = z.infer<typeof invitationSchema>;
113
113
 
114
+ /** `GET /v1/store/invitations` 쿼리 — OpenAPI 문서용 형태 */
115
+ export const invitationListQuerySchema = z.object({
116
+ status: invitationSchema.shape.status.optional().describe("초대 상태 필터"),
117
+ });
118
+
119
+ /** `PATCH /v1/store/members/{userId}` 응답 — 바뀐 역할 */
120
+ export const storeMemberRoleUpdatedSchema = z.object({
121
+ userId: z.string(),
122
+ role: z.enum(["ADMIN", "STAFF"]),
123
+ });
124
+
125
+ export type StoreMemberRoleUpdated = z.infer<typeof storeMemberRoleUpdatedSchema>;
126
+
114
127
  export const addressTypeSchema = z.enum(["SHIPPING", "RETURN"]);
115
128
 
116
129
  export type AddressType = z.infer<typeof addressTypeSchema>;
117
130
 
131
+ /** `GET /v1/seller-addresses` 쿼리 — OpenAPI 문서용 형태. 기본 주소 우선, 그다음 등록순이다 */
132
+ export const sellerAddressListQuerySchema = z.object({
133
+ type: addressTypeSchema.optional().describe("주소 유형 필터"),
134
+ });
135
+
118
136
  export const sellerAddressSchema = z.object({
119
137
  addressId: z.string(),
120
138
  type: addressTypeSchema,