@sayren/store-sdk 0.66.0 → 0.68.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
@@ -9311,6 +9311,7 @@ export declare const customerDetailSchema: z$1.ZodObject<{
9311
9311
  joinedAt: z$1.ZodString;
9312
9312
  point: z$1.ZodNumber;
9313
9313
  marketingAgreed: z$1.ZodBoolean;
9314
+ lockedUntil: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodNullable<z$1.ZodString>>>;
9314
9315
  loginMethods: z$1.ZodArray<z$1.ZodObject<{
9315
9316
  method: z$1.ZodEnum<{
9316
9317
  kakao: "kakao";
@@ -16796,6 +16797,7 @@ export declare const updateStoreRequestSchema: z$1.ZodObject<{
16796
16797
  privacyOfficerEmail: z$1.ZodOptional<z$1.ZodNullable<z$1.ZodEmail>>;
16797
16798
  name: z$1.ZodOptional<z$1.ZodString>;
16798
16799
  logoUrl: z$1.ZodOptional<z$1.ZodURL>;
16800
+ iconUrl: z$1.ZodOptional<z$1.ZodNullable<z$1.ZodURL>>;
16799
16801
  customerCenterPhone: z$1.ZodOptional<z$1.ZodNullable<z$1.ZodString>>;
16800
16802
  businessHours: z$1.ZodOptional<z$1.ZodString>;
16801
16803
  }, z$1.core.$strip>;
@@ -16889,6 +16891,7 @@ export declare const storeSchema: z$1.ZodObject<{
16889
16891
  ACTIVE: "ACTIVE";
16890
16892
  }>;
16891
16893
  logoUrl: z$1.ZodNullable<z$1.ZodURL>;
16894
+ iconUrl: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodNullable<z$1.ZodString>>>;
16892
16895
  businessNumber: z$1.ZodNullable<z$1.ZodString>;
16893
16896
  customerCenterPhone: z$1.ZodNullable<z$1.ZodString>;
16894
16897
  }, z$1.core.$strip>;
@@ -18580,12 +18583,14 @@ export type SetStorefrontDeployApprovalRequest = z$1.infer<typeof setStorefrontD
18580
18583
  * - `description`: 상세설명 본문에 삽입하는 미디어. 동영상과 svg도 받는다.
18581
18584
  * - `flow-attachment`: 주문 흐름 행동의 첨부(시안 등, 이슈 #115). 구매자에게 보이므로 정지 이미지와 PDF만 받는다.
18582
18585
  * - `ai-attachment`: 상점 플랫폼 AI 채팅에 붙이는 자료(이슈 #124). 모델이 읽는 정지 이미지와 PDF만 받는다.
18586
+ * - `store-icon`: 상점 아이콘(정사각, 이슈 #400). 메일에도 실리므로 메일 클라이언트가 그리는 PNG·JPG만 받는다.
18583
18587
  */
18584
18588
  export declare const uploadPurposeSchema: z$1.ZodEnum<{
18585
18589
  description: "description";
18586
18590
  "product-image": "product-image";
18587
18591
  "flow-attachment": "flow-attachment";
18588
18592
  "ai-attachment": "ai-attachment";
18593
+ "store-icon": "store-icon";
18589
18594
  }>;
18590
18595
  export type UploadPurpose = z$1.infer<typeof uploadPurposeSchema>;
18591
18596
  export interface UploadPurposeLimit {
@@ -18627,6 +18632,7 @@ export declare const uploadRequestSchema: z$1.ZodObject<{
18627
18632
  "product-image": "product-image";
18628
18633
  "flow-attachment": "flow-attachment";
18629
18634
  "ai-attachment": "ai-attachment";
18635
+ "store-icon": "store-icon";
18630
18636
  }>>;
18631
18637
  size: z$1.ZodOptional<z$1.ZodNumber>;
18632
18638
  }, z$1.core.$strip>;
@@ -22766,6 +22772,7 @@ export declare function createStoreClient(options: StoreClientOptions): {
22766
22772
  joinedAt: string;
22767
22773
  point: number;
22768
22774
  marketingAgreed: boolean;
22775
+ lockedUntil: string | null;
22769
22776
  loginMethods: {
22770
22777
  method: "kakao" | "naver" | "google" | "password";
22771
22778
  linkedAt: string;
@@ -22860,6 +22867,7 @@ export declare function createStoreClient(options: StoreClientOptions): {
22860
22867
  joinedAt: string;
22861
22868
  point: number;
22862
22869
  marketingAgreed: boolean;
22870
+ lockedUntil: string | null;
22863
22871
  loginMethods: {
22864
22872
  method: "kakao" | "naver" | "google" | "password";
22865
22873
  linkedAt: string;
@@ -23004,6 +23012,103 @@ export declare function createStoreClient(options: StoreClientOptions): {
23004
23012
  };
23005
23013
  source?: string | undefined;
23006
23014
  }[]>;
23015
+ /** 비밀번호 재설정 메일 보내기(#400) — 구매자가 메일 링크에서 새 비밀번호를 정한다. 상점 플랫폼 OWNER·ADMIN */
23016
+ sendPasswordReset: (customerId: string) => Promise<void>;
23017
+ /** 로그인 잠금 해제 — 비밀번호 연속 실패 잠금과 실패 횟수를 지운다(멱등). 상점 플랫폼 OWNER·ADMIN */
23018
+ unlock: (customerId: string) => Promise<{
23019
+ customerId: string;
23020
+ name: string;
23021
+ email: string | null;
23022
+ phone: string | null;
23023
+ joinedAt: string;
23024
+ point: number;
23025
+ marketingAgreed: boolean;
23026
+ lockedUntil: string | null;
23027
+ loginMethods: {
23028
+ method: "kakao" | "naver" | "google" | "password";
23029
+ linkedAt: string;
23030
+ }[];
23031
+ consents: {
23032
+ terms: {
23033
+ kind: "TERMS" | "PRIVACY" | "MARKETING";
23034
+ agreed: boolean;
23035
+ agreedVersion: string | null;
23036
+ currentVersion: string | null;
23037
+ currentDocumentUrl: string | null;
23038
+ updatedAt: string | null;
23039
+ reconsentRequired: boolean;
23040
+ };
23041
+ privacy: {
23042
+ kind: "TERMS" | "PRIVACY" | "MARKETING";
23043
+ agreed: boolean;
23044
+ agreedVersion: string | null;
23045
+ currentVersion: string | null;
23046
+ currentDocumentUrl: string | null;
23047
+ updatedAt: string | null;
23048
+ reconsentRequired: boolean;
23049
+ };
23050
+ marketing: {
23051
+ kind: "TERMS" | "PRIVACY" | "MARKETING";
23052
+ agreed: boolean;
23053
+ agreedVersion: string | null;
23054
+ currentVersion: string | null;
23055
+ currentDocumentUrl: string | null;
23056
+ updatedAt: string | null;
23057
+ reconsentRequired: boolean;
23058
+ };
23059
+ reconsentRequired: boolean;
23060
+ };
23061
+ addresses: {
23062
+ addressId: string;
23063
+ alias: string;
23064
+ isDefault: boolean;
23065
+ receiverName: string;
23066
+ phone: string;
23067
+ zipCode: string;
23068
+ address1: string;
23069
+ address2: string | null;
23070
+ countryCode: string;
23071
+ city: string | null;
23072
+ region: string | null;
23073
+ }[];
23074
+ stats: {
23075
+ orderCount: number;
23076
+ totalPaid: number;
23077
+ lastOrderedAt: string | null;
23078
+ canceledOrReturnedCount: number;
23079
+ reviewCount: number;
23080
+ inquiryCount: number;
23081
+ };
23082
+ userinfo?: {
23083
+ sub: string;
23084
+ name?: string | undefined;
23085
+ given_name?: string | undefined;
23086
+ family_name?: string | undefined;
23087
+ middle_name?: string | undefined;
23088
+ nickname?: string | undefined;
23089
+ preferred_username?: string | undefined;
23090
+ profile?: string | undefined;
23091
+ picture?: string | undefined;
23092
+ website?: string | undefined;
23093
+ email?: string | undefined;
23094
+ email_verified?: boolean | undefined;
23095
+ gender?: string | undefined;
23096
+ birthdate?: string | undefined;
23097
+ zoneinfo?: string | undefined;
23098
+ locale?: string | undefined;
23099
+ phone_number?: string | undefined;
23100
+ phone_number_verified?: boolean | undefined;
23101
+ address?: {
23102
+ formatted?: string | undefined;
23103
+ street_address?: string | undefined;
23104
+ locality?: string | undefined;
23105
+ region?: string | undefined;
23106
+ postal_code?: string | undefined;
23107
+ country?: string | undefined;
23108
+ } | undefined;
23109
+ updated_at?: number | undefined;
23110
+ } | undefined;
23111
+ }>;
23007
23112
  withdraw: (customerId: string, body: WithdrawCustomerRequest) => Promise<void>;
23008
23113
  };
23009
23114
  /** 쿠폰 (이슈 #47) — 조회 `promotion:r`, 쓰기 `promotion:rw` */
@@ -29141,6 +29246,7 @@ export declare function createStoreClient(options: StoreClientOptions): {
29141
29246
  storefrontUrl: string | null;
29142
29247
  status: "SUSPENDED" | "CLOSED" | "ACTIVE";
29143
29248
  logoUrl: string | null;
29249
+ iconUrl: string | null;
29144
29250
  businessNumber: string | null;
29145
29251
  customerCenterPhone: string | null;
29146
29252
  }>;
@@ -29199,6 +29305,7 @@ export declare function createStoreClient(options: StoreClientOptions): {
29199
29305
  storefrontUrl: string | null;
29200
29306
  status: "SUSPENDED" | "CLOSED" | "ACTIVE";
29201
29307
  logoUrl: string | null;
29308
+ iconUrl: string | null;
29202
29309
  businessNumber: string | null;
29203
29310
  customerCenterPhone: string | null;
29204
29311
  }>;
package/dist/index.mjs CHANGED
@@ -1365,6 +1365,7 @@ const autoConfirmDaysDescription = "배송완료 후 자동 구매확정까지
1365
1365
  const updateStoreRequestSchema = strictRequest(z$1.object({
1366
1366
  name: z$1.string().min(2).max(50).optional(),
1367
1367
  logoUrl: z$1.url().optional(),
1368
+ iconUrl: z$1.url().nullable().optional().describe("상점 아이콘(정사각, https) — 구매자 비밀번호 재설정 메일·화면에 보인다. `null`을 주면 지운다(상점 이름 첫 글자로 보인다)"),
1368
1369
  customerCenterPhone: z$1.string().nullable().optional().describe("고객센터 전화번호. `null`을 주면 지운다"),
1369
1370
  businessHours: z$1.string().max(100).optional(),
1370
1371
  ...businessInfoPatchShape,
@@ -1393,6 +1394,7 @@ const storeSchema = z$1.object({
1393
1394
  "CLOSED"
1394
1395
  ]),
1395
1396
  logoUrl: z$1.url().nullable(),
1397
+ iconUrl: z$1.string().nullable().optional().default(null).describe("상점 아이콘(정사각). 없으면 null. 서버는 항상 싣는다"),
1396
1398
  businessNumber: z$1.string().nullable().describe("사업자등록번호(숫자 10자리). 없으면 null"),
1397
1399
  customerCenterPhone: z$1.string().nullable(),
1398
1400
  ...businessInfoResponseShape,
@@ -4407,12 +4409,14 @@ const setCalendarRequestSchema = strictRequest(z$1.object({
4407
4409
  * - `description`: 상세설명 본문에 삽입하는 미디어. 동영상과 svg도 받는다.
4408
4410
  * - `flow-attachment`: 주문 흐름 행동의 첨부(시안 등, 이슈 #115). 구매자에게 보이므로 정지 이미지와 PDF만 받는다.
4409
4411
  * - `ai-attachment`: 상점 플랫폼 AI 채팅에 붙이는 자료(이슈 #124). 모델이 읽는 정지 이미지와 PDF만 받는다.
4412
+ * - `store-icon`: 상점 아이콘(정사각, 이슈 #400). 메일에도 실리므로 메일 클라이언트가 그리는 PNG·JPG만 받는다.
4410
4413
  */
4411
4414
  const uploadPurposeSchema = z$1.enum([
4412
4415
  "product-image",
4413
4416
  "description",
4414
4417
  "flow-attachment",
4415
- "ai-attachment"
4418
+ "ai-attachment",
4419
+ "store-icon"
4416
4420
  ]);
4417
4421
  const MB = 1048576;
4418
4422
  /**
@@ -4470,6 +4474,14 @@ const UPLOAD_PURPOSE_LIMITS = {
4470
4474
  "pdf"
4471
4475
  ],
4472
4476
  maxBytes: 10 * MB
4477
+ },
4478
+ "store-icon": {
4479
+ extensions: [
4480
+ "jpg",
4481
+ "jpeg",
4482
+ "png"
4483
+ ],
4484
+ maxBytes: 5 * MB
4473
4485
  }
4474
4486
  };
4475
4487
  /** 파일명의 소문자 확장자. 확장자가 없으면 `""` */
@@ -10327,6 +10339,7 @@ const customerDetailSchema = z$1.object({
10327
10339
  joinedAt: z$1.string(),
10328
10340
  point: z$1.number().int(),
10329
10341
  marketingAgreed: z$1.boolean(),
10342
+ lockedUntil: z$1.string().nullable().optional().default(null).describe("로그인 잠금이 풀리는 시각(ISO 8601). 비밀번호를 5회 연속 틀리면 10분 잠긴다. 잠겨 있지 않으면 null. `POST /v1/customers/{customerId}/unlock`으로 바로 풀 수 있다. 서버는 항상 싣는다"),
10330
10343
  loginMethods: z$1.array(z$1.object({
10331
10344
  method: z$1.enum([
10332
10345
  "password",
@@ -11069,7 +11082,7 @@ const paymentRecordSchema = z$1.object({
11069
11082
  status: paymentRecordStatusSchema,
11070
11083
  amount: z$1.number().int().describe("결제 금액"),
11071
11084
  refundedAmount: z$1.number().int().describe("환불 완료 금액 합계. 실패한 환불은 빼고 센다"),
11072
- heldRefundAmount: z$1.number().int().optional().default(0).describe("환불 대기 금액 합계(#115) — 주문만 취소하고 아직 환불하지 않은 몫. 결제 상세에서 환불 처리한다"),
11085
+ heldRefundAmount: z$1.number().int().optional().default(0).describe("환불 대기 금액 합계(#115) — 주문만 취소하고 아직 환불하지 않은 몫(`HELD`)과 다시 요청할 수 있는 실패 환불(`FAILED`, 결제 잔액 안의 것). 결제 상세에서 환불 처리한다"),
11073
11086
  provider: pgProviderResponseSchema.nullable().describe("승인한 PG. 승인 전에 끝났으면 마지막 시도의 PG"),
11074
11087
  method: pgPaymentMethodSchema.nullable().describe("실제 결제수단. 모르면 요청 수단"),
11075
11088
  easyPayProvider: easyPayProviderResponseSchema.nullable().optional().default(null).describe("간편결제사. `method`가 `EASY_PAY`일 때만 값이 있고, PG가 알려 주지 않았으면 요청한 간편결제사다. 그 밖의 결제수단과 간편결제 이전 결제는 null. 서버는 항상 싣는다. 현재 값은 `NAVERPAY`·`KAKAOPAY`·`TOSSPAY`·`PAYCO`이고 값이 추가될 수 있어 문자열로 받는다"),
@@ -11133,7 +11146,7 @@ const paymentListQuerySchema = z$1.object({
11133
11146
  method: z$1.string().optional().describe("실제 결제수단 필터"),
11134
11147
  keyword: z$1.string().optional().describe("결제 id·주문 id·PG 거래 id·시도 id·PG 주문번호(일치), 구매자명(포함)"),
11135
11148
  includeTest: z$1.string().optional().describe("테스트 결제 포함 여부 (`true`·`false`. 기본 false — 실결제만)"),
11136
- refundHeld: z$1.string().optional().describe("`true`면 환불 대기가 있는 결제만(#115)"),
11149
+ refundHeld: z$1.string().optional().describe("`true`면 환불 대기(`heldRefundAmount` > 0)가 있는 결제만(#115). 다시 요청할 수 있는 실패 환불도 포함한다"),
11137
11150
  page: z$1.string().optional().describe("페이지 번호 (1부터)"),
11138
11151
  size: z$1.string().optional().describe("페이지 크기 (기본 20, 최대 100)")
11139
11152
  });
@@ -12651,6 +12664,10 @@ listHistory: (params) => storeHttp.request("GET", "/points/history", pageSchema(
12651
12664
  consents: (customerId, params) => storeHttp.request("GET", path`/customers/${customerId}/consents`, pageSchema(customerConsentSchema), { query: params }),
12652
12665
  /** 보유 쿠폰 (이슈 #47) — 최근 지급 순, 최대 500장 */
12653
12666
  coupons: (customerId) => storeHttp.request("GET", path`/customers/${customerId}/coupons`, z$1.array(customerCouponSchema)),
12667
+ /** 비밀번호 재설정 메일 보내기(#400) — 구매자가 메일 링크에서 새 비밀번호를 정한다. 상점 플랫폼 OWNER·ADMIN */
12668
+ sendPasswordReset: (customerId) => storeHttp.requestVoid("POST", path`/customers/${customerId}/password-reset`),
12669
+ /** 로그인 잠금 해제 — 비밀번호 연속 실패 잠금과 실패 횟수를 지운다(멱등). 상점 플랫폼 OWNER·ADMIN */
12670
+ unlock: (customerId) => storeHttp.request("POST", path`/customers/${customerId}/unlock`, customerDetailSchema),
12654
12671
  withdraw: (customerId, body) => storeHttp.requestVoid("POST", path`/customers/${customerId}/withdraw`, { body: withdrawCustomerRequestSchema.parse(body) })
12655
12672
  },
12656
12673
  /** 쿠폰 (이슈 #47) — 조회 `promotion:r`, 쓰기 `promotion:rw` */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sayren/store-sdk",
3
- "version": "0.66.0",
3
+ "version": "0.68.0",
4
4
  "main": "./dist/index.mjs",
5
5
  "types": "./dist/index.d.mts",
6
6
  "exports": {
package/src/client.ts CHANGED
@@ -1603,6 +1603,12 @@ export function createStoreClient(options: StoreClientOptions) {
1603
1603
  path`/customers/${customerId}/coupons`,
1604
1604
  z.array(customerCouponSchema),
1605
1605
  ),
1606
+ /** 비밀번호 재설정 메일 보내기(#400) — 구매자가 메일 링크에서 새 비밀번호를 정한다. 상점 플랫폼 OWNER·ADMIN */
1607
+ sendPasswordReset: (customerId: string) =>
1608
+ storeHttp.requestVoid("POST", path`/customers/${customerId}/password-reset`),
1609
+ /** 로그인 잠금 해제 — 비밀번호 연속 실패 잠금과 실패 횟수를 지운다(멱등). 상점 플랫폼 OWNER·ADMIN */
1610
+ unlock: (customerId: string) =>
1611
+ storeHttp.request("POST", path`/customers/${customerId}/unlock`, customerDetailSchema),
1606
1612
  withdraw: (customerId: string, body: WithdrawCustomerRequest) =>
1607
1613
  storeHttp.requestVoid("POST", path`/customers/${customerId}/withdraw`, {
1608
1614
  body: withdrawCustomerRequestSchema.parse(body),
@@ -236,6 +236,15 @@ export const customerDetailSchema = z.object({
236
236
  joinedAt: z.string(),
237
237
  point: z.number().int(),
238
238
  marketingAgreed: z.boolean(),
239
+ lockedUntil: z
240
+ .string()
241
+ .nullable()
242
+ .optional()
243
+ .default(null)
244
+ .describe(
245
+ "로그인 잠금이 풀리는 시각(ISO 8601). 비밀번호를 5회 연속 틀리면 10분 잠긴다. 잠겨 있지 않으면 null. " +
246
+ "`POST /v1/customers/{customerId}/unlock`으로 바로 풀 수 있다. 서버는 항상 싣는다",
247
+ ),
239
248
  loginMethods: z
240
249
  .array(
241
250
  z.object({
@@ -813,7 +813,7 @@ export const paymentRecordSchema = z.object({
813
813
  .optional()
814
814
  .default(0)
815
815
  .describe(
816
- "환불 대기 금액 합계(#115) — 주문만 취소하고 아직 환불하지 않은 몫. 결제 상세에서 환불 처리한다",
816
+ "환불 대기 금액 합계(#115) — 주문만 취소하고 아직 환불하지 않은 몫(`HELD`)과 다시 요청할 수 있는 실패 환불(`FAILED`, 결제 잔액 안의 것). 결제 상세에서 환불 처리한다",
817
817
  ),
818
818
  provider: pgProviderResponseSchema
819
819
  .nullable()
@@ -974,7 +974,12 @@ export const paymentListQuerySchema = z.object({
974
974
  .string()
975
975
  .optional()
976
976
  .describe("테스트 결제 포함 여부 (`true`·`false`. 기본 false — 실결제만)"),
977
- refundHeld: z.string().optional().describe("`true`면 환불 대기가 있는 결제만(#115)"),
977
+ refundHeld: z
978
+ .string()
979
+ .optional()
980
+ .describe(
981
+ "`true`면 환불 대기(`heldRefundAmount` > 0)가 있는 결제만(#115). 다시 요청할 수 있는 실패 환불도 포함한다",
982
+ ),
978
983
  page: z.string().optional().describe("페이지 번호 (1부터)"),
979
984
  size: z.string().optional().describe("페이지 크기 (기본 20, 최대 100)"),
980
985
  });
@@ -233,6 +233,13 @@ export const updateStoreRequestSchema = strictRequest(
233
233
  .object({
234
234
  name: z.string().min(2).max(50).optional(),
235
235
  logoUrl: z.url().optional(),
236
+ iconUrl: z
237
+ .url()
238
+ .nullable()
239
+ .optional()
240
+ .describe(
241
+ "상점 아이콘(정사각, https) — 구매자 비밀번호 재설정 메일·화면에 보인다. `null`을 주면 지운다(상점 이름 첫 글자로 보인다)",
242
+ ),
236
243
  customerCenterPhone: z
237
244
  .string()
238
245
  .nullable()
@@ -332,6 +339,12 @@ export const storeSchema = z.object({
332
339
  .describe("스토어프론트 호스팅 사이트의 대표 주소. 사이트가 없으면 null"),
333
340
  status: z.enum(["ACTIVE", "SUSPENDED", "CLOSED"]),
334
341
  logoUrl: z.url().nullable(),
342
+ iconUrl: z
343
+ .string()
344
+ .nullable()
345
+ .optional()
346
+ .default(null)
347
+ .describe("상점 아이콘(정사각). 없으면 null. 서버는 항상 싣는다"),
335
348
  businessNumber: z.string().nullable().describe("사업자등록번호(숫자 10자리). 없으면 null"),
336
349
  customerCenterPhone: z.string().nullable(),
337
350
  ...businessInfoResponseShape,
@@ -8,12 +8,14 @@ import { strictRequest } from "./strict";
8
8
  * - `description`: 상세설명 본문에 삽입하는 미디어. 동영상과 svg도 받는다.
9
9
  * - `flow-attachment`: 주문 흐름 행동의 첨부(시안 등, 이슈 #115). 구매자에게 보이므로 정지 이미지와 PDF만 받는다.
10
10
  * - `ai-attachment`: 상점 플랫폼 AI 채팅에 붙이는 자료(이슈 #124). 모델이 읽는 정지 이미지와 PDF만 받는다.
11
+ * - `store-icon`: 상점 아이콘(정사각, 이슈 #400). 메일에도 실리므로 메일 클라이언트가 그리는 PNG·JPG만 받는다.
11
12
  */
12
13
  export const uploadPurposeSchema = z.enum([
13
14
  "product-image",
14
15
  "description",
15
16
  "flow-attachment",
16
17
  "ai-attachment",
18
+ "store-icon",
17
19
  ]);
18
20
 
19
21
  export type UploadPurpose = z.infer<typeof uploadPurposeSchema>;
@@ -51,6 +53,10 @@ export const UPLOAD_PURPOSE_LIMITS: Record<UploadPurpose, UploadPurposeLimit> =
51
53
  extensions: ["jpg", "jpeg", "png", "webp", "gif", "pdf"],
52
54
  maxBytes: 10 * MB,
53
55
  },
56
+ "store-icon": {
57
+ extensions: ["jpg", "jpeg", "png"],
58
+ maxBytes: 5 * MB,
59
+ },
54
60
  };
55
61
 
56
62
  /** 파일명의 소문자 확장자. 확장자가 없으면 `""` */