@air/api-rest 0.1.2 → 0.1.3

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.cjs CHANGED
@@ -420,22 +420,23 @@ var Uploads = class {
420
420
  });
421
421
  }
422
422
  async uploadFile(params, options = {}) {
423
- const { fileData, fileName, ext, mime, size } = await resolveFileData(params);
423
+ const meta = await resolveFileMeta(params);
424
424
  const uploadResponse = await this.create({
425
- fileName,
426
- ext,
427
- size,
428
- mime,
425
+ fileName: meta.fileName,
426
+ ext: meta.ext,
427
+ size: meta.size,
428
+ mime: meta.mime,
429
429
  parentBoardId: options.parentBoardId,
430
430
  assetId: options.assetId,
431
431
  customFields: options.customFields,
432
432
  tags: options.tags
433
433
  });
434
434
  if (isSmallUpload(uploadResponse)) {
435
- await this._uploadSmallFile(uploadResponse.uploadUrl, fileData, options.onProgress, size);
435
+ const data = await materializeData(meta);
436
+ await this._uploadSmallFile(uploadResponse.uploadUrl, data, options.onProgress, meta.size);
436
437
  return { assetId: uploadResponse.assetId, versionId: uploadResponse.versionId };
437
438
  }
438
- await this._uploadLargeFile(uploadResponse, fileData, size, options.onProgress);
439
+ await this._uploadLargeFile(uploadResponse, meta, options.onProgress);
439
440
  return { assetId: uploadResponse.assetId, versionId: uploadResponse.versionId };
440
441
  }
441
442
  async _uploadSmallFile(url, data, onProgress, totalSize) {
@@ -451,42 +452,73 @@ var Uploads = class {
451
452
  onProgress({ percentage: 100, uploadedBytes: totalSize, totalBytes: totalSize });
452
453
  }
453
454
  }
454
- async _uploadLargeFile(uploadInfo, data, totalSize, onProgress) {
455
+ async _uploadLargeFile(uploadInfo, meta, onProgress) {
455
456
  const { multiPartUploadId, key } = uploadInfo;
456
- const buffer = data instanceof Buffer ? data : Buffer.from(data);
457
+ const { size: totalSize } = meta;
457
458
  const partCount = Math.ceil(totalSize / DEFAULT_PART_SIZE);
458
459
  const parts = [];
459
460
  let uploadedBytes = 0;
460
461
  const fetchFn = this.client.fetchFn;
461
- for (let i = 0; i < partCount; i++) {
462
- const partNumber = i + 1;
463
- const start = i * DEFAULT_PART_SIZE;
464
- const end = Math.min(start + DEFAULT_PART_SIZE, totalSize);
465
- const chunk = buffer.subarray(start, end);
466
- const { url } = await this.getPartUploadUrl({
467
- multiPartUploadId,
468
- key,
469
- partNumber
470
- });
471
- const response = await fetchFn(url, {
472
- method: "PUT",
473
- body: chunk
474
- });
475
- if (!response.ok) {
476
- throw new Error(`Part ${partNumber} upload failed with status ${response.status}`);
462
+ if (meta.source.type === "path") {
463
+ const fs = await import("fs");
464
+ const fd = fs.openSync(meta.source.filePath, "r");
465
+ try {
466
+ for (let i = 0; i < partCount; i++) {
467
+ const partNumber = i + 1;
468
+ const start = i * DEFAULT_PART_SIZE;
469
+ const end = Math.min(start + DEFAULT_PART_SIZE, totalSize);
470
+ const length = end - start;
471
+ const chunk = Buffer.alloc(length);
472
+ const bytesRead = fs.readSync(fd, chunk, 0, length, start);
473
+ const body = bytesRead < length ? chunk.subarray(0, bytesRead) : chunk;
474
+ const { url } = await this.getPartUploadUrl({ multiPartUploadId, key, partNumber });
475
+ const response = await fetchFn(url, { method: "PUT", body });
476
+ if (!response.ok) {
477
+ throw new Error(`Part ${partNumber} upload failed with status ${response.status}`);
478
+ }
479
+ const etag = response.headers.get("etag");
480
+ if (!etag) {
481
+ throw new Error(`Part ${partNumber} upload did not return an ETag`);
482
+ }
483
+ parts.push({ etag, partNumber });
484
+ uploadedBytes += bytesRead;
485
+ if (onProgress) {
486
+ onProgress({
487
+ percentage: Math.round(uploadedBytes / totalSize * 100),
488
+ uploadedBytes,
489
+ totalBytes: totalSize
490
+ });
491
+ }
492
+ }
493
+ } finally {
494
+ fs.closeSync(fd);
477
495
  }
478
- const etag = response.headers.get("etag");
479
- if (!etag) {
480
- throw new Error(`Part ${partNumber} upload did not return an ETag`);
481
- }
482
- parts.push({ etag, partNumber });
483
- uploadedBytes += chunk.byteLength;
484
- if (onProgress) {
485
- onProgress({
486
- percentage: Math.round(uploadedBytes / totalSize * 100),
487
- uploadedBytes,
488
- totalBytes: totalSize
489
- });
496
+ } else {
497
+ const buffer = await materializeData(meta);
498
+ const buf = buffer instanceof Buffer ? buffer : Buffer.from(buffer);
499
+ for (let i = 0; i < partCount; i++) {
500
+ const partNumber = i + 1;
501
+ const start = i * DEFAULT_PART_SIZE;
502
+ const end = Math.min(start + DEFAULT_PART_SIZE, totalSize);
503
+ const chunk = buf.subarray(start, end);
504
+ const { url } = await this.getPartUploadUrl({ multiPartUploadId, key, partNumber });
505
+ const response = await fetchFn(url, { method: "PUT", body: chunk });
506
+ if (!response.ok) {
507
+ throw new Error(`Part ${partNumber} upload failed with status ${response.status}`);
508
+ }
509
+ const etag = response.headers.get("etag");
510
+ if (!etag) {
511
+ throw new Error(`Part ${partNumber} upload did not return an ETag`);
512
+ }
513
+ parts.push({ etag, partNumber });
514
+ uploadedBytes += chunk.byteLength;
515
+ if (onProgress) {
516
+ onProgress({
517
+ percentage: Math.round(uploadedBytes / totalSize * 100),
518
+ uploadedBytes,
519
+ totalBytes: totalSize
520
+ });
521
+ }
490
522
  }
491
523
  }
492
524
  await this.completeMultipart({ multiPartUploadId, key, parts });
@@ -495,16 +527,22 @@ var Uploads = class {
495
527
  function isSmallUpload(response) {
496
528
  return "uploadUrl" in response;
497
529
  }
498
- async function resolveFileData(params) {
530
+ async function resolveFileMeta(params) {
499
531
  if (params.filePath) {
500
532
  const fs = await import("fs");
501
533
  const path = await import("path");
502
- const fileData = fs.readFileSync(params.filePath);
534
+ const stat = fs.statSync(params.filePath);
503
535
  const parsed = path.parse(params.filePath);
504
536
  const fileName = params.fileName ?? parsed.name;
505
537
  const ext = params.ext ?? parsed.ext.replace(/^\./, "");
506
538
  const mime = params.mime ?? guessMime(ext);
507
- return { fileData, fileName, ext, mime, size: fileData.byteLength };
539
+ return {
540
+ source: { type: "path", filePath: params.filePath },
541
+ fileName,
542
+ ext,
543
+ mime,
544
+ size: stat.size
545
+ };
508
546
  }
509
547
  if (params.buffer) {
510
548
  const data = params.buffer instanceof Buffer ? params.buffer : Buffer.from(params.buffer);
@@ -513,7 +551,7 @@ async function resolveFileData(params) {
513
551
  }
514
552
  const mime = params.mime ?? guessMime(params.ext);
515
553
  return {
516
- fileData: data,
554
+ source: { type: "buffer", data },
517
555
  fileName: params.fileName,
518
556
  ext: params.ext,
519
557
  mime,
@@ -521,17 +559,35 @@ async function resolveFileData(params) {
521
559
  };
522
560
  }
523
561
  if (params.file) {
524
- const arrayBuffer = await params.file.arrayBuffer();
525
- const data = new Uint8Array(arrayBuffer);
526
562
  const name = params.file.name;
527
563
  const dotIndex = name.lastIndexOf(".");
528
564
  const fileName = params.fileName ?? (dotIndex > 0 ? name.substring(0, dotIndex) : name);
529
565
  const ext = params.ext ?? (dotIndex > 0 ? name.substring(dotIndex + 1) : "");
530
566
  const mime = params.mime ?? (params.file.type || guessMime(ext));
531
- return { fileData: data, fileName, ext, mime, size: data.byteLength };
567
+ return {
568
+ source: { type: "file", file: params.file },
569
+ fileName,
570
+ ext,
571
+ mime,
572
+ size: params.file.size
573
+ };
532
574
  }
533
575
  throw new Error("One of filePath, buffer, or file must be provided");
534
576
  }
577
+ async function materializeData(meta) {
578
+ switch (meta.source.type) {
579
+ case "path": {
580
+ const fs = await import("fs");
581
+ return fs.readFileSync(meta.source.filePath);
582
+ }
583
+ case "buffer":
584
+ return meta.source.data;
585
+ case "file": {
586
+ const arrayBuffer = await meta.source.file.arrayBuffer();
587
+ return new Uint8Array(arrayBuffer);
588
+ }
589
+ }
590
+ }
535
591
  function guessMime(ext) {
536
592
  const mimeMap = {
537
593
  jpg: "image/jpeg",
package/dist/index.d.cts CHANGED
@@ -341,6 +341,23 @@ interface CompleteMultipartParams {
341
341
  partNumber: number;
342
342
  }[];
343
343
  }
344
+ type FileSource = {
345
+ type: "path";
346
+ filePath: string;
347
+ } | {
348
+ type: "buffer";
349
+ data: Buffer;
350
+ } | {
351
+ type: "file";
352
+ file: File;
353
+ };
354
+ interface FileMeta {
355
+ source: FileSource;
356
+ fileName: string;
357
+ ext: string;
358
+ mime: string;
359
+ size: number;
360
+ }
344
361
  interface UploadFileParams {
345
362
  filePath?: string;
346
363
  buffer?: Buffer | ArrayBuffer;
@@ -397,4 +414,4 @@ declare class AirApi extends AirBase {
397
414
  constructor(options?: AirApiOptions);
398
415
  }
399
416
 
400
- export { type AddBoardAssetsParams, type AddGuestParams, type AddVersionTagParams, AirApi, type AirApiOptions, type Asset, type AssetBoardListParams, type AssetCustomFieldValue, type AssetListParams, type AssetVersion, type AssetVersionDownloadUrl, type AssetVersionListResponse, type AssetVersionUpdateParams, type AssetVersionUrls, Assets, type Board, type BoardCreateParams, type BoardListParams, type BoardUpdateParams, Boards, type CompleteMultipartParams, type CustomField, type CustomFieldCreateParams, type CustomFieldListParams, type CustomFieldType, type CustomFieldUpdateParams, type CustomFieldValue, type CustomFieldValueCreateParams, type CustomFieldValueUpdateParams, CustomFields, type GetPartUploadUrlParams, type GetPartUploadUrlResponse, type Guest, type GuestListParams, type GuestListResponse, type ImportCreateParams, type ImportCreateResponse, type ImportStatus, type ImportStatusResponse, Imports, type LargeUploadResponse, type Role, type RoleListParams, type RoleListResponse, Roles, type SetBoardCustomFieldParams, type SetCustomFieldParams, type SmallUploadResponse, type SmartTag, type Tag, type TagCreateParams, type TagListParams, type TagUpdateParams, Tags, type UpdateGuestParams, type UploadCreateParams, type UploadCreateResponse, type UploadFileOptions, type UploadFileParams, type UploadFileResponse, Uploads };
417
+ export { type AddBoardAssetsParams, type AddGuestParams, type AddVersionTagParams, AirApi, type AirApiOptions, type Asset, type AssetBoardListParams, type AssetCustomFieldValue, type AssetListParams, type AssetVersion, type AssetVersionDownloadUrl, type AssetVersionListResponse, type AssetVersionUpdateParams, type AssetVersionUrls, Assets, type Board, type BoardCreateParams, type BoardListParams, type BoardUpdateParams, Boards, type CompleteMultipartParams, type CustomField, type CustomFieldCreateParams, type CustomFieldListParams, type CustomFieldType, type CustomFieldUpdateParams, type CustomFieldValue, type CustomFieldValueCreateParams, type CustomFieldValueUpdateParams, CustomFields, type FileMeta, type FileSource, type GetPartUploadUrlParams, type GetPartUploadUrlResponse, type Guest, type GuestListParams, type GuestListResponse, type ImportCreateParams, type ImportCreateResponse, type ImportStatus, type ImportStatusResponse, Imports, type LargeUploadResponse, type Role, type RoleListParams, type RoleListResponse, Roles, type SetBoardCustomFieldParams, type SetCustomFieldParams, type SmallUploadResponse, type SmartTag, type Tag, type TagCreateParams, type TagListParams, type TagUpdateParams, Tags, type UpdateGuestParams, type UploadCreateParams, type UploadCreateResponse, type UploadFileOptions, type UploadFileParams, type UploadFileResponse, Uploads };
package/dist/index.d.ts CHANGED
@@ -341,6 +341,23 @@ interface CompleteMultipartParams {
341
341
  partNumber: number;
342
342
  }[];
343
343
  }
344
+ type FileSource = {
345
+ type: "path";
346
+ filePath: string;
347
+ } | {
348
+ type: "buffer";
349
+ data: Buffer;
350
+ } | {
351
+ type: "file";
352
+ file: File;
353
+ };
354
+ interface FileMeta {
355
+ source: FileSource;
356
+ fileName: string;
357
+ ext: string;
358
+ mime: string;
359
+ size: number;
360
+ }
344
361
  interface UploadFileParams {
345
362
  filePath?: string;
346
363
  buffer?: Buffer | ArrayBuffer;
@@ -397,4 +414,4 @@ declare class AirApi extends AirBase {
397
414
  constructor(options?: AirApiOptions);
398
415
  }
399
416
 
400
- export { type AddBoardAssetsParams, type AddGuestParams, type AddVersionTagParams, AirApi, type AirApiOptions, type Asset, type AssetBoardListParams, type AssetCustomFieldValue, type AssetListParams, type AssetVersion, type AssetVersionDownloadUrl, type AssetVersionListResponse, type AssetVersionUpdateParams, type AssetVersionUrls, Assets, type Board, type BoardCreateParams, type BoardListParams, type BoardUpdateParams, Boards, type CompleteMultipartParams, type CustomField, type CustomFieldCreateParams, type CustomFieldListParams, type CustomFieldType, type CustomFieldUpdateParams, type CustomFieldValue, type CustomFieldValueCreateParams, type CustomFieldValueUpdateParams, CustomFields, type GetPartUploadUrlParams, type GetPartUploadUrlResponse, type Guest, type GuestListParams, type GuestListResponse, type ImportCreateParams, type ImportCreateResponse, type ImportStatus, type ImportStatusResponse, Imports, type LargeUploadResponse, type Role, type RoleListParams, type RoleListResponse, Roles, type SetBoardCustomFieldParams, type SetCustomFieldParams, type SmallUploadResponse, type SmartTag, type Tag, type TagCreateParams, type TagListParams, type TagUpdateParams, Tags, type UpdateGuestParams, type UploadCreateParams, type UploadCreateResponse, type UploadFileOptions, type UploadFileParams, type UploadFileResponse, Uploads };
417
+ export { type AddBoardAssetsParams, type AddGuestParams, type AddVersionTagParams, AirApi, type AirApiOptions, type Asset, type AssetBoardListParams, type AssetCustomFieldValue, type AssetListParams, type AssetVersion, type AssetVersionDownloadUrl, type AssetVersionListResponse, type AssetVersionUpdateParams, type AssetVersionUrls, Assets, type Board, type BoardCreateParams, type BoardListParams, type BoardUpdateParams, Boards, type CompleteMultipartParams, type CustomField, type CustomFieldCreateParams, type CustomFieldListParams, type CustomFieldType, type CustomFieldUpdateParams, type CustomFieldValue, type CustomFieldValueCreateParams, type CustomFieldValueUpdateParams, CustomFields, type FileMeta, type FileSource, type GetPartUploadUrlParams, type GetPartUploadUrlResponse, type Guest, type GuestListParams, type GuestListResponse, type ImportCreateParams, type ImportCreateResponse, type ImportStatus, type ImportStatusResponse, Imports, type LargeUploadResponse, type Role, type RoleListParams, type RoleListResponse, Roles, type SetBoardCustomFieldParams, type SetCustomFieldParams, type SmallUploadResponse, type SmartTag, type Tag, type TagCreateParams, type TagListParams, type TagUpdateParams, Tags, type UpdateGuestParams, type UploadCreateParams, type UploadCreateResponse, type UploadFileOptions, type UploadFileParams, type UploadFileResponse, Uploads };
package/dist/index.js CHANGED
@@ -364,22 +364,23 @@ var Uploads = class {
364
364
  });
365
365
  }
366
366
  async uploadFile(params, options = {}) {
367
- const { fileData, fileName, ext, mime, size } = await resolveFileData(params);
367
+ const meta = await resolveFileMeta(params);
368
368
  const uploadResponse = await this.create({
369
- fileName,
370
- ext,
371
- size,
372
- mime,
369
+ fileName: meta.fileName,
370
+ ext: meta.ext,
371
+ size: meta.size,
372
+ mime: meta.mime,
373
373
  parentBoardId: options.parentBoardId,
374
374
  assetId: options.assetId,
375
375
  customFields: options.customFields,
376
376
  tags: options.tags
377
377
  });
378
378
  if (isSmallUpload(uploadResponse)) {
379
- await this._uploadSmallFile(uploadResponse.uploadUrl, fileData, options.onProgress, size);
379
+ const data = await materializeData(meta);
380
+ await this._uploadSmallFile(uploadResponse.uploadUrl, data, options.onProgress, meta.size);
380
381
  return { assetId: uploadResponse.assetId, versionId: uploadResponse.versionId };
381
382
  }
382
- await this._uploadLargeFile(uploadResponse, fileData, size, options.onProgress);
383
+ await this._uploadLargeFile(uploadResponse, meta, options.onProgress);
383
384
  return { assetId: uploadResponse.assetId, versionId: uploadResponse.versionId };
384
385
  }
385
386
  async _uploadSmallFile(url, data, onProgress, totalSize) {
@@ -395,42 +396,73 @@ var Uploads = class {
395
396
  onProgress({ percentage: 100, uploadedBytes: totalSize, totalBytes: totalSize });
396
397
  }
397
398
  }
398
- async _uploadLargeFile(uploadInfo, data, totalSize, onProgress) {
399
+ async _uploadLargeFile(uploadInfo, meta, onProgress) {
399
400
  const { multiPartUploadId, key } = uploadInfo;
400
- const buffer = data instanceof Buffer ? data : Buffer.from(data);
401
+ const { size: totalSize } = meta;
401
402
  const partCount = Math.ceil(totalSize / DEFAULT_PART_SIZE);
402
403
  const parts = [];
403
404
  let uploadedBytes = 0;
404
405
  const fetchFn = this.client.fetchFn;
405
- for (let i = 0; i < partCount; i++) {
406
- const partNumber = i + 1;
407
- const start = i * DEFAULT_PART_SIZE;
408
- const end = Math.min(start + DEFAULT_PART_SIZE, totalSize);
409
- const chunk = buffer.subarray(start, end);
410
- const { url } = await this.getPartUploadUrl({
411
- multiPartUploadId,
412
- key,
413
- partNumber
414
- });
415
- const response = await fetchFn(url, {
416
- method: "PUT",
417
- body: chunk
418
- });
419
- if (!response.ok) {
420
- throw new Error(`Part ${partNumber} upload failed with status ${response.status}`);
406
+ if (meta.source.type === "path") {
407
+ const fs = await import("fs");
408
+ const fd = fs.openSync(meta.source.filePath, "r");
409
+ try {
410
+ for (let i = 0; i < partCount; i++) {
411
+ const partNumber = i + 1;
412
+ const start = i * DEFAULT_PART_SIZE;
413
+ const end = Math.min(start + DEFAULT_PART_SIZE, totalSize);
414
+ const length = end - start;
415
+ const chunk = Buffer.alloc(length);
416
+ const bytesRead = fs.readSync(fd, chunk, 0, length, start);
417
+ const body = bytesRead < length ? chunk.subarray(0, bytesRead) : chunk;
418
+ const { url } = await this.getPartUploadUrl({ multiPartUploadId, key, partNumber });
419
+ const response = await fetchFn(url, { method: "PUT", body });
420
+ if (!response.ok) {
421
+ throw new Error(`Part ${partNumber} upload failed with status ${response.status}`);
422
+ }
423
+ const etag = response.headers.get("etag");
424
+ if (!etag) {
425
+ throw new Error(`Part ${partNumber} upload did not return an ETag`);
426
+ }
427
+ parts.push({ etag, partNumber });
428
+ uploadedBytes += bytesRead;
429
+ if (onProgress) {
430
+ onProgress({
431
+ percentage: Math.round(uploadedBytes / totalSize * 100),
432
+ uploadedBytes,
433
+ totalBytes: totalSize
434
+ });
435
+ }
436
+ }
437
+ } finally {
438
+ fs.closeSync(fd);
421
439
  }
422
- const etag = response.headers.get("etag");
423
- if (!etag) {
424
- throw new Error(`Part ${partNumber} upload did not return an ETag`);
425
- }
426
- parts.push({ etag, partNumber });
427
- uploadedBytes += chunk.byteLength;
428
- if (onProgress) {
429
- onProgress({
430
- percentage: Math.round(uploadedBytes / totalSize * 100),
431
- uploadedBytes,
432
- totalBytes: totalSize
433
- });
440
+ } else {
441
+ const buffer = await materializeData(meta);
442
+ const buf = buffer instanceof Buffer ? buffer : Buffer.from(buffer);
443
+ for (let i = 0; i < partCount; i++) {
444
+ const partNumber = i + 1;
445
+ const start = i * DEFAULT_PART_SIZE;
446
+ const end = Math.min(start + DEFAULT_PART_SIZE, totalSize);
447
+ const chunk = buf.subarray(start, end);
448
+ const { url } = await this.getPartUploadUrl({ multiPartUploadId, key, partNumber });
449
+ const response = await fetchFn(url, { method: "PUT", body: chunk });
450
+ if (!response.ok) {
451
+ throw new Error(`Part ${partNumber} upload failed with status ${response.status}`);
452
+ }
453
+ const etag = response.headers.get("etag");
454
+ if (!etag) {
455
+ throw new Error(`Part ${partNumber} upload did not return an ETag`);
456
+ }
457
+ parts.push({ etag, partNumber });
458
+ uploadedBytes += chunk.byteLength;
459
+ if (onProgress) {
460
+ onProgress({
461
+ percentage: Math.round(uploadedBytes / totalSize * 100),
462
+ uploadedBytes,
463
+ totalBytes: totalSize
464
+ });
465
+ }
434
466
  }
435
467
  }
436
468
  await this.completeMultipart({ multiPartUploadId, key, parts });
@@ -439,16 +471,22 @@ var Uploads = class {
439
471
  function isSmallUpload(response) {
440
472
  return "uploadUrl" in response;
441
473
  }
442
- async function resolveFileData(params) {
474
+ async function resolveFileMeta(params) {
443
475
  if (params.filePath) {
444
476
  const fs = await import("fs");
445
477
  const path = await import("path");
446
- const fileData = fs.readFileSync(params.filePath);
478
+ const stat = fs.statSync(params.filePath);
447
479
  const parsed = path.parse(params.filePath);
448
480
  const fileName = params.fileName ?? parsed.name;
449
481
  const ext = params.ext ?? parsed.ext.replace(/^\./, "");
450
482
  const mime = params.mime ?? guessMime(ext);
451
- return { fileData, fileName, ext, mime, size: fileData.byteLength };
483
+ return {
484
+ source: { type: "path", filePath: params.filePath },
485
+ fileName,
486
+ ext,
487
+ mime,
488
+ size: stat.size
489
+ };
452
490
  }
453
491
  if (params.buffer) {
454
492
  const data = params.buffer instanceof Buffer ? params.buffer : Buffer.from(params.buffer);
@@ -457,7 +495,7 @@ async function resolveFileData(params) {
457
495
  }
458
496
  const mime = params.mime ?? guessMime(params.ext);
459
497
  return {
460
- fileData: data,
498
+ source: { type: "buffer", data },
461
499
  fileName: params.fileName,
462
500
  ext: params.ext,
463
501
  mime,
@@ -465,17 +503,35 @@ async function resolveFileData(params) {
465
503
  };
466
504
  }
467
505
  if (params.file) {
468
- const arrayBuffer = await params.file.arrayBuffer();
469
- const data = new Uint8Array(arrayBuffer);
470
506
  const name = params.file.name;
471
507
  const dotIndex = name.lastIndexOf(".");
472
508
  const fileName = params.fileName ?? (dotIndex > 0 ? name.substring(0, dotIndex) : name);
473
509
  const ext = params.ext ?? (dotIndex > 0 ? name.substring(dotIndex + 1) : "");
474
510
  const mime = params.mime ?? (params.file.type || guessMime(ext));
475
- return { fileData: data, fileName, ext, mime, size: data.byteLength };
511
+ return {
512
+ source: { type: "file", file: params.file },
513
+ fileName,
514
+ ext,
515
+ mime,
516
+ size: params.file.size
517
+ };
476
518
  }
477
519
  throw new Error("One of filePath, buffer, or file must be provided");
478
520
  }
521
+ async function materializeData(meta) {
522
+ switch (meta.source.type) {
523
+ case "path": {
524
+ const fs = await import("fs");
525
+ return fs.readFileSync(meta.source.filePath);
526
+ }
527
+ case "buffer":
528
+ return meta.source.data;
529
+ case "file": {
530
+ const arrayBuffer = await meta.source.file.arrayBuffer();
531
+ return new Uint8Array(arrayBuffer);
532
+ }
533
+ }
534
+ }
479
535
  function guessMime(ext) {
480
536
  const mimeMap = {
481
537
  jpg: "image/jpeg",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@air/api-rest",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "description": "Typed REST client for Air API",
6
6
  "main": "./dist/index.cjs",