@sayren/store-sdk 0.47.0 → 0.49.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/server.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as WEBHOOK_HEADERS, i as WEBHOOK_EVENT_TYPE_HEADER, n as WEBHOOK_DELIVERY_ID_HEADER, o as WEBHOOK_SIGNATURE_HEADER, r as WEBHOOK_EVENT_ID_HEADER, s as WEBHOOK_USER_AGENT, t as WEBHOOK_DEFAULT_TOLERANCE_SEC } from "./webhook-headers-CTez3xDY.mjs";
1
+ import { a as WEBHOOK_HEADERS, i as WEBHOOK_EVENT_TYPE_HEADER, n as WEBHOOK_DELIVERY_ID_HEADER, o as WEBHOOK_SIGNATURE_HEADER, r as WEBHOOK_EVENT_ID_HEADER, s as WEBHOOK_USER_AGENT, t as WEBHOOK_DEFAULT_TOLERANCE_SEC } from "./webhook-headers-COVjv1yo.mjs";
2
2
  //#region src/member-delegation.ts
3
3
  /** 위임 실패 — `error`는 api 오류 코드(엔벨로프 `error.code`, 없으면 `http_{status}`) */
4
4
  var MemberDelegationError = class extends Error {
@@ -1,4 +1,4 @@
1
- import * as z from "zod";
1
+ import * as z$1 from "zod";
2
2
  //#region src/schemas/strict.ts
3
3
  /**
4
4
  * 관리 API 요청 본문을 모르는 키까지 거르는 스키마로 바꾼다(이슈 #193, 2026-10-24). `z.object`는 모르는 키를 조용히 버려서
@@ -18,8 +18,8 @@ function strictOf(schema, seen) {
18
18
  ...def,
19
19
  ...patch
20
20
  });
21
- const meta = z.globalRegistry.get(schema);
22
- if (meta) z.globalRegistry.add(next, meta);
21
+ const meta = z$1.globalRegistry.get(schema);
22
+ if (meta) z$1.globalRegistry.add(next, meta);
23
23
  return next;
24
24
  };
25
25
  let next;
@@ -27,7 +27,7 @@ function strictOf(schema, seen) {
27
27
  case "object":
28
28
  next = clone({
29
29
  shape: Object.fromEntries(Object.entries(def.shape).map(([key, value]) => [key, strictOf(value, seen)])),
30
- catchall: def.catchall ?? z.never()
30
+ catchall: def.catchall ?? z$1.never()
31
31
  });
32
32
  break;
33
33
  case "array":
@@ -84,107 +84,107 @@ function strictOf(schema, seen) {
84
84
  * 관리 API 쓰기(`/v1/**`의 GET 외 요청)는 모두 요청 단위 기록(`source: REQUEST`) 한 줄을 남긴다. 환불·직권취소 같은
85
85
  * 도메인 동작은 그 안에서 변경 전후를 담은 기록(`source: DOMAIN`)을 따로 남기고 `requestId`로 요청 기록과 이어진다.
86
86
  */
87
- const auditActorTypeSchema = z.enum([
87
+ const auditActorTypeSchema = z$1.enum([
88
88
  "USER",
89
89
  "AGENT",
90
90
  "APP",
91
91
  "TOKEN",
92
92
  "SYSTEM"
93
93
  ]).describe("행위자 유형. `USER`=상점 플랫폼 사용자, `AGENT`=AI 에이전트(MCP·에이전트용 API 토큰), `APP`=앱(OAuth 클라이언트·M2M), `TOKEN`=API 토큰, `SYSTEM`=자동화(주기 잡)");
94
- const auditActorSchema = z.object({
94
+ const auditActorSchema = z$1.object({
95
95
  type: auditActorTypeSchema,
96
- id: z.string().describe("행위자 ID. `USER`=userId, `TOKEN`·`AGENT`(API 토큰)=`pat:{tokenId}`, `APP`=`client:{clientId}`, `SYSTEM`=`system`. 사람이 앱에 위임한 호출은 `APP`이고 위임한 사람은 `metadata.onBehalfOf`에 있다"),
97
- name: z.string().nullable().describe("기록 시점의 표시 이름. 알 수 없으면 null")
96
+ id: z$1.string().describe("행위자 ID. `USER`=userId, `TOKEN`·`AGENT`(API 토큰)=`pat:{tokenId}`, `APP`=`client:{clientId}`, `SYSTEM`=`system`. 사람이 앱에 위임한 호출은 `APP`이고 위임한 사람은 `metadata.onBehalfOf`에 있다"),
97
+ name: z$1.string().nullable().describe("기록 시점의 표시 이름. 알 수 없으면 null")
98
98
  });
99
- const auditLogSourceSchema = z.enum(["REQUEST", "DOMAIN"]).describe("기록 단위. `REQUEST`=관리 API 쓰기 요청 한 건, `DOMAIN`=환불·취소 같은 도메인 동작의 상세");
100
- const auditLogOutcomeSchema = z.enum([
99
+ const auditLogSourceSchema = z$1.enum(["REQUEST", "DOMAIN"]).describe("기록 단위. `REQUEST`=관리 API 쓰기 요청 한 건, `DOMAIN`=환불·취소 같은 도메인 동작의 상세");
100
+ const auditLogOutcomeSchema = z$1.enum([
101
101
  "SUCCEEDED",
102
102
  "FAILED",
103
103
  "PENDING_APPROVAL",
104
104
  "DENIED",
105
105
  "DRY_RUN"
106
106
  ]).describe("요청 결과. `PENDING_APPROVAL`=승인 대기로 보류(202), `DENIED`=에이전트 정책으로 거부(403 `AGENT_OPERATION_DENIED`), `DRY_RUN`=드라이런(`x-sayren-dry-run: 1`)이라 실행하지 않음");
107
- const auditLogSchema = z.object({
108
- auditId: z.string().describe("감사 로그 ID"),
109
- occurredAt: z.string().describe("기록 일시 (ISO 8601)"),
107
+ const auditLogSchema = z$1.object({
108
+ auditId: z$1.string().describe("감사 로그 ID"),
109
+ occurredAt: z$1.string().describe("기록 일시 (ISO 8601)"),
110
110
  source: auditLogSourceSchema,
111
- action: z.string().describe("동작. `REQUEST`는 오퍼레이션 ID(OpenAPI `operationId`, 예: `ProductsController_patch`), `DOMAIN`은 도메인 코드(예: `ORDER_ITEM_CANCELED_BY_SELLER`)"),
111
+ action: z$1.string().describe("동작. `REQUEST`는 오퍼레이션 ID(OpenAPI `operationId`, 예: `ProductsController_patch`), `DOMAIN`은 도메인 코드(예: `ORDER_ITEM_CANCELED_BY_SELLER`)"),
112
112
  actor: auditActorSchema,
113
- actorRole: z.string().nullable().describe("요청 시점의 상점 역할. 역할이 없는 토큰·자동화는 null"),
114
- target: z.object({
115
- type: z.string().describe("대상 리소스 유형 (예: `products`, `order-items`, `claim`)"),
116
- id: z.string().nullable().describe("대상 리소스 ID. 목록 대상 요청처럼 하나로 정할 수 없으면 null")
113
+ actorRole: z$1.string().nullable().describe("요청 시점의 상점 역할. 역할이 없는 토큰·자동화는 null"),
114
+ target: z$1.object({
115
+ type: z$1.string().describe("대상 리소스 유형 (예: `products`, `order-items`, `claim`)"),
116
+ id: z$1.string().nullable().describe("대상 리소스 ID. 목록 대상 요청처럼 하나로 정할 수 없으면 null")
117
117
  }),
118
- requestId: z.string().nullable().describe("요청 ID. 같은 요청에서 나온 `REQUEST`·`DOMAIN` 기록이 같은 값을 가진다. 자동화는 null"),
119
- method: z.string().nullable().describe("HTTP 메서드 (`REQUEST`만)"),
120
- path: z.string().nullable().describe("요청 경로와 쿼리 (`REQUEST`만). 민감한 쿼리 값은 `***`로 가린다"),
121
- statusCode: z.number().int().nullable().describe("응답 HTTP 상태 코드 (`REQUEST`만)"),
118
+ requestId: z$1.string().nullable().describe("요청 ID. 같은 요청에서 나온 `REQUEST`·`DOMAIN` 기록이 같은 값을 가진다. 자동화는 null"),
119
+ method: z$1.string().nullable().describe("HTTP 메서드 (`REQUEST`만)"),
120
+ path: z$1.string().nullable().describe("요청 경로와 쿼리 (`REQUEST`만). 민감한 쿼리 값은 `***`로 가린다"),
121
+ statusCode: z$1.number().int().nullable().describe("응답 HTTP 상태 코드 (`REQUEST`만)"),
122
122
  outcome: auditLogOutcomeSchema.nullable().describe("요청 결과 (`REQUEST`만)"),
123
- errorCode: z.string().nullable().describe("에러 응답의 `error.code` (실패한 요청만)"),
124
- traceId: z.string().nullable().describe("추적 ID. 에러 응답의 `error.traceId`와 같다"),
125
- idempotencyKey: z.string().nullable().describe("요청의 멱등키"),
126
- approvalId: z.string().nullable().describe("승인 요청 ID. 승인 대기로 보류된 요청과 승인 뒤 실행된 요청에 실린다"),
127
- metadata: z.record(z.string(), z.unknown()).describe("부가 정보. 도메인 기록은 변경 전후 값·사유를, 승인 실행 기록은 승인자(`approvedBy`)를 싣는다")
123
+ errorCode: z$1.string().nullable().describe("에러 응답의 `error.code` (실패한 요청만)"),
124
+ traceId: z$1.string().nullable().describe("추적 ID. 에러 응답의 `error.traceId`와 같다"),
125
+ idempotencyKey: z$1.string().nullable().describe("요청의 멱등키"),
126
+ approvalId: z$1.string().nullable().describe("승인 요청 ID. 승인 대기로 보류된 요청과 승인 뒤 실행된 요청에 실린다"),
127
+ metadata: z$1.record(z$1.string(), z$1.unknown()).describe("부가 정보. 도메인 기록은 변경 전후 값·사유를, 승인 실행 기록은 승인자(`approvedBy`)를 싣는다")
128
128
  });
129
129
  /** 쉼표 구분 목록 쿼리 → 배열 */
130
130
  function commaList(item) {
131
- return z.union([z.string(), z.array(z.string())]).transform((value) => (Array.isArray(value) ? value : [value]).flatMap((part) => part.split(",")).map((part) => part.trim()).filter((part) => part.length > 0)).pipe(z.array(item).min(1));
131
+ return z$1.union([z$1.string(), z$1.array(z$1.string())]).transform((value) => (Array.isArray(value) ? value : [value]).flatMap((part) => part.split(",")).map((part) => part.trim()).filter((part) => part.length > 0)).pipe(z$1.array(item).min(1));
132
132
  }
133
133
  /** 감사 로그 조회 쿼리 — `GET /audit-logs` */
134
- const auditLogListQuerySchema = z.object({
135
- from: z.string().optional().describe("조회 시작 일시 (ISO 8601, 포함)"),
136
- to: z.string().optional().describe("조회 종료 일시 (ISO 8601, 미포함)"),
134
+ const auditLogListQuerySchema = z$1.object({
135
+ from: z$1.string().optional().describe("조회 시작 일시 (ISO 8601, 포함)"),
136
+ to: z$1.string().optional().describe("조회 종료 일시 (ISO 8601, 미포함)"),
137
137
  actorType: commaList(auditActorTypeSchema).optional().describe("행위자 유형 필터. 여러 개는 쉼표로 구분한다 (예: `AGENT,APP`)"),
138
- actorId: z.string().optional().describe("행위자 ID 필터 (정확히 일치)"),
139
- action: z.string().optional().describe("동작 필터 (정확히 일치)"),
140
- targetType: z.string().optional().describe("대상 유형 필터 (정확히 일치)"),
141
- targetId: z.string().optional().describe("대상 ID 필터 (정확히 일치)"),
138
+ actorId: z$1.string().optional().describe("행위자 ID 필터 (정확히 일치)"),
139
+ action: z$1.string().optional().describe("동작 필터 (정확히 일치)"),
140
+ targetType: z$1.string().optional().describe("대상 유형 필터 (정확히 일치)"),
141
+ targetId: z$1.string().optional().describe("대상 ID 필터 (정확히 일치)"),
142
142
  source: auditLogSourceSchema.optional(),
143
143
  outcome: auditLogOutcomeSchema.optional(),
144
- requestId: z.string().optional().describe("요청 ID 필터 — 한 요청의 요청·도메인 기록을 함께 본다"),
145
- approvalId: z.string().optional().describe("승인 요청 ID 필터"),
146
- cursor: z.string().optional().describe("이전 응답의 `nextCursor`. 생략하면 가장 최신부터"),
147
- limit: z.coerce.number().int().min(1).max(100).optional().describe("최대 건수 (1~100, 기본 50)")
144
+ requestId: z$1.string().optional().describe("요청 ID 필터 — 한 요청의 요청·도메인 기록을 함께 본다"),
145
+ approvalId: z$1.string().optional().describe("승인 요청 ID 필터"),
146
+ cursor: z$1.string().optional().describe("이전 응답의 `nextCursor`. 생략하면 가장 최신부터"),
147
+ limit: z$1.coerce.number().int().min(1).max(100).optional().describe("최대 건수 (1~100, 기본 50)")
148
148
  });
149
- const auditLogPageSchema = z.object({
150
- items: z.array(auditLogSchema),
151
- nextCursor: z.string().nullable().describe("다음 페이지 커서. 마지막 페이지면 null")
149
+ const auditLogPageSchema = z$1.object({
150
+ items: z$1.array(auditLogSchema),
151
+ nextCursor: z$1.string().nullable().describe("다음 페이지 커서. 마지막 페이지면 null")
152
152
  });
153
- const agentPolicyDecisionSchema = z.enum([
153
+ const agentPolicyDecisionSchema = z$1.enum([
154
154
  "ALLOW",
155
155
  "APPROVAL_REQUIRED",
156
156
  "DENIED"
157
157
  ]).describe("에이전트 쓰기 판정. `ALLOW`=바로 실행, `APPROVAL_REQUIRED`=상점 플랫폼 승인 뒤 실행, `DENIED`=에이전트는 실행할 수 없음");
158
- const previewValueSchema = z.union([
159
- z.string(),
160
- z.number(),
161
- z.boolean(),
162
- z.null()
158
+ const previewValueSchema = z$1.union([
159
+ z$1.string(),
160
+ z$1.number(),
161
+ z$1.boolean(),
162
+ z$1.null()
163
163
  ]);
164
- const writePreviewSchema = z.object({
165
- operationId: z.string().describe("오퍼레이션 ID"),
166
- method: z.string(),
167
- path: z.string(),
168
- target: z.object({
169
- type: z.string(),
170
- id: z.string().nullable()
164
+ const writePreviewSchema = z$1.object({
165
+ operationId: z$1.string().describe("오퍼레이션 ID"),
166
+ method: z$1.string(),
167
+ path: z$1.string(),
168
+ target: z$1.object({
169
+ type: z$1.string(),
170
+ id: z$1.string().nullable()
171
171
  }),
172
- targetName: z.string().nullable().optional().describe("대상 이름(상품명·쿠폰명·흐름 이름·구매자 이름 등). 읽을 수 없으면 null"),
173
- changes: z.array(z.object({
174
- field: z.string().describe("바뀌는 필드"),
175
- before: z.unknown().describe("현재 값. 새로 만드는 요청이거나 읽을 수 없으면 null"),
176
- after: z.unknown().describe("요청이 넣을 값")
172
+ targetName: z$1.string().nullable().optional().describe("대상 이름(상품명·쿠폰명·흐름 이름·구매자 이름 등). 읽을 수 없으면 null"),
173
+ changes: z$1.array(z$1.object({
174
+ field: z$1.string().describe("바뀌는 필드"),
175
+ before: z$1.unknown().describe("현재 값. 새로 만드는 요청이거나 읽을 수 없으면 null"),
176
+ after: z$1.unknown().describe("요청이 넣을 값")
177
177
  })).describe("값이 달라지는 필드. 서버가 현재 값과 비교할 수 있는 오퍼레이션만 채운다"),
178
- facts: z.record(z.string(), previewValueSchema).describe("영향 요약 (예: 취소 수량·주문상품 금액·예상 환불액). 오퍼레이션마다 다르다")
178
+ facts: z$1.record(z$1.string(), previewValueSchema).describe("영향 요약 (예: 취소 수량·주문상품 금액·예상 환불액). 오퍼레이션마다 다르다")
179
179
  });
180
180
  /** `x-sayren-dry-run: 1`을 실은 쓰기 요청의 응답(200) — 실행하지 않고 판정과 영향만 돌려준다 */
181
- const writeDryRunResultSchema = z.object({
182
- dryRun: z.literal(true),
181
+ const writeDryRunResultSchema = z$1.object({
182
+ dryRun: z$1.literal(true),
183
183
  decision: agentPolicyDecisionSchema,
184
- reason: z.string().nullable().describe("승인 필요·거부 사유. `ALLOW`면 null"),
184
+ reason: z$1.string().nullable().describe("승인 필요·거부 사유. `ALLOW`면 null"),
185
185
  preview: writePreviewSchema
186
186
  });
187
- const approvalStatusSchema = z.enum([
187
+ const approvalStatusSchema = z$1.enum([
188
188
  "PENDING",
189
189
  "EXECUTING",
190
190
  "SUCCEEDED",
@@ -193,82 +193,82 @@ const approvalStatusSchema = z.enum([
193
193
  "REJECTED",
194
194
  "EXPIRED"
195
195
  ]).describe("승인 요청 상태. `PENDING` 승인 대기 → 승인하면 `EXECUTING`(원 요청 실행 중) → `SUCCEEDED`·`FAILED`(원 요청의 응답 기준), 거절하면 `REJECTED`, 기한이 지나면 `EXPIRED`. 실행 응답을 받지 못했으면(타임아웃·서버 종료) `UNKNOWN`이다 — 서버가 감사 로그로 결과를 확정하면 `SUCCEEDED`·`FAILED`로 바뀌고, 확정하지 못하면 `UNKNOWN`에 남는다. `UNKNOWN`은 다시 실행하지 않는다(이미 실행됐을 수 있다)");
196
- const approvalRequestSchema = z.object({
197
- approvalId: z.string().describe("승인 요청 ID"),
196
+ const approvalRequestSchema = z$1.object({
197
+ approvalId: z$1.string().describe("승인 요청 ID"),
198
198
  status: approvalStatusSchema,
199
- operationId: z.string().describe("보류된 오퍼레이션 ID"),
200
- operationName: z.string().nullable().optional().describe("작업 이름(예: 흐름 게시, 구매자 적립금 지급·차감). API 문서의 요약과 같다. 모르면 null"),
201
- method: z.string().describe("HTTP 메서드"),
202
- path: z.string().describe("요청 경로와 쿼리"),
203
- body: z.unknown().describe("요청 본문. 승인하면 이 본문 그대로 실행한다. 없으면 null"),
204
- idempotencyKey: z.string().nullable().describe("원 요청의 멱등키"),
205
- reason: z.string().describe("승인이 필요한 이유"),
199
+ operationId: z$1.string().describe("보류된 오퍼레이션 ID"),
200
+ operationName: z$1.string().nullable().optional().describe("작업 이름(예: 흐름 게시, 구매자 적립금 지급·차감). API 문서의 요약과 같다. 모르면 null"),
201
+ method: z$1.string().describe("HTTP 메서드"),
202
+ path: z$1.string().describe("요청 경로와 쿼리"),
203
+ body: z$1.unknown().describe("요청 본문. 승인하면 이 본문 그대로 실행한다. 없으면 null"),
204
+ idempotencyKey: z$1.string().nullable().describe("원 요청의 멱등키"),
205
+ reason: z$1.string().describe("승인이 필요한 이유"),
206
206
  actor: auditActorSchema.describe("요청한 행위자"),
207
207
  preview: writePreviewSchema.nullable().describe("요청 시점에 서버가 계산한 영향 미리보기"),
208
- createdAt: z.string().describe("요청 일시 (ISO 8601)"),
209
- expiresAt: z.string().describe("승인 기한 (ISO 8601). 지나면 `EXPIRED`가 된다"),
210
- decidedAt: z.string().nullable().describe("승인·거절 일시"),
211
- decidedBy: z.object({
212
- id: z.string(),
213
- name: z.string().nullable()
208
+ createdAt: z$1.string().describe("요청 일시 (ISO 8601)"),
209
+ expiresAt: z$1.string().describe("승인 기한 (ISO 8601). 지나면 `EXPIRED`가 된다"),
210
+ decidedAt: z$1.string().nullable().describe("승인·거절 일시"),
211
+ decidedBy: z$1.object({
212
+ id: z$1.string(),
213
+ name: z$1.string().nullable()
214
214
  }).nullable().describe("승인·거절한 상점 플랫폼 사용자"),
215
- decisionNote: z.string().nullable().describe("승인·거절 메모"),
216
- executedAt: z.string().nullable().describe("원 요청 실행을 마친 일시"),
217
- result: z.object({
218
- statusCode: z.number().int().describe("원 요청의 응답 상태 코드"),
219
- data: z.unknown().describe("성공 응답의 `data` (큰 응답은 잘린다)"),
220
- error: z.object({
221
- code: z.string(),
222
- message: z.string()
215
+ decisionNote: z$1.string().nullable().describe("승인·거절 메모"),
216
+ executedAt: z$1.string().nullable().describe("원 요청 실행을 마친 일시"),
217
+ result: z$1.object({
218
+ statusCode: z$1.number().int().describe("원 요청의 응답 상태 코드"),
219
+ data: z$1.unknown().describe("성공 응답의 `data` (큰 응답은 잘린다)"),
220
+ error: z$1.object({
221
+ code: z$1.string(),
222
+ message: z$1.string()
223
223
  }).nullable().describe("실패 응답의 `error` 요약")
224
224
  }).nullable().describe("실행 결과. `SUCCEEDED`·`FAILED`·`UNKNOWN`에서 값이 있다. 감사 로그로 확정한 결과는 `data`가 null이다"),
225
- approvalUrl: z.string().nullable().describe("상점 플랫폼의 승인 화면 주소. 이 배포의 상점 플랫폼 주소를 알 수 없으면 null")
225
+ approvalUrl: z$1.string().nullable().describe("상점 플랫폼의 승인 화면 주소. 이 배포의 상점 플랫폼 주소를 알 수 없으면 null")
226
226
  });
227
- const approvalListQuerySchema = z.object({
227
+ const approvalListQuerySchema = z$1.object({
228
228
  status: commaList(approvalStatusSchema).optional().describe("상태 필터. 여러 개는 쉼표로 구분한다 (예: `PENDING,EXECUTING`)"),
229
- cursor: z.string().optional().describe("이전 응답의 `nextCursor`. 생략하면 가장 최신부터"),
230
- limit: z.coerce.number().int().min(1).max(100).optional().describe("최대 건수 (1~100, 기본 50)")
229
+ cursor: z$1.string().optional().describe("이전 응답의 `nextCursor`. 생략하면 가장 최신부터"),
230
+ limit: z$1.coerce.number().int().min(1).max(100).optional().describe("최대 건수 (1~100, 기본 50)")
231
231
  });
232
- const approvalPageSchema = z.object({
233
- items: z.array(approvalRequestSchema),
234
- nextCursor: z.string().nullable().describe("다음 페이지 커서. 마지막 페이지면 null")
232
+ const approvalPageSchema = z$1.object({
233
+ items: z$1.array(approvalRequestSchema),
234
+ nextCursor: z$1.string().nullable().describe("다음 페이지 커서. 마지막 페이지면 null")
235
235
  });
236
- const approvalDecisionRequestSchema = strictRequest(z.object({ note: z.string().trim().max(500).optional().describe("승인·거절 메모 (최대 500자)") }));
236
+ const approvalDecisionRequestSchema = strictRequest(z$1.object({ note: z$1.string().trim().max(500).optional().describe("승인·거절 메모 (최대 500자)") }));
237
237
  //#endregion
238
238
  //#region src/http.ts
239
239
  /** 표준 엔벨로프의 $.error 상세 */
240
- const errorDetailSchema = z.object({
241
- code: z.string(),
242
- message: z.string(),
243
- traceId: z.string().optional(),
240
+ const errorDetailSchema = z$1.object({
241
+ code: z$1.string(),
242
+ message: z$1.string(),
243
+ traceId: z$1.string().optional(),
244
244
  /**
245
245
  * 이 에러 코드를 설명하는 문서 URL(선택). 서버가 코드별 매핑을 가진 코드에만 실린다 —
246
246
  * 없으면 필드가 아예 없으므로 소비측은 있을 때만 쓴다
247
247
  */
248
- docs: z.url().optional().catch(void 0),
248
+ docs: z$1.url().optional().catch(void 0),
249
249
  /**
250
250
  * 에러 코드별 보조 데이터(선택). 예: 관리 API `LIVE_GATE_NOT_MET`의
251
251
  * `{ conditions: LiveGateCondition[] }`. 형태는 에러 코드마다 다르므로 소비측이 코드별 스키마로 다시 파싱한다
252
252
  */
253
- details: z.record(z.string(), z.unknown()).optional().catch(void 0)
253
+ details: z$1.record(z$1.string(), z$1.unknown()).optional().catch(void 0)
254
254
  });
255
255
  /** 표준 응답 엔벨로프 — $.meta / $.data / $.error */
256
- const envelopeSchema = z.object({
257
- meta: z.object({
258
- status: z.number(),
259
- code: z.string(),
260
- message: z.string(),
261
- isSuccess: z.boolean()
256
+ const envelopeSchema = z$1.object({
257
+ meta: z$1.object({
258
+ status: z$1.number(),
259
+ code: z$1.string(),
260
+ message: z$1.string(),
261
+ isSuccess: z$1.boolean()
262
262
  }),
263
- data: z.unknown().optional(),
263
+ data: z$1.unknown().optional(),
264
264
  /** 구형 필드 — data로 개명되기 전 응답과의 전환기 호환 */
265
- content: z.unknown().optional(),
265
+ content: z$1.unknown().optional(),
266
266
  error: errorDetailSchema.nullable()
267
267
  });
268
268
  /** OAuth 프로토콜 표면의 평면 에러 (RFC 6749 §5.2, RFC 7591 §3.2.2) */
269
- const oauthErrorSchema = z.object({
270
- error: z.string(),
271
- error_description: z.string().optional()
269
+ const oauthErrorSchema = z$1.object({
270
+ error: z$1.string(),
271
+ error_description: z$1.string().optional()
272
272
  });
273
273
  /** 표준 엔벨로프면 $.data(구형 $.content)를, 아니면(평면 응답) 본문 전체를 반환 */
274
274
  function unwrapData(json) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sayren/store-sdk",
3
- "version": "0.47.0",
3
+ "version": "0.49.0",
4
4
  "main": "./dist/index.mjs",
5
5
  "types": "./dist/index.d.mts",
6
6
  "exports": {
package/src/client.ts CHANGED
@@ -270,7 +270,9 @@ import {
270
270
  orderSchema,
271
271
  orderSummarySchema,
272
272
  purchaseDecisionExtendResultSchema,
273
+ type ShippingOrderItemListParams,
273
274
  sellerCancelPreviewSchema,
275
+ shippingOrderItemSchema,
274
276
  } from "./schemas/order";
275
277
  import {
276
278
  cashReceiptSchema,
@@ -342,6 +344,13 @@ import {
342
344
  variantStockRequestSchema,
343
345
  variantStockSchema,
344
346
  } from "./schemas/product";
347
+ import {
348
+ type ProductImportItemInput,
349
+ type ProductLookupRequest,
350
+ productImportItemsRequestSchema,
351
+ productImportSchema,
352
+ productLookupRequestSchema,
353
+ } from "./schemas/product-import";
345
354
  import {
346
355
  type InfoSectionLocalizationRequest,
347
356
  type InfoSectionRequestInput,
@@ -672,6 +681,26 @@ export function createStoreClient(options: StoreClientOptions) {
672
681
  body: { productIds, status: productStatusSchema.parse(status) },
673
682
  headers: idempotency(idempotencyKey),
674
683
  }),
684
+ /**
685
+ * 상품 일괄 반영(이슈 #211, 상점 플랫폼 전용) — 작업 만들기 → 항목 붙이기(여러 번) → 시작(202) → 조회.
686
+ * 항목 하나라도 실패하면 아무것도 반영하지 않는다
687
+ */
688
+ imports: {
689
+ create: () => storeHttp.request("POST", "/product-imports", productImportSchema),
690
+ addItems: (importId: string, items: ProductImportItemInput[]) =>
691
+ storeHttp.request("POST", path`/product-imports/${importId}/items`, productImportSchema, {
692
+ body: productImportItemsRequestSchema.parse({ items }),
693
+ }),
694
+ start: (importId: string) =>
695
+ storeHttp.request("POST", path`/product-imports/${importId}/start`, productImportSchema),
696
+ get: (importId: string) =>
697
+ storeHttp.request("GET", path`/product-imports/${importId}`, productImportSchema),
698
+ /** 상품 상세 묶음 조회(id·상품번호 합 100개) — 상점 플랫폼 전용. 이 상점에 없는 값은 빠진다 */
699
+ lookup: (body: ProductLookupRequest) =>
700
+ storeHttp.request("POST", "/product-imports/products", z.array(productSchema), {
701
+ body: productLookupRequestSchema.parse(body),
702
+ }),
703
+ },
675
704
  /** 옵션 축(그룹) × 값 → variant 모델 조회 */
676
705
  getOptionModel: (productId: string) =>
677
706
  storeHttp.request("GET", path`/products/${productId}/options`, optionModelSchema),
@@ -1005,6 +1034,15 @@ export function createStoreClient(options: StoreClientOptions) {
1005
1034
  storeHttp.request("GET", "/order-items", pageSchema(orderItemSchema), {
1006
1035
  query: params as unknown as Query,
1007
1036
  }),
1037
+ /** `GET /v1/order-items/shipping` — 배송지가 필요한 주문상품을 주문번호·배송지·발송 정보와 함께, 주문 시각 최신순으로(#208). 스코프 `order:r` */
1038
+ listShipping: (params: ShippingOrderItemListParams) =>
1039
+ storeHttp.request("GET", "/order-items/shipping", pageSchema(shippingOrderItemSchema), {
1040
+ query: {
1041
+ ...params,
1042
+ status: Array.isArray(params.status) ? params.status.join(",") : params.status,
1043
+ orderItemNos: params.orderItemNos?.join(","),
1044
+ } as Query,
1045
+ }),
1008
1046
  confirm: (orderItemId: string, idempotencyKey?: string) =>
1009
1047
  storeHttp.requestVoid("POST", path`/order-items/${orderItemId}/confirm`, {
1010
1048
  headers: idempotency(idempotencyKey),
package/src/index.ts CHANGED
@@ -32,7 +32,10 @@ export * from "./schemas/collection";
32
32
  export * from "./schemas/commerce-flow";
33
33
  export * from "./schemas/commerce-number";
34
34
  export * from "./schemas/common";
35
+ export * from "./schemas/condition-tree";
35
36
  export * from "./schemas/coupon";
37
+ export * from "./schemas/coupon-rules";
38
+ export * from "./schemas/coupon-selection";
36
39
  export * from "./schemas/currency";
37
40
  export * from "./schemas/currency-prices";
38
41
  export * from "./schemas/customer";
@@ -48,6 +51,7 @@ export * from "./schemas/payment";
48
51
  export * from "./schemas/plans";
49
52
  export * from "./schemas/points";
50
53
  export * from "./schemas/product";
54
+ export * from "./schemas/product-import";
51
55
  export * from "./schemas/product-info";
52
56
  export * from "./schemas/product-localization";
53
57
  export * from "./schemas/promotion";