@shipstatic/types 0.1.14 → 0.2.1

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
@@ -1,6 +1,6 @@
1
- # Shipstatic Types
1
+ # @shipstatic/types
2
2
 
3
- Shared TypeScript types and constants for the Shipstatic platform. This package provides a single source of truth for types, errors, and configuration across the Shipstatic ecosystem.
3
+ Shared TypeScript types, constants, and utilities for the Shipstatic platform. This package is the single source of truth for all shared data structures used across the API, SDK, and CLI.
4
4
 
5
5
  ## Overview
6
6
 
@@ -9,82 +9,146 @@ This package contains all shared types used between:
9
9
  - **Shipstatic SDK** (`/ship`) - Universal SDK for Node.js and Browser
10
10
  - **Shipstatic CLI** - Command-line interface
11
11
 
12
- ## Core Types
12
+ ## Core Entities
13
13
 
14
- ### Deployment Types
14
+ ### Deployment
15
15
 
16
16
  ```typescript
17
- // Core deployment object
18
17
  interface Deployment {
19
- deployment: string; // Deployment ID
20
- files: number; // Number of files
21
- size: number; // Total size in bytes
18
+ deployment: string; // Deployment ID (e.g., "happy-cat-abc1234")
19
+ files: number; // Number of files in deployment
20
+ size: number; // Total size in bytes
21
+ status: 'pending' | 'success' | 'failed' | 'deleting';
22
+ config?: boolean; // Whether deployment has ship.json
23
+ url: string; // Deployment URL
24
+ created: number; // Unix timestamp (seconds)
25
+ expires?: number; // Unix timestamp (seconds)
26
+ verified?: number; // Unix timestamp (seconds) when verified
27
+ }
28
+ ```
29
+
30
+ ### Alias
31
+
32
+ ```typescript
33
+ interface Alias {
34
+ alias: string; // Alias name (subdomain or custom domain)
35
+ deployment: string; // Target deployment ID
22
36
  status: 'pending' | 'success' | 'failed';
23
- created: number; // Unix timestamp
24
- expires?: number; // Unix timestamp
25
- verified?: number; // Unix timestamp
37
+ url: string; // Alias URL
38
+ created: number; // Unix timestamp (seconds)
39
+ confirmed?: number; // Unix timestamp (seconds) when confirmed
40
+ isCreate?: boolean; // Present in set operations only
26
41
  }
42
+ ```
27
43
 
28
- // Successful deployment response
29
- interface DeploySuccessResponse {
30
- success: true;
31
- deployment: string;
32
- expires: number;
33
- files: number;
34
- size: number;
44
+ ### Account
45
+
46
+ ```typescript
47
+ interface Account {
48
+ email: string; // User email address
49
+ name: string; // User display name
50
+ picture?: string; // Profile picture URL
51
+ plan: 'free' | 'active' | 'suspended'; // Account plan status
52
+ created: number; // Unix timestamp (seconds)
53
+ subscribed?: number; // Unix timestamp (seconds) when plan started
54
+ suspended?: number; // Unix timestamp (seconds) when suspended
35
55
  }
56
+ ```
36
57
 
37
- // Deployment list response
38
- interface DeploymentListResponse {
39
- deployments: Deployment[];
40
- cursor?: string;
41
- total?: number;
58
+ ### Static File
59
+
60
+ ```typescript
61
+ interface StaticFile {
62
+ content: File | Buffer | Blob; // File content
63
+ path: string; // Server path (e.g., "assets/style.css")
64
+ filePath?: string; // Original filesystem path (Node.js)
65
+ md5?: string; // MD5 hash of content
66
+ size: number; // File size in bytes
42
67
  }
43
68
  ```
44
69
 
45
- ### Alias Types
70
+ ## API Response Types
71
+
72
+ ### Success Responses
46
73
 
47
74
  ```typescript
48
- // Core alias object
49
- interface Alias {
50
- alias: string; // Alias name
51
- deployment: string; // Target deployment ID
52
- status: 'pending' | 'success' | 'failed';
53
- created: number; // Unix timestamp
54
- confirmed?: number; // Unix timestamp
75
+ interface DeploymentListResponse {
76
+ deployments: Deployment[];
77
+ cursor?: string; // Pagination cursor
78
+ total?: number; // Total count if available
55
79
  }
56
80
 
57
- // Alias list response
58
81
  interface AliasListResponse {
59
82
  aliases: Alias[];
60
83
  cursor?: string;
61
84
  total?: number;
62
85
  }
86
+
87
+ interface SuccessResponse<T = any> {
88
+ success: true;
89
+ data: T;
90
+ }
63
91
  ```
64
92
 
65
- ### Account Types
93
+ ### Configuration
66
94
 
67
95
  ```typescript
68
- // Core account object
69
- interface Account {
70
- email: string;
71
- name: string;
72
- picture?: string;
73
- subscription: 'free' | 'active' | 'suspended';
74
- created: number; // Unix timestamp
75
- subscribed?: number; // Unix timestamp
76
- suspended?: number; // Unix timestamp
96
+ interface ConfigResponse {
97
+ maxFileSize: number; // Maximum file size in bytes
98
+ maxFilesCount: number; // Maximum files per deployment
99
+ maxTotalSize: number; // Maximum total deployment size
100
+ }
101
+
102
+ interface PlatformConfig {
103
+ apiUrl?: string;
104
+ deployToken?: string;
105
+ apiKey?: string;
77
106
  }
78
107
  ```
79
108
 
80
- ### Platform Configuration
109
+ ### SPA Detection
81
110
 
82
111
  ```typescript
83
- // Dynamic platform configuration from API
84
- interface ConfigResponse {
85
- maxFileSize: number; // Maximum file size in bytes
86
- maxFilesCount: number; // Maximum files per deployment
87
- maxTotalSize: number; // Maximum total deployment size
112
+ interface SPACheckRequest {
113
+ files: string[]; // Array of file paths
114
+ index: string; // Index file path
115
+ }
116
+
117
+ interface SPACheckResponse {
118
+ isSPA: boolean; // Whether it's detected as SPA
119
+ debug: {
120
+ tier: 'exclusions' | 'inclusions' | 'scoring' | 'ai' | 'fallback';
121
+ reason: string;
122
+ };
123
+ }
124
+ ```
125
+
126
+ ## Resource Interface Contracts
127
+
128
+ These interfaces define the contracts that all SDK implementations must follow:
129
+
130
+ ```typescript
131
+ interface DeploymentResource {
132
+ create: (input: DeployInput, options?: any) => Promise<Deployment>;
133
+ list: () => Promise<DeploymentListResponse>;
134
+ remove: (id: string) => Promise<void>;
135
+ get: (id: string) => Promise<Deployment>;
136
+ }
137
+
138
+ interface AliasResource {
139
+ set: (aliasName: string, deployment: string) => Promise<Alias>;
140
+ get: (aliasName: string) => Promise<Alias>;
141
+ list: () => Promise<AliasListResponse>;
142
+ remove: (aliasName: string) => Promise<void>;
143
+ check: (aliasName: string) => Promise<{ message: string }>;
144
+ }
145
+
146
+ interface AccountResource {
147
+ get: () => Promise<Account>;
148
+ }
149
+
150
+ interface KeysResource {
151
+ create: () => Promise<{ apiKey: string }>;
88
152
  }
89
153
  ```
90
154
 
@@ -93,7 +157,6 @@ interface ConfigResponse {
93
157
  ### Unified Error Handling
94
158
 
95
159
  ```typescript
96
- // All possible error types
97
160
  enum ErrorType {
98
161
  Validation = "validation_failed",
99
162
  NotFound = "not_found",
@@ -107,7 +170,6 @@ enum ErrorType {
107
170
  Config = "config_error"
108
171
  }
109
172
 
110
- // Standard error response format
111
173
  interface ErrorResponse {
112
174
  error: ErrorType;
113
175
  message: string;
@@ -115,7 +177,6 @@ interface ErrorResponse {
115
177
  details?: any;
116
178
  }
117
179
 
118
- // Unified error class for both API and SDK
119
180
  class ShipError extends Error {
120
181
  constructor(
121
182
  public readonly type: ErrorType,
@@ -128,72 +189,102 @@ class ShipError extends Error {
128
189
  static validation(message: string, details?: any): ShipError;
129
190
  static notFound(resource: string, id?: string): ShipError;
130
191
  static authentication(message?: string): ShipError;
131
- static client(message: string, details?: any): ShipError;
192
+ static business(message: string, status?: number): ShipError;
193
+ static network(message: string, cause?: Error): ShipError;
194
+ static api(message?: string, status?: number): ShipError;
132
195
 
133
196
  // Helper methods
134
197
  isClientError(): boolean;
135
198
  isNetworkError(): boolean;
136
199
  isAuthError(): boolean;
200
+ toResponse(): ErrorResponse;
137
201
  }
138
202
  ```
139
203
 
140
- ## Platform Configuration
141
-
142
- ### Shared Constants
204
+ ## Platform Constants
143
205
 
144
206
  ```typescript
145
- // Server-side platform configuration
146
- export const serverConfig = {
147
- /** Maximum individual file size in bytes (10MB) */
148
- maxFileSize: 10 * 1024 * 1024,
149
- /** Maximum number of files per deployment */
150
- maxFilesCount: 1000,
151
- /** Maximum total deployment size in bytes (100MB) */
152
- maxTotalSize: 100 * 1024 * 1024,
153
- /** Deployment expiry in hours */
154
- deploymentExpiryHours: 168, // 7 days
155
- /** Pagination limits */
156
- defaultLimit: 50,
157
- maxLimit: 100,
207
+ // API configuration
208
+ const DEFAULT_API = 'https://api.shipstatic.com';
209
+
210
+ // Server configuration limits
211
+ const serverConfig = {
212
+ maxFileSize: 10 * 1024 * 1024, // 10MB
213
+ maxFilesCount: 1000, // Files per deployment
214
+ maxTotalSize: 100 * 1024 * 1024, // 100MB total
215
+ deploymentExpiryHours: 168, // 7 days
216
+ defaultLimit: 50, // Pagination default
217
+ maxLimit: 100, // Pagination maximum
158
218
  } as const;
159
219
 
160
- // Client-side configuration - conservative defaults for SDK/CLI
161
- export const clientConfig = {
162
- /** Conservative file size limit for client validation (5MB) */
163
- maxFileSize: 5 * 1024 * 1024,
164
- /** Conservative file count limit for client validation */
165
- maxFilesCount: 100,
166
- /** Conservative total size limit for client validation (25MB) */
167
- maxTotalSize: 25 * 1024 * 1024,
168
- } as const;
220
+ // API key format validation
221
+ const API_KEY_PREFIX = 'ship-';
222
+ const API_KEY_HEX_LENGTH = 64;
223
+ const API_KEY_TOTAL_LENGTH = 69; // 'ship-' + 64 hex chars
169
224
  ```
170
225
 
171
- ### Dynamic Configuration
226
+ ## Upload Types
227
+
228
+ ```typescript
229
+ enum UploadStatus {
230
+ PENDING = 'pending',
231
+ SUCCESS = 'success',
232
+ FAILED = 'failed',
233
+ DELETING = 'deleting'
234
+ }
172
235
 
173
- The platform provides dynamic configuration through the API's `/config` endpoint:
236
+ interface UploadedFile {
237
+ key: string; // Storage key
238
+ etag: string; // ETag from storage
239
+ size: number; // File size in bytes
240
+ validated?: boolean; // Whether file was validated
241
+ }
174
242
 
175
- ```json
176
- {
177
- "maxFileSize": 10485760, // 10MB
178
- "maxFilesCount": 1000, // Files per deployment
179
- "maxTotalSize": 104857600 // 100MB total
243
+ interface RateLimitData {
244
+ count: number; // Current request count
245
+ timestamp: number; // Window start timestamp
180
246
  }
181
247
  ```
182
248
 
183
- **Benefits:**
184
- - **Single source of truth** - Configuration defined once in `serverConfig`
185
- - **Dynamic updates** - API can adjust limits without code changes
186
- - **SDK synchronization** - SDK automatically fetches current limits
187
- - **Type safety** - Shared `ConfigResponse` interface ensures consistency
249
+ ## Validation Utilities
250
+
251
+ ```typescript
252
+ // Validate API key format
253
+ function validateApiKey(apiKey: string): void;
254
+
255
+ // Validate deploy token format
256
+ function validateDeployToken(deployToken: string): void;
188
257
 
189
- ## Usage
258
+ // Validate API URL format
259
+ function validateApiUrl(apiUrl: string): void;
190
260
 
191
- ### In Ship API
261
+ // Validate deployment subdomain format
262
+ function validateSubdomain(input: string): boolean;
263
+ ```
264
+
265
+ ## URL Generation
192
266
 
193
267
  ```typescript
194
- import { serverConfig, ShipError, type ConfigResponse } from '@shipstatic/types';
268
+ // Generate deployment URL
269
+ function generateDeploymentUrl(deployment: string, sitesDomain?: string): string;
195
270
 
196
- // Use shared configuration constants
271
+ // Generate alias URL (handles both subdomains and custom domains)
272
+ function generateAliasUrl(alias: string, sitesDomain?: string): string;
273
+ ```
274
+
275
+ ## Usage Examples
276
+
277
+ ### In the API
278
+
279
+ ```typescript
280
+ import {
281
+ serverConfig,
282
+ ShipError,
283
+ type ConfigResponse,
284
+ type Deployment
285
+ } from '@shipstatic/types';
286
+
287
+ // Use shared configuration
197
288
  const config: ConfigResponse = {
198
289
  maxFileSize: serverConfig.maxFileSize,
199
290
  maxFilesCount: serverConfig.maxFilesCount,
@@ -201,32 +292,45 @@ const config: ConfigResponse = {
201
292
  };
202
293
 
203
294
  // Use unified error handling
204
- throw ShipError.validation('File too large', { maxSize: serverConfig.maxFileSize });
295
+ throw ShipError.validation('File too large', {
296
+ maxSize: serverConfig.maxFileSize
297
+ });
205
298
  ```
206
299
 
207
- ### In Ship SDK
300
+ ### In the SDK
208
301
 
209
302
  ```typescript
210
- import { ShipError, type ConfigResponse, type DeploySuccessResponse } from '@shipstatic/types';
303
+ import {
304
+ ShipError,
305
+ type ConfigResponse,
306
+ type DeploymentListResponse,
307
+ generateDeploymentUrl
308
+ } from '@shipstatic/types';
211
309
 
212
- // Receive platform configuration
213
- const config: ConfigResponse = await api.getConfig();
310
+ // Handle API responses
311
+ const deployments: DeploymentListResponse = await api.listDeployments();
312
+
313
+ // Generate URLs consistently
314
+ const url = generateDeploymentUrl('happy-cat-abc1234');
214
315
 
215
316
  // Handle errors consistently
216
317
  try {
217
- const result: DeploySuccessResponse = await deploy(files);
318
+ const result = await deploy(files);
218
319
  } catch (error) {
219
- if (error instanceof ShipError) {
220
- // Handle Ship-specific errors
320
+ if (error instanceof ShipError && error.isClientError()) {
321
+ // Handle client errors
221
322
  }
222
323
  }
223
324
  ```
224
325
 
225
326
  ## Installation
226
327
 
227
- This package is automatically installed as a dependency of the Ship SDK and API:
328
+ This package is automatically installed as a dependency:
228
329
 
229
330
  ```bash
331
+ # Included with Ship SDK
332
+ npm install @shipstatic/ship
333
+
230
334
  # Direct installation (if needed)
231
335
  npm install @shipstatic/types
232
336
  ```
@@ -236,40 +340,34 @@ npm install @shipstatic/types
236
340
  ### Design Principles
237
341
 
238
342
  - **Single source of truth** - All types defined once, used everywhere
239
- - **Type safety** - Strict TypeScript with no `any` types
240
- - **Wire format compatibility** - Types match API request/response formats
343
+ - **Type safety** - Strict TypeScript with comprehensive validation
344
+ - **Wire format compatibility** - Types match actual API contracts
241
345
  - **Error consistency** - Unified error handling across all components
242
- - **Configuration sharing** - Shared constants prevent drift
243
-
244
- ### Package Structure
245
-
246
- ```
247
- /types/src/
248
- └── index.ts # All types and exports in single file
249
- ```
346
+ - **Platform contracts** - Resource interfaces define SDK behavior
250
347
 
251
348
  ### Type Organization
252
349
 
253
- All types are organized in a single `index.ts` file by category:
350
+ All types are organized in a single `src/index.ts` file by category:
254
351
 
255
- - **Core entities** - Deployment, Alias, Account objects
256
- - **API responses** - Success/error response wrappers
257
- - **Configuration** - `serverConfig` and `clientConfig` with platform limits
258
- - **Error system** - Unified `ShipError` class with factory methods
259
- - **Common patterns** - Shared response formats and interfaces
352
+ 1. **Core entities** - Deployment, Alias, Account objects
353
+ 2. **API responses** - Response wrappers and pagination
354
+ 3. **Resource contracts** - SDK interface definitions
355
+ 4. **Error system** - Unified ShipError class and error types
356
+ 5. **Platform configuration** - Shared constants and validation
357
+ 6. **Upload types** - File handling and status enums
358
+ 7. **Utility functions** - URL generation and validation
260
359
 
261
360
  ## Philosophy
262
361
 
263
362
  This package follows the **"Impossible Simplicity"** principle:
264
363
 
265
- - **Do more with less** - Maximum type safety with minimal complexity
266
- - **Single source of truth** - Types defined once, used everywhere
267
- - **Wire format compatibility** - Types match actual API contracts
268
- - **Developer experience** - Clear, predictable type interfaces
364
+ - **Clear contracts** - Types define platform behavior
365
+ - **Zero duplication** - Single source prevents drift
366
+ - **Developer experience** - Predictable, well-documented interfaces
269
367
  - **Maintainability** - Easy to update types across entire platform
270
368
 
271
- **Result:** Type-safe development across the entire Ship platform with zero type drift between components.
369
+ The result is type-safe development across the entire Shipstatic platform with guaranteed consistency between API, SDK, and CLI components.
272
370
 
273
371
  ---
274
372
 
275
- **Ship Types** - Shared types for the Ship platform 🚢
373
+ **@shipstatic/types** - The foundation of type safety for Shipstatic 🚢
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
- * @file Shared types for Shipstatic platform
3
- * Simple, clean types that both API and SDK agree on
2
+ * @file Shared TypeScript types, constants, and utilities for the Shipstatic platform.
3
+ * This package is the single source of truth for all shared data structures.
4
4
  */
5
5
  /**
6
6
  * Core deployment object - used in both API responses and SDK
@@ -13,7 +13,7 @@ export interface Deployment {
13
13
  /** Total size of all files in bytes */
14
14
  size: number;
15
15
  /** Current deployment status */
16
- status: 'pending' | 'success' | 'failed';
16
+ status: 'pending' | 'success' | 'failed' | 'deleting';
17
17
  /** Whether deployment has configuration */
18
18
  config?: boolean;
19
19
  /** The deployment URL */
@@ -22,6 +22,8 @@ export interface Deployment {
22
22
  created: number;
23
23
  /** Unix timestamp (seconds) when deployment expires */
24
24
  expires?: number;
25
+ /** Unix timestamp (seconds) when deployment was verified and ready */
26
+ verified?: number;
25
27
  }
26
28
  /**
27
29
  * Response for listing deployments
@@ -150,7 +152,7 @@ export declare class ShipError extends Error {
150
152
  static validation(message: string, details?: any): ShipError;
151
153
  static notFound(resource: string, id?: string): ShipError;
152
154
  static rateLimit(message?: string): ShipError;
153
- static authentication(message?: string): ShipError;
155
+ static authentication(message?: string, details?: any): ShipError;
154
156
  static business(message: string, status?: number): ShipError;
155
157
  static network(message: string, cause?: Error): ShipError;
156
158
  static cancelled(message: string): ShipError;
@@ -243,7 +245,7 @@ export declare function validateSubdomain(input: string): boolean;
243
245
  export interface SPACheckRequest {
244
246
  /** Array of file paths */
245
247
  files: string[];
246
- /** Raw HTML content of index.html file */
248
+ /** HTML content of index.html file */
247
249
  index: string;
248
250
  }
249
251
  /**
@@ -252,4 +254,124 @@ export interface SPACheckRequest {
252
254
  export interface SPACheckResponse {
253
255
  /** Whether the project is detected as a Single Page Application */
254
256
  isSPA: boolean;
257
+ /** Debugging information about detection */
258
+ debug: {
259
+ /** Which tier made the detection: 'exclusions', 'inclusions', 'scoring', 'ai', or 'fallback' */
260
+ tier: 'exclusions' | 'inclusions' | 'scoring' | 'ai' | 'fallback';
261
+ /** The reason for the detection result */
262
+ reason: string;
263
+ };
264
+ }
265
+ /**
266
+ * Represents a file that has been processed and is ready for deploy.
267
+ * Used across the platform (API, SDK, CLI) for file operations.
268
+ */
269
+ export interface StaticFile {
270
+ /**
271
+ * The content of the file.
272
+ * In Node.js, this is typically a `Buffer`.
273
+ * In the browser, this is typically a `File` or `Blob` object.
274
+ */
275
+ content: File | Buffer | Blob;
276
+ /**
277
+ * The desired path for the file on the server, relative to the deployment root.
278
+ * Should include the filename, e.g., `images/photo.jpg`.
279
+ */
280
+ path: string;
281
+ /**
282
+ * The original absolute file system path (primarily used in Node.js environments).
283
+ * This helps in debugging or associating the server path back to its source.
284
+ */
285
+ filePath?: string;
286
+ /**
287
+ * The MD5 hash (checksum) of the file's content.
288
+ * This is calculated by the SDK before deploy if not provided.
289
+ */
290
+ md5?: string;
291
+ /** The size of the file in bytes. */
292
+ size: number;
293
+ }
294
+ /**
295
+ * Standard platform configuration format used by all clients
296
+ */
297
+ export interface PlatformConfig {
298
+ apiUrl?: string;
299
+ deployToken?: string;
300
+ apiKey?: string;
301
+ }
302
+ /** Default API URL if not otherwise configured. */
303
+ export declare const DEFAULT_API = "https://api.shipstatic.com";
304
+ /**
305
+ * Universal deploy input type for all environments.
306
+ * - File[] | FileList: Browser environments (file upload)
307
+ * - string: Node.js environments (file/directory path)
308
+ */
309
+ export type DeployInput = File[] | FileList | string;
310
+ /**
311
+ * Deployment resource interface - the contract all implementations must follow
312
+ */
313
+ export interface DeploymentResource {
314
+ create: (input: DeployInput, options?: any) => Promise<Deployment>;
315
+ list: () => Promise<DeploymentListResponse>;
316
+ remove: (id: string) => Promise<void>;
317
+ get: (id: string) => Promise<Deployment>;
318
+ }
319
+ /**
320
+ * Alias resource interface - the contract all implementations must follow
321
+ */
322
+ export interface AliasResource {
323
+ set: (aliasName: string, deployment: string) => Promise<Alias>;
324
+ get: (aliasName: string) => Promise<Alias>;
325
+ list: () => Promise<AliasListResponse>;
326
+ remove: (aliasName: string) => Promise<void>;
327
+ check: (aliasName: string) => Promise<{
328
+ message: string;
329
+ }>;
330
+ }
331
+ /**
332
+ * Account resource interface - the contract all implementations must follow
333
+ */
334
+ export interface AccountResource {
335
+ get: () => Promise<Account>;
336
+ }
337
+ /**
338
+ * Keys resource interface - the contract all implementations must follow
339
+ */
340
+ export interface KeysResource {
341
+ create: () => Promise<{
342
+ apiKey: string;
343
+ }>;
344
+ }
345
+ /**
346
+ * Represents a file that has been uploaded and stored
347
+ */
348
+ export interface UploadedFile {
349
+ key: string;
350
+ etag: string;
351
+ size: number;
352
+ validated?: boolean;
353
+ }
354
+ /**
355
+ * Upload/deployment status enum
356
+ */
357
+ export declare enum UploadStatus {
358
+ PENDING = "pending",
359
+ SUCCESS = "success",
360
+ FAILED = "failed",
361
+ DELETING = "deleting"
362
+ }
363
+ /**
364
+ * Rate limiting data structure
365
+ */
366
+ export interface RateLimitData {
367
+ count: number;
368
+ timestamp: number;
255
369
  }
370
+ /**
371
+ * Generate deployment URL from deployment ID and sites domain
372
+ */
373
+ export declare function generateDeploymentUrl(deployment: string, sitesDomain?: string): string;
374
+ /**
375
+ * Generate alias URL based on whether it's internal (subdomain) or external (custom domain)
376
+ */
377
+ export declare function generateAliasUrl(alias: string, sitesDomain?: string): string;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
- * @file Shared types for Shipstatic platform
3
- * Simple, clean types that both API and SDK agree on
2
+ * @file Shared TypeScript types, constants, and utilities for the Shipstatic platform.
3
+ * This package is the single source of truth for all shared data structures.
4
4
  */
5
5
  // =============================================================================
6
6
  // ERROR SYSTEM
@@ -58,11 +58,15 @@ export class ShipError extends Error {
58
58
  }
59
59
  /** Convert to wire format */
60
60
  toResponse() {
61
+ // For security, exclude internal details from authentication errors in API responses
62
+ const details = this.type === ErrorType.Authentication && this.details?.internal
63
+ ? undefined
64
+ : this.details;
61
65
  return {
62
66
  error: this.type,
63
67
  message: this.message,
64
68
  status: this.status,
65
- details: this.details
69
+ details
66
70
  };
67
71
  }
68
72
  /** Create from wire format */
@@ -80,8 +84,8 @@ export class ShipError extends Error {
80
84
  static rateLimit(message = "Too many requests") {
81
85
  return new ShipError(ErrorType.RateLimit, message, 429);
82
86
  }
83
- static authentication(message = "Authentication required") {
84
- return new ShipError(ErrorType.Authentication, message, 401);
87
+ static authentication(message = "Authentication required", details) {
88
+ return new ShipError(ErrorType.Authentication, message, 401, details);
85
89
  }
86
90
  static business(message, status = 400) {
87
91
  return new ShipError(ErrorType.Business, message, status);
@@ -230,3 +234,40 @@ export function validateSubdomain(input) {
230
234
  // Deployment subdomain format: word-word-7chars (e.g. "happy-cat-abc1234")
231
235
  return /^[a-z]+-[a-z]+-[a-z0-9]{7}$/i.test(input);
232
236
  }
237
+ // =============================================================================
238
+ // PLATFORM CONSTANTS
239
+ // =============================================================================
240
+ /** Default API URL if not otherwise configured. */
241
+ export const DEFAULT_API = 'https://api.shipstatic.com';
242
+ /**
243
+ * Upload/deployment status enum
244
+ */
245
+ export var UploadStatus;
246
+ (function (UploadStatus) {
247
+ UploadStatus["PENDING"] = "pending";
248
+ UploadStatus["SUCCESS"] = "success";
249
+ UploadStatus["FAILED"] = "failed";
250
+ UploadStatus["DELETING"] = "deleting";
251
+ })(UploadStatus || (UploadStatus = {}));
252
+ // =============================================================================
253
+ // URL GENERATION UTILITIES
254
+ // =============================================================================
255
+ /**
256
+ * Generate deployment URL from deployment ID and sites domain
257
+ */
258
+ export function generateDeploymentUrl(deployment, sitesDomain) {
259
+ const domain = sitesDomain || 'statichost.com';
260
+ return `https://${deployment}.${domain}`;
261
+ }
262
+ /**
263
+ * Generate alias URL based on whether it's internal (subdomain) or external (custom domain)
264
+ */
265
+ export function generateAliasUrl(alias, sitesDomain) {
266
+ // If alias contains dots, it's an external domain
267
+ if (alias.includes('.')) {
268
+ return `https://${alias}`;
269
+ }
270
+ // Otherwise it's an internal subdomain
271
+ const domain = sitesDomain || 'statichost.dev';
272
+ return `https://${alias}.${domain}`;
273
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shipstatic/types",
3
- "version": "0.1.14",
3
+ "version": "0.2.1",
4
4
  "description": "Shared types for Shipstatic platform",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -33,6 +33,7 @@
33
33
  "node": ">=20.0.0"
34
34
  },
35
35
  "devDependencies": {
36
+ "@types/node": "^24.3.0",
36
37
  "typescript": "^5.8.3"
37
38
  },
38
39
  "scripts": {
package/src/index.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  /**
2
- * @file Shared types for Shipstatic platform
3
- * Simple, clean types that both API and SDK agree on
2
+ * @file Shared TypeScript types, constants, and utilities for the Shipstatic platform.
3
+ * This package is the single source of truth for all shared data structures.
4
4
  */
5
5
 
6
6
  // =============================================================================
7
- // DEPLOYMENT TYPES
7
+ // I. CORE ENTITIES
8
8
  // =============================================================================
9
9
 
10
10
  /**
@@ -18,7 +18,7 @@ export interface Deployment {
18
18
  /** Total size of all files in bytes */
19
19
  size: number;
20
20
  /** Current deployment status */
21
- status: 'pending' | 'success' | 'failed';
21
+ status: 'pending' | 'success' | 'failed' | 'deleting';
22
22
  /** Whether deployment has configuration */
23
23
  config?: boolean;
24
24
  /** The deployment URL */
@@ -27,6 +27,8 @@ export interface Deployment {
27
27
  created: number;
28
28
  /** Unix timestamp (seconds) when deployment expires */
29
29
  expires?: number;
30
+ /** Unix timestamp (seconds) when deployment was verified and ready */
31
+ verified?: number;
30
32
  }
31
33
 
32
34
 
@@ -187,11 +189,16 @@ export class ShipError extends Error {
187
189
 
188
190
  /** Convert to wire format */
189
191
  toResponse(): ErrorResponse {
192
+ // For security, exclude internal details from authentication errors in API responses
193
+ const details = this.type === ErrorType.Authentication && this.details?.internal
194
+ ? undefined
195
+ : this.details;
196
+
190
197
  return {
191
198
  error: this.type,
192
199
  message: this.message,
193
200
  status: this.status,
194
- details: this.details
201
+ details
195
202
  };
196
203
  }
197
204
 
@@ -214,8 +221,8 @@ export class ShipError extends Error {
214
221
  return new ShipError(ErrorType.RateLimit, message, 429);
215
222
  }
216
223
 
217
- static authentication(message: string = "Authentication required"): ShipError {
218
- return new ShipError(ErrorType.Authentication, message, 401);
224
+ static authentication(message: string = "Authentication required", details?: any): ShipError {
225
+ return new ShipError(ErrorType.Authentication, message, 401, details);
219
226
  }
220
227
 
221
228
 
@@ -452,7 +459,7 @@ export function validateSubdomain(input: string): boolean {
452
459
  export interface SPACheckRequest {
453
460
  /** Array of file paths */
454
461
  files: string[];
455
- /** Raw HTML content of index.html file */
462
+ /** HTML content of index.html file */
456
463
  index: string;
457
464
  }
458
465
 
@@ -462,4 +469,169 @@ export interface SPACheckRequest {
462
469
  export interface SPACheckResponse {
463
470
  /** Whether the project is detected as a Single Page Application */
464
471
  isSPA: boolean;
472
+ /** Debugging information about detection */
473
+ debug: {
474
+ /** Which tier made the detection: 'exclusions', 'inclusions', 'scoring', 'ai', or 'fallback' */
475
+ tier: 'exclusions' | 'inclusions' | 'scoring' | 'ai' | 'fallback';
476
+ /** The reason for the detection result */
477
+ reason: string;
478
+ };
479
+ }
480
+
481
+ // =============================================================================
482
+ // STATIC FILE REPRESENTATION
483
+ // =============================================================================
484
+
485
+ /**
486
+ * Represents a file that has been processed and is ready for deploy.
487
+ * Used across the platform (API, SDK, CLI) for file operations.
488
+ */
489
+ export interface StaticFile {
490
+ /**
491
+ * The content of the file.
492
+ * In Node.js, this is typically a `Buffer`.
493
+ * In the browser, this is typically a `File` or `Blob` object.
494
+ */
495
+ content: File | Buffer | Blob;
496
+ /**
497
+ * The desired path for the file on the server, relative to the deployment root.
498
+ * Should include the filename, e.g., `images/photo.jpg`.
499
+ */
500
+ path: string;
501
+ /**
502
+ * The original absolute file system path (primarily used in Node.js environments).
503
+ * This helps in debugging or associating the server path back to its source.
504
+ */
505
+ filePath?: string;
506
+ /**
507
+ * The MD5 hash (checksum) of the file's content.
508
+ * This is calculated by the SDK before deploy if not provided.
509
+ */
510
+ md5?: string;
511
+ /** The size of the file in bytes. */
512
+ size: number;
513
+ }
514
+
515
+ // =============================================================================
516
+ // PLATFORM CONFIGURATION
517
+ // =============================================================================
518
+
519
+ /**
520
+ * Standard platform configuration format used by all clients
521
+ */
522
+ export interface PlatformConfig {
523
+ apiUrl?: string;
524
+ deployToken?: string;
525
+ apiKey?: string;
526
+ }
527
+
528
+ // =============================================================================
529
+ // PLATFORM CONSTANTS
530
+ // =============================================================================
531
+
532
+ /** Default API URL if not otherwise configured. */
533
+ export const DEFAULT_API = 'https://api.shipstatic.com';
534
+
535
+ // =============================================================================
536
+ // RESOURCE INTERFACE CONTRACTS
537
+ // =============================================================================
538
+
539
+ /**
540
+ * Universal deploy input type for all environments.
541
+ * - File[] | FileList: Browser environments (file upload)
542
+ * - string: Node.js environments (file/directory path)
543
+ */
544
+ export type DeployInput = File[] | FileList | string;
545
+
546
+ /**
547
+ * Deployment resource interface - the contract all implementations must follow
548
+ */
549
+ export interface DeploymentResource {
550
+ create: (input: DeployInput, options?: any) => Promise<Deployment>;
551
+ list: () => Promise<DeploymentListResponse>;
552
+ remove: (id: string) => Promise<void>;
553
+ get: (id: string) => Promise<Deployment>;
554
+ }
555
+
556
+ /**
557
+ * Alias resource interface - the contract all implementations must follow
558
+ */
559
+ export interface AliasResource {
560
+ set: (aliasName: string, deployment: string) => Promise<Alias>;
561
+ get: (aliasName: string) => Promise<Alias>;
562
+ list: () => Promise<AliasListResponse>;
563
+ remove: (aliasName: string) => Promise<void>;
564
+ check: (aliasName: string) => Promise<{ message: string }>;
565
+ }
566
+
567
+ /**
568
+ * Account resource interface - the contract all implementations must follow
569
+ */
570
+ export interface AccountResource {
571
+ get: () => Promise<Account>;
572
+ }
573
+
574
+ /**
575
+ * Keys resource interface - the contract all implementations must follow
576
+ */
577
+ export interface KeysResource {
578
+ create: () => Promise<{ apiKey: string }>;
579
+ }
580
+
581
+ // =============================================================================
582
+ // FILE UPLOAD TYPES
583
+ // =============================================================================
584
+
585
+ /**
586
+ * Represents a file that has been uploaded and stored
587
+ */
588
+ export interface UploadedFile {
589
+ key: string;
590
+ etag: string;
591
+ size: number;
592
+ validated?: boolean;
593
+ }
594
+
595
+ /**
596
+ * Upload/deployment status enum
597
+ */
598
+ export enum UploadStatus {
599
+ PENDING = 'pending',
600
+ SUCCESS = 'success',
601
+ FAILED = 'failed',
602
+ DELETING = 'deleting'
603
+ }
604
+
605
+ /**
606
+ * Rate limiting data structure
607
+ */
608
+ export interface RateLimitData {
609
+ count: number;
610
+ timestamp: number;
611
+ }
612
+
613
+ // =============================================================================
614
+ // URL GENERATION UTILITIES
615
+ // =============================================================================
616
+
617
+ /**
618
+ * Generate deployment URL from deployment ID and sites domain
619
+ */
620
+ export function generateDeploymentUrl(deployment: string, sitesDomain?: string): string {
621
+ const domain = sitesDomain || 'statichost.com';
622
+ return `https://${deployment}.${domain}`;
623
+ }
624
+
625
+ /**
626
+ * Generate alias URL based on whether it's internal (subdomain) or external (custom domain)
627
+ */
628
+ export function generateAliasUrl(alias: string, sitesDomain?: string): string {
629
+ // If alias contains dots, it's an external domain
630
+ if (alias.includes('.')) {
631
+ return `https://${alias}`;
632
+ }
633
+
634
+ // Otherwise it's an internal subdomain
635
+ const domain = sitesDomain || 'statichost.dev';
636
+ return `https://${alias}.${domain}`;
465
637
  }