connectbase-client 3.48.2 → 3.50.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.mjs CHANGED
@@ -1269,6 +1269,7 @@ var DatabaseAPI = class {
1269
1269
  if (options?.limit) params.append("limit", options.limit.toString());
1270
1270
  if (options?.offset) params.append("offset", options.offset.toString());
1271
1271
  if (options?.count === false) params.append("count", "false");
1272
+ if (options?.cursor) params.append("cursor", options.cursor);
1272
1273
  const queryString = params.toString();
1273
1274
  const url = queryString ? `${prefix}/tables/${tableId}/data?${queryString}` : `${prefix}/tables/${tableId}/data`;
1274
1275
  return this.http.get(url);
@@ -1288,7 +1289,8 @@ var DatabaseAPI = class {
1288
1289
  offset: options.offset,
1289
1290
  select: options.select,
1290
1291
  exclude: options.exclude,
1291
- count: options.count
1292
+ count: options.count,
1293
+ cursor: options.cursor
1292
1294
  }
1293
1295
  );
1294
1296
  }
@@ -2249,18 +2251,27 @@ var StorageAPI = class {
2249
2251
  * Presigned URL 로 직접 업로드. 호출 전에 URL 스킴(https)을 검증해
2250
2252
  * 서버 응답을 그대로 신뢰하는 SSRF/오용 경로를 차단.
2251
2253
  * 타임아웃과 외부 signal 을 모두 지원한다.
2254
+ *
2255
+ * `onProgress` 가 주어지고 `XMLHttpRequest` 를 쓸 수 있는(브라우저) 환경이면
2256
+ * XHR 의 `upload.onprogress` 로 바이트 단위 진행률을 보고한다. 그 외에는
2257
+ * fetch 로 업로드하고 시작(0%)/완료(100%)만 통지한다(Node/Edge 호환).
2252
2258
  */
2253
2259
  async uploadToPresigned(rawUrl, file, options) {
2254
2260
  const parsed = validateExternalUrl(rawUrl, {
2255
2261
  allowLocalhost: isLocalhostOrigin(),
2256
2262
  context: "storage.presigned-url"
2257
2263
  });
2264
+ const url = parsed.toString();
2265
+ if (options?.onProgress && typeof XMLHttpRequest !== "undefined") {
2266
+ return this.putViaXhr(url, file, options.onProgress, options);
2267
+ }
2258
2268
  const { signal, cleanup } = createTimeoutController({
2259
2269
  timeout: options?.timeout,
2260
2270
  signal: options?.signal
2261
2271
  });
2262
2272
  try {
2263
- const response = await fetch(parsed.toString(), {
2273
+ options?.onProgress?.({ loaded: 0, total: file.size, percentage: 0 });
2274
+ const response = await fetch(url, {
2264
2275
  method: "PUT",
2265
2276
  body: file,
2266
2277
  headers: {
@@ -2275,10 +2286,79 @@ var StorageAPI = class {
2275
2286
  "PRESIGNED_UPLOAD_FAILED"
2276
2287
  );
2277
2288
  }
2289
+ options?.onProgress?.({ loaded: file.size, total: file.size, percentage: 100 });
2278
2290
  } finally {
2279
2291
  cleanup();
2280
2292
  }
2281
2293
  }
2294
+ /**
2295
+ * XMLHttpRequest 기반 PUT 업로드. `upload.onprogress` 로 바이트 진행률을
2296
+ * 보고하며, 외부 signal(취소)과 타임아웃을 모두 지원한다. URL 은 호출 전에
2297
+ * 이미 검증된 값을 받는다(uploadToPresigned 에서 스킴 검증 수행).
2298
+ */
2299
+ putViaXhr(url, file, onProgress, options) {
2300
+ return new Promise((resolve, reject) => {
2301
+ const external = options?.signal;
2302
+ if (external?.aborted) {
2303
+ reject(external.reason ?? new DOMException("Aborted", "AbortError"));
2304
+ return;
2305
+ }
2306
+ const xhr = new XMLHttpRequest();
2307
+ xhr.open("PUT", url, true);
2308
+ xhr.setRequestHeader("Content-Type", file.type || "application/octet-stream");
2309
+ const timeout = options?.timeout ?? DEFAULT_REQUEST_TIMEOUT_MS;
2310
+ if (timeout > 0 && Number.isFinite(timeout)) {
2311
+ xhr.timeout = timeout;
2312
+ }
2313
+ let abortListener = null;
2314
+ const cleanup = () => {
2315
+ if (external && abortListener) {
2316
+ external.removeEventListener("abort", abortListener);
2317
+ }
2318
+ };
2319
+ if (external) {
2320
+ abortListener = () => xhr.abort();
2321
+ external.addEventListener("abort", abortListener, { once: true });
2322
+ }
2323
+ xhr.upload.onprogress = (event) => {
2324
+ if (!event.lengthComputable) return;
2325
+ const total = event.total || file.size;
2326
+ onProgress({
2327
+ loaded: event.loaded,
2328
+ total,
2329
+ percentage: total > 0 ? Math.round(event.loaded / total * 100) : 0
2330
+ });
2331
+ };
2332
+ xhr.onload = () => {
2333
+ cleanup();
2334
+ if (xhr.status >= 200 && xhr.status < 300) {
2335
+ onProgress({ loaded: file.size, total: file.size, percentage: 100 });
2336
+ resolve();
2337
+ } else {
2338
+ reject(
2339
+ new ApiError(
2340
+ xhr.status,
2341
+ `Upload failed: ${xhr.statusText || "unknown error"}`,
2342
+ "PRESIGNED_UPLOAD_FAILED"
2343
+ )
2344
+ );
2345
+ }
2346
+ };
2347
+ xhr.onerror = () => {
2348
+ cleanup();
2349
+ reject(new ApiError(0, "Upload failed: network error", "PRESIGNED_UPLOAD_FAILED"));
2350
+ };
2351
+ xhr.ontimeout = () => {
2352
+ cleanup();
2353
+ reject(new DOMException(`Request timed out after ${timeout}ms`, "TimeoutError"));
2354
+ };
2355
+ xhr.onabort = () => {
2356
+ cleanup();
2357
+ reject(external?.reason ?? new DOMException("Aborted", "AbortError"));
2358
+ };
2359
+ xhr.send(file);
2360
+ });
2361
+ }
2282
2362
  /**
2283
2363
  * 파일 목록 조회
2284
2364
  *
@@ -2308,14 +2388,28 @@ var StorageAPI = class {
2308
2388
  *
2309
2389
  * 서버를 거치지 않고 Object Storage에 직접 업로드합니다.
2310
2390
  *
2391
+ * 3번째 인자는 부모 폴더 ID(문자열) 또는 옵션 객체를 받습니다. 옵션으로
2392
+ * `onProgress` 콜백을 넘기면 업로드 진행률(%)을 실시간으로 받을 수 있습니다
2393
+ * (브라우저 환경). 기존 `uploadFile(id, file, 'folder-id')` 호출과 하위 호환됩니다.
2394
+ *
2311
2395
  * @example
2312
2396
  * ```ts
2313
2397
  * const fileInput = document.querySelector('input[type="file"]')
2314
2398
  * const result = await cb.storage.uploadFile('storage-id', fileInput.files[0])
2315
2399
  * console.log(result.url) // 업로드된 파일 URL
2400
+ *
2401
+ * // 특정 폴더에 업로드 (기존 방식 그대로)
2402
+ * await cb.storage.uploadFile('storage-id', file, 'folder-id')
2403
+ *
2404
+ * // 진행률 표시 + 특정 폴더
2405
+ * await cb.storage.uploadFile('storage-id', file, {
2406
+ * parentId: 'folder-id',
2407
+ * onProgress: (p) => console.log(`${p.percentage}%`), // { loaded, total, percentage }
2408
+ * })
2316
2409
  * ```
2317
2410
  */
2318
- async uploadFile(storageId, file, parentId) {
2411
+ async uploadFile(storageId, file, parentIdOrOptions) {
2412
+ const options = typeof parentIdOrOptions === "string" ? { parentId: parentIdOrOptions } : parentIdOrOptions ?? {};
2319
2413
  const prefix = this.getPublicPrefix();
2320
2414
  const presignedResponse = await this.http.post(
2321
2415
  `${prefix}/storages/files/${storageId}/presigned-url`,
@@ -2323,10 +2417,14 @@ var StorageAPI = class {
2323
2417
  file_name: file.name,
2324
2418
  file_size: file.size,
2325
2419
  mime_type: file.type || "application/octet-stream",
2326
- parent_id: parentId
2420
+ parent_id: options.parentId
2327
2421
  }
2328
2422
  );
2329
- await this.uploadToPresigned(presignedResponse.upload_url, file);
2423
+ await this.uploadToPresigned(presignedResponse.upload_url, file, {
2424
+ onProgress: options.onProgress,
2425
+ signal: options.signal,
2426
+ timeout: options.timeout
2427
+ });
2330
2428
  const completeResponse = await this.http.post(
2331
2429
  `${prefix}/storages/files/${storageId}/complete-upload`,
2332
2430
  { file_id: presignedResponse.file_id }
@@ -2345,11 +2443,14 @@ var StorageAPI = class {
2345
2443
  }
2346
2444
  /**
2347
2445
  * 여러 파일 업로드
2446
+ *
2447
+ * `onProgress` 를 옵션으로 넘기면 **파일별로** 진행률 콜백이 호출됩니다
2448
+ * (각 파일마다 0→100%). 전체 진행률이 필요하면 완료된 파일 수를 직접 집계하세요.
2348
2449
  */
2349
- async uploadFiles(storageId, files, parentId) {
2450
+ async uploadFiles(storageId, files, parentIdOrOptions) {
2350
2451
  const results = [];
2351
2452
  for (const file of files) {
2352
- const result = await this.uploadFile(storageId, file, parentId);
2453
+ const result = await this.uploadFile(storageId, file, parentIdOrOptions);
2353
2454
  results.push(result);
2354
2455
  }
2355
2456
  return results;
@@ -2448,7 +2549,11 @@ var StorageAPI = class {
2448
2549
  overwrite
2449
2550
  }
2450
2551
  );
2451
- await this.uploadToPresigned(presignedResponse.upload_url, file);
2552
+ await this.uploadToPresigned(presignedResponse.upload_url, file, {
2553
+ onProgress: options?.onProgress,
2554
+ signal: options?.signal,
2555
+ timeout: options?.timeout
2556
+ });
2452
2557
  const completeResponse = await this.http.post(
2453
2558
  `${prefix}/storages/files/${storageId}/complete-upload`,
2454
2559
  { file_id: presignedResponse.file_id }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "connectbase-client",
3
- "version": "3.48.2",
3
+ "version": "3.50.0",
4
4
  "description": "Connect Base JavaScript/TypeScript SDK for browser and Node.js",
5
5
  "repository": {
6
6
  "type": "git",