@sayren/store-sdk 0.4.0 → 0.5.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
@@ -1147,7 +1147,7 @@ export declare const customerStatsSchema: z.ZodObject<{
1147
1147
  export declare const customerSummarySchema: z.ZodObject<{
1148
1148
  customerId: z.ZodString;
1149
1149
  name: z.ZodString;
1150
- email: z.ZodString;
1150
+ email: z.ZodNullable<z.ZodString>;
1151
1151
  maskedPhone: z.ZodNullable<z.ZodString>;
1152
1152
  joinedAt: z.ZodString;
1153
1153
  point: z.ZodNumber;
@@ -1171,14 +1171,20 @@ export declare const customerAddressSchema: z.ZodObject<{
1171
1171
  export declare const customerDetailSchema: z.ZodObject<{
1172
1172
  customerId: z.ZodString;
1173
1173
  name: z.ZodString;
1174
- email: z.ZodString;
1174
+ email: z.ZodNullable<z.ZodString>;
1175
1175
  phone: z.ZodNullable<z.ZodString>;
1176
1176
  joinedAt: z.ZodString;
1177
1177
  point: z.ZodNumber;
1178
1178
  marketingAgreed: z.ZodBoolean;
1179
- loginMethods: z.ZodArray<z.ZodEnum<{
1180
- password: "password";
1181
- }>>;
1179
+ loginMethods: z.ZodArray<z.ZodObject<{
1180
+ method: z.ZodEnum<{
1181
+ kakao: "kakao";
1182
+ naver: "naver";
1183
+ google: "google";
1184
+ password: "password";
1185
+ }>;
1186
+ linkedAt: z.ZodString;
1187
+ }, z.core.$strip>>;
1182
1188
  addresses: z.ZodArray<z.ZodObject<{
1183
1189
  addressId: z.ZodString;
1184
1190
  alias: z.ZodString;
@@ -1247,6 +1253,81 @@ export declare const customerWithdrawalBlockedDetailsSchema: z.ZodObject<{
1247
1253
  }, z.core.$strip>;
1248
1254
  export type CustomerWithdrawalBlockedDetails = z.infer<typeof customerWithdrawalBlockedDetailsSchema>;
1249
1255
  //#endregion
1256
+ //#region src/schemas/login.d.ts
1257
+ /** 소셜 로그인 공급자 */
1258
+ export declare const loginProviderSchema: z.ZodEnum<{
1259
+ kakao: "kakao";
1260
+ naver: "naver";
1261
+ google: "google";
1262
+ }>;
1263
+ export type LoginProvider = z.infer<typeof loginProviderSchema>;
1264
+ /** 공급자 연결 상태 — 비밀 값은 앞 4자리만 */
1265
+ export declare const loginProviderStatusSchema: z.ZodObject<{
1266
+ provider: z.ZodEnum<{
1267
+ kakao: "kakao";
1268
+ naver: "naver";
1269
+ google: "google";
1270
+ }>;
1271
+ connected: z.ZodBoolean;
1272
+ enabled: z.ZodBoolean;
1273
+ clientIdPrefix: z.ZodNullable<z.ZodString>;
1274
+ secretPrefix: z.ZodNullable<z.ZodString>;
1275
+ lastTestedAt: z.ZodNullable<z.ZodString>;
1276
+ lastTestOk: z.ZodNullable<z.ZodBoolean>;
1277
+ linkedMemberCount: z.ZodNumber;
1278
+ onlyMethodMemberCount: z.ZodNumber;
1279
+ callbackUrl: z.ZodURL;
1280
+ }, z.core.$strip>;
1281
+ export type LoginProviderStatus = z.infer<typeof loginProviderStatusSchema>;
1282
+ /** `GET /v1/store/login-settings` */
1283
+ export declare const loginSettingsSchema: z.ZodObject<{
1284
+ passwordLoginEnabled: z.ZodBoolean;
1285
+ passwordOnlyMemberCount: z.ZodNumber;
1286
+ storefrontOrigins: z.ZodArray<z.ZodString>;
1287
+ providers: z.ZodArray<z.ZodObject<{
1288
+ provider: z.ZodEnum<{
1289
+ kakao: "kakao";
1290
+ naver: "naver";
1291
+ google: "google";
1292
+ }>;
1293
+ connected: z.ZodBoolean;
1294
+ enabled: z.ZodBoolean;
1295
+ clientIdPrefix: z.ZodNullable<z.ZodString>;
1296
+ secretPrefix: z.ZodNullable<z.ZodString>;
1297
+ lastTestedAt: z.ZodNullable<z.ZodString>;
1298
+ lastTestOk: z.ZodNullable<z.ZodBoolean>;
1299
+ linkedMemberCount: z.ZodNumber;
1300
+ onlyMethodMemberCount: z.ZodNumber;
1301
+ callbackUrl: z.ZodURL;
1302
+ }, z.core.$strip>>;
1303
+ }, z.core.$strip>;
1304
+ export type LoginSettings = z.infer<typeof loginSettingsSchema>;
1305
+ /** `PATCH /v1/store/login-settings` */
1306
+ export declare const updateLoginSettingsRequestSchema: z.ZodObject<{
1307
+ passwordLoginEnabled: z.ZodBoolean;
1308
+ }, z.core.$strip>;
1309
+ export type UpdateLoginSettingsRequest = z.infer<typeof updateLoginSettingsRequestSchema>;
1310
+ /** `PUT /v1/store/auth-providers/{provider}` — 저장 전에 연결 테스트를 한다 */
1311
+ export declare const saveLoginProviderRequestSchema: z.ZodObject<{
1312
+ clientId: z.ZodString;
1313
+ clientSecret: z.ZodString;
1314
+ }, z.core.$strip>;
1315
+ export type SaveLoginProviderRequest = z.infer<typeof saveLoginProviderRequestSchema>;
1316
+ /** `PATCH /v1/store/auth-providers/{provider}` */
1317
+ export declare const updateLoginProviderRequestSchema: z.ZodObject<{
1318
+ enabled: z.ZodBoolean;
1319
+ }, z.core.$strip>;
1320
+ /** 연결 테스트 결과 */
1321
+ export declare const loginProviderTestSchema: z.ZodObject<{
1322
+ ok: z.ZodBoolean;
1323
+ code: z.ZodNullable<z.ZodEnum<{
1324
+ INVALID_CLIENT: "INVALID_CLIENT";
1325
+ PROVIDER_UNAVAILABLE: "PROVIDER_UNAVAILABLE";
1326
+ }>>;
1327
+ testedAt: z.ZodString;
1328
+ }, z.core.$strip>;
1329
+ export type LoginProviderTest = z.infer<typeof loginProviderTestSchema>;
1330
+ //#endregion
1250
1331
  //#region src/schemas/misc.d.ts
1251
1332
  export declare const inquirySchema: z.ZodObject<{
1252
1333
  inquiryId: z.ZodString;
@@ -3472,6 +3553,7 @@ export declare const updateStoreRequestSchema: z.ZodObject<{
3472
3553
  customerCenterPhone: z.ZodOptional<z.ZodString>;
3473
3554
  businessHours: z.ZodOptional<z.ZodString>;
3474
3555
  analyticsAllowedOrigins: z.ZodOptional<z.ZodArray<z.ZodString>>;
3556
+ storefrontOrigins: z.ZodOptional<z.ZodArray<z.ZodString>>;
3475
3557
  guestCheckoutEnabled: z.ZodOptional<z.ZodBoolean>;
3476
3558
  }, z.core.$strip>;
3477
3559
  export type UpdateStoreRequest = z.infer<typeof updateStoreRequestSchema>;
@@ -3489,6 +3571,7 @@ export declare const storeSchema: z.ZodObject<{
3489
3571
  businessNumber: z.ZodNullable<z.ZodString>;
3490
3572
  customerCenterPhone: z.ZodNullable<z.ZodString>;
3491
3573
  analyticsAllowedOrigins: z.ZodArray<z.ZodString>;
3574
+ storefrontOrigins: z.ZodArray<z.ZodString>;
3492
3575
  guestCheckoutEnabled: z.ZodBoolean;
3493
3576
  memberCount: z.ZodNumber;
3494
3577
  createdAt: z.ZodString;
@@ -4605,6 +4688,103 @@ export declare function createStoreClient(options: StoreClientOptions): {
4605
4688
  answer: (inquiryId: string, content: string) => Promise<void>;
4606
4689
  updateAnswer: (inquiryId: string, content: string) => Promise<void>;
4607
4690
  };
4691
+ /**
4692
+ * 구매자 로그인 설정 — 이메일·비밀번호 허용, 소셜 공급자 연결. 비밀 값을 다루므로 콘솔에 로그인한 OWNER만 호출할 수 있다
4693
+ */
4694
+ loginSettings: {
4695
+ get: () => Promise<{
4696
+ passwordLoginEnabled: boolean;
4697
+ passwordOnlyMemberCount: number;
4698
+ storefrontOrigins: string[];
4699
+ providers: {
4700
+ provider: "kakao" | "naver" | "google";
4701
+ connected: boolean;
4702
+ enabled: boolean;
4703
+ clientIdPrefix: string | null;
4704
+ secretPrefix: string | null;
4705
+ lastTestedAt: string | null;
4706
+ lastTestOk: boolean | null;
4707
+ linkedMemberCount: number;
4708
+ onlyMethodMemberCount: number;
4709
+ callbackUrl: string;
4710
+ }[];
4711
+ }>;
4712
+ update: (body: UpdateLoginSettingsRequest) => Promise<{
4713
+ passwordLoginEnabled: boolean;
4714
+ passwordOnlyMemberCount: number;
4715
+ storefrontOrigins: string[];
4716
+ providers: {
4717
+ provider: "kakao" | "naver" | "google";
4718
+ connected: boolean;
4719
+ enabled: boolean;
4720
+ clientIdPrefix: string | null;
4721
+ secretPrefix: string | null;
4722
+ lastTestedAt: string | null;
4723
+ lastTestOk: boolean | null;
4724
+ linkedMemberCount: number;
4725
+ onlyMethodMemberCount: number;
4726
+ callbackUrl: string;
4727
+ }[];
4728
+ }>;
4729
+ /** 키 저장 — 저장 전에 연결 테스트를 하고, 실패하면 422 `LOGIN_PROVIDER_VERIFICATION_FAILED` */
4730
+ saveProvider: (provider: LoginProvider, body: SaveLoginProviderRequest) => Promise<{
4731
+ passwordLoginEnabled: boolean;
4732
+ passwordOnlyMemberCount: number;
4733
+ storefrontOrigins: string[];
4734
+ providers: {
4735
+ provider: "kakao" | "naver" | "google";
4736
+ connected: boolean;
4737
+ enabled: boolean;
4738
+ clientIdPrefix: string | null;
4739
+ secretPrefix: string | null;
4740
+ lastTestedAt: string | null;
4741
+ lastTestOk: boolean | null;
4742
+ linkedMemberCount: number;
4743
+ onlyMethodMemberCount: number;
4744
+ callbackUrl: string;
4745
+ }[];
4746
+ }>;
4747
+ setProviderEnabled: (provider: LoginProvider, enabled: boolean) => Promise<{
4748
+ passwordLoginEnabled: boolean;
4749
+ passwordOnlyMemberCount: number;
4750
+ storefrontOrigins: string[];
4751
+ providers: {
4752
+ provider: "kakao" | "naver" | "google";
4753
+ connected: boolean;
4754
+ enabled: boolean;
4755
+ clientIdPrefix: string | null;
4756
+ secretPrefix: string | null;
4757
+ lastTestedAt: string | null;
4758
+ lastTestOk: boolean | null;
4759
+ linkedMemberCount: number;
4760
+ onlyMethodMemberCount: number;
4761
+ callbackUrl: string;
4762
+ }[];
4763
+ }>;
4764
+ testProvider: (provider: LoginProvider) => Promise<{
4765
+ ok: boolean;
4766
+ code: "INVALID_CLIENT" | "PROVIDER_UNAVAILABLE" | null;
4767
+ testedAt: string;
4768
+ }>;
4769
+ /** 연결 해제 — 키를 지운다. 연결된 구매자 계정은 남는다 */
4770
+ removeProvider: (provider: LoginProvider) => Promise<{
4771
+ passwordLoginEnabled: boolean;
4772
+ passwordOnlyMemberCount: number;
4773
+ storefrontOrigins: string[];
4774
+ providers: {
4775
+ provider: "kakao" | "naver" | "google";
4776
+ connected: boolean;
4777
+ enabled: boolean;
4778
+ clientIdPrefix: string | null;
4779
+ secretPrefix: string | null;
4780
+ lastTestedAt: string | null;
4781
+ lastTestOk: boolean | null;
4782
+ linkedMemberCount: number;
4783
+ onlyMethodMemberCount: number;
4784
+ callbackUrl: string;
4785
+ }[];
4786
+ }>;
4787
+ };
4608
4788
  /** 구매자 관리 — 조회 `customer:r`, 탈퇴 처리 `customer:rw`(콘솔 OWNER·ADMIN) */
4609
4789
  customers: {
4610
4790
  list: (params?: PageParams & Omit<z.input<typeof customerListQuerySchema>, "page" | "size">) => Promise<{
@@ -4615,7 +4795,7 @@ export declare function createStoreClient(options: StoreClientOptions): {
4615
4795
  contents: {
4616
4796
  customerId: string;
4617
4797
  name: string;
4618
- email: string;
4798
+ email: string | null;
4619
4799
  maskedPhone: string | null;
4620
4800
  joinedAt: string;
4621
4801
  point: number;
@@ -4628,12 +4808,15 @@ export declare function createStoreClient(options: StoreClientOptions): {
4628
4808
  get: (customerId: string) => Promise<{
4629
4809
  customerId: string;
4630
4810
  name: string;
4631
- email: string;
4811
+ email: string | null;
4632
4812
  phone: string | null;
4633
4813
  joinedAt: string;
4634
4814
  point: number;
4635
4815
  marketingAgreed: boolean;
4636
- loginMethods: "password"[];
4816
+ loginMethods: {
4817
+ method: "kakao" | "naver" | "google" | "password";
4818
+ linkedAt: string;
4819
+ }[];
4637
4820
  addresses: {
4638
4821
  addressId: string;
4639
4822
  alias: string;
@@ -5934,6 +6117,7 @@ export declare function createStoreClient(options: StoreClientOptions): {
5934
6117
  businessNumber: string | null;
5935
6118
  customerCenterPhone: string | null;
5936
6119
  analyticsAllowedOrigins: string[];
6120
+ storefrontOrigins: string[];
5937
6121
  guestCheckoutEnabled: boolean;
5938
6122
  memberCount: number;
5939
6123
  createdAt: string;
@@ -5952,6 +6136,7 @@ export declare function createStoreClient(options: StoreClientOptions): {
5952
6136
  businessNumber: string | null;
5953
6137
  customerCenterPhone: string | null;
5954
6138
  analyticsAllowedOrigins: string[];
6139
+ storefrontOrigins: string[];
5955
6140
  guestCheckoutEnabled: boolean;
5956
6141
  memberCount: number;
5957
6142
  createdAt: string;
package/dist/index.mjs CHANGED
@@ -726,7 +726,8 @@ const customerStatsSchema = z.object({
726
726
  const customerSummarySchema = z.object({
727
727
  customerId: z.string(),
728
728
  name: z.string(),
729
- email: z.string(),
729
+ /** 소셜 가입에서 이메일을 받지 못했으면 null */
730
+ email: z.string().nullable(),
730
731
  maskedPhone: z.string().nullable(),
731
732
  joinedAt: z.string(),
732
733
  point: z.number().int(),
@@ -746,12 +747,21 @@ const customerAddressSchema = z.object({
746
747
  const customerDetailSchema = z.object({
747
748
  customerId: z.string(),
748
749
  name: z.string(),
749
- email: z.string(),
750
+ email: z.string().nullable(),
750
751
  phone: z.string().nullable(),
751
752
  joinedAt: z.string(),
752
753
  point: z.number().int(),
753
754
  marketingAgreed: z.boolean(),
754
- loginMethods: z.array(z.enum(["password"])).describe("로그인 방법. 지금은 이메일·비밀번호(`password`)뿐이다"),
755
+ loginMethods: z.array(z.object({
756
+ method: z.enum([
757
+ "password",
758
+ "kakao",
759
+ "naver",
760
+ "google"
761
+ ]),
762
+ /** 소셜 연결 시각. 비밀번호는 가입 시각 */
763
+ linkedAt: z.string()
764
+ })).describe("로그인 방법 — 이메일·비밀번호(`password`)와 연결된 소셜 계정"),
755
765
  addresses: z.array(customerAddressSchema),
756
766
  stats: customerStatsSchema.extend({
757
767
  canceledOrReturnedCount: z.number().int().describe("취소된 주문 상품 + 완료된 반품 수"),
@@ -795,6 +805,53 @@ const customerWithdrawalBlockedDetailsSchema = z.object({
795
805
  pendingPayments: z.number().int()
796
806
  });
797
807
  //#endregion
808
+ //#region src/schemas/login.ts
809
+ /** 소셜 로그인 공급자 */
810
+ const loginProviderSchema = z.enum([
811
+ "kakao",
812
+ "naver",
813
+ "google"
814
+ ]);
815
+ /** 공급자 연결 상태 — 비밀 값은 앞 4자리만 */
816
+ const loginProviderStatusSchema = z.object({
817
+ provider: loginProviderSchema,
818
+ connected: z.boolean(),
819
+ /** 스토어프런트에서 사용 중인지. 연결 안 됐으면 false */
820
+ enabled: z.boolean(),
821
+ clientIdPrefix: z.string().nullable().describe("클라이언트 ID(카카오 REST API 키) 앞 4자리"),
822
+ secretPrefix: z.string().nullable(),
823
+ lastTestedAt: z.string().nullable(),
824
+ lastTestOk: z.boolean().nullable(),
825
+ linkedMemberCount: z.number().int().describe("이 공급자로 연결된 구매자 수"),
826
+ /** 이 공급자로만 로그인하는 구매자 수 — 연결을 해제하면 로그인할 방법이 없어진다 */
827
+ onlyMethodMemberCount: z.number().int(),
828
+ callbackUrl: z.url().describe("공급자 개발자 콘솔에 등록할 리디렉트 URI")
829
+ });
830
+ /** `GET /v1/store/login-settings` */
831
+ const loginSettingsSchema = z.object({
832
+ passwordLoginEnabled: z.boolean(),
833
+ /** 비밀번호로만 로그인하는 구매자 수 — 이메일·비밀번호를 끄면 이들은 로그인할 수 없다 */
834
+ passwordOnlyMemberCount: z.number().int(),
835
+ storefrontOrigins: z.array(z.string()),
836
+ providers: z.array(loginProviderStatusSchema)
837
+ });
838
+ /** `PATCH /v1/store/login-settings` */
839
+ const updateLoginSettingsRequestSchema = z.object({ passwordLoginEnabled: z.boolean() });
840
+ /** `PUT /v1/store/auth-providers/{provider}` — 저장 전에 연결 테스트를 한다 */
841
+ const saveLoginProviderRequestSchema = z.object({
842
+ clientId: z.string().trim().min(1).max(200),
843
+ clientSecret: z.string().trim().min(1).max(500)
844
+ });
845
+ /** `PATCH /v1/store/auth-providers/{provider}` */
846
+ const updateLoginProviderRequestSchema = z.object({ enabled: z.boolean() });
847
+ /** 연결 테스트 결과 */
848
+ const loginProviderTestSchema = z.object({
849
+ ok: z.boolean(),
850
+ /** 실패 이유 — `INVALID_CLIENT`(키가 틀림)·`PROVIDER_UNAVAILABLE`(공급자 응답 없음) */
851
+ code: z.enum(["INVALID_CLIENT", "PROVIDER_UNAVAILABLE"]).nullable(),
852
+ testedAt: z.string()
853
+ });
854
+ //#endregion
798
855
  //#region src/schemas/misc.ts
799
856
  const inquirySchema = z.object({
800
857
  inquiryId: z.string(),
@@ -1826,7 +1883,8 @@ const updateStoreRequestSchema = z.object({
1826
1883
  logoUrl: z.url().optional(),
1827
1884
  customerCenterPhone: z.string().optional(),
1828
1885
  businessHours: z.string().max(100).optional(),
1829
- analyticsAllowedOrigins: z.array(analyticsOriginSchema).max(20).optional().describe("방문 분석 수집을 받을 스토어프런트 오리진(최대 20개). 비우면 모든 오리진에서 받는다. 넣으면 목록에 없는 오리진의 수집 요청은 403 `ORIGIN_NOT_ALLOWED`이고, 페이지 URL이 목록 밖인 이벤트는 버린다"),
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`와 같은 목록이다(둘 다 주면 이 값이 이긴다)"),
1830
1888
  guestCheckoutEnabled: z.boolean().optional().describe("비회원 주문 허용. false(회원만)면 로그인하지 않은 구매자의 주문서 생성·결제 요청이 403 `GUEST_CHECKOUT_DISABLED`다. 장바구니 담기와 이미 받은 비회원 주문의 조회·취소는 막지 않는다")
1831
1889
  }).refine((value) => Object.values(value).some((v) => v !== void 0), { message: "최소 1개 필드가 필요합니다" });
1832
1890
  const storeSchema = z.object({
@@ -1843,6 +1901,7 @@ const storeSchema = z.object({
1843
1901
  businessNumber: z.string().nullable(),
1844
1902
  customerCenterPhone: z.string().nullable(),
1845
1903
  analyticsAllowedOrigins: z.array(z.string()).describe("방문 분석 수집을 받는 스토어프런트 오리진. 비어 있으면 모든 오리진에서 받는다"),
1904
+ storefrontOrigins: z.array(z.string()).describe("스토어프런트 도메인 — 소셜 로그인 리디렉트와 방문 분석 수집이 함께 쓴다(`analyticsAllowedOrigins`와 같은 값)"),
1846
1905
  guestCheckoutEnabled: z.boolean().describe("비회원 주문 허용. false면 회원만 주문할 수 있다"),
1847
1906
  memberCount: z.number().int(),
1848
1907
  createdAt: z.string()
@@ -2151,6 +2210,19 @@ function createStoreClient(options) {
2151
2210
  answer: (inquiryId, content) => storeHttp.requestVoid("POST", path`/inquiries/${inquiryId}/answer`, { body: { content } }),
2152
2211
  updateAnswer: (inquiryId, content) => storeHttp.requestVoid("PUT", path`/inquiries/${inquiryId}/answer`, { body: { content } })
2153
2212
  },
2213
+ /**
2214
+ * 구매자 로그인 설정 — 이메일·비밀번호 허용, 소셜 공급자 연결. 비밀 값을 다루므로 콘솔에 로그인한 OWNER만 호출할 수 있다
2215
+ */
2216
+ loginSettings: {
2217
+ get: () => storeHttp.request("GET", "/store/login-settings", loginSettingsSchema),
2218
+ update: (body) => storeHttp.request("PATCH", "/store/login-settings", loginSettingsSchema, { body: updateLoginSettingsRequestSchema.parse(body) }),
2219
+ /** 키 저장 — 저장 전에 연결 테스트를 하고, 실패하면 422 `LOGIN_PROVIDER_VERIFICATION_FAILED` */
2220
+ saveProvider: (provider, body) => storeHttp.request("PUT", path`/store/auth-providers/${provider}`, loginSettingsSchema, { body: saveLoginProviderRequestSchema.parse(body) }),
2221
+ setProviderEnabled: (provider, enabled) => storeHttp.request("PATCH", path`/store/auth-providers/${provider}`, loginSettingsSchema, { body: { enabled } }),
2222
+ testProvider: (provider) => storeHttp.request("POST", path`/store/auth-providers/${provider}/test`, loginProviderTestSchema),
2223
+ /** 연결 해제 — 키를 지운다. 연결된 구매자 계정은 남는다 */
2224
+ removeProvider: (provider) => storeHttp.request("DELETE", path`/store/auth-providers/${provider}`, loginSettingsSchema)
2225
+ },
2154
2226
  /** 구매자 관리 — 조회 `customer:r`, 탈퇴 처리 `customer:rw`(콘솔 OWNER·ADMIN) */
2155
2227
  customers: {
2156
2228
  list: (params) => storeHttp.request("GET", "/customers", pageSchema(customerSummarySchema), { query: params }),
@@ -2731,4 +2803,4 @@ function createStoreSession(options) {
2731
2803
  };
2732
2804
  }
2733
2805
  //#endregion
2734
- export { ApiError, MAX_ANALYTICS_ALLOWED_ORIGINS, MAX_OPTION_GROUPS, MAX_VALUES_PER_GROUP, MAX_VARIANTS, PAYMENT_ROUTING_EXCLUSION_CODES, PORTONE_CHANNEL_NAME_MAX_LENGTH, PORTONE_MAX_CHANNELS, PORTONE_MIN_CHANNELS, RESERVED_STORE_CODES, STORE_CODE_PATTERN, STORE_ROLE_SCOPES, STORE_SCOPE_RESOURCES, STORE_SESSION_KEYS, TOSS_WIDGET_CLIENT_KEY_PATTERN, TOSS_WIDGET_KEY_MESSAGE, TOSS_WIDGET_SECRET_KEY_PATTERN, VARIANT_STOCK_EXCLUSIVE_MESSAGE, WEBHOOK_DEFAULT_TOLERANCE_SEC, WEBHOOK_DELIVERY_ID_HEADER, WEBHOOK_EVENT_ID_HEADER, WEBHOOK_EVENT_TYPE_HEADER, WEBHOOK_HEADERS, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_USER_AGENT, addressChangeRequestListSchema, addressTypeSchema, analyticsChannelSchema, analyticsFunnelStepSchema, analyticsOriginSchema, analyticsOverviewSchema, analyticsProductRowSchema, analyticsProductSortSchema, analyticsProductsQuerySchema, analyticsProductsSchema, analyticsRangeQuerySchema, analyticsSourceGroupBySchema, analyticsSourceRowSchema, analyticsSourcesQuerySchema, analyticsSourcesSchema, analyticsTotalsSchema, apiClientListQuerySchema, apiClientSchema, apiClientSecretRotatedSchema, apiClientStatusSchema, apiClientTypeSchema, apiLogErrorSchema, apiLogListQuerySchema, apiLogPageSchema, apiLogPrincipalSchema, apiLogPrincipalTypeSchema, apiLogSchema, apiLogStatusFilterSchema, apiLogSummarySchema, apiTokenCreateRequestSchema, apiTokenCreatedSchema, apiTokenSchema, approveClaimResultSchema, buildAuthorizeUrl, buildQuery, bulkResultSchema, cancelBySellerRequestSchema, cancelBySellerResultSchema, carrierSchema, categoryAttributeSchema, categoryCreateRequestSchema, categoryDeleteQuerySchema, categoryDeleteStrategySchema, categoryListQuerySchema, categoryPatchRequestSchema, categoryProductSortSchema, categorySchema, categorySearchResultSchema, categoryTreeNodeSchema, categoryWithPathSchema, changeTypeSchema, claimDetailSchema, claimHoldResultSchema, claimListQuerySchema, claimReasonSchema, claimSchema, claimStatusSchema, claimTypeSchema, claimWebhookEventDataSchema, claimWebhookEventSchema, clientCredentialsTokenResponseSchema, createPkcePair, createStoreClient, createStoreSession, customerAddressSchema, customerDetailSchema, customerInquiryCategorySchema, customerInquiryListQuerySchema, customerListQuerySchema, customerOrderSchema, customerSortSchema, customerStatsSchema, customerSummarySchema, customerWithdrawalBlockedDetailsSchema, deliveryInfoSchema, deliveryMethodSchema, deliveryStatusSchema, deliveryTypeSchema, discountRequestSchema, discountSchema, dispatchRequestSchema, effectivePaymentRoutingModeSchema, eventTypeSchema, exchangeAuthorizationCode, exchangeStoreTokenViaOAuth, holdOrderItemRequestSchema, inquiryListQuerySchema, inquirySchema, inquiryWebhookEventDataSchema, inquiryWebhookEventSchema, invitationListQuerySchema, invitationSchema, isReservedStoreCode, isStoreScope, isWebOrigin, liveGateConditionCodeSchema, liveGateConditionSchema, liveGateErrorDetailsSchema, liveGateSchema, maskedSecretSchema, myAccountSchema, myStoreSchema, oauthClientRegistrationRequestSchema, oauthClientRegistrationResponseSchema, oauthTokenResponseSchema, optionGroupRequestSchema, optionGroupSchema, optionModelRequestSchema, optionModelSchema, optionValueRequestSchema, optionValueSchema, orderItemListQuerySchema, orderItemMemoResultSchema, orderItemPageSchema, orderItemSchema, orderItemStatusSchema, orderListQuerySchema, orderSchema, orderSummaryPageSchema, orderSummarySchema, orderWebhookEventDataSchema, orderWebhookEventSchema, pageInfoSchema, pageQueryShape, pageSchema, paymentAttemptRecordSchema, paymentAttemptStatusSchema, paymentCredentialSetSchema, paymentListQuerySchema, paymentProviderSchema, paymentProviderVerificationSchema, paymentRecordDetailSchema, paymentRecordPageSchema, paymentRecordSchema, paymentRecordStatusSchema, paymentRefundRecordSchema, paymentRoutingModeSchema, paymentSettingsSchema, pgEnvironmentSchema, pgPaymentMethodSchema, pgProviderSchema, pgVerificationResultSchema, portOneChannelSchema, portOneCredentialsInputSchema, productCreateRequestSchema, productImageUploadResultSchema, productListQuerySchema, productOutOfStockWebhookEventDataSchema, productOutOfStockWebhookEventSchema, productPatchRequestSchema, productSchema, productSortSchema, productStatusSchema, productSummarySchema, productVariantRequestSchema, productVariantSchema, purchaseDecisionExtendResultSchema, purchaseDecisionRequestResultSchema, refreshUserToken, rejectClaimRequestSchema, reviewListQuerySchema, reviewReportResultSchema, reviewSchema, reviewSortSchema, reviewWebhookEventDataSchema, reviewWebhookEventSchema, salesReportGroupBySchema, salesReportQuerySchema, salesReportRowSchema, salesReportSchema, salesTotalsSchema, scopeAccessSchema, sellerAddressListQuerySchema, sellerAddressRequestSchema, sellerAddressSchema, sellerCustomerInquirySchema, settlementDetailQuerySchema, settlementDetailSchema, settlementListQuerySchema, settlementStatusSchema, settlementSummarySchema, settlementWithDetailsSchema, shippingAddressSchema, storeCodeSchema, storeMemberRoleUpdatedSchema, storeMemberSchema, storeRoleSchema, storeSchema, storeScopeResourceSchema, storeTokenResponseSchema, tossPaymentsCredentialsInputSchema, trackingUpdateResultSchema, updatePaymentProviderRequestSchema, updatePaymentSettingsRequestSchema, updateStoreRequestSchema, uploadRequestSchema, uploadTicketSchema, upsertPortOneProviderRequestSchema, upsertTossPaymentsProviderRequestSchema, userTokenResponseSchema, variantStockRequestSchema, variantStockSchema, verifyPaymentProviderRequestSchema, webhookCreatedSchema, webhookDeliveryErrorCodeSchema, webhookDeliveryListQuerySchema, webhookDeliverySchema, webhookDeliveryStatusSchema, webhookEventSchema, webhookRedeliverFailedResultSchema, webhookRequestSchema, webhookSchema, webhookSecretRotatedSchema, webhookStatusSchema, webhookTestRequestSchema, webhookTestResultSchema, withdrawCustomerRequestSchema };
2806
+ export { ApiError, MAX_ANALYTICS_ALLOWED_ORIGINS, MAX_OPTION_GROUPS, MAX_VALUES_PER_GROUP, MAX_VARIANTS, PAYMENT_ROUTING_EXCLUSION_CODES, PORTONE_CHANNEL_NAME_MAX_LENGTH, PORTONE_MAX_CHANNELS, PORTONE_MIN_CHANNELS, RESERVED_STORE_CODES, STORE_CODE_PATTERN, STORE_ROLE_SCOPES, STORE_SCOPE_RESOURCES, STORE_SESSION_KEYS, TOSS_WIDGET_CLIENT_KEY_PATTERN, TOSS_WIDGET_KEY_MESSAGE, TOSS_WIDGET_SECRET_KEY_PATTERN, VARIANT_STOCK_EXCLUSIVE_MESSAGE, WEBHOOK_DEFAULT_TOLERANCE_SEC, WEBHOOK_DELIVERY_ID_HEADER, WEBHOOK_EVENT_ID_HEADER, WEBHOOK_EVENT_TYPE_HEADER, WEBHOOK_HEADERS, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_USER_AGENT, addressChangeRequestListSchema, addressTypeSchema, analyticsChannelSchema, analyticsFunnelStepSchema, analyticsOriginSchema, analyticsOverviewSchema, analyticsProductRowSchema, analyticsProductSortSchema, analyticsProductsQuerySchema, analyticsProductsSchema, analyticsRangeQuerySchema, analyticsSourceGroupBySchema, analyticsSourceRowSchema, analyticsSourcesQuerySchema, analyticsSourcesSchema, analyticsTotalsSchema, apiClientListQuerySchema, apiClientSchema, apiClientSecretRotatedSchema, apiClientStatusSchema, apiClientTypeSchema, apiLogErrorSchema, apiLogListQuerySchema, apiLogPageSchema, apiLogPrincipalSchema, apiLogPrincipalTypeSchema, apiLogSchema, apiLogStatusFilterSchema, apiLogSummarySchema, apiTokenCreateRequestSchema, apiTokenCreatedSchema, apiTokenSchema, approveClaimResultSchema, buildAuthorizeUrl, buildQuery, bulkResultSchema, cancelBySellerRequestSchema, cancelBySellerResultSchema, carrierSchema, categoryAttributeSchema, categoryCreateRequestSchema, categoryDeleteQuerySchema, categoryDeleteStrategySchema, categoryListQuerySchema, categoryPatchRequestSchema, categoryProductSortSchema, categorySchema, categorySearchResultSchema, categoryTreeNodeSchema, categoryWithPathSchema, changeTypeSchema, claimDetailSchema, claimHoldResultSchema, claimListQuerySchema, claimReasonSchema, claimSchema, claimStatusSchema, claimTypeSchema, claimWebhookEventDataSchema, claimWebhookEventSchema, clientCredentialsTokenResponseSchema, createPkcePair, createStoreClient, createStoreSession, customerAddressSchema, customerDetailSchema, customerInquiryCategorySchema, customerInquiryListQuerySchema, customerListQuerySchema, customerOrderSchema, customerSortSchema, customerStatsSchema, customerSummarySchema, customerWithdrawalBlockedDetailsSchema, deliveryInfoSchema, deliveryMethodSchema, deliveryStatusSchema, deliveryTypeSchema, discountRequestSchema, discountSchema, dispatchRequestSchema, effectivePaymentRoutingModeSchema, eventTypeSchema, exchangeAuthorizationCode, exchangeStoreTokenViaOAuth, holdOrderItemRequestSchema, inquiryListQuerySchema, inquirySchema, inquiryWebhookEventDataSchema, inquiryWebhookEventSchema, invitationListQuerySchema, invitationSchema, isReservedStoreCode, isStoreScope, isWebOrigin, liveGateConditionCodeSchema, liveGateConditionSchema, liveGateErrorDetailsSchema, liveGateSchema, loginProviderSchema, loginProviderStatusSchema, loginProviderTestSchema, loginSettingsSchema, maskedSecretSchema, myAccountSchema, myStoreSchema, oauthClientRegistrationRequestSchema, oauthClientRegistrationResponseSchema, oauthTokenResponseSchema, optionGroupRequestSchema, optionGroupSchema, optionModelRequestSchema, optionModelSchema, optionValueRequestSchema, optionValueSchema, orderItemListQuerySchema, orderItemMemoResultSchema, orderItemPageSchema, orderItemSchema, orderItemStatusSchema, orderListQuerySchema, orderSchema, orderSummaryPageSchema, orderSummarySchema, orderWebhookEventDataSchema, orderWebhookEventSchema, pageInfoSchema, pageQueryShape, pageSchema, paymentAttemptRecordSchema, paymentAttemptStatusSchema, paymentCredentialSetSchema, paymentListQuerySchema, paymentProviderSchema, paymentProviderVerificationSchema, paymentRecordDetailSchema, paymentRecordPageSchema, paymentRecordSchema, paymentRecordStatusSchema, paymentRefundRecordSchema, paymentRoutingModeSchema, paymentSettingsSchema, pgEnvironmentSchema, pgPaymentMethodSchema, pgProviderSchema, pgVerificationResultSchema, portOneChannelSchema, portOneCredentialsInputSchema, productCreateRequestSchema, productImageUploadResultSchema, productListQuerySchema, productOutOfStockWebhookEventDataSchema, productOutOfStockWebhookEventSchema, productPatchRequestSchema, productSchema, productSortSchema, productStatusSchema, productSummarySchema, productVariantRequestSchema, productVariantSchema, purchaseDecisionExtendResultSchema, purchaseDecisionRequestResultSchema, refreshUserToken, rejectClaimRequestSchema, reviewListQuerySchema, reviewReportResultSchema, reviewSchema, reviewSortSchema, reviewWebhookEventDataSchema, reviewWebhookEventSchema, salesReportGroupBySchema, salesReportQuerySchema, salesReportRowSchema, salesReportSchema, salesTotalsSchema, saveLoginProviderRequestSchema, scopeAccessSchema, sellerAddressListQuerySchema, sellerAddressRequestSchema, sellerAddressSchema, sellerCustomerInquirySchema, settlementDetailQuerySchema, settlementDetailSchema, settlementListQuerySchema, settlementStatusSchema, settlementSummarySchema, settlementWithDetailsSchema, shippingAddressSchema, storeCodeSchema, storeMemberRoleUpdatedSchema, storeMemberSchema, storeRoleSchema, storeSchema, storeScopeResourceSchema, storeTokenResponseSchema, tossPaymentsCredentialsInputSchema, trackingUpdateResultSchema, updateLoginProviderRequestSchema, updateLoginSettingsRequestSchema, updatePaymentProviderRequestSchema, updatePaymentSettingsRequestSchema, updateStoreRequestSchema, uploadRequestSchema, uploadTicketSchema, upsertPortOneProviderRequestSchema, upsertTossPaymentsProviderRequestSchema, userTokenResponseSchema, variantStockRequestSchema, variantStockSchema, verifyPaymentProviderRequestSchema, webhookCreatedSchema, webhookDeliveryErrorCodeSchema, webhookDeliveryListQuerySchema, webhookDeliverySchema, webhookDeliveryStatusSchema, webhookEventSchema, webhookRedeliverFailedResultSchema, webhookRequestSchema, webhookSchema, webhookSecretRotatedSchema, webhookStatusSchema, webhookTestRequestSchema, webhookTestResultSchema, withdrawCustomerRequestSchema };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sayren/store-sdk",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "main": "./dist/index.mjs",
5
5
  "types": "./dist/index.d.mts",
6
6
  "exports": {
package/src/client.ts CHANGED
@@ -60,6 +60,15 @@ import {
60
60
  type WithdrawCustomerRequest,
61
61
  withdrawCustomerRequestSchema,
62
62
  } from "./schemas/customer";
63
+ import {
64
+ type LoginProvider,
65
+ loginProviderTestSchema,
66
+ loginSettingsSchema,
67
+ type SaveLoginProviderRequest,
68
+ saveLoginProviderRequestSchema,
69
+ type UpdateLoginSettingsRequest,
70
+ updateLoginSettingsRequestSchema,
71
+ } from "./schemas/login";
63
72
  import {
64
73
  type CustomerInquiryCategory,
65
74
  inquirySchema,
@@ -567,6 +576,35 @@ export function createStoreClient(options: StoreClientOptions) {
567
576
  storeHttp.requestVoid("PUT", path`/inquiries/${inquiryId}/answer`, { body: { content } }),
568
577
  },
569
578
 
579
+ /**
580
+ * 구매자 로그인 설정 — 이메일·비밀번호 허용, 소셜 공급자 연결. 비밀 값을 다루므로 콘솔에 로그인한 OWNER만 호출할 수 있다
581
+ */
582
+ loginSettings: {
583
+ get: () => storeHttp.request("GET", "/store/login-settings", loginSettingsSchema),
584
+ update: (body: UpdateLoginSettingsRequest) =>
585
+ storeHttp.request("PATCH", "/store/login-settings", loginSettingsSchema, {
586
+ body: updateLoginSettingsRequestSchema.parse(body),
587
+ }),
588
+ /** 키 저장 — 저장 전에 연결 테스트를 하고, 실패하면 422 `LOGIN_PROVIDER_VERIFICATION_FAILED` */
589
+ saveProvider: (provider: LoginProvider, body: SaveLoginProviderRequest) =>
590
+ storeHttp.request("PUT", path`/store/auth-providers/${provider}`, loginSettingsSchema, {
591
+ body: saveLoginProviderRequestSchema.parse(body),
592
+ }),
593
+ setProviderEnabled: (provider: LoginProvider, enabled: boolean) =>
594
+ storeHttp.request("PATCH", path`/store/auth-providers/${provider}`, loginSettingsSchema, {
595
+ body: { enabled },
596
+ }),
597
+ testProvider: (provider: LoginProvider) =>
598
+ storeHttp.request(
599
+ "POST",
600
+ path`/store/auth-providers/${provider}/test`,
601
+ loginProviderTestSchema,
602
+ ),
603
+ /** 연결 해제 — 키를 지운다. 연결된 구매자 계정은 남는다 */
604
+ removeProvider: (provider: LoginProvider) =>
605
+ storeHttp.request("DELETE", path`/store/auth-providers/${provider}`, loginSettingsSchema),
606
+ },
607
+
570
608
  /** 구매자 관리 — 조회 `customer:r`, 탈퇴 처리 `customer:rw`(콘솔 OWNER·ADMIN) */
571
609
  customers: {
572
610
  list: (
package/src/index.ts CHANGED
@@ -19,6 +19,7 @@ export * from "./schemas/category";
19
19
  export * from "./schemas/claim";
20
20
  export * from "./schemas/common";
21
21
  export * from "./schemas/customer";
22
+ export * from "./schemas/login";
22
23
  export * from "./schemas/misc";
23
24
  export * from "./schemas/order";
24
25
  export * from "./schemas/payment";
@@ -37,7 +37,8 @@ export const customerSummarySchema = z
37
37
  .object({
38
38
  customerId: z.string(),
39
39
  name: z.string(),
40
- email: z.string(),
40
+ /** 소셜 가입에서 이메일을 받지 못했으면 null */
41
+ email: z.string().nullable(),
41
42
  maskedPhone: z.string().nullable(),
42
43
  joinedAt: z.string(),
43
44
  point: z.number().int(),
@@ -61,14 +62,20 @@ export const customerAddressSchema = z.object({
61
62
  export const customerDetailSchema = z.object({
62
63
  customerId: z.string(),
63
64
  name: z.string(),
64
- email: z.string(),
65
+ email: z.string().nullable(),
65
66
  phone: z.string().nullable(),
66
67
  joinedAt: z.string(),
67
68
  point: z.number().int(),
68
69
  marketingAgreed: z.boolean(),
69
70
  loginMethods: z
70
- .array(z.enum(["password"]))
71
- .describe("로그인 방법. 지금은 이메일·비밀번호(`password`)뿐이다"),
71
+ .array(
72
+ z.object({
73
+ method: z.enum(["password", "kakao", "naver", "google"]),
74
+ /** 소셜 연결 시각. 비밀번호는 가입 시각 */
75
+ linkedAt: z.string(),
76
+ }),
77
+ )
78
+ .describe("로그인 방법 — 이메일·비밀번호(`password`)와 연결된 소셜 계정"),
72
79
  addresses: z.array(customerAddressSchema),
73
80
  stats: customerStatsSchema.extend({
74
81
  canceledOrReturnedCount: z.number().int().describe("취소된 주문 상품 + 완료된 반품 수"),
@@ -0,0 +1,59 @@
1
+ import { z } from "zod";
2
+
3
+ /** 소셜 로그인 공급자 */
4
+ export const loginProviderSchema = z.enum(["kakao", "naver", "google"]);
5
+ export type LoginProvider = z.infer<typeof loginProviderSchema>;
6
+
7
+ /** 공급자 연결 상태 — 비밀 값은 앞 4자리만 */
8
+ export const loginProviderStatusSchema = z.object({
9
+ provider: loginProviderSchema,
10
+ connected: z.boolean(),
11
+ /** 스토어프런트에서 사용 중인지. 연결 안 됐으면 false */
12
+ enabled: z.boolean(),
13
+ clientIdPrefix: z.string().nullable().describe("클라이언트 ID(카카오 REST API 키) 앞 4자리"),
14
+ secretPrefix: z.string().nullable(),
15
+ lastTestedAt: z.string().nullable(),
16
+ lastTestOk: z.boolean().nullable(),
17
+ linkedMemberCount: z.number().int().describe("이 공급자로 연결된 구매자 수"),
18
+ /** 이 공급자로만 로그인하는 구매자 수 — 연결을 해제하면 로그인할 방법이 없어진다 */
19
+ onlyMethodMemberCount: z.number().int(),
20
+ callbackUrl: z.url().describe("공급자 개발자 콘솔에 등록할 리디렉트 URI"),
21
+ });
22
+ export type LoginProviderStatus = z.infer<typeof loginProviderStatusSchema>;
23
+
24
+ /** `GET /v1/store/login-settings` */
25
+ export const loginSettingsSchema = z.object({
26
+ passwordLoginEnabled: z.boolean(),
27
+ /** 비밀번호로만 로그인하는 구매자 수 — 이메일·비밀번호를 끄면 이들은 로그인할 수 없다 */
28
+ passwordOnlyMemberCount: z.number().int(),
29
+ storefrontOrigins: z.array(z.string()),
30
+ providers: z.array(loginProviderStatusSchema),
31
+ });
32
+ export type LoginSettings = z.infer<typeof loginSettingsSchema>;
33
+
34
+ /** `PATCH /v1/store/login-settings` */
35
+ export const updateLoginSettingsRequestSchema = z.object({
36
+ passwordLoginEnabled: z.boolean(),
37
+ });
38
+ export type UpdateLoginSettingsRequest = z.infer<typeof updateLoginSettingsRequestSchema>;
39
+
40
+ /** `PUT /v1/store/auth-providers/{provider}` — 저장 전에 연결 테스트를 한다 */
41
+ export const saveLoginProviderRequestSchema = z.object({
42
+ clientId: z.string().trim().min(1).max(200),
43
+ clientSecret: z.string().trim().min(1).max(500),
44
+ });
45
+ export type SaveLoginProviderRequest = z.infer<typeof saveLoginProviderRequestSchema>;
46
+
47
+ /** `PATCH /v1/store/auth-providers/{provider}` */
48
+ export const updateLoginProviderRequestSchema = z.object({
49
+ enabled: z.boolean(),
50
+ });
51
+
52
+ /** 연결 테스트 결과 */
53
+ export const loginProviderTestSchema = z.object({
54
+ ok: z.boolean(),
55
+ /** 실패 이유 — `INVALID_CLIENT`(키가 틀림)·`PROVIDER_UNAVAILABLE`(공급자 응답 없음) */
56
+ code: z.enum(["INVALID_CLIENT", "PROVIDER_UNAVAILABLE"]).nullable(),
57
+ testedAt: z.string(),
58
+ });
59
+ export type LoginProviderTest = z.infer<typeof loginProviderTestSchema>;
@@ -114,9 +114,17 @@ export const updateStoreRequestSchema = z
114
114
  .max(MAX_ANALYTICS_ALLOWED_ORIGINS)
115
115
  .optional()
116
116
  .describe(
117
- "방문 분석 수집을 받을 스토어프런트 오리진(최대 20개). 비우면 모든 오리진에서 받는다. " +
117
+ "@deprecated `storefrontOrigins`를 쓴다(같은 목록). 방문 분석 수집을 받을 스토어프런트 오리진(최대 20개). 비우면 모든 오리진에서 받는다. " +
118
118
  "넣으면 목록에 없는 오리진의 수집 요청은 403 `ORIGIN_NOT_ALLOWED`이고, 페이지 URL이 목록 밖인 이벤트는 버린다",
119
119
  ),
120
+ storefrontOrigins: z
121
+ .array(analyticsOriginSchema)
122
+ .max(MAX_ANALYTICS_ALLOWED_ORIGINS)
123
+ .optional()
124
+ .describe(
125
+ "스토어프런트 도메인(최대 20개) — 소셜 로그인 뒤 돌아갈 주소와 방문 분석 수집을 함께 제한한다. " +
126
+ "`analyticsAllowedOrigins`와 같은 목록이다(둘 다 주면 이 값이 이긴다)",
127
+ ),
120
128
  guestCheckoutEnabled: z
121
129
  .boolean()
122
130
  .optional()
@@ -142,6 +150,11 @@ export const storeSchema = z.object({
142
150
  analyticsAllowedOrigins: z
143
151
  .array(z.string())
144
152
  .describe("방문 분석 수집을 받는 스토어프런트 오리진. 비어 있으면 모든 오리진에서 받는다"),
153
+ storefrontOrigins: z
154
+ .array(z.string())
155
+ .describe(
156
+ "스토어프런트 도메인 — 소셜 로그인 리디렉트와 방문 분석 수집이 함께 쓴다(`analyticsAllowedOrigins`와 같은 값)",
157
+ ),
145
158
  guestCheckoutEnabled: z.boolean().describe("비회원 주문 허용. false면 회원만 주문할 수 있다"),
146
159
  memberCount: z.number().int(),
147
160
  createdAt: z.string(),