@shipstatic/ship 0.3.2 → 0.3.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/README.md CHANGED
@@ -5,9 +5,10 @@ A modern, lightweight SDK and CLI for deploying static files, designed for both
5
5
  ## Features
6
6
 
7
7
  - **🚀 Modern Resource API**: Clean `ship.deployments.create()` interface - no legacy wrappers
8
- - **🌍 Universal**: Automatic environment detection (Node.js/Browser) with optimized implementations
8
+ - **🌍 Universal**: Automatic environment detection (Node.js/Browser) with optimized implementations
9
9
  - **📡 Event System**: Complete observability with request, response, and error events
10
10
  - **🔧 Dynamic Configuration**: Automatically fetches platform limits from API
11
+ - **✅ Client-Side Validation**: Validate files before upload (size, count, MIME types)
11
12
  - **📁 Flexible Input**: File paths (Node.js) or File objects (Browser/drag-drop)
12
13
  - **🔐 Secure**: MD5 checksums and data integrity validation
13
14
  - **📊 Progress Tracking**: Real-time deployment progress and statistics
@@ -133,6 +134,56 @@ const ship = new Ship({ apiKey: 'ship-your-key' });
133
134
  - **Always current** - SDK always uses current platform limits
134
135
  - **Fail fast** - SDK fails if unable to fetch valid configuration
135
136
 
137
+ ## Client-Side File Validation
138
+
139
+ Ship SDK provides utilities for validating files before upload. Validation is **atomic** - if any file is invalid, the entire upload is rejected.
140
+
141
+ ```typescript
142
+ import { validateFiles, formatFileSize } from '@shipstatic/ship';
143
+
144
+ // Get platform configuration
145
+ const config = await ship.getConfig();
146
+
147
+ // Validate files before upload
148
+ const result = validateFiles(files, config);
149
+
150
+ if (result.error) {
151
+ // Global summary
152
+ console.error(result.error.details); // "2 files failed validation"
153
+
154
+ // All specific errors
155
+ result.error.errors.forEach(err => console.error(err));
156
+ // "file1.wasm: File type 'application/wasm' is not allowed"
157
+ // "file2.txt: File size (10 MB) exceeds limit of 5 MB"
158
+
159
+ // Per-file status (all files marked failed in atomic validation)
160
+ result.files.forEach(f => {
161
+ console.log(`${f.name}: ${f.statusMessage}`);
162
+ });
163
+ } else {
164
+ console.log(`${result.validFiles.length} files ready to upload`);
165
+ await ship.deployments.create(result.validFiles);
166
+ }
167
+ ```
168
+
169
+ **Validation checks:**
170
+ - File count limit
171
+ - Individual file size limit
172
+ - Total deployment size limit
173
+ - MIME type validation (against allowed categories)
174
+ - Empty file detection
175
+
176
+ **Error handling:**
177
+ - `error.details` - Human-readable summary ("2 files failed validation")
178
+ - `error.errors` - Array of all validation errors for detailed display
179
+ - `file.statusMessage` - Individual file status for UI highlighting
180
+
181
+ **Utilities:**
182
+ - `validateFiles(files, config)` - Validate files against config limits
183
+ - `formatFileSize(bytes, decimals?)` - Format bytes to human-readable string
184
+ - `getValidFiles(files)` - Filter files with `READY` status
185
+ - `FILE_VALIDATION_STATUS` - Status constants for file processing
186
+
136
187
  ## API Reference
137
188
 
138
189
  ### Ship Class
package/dist/browser.d.ts CHANGED
@@ -439,6 +439,96 @@ declare function __setTestEnvironment(env: ExecutionEnvironment | null): void;
439
439
  */
440
440
  declare function getENV(): ExecutionEnvironment;
441
441
 
442
+ /**
443
+ * @file File validation utilities for Ship SDK
444
+ * Provides client-side validation for file uploads before deployment
445
+ */
446
+
447
+ /**
448
+ * File status constants for validation state tracking
449
+ */
450
+ declare const FILE_VALIDATION_STATUS: {
451
+ readonly PENDING: "pending";
452
+ readonly PROCESSING_ERROR: "processing_error";
453
+ readonly EMPTY_FILE: "empty_file";
454
+ readonly VALIDATION_FAILED: "validation_failed";
455
+ readonly READY: "ready";
456
+ };
457
+ type FileValidationStatus = (typeof FILE_VALIDATION_STATUS)[keyof typeof FILE_VALIDATION_STATUS];
458
+ /**
459
+ * Client-side validation error structure
460
+ */
461
+ interface ValidationError {
462
+ error: string;
463
+ details: string;
464
+ errors: string[];
465
+ isClientError: true;
466
+ }
467
+ /**
468
+ * Minimal file interface required for validation
469
+ */
470
+ interface ValidatableFile {
471
+ name: string;
472
+ size: number;
473
+ type: string;
474
+ status?: string;
475
+ statusMessage?: string;
476
+ }
477
+ /**
478
+ * File validation result
479
+ *
480
+ * NOTE: Validation is ATOMIC - if any file fails validation, ALL files are rejected.
481
+ * This ensures deployments are all-or-nothing for data integrity.
482
+ */
483
+ interface FileValidationResult<T extends ValidatableFile> {
484
+ /** All files with updated status */
485
+ files: T[];
486
+ /** Files that passed validation (empty if ANY file failed - atomic validation) */
487
+ validFiles: T[];
488
+ /** Validation error if any files failed */
489
+ error: ValidationError | null;
490
+ }
491
+ /**
492
+ * Format file size to human-readable string
493
+ */
494
+ declare function formatFileSize(bytes: number, decimals?: number): string;
495
+ /**
496
+ * Validate files against configuration limits
497
+ *
498
+ * ATOMIC VALIDATION: If ANY file fails validation, ALL files are rejected.
499
+ * This ensures deployments are all-or-nothing for data integrity.
500
+ *
501
+ * @param files - Array of files to validate
502
+ * @param config - Validation configuration from ship.getConfig()
503
+ * @returns Validation result with updated file status
504
+ *
505
+ * @example
506
+ * ```typescript
507
+ * const config = await ship.getConfig();
508
+ * const result = validateFiles(files, config);
509
+ *
510
+ * if (result.error) {
511
+ * // Validation failed - result.validFiles will be empty
512
+ * console.error(result.error.details);
513
+ * // Show individual file errors:
514
+ * result.files.forEach(f => console.log(`${f.name}: ${f.statusMessage}`));
515
+ * } else {
516
+ * // All files valid - safe to upload
517
+ * await ship.deploy(result.validFiles);
518
+ * }
519
+ * ```
520
+ */
521
+ declare function validateFiles<T extends ValidatableFile>(files: T[], config: ConfigResponse): FileValidationResult<T>;
522
+ /**
523
+ * Get only the valid files from validation results
524
+ */
525
+ declare function getValidFiles<T extends ValidatableFile>(files: T[]): T[];
526
+ /**
527
+ * Check if all valid files have required properties for upload
528
+ * (Can be extended to check for MD5, etc.)
529
+ */
530
+ declare function allValidFilesReady<T extends ValidatableFile>(files: T[]): boolean;
531
+
442
532
  /**
443
533
  * @file Browser configuration implementation - no file system access.
444
534
  * Browser environment receives all config through constructor options.
@@ -512,4 +602,4 @@ declare class Ship extends Ship$1 {
512
602
  protected processInput(input: DeployInput, options: DeploymentOptions): Promise<StaticFile[]>;
513
603
  }
514
604
 
515
- export { type ApiDeployOptions, ApiHttp, type Config, type DeployFile, type DeploymentOptions, type ExecutionEnvironment, JUNK_DIRECTORIES, type MD5Result, type ProgressStats, Ship, type ShipClientOptions, type ShipEvents, __setTestEnvironment, calculateMD5, createAccountResource, createDeploymentResource, createDomainResource, createTokenResource, Ship as default, filterJunk, getCurrentConfig, getENV, loadConfig, mergeDeployOptions, optimizeDeployPaths, pluralize, processFilesForBrowser, resolveConfig, setConfig as setPlatformConfig };
605
+ export { type ApiDeployOptions, ApiHttp, type Config, type DeployFile, type DeploymentOptions, type ExecutionEnvironment, FILE_VALIDATION_STATUS, type FileValidationResult, type FileValidationStatus, JUNK_DIRECTORIES, type MD5Result, type ProgressStats, Ship, type ShipClientOptions, type ShipEvents, type ValidatableFile, type ValidationError, __setTestEnvironment, allValidFilesReady, calculateMD5, createAccountResource, createDeploymentResource, createDomainResource, createTokenResource, Ship as default, filterJunk, formatFileSize, getCurrentConfig, getENV, getValidFiles, loadConfig, mergeDeployOptions, optimizeDeployPaths, pluralize, processFilesForBrowser, resolveConfig, setConfig as setPlatformConfig, validateFiles };