@shipstatic/types 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 shipstatic
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,275 @@
1
+ # Shipstatic Types
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.
4
+
5
+ ## Overview
6
+
7
+ This package contains all shared types used between:
8
+ - **Shipstatic API** (`/cloudflare/api`) - Backend API on Cloudflare Workers
9
+ - **Shipstatic SDK** (`/ship`) - Universal SDK for Node.js and Browser
10
+ - **Shipstatic CLI** - Command-line interface
11
+
12
+ ## Core Types
13
+
14
+ ### Deployment Types
15
+
16
+ ```typescript
17
+ // Core deployment object
18
+ interface Deployment {
19
+ deployment: string; // Deployment ID
20
+ filesCount: number; // Number of files
21
+ totalSize: number; // Total size in bytes
22
+ status: 'pending' | 'success' | 'failed';
23
+ createdAt: number; // Unix timestamp
24
+ expiresAt?: number; // Unix timestamp
25
+ verifiedAt?: number; // Unix timestamp
26
+ }
27
+
28
+ // Successful deployment response
29
+ interface DeploySuccessResponse {
30
+ success: true;
31
+ deployment: string;
32
+ expiresAt: number;
33
+ filesCount: number;
34
+ totalSize: number;
35
+ }
36
+
37
+ // Deployment list response
38
+ interface DeploymentListResponse {
39
+ deployments: Deployment[];
40
+ cursor?: string;
41
+ total?: number;
42
+ }
43
+ ```
44
+
45
+ ### Alias Types
46
+
47
+ ```typescript
48
+ // Core alias object
49
+ interface Alias {
50
+ alias: string; // Alias name
51
+ deploymentName: string; // Target deployment name
52
+ status: 'pending' | 'success' | 'failed';
53
+ createdAt: number; // Unix timestamp
54
+ confirmedAt?: number; // Unix timestamp
55
+ }
56
+
57
+ // Alias list response
58
+ interface AliasListResponse {
59
+ aliases: Alias[];
60
+ cursor?: string;
61
+ total?: number;
62
+ }
63
+ ```
64
+
65
+ ### Account Types
66
+
67
+ ```typescript
68
+ // Core account object
69
+ interface Account {
70
+ email: string;
71
+ name: string;
72
+ picture?: string;
73
+ subscription: 'free' | 'active' | 'suspended';
74
+ createdAt: number; // Unix timestamp
75
+ subscribedAt?: number; // Unix timestamp
76
+ suspendedAt?: number; // Unix timestamp
77
+ }
78
+ ```
79
+
80
+ ### Platform Configuration
81
+
82
+ ```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
88
+ }
89
+ ```
90
+
91
+ ## Error System
92
+
93
+ ### Unified Error Handling
94
+
95
+ ```typescript
96
+ // All possible error types
97
+ enum ErrorType {
98
+ Validation = "validation_failed",
99
+ NotFound = "not_found",
100
+ RateLimit = "rate_limit_exceeded",
101
+ Authentication = "authentication_failed",
102
+ Business = "business_logic_error",
103
+ Api = "internal_server_error",
104
+ Network = "network_error",
105
+ Cancelled = "operation_cancelled",
106
+ File = "file_error",
107
+ Config = "config_error"
108
+ }
109
+
110
+ // Standard error response format
111
+ interface ErrorResponse {
112
+ error: ErrorType;
113
+ message: string;
114
+ status?: number;
115
+ details?: any;
116
+ }
117
+
118
+ // Unified error class for both API and SDK
119
+ class ShipError extends Error {
120
+ constructor(
121
+ public readonly type: ErrorType,
122
+ message: string,
123
+ public readonly status?: number,
124
+ public readonly details?: any
125
+ );
126
+
127
+ // Factory methods
128
+ static validation(message: string, details?: any): ShipError;
129
+ static notFound(resource: string, id?: string): ShipError;
130
+ static authentication(message?: string): ShipError;
131
+ static client(message: string, details?: any): ShipError;
132
+
133
+ // Helper methods
134
+ isClientError(): boolean;
135
+ isNetworkError(): boolean;
136
+ isAuthError(): boolean;
137
+ }
138
+ ```
139
+
140
+ ## Platform Configuration
141
+
142
+ ### Shared Constants
143
+
144
+ ```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,
158
+ } as const;
159
+
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;
169
+ ```
170
+
171
+ ### Dynamic Configuration
172
+
173
+ The platform provides dynamic configuration through the API's `/config` endpoint:
174
+
175
+ ```json
176
+ {
177
+ "maxFileSize": 10485760, // 10MB
178
+ "maxFilesCount": 1000, // Files per deployment
179
+ "maxTotalSize": 104857600 // 100MB total
180
+ }
181
+ ```
182
+
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
188
+
189
+ ## Usage
190
+
191
+ ### In Ship API
192
+
193
+ ```typescript
194
+ import { serverConfig, ShipError, type ConfigResponse } from '@shipstatic/types';
195
+
196
+ // Use shared configuration constants
197
+ const config: ConfigResponse = {
198
+ maxFileSize: serverConfig.maxFileSize,
199
+ maxFilesCount: serverConfig.maxFilesCount,
200
+ maxTotalSize: serverConfig.maxTotalSize,
201
+ };
202
+
203
+ // Use unified error handling
204
+ throw ShipError.validation('File too large', { maxSize: serverConfig.maxFileSize });
205
+ ```
206
+
207
+ ### In Ship SDK
208
+
209
+ ```typescript
210
+ import { ShipError, type ConfigResponse, type DeploySuccessResponse } from '@shipstatic/types';
211
+
212
+ // Receive platform configuration
213
+ const config: ConfigResponse = await api.getConfig();
214
+
215
+ // Handle errors consistently
216
+ try {
217
+ const result: DeploySuccessResponse = await deploy(files);
218
+ } catch (error) {
219
+ if (error instanceof ShipError) {
220
+ // Handle Ship-specific errors
221
+ }
222
+ }
223
+ ```
224
+
225
+ ## Installation
226
+
227
+ This package is automatically installed as a dependency of the Ship SDK and API:
228
+
229
+ ```bash
230
+ # Direct installation (if needed)
231
+ npm install @shipstatic/types
232
+ ```
233
+
234
+ ## Architecture
235
+
236
+ ### Design Principles
237
+
238
+ - **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
241
+ - **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
+ ```
250
+
251
+ ### Type Organization
252
+
253
+ All types are organized in a single `index.ts` file by category:
254
+
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
260
+
261
+ ## Philosophy
262
+
263
+ This package follows the **"Impossible Simplicity"** principle:
264
+
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
269
+ - **Maintainability** - Easy to update types across entire platform
270
+
271
+ **Result:** Type-safe development across the entire Ship platform with zero type drift between components.
272
+
273
+ ---
274
+
275
+ **Ship Types** - Shared types for the Ship platform 🚢
@@ -0,0 +1,209 @@
1
+ /**
2
+ * @file Shared types for Shipstatic platform
3
+ * Simple, clean types that both API and SDK agree on
4
+ */
5
+ /**
6
+ * Core deployment object - used in both API responses and SDK
7
+ */
8
+ export interface Deployment {
9
+ /** The deployment ID */
10
+ deployment: string;
11
+ /** Number of files in this deployment */
12
+ filesCount: number;
13
+ /** Total size of all files in bytes */
14
+ totalSize: number;
15
+ /** Current deployment status */
16
+ status: 'pending' | 'success' | 'failed';
17
+ /** Unix timestamp (seconds) when deployment was created */
18
+ createdAt: number;
19
+ /** Unix timestamp (seconds) when deployment expires */
20
+ expiresAt?: number;
21
+ /** Unix timestamp (seconds) when deployment was verified */
22
+ verifiedAt?: number;
23
+ }
24
+ /**
25
+ * Response for listing deployments
26
+ */
27
+ export interface DeploymentListResponse {
28
+ /** Array of deployments */
29
+ deployments: Deployment[];
30
+ /** Optional cursor for pagination */
31
+ cursor?: string;
32
+ /** Total number of deployments if available */
33
+ total?: number;
34
+ }
35
+ /**
36
+ * Core alias object - used in both API responses and SDK
37
+ */
38
+ export interface Alias {
39
+ /** The alias name */
40
+ alias: string;
41
+ /** The deployment name this alias points to */
42
+ deploymentName: string;
43
+ /** Current alias status */
44
+ status: 'pending' | 'success' | 'failed';
45
+ /** Unix timestamp (seconds) when alias was created */
46
+ createdAt: number;
47
+ /** Unix timestamp (seconds) when alias was confirmed */
48
+ confirmedAt?: number;
49
+ }
50
+ /**
51
+ * Response for listing aliases
52
+ */
53
+ export interface AliasListResponse {
54
+ /** Array of aliases */
55
+ aliases: Alias[];
56
+ /** Optional cursor for pagination */
57
+ cursor?: string;
58
+ /** Total number of aliases if available */
59
+ total?: number;
60
+ }
61
+ /**
62
+ * Response for deployment removal
63
+ */
64
+ export interface DeploymentRemoveResponse {
65
+ /** Operation success status */
66
+ success: boolean;
67
+ /** The deployment ID */
68
+ deployment: string;
69
+ /** Human-readable message */
70
+ message?: string;
71
+ }
72
+ /**
73
+ * Core account object - used in both API responses and SDK
74
+ */
75
+ export interface Account {
76
+ /** User email address */
77
+ email: string;
78
+ /** User display name */
79
+ name: string;
80
+ /** User profile picture URL */
81
+ picture?: string;
82
+ /** Account subscription status */
83
+ subscription: 'free' | 'active' | 'suspended';
84
+ /** Unix timestamp (seconds) when account was created */
85
+ createdAt: number;
86
+ /** Unix timestamp (seconds) when subscription started */
87
+ subscribedAt?: number;
88
+ /** Unix timestamp (seconds) when account was suspended */
89
+ suspendedAt?: number;
90
+ }
91
+ /**
92
+ * All possible error types in the Shipstatic platform
93
+ * Names are developer-friendly while wire format stays consistent
94
+ */
95
+ export declare enum ErrorType {
96
+ /** Validation failed (400) */
97
+ Validation = "validation_failed",
98
+ /** Resource not found (404) */
99
+ NotFound = "not_found",
100
+ /** Rate limit exceeded (429) */
101
+ RateLimit = "rate_limit_exceeded",
102
+ /** Authentication required (401) */
103
+ Authentication = "authentication_failed",
104
+ /** Business logic error (400) */
105
+ Business = "business_logic_error",
106
+ /** API server error (500) - renamed from Internal for clarity */
107
+ Api = "internal_server_error",
108
+ /** Network/connection error */
109
+ Network = "network_error",
110
+ /** Operation was cancelled */
111
+ Cancelled = "operation_cancelled",
112
+ /** File operation error */
113
+ File = "file_error",
114
+ /** Configuration error */
115
+ Config = "config_error"
116
+ }
117
+ /** @deprecated Use ErrorType instead. Kept for backward compatibility. */
118
+ export declare const ShipErrorType: typeof ErrorType;
119
+ /**
120
+ * Standard error response format used everywhere
121
+ */
122
+ export interface ErrorResponse {
123
+ /** Error type identifier */
124
+ error: ErrorType;
125
+ /** Human-readable error message */
126
+ message: string;
127
+ /** HTTP status code (API contexts) */
128
+ status?: number;
129
+ /** Optional additional error details */
130
+ details?: any;
131
+ }
132
+ /**
133
+ * Simple unified error class for both API and SDK
134
+ */
135
+ export declare class ShipError extends Error {
136
+ readonly type: ErrorType;
137
+ readonly status?: number | undefined;
138
+ readonly details?: any | undefined;
139
+ constructor(type: ErrorType, message: string, status?: number | undefined, details?: any | undefined);
140
+ /** Convert to wire format */
141
+ toResponse(): ErrorResponse;
142
+ /** Create from wire format */
143
+ static fromResponse(response: ErrorResponse): ShipError;
144
+ static validation(message: string, details?: any): ShipError;
145
+ static notFound(resource: string, id?: string): ShipError;
146
+ static rateLimit(message?: string): ShipError;
147
+ static authentication(message?: string): ShipError;
148
+ static business(message: string, status?: number): ShipError;
149
+ static network(message: string, cause?: Error): ShipError;
150
+ static cancelled(message: string): ShipError;
151
+ static file(message: string, filePath?: string): ShipError;
152
+ static config(message: string, details?: any): ShipError;
153
+ static api(message: string, status?: number, code?: string, data?: any): ShipError;
154
+ get filePath(): string | undefined;
155
+ get code(): string | undefined;
156
+ isClientError(): boolean;
157
+ isNetworkError(): boolean;
158
+ isAuthError(): boolean;
159
+ isValidationError(): boolean;
160
+ isFileError(): boolean;
161
+ isConfigError(): boolean;
162
+ isType(errorType: ErrorType): boolean;
163
+ }
164
+ /**
165
+ * Server-side platform configuration - enforced limits on the platform
166
+ */
167
+ export declare const serverConfig: {
168
+ /** Maximum individual file size in bytes (10MB) */
169
+ readonly maxFileSize: number;
170
+ /** Maximum number of files per deployment */
171
+ readonly maxFilesCount: 1000;
172
+ /** Maximum total deployment size in bytes (100MB) */
173
+ readonly maxTotalSize: number;
174
+ /** Deployment expiry in hours */
175
+ readonly deploymentExpiryHours: 168;
176
+ /** Pagination limits */
177
+ readonly defaultLimit: 50;
178
+ readonly maxLimit: 100;
179
+ };
180
+ /**
181
+ * Platform configuration response from API
182
+ */
183
+ export interface ConfigResponse {
184
+ /** Maximum individual file size in bytes */
185
+ maxFileSize: number;
186
+ /** Maximum number of files per deployment */
187
+ maxFilesCount: number;
188
+ /** Maximum total deployment size in bytes */
189
+ maxTotalSize: number;
190
+ }
191
+ /**
192
+ * Generic success response wrapper
193
+ */
194
+ export interface SuccessResponse<T = any> {
195
+ /** Always true for success */
196
+ success: true;
197
+ /** Response data */
198
+ data: T;
199
+ }
200
+ /**
201
+ * Simple ping response for health checks
202
+ */
203
+ export interface PingResponse {
204
+ /** Always true if service is healthy */
205
+ success: boolean;
206
+ /** Optional timestamp */
207
+ timestamp?: number;
208
+ }
209
+ export declare const API_KEY_PREFIX = "ship-";
package/dist/index.js ADDED
@@ -0,0 +1,152 @@
1
+ /// <reference types="@cloudflare/workers-types" />
2
+ // =============================================================================
3
+ // ERROR SYSTEM
4
+ // =============================================================================
5
+ /**
6
+ * All possible error types in the Shipstatic platform
7
+ * Names are developer-friendly while wire format stays consistent
8
+ */
9
+ export var ErrorType;
10
+ (function (ErrorType) {
11
+ /** Validation failed (400) */
12
+ ErrorType["Validation"] = "validation_failed";
13
+ /** Resource not found (404) */
14
+ ErrorType["NotFound"] = "not_found";
15
+ /** Rate limit exceeded (429) */
16
+ ErrorType["RateLimit"] = "rate_limit_exceeded";
17
+ /** Authentication required (401) */
18
+ ErrorType["Authentication"] = "authentication_failed";
19
+ /** Business logic error (400) */
20
+ ErrorType["Business"] = "business_logic_error";
21
+ /** API server error (500) - renamed from Internal for clarity */
22
+ ErrorType["Api"] = "internal_server_error";
23
+ /** Network/connection error */
24
+ ErrorType["Network"] = "network_error";
25
+ /** Operation was cancelled */
26
+ ErrorType["Cancelled"] = "operation_cancelled";
27
+ /** File operation error */
28
+ ErrorType["File"] = "file_error";
29
+ /** Configuration error */
30
+ ErrorType["Config"] = "config_error";
31
+ })(ErrorType || (ErrorType = {}));
32
+ /** @deprecated Use ErrorType instead. Kept for backward compatibility. */
33
+ export const ShipErrorType = ErrorType;
34
+ /**
35
+ * Categorizes error types for better type checking
36
+ */
37
+ const ERROR_CATEGORIES = {
38
+ client: new Set([ErrorType.Business, ErrorType.Config, ErrorType.File, ErrorType.Validation]),
39
+ network: new Set([ErrorType.Network]),
40
+ auth: new Set([ErrorType.Authentication]),
41
+ };
42
+ /**
43
+ * Simple unified error class for both API and SDK
44
+ */
45
+ export class ShipError extends Error {
46
+ type;
47
+ status;
48
+ details;
49
+ constructor(type, message, status, details) {
50
+ super(message);
51
+ this.type = type;
52
+ this.status = status;
53
+ this.details = details;
54
+ this.name = 'ShipError';
55
+ }
56
+ /** Convert to wire format */
57
+ toResponse() {
58
+ return {
59
+ error: this.type,
60
+ message: this.message,
61
+ status: this.status,
62
+ details: this.details
63
+ };
64
+ }
65
+ /** Create from wire format */
66
+ static fromResponse(response) {
67
+ return new ShipError(response.error, response.message, response.status, response.details);
68
+ }
69
+ // Factory methods for common errors
70
+ static validation(message, details) {
71
+ return new ShipError(ErrorType.Validation, message, 400, details);
72
+ }
73
+ static notFound(resource, id) {
74
+ const message = id ? `${resource} ${id} not found` : `${resource} not found`;
75
+ return new ShipError(ErrorType.NotFound, message, 404);
76
+ }
77
+ static rateLimit(message = "Too many requests") {
78
+ return new ShipError(ErrorType.RateLimit, message, 429);
79
+ }
80
+ static authentication(message = "Authentication required") {
81
+ return new ShipError(ErrorType.Authentication, message, 401);
82
+ }
83
+ static business(message, status = 400) {
84
+ return new ShipError(ErrorType.Business, message, status);
85
+ }
86
+ static network(message, cause) {
87
+ return new ShipError(ErrorType.Network, message, undefined, { cause });
88
+ }
89
+ static cancelled(message) {
90
+ return new ShipError(ErrorType.Cancelled, message);
91
+ }
92
+ static file(message, filePath) {
93
+ return new ShipError(ErrorType.File, message, undefined, { filePath });
94
+ }
95
+ static config(message, details) {
96
+ return new ShipError(ErrorType.Config, message, undefined, details);
97
+ }
98
+ static api(message, status = 500, code, data) {
99
+ return new ShipError(ErrorType.Api, message, status, { code, data });
100
+ }
101
+ // Helper getters for accessing common detail properties
102
+ get filePath() {
103
+ return this.details?.filePath;
104
+ }
105
+ get code() {
106
+ return this.details?.code;
107
+ }
108
+ // Helper methods for error type checking using categorization
109
+ isClientError() {
110
+ return ERROR_CATEGORIES.client.has(this.type);
111
+ }
112
+ isNetworkError() {
113
+ return ERROR_CATEGORIES.network.has(this.type);
114
+ }
115
+ isAuthError() {
116
+ return ERROR_CATEGORIES.auth.has(this.type);
117
+ }
118
+ isValidationError() {
119
+ return this.type === ErrorType.Validation;
120
+ }
121
+ isFileError() {
122
+ return this.type === ErrorType.File;
123
+ }
124
+ isConfigError() {
125
+ return this.type === ErrorType.Config;
126
+ }
127
+ // Generic type checker
128
+ isType(errorType) {
129
+ return this.type === errorType;
130
+ }
131
+ }
132
+ // =============================================================================
133
+ // CONFIGURATION CONSTANTS
134
+ // =============================================================================
135
+ /**
136
+ * Server-side platform configuration - enforced limits on the platform
137
+ */
138
+ export const serverConfig = {
139
+ /** Maximum individual file size in bytes (10MB) */
140
+ maxFileSize: 10 * 1024 * 1024,
141
+ /** Maximum number of files per deployment */
142
+ maxFilesCount: 1000,
143
+ /** Maximum total deployment size in bytes (100MB) */
144
+ maxTotalSize: 100 * 1024 * 1024,
145
+ /** Deployment expiry in hours */
146
+ deploymentExpiryHours: 168, // 7 days
147
+ /** Pagination limits */
148
+ defaultLimit: 50,
149
+ maxLimit: 100,
150
+ };
151
+ // API Key Configuration
152
+ export const API_KEY_PREFIX = 'ship-';
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@shipstatic/types",
3
+ "version": "0.1.0",
4
+ "description": "Shared types for Shipstatic platform",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "src"
17
+ ],
18
+ "keywords": [
19
+ "types",
20
+ "shipstatic"
21
+ ],
22
+ "author": "ShipStatic",
23
+ "license": "MIT",
24
+ "devDependencies": {
25
+ "typescript": "^5.8.3",
26
+ "@cloudflare/workers-types": "^4.20241218.0"
27
+ },
28
+ "scripts": {
29
+ "build": "tsc",
30
+ "clean": "rm -rf dist"
31
+ }
32
+ }
package/src/index.ts ADDED
@@ -0,0 +1,347 @@
1
+ /// <reference types="@cloudflare/workers-types" />
2
+
3
+ /**
4
+ * @file Shared types for Shipstatic platform
5
+ * Simple, clean types that both API and SDK agree on
6
+ */
7
+
8
+ // =============================================================================
9
+ // DEPLOYMENT TYPES
10
+ // =============================================================================
11
+
12
+ /**
13
+ * Core deployment object - used in both API responses and SDK
14
+ */
15
+ export interface Deployment {
16
+ /** The deployment ID */
17
+ deployment: string;
18
+ /** Number of files in this deployment */
19
+ filesCount: number;
20
+ /** Total size of all files in bytes */
21
+ totalSize: number;
22
+ /** Current deployment status */
23
+ status: 'pending' | 'success' | 'failed';
24
+ /** Unix timestamp (seconds) when deployment was created */
25
+ createdAt: number;
26
+ /** Unix timestamp (seconds) when deployment expires */
27
+ expiresAt?: number;
28
+ /** Unix timestamp (seconds) when deployment was verified */
29
+ verifiedAt?: number;
30
+ }
31
+
32
+
33
+ /**
34
+ * Response for listing deployments
35
+ */
36
+ export interface DeploymentListResponse {
37
+ /** Array of deployments */
38
+ deployments: Deployment[];
39
+ /** Optional cursor for pagination */
40
+ cursor?: string;
41
+ /** Total number of deployments if available */
42
+ total?: number;
43
+ }
44
+
45
+ // =============================================================================
46
+ // ALIAS TYPES
47
+ // =============================================================================
48
+
49
+ /**
50
+ * Core alias object - used in both API responses and SDK
51
+ */
52
+ export interface Alias {
53
+ /** The alias name */
54
+ alias: string;
55
+ /** The deployment name this alias points to */
56
+ deploymentName: string;
57
+ /** Current alias status */
58
+ status: 'pending' | 'success' | 'failed';
59
+ /** Unix timestamp (seconds) when alias was created */
60
+ createdAt: number;
61
+ /** Unix timestamp (seconds) when alias was confirmed */
62
+ confirmedAt?: number;
63
+ }
64
+
65
+ /**
66
+ * Response for listing aliases
67
+ */
68
+ export interface AliasListResponse {
69
+ /** Array of aliases */
70
+ aliases: Alias[];
71
+ /** Optional cursor for pagination */
72
+ cursor?: string;
73
+ /** Total number of aliases if available */
74
+ total?: number;
75
+ }
76
+
77
+ /**
78
+ * Response for deployment removal
79
+ */
80
+ export interface DeploymentRemoveResponse {
81
+ /** Operation success status */
82
+ success: boolean;
83
+ /** The deployment ID */
84
+ deployment: string;
85
+ /** Human-readable message */
86
+ message?: string;
87
+ }
88
+
89
+ // =============================================================================
90
+ // ACCOUNT TYPES
91
+ // =============================================================================
92
+
93
+ /**
94
+ * Core account object - used in both API responses and SDK
95
+ */
96
+ export interface Account {
97
+ /** User email address */
98
+ email: string;
99
+ /** User display name */
100
+ name: string;
101
+ /** User profile picture URL */
102
+ picture?: string;
103
+ /** Account subscription status */
104
+ subscription: 'free' | 'active' | 'suspended';
105
+ /** Unix timestamp (seconds) when account was created */
106
+ createdAt: number;
107
+ /** Unix timestamp (seconds) when subscription started */
108
+ subscribedAt?: number;
109
+ /** Unix timestamp (seconds) when account was suspended */
110
+ suspendedAt?: number;
111
+ }
112
+
113
+ // =============================================================================
114
+ // ERROR SYSTEM
115
+ // =============================================================================
116
+
117
+ /**
118
+ * All possible error types in the Shipstatic platform
119
+ * Names are developer-friendly while wire format stays consistent
120
+ */
121
+ export enum ErrorType {
122
+ /** Validation failed (400) */
123
+ Validation = "validation_failed",
124
+ /** Resource not found (404) */
125
+ NotFound = "not_found",
126
+ /** Rate limit exceeded (429) */
127
+ RateLimit = "rate_limit_exceeded",
128
+ /** Authentication required (401) */
129
+ Authentication = "authentication_failed",
130
+ /** Business logic error (400) */
131
+ Business = "business_logic_error",
132
+ /** API server error (500) - renamed from Internal for clarity */
133
+ Api = "internal_server_error",
134
+ /** Network/connection error */
135
+ Network = "network_error",
136
+ /** Operation was cancelled */
137
+ Cancelled = "operation_cancelled",
138
+ /** File operation error */
139
+ File = "file_error",
140
+ /** Configuration error */
141
+ Config = "config_error"
142
+ }
143
+
144
+ /** @deprecated Use ErrorType instead. Kept for backward compatibility. */
145
+ export const ShipErrorType = ErrorType;
146
+
147
+ /**
148
+ * Categorizes error types for better type checking
149
+ */
150
+ const ERROR_CATEGORIES = {
151
+ client: new Set([ErrorType.Business, ErrorType.Config, ErrorType.File, ErrorType.Validation]),
152
+ network: new Set([ErrorType.Network]),
153
+ auth: new Set([ErrorType.Authentication]),
154
+ } as const;
155
+
156
+ /**
157
+ * Standard error response format used everywhere
158
+ */
159
+ export interface ErrorResponse {
160
+ /** Error type identifier */
161
+ error: ErrorType;
162
+ /** Human-readable error message */
163
+ message: string;
164
+ /** HTTP status code (API contexts) */
165
+ status?: number;
166
+ /** Optional additional error details */
167
+ details?: any;
168
+ }
169
+
170
+ /**
171
+ * Simple unified error class for both API and SDK
172
+ */
173
+ export class ShipError extends Error {
174
+ constructor(
175
+ public readonly type: ErrorType,
176
+ message: string,
177
+ public readonly status?: number,
178
+ public readonly details?: any
179
+ ) {
180
+ super(message);
181
+ this.name = 'ShipError';
182
+ }
183
+
184
+ /** Convert to wire format */
185
+ toResponse(): ErrorResponse {
186
+ return {
187
+ error: this.type,
188
+ message: this.message,
189
+ status: this.status,
190
+ details: this.details
191
+ };
192
+ }
193
+
194
+ /** Create from wire format */
195
+ static fromResponse(response: ErrorResponse): ShipError {
196
+ return new ShipError(response.error, response.message, response.status, response.details);
197
+ }
198
+
199
+ // Factory methods for common errors
200
+ static validation(message: string, details?: any): ShipError {
201
+ return new ShipError(ErrorType.Validation, message, 400, details);
202
+ }
203
+
204
+ static notFound(resource: string, id?: string): ShipError {
205
+ const message = id ? `${resource} ${id} not found` : `${resource} not found`;
206
+ return new ShipError(ErrorType.NotFound, message, 404);
207
+ }
208
+
209
+ static rateLimit(message: string = "Too many requests"): ShipError {
210
+ return new ShipError(ErrorType.RateLimit, message, 429);
211
+ }
212
+
213
+ static authentication(message: string = "Authentication required"): ShipError {
214
+ return new ShipError(ErrorType.Authentication, message, 401);
215
+ }
216
+
217
+
218
+ static business(message: string, status: number = 400): ShipError {
219
+ return new ShipError(ErrorType.Business, message, status);
220
+ }
221
+
222
+ static network(message: string, cause?: Error): ShipError {
223
+ return new ShipError(ErrorType.Network, message, undefined, { cause });
224
+ }
225
+
226
+ static cancelled(message: string): ShipError {
227
+ return new ShipError(ErrorType.Cancelled, message);
228
+ }
229
+
230
+ static file(message: string, filePath?: string): ShipError {
231
+ return new ShipError(ErrorType.File, message, undefined, { filePath });
232
+ }
233
+
234
+ static config(message: string, details?: any): ShipError {
235
+ return new ShipError(ErrorType.Config, message, undefined, details);
236
+ }
237
+
238
+ static api(message: string, status: number = 500, code?: string, data?: any): ShipError {
239
+ return new ShipError(ErrorType.Api, message, status, { code, data });
240
+ }
241
+
242
+ // Helper getters for accessing common detail properties
243
+ get filePath(): string | undefined {
244
+ return this.details?.filePath;
245
+ }
246
+
247
+ get code(): string | undefined {
248
+ return this.details?.code;
249
+ }
250
+
251
+ // Helper methods for error type checking using categorization
252
+ isClientError(): boolean {
253
+ return ERROR_CATEGORIES.client.has(this.type);
254
+ }
255
+
256
+ isNetworkError(): boolean {
257
+ return ERROR_CATEGORIES.network.has(this.type);
258
+ }
259
+
260
+ isAuthError(): boolean {
261
+ return ERROR_CATEGORIES.auth.has(this.type);
262
+ }
263
+
264
+ isValidationError(): boolean {
265
+ return this.type === ErrorType.Validation;
266
+ }
267
+
268
+ isFileError(): boolean {
269
+ return this.type === ErrorType.File;
270
+ }
271
+
272
+ isConfigError(): boolean {
273
+ return this.type === ErrorType.Config;
274
+ }
275
+
276
+ // Generic type checker
277
+ isType(errorType: ErrorType): boolean {
278
+ return this.type === errorType;
279
+ }
280
+ }
281
+
282
+ // =============================================================================
283
+ // CONFIGURATION CONSTANTS
284
+ // =============================================================================
285
+
286
+ /**
287
+ * Server-side platform configuration - enforced limits on the platform
288
+ */
289
+ export const serverConfig = {
290
+ /** Maximum individual file size in bytes (10MB) */
291
+ maxFileSize: 10 * 1024 * 1024,
292
+ /** Maximum number of files per deployment */
293
+ maxFilesCount: 1000,
294
+ /** Maximum total deployment size in bytes (100MB) */
295
+ maxTotalSize: 100 * 1024 * 1024,
296
+ /** Deployment expiry in hours */
297
+ deploymentExpiryHours: 168, // 7 days
298
+ /** Pagination limits */
299
+ defaultLimit: 50,
300
+ maxLimit: 100,
301
+ } as const;
302
+
303
+
304
+
305
+ // =============================================================================
306
+ // CONFIG TYPES
307
+ // =============================================================================
308
+
309
+ /**
310
+ * Platform configuration response from API
311
+ */
312
+ export interface ConfigResponse {
313
+ /** Maximum individual file size in bytes */
314
+ maxFileSize: number;
315
+ /** Maximum number of files per deployment */
316
+ maxFilesCount: number;
317
+ /** Maximum total deployment size in bytes */
318
+ maxTotalSize: number;
319
+ }
320
+
321
+ // =============================================================================
322
+ // COMMON RESPONSE PATTERNS
323
+ // =============================================================================
324
+
325
+ /**
326
+ * Generic success response wrapper
327
+ */
328
+ export interface SuccessResponse<T = any> {
329
+ /** Always true for success */
330
+ success: true;
331
+ /** Response data */
332
+ data: T;
333
+ }
334
+
335
+ /**
336
+ * Simple ping response for health checks
337
+ */
338
+ export interface PingResponse {
339
+ /** Always true if service is healthy */
340
+ success: boolean;
341
+ /** Optional timestamp */
342
+ timestamp?: number;
343
+ }
344
+
345
+
346
+ // API Key Configuration
347
+ export const API_KEY_PREFIX = 'ship-';