@sayren/storefront-sdk 0.20.7 → 0.20.8
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-S_gOAeBM.mjs} +91 -5
- package/dist/{index-atHaDBC3.d.mts → index-Bv49jTFH.d.mts} +760 -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 +49 -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 +88 -0
- package/src/schemas/fulfillment.ts +53 -3
- package/src/schemas/order.ts +10 -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 { t as createStorefrontClient, zt as ApiError } from "../client-S_gOAeBM.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,74 @@ 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
|
+
//#endregion
|
|
519
589
|
//#region src/schemas/consent.ts
|
|
520
590
|
/**
|
|
521
591
|
* 동의 종류 — 이용약관(`TERMS`)·개인정보 수집이용(`PRIVACY`)은 가입 필수, 마케팅 수신(`MARKETING`)은 선택이다.
|
|
@@ -711,7 +781,9 @@ const myOrderItemSchema = z.object({
|
|
|
711
781
|
}).nullable().optional().default(null).describe("배송 없는 상품의 제공 기록(이슈 #48). 제공 전이거나 배송 상품이면 null이다. 배송 없는 상품의 `DELIVERED`는 제공 완료로 표시한다. 서버는 항상 싣는다"),
|
|
712
782
|
claimStatus: z.string().nullable(),
|
|
713
783
|
reviewWritten: z.boolean(),
|
|
714
|
-
autoDecisionDate: z.string().nullable()
|
|
784
|
+
autoDecisionDate: z.string().nullable(),
|
|
785
|
+
flowState: flowStateSchema.optional().describe("주문 플로우의 지금 상태(이슈 #115). 플로우가 없는 주문상품은 없다"),
|
|
786
|
+
actions: z.array(flowActionSchema).optional().describe("지금 할 수 있는 행동. 화면은 이 목록으로 버튼을 그린다(상태 이름으로 분기하지 않는다)")
|
|
715
787
|
});
|
|
716
788
|
/**
|
|
717
789
|
* 주문 응답의 배송지 — 결제 요청 시 저장된 스냅샷. 요청 스키마(`shippingAddressInputSchema`)와 분리한 응답 스키마라
|
|
@@ -1051,6 +1123,11 @@ get: () => http.request("GET", "/store", storefrontStoreSchema) },
|
|
|
1051
1123
|
/** 상품 리뷰 목록 — `variantId`로 옵션(조합)별 리뷰만 받는다(상품 상세 `variants[].variantId`) */
|
|
1052
1124
|
listProductReviews: (productId, params) => http.request("GET", path`/products/${productId}/reviews`, reviewPageSchema, { query: params }),
|
|
1053
1125
|
listProductInquiries: (productId, params) => http.request("GET", path`/products/${productId}/inquiries`, pageSchema(publicInquirySchema), { query: params }),
|
|
1126
|
+
/**
|
|
1127
|
+
* `GET /products/{productId}/calendar` — 날짜별 재고 상품(상세 `inventoryMode: "DATED"`, 이슈 #118)의 날마다 예약 가능 여부·가격.
|
|
1128
|
+
* 기간은 포함이고 최대 120일이다. `variantId`를 생략하면 기본 조합이다
|
|
1129
|
+
*/
|
|
1130
|
+
getProductCalendar: (productId, params) => http.request("GET", path`/products/${productId}/calendar`, z.array(calendarDayViewSchema), { query: params }),
|
|
1054
1131
|
createInquiry: (productId, body) => http.requestVoid("POST", path`/products/${productId}/inquiries`, { body }),
|
|
1055
1132
|
/** 노출 중인 컬렉션(노출 켜짐 + 기간 안) — 셀러가 정한 순서 */
|
|
1056
1133
|
listCollections: (params) => http.request("GET", "/collections", pageSchema(storefrontCollectionSchema), { query: params }),
|
|
@@ -1064,6 +1141,8 @@ get: () => http.request("GET", "/store", storefrontStoreSchema) },
|
|
|
1064
1141
|
/** 컬렉션 상품(판매 중만). `sort`를 생략하면 컬렉션의 기본 정렬이다 */
|
|
1065
1142
|
listCollectionProducts: (slug, params) => http.request("GET", path`/collections/${slug}/products`, collectionProductPageSchema, { query: params })
|
|
1066
1143
|
},
|
|
1144
|
+
/** `GET /pickup-locations` — 방문 수령 장소(이슈 #115). 주문서의 `pickupLocationId`로 고른다 */
|
|
1145
|
+
pickupLocations: { list: () => http.request("GET", "/pickup-locations", z.array(pickupLocationViewSchema)) },
|
|
1067
1146
|
cart: {
|
|
1068
1147
|
get: () => http.request("GET", "/cart", cartSchema),
|
|
1069
1148
|
addItem: (body) => http.request("POST", "/cart/items", cartSchema, { body: addCartItemRequestSchema.parse(body) }),
|
|
@@ -1134,7 +1213,14 @@ get: () => http.request("GET", "/store", storefrontStoreSchema) },
|
|
|
1134
1213
|
*/
|
|
1135
1214
|
getGuestOrder: (orderId, body) => http.request("POST", path`/guest/orders/${orderId}`, myOrderSchema, { body }),
|
|
1136
1215
|
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`)
|
|
1216
|
+
decidePurchase: (orderItemId) => http.requestVoid("POST", path`/me/order-items/${orderItemId}/purchase-decision`),
|
|
1217
|
+
/**
|
|
1218
|
+
* `POST /me/order-items/{id}/actions/{key}` — 주문상품 `actions`에 켜진 행동을 실행한다(#115, 시안 승인 등).
|
|
1219
|
+
* 응답의 `flowState`·`actions`로 화면을 바로 바꾼다. 에러: 409 `ACTION_NOT_AVAILABLE`(`details.reason`)
|
|
1220
|
+
*/
|
|
1221
|
+
act: (orderItemId, key, input = {}) => http.request("POST", path`/me/order-items/${orderItemId}/actions/${key}`, flowActionResultSchema, { body: flowActionRequestSchema.parse({ input }) }),
|
|
1222
|
+
/** 비회원 행동 — 비회원 주문 조회와 같은 연락처·비밀번호 확인과 시도 한도를 지난다 */
|
|
1223
|
+
guestAct: (orderId, orderItemId, key, body) => http.request("POST", path`/guest/orders/${orderId}/items/${orderItemId}/actions/${key}`, flowActionResultSchema, { body: guestFlowActionRequestSchema.parse(body) })
|
|
1138
1224
|
},
|
|
1139
1225
|
myClaims: {
|
|
1140
1226
|
create: (orderItemId, body) => http.request("POST", path`/me/order-items/${orderItemId}/claims`, createClaimResultSchema, { body: createClaimRequestSchema.parse(body) }),
|
|
@@ -1194,4 +1280,4 @@ get: () => http.request("GET", "/store", storefrontStoreSchema) },
|
|
|
1194
1280
|
};
|
|
1195
1281
|
}
|
|
1196
1282
|
//#endregion
|
|
1197
|
-
export {
|
|
1283
|
+
export { claimTypeSchema as $, wishlistAddResultSchema as A, idpTokenRequestSchema as At, consentSourceSchema as B, buildQuery as Bt, orderShippingAddressSchema as C, cartItemSchema as Ct, memberAddressSchema as D, idpAgreementsSchema as Dt, memberAddressRequestSchema as E, anonymousSessionSchema as Et, createCustomerInquiryRequestSchema as F, socialProviderSchema as Ft, flowActionResultSchema as G, consentUpdateRequestSchema as H, unwrapData as Ht, customerInquiryCategorySchema as I, tokenPairSchema as It, flowInputFieldSchema as J, flowActionSchema as K, customerInquirySchema as L, withdrawRequestSchema as Lt, createInquiryResultSchema as M, loginRequestSchema as Mt, productInquiryCategorySchema as N, memberIdentitiesSchema as Nt, memberSchema as O, idpAuthorizeRequestSchema as Ot, publicInquirySchema as P, signupRequestSchema as Pt, claimReturnAddressSchema as Q, consentActionSchema as R, withdrawalBlockedDetailsSchema as Rt, myOrderSchema as S, addCartItemRequestSchema as St, trackingStageResponseSchema as T, updateCartItemRequestSchema as Tt, memberConsentsSchema as U, consentStateSchema as V, toApiError as Vt, flowActionRequestSchema as W, guestFlowActionRequestSchema as X, flowStateSchema as Y, claimReasonSchema as Z, memberPointEntrySchema as _, storefrontCollectionSchema as _t, myReviewSchema as a, parseOrderNo as at, deliveryTrackingSchema as b, pageInfoSchema as bt, publicReviewSchema as c, collectionProductQuerySchema as ct, reviewSummarySchema as d, productDetailSchema as dt, createClaimRequestSchema as et, updateReviewRequestSchema as f, productFacetsSchema as ft, memberPointEntryPageSchema as g, storefrontCollectionListQuerySchema as gt, writableReviewSchema as h, storefrontCollectionDetailSchema as ht, createReviewResultSchema as i, formatOrderNo as it, createInquiryRequestSchema as j, linkIdentityRequestSchema as jt, updateProfileRequestSchema as k, idpAuthorizeResponseSchema as kt, reviewImageUploadRequestSchema as l, collectionProductSortSchema as lt, uploadTicketSchema as m, productSortSchema as mt, storefrontStoreSchema as n, myClaimSchema as nt, productReviewQuerySchema as o, categoryNodeSchema as ot, updateReviewResultSchema as p, productPageSchema as pt, flowFieldValueSchema as q, createReviewRequestSchema as r, commerceNumberField as rt, productReviewSortSchema as s, collectionProductPageSchema as st, createStorefrontClient as t, createClaimResultSchema as tt, reviewPageSchema as u, productCardSchema as ut, memberPointsSchema as v, claimStatusSchema as vt, purchaseDecisionResultSchema as w, cartSchema as wt, myOrderItemSchema as x, pageSchema as xt, storefrontPointPolicySchema as y, orderItemStatusSchema as yt, consentKindSchema as z, ApiError as zt };
|