@shipstatic/drop 0.1.12 → 0.1.13

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/README.md CHANGED
@@ -85,7 +85,7 @@ function MyUploader() {
85
85
  });
86
86
 
87
87
  const handleUpload = async () => {
88
- // ProcessedFile extends StaticFile - no conversion needed!
88
+ // Extract File objects from ProcessedFiles for Ship SDK
89
89
  await ship.deployments.create(drop.validFiles.map(f => f.file));
90
90
  };
91
91
 
@@ -476,27 +476,34 @@ Use `clearAll()` to reset and try again:
476
476
 
477
477
  ```typescript
478
478
  /**
479
- * ProcessedFile extends StaticFile from @shipstatic/types
480
- * This means it can be passed directly to ship.deployments.create()
479
+ * ProcessedFile - a file processed by Drop, ready for Ship SDK deployment
481
480
  *
481
+ * Use the `file` property to pass to ship.deployments.create()
482
482
  * Note: md5 is intentionally undefined - Ship SDK calculates it during deployment
483
483
  */
484
- interface ProcessedFile extends StaticFile {
485
- // StaticFile properties (SDK compatibility)
486
- content: File; // File object (required by SDK)
487
- path: string; // Normalized path (webkitRelativePath or file.name)
488
- size: number; // File size in bytes
489
- md5?: string; // Undefined - Ship SDK calculates during deployment
490
-
491
- // ProcessedFile-specific properties (UI functionality)
492
- id: string; // Unique identifier for React keys
493
- file: File; // Alias for 'content' (better DX)
494
- name: string; // File name without path
495
- type: string; // MIME type
484
+ interface ProcessedFile {
485
+ /** Unique identifier for React keys */
486
+ id: string;
487
+ /** The File object - pass this to ship.deployments.create() */
488
+ file: File;
489
+ /** Relative path for deployment (e.g., "images/photo.jpg") */
490
+ path: string;
491
+ /** File size in bytes */
492
+ size: number;
493
+ /** MD5 hash (optional - Ship SDK calculates during deployment if not provided) */
494
+ md5?: string;
495
+ /** Filename without path */
496
+ name: string;
497
+ /** MIME type for UI icons/previews */
498
+ type: string;
499
+ /** Last modified timestamp */
496
500
  lastModified: number;
501
+ /** Current processing/upload status */
497
502
  status: FileStatus;
498
- statusMessage?: string; // Per-file error message
499
- progress?: number; // Upload progress (0-100)
503
+ /** Human-readable status message for UI */
504
+ statusMessage?: string;
505
+ /** Upload progress (0-100) - only set during upload */
506
+ progress?: number;
500
507
  }
501
508
 
502
509
  interface ClientError {
@@ -519,36 +526,30 @@ type FileStatus =
519
526
 
520
527
  ## Direct Ship SDK Integration
521
528
 
522
- **ProcessedFile extends StaticFile** - no conversion needed! Since `ProcessedFile` extends `StaticFile` from `@shipstatic/types`, you can pass the files directly to the Ship SDK:
529
+ Extract the `file` property from ProcessedFiles to pass to Ship SDK:
523
530
 
524
531
  ```typescript
525
- const validFiles = drop.getValidFiles();
532
+ // Get valid files and extract File objects for deployment
533
+ const filesToDeploy = drop.validFiles.map(f => f.file);
526
534
 
527
- // ProcessedFile[] IS StaticFile[] - pass directly!
528
- await ship.deployments.create({ files: validFiles });
535
+ // Pass File[] to Ship SDK
536
+ await ship.deployments.create(filesToDeploy);
529
537
  ```
530
538
 
531
- ### Type Compatibility
539
+ ### Why Extract `.file`?
540
+
541
+ Ship SDK's browser `deployments.create()` accepts `File[]`. Drop's `ProcessedFile` wraps the File with additional UI metadata (id, status, progress). The `.file` property gives you the raw File object that Ship SDK expects.
532
542
 
533
543
  ```typescript
534
- // ✅ This works because ProcessedFile extends StaticFile
535
- interface ProcessedFile extends StaticFile {
536
- content: File; // Required by StaticFile
537
- path: string; // Required by StaticFile
538
- size: number; // Required by StaticFile
539
- md5?: string; // Required by StaticFile
540
-
541
- // Additional UI properties
542
- id: string;
543
- file: File; // Alias for 'content' (better DX)
544
- name: string;
545
- type: string;
546
- status: FileStatus;
547
- // ... etc
544
+ // ProcessedFile structure
545
+ interface ProcessedFile {
546
+ file: File; // Pass this to Ship SDK
547
+ path: string; // Normalized path (set on file.webkitRelativePath)
548
+ // ... UI properties (id, status, progress, etc.)
548
549
  }
549
550
  ```
550
551
 
551
- **Important**: The drop hook preserves folder structure via `webkitRelativePath` and processes paths with `stripCommonPrefix` automatically. The `path` property is always deployment-ready.
552
+ **Important**: Drop automatically sets `webkitRelativePath` on each File to preserve folder structure. Ship SDK reads this property during deployment, so paths are handled correctly.
552
553
 
553
554
  ## Architecture Decisions
554
555
 
@@ -599,19 +600,19 @@ This is the same pattern used by popular libraries like `react-dropzone`, `downs
599
600
  **3. Loosely Coupled Integration**
600
601
  Following industry standards (Firebase hooks, Supabase utilities), we chose:
601
602
  - ✅ **Ship instance as dependency**: Validates using `ship.getConfig()`
602
- - ✅ **Simple output**: ProcessedFile[] can be passed directly to Ship SDK
603
+ - ✅ **Simple output**: Extract `.file` from ProcessedFile[] for Ship SDK
603
604
  - ✅ **Testable**: Easy to mock Ship SDK for testing
604
605
  - ✅ **Flexible**: Host app controls WHEN to deploy
605
606
 
606
607
  **4. Type System Integration**
607
608
 
608
- ProcessedFile extends StaticFile from `@shipstatic/types` - the single source of truth for Ship SDK types:
609
+ ProcessedFile wraps File objects with UI-specific metadata:
609
610
 
610
611
  ```
611
- File[] → ProcessedFile[] (which IS StaticFile[]) → ship.deployments.create()
612
+ File[] → ProcessedFile[] → .map(f => f.file) → ship.deployments.create()
612
613
  ```
613
614
 
614
- No conversion needed. ProcessedFile adds UI-specific properties (id, name, status, progress) to StaticFile's base properties (content, path, size, md5).
615
+ ProcessedFile adds UI properties (id, name, status, progress) while preserving the original File object. The `.file` property gives you direct access for Ship SDK deployment.
615
616
 
616
617
  **5. No Visual Components**
617
618
 
package/dist/index.cjs CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  var react = require('react');
4
4
  var ship = require('@shipstatic/ship');
5
- var types = require('@shipstatic/types');
6
5
 
7
6
  var __create = Object.create;
8
7
  var __defProp = Object.defineProperty;
@@ -11703,6 +11702,42 @@ var require_mime_db = __commonJS({
11703
11702
  }
11704
11703
  });
11705
11704
 
11705
+ // node_modules/.pnpm/@shipstatic+types@0.3.18/node_modules/@shipstatic/types/dist/index.js
11706
+ var ErrorType;
11707
+ (function(ErrorType2) {
11708
+ ErrorType2["Validation"] = "validation_failed";
11709
+ ErrorType2["NotFound"] = "not_found";
11710
+ ErrorType2["RateLimit"] = "rate_limit_exceeded";
11711
+ ErrorType2["Authentication"] = "authentication_failed";
11712
+ ErrorType2["Business"] = "business_logic_error";
11713
+ ErrorType2["Api"] = "internal_server_error";
11714
+ ErrorType2["Network"] = "network_error";
11715
+ ErrorType2["Cancelled"] = "operation_cancelled";
11716
+ ErrorType2["File"] = "file_error";
11717
+ ErrorType2["Config"] = "config_error";
11718
+ })(ErrorType || (ErrorType = {}));
11719
+ ({
11720
+ client: /* @__PURE__ */ new Set([ErrorType.Business, ErrorType.Config, ErrorType.File, ErrorType.Validation]),
11721
+ network: /* @__PURE__ */ new Set([ErrorType.Network]),
11722
+ auth: /* @__PURE__ */ new Set([ErrorType.Authentication])
11723
+ });
11724
+ var FileValidationStatus = {
11725
+ PENDING: "pending",
11726
+ PROCESSING_ERROR: "processing_error",
11727
+ EMPTY_FILE: "empty_file",
11728
+ VALIDATION_FAILED: "validation_failed",
11729
+ READY: "ready"
11730
+ };
11731
+
11732
+ // src/types.ts
11733
+ var FILE_STATUSES = {
11734
+ ...FileValidationStatus,
11735
+ PROCESSING: "processing",
11736
+ UPLOADING: "uploading",
11737
+ COMPLETE: "complete",
11738
+ ERROR: "error"
11739
+ };
11740
+
11706
11741
  // src/utils/zipExtractor.ts
11707
11742
  var import_jszip = __toESM(require_jszip_min());
11708
11743
 
@@ -11778,15 +11813,6 @@ function normalizePath(path) {
11778
11813
  function isZipFile(file) {
11779
11814
  return file.type === "application/zip" || file.type === "application/x-zip-compressed" || file.name.toLowerCase().endsWith(".zip");
11780
11815
  }
11781
- var FILE_STATUSES = {
11782
- ...types.FileValidationStatus,
11783
- PROCESSING: "processing",
11784
- UPLOADING: "uploading",
11785
- COMPLETE: "complete",
11786
- ERROR: "error"
11787
- };
11788
-
11789
- // src/utils/fileProcessing.ts
11790
11816
  var formatFileSize = ship.formatFileSize;
11791
11817
  async function createProcessedFile(file, options) {
11792
11818
  const webkitPath = file.webkitRelativePath || "";
@@ -12028,7 +12054,17 @@ function useDrop(options) {
12028
12054
  e.preventDefault();
12029
12055
  setState((prev) => {
12030
12056
  if (prev.value !== "dragging") return prev;
12031
- const nextValue = prev.files.length > 0 ? prev.status?.title === "Ready" ? "ready" : "error" : "idle";
12057
+ if (prev.files.length === 0) {
12058
+ return { ...prev, value: "idle" };
12059
+ }
12060
+ const errorStatuses = [
12061
+ FILE_STATUSES.VALIDATION_FAILED,
12062
+ FILE_STATUSES.PROCESSING_ERROR,
12063
+ FILE_STATUSES.EMPTY_FILE,
12064
+ FILE_STATUSES.ERROR
12065
+ ];
12066
+ const hasErrors = prev.files.some((f) => errorStatuses.includes(f.status));
12067
+ const nextValue = hasErrors ? "error" : "ready";
12032
12068
  return { ...prev, value: nextValue };
12033
12069
  });
12034
12070
  }, []);