@sayren/store-sdk 0.33.0 → 0.34.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 +1014 -681
- package/dist/index.mjs +153 -20
- package/package.json +1 -1
- package/src/client.ts +47 -5
- package/src/http.ts +1 -1
- package/src/index.ts +1 -0
- package/src/schemas/payment.ts +2 -2
- package/src/schemas/points.ts +2 -5
- package/src/schemas/product-info.ts +190 -0
- package/src/schemas/product.ts +41 -2
- package/src/schemas/storefront-hosting.ts +6 -10
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 상품정보제공 고시·인증 정보·안내 섹션 (이슈 #135).
|
|
5
|
+
*
|
|
6
|
+
* **코드 값은 문자열이다.** 품목군(`schemaId`)·인증 종류·대상·면제 사유는 플랫폼 코드 표(서버 DB)가 원천이고, 코드가 늘어도 이 SDK의
|
|
7
|
+
* 계약이 깨지지 않게 zod enum으로 막지 않는다. 서버가 코드 표에 있는지 검사한다(없으면 400 `INVALID_INFO_CODE`).
|
|
8
|
+
* enum으로 두는 값은 서버가 그 값으로 분기하는 인증 상태(`CERTIFICATION_STATUSES`)뿐이다.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// ── 플랫폼 코드 표 ────────────────────────────────────────────────
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 칸 값의 출처 — 셀러가 비운 칸을 서버가 채운다. 서버가 분기하는 값이라 형태가 정해져 있지만, 새 출처가 늘 수 있어 응답은 열린 객체다.
|
|
15
|
+
* - `legal`: 법정 문구(`text`). 셀러가 적지 않는다
|
|
16
|
+
* - `option`: 이름이 `names` 중 하나인 조합 옵션명의 값 목록
|
|
17
|
+
* - `store`: 상점 필드(`field`, 예: `customerCenterPhone`)
|
|
18
|
+
*/
|
|
19
|
+
export const infoFieldSourceSchema = z.looseObject({
|
|
20
|
+
type: z.string(),
|
|
21
|
+
text: z.string().optional(),
|
|
22
|
+
names: z.array(z.string()).optional(),
|
|
23
|
+
field: z.string().optional(),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export type InfoFieldSource = z.infer<typeof infoFieldSourceSchema>;
|
|
27
|
+
|
|
28
|
+
export const infoSchemaFieldSchema = z.object({
|
|
29
|
+
key: z.string(),
|
|
30
|
+
label: z.string(),
|
|
31
|
+
required: z
|
|
32
|
+
.boolean()
|
|
33
|
+
.describe("법정 필수 칸인가. 서버는 비어 있어도 막지 않는다(표시는 「상품상세 참조」)"),
|
|
34
|
+
maxLength: z.number().int(),
|
|
35
|
+
source: infoFieldSourceSchema.nullable().optional().describe("값 출처. 없으면 셀러가 적는 칸"),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export type InfoSchemaField = z.infer<typeof infoSchemaFieldSchema>;
|
|
39
|
+
|
|
40
|
+
/** 정형 정보 스키마 — 고시 품목군 하나(`kind: "notice"`). 칸 구성은 버전마다 고정이고 상품은 저장한 버전으로 표시된다 */
|
|
41
|
+
export const infoSchemaSchema = z.object({
|
|
42
|
+
schemaId: z.string().describe("품목군 코드(예: `WEAR`)"),
|
|
43
|
+
version: z.number().int(),
|
|
44
|
+
kind: z.string().describe("스키마 종류. 지금은 `notice`(상품정보제공 고시)"),
|
|
45
|
+
name: z.string(),
|
|
46
|
+
fallback: z.string().describe("비운 칸의 표시 문구(예: 「상품상세 참조」)"),
|
|
47
|
+
fields: z.array(infoSchemaFieldSchema).describe("칸. 배열 순서가 표시 순서다"),
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
export type InfoSchema = z.infer<typeof infoSchemaSchema>;
|
|
51
|
+
|
|
52
|
+
/** 플랫폼 코드 하나 — 코드 묶음(`setId`) 안에서 유일하다. `attrs`는 묶음마다 다른 부가 정보다 */
|
|
53
|
+
export const platformCodeSchema = z.object({
|
|
54
|
+
code: z.string(),
|
|
55
|
+
label: z.string(),
|
|
56
|
+
attrs: z
|
|
57
|
+
.record(z.string(), z.unknown())
|
|
58
|
+
.describe(
|
|
59
|
+
"부가 정보. `certification.subject`는 `kinds`(이 대상을 충족하는 인증 종류)·`exemptions`(허용 면제 사유)를 싣는다",
|
|
60
|
+
),
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
export type PlatformCode = z.infer<typeof platformCodeSchema>;
|
|
64
|
+
|
|
65
|
+
/** 코드 묶음 — `GET /v1/codes/{setId}` */
|
|
66
|
+
export const PLATFORM_CODE_SETS = {
|
|
67
|
+
certificationKind: "certification.kind",
|
|
68
|
+
certificationSubject: "certification.subject",
|
|
69
|
+
certificationExemption: "certification.exemption",
|
|
70
|
+
} as const;
|
|
71
|
+
|
|
72
|
+
// ── 상품 고시 ────────────────────────────────────────────────────
|
|
73
|
+
|
|
74
|
+
export const productNoticeSchema = z.object({
|
|
75
|
+
schemaId: z.string(),
|
|
76
|
+
version: z.number().int(),
|
|
77
|
+
values: z.record(z.string(), z.string()).describe("칸 키 → 셀러가 적은 값. 비운 칸은 없다"),
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
export type ProductNotice = z.infer<typeof productNoticeSchema>;
|
|
81
|
+
|
|
82
|
+
export const MAX_NOTICE_VALUE_LENGTH = 1500;
|
|
83
|
+
|
|
84
|
+
export const productNoticeRequestSchema = z.object({
|
|
85
|
+
schemaId: z.string().trim().min(1).max(50).describe("품목군 코드(`GET /v1/info-schemas`)"),
|
|
86
|
+
version: z.number().int().positive().optional().describe("품목군 버전. 생략하면 현재 버전"),
|
|
87
|
+
values: z
|
|
88
|
+
.record(z.string().max(50), z.string().max(MAX_NOTICE_VALUE_LENGTH))
|
|
89
|
+
.default({})
|
|
90
|
+
.describe(
|
|
91
|
+
"칸 키 → 값. 출처가 `legal`인 칸은 받지 않는다(400). 빈 문자열은 비운 칸으로 저장하지 않는다. 칸 길이는 스키마 `maxLength`",
|
|
92
|
+
),
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
export type ProductNoticeRequest = z.infer<typeof productNoticeRequestSchema>;
|
|
96
|
+
|
|
97
|
+
// ── 상품 인증 ────────────────────────────────────────────────────
|
|
98
|
+
|
|
99
|
+
/** 인증 대상 상태 — 서버가 분기한다(대상이면 인증서 필수, 면제면 사유 필수) */
|
|
100
|
+
export const CERTIFICATION_STATUSES = ["REQUIRED", "NOT_REQUIRED", "EXEMPT"] as const;
|
|
101
|
+
|
|
102
|
+
export type CertificationStatus = (typeof CERTIFICATION_STATUSES)[number];
|
|
103
|
+
|
|
104
|
+
export const MAX_CERTIFICATION_ITEMS = 20;
|
|
105
|
+
|
|
106
|
+
export const productCertificationsSchema = z.object({
|
|
107
|
+
subjects: z
|
|
108
|
+
.array(
|
|
109
|
+
z.object({
|
|
110
|
+
subject: z.string().describe("인증 대상 코드(`certification.subject`)"),
|
|
111
|
+
status: z
|
|
112
|
+
.string()
|
|
113
|
+
.describe("`REQUIRED`·`NOT_REQUIRED`·`EXEMPT`. 값이 늘 수 있어 문자열이다"),
|
|
114
|
+
exemption: z.string().nullable().describe("면제 사유 코드. `EXEMPT`일 때만 있다"),
|
|
115
|
+
}),
|
|
116
|
+
)
|
|
117
|
+
.describe("인증 대상 여부. 없는 대상은 `NOT_REQUIRED`다"),
|
|
118
|
+
items: z
|
|
119
|
+
.array(
|
|
120
|
+
z.object({
|
|
121
|
+
kind: z.string().describe("인증 종류 코드(`certification.kind`)"),
|
|
122
|
+
agency: z.string().nullable().describe("인증 기관"),
|
|
123
|
+
number: z.string().describe("인증 번호"),
|
|
124
|
+
}),
|
|
125
|
+
)
|
|
126
|
+
.describe("인증서. 배열 순서가 표시 순서다"),
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
export type ProductCertifications = z.infer<typeof productCertificationsSchema>;
|
|
130
|
+
|
|
131
|
+
export const productCertificationsRequestSchema = z.object({
|
|
132
|
+
subjects: z
|
|
133
|
+
.array(
|
|
134
|
+
z.object({
|
|
135
|
+
subject: z.string().trim().min(1).max(50),
|
|
136
|
+
status: z.enum(CERTIFICATION_STATUSES),
|
|
137
|
+
exemption: z.string().trim().min(1).max(50).nullish(),
|
|
138
|
+
}),
|
|
139
|
+
)
|
|
140
|
+
.max(20)
|
|
141
|
+
.default([])
|
|
142
|
+
.describe(
|
|
143
|
+
"인증 대상 여부. `REQUIRED`인데 그 대상의 인증 종류(`attrs.kinds`) 인증서가 `items`에 없으면 400 `CERTIFICATION_REQUIRED`, " +
|
|
144
|
+
"`EXEMPT`인데 사유가 없거나 대상이 허용하지 않는 사유면 400 `CERTIFICATION_EXEMPTION_INVALID`",
|
|
145
|
+
),
|
|
146
|
+
items: z
|
|
147
|
+
.array(
|
|
148
|
+
z.object({
|
|
149
|
+
kind: z.string().trim().min(1).max(50),
|
|
150
|
+
agency: z.string().trim().max(100).nullish(),
|
|
151
|
+
number: z.string().trim().min(1).max(100),
|
|
152
|
+
}),
|
|
153
|
+
)
|
|
154
|
+
.max(MAX_CERTIFICATION_ITEMS)
|
|
155
|
+
.default([]),
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
export type ProductCertificationsRequest = z.infer<typeof productCertificationsRequestSchema>;
|
|
159
|
+
export type ProductCertificationsRequestInput = z.input<typeof productCertificationsRequestSchema>;
|
|
160
|
+
|
|
161
|
+
// ── 안내 섹션 ────────────────────────────────────────────────────
|
|
162
|
+
|
|
163
|
+
/** 상품 하나에 연결할 수 있는 안내 섹션 수 */
|
|
164
|
+
export const MAX_PRODUCT_INFO_SECTIONS = 10;
|
|
165
|
+
export const MAX_INFO_SECTION_TITLE = 100;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* 안내 섹션 — 사이즈 가이드·세탁 안내처럼 여러 상품이 같이 쓰는 글이다. **상품은 연결만 한다**(복사가 아니다).
|
|
169
|
+
* 섹션을 고치면 연결된 모든 상품의 표시가 바뀐다.
|
|
170
|
+
*/
|
|
171
|
+
export const infoSectionSchema = z.object({
|
|
172
|
+
infoSectionId: z.string(),
|
|
173
|
+
title: z.string(),
|
|
174
|
+
body: z.string().describe("본문 HTML(상세설명과 같은 정화 규칙)"),
|
|
175
|
+
bodyJson: z.string().nullable().describe("에디터 복원용 직렬화 상태"),
|
|
176
|
+
assignedProductCount: z.number().int().describe("이 섹션을 연결한 상품 수"),
|
|
177
|
+
createdAt: z.string(),
|
|
178
|
+
updatedAt: z.string(),
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
export type InfoSection = z.infer<typeof infoSectionSchema>;
|
|
182
|
+
|
|
183
|
+
export const infoSectionRequestSchema = z.object({
|
|
184
|
+
title: z.string().trim().min(1).max(MAX_INFO_SECTION_TITLE),
|
|
185
|
+
body: z.string().default(""),
|
|
186
|
+
bodyJson: z.string().nullable().optional(),
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
export type InfoSectionRequest = z.infer<typeof infoSectionRequestSchema>;
|
|
190
|
+
export type InfoSectionRequestInput = z.input<typeof infoSectionRequestSchema>;
|
package/src/schemas/product.ts
CHANGED
|
@@ -14,6 +14,13 @@ import {
|
|
|
14
14
|
productFulfillmentUpdateSchema,
|
|
15
15
|
} from "./fulfillment";
|
|
16
16
|
import { pointEarnRateBpSchema } from "./points";
|
|
17
|
+
import {
|
|
18
|
+
MAX_PRODUCT_INFO_SECTIONS,
|
|
19
|
+
productCertificationsRequestSchema,
|
|
20
|
+
productCertificationsSchema,
|
|
21
|
+
productNoticeRequestSchema,
|
|
22
|
+
productNoticeSchema,
|
|
23
|
+
} from "./product-info";
|
|
17
24
|
import { productRefundPolicyPatchSchema } from "./refund-policy";
|
|
18
25
|
import { inventoryModeSchema } from "./stay";
|
|
19
26
|
import { UPLOAD_PURPOSE_LIMITS, uploadExtensionOf } from "./upload";
|
|
@@ -445,6 +452,19 @@ export const productSchema = productSummarySchema.extend({
|
|
|
445
452
|
.describe(
|
|
446
453
|
"설정된 즉시할인. GET /v1/products/{productId}/discount 응답과 같은 형태다. 할인이 없으면 null",
|
|
447
454
|
),
|
|
455
|
+
notice: productNoticeSchema
|
|
456
|
+
.nullable()
|
|
457
|
+
.optional()
|
|
458
|
+
.describe("상품정보제공 고시(이슈 #135). 없으면 null. 서버는 항상 싣는다"),
|
|
459
|
+
certifications: productCertificationsSchema
|
|
460
|
+
.nullable()
|
|
461
|
+
.optional()
|
|
462
|
+
.describe("인증 정보(이슈 #135). 없으면 null. 서버는 항상 싣는다"),
|
|
463
|
+
infoSectionIds: z
|
|
464
|
+
.array(z.string())
|
|
465
|
+
.optional()
|
|
466
|
+
.default([])
|
|
467
|
+
.describe("연결한 안내 섹션 id(이슈 #135). 배열 순서가 표시 순서다. 서버는 항상 싣는다"),
|
|
448
468
|
createdAt: z.string().optional(),
|
|
449
469
|
});
|
|
450
470
|
|
|
@@ -569,14 +589,14 @@ export const optionModelRequestSchema = z.object({
|
|
|
569
589
|
.max(MAX_ADDON_GROUPS)
|
|
570
590
|
.optional()
|
|
571
591
|
.describe(
|
|
572
|
-
"추가 선택 옵션명 전체(이슈 #59). 주면 통째로 바꾸고, 생략하면 등록은 없음·수정은 현재 값을 그대로 둔다. 끄려면 빈 배열을
|
|
592
|
+
"추가 선택 옵션명 전체(이슈 #59). 주면 통째로 바꾸고, 생략하면 등록은 없음·수정은 현재 값을 그대로 둔다. 끄려면 빈 배열을 보낸다",
|
|
573
593
|
),
|
|
574
594
|
customInputs: z
|
|
575
595
|
.array(customInputRequestSchema)
|
|
576
596
|
.max(MAX_CUSTOM_INPUTS)
|
|
577
597
|
.optional()
|
|
578
598
|
.describe(
|
|
579
|
-
"직접 입력 항목 전체(이슈 #59). 배열 순서가 표시 순서다. 주면 통째로 바꾸고, 생략하면 등록은 없음·수정은 현재 값을 그대로 둔다. 항목명에 개인정보성 단어(`CUSTOM_INPUT_FORBIDDEN_WORDS`)가 있으면 400 `CUSTOM_INPUT_LABEL_FORBIDDEN
|
|
599
|
+
"직접 입력 항목 전체(이슈 #59). 배열 순서가 표시 순서다. 주면 통째로 바꾸고, 생략하면 등록은 없음·수정은 현재 값을 그대로 둔다. 항목명에 개인정보성 단어(`CUSTOM_INPUT_FORBIDDEN_WORDS`)가 있으면 400 `CUSTOM_INPUT_LABEL_FORBIDDEN`이다",
|
|
580
600
|
),
|
|
581
601
|
optionSort: optionSortSchema
|
|
582
602
|
.optional()
|
|
@@ -694,6 +714,25 @@ const productWriteShape = {
|
|
|
694
714
|
"상품별 환불 정책 — 준 항목만 상점 기본을 덮어쓴다. `null`이나 생략은 상점 기본을 그대로 쓴다는 뜻이다. " +
|
|
695
715
|
"반품·교환 배송비(`returnDeliveryFee`·`exchangeDeliveryFee`)는 배송 상품에만 줄 수 있다(다른 유형은 400)",
|
|
696
716
|
),
|
|
717
|
+
notice: productNoticeRequestSchema
|
|
718
|
+
.nullable()
|
|
719
|
+
.optional()
|
|
720
|
+
.describe(
|
|
721
|
+
"상품정보제공 고시(이슈 #135). `null`은 지운다. 등록에서 생략하면 없음, 전체 수정(PUT)에서 생략하면 지금 값을 유지한다",
|
|
722
|
+
),
|
|
723
|
+
certifications: productCertificationsRequestSchema
|
|
724
|
+
.nullable()
|
|
725
|
+
.optional()
|
|
726
|
+
.describe(
|
|
727
|
+
"인증 정보(이슈 #135). `null`은 지운다. 등록에서 생략하면 없음, 전체 수정(PUT)에서 생략하면 지금 값을 유지한다",
|
|
728
|
+
),
|
|
729
|
+
infoSectionIds: z
|
|
730
|
+
.array(z.string().min(1))
|
|
731
|
+
.max(MAX_PRODUCT_INFO_SECTIONS)
|
|
732
|
+
.optional()
|
|
733
|
+
.describe(
|
|
734
|
+
"연결할 안내 섹션 id(이슈 #135). 배열 순서가 표시 순서다. 이 상점의 섹션이 아니면 400 `INFO_SECTION_NOT_FOUND`. 전체 수정(PUT)에서 생략하면 지금 연결을 유지한다",
|
|
735
|
+
),
|
|
697
736
|
...optionModelRequestSchema.shape,
|
|
698
737
|
sourceOptionSetIds: z
|
|
699
738
|
.array(z.string())
|
|
@@ -13,7 +13,6 @@ import { RESERVED_STORE_CODES } from "./store";
|
|
|
13
13
|
* 공개 전환·슬러그 변경·호스팅 끄기는 승인(`APPROVAL_REQUIRED`)이다 — 구매자가 보는 화면을 바꾸는 쓰기다.
|
|
14
14
|
*
|
|
15
15
|
* 오류 코드:
|
|
16
|
-
* - 403 `STOREFRONT_HOSTING_DISABLED` — 플랫폼 스위치가 꺼져 새 사이트를 만들 수 없다
|
|
17
16
|
* - 404 `STOREFRONT_SITE_NOT_FOUND` · `STOREFRONT_TEMPLATE_NOT_FOUND` · `STOREFRONT_VERSION_NOT_FOUND`
|
|
18
17
|
* - 409 `STOREFRONT_SITE_EXISTS` — 이미 사이트가 있다(상점당 1개)
|
|
19
18
|
* - 409 `STOREFRONT_SLUG_TAKEN` — 다른 사이트가 쓰거나 보류 중인 슬러그다
|
|
@@ -30,7 +29,7 @@ import { RESERVED_STORE_CODES } from "./store";
|
|
|
30
29
|
* - 503 `STOREFRONT_PREVIEW_NOT_CONFIGURED` — 미리보기 서명 키가 설정되지 않았다
|
|
31
30
|
*
|
|
32
31
|
* 편집(M2b, `/v1/storefront/site/editing`·`files/**`·`checks/**`·`verify`·`builds/**`, 버전 만들기):
|
|
33
|
-
* - 403 `STOREFRONT_EDITING_DISABLED` —
|
|
32
|
+
* - 403 `STOREFRONT_EDITING_DISABLED` — 편집을 쓸 수 없어 셀러 템플릿으로 사이트를 만들 수 없다(사이트 만들기)
|
|
34
33
|
* - 503 `STOREFRONT_EDITING_NOT_CONFIGURED` — 편집 Sandbox가 설정되지 않았다
|
|
35
34
|
* - 409 `EDIT_CAPACITY_FULL` — 플랫폼 전체 동시 편집 상한에 걸렸다. `error.details.retryAfterSeconds` 뒤에 다시 한다
|
|
36
35
|
* - 409 `EDIT_SESSION_REQUIRED` — 편집 미리보기 링크: 편집 환경이 없다
|
|
@@ -392,13 +391,11 @@ export const storefrontSiteSchema = z.object({
|
|
|
392
391
|
});
|
|
393
392
|
export type StorefrontSite = z.infer<typeof storefrontSiteSchema>;
|
|
394
393
|
|
|
395
|
-
/** `GET /v1/storefront/site` —
|
|
394
|
+
/** `GET /v1/storefront/site` — 호스팅 설정과 현재 사이트(없으면 null. 끈 사이트는 싣지 않는다) */
|
|
396
395
|
export const storefrontHostingSchema = z.object({
|
|
397
|
-
enabled: z.boolean().describe("새 사이트를 만들 수 있는가 (
|
|
396
|
+
enabled: z.boolean().describe("새 사이트를 만들 수 있는가 (항상 true)"),
|
|
398
397
|
domain: z.string().describe("호스팅 도메인 (예: `sayren.co`). 사이트 주소는 `{slug}.{domain}`"),
|
|
399
|
-
editingEnabled: z
|
|
400
|
-
.boolean()
|
|
401
|
-
.describe("파일 편집·버전 만들기를 쓸 수 있는가 (플랫폼 편집 스위치와 Sandbox 설정)"),
|
|
398
|
+
editingEnabled: z.boolean().describe("파일 편집·버전 만들기를 쓸 수 있는가 (Sandbox 설정)"),
|
|
402
399
|
site: storefrontSiteSchema.nullable(),
|
|
403
400
|
});
|
|
404
401
|
export type StorefrontHosting = z.infer<typeof storefrontHostingSchema>;
|
|
@@ -574,7 +571,6 @@ export type StorefrontPreviewLink = z.infer<typeof storefrontPreviewLinkSchema>;
|
|
|
574
571
|
// - 결제 복귀·방문 분석·소셜 로그인 허용 목록은 연결된(`ACTIVE`) 도메인을 자동으로 더한다.
|
|
575
572
|
//
|
|
576
573
|
// 오류 코드:
|
|
577
|
-
// - 403 `STOREFRONT_CUSTOM_DOMAINS_DISABLED` — 플랫폼 스위치가 꺼져 도메인을 추가할 수 없다
|
|
578
574
|
// - 400 `STOREFRONT_DOMAIN_INVALID` — 형식이 틀렸거나 연결할 수 없는 도메인이다(`error.details.reason`)
|
|
579
575
|
// - 404 `STOREFRONT_DOMAIN_NOT_FOUND`
|
|
580
576
|
// - 409 `STOREFRONT_DOMAIN_EXISTS` — 이 상점에 이미 추가한 도메인이다
|
|
@@ -798,7 +794,7 @@ export type StorefrontSiteDomain = z.infer<typeof storefrontSiteDomainSchema>;
|
|
|
798
794
|
|
|
799
795
|
/** `GET /v1/storefront/site/domains` — 사이트의 주소 목록(기본 주소 + 내 도메인)과 연결 설정 */
|
|
800
796
|
export const storefrontSiteDomainsSchema = z.object({
|
|
801
|
-
enabled: z.boolean().describe("내 도메인을 추가할 수 있는가 (
|
|
797
|
+
enabled: z.boolean().describe("내 도메인을 추가할 수 있는가 (항상 true)"),
|
|
802
798
|
limit: z.number().int().min(0).describe("상점당 내 도메인 수 상한 (해제한 도메인은 세지 않는다)"),
|
|
803
799
|
target: z.string().describe("CNAME 대상 (예: `sites.sayren.co`)"),
|
|
804
800
|
domains: z.array(storefrontSiteDomainSchema).describe("대표 주소 먼저, 그다음 추가한 순서"),
|
|
@@ -971,7 +967,7 @@ export const storefrontDevLogsSchema = z.object({
|
|
|
971
967
|
export type StorefrontDevLogs = z.infer<typeof storefrontDevLogsSchema>;
|
|
972
968
|
|
|
973
969
|
export const storefrontEditingSchema = z.object({
|
|
974
|
-
enabled: z.boolean().describe("편집을 쓸 수 있는가 (
|
|
970
|
+
enabled: z.boolean().describe("편집을 쓸 수 있는가 (Sandbox 설정)"),
|
|
975
971
|
session: storefrontEditSessionSchema
|
|
976
972
|
.nullable()
|
|
977
973
|
.describe("열린 편집 환경. 잠들었거나 닫았으면 null"),
|