@shipstatic/drop 0.1.12 → 0.1.14

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
 
@@ -231,7 +231,6 @@ interface DropOptions {
231
231
 
232
232
  **Returns:**
233
233
 
234
- ```typescript
235
234
  ```typescript
236
235
  interface DropReturn {
237
236
  // Convenience getters (computed from state)
@@ -476,27 +475,34 @@ Use `clearAll()` to reset and try again:
476
475
 
477
476
  ```typescript
478
477
  /**
479
- * ProcessedFile extends StaticFile from @shipstatic/types
480
- * This means it can be passed directly to ship.deployments.create()
478
+ * ProcessedFile - a file processed by Drop, ready for Ship SDK deployment
481
479
  *
480
+ * Use the `file` property to pass to ship.deployments.create()
482
481
  * Note: md5 is intentionally undefined - Ship SDK calculates it during deployment
483
482
  */
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
483
+ interface ProcessedFile {
484
+ /** Unique identifier for React keys */
485
+ id: string;
486
+ /** The File object - pass this to ship.deployments.create() */
487
+ file: File;
488
+ /** Relative path for deployment (e.g., "images/photo.jpg") */
489
+ path: string;
490
+ /** File size in bytes */
491
+ size: number;
492
+ /** MD5 hash (optional - Ship SDK calculates during deployment if not provided) */
493
+ md5?: string;
494
+ /** Filename without path */
495
+ name: string;
496
+ /** MIME type for UI icons/previews */
497
+ type: string;
498
+ /** Last modified timestamp */
496
499
  lastModified: number;
500
+ /** Current processing/upload status */
497
501
  status: FileStatus;
498
- statusMessage?: string; // Per-file error message
499
- progress?: number; // Upload progress (0-100)
502
+ /** Human-readable status message for UI */
503
+ statusMessage?: string;
504
+ /** Upload progress (0-100) - only set during upload */
505
+ progress?: number;
500
506
  }
501
507
 
502
508
  interface ClientError {
@@ -519,36 +525,30 @@ type FileStatus =
519
525
 
520
526
  ## Direct Ship SDK Integration
521
527
 
522
- **ProcessedFile extends StaticFile** - no conversion needed! Since `ProcessedFile` extends `StaticFile` from `@shipstatic/types`, you can pass the files directly to the Ship SDK:
528
+ Extract the `file` property from ProcessedFiles to pass to Ship SDK:
523
529
 
524
530
  ```typescript
525
- const validFiles = drop.getValidFiles();
531
+ // Get valid files and extract File objects for deployment
532
+ const filesToDeploy = drop.validFiles.map(f => f.file);
526
533
 
527
- // ProcessedFile[] IS StaticFile[] - pass directly!
528
- await ship.deployments.create({ files: validFiles });
534
+ // Pass File[] to Ship SDK
535
+ await ship.deployments.create(filesToDeploy);
529
536
  ```
530
537
 
531
- ### Type Compatibility
538
+ ### Why Extract `.file`?
539
+
540
+ 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
541
 
533
542
  ```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
543
+ // ProcessedFile structure
544
+ interface ProcessedFile {
545
+ file: File; // Pass this to Ship SDK
546
+ path: string; // Normalized path (set on file.webkitRelativePath)
547
+ // ... UI properties (id, status, progress, etc.)
548
548
  }
549
549
  ```
550
550
 
551
- **Important**: The drop hook preserves folder structure via `webkitRelativePath` and processes paths with `stripCommonPrefix` automatically. The `path` property is always deployment-ready.
551
+ **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
552
 
553
553
  ## Architecture Decisions
554
554
 
@@ -599,19 +599,19 @@ This is the same pattern used by popular libraries like `react-dropzone`, `downs
599
599
  **3. Loosely Coupled Integration**
600
600
  Following industry standards (Firebase hooks, Supabase utilities), we chose:
601
601
  - ✅ **Ship instance as dependency**: Validates using `ship.getConfig()`
602
- - ✅ **Simple output**: ProcessedFile[] can be passed directly to Ship SDK
602
+ - ✅ **Simple output**: Extract `.file` from ProcessedFile[] for Ship SDK
603
603
  - ✅ **Testable**: Easy to mock Ship SDK for testing
604
604
  - ✅ **Flexible**: Host app controls WHEN to deploy
605
605
 
606
606
  **4. Type System Integration**
607
607
 
608
- ProcessedFile extends StaticFile from `@shipstatic/types` - the single source of truth for Ship SDK types:
608
+ ProcessedFile wraps File objects with UI-specific metadata:
609
609
 
610
610
  ```
611
- File[] → ProcessedFile[] (which IS StaticFile[]) → ship.deployments.create()
611
+ File[] → ProcessedFile[] → .map(f => f.file) → ship.deployments.create()
612
612
  ```
613
613
 
614
- No conversion needed. ProcessedFile adds UI-specific properties (id, name, status, progress) to StaticFile's base properties (content, path, size, md5).
614
+ 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
615
 
616
616
  **5. No Visual Components**
617
617
 
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.19/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
  }, []);