@sayren/storefront-sdk 0.20.7 → 0.20.9
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/auth/index.mjs +1 -1
- package/dist/{checkout-Bt6j2eDw.mjs → checkout-BjJ4Efbn.mjs} +98 -10
- package/dist/{client-Dn_JdIqv.mjs → client-vjq513VD.mjs} +118 -5
- package/dist/{index-atHaDBC3.d.mts → index-BLjQQj49.d.mts} +894 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +3 -3
- package/dist/payments/index.d.mts +1 -1
- package/dist/payments/index.mjs +1 -1
- package/package.json +1 -1
- package/src/client.ts +75 -0
- package/src/index.ts +2 -0
- package/src/schemas/catalog.ts +10 -0
- package/src/schemas/checkout.ts +12 -0
- package/src/schemas/commerce-flow.ts +115 -0
- package/src/schemas/fulfillment.ts +53 -3
- package/src/schemas/order.ts +21 -0
- package/src/schemas/product-options.ts +72 -2
- package/src/schemas/stay.ts +32 -0
package/dist/auth/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Bt as ApiError, t as createStorefrontClient } from "../client-vjq513VD.mjs";
|
|
2
2
|
//#region src/auth/index.ts
|
|
3
3
|
/** 소셜 로그인 실패 — 구매자가 취소했거나(`access_denied`) state가 맞지 않는다 */
|
|
4
4
|
var IdpCallbackError = class extends Error {
|
|
@@ -21,6 +21,7 @@ function openUnion(known) {
|
|
|
21
21
|
requiresShipping: value.requiresShipping
|
|
22
22
|
}))]);
|
|
23
23
|
}
|
|
24
|
+
const methodsViewSchema = z.array(z.string()).optional().describe("고를 수 있는 이행 방식(이슈 #115). 현재 값은 `CARRIER`(택배)·`DIRECT`(직접 배달)·`PICKUP`(방문 수령)·`PROVIDED`(제공 처리)이고 값이 추가될 수 있어 문자열로 받는다. 첫 값이 기본이다. 서버는 항상 싣는다");
|
|
24
25
|
const requiresShippingDescription = "택배 배송이 필요한가. false면 배송비가 없고 주문서가 배송지를 받지 않는다";
|
|
25
26
|
/** 상품 카드(목록·찜)의 이행 — 유형과 배송 필요 여부만. 배송비·환불 정책은 상세에서 본다 */
|
|
26
27
|
const productCardFulfillmentSchema = z.object({
|
|
@@ -38,29 +39,70 @@ const productFulfillmentViewSchema = openUnion(z.discriminatedUnion("type", [z.o
|
|
|
38
39
|
estimatedDays: z.string().describe("예상 배송 기간 안내 문구"),
|
|
39
40
|
returnDeliveryFee: z.number().int().describe("단순 변심 반품 배송비(유효 환불 정책). 원 단위"),
|
|
40
41
|
exchangeDeliveryFee: z.number().int().describe("단순 변심 교환 배송비(유효 환불 정책). 원 단위")
|
|
41
|
-
})
|
|
42
|
+
}),
|
|
43
|
+
methods: methodsViewSchema
|
|
42
44
|
}), z.object({
|
|
43
45
|
type: z.literal("MANUAL"),
|
|
44
|
-
requiresShipping: z.literal(false)
|
|
46
|
+
requiresShipping: z.literal(false),
|
|
47
|
+
methods: methodsViewSchema
|
|
45
48
|
})])).describe("상품 이행. `type`이 유형이고 같은 이름의 키가 유형별 안내다. 값이 추가될 수 있어 SDK는 모르는 유형을 `OTHER`로 읽는다");
|
|
46
49
|
/** 장바구니 줄·주문서 줄의 이행 — 주문서 줄은 주문서 시점 스냅샷이다 */
|
|
47
50
|
const lineFulfillmentSchema = z.object({
|
|
48
51
|
type: z.string().describe("상품 유형. 값이 추가될 수 있어 문자열로 받는다"),
|
|
49
52
|
requiresShipping: z.boolean().describe(requiresShippingDescription),
|
|
53
|
+
method: z.string().optional().describe("이행 방식(이슈 #115). 주문서 줄은 고른 방식, 장바구니 줄은 기본 방식이다. 값이 추가될 수 있어 문자열로 받는다"),
|
|
50
54
|
withdrawalRestricted: z.boolean().optional().describe("**Deprecated** — 항상 false다. 청약철회 제한 기능을 없앴고(이슈 #48) storefront-sdk 0.15 이하 호환으로만 싣는다. 게시된 스토어프론트가 0.16 이상으로 넘어간 뒤 다음 릴리스에서 뺀다")
|
|
51
55
|
});
|
|
56
|
+
/** 픽업 장소 — 방문 수령(`PICKUP`) 주문서에서 고른다 */
|
|
57
|
+
const pickupLocationViewSchema = z.object({
|
|
58
|
+
locationId: z.string(),
|
|
59
|
+
name: z.string(),
|
|
60
|
+
address: z.string(),
|
|
61
|
+
phone: z.string().nullable(),
|
|
62
|
+
hours: z.string().nullable().describe("수령 가능 시간 안내")
|
|
63
|
+
});
|
|
64
|
+
const snapshotMethodSchema = z.string().optional().describe("주문 시점 이행 방식(이슈 #115). 값이 추가될 수 있어 문자열로 받는다. `requiresShipping`은 유형 규칙이고, 방문 수령(`PICKUP`)이면 배송지가 없다");
|
|
65
|
+
const snapshotPickupSchema = pickupLocationViewSchema.optional().describe("방문 수령에서 고른 장소(주문 시점 값). 없으면 생략");
|
|
52
66
|
/**
|
|
53
67
|
* 내 주문 주문상품의 주문 시점 이행 스냅샷. 상품을 나중에 고쳐도 바뀌지 않는다. 제공 기록(제공 시각·판매자 안내)은
|
|
54
68
|
* 주문상품의 `fulfillment`다.
|
|
55
69
|
*/
|
|
56
70
|
const myOrderItemFulfillmentSnapshotSchema = openUnion(z.discriminatedUnion("type", [z.object({
|
|
57
71
|
type: z.literal("SHIPPING"),
|
|
58
|
-
requiresShipping: z.literal(true)
|
|
72
|
+
requiresShipping: z.literal(true),
|
|
73
|
+
method: snapshotMethodSchema,
|
|
74
|
+
pickupLocation: snapshotPickupSchema
|
|
59
75
|
}), z.object({
|
|
60
76
|
type: z.literal("MANUAL"),
|
|
61
|
-
requiresShipping: z.literal(false)
|
|
77
|
+
requiresShipping: z.literal(false),
|
|
78
|
+
method: snapshotMethodSchema,
|
|
79
|
+
pickupLocation: snapshotPickupSchema
|
|
62
80
|
})])).describe("주문 시점 이행 스냅샷. 값이 추가될 수 있어 SDK는 모르는 유형을 `OTHER`로 읽는다");
|
|
63
81
|
//#endregion
|
|
82
|
+
//#region src/schemas/stay.ts
|
|
83
|
+
/**
|
|
84
|
+
* 숙박 기간·날짜별 달력(이슈 #118) — 날짜별 재고 상품(상품 상세 `inventoryMode: "DATED"`)은 담기·바로 구매에 기간을 함께 보내고,
|
|
85
|
+
* 가격은 박마다 달력의 가격을 더한 값이다. 날짜는 한국 날짜 `YYYY-MM-DD`다.
|
|
86
|
+
*/
|
|
87
|
+
const stayRequestSchema = z.object({
|
|
88
|
+
checkIn: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
|
|
89
|
+
checkOut: z.string().regex(/^\d{4}-\d{2}-\d{2}$/)
|
|
90
|
+
}).describe("숙박 기간(날짜별 재고 상품만). 체크인 날부터 체크아웃 전날까지 박마다 재고·가격을 본다. 최대 30박. 날짜별 재고 상품에 빠지면 400 `STAY_REQUIRED`, 다른 상품에 주면 400 `STAY_NOT_APPLICABLE`, 재고가 없는 날이 있으면 409 `DATES_UNAVAILABLE`");
|
|
91
|
+
const stayViewSchema = z.object({
|
|
92
|
+
checkIn: z.string(),
|
|
93
|
+
checkOut: z.string(),
|
|
94
|
+
nights: z.array(z.object({
|
|
95
|
+
date: z.string(),
|
|
96
|
+
price: z.number().int()
|
|
97
|
+
})).describe("박마다 날짜·가격(객실 1개 기준). 합이 줄 단가다")
|
|
98
|
+
});
|
|
99
|
+
/** 구매자 달력 한 칸 — 재고 수는 보이지 않고 예약 가능 여부만 */
|
|
100
|
+
const calendarDayViewSchema = z.object({
|
|
101
|
+
date: z.string(),
|
|
102
|
+
available: z.boolean(),
|
|
103
|
+
price: z.number().int().describe("그날 가격(원)")
|
|
104
|
+
});
|
|
105
|
+
//#endregion
|
|
64
106
|
//#region src/schemas/product-options.ts
|
|
65
107
|
/**
|
|
66
108
|
* 추가 선택·직접 입력 (이슈 #59) — 상품 상세의 옵션 표시, 장바구니 담기·바로 구매 요청, 줄 스냅샷의 공통 모양.
|
|
@@ -83,9 +125,39 @@ const customInputViewSchema = z.object({
|
|
|
83
125
|
label: z.string().describe("항목명"),
|
|
84
126
|
placeholder: z.string().nullable().describe("입력 안내. 없으면 null"),
|
|
85
127
|
maxLength: z.number().int().describe("최대 글자 수"),
|
|
86
|
-
required: z.boolean()
|
|
128
|
+
required: z.boolean(),
|
|
129
|
+
key: z.string().nullable().optional().describe("고정 키. 없으면 null"),
|
|
130
|
+
type: z.string().optional().describe("입력 타입. 현재 값은 `text`·`number`(정수)·`select`·`date`(`YYYY-MM-DD`, 한국 날짜)·`datetime`(오프셋 있는 ISO 8601)·`image`(업로드 주소 목록, `maxLength`가 최대 장수)이고 값이 추가될 수 있어 문자열로 받는다. 없으면 `text`"),
|
|
131
|
+
options: z.array(z.string()).nullable().optional().describe("`select`의 선택지. 그 밖의 타입은 null")
|
|
87
132
|
});
|
|
88
133
|
/**
|
|
134
|
+
* 직접 입력값을 타입대로 검사하고 저장할 모양으로 바꾼다(정규화 뒤 값). 서버 판정(400 `CUSTOM_INPUT_INVALID`)과 스토어프론트
|
|
135
|
+
* 입력 검사가 이 함수 하나를 쓴다. 모르는 타입은 `text`로 본다. 맞지 않으면 null
|
|
136
|
+
*/
|
|
137
|
+
function parseCustomInputValue(type, options, raw) {
|
|
138
|
+
const value = normalizeCustomInputValue(raw);
|
|
139
|
+
switch (type) {
|
|
140
|
+
case "number": return /^-?\d{1,15}$/.test(value) ? String(Number(value)) : null;
|
|
141
|
+
case "select": return options?.includes(value) ? value : null;
|
|
142
|
+
case "date": {
|
|
143
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) return null;
|
|
144
|
+
const date = /* @__PURE__ */ new Date(`${value}T00:00:00Z`);
|
|
145
|
+
return !Number.isNaN(date.getTime()) && date.toISOString().slice(0, 10) === value ? value : null;
|
|
146
|
+
}
|
|
147
|
+
case "image": {
|
|
148
|
+
const urls = value.split(/\s+/).filter(Boolean);
|
|
149
|
+
if (urls.length === 0 || !urls.every((url) => /^https:\/\/\S+$/.test(url))) return null;
|
|
150
|
+
return [...new Set(urls)].join("\n");
|
|
151
|
+
}
|
|
152
|
+
case "datetime": {
|
|
153
|
+
if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d{1,3})?)?(Z|[+-]\d{2}:\d{2})$/.test(value)) return null;
|
|
154
|
+
const time = new Date(value);
|
|
155
|
+
return Number.isNaN(time.getTime()) ? null : time.toISOString();
|
|
156
|
+
}
|
|
157
|
+
default: return value;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
89
161
|
* 직접 입력값 정규화 — NFC로 모으고, 제어 문자(C0·C1·줄바꿈·줄·문단 구분자)는 공백으로, 제로폭·양방향 제어 문자는 지운 뒤
|
|
90
162
|
* 앞뒤 공백을 지운다. 서버가 저장하는 값이 이것이다. 빈 문자열이면 입력하지 않은 것으로 본다.
|
|
91
163
|
* (양방향 제어 문자를 두면 셀러 주문 화면의 각인 문구가 뒤집혀 보이게 할 수 있다.)
|
|
@@ -113,7 +185,8 @@ const addonSelectionSchema = z.object({
|
|
|
113
185
|
/** 요청의 추가 선택·직접 입력 필드 — 담기·장바구니 수정·바로 구매가 같은 이름을 쓴다 */
|
|
114
186
|
const lineSelectionRequestShape = {
|
|
115
187
|
addons: z.array(addonSelectionSchema).max(20).optional().describe("고른 추가 선택(옵션명마다 하나, 고르지 않은 옵션명은 빼고 보낸다). 필수 옵션명을 빼면 400 `ADDON_OPTION_REQUIRED`, 없거나 꺼진 값이거나 한 옵션명에서 둘을 고르면 400 `ADDON_OPTION_NOT_FOUND`"),
|
|
116
|
-
customInputs: z.array(customInputEntrySchema).max(20).optional().describe("직접 입력값. 필수 항목을 비우면 400 `CUSTOM_INPUT_REQUIRED`, 최대 글자 수를 넘으면 400 `CUSTOM_INPUT_TOO_LONG`, 없는 항목이면 400 `CUSTOM_INPUT_NOT_FOUND`")
|
|
188
|
+
customInputs: z.array(customInputEntrySchema).max(20).optional().describe("직접 입력값. 필수 항목을 비우면 400 `CUSTOM_INPUT_REQUIRED`, 최대 글자 수를 넘으면 400 `CUSTOM_INPUT_TOO_LONG`, 없는 항목이면 400 `CUSTOM_INPUT_NOT_FOUND`, 항목 타입에 맞지 않으면 400 `CUSTOM_INPUT_INVALID`"),
|
|
189
|
+
stay: stayRequestSchema.optional()
|
|
117
190
|
};
|
|
118
191
|
/** 줄의 옵션 선택 스냅샷 한 칸 — 조합 옵션은 옵션명마다 한 칸이고 추가금이 0이다(조합 추가금은 단가에 들어 있다) */
|
|
119
192
|
const optionSelectionViewSchema = z.object({
|
|
@@ -124,13 +197,21 @@ const optionSelectionViewSchema = z.object({
|
|
|
124
197
|
});
|
|
125
198
|
const customInputValueViewSchema = z.object({
|
|
126
199
|
label: z.string().describe("항목명"),
|
|
127
|
-
value: z.string().describe("구매자가 적은 값")
|
|
200
|
+
value: z.string().describe("구매자가 적은 값(타입별 정규화 뒤 값, `datetime`은 UTC ISO 8601)"),
|
|
201
|
+
key: z.string().nullable().optional().describe("항목의 고정 키(주문 시점). 없으면 null"),
|
|
202
|
+
type: z.string().optional().describe("항목의 입력 타입(주문 시점). 없으면 `text`")
|
|
128
203
|
});
|
|
129
204
|
/** 응답 줄의 표시 필드 — 장바구니·주문서·주문상품이 같은 이름을 쓴다 */
|
|
130
205
|
const lineSelectionResponseShape = {
|
|
131
206
|
optionSelections: z.array(optionSelectionViewSchema).optional().default([]).describe("옵션 선택(조합 옵션 + 추가 선택). 옵션이 없으면 빈 배열. 서버는 항상 싣는다"),
|
|
132
|
-
customInputs: z.array(customInputValueViewSchema).optional().default([]).describe("직접 입력값(항목명과 값). 없으면 빈 배열. 서버는 항상 싣는다")
|
|
207
|
+
customInputs: z.array(customInputValueViewSchema).optional().default([]).describe("직접 입력값(항목명과 값). 없으면 빈 배열. 서버는 항상 싣는다"),
|
|
208
|
+
stay: stayViewSchema.optional().describe("숙박 기간과 박별 가격(날짜별 재고 상품만, 이슈 #118)")
|
|
133
209
|
};
|
|
210
|
+
/** 주문 입력 이미지 업로드 자리 요청(#115 E4) — 파일명은 확장자만 쓰인다 */
|
|
211
|
+
const orderInputUploadRequestSchema = z.object({
|
|
212
|
+
filename: z.string().min(1).max(200),
|
|
213
|
+
size: z.number().int().positive().optional().describe("바이트. 주면 상한을 넘을 때 미리 거절한다")
|
|
214
|
+
});
|
|
134
215
|
//#endregion
|
|
135
216
|
//#region src/schemas/coupon.ts
|
|
136
217
|
/**
|
|
@@ -284,7 +365,14 @@ const createCheckoutRequestSchema = z.object({
|
|
|
284
365
|
optionId: z.string().optional(),
|
|
285
366
|
quantity: z.number().int().min(1),
|
|
286
367
|
...lineSelectionRequestShape
|
|
287
|
-
}).optional()
|
|
368
|
+
}).optional(),
|
|
369
|
+
fulfillmentMethod: z.enum([
|
|
370
|
+
"CARRIER",
|
|
371
|
+
"DIRECT",
|
|
372
|
+
"PICKUP",
|
|
373
|
+
"PROVIDED"
|
|
374
|
+
]).optional().describe("이행 방식(이슈 #115). 모든 줄에 같은 방식을 적용하고, 상품 `fulfillment.methods`에 없는 줄이 있으면 400 `FULFILLMENT_METHOD_NOT_ALLOWED`다. 생략하면 줄마다 상품 허용 방식의 첫 값이다. 방문 수령(`PICKUP`)은 배송지·배송비가 없다"),
|
|
375
|
+
pickupLocationId: z.string().optional().describe("방문 수령 장소(`GET /pickup-locations`). 방식이 `PICKUP`이고 상점에 픽업 장소가 있으면 필수(400 `PICKUP_LOCATION_REQUIRED`), 없거나 쓰지 않는 장소면 400 `PICKUP_LOCATION_NOT_FOUND`. 다른 방식에 주면 400 `PICKUP_LOCATION_NOT_APPLICABLE`")
|
|
288
376
|
}).refine((value) => value.cartItemIds ? !value.directItem : !!value.directItem, { message: "cartItemIds와 directItem 중 하나만 전달해야 합니다" });
|
|
289
377
|
/** 지역 추가 배송비 구분 — 우편번호로 판정한다 */
|
|
290
378
|
const remoteAreaSchema = z.enum([
|
|
@@ -622,4 +710,4 @@ const paymentMessageSchema = z.object({
|
|
|
622
710
|
orderId: z.string().optional()
|
|
623
711
|
});
|
|
624
712
|
//#endregion
|
|
625
|
-
export { customInputViewSchema as $, retryPaymentRequestSchema as A, couponBenefitViewSchema as B, paymentOptionSchema as C, remoteAreaSchema as D, pgProviderSchema as E, applicableCouponSchema as F, storefrontCouponListQuerySchema as G, myCouponListQuerySchema as H, checkoutPricingRequestSchema as I, addonGroupViewSchema as J, storefrontCouponSchema as K, checkoutPricingSchema as L, startPaymentRequestSchema as M, MAX_COUPONS_PER_CHECKOUT as N, residentNumberLike as O, MIN_PAYMENT_AMOUNT as P, customInputValueViewSchema as Q, couponApplicationListSchema as R, paymentOptionListSchema as S, paymentStatusSchema as T, myCouponSchema as U, couponResultSchema as V, pricingAmountsSchema as W, customInputEntrySchema as X, addonSelectionSchema as Y, customInputLength as Z, guestInfoSchema as _, availablePaymentOptionSchema as a,
|
|
713
|
+
export { customInputViewSchema as $, retryPaymentRequestSchema as A, couponBenefitViewSchema as B, paymentOptionSchema as C, remoteAreaSchema as D, pgProviderSchema as E, applicableCouponSchema as F, storefrontCouponListQuerySchema as G, myCouponListQuerySchema as H, checkoutPricingRequestSchema as I, addonGroupViewSchema as J, storefrontCouponSchema as K, checkoutPricingSchema as L, startPaymentRequestSchema as M, MAX_COUPONS_PER_CHECKOUT as N, residentNumberLike as O, MIN_PAYMENT_AMOUNT as P, customInputValueViewSchema as Q, couponApplicationListSchema as R, paymentOptionListSchema as S, paymentStatusSchema as T, myCouponSchema as U, couponResultSchema as V, pricingAmountsSchema as W, customInputEntrySchema as X, addonSelectionSchema as Y, customInputLength as Z, guestInfoSchema as _, availablePaymentOptionSchema as a, parseCustomInputValue as at, paymentMethodSchema as b, cashReceiptRequestSchema as c, stayViewSchema as ct, checkoutSessionSchema as d, pickupLocationViewSchema as dt, lineSelectionRequestShape as et, createCheckoutRequestSchema as f, productCardFulfillmentSchema as ft, easyPayProviderSchema as g, easyPayProviderResponseSchema as h, PAYMENT_STATUS_VALUES as i, orderInputUploadRequestSchema as it, shippingAddressInputSchema as j, responsePaymentMethodSchema as k, cashReceiptTypeSchema as l, lineFulfillmentSchema as lt, deliveryQuoteSchema as m, PAYMENT_RESULT_VALUES as n, normalizeCustomInputValue as nt, cashReceiptAvailable as o, calendarDayViewSchema as ot, deliveryQuoteRequestSchema as p, productFulfillmentViewSchema as pt, storefrontCouponTargetSchema as q, PAYMENT_START_STATUS_VALUES as r, optionSelectionViewSchema as rt, cashReceiptIdentityTypeOf as s, stayRequestSchema as st, CASH_RECEIPT_METHODS as t, lineSelectionResponseShape as tt, checkoutDeliverySchema as u, myOrderItemFulfillmentSnapshotSchema as ut, paymentFailureCategorySchema as v, paymentStartSchema as w, paymentOptionKey as x, paymentMessageSchema as y, couponApplicationSchema as z };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as ANALYTICS_VISITOR_HEADER, r as ANALYTICS_SESSION_HEADER } from "./analytics-CgD70OqH.mjs";
|
|
2
|
-
import { $ as customInputViewSchema, A as retryPaymentRequestSchema, F as applicableCouponSchema, I as checkoutPricingRequestSchema, J as addonGroupViewSchema, K as storefrontCouponSchema, L as checkoutPricingSchema, M as startPaymentRequestSchema, T as paymentStatusSchema, U as myCouponSchema,
|
|
2
|
+
import { $ as customInputViewSchema, A as retryPaymentRequestSchema, F as applicableCouponSchema, I as checkoutPricingRequestSchema, J as addonGroupViewSchema, K as storefrontCouponSchema, L as checkoutPricingSchema, M as startPaymentRequestSchema, T as paymentStatusSchema, U as myCouponSchema, d as checkoutSessionSchema, dt as pickupLocationViewSchema, et as lineSelectionRequestShape, f as createCheckoutRequestSchema, ft as productCardFulfillmentSchema, h as easyPayProviderResponseSchema, k as responsePaymentMethodSchema, lt as lineFulfillmentSchema, m as deliveryQuoteSchema, ot as calendarDayViewSchema, p as deliveryQuoteRequestSchema, pt as productFulfillmentViewSchema, tt as lineSelectionResponseShape, ut as myOrderItemFulfillmentSnapshotSchema, w as paymentStartSchema } from "./checkout-BjJ4Efbn.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
//#region src/http.ts
|
|
5
5
|
/** 표준 엔벨로프의 $.error 상세 */
|
|
@@ -353,9 +353,11 @@ const productDetailSchema = productCardSchema.extend({
|
|
|
353
353
|
/** 값 이름을 " / "로 이은 표시명. 옵션 없으면 "" */
|
|
354
354
|
name: z.string(),
|
|
355
355
|
additionalPrice: z.number().int(),
|
|
356
|
-
soldOut: z.boolean()
|
|
356
|
+
soldOut: z.boolean(),
|
|
357
|
+
attributes: z.record(z.string(), z.string()).optional().describe("조합 속성(이슈 #115, 예: 회차 일시 `showAt`). 없으면 생략")
|
|
357
358
|
})),
|
|
358
359
|
addonGroups: z.array(addonGroupViewSchema).optional().default([]).describe("추가 선택 옵션명(이슈 #59). 배열 순서가 표시 순서다. 담기·바로 구매의 `addons`로 `{groupId, valueId}`를 보낸다. 없으면 빈 배열. 서버는 항상 싣는다"),
|
|
360
|
+
inventoryMode: z.string().optional().describe("재고 방식(이슈 #118). `DATED`면 날짜별 재고 상품이다 — 달력(`GET /products/{id}/calendar`)으로 날짜를 고르고 담기·바로 구매에 `stay`를 보낸다. 없으면 일반 상품"),
|
|
359
361
|
customInputs: z.array(customInputViewSchema).optional().default([]).describe("직접 입력 항목(이슈 #59). 배열 순서가 표시 순서다. 담기·바로 구매의 `customInputs`로 값을 보낸다. 없으면 빈 배열. 서버는 항상 싣는다"),
|
|
360
362
|
fulfillment: productFulfillmentViewSchema,
|
|
361
363
|
returnPeriodDays: z.number().int().describe("반품·교환을 받는 기간(수령·제공일부터 일수)"),
|
|
@@ -516,6 +518,92 @@ const myClaimSchema = z.object({
|
|
|
516
518
|
completedAt: z.string().nullable()
|
|
517
519
|
});
|
|
518
520
|
//#endregion
|
|
521
|
+
//#region src/schemas/commerce-flow.ts
|
|
522
|
+
/**
|
|
523
|
+
* 커머스 플로우(이슈 #115) — 구매자가 보는 주문상품의 지금 상태와 할 수 있는 행동. 화면은 이 값만 그리고 상태 이름(`key`)으로
|
|
524
|
+
* 분기하지 않는다. 행동 키·필드 키·꺼진 이유는 열린 문자열이다(모르는 값도 파싱한다). 공개 상태(`coreStatus`)만 닫힌 값이다.
|
|
525
|
+
*/
|
|
526
|
+
const flowInputFieldSchema = z.object({
|
|
527
|
+
key: z.string(),
|
|
528
|
+
type: z.string().describe("text · number · select · date · datetime · image (늘어날 수 있다)"),
|
|
529
|
+
required: z.boolean(),
|
|
530
|
+
label: z.string(),
|
|
531
|
+
maxLength: z.number().int().optional(),
|
|
532
|
+
maxFiles: z.number().int().optional(),
|
|
533
|
+
options: z.array(z.union([z.string(), z.number()])).optional()
|
|
534
|
+
});
|
|
535
|
+
const flowActionSchema = z.object({
|
|
536
|
+
key: z.string(),
|
|
537
|
+
label: z.string().describe("버튼에 쓸 이름"),
|
|
538
|
+
mode: z.enum([
|
|
539
|
+
"INSTANT",
|
|
540
|
+
"REQUEST",
|
|
541
|
+
"VIEW"
|
|
542
|
+
]),
|
|
543
|
+
enabled: z.boolean(),
|
|
544
|
+
disabled: z.object({
|
|
545
|
+
reason: z.string(),
|
|
546
|
+
message: z.string().optional()
|
|
547
|
+
}).optional(),
|
|
548
|
+
availableUntil: z.string().optional().describe("이 시각까지만 할 수 있다(ISO 8601)"),
|
|
549
|
+
subflow: z.string().optional().describe("취소·반품·교환 요청처럼 하위 플로우를 시작하는 행동. 지금은 클레임 API(`POST /me/order-items/{id}/claims`)로 실행한다"),
|
|
550
|
+
input: z.array(flowInputFieldSchema).optional().describe("받는 입력 폼"),
|
|
551
|
+
partialQuantity: z.union([z.boolean(), z.literal("UNIT")]).optional()
|
|
552
|
+
});
|
|
553
|
+
/** 커스텀 필드 값 — 문자열(날짜·일시는 ISO 8601)·숫자·참거짓·null, 수량 단위 필드는 문자열 배열 */
|
|
554
|
+
const flowFieldValueSchema = z.union([
|
|
555
|
+
z.string(),
|
|
556
|
+
z.number(),
|
|
557
|
+
z.boolean(),
|
|
558
|
+
z.null(),
|
|
559
|
+
z.array(z.string())
|
|
560
|
+
]);
|
|
561
|
+
const flowStateSchema = z.object({
|
|
562
|
+
key: z.string(),
|
|
563
|
+
label: z.string().describe("구매자에게 보여 줄 상태 이름"),
|
|
564
|
+
coreStatus: orderItemStatusSchema.optional(),
|
|
565
|
+
message: z.string().optional().describe("구매자 안내문"),
|
|
566
|
+
enteredAt: z.string(),
|
|
567
|
+
deadlineAt: z.string().optional().describe("가장 가까운 기한(ISO 8601)"),
|
|
568
|
+
attachments: z.array(z.string()).optional().describe("가장 최근 행동이 붙인 첨부 주소(시안 등, #115). 없으면 생략"),
|
|
569
|
+
progress: z.boolean().optional(),
|
|
570
|
+
fields: z.record(z.string(), flowFieldValueSchema).describe("구매자 공개 범위의 커스텀 필드")
|
|
571
|
+
});
|
|
572
|
+
const flowActionRequestSchema = z.object({ input: z.record(z.string(), z.unknown()).optional() });
|
|
573
|
+
/** 비회원 행동 — 비회원 주문 조회와 같은 확인(연락처·주문 조회 비밀번호)을 함께 보낸다 */
|
|
574
|
+
const guestFlowActionRequestSchema = flowActionRequestSchema.extend({
|
|
575
|
+
phone: z.string(),
|
|
576
|
+
orderPassword: z.string()
|
|
577
|
+
});
|
|
578
|
+
const flowActionResultSchema = z.object({
|
|
579
|
+
status: z.literal("COMPLETED"),
|
|
580
|
+
flowState: flowStateSchema,
|
|
581
|
+
actions: z.array(flowActionSchema),
|
|
582
|
+
affectedOrderItemIds: z.array(z.string()),
|
|
583
|
+
claim: z.object({
|
|
584
|
+
claimId: z.string(),
|
|
585
|
+
claimNo: z.string().nullable()
|
|
586
|
+
}).optional().describe("취소·반품·교환 행동(하위 플로우 `core.claim.*`)이 접수한 클레임(#115). 클레임 API(`POST /me/order-items/{id}/claims`)와 같은 접수다. 다른 행동은 생략")
|
|
587
|
+
});
|
|
588
|
+
/**
|
|
589
|
+
* 주문 전체 행동 결과(#115) — 같은 행동을 주문의 주문상품마다 실행한다. 한 주문상품의 실패가 다른 주문상품을 되돌리지 않는다(부분 실행).
|
|
590
|
+
* 묶음 진행이면 한 번 실행이 묶음의 주문상품을 함께 움직인다(COMPLETED로 함께 나온다). 그 행동이 없는 주문상품은 SKIPPED다
|
|
591
|
+
*/
|
|
592
|
+
const orderFlowActionResultSchema = z.object({
|
|
593
|
+
orderId: z.string(),
|
|
594
|
+
key: z.string(),
|
|
595
|
+
results: z.array(z.object({
|
|
596
|
+
orderItemId: z.string(),
|
|
597
|
+
status: z.enum([
|
|
598
|
+
"COMPLETED",
|
|
599
|
+
"SKIPPED",
|
|
600
|
+
"FAILED"
|
|
601
|
+
]).describe("COMPLETED 실행 · SKIPPED 이 주문상품에는 그 행동이 없다 · FAILED 실행하다 거절됐다"),
|
|
602
|
+
reason: z.string().optional().describe("SKIPPED·FAILED의 이유 — 꺼진 이유(EXPIRED·CONDITION·NOT_IN_STATE) 또는 오류 코드"),
|
|
603
|
+
message: z.string().optional()
|
|
604
|
+
}))
|
|
605
|
+
});
|
|
606
|
+
//#endregion
|
|
519
607
|
//#region src/schemas/consent.ts
|
|
520
608
|
/**
|
|
521
609
|
* 동의 종류 — 이용약관(`TERMS`)·개인정보 수집이용(`PRIVACY`)은 가입 필수, 마케팅 수신(`MARKETING`)은 선택이다.
|
|
@@ -711,7 +799,10 @@ const myOrderItemSchema = z.object({
|
|
|
711
799
|
}).nullable().optional().default(null).describe("배송 없는 상품의 제공 기록(이슈 #48). 제공 전이거나 배송 상품이면 null이다. 배송 없는 상품의 `DELIVERED`는 제공 완료로 표시한다. 서버는 항상 싣는다"),
|
|
712
800
|
claimStatus: z.string().nullable(),
|
|
713
801
|
reviewWritten: z.boolean(),
|
|
714
|
-
autoDecisionDate: z.string().nullable()
|
|
802
|
+
autoDecisionDate: z.string().nullable(),
|
|
803
|
+
flowState: flowStateSchema.optional().describe("주문 플로우의 지금 상태(이슈 #115). 플로우가 없는 주문상품은 없다"),
|
|
804
|
+
actions: z.array(flowActionSchema).optional().describe("지금 할 수 있는 행동. 화면은 이 목록으로 버튼을 그린다(상태 이름으로 분기하지 않는다)"),
|
|
805
|
+
flowBranches: z.array(flowStateSchema).optional().describe("진행 위치가 둘 이상(병렬 진행·하위 흐름)이면 각 위치의 상태. `flowState`는 그 가운데 가장 앞 단계다")
|
|
715
806
|
});
|
|
716
807
|
/**
|
|
717
808
|
* 주문 응답의 배송지 — 결제 요청 시 저장된 스냅샷. 요청 스키마(`shippingAddressInputSchema`)와 분리한 응답 스키마라
|
|
@@ -728,6 +819,7 @@ const orderShippingAddressSchema = z.object({
|
|
|
728
819
|
});
|
|
729
820
|
const myOrderSchema = z.object({
|
|
730
821
|
orderId: z.string(),
|
|
822
|
+
progressStatus: orderItemStatusSchema.optional().describe("진행 중 주문상품 가운데 가장 앞 단계(취소 제외, 모두 취소면 CANCELED, #115). 섞인 주문에서 아직 기다리는 단계다. 서버는 항상 싣는다"),
|
|
731
823
|
orderNo: commerceNumberField("주문번호(이슈 #107) — 숫자 14자리, 생성 후 바뀌지 않습니다. 구매자 화면에는 `formatOrderNo`(4자리 하이픈)로 표시하십시오. 비회원 주문 조회 경로에도 쓸 수 있습니다"),
|
|
732
824
|
orderedAt: z.string(),
|
|
733
825
|
items: z.array(myOrderItemSchema),
|
|
@@ -1051,6 +1143,11 @@ get: () => http.request("GET", "/store", storefrontStoreSchema) },
|
|
|
1051
1143
|
/** 상품 리뷰 목록 — `variantId`로 옵션(조합)별 리뷰만 받는다(상품 상세 `variants[].variantId`) */
|
|
1052
1144
|
listProductReviews: (productId, params) => http.request("GET", path`/products/${productId}/reviews`, reviewPageSchema, { query: params }),
|
|
1053
1145
|
listProductInquiries: (productId, params) => http.request("GET", path`/products/${productId}/inquiries`, pageSchema(publicInquirySchema), { query: params }),
|
|
1146
|
+
/**
|
|
1147
|
+
* `GET /products/{productId}/calendar` — 날짜별 재고 상품(상세 `inventoryMode: "DATED"`, 이슈 #118)의 날마다 예약 가능 여부·가격.
|
|
1148
|
+
* 기간은 포함이고 최대 120일이다. `variantId`를 생략하면 기본 조합이다
|
|
1149
|
+
*/
|
|
1150
|
+
getProductCalendar: (productId, params) => http.request("GET", path`/products/${productId}/calendar`, z.array(calendarDayViewSchema), { query: params }),
|
|
1054
1151
|
createInquiry: (productId, body) => http.requestVoid("POST", path`/products/${productId}/inquiries`, { body }),
|
|
1055
1152
|
/** 노출 중인 컬렉션(노출 켜짐 + 기간 안) — 셀러가 정한 순서 */
|
|
1056
1153
|
listCollections: (params) => http.request("GET", "/collections", pageSchema(storefrontCollectionSchema), { query: params }),
|
|
@@ -1064,6 +1161,8 @@ get: () => http.request("GET", "/store", storefrontStoreSchema) },
|
|
|
1064
1161
|
/** 컬렉션 상품(판매 중만). `sort`를 생략하면 컬렉션의 기본 정렬이다 */
|
|
1065
1162
|
listCollectionProducts: (slug, params) => http.request("GET", path`/collections/${slug}/products`, collectionProductPageSchema, { query: params })
|
|
1066
1163
|
},
|
|
1164
|
+
/** `GET /pickup-locations` — 방문 수령 장소(이슈 #115). 주문서의 `pickupLocationId`로 고른다 */
|
|
1165
|
+
pickupLocations: { list: () => http.request("GET", "/pickup-locations", z.array(pickupLocationViewSchema)) },
|
|
1067
1166
|
cart: {
|
|
1068
1167
|
get: () => http.request("GET", "/cart", cartSchema),
|
|
1069
1168
|
addItem: (body) => http.request("POST", "/cart/items", cartSchema, { body: addCartItemRequestSchema.parse(body) }),
|
|
@@ -1134,7 +1233,21 @@ get: () => http.request("GET", "/store", storefrontStoreSchema) },
|
|
|
1134
1233
|
*/
|
|
1135
1234
|
getGuestOrder: (orderId, body) => http.request("POST", path`/guest/orders/${orderId}`, myOrderSchema, { body }),
|
|
1136
1235
|
getDelivery: (orderItemId) => http.request("GET", path`/me/order-items/${orderItemId}/delivery`, deliveryTrackingSchema),
|
|
1137
|
-
decidePurchase: (orderItemId) => http.requestVoid("POST", path`/me/order-items/${orderItemId}/purchase-decision`)
|
|
1236
|
+
decidePurchase: (orderItemId) => http.requestVoid("POST", path`/me/order-items/${orderItemId}/purchase-decision`),
|
|
1237
|
+
/**
|
|
1238
|
+
* `POST /me/order-items/{id}/actions/{key}` — 주문상품 `actions`에 켜진 행동을 실행한다(#115, 시안 승인 등).
|
|
1239
|
+
* 응답의 `flowState`·`actions`로 화면을 바로 바꾼다. 에러: 409 `ACTION_NOT_AVAILABLE`(`details.reason`)
|
|
1240
|
+
*/
|
|
1241
|
+
act: (orderItemId, key, input = {}) => http.request("POST", path`/me/order-items/${orderItemId}/actions/${key}`, flowActionResultSchema, { body: flowActionRequestSchema.parse({ input }) }),
|
|
1242
|
+
/** 비회원 행동 — 비회원 주문 조회와 같은 연락처·비밀번호 확인과 시도 한도를 지난다 */
|
|
1243
|
+
guestAct: (orderId, orderItemId, key, body) => http.request("POST", path`/guest/orders/${orderId}/items/${orderItemId}/actions/${key}`, flowActionResultSchema, { body: guestFlowActionRequestSchema.parse(body) }),
|
|
1244
|
+
/**
|
|
1245
|
+
* `POST /me/orders/{id}/actions/{key}` — 주문 전체 행동(#115, 예: 주문 전체 취소). 그 행동이 켜진 주문상품마다 실행하고 결과를
|
|
1246
|
+
* 주문상품별로 준다(부분 실행). 켜진 주문상품이 하나도 없으면 409 `ACTION_NOT_AVAILABLE`
|
|
1247
|
+
*/
|
|
1248
|
+
actOnOrder: (orderId, key, input = {}) => http.request("POST", path`/me/orders/${orderId}/actions/${key}`, orderFlowActionResultSchema, { body: flowActionRequestSchema.parse({ input }) }),
|
|
1249
|
+
/** 비회원 주문 전체 행동 — 비회원 주문 조회와 같은 확인·시도 한도 */
|
|
1250
|
+
guestActOnOrder: (orderId, key, body) => http.request("POST", path`/guest/orders/${orderId}/actions/${key}`, orderFlowActionResultSchema, { body: guestFlowActionRequestSchema.parse(body) })
|
|
1138
1251
|
},
|
|
1139
1252
|
myClaims: {
|
|
1140
1253
|
create: (orderItemId, body) => http.request("POST", path`/me/order-items/${orderItemId}/claims`, createClaimResultSchema, { body: createClaimRequestSchema.parse(body) }),
|
|
@@ -1194,4 +1307,4 @@ get: () => http.request("GET", "/store", storefrontStoreSchema) },
|
|
|
1194
1307
|
};
|
|
1195
1308
|
}
|
|
1196
1309
|
//#endregion
|
|
1197
|
-
export {
|
|
1310
|
+
export { claimReturnAddressSchema as $, wishlistAddResultSchema as A, idpAuthorizeResponseSchema as At, consentSourceSchema as B, ApiError as Bt, orderShippingAddressSchema as C, addCartItemRequestSchema as Ct, memberAddressSchema as D, anonymousSessionSchema as Dt, memberAddressRequestSchema as E, updateCartItemRequestSchema as Et, createCustomerInquiryRequestSchema as F, signupRequestSchema as Ft, flowActionResultSchema as G, consentUpdateRequestSchema as H, toApiError as Ht, customerInquiryCategorySchema as I, socialProviderSchema as It, flowInputFieldSchema as J, flowActionSchema as K, customerInquirySchema as L, tokenPairSchema as Lt, createInquiryResultSchema as M, linkIdentityRequestSchema as Mt, productInquiryCategorySchema as N, loginRequestSchema as Nt, memberSchema as O, idpAgreementsSchema as Ot, publicInquirySchema as P, memberIdentitiesSchema as Pt, claimReasonSchema as Q, consentActionSchema as R, withdrawRequestSchema as Rt, myOrderSchema as S, pageSchema as St, trackingStageResponseSchema as T, cartSchema as Tt, memberConsentsSchema as U, unwrapData as Ut, consentStateSchema as V, buildQuery as Vt, flowActionRequestSchema as W, guestFlowActionRequestSchema as X, flowStateSchema as Y, orderFlowActionResultSchema as Z, memberPointEntrySchema as _, storefrontCollectionListQuerySchema as _t, myReviewSchema as a, formatOrderNo as at, deliveryTrackingSchema as b, orderItemStatusSchema as bt, publicReviewSchema as c, collectionProductPageSchema as ct, reviewSummarySchema as d, productCardSchema as dt, claimTypeSchema as et, updateReviewRequestSchema as f, productDetailSchema as ft, memberPointEntryPageSchema as g, storefrontCollectionDetailSchema as gt, writableReviewSchema as h, productSortSchema as ht, createReviewResultSchema as i, commerceNumberField as it, createInquiryRequestSchema as j, idpTokenRequestSchema as jt, updateProfileRequestSchema as k, idpAuthorizeRequestSchema as kt, reviewImageUploadRequestSchema as l, collectionProductQuerySchema as lt, uploadTicketSchema as m, productPageSchema as mt, storefrontStoreSchema as n, createClaimResultSchema as nt, productReviewQuerySchema as o, parseOrderNo as ot, updateReviewResultSchema as p, productFacetsSchema as pt, flowFieldValueSchema as q, createReviewRequestSchema as r, myClaimSchema as rt, productReviewSortSchema as s, categoryNodeSchema as st, createStorefrontClient as t, createClaimRequestSchema as tt, reviewPageSchema as u, collectionProductSortSchema as ut, memberPointsSchema as v, storefrontCollectionSchema as vt, purchaseDecisionResultSchema as w, cartItemSchema as wt, myOrderItemSchema as x, pageInfoSchema as xt, storefrontPointPolicySchema as y, claimStatusSchema as yt, consentKindSchema as z, withdrawalBlockedDetailsSchema as zt };
|