@shipstatic/types 0.9.0 → 0.9.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 +3 -5
- package/dist/index.d.ts +68 -69
- package/dist/index.js +61 -38
- package/package.json +1 -1
- package/src/index.ts +87 -91
package/README.md
CHANGED
|
@@ -62,7 +62,7 @@ import {
|
|
|
62
62
|
|
|
63
63
|
```typescript
|
|
64
64
|
import type {
|
|
65
|
-
|
|
65
|
+
PlatformLimits, // plan-based caps from /config (file size, file count, total size)
|
|
66
66
|
BillingStatus,
|
|
67
67
|
CheckoutSession,
|
|
68
68
|
ActivityListResponse,
|
|
@@ -80,8 +80,6 @@ import type {
|
|
|
80
80
|
DomainResource,
|
|
81
81
|
AccountResource,
|
|
82
82
|
TokenResource,
|
|
83
|
-
BillingResource,
|
|
84
|
-
KeysResource,
|
|
85
83
|
} from '@shipstatic/types';
|
|
86
84
|
```
|
|
87
85
|
|
|
@@ -138,8 +136,8 @@ import {
|
|
|
138
136
|
```typescript
|
|
139
137
|
import {
|
|
140
138
|
DEFAULT_API,
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
API_KEY, // { PREFIX, HEX_LENGTH, TOTAL_LENGTH, HINT_LENGTH }
|
|
140
|
+
DEPLOY_TOKEN, // { PREFIX, HEX_LENGTH, TOTAL_LENGTH }
|
|
143
141
|
DEPLOYMENT_CONFIG_FILENAME,
|
|
144
142
|
} from '@shipstatic/types';
|
|
145
143
|
```
|
package/dist/index.d.ts
CHANGED
|
@@ -296,31 +296,37 @@ export interface AccountOverrides {
|
|
|
296
296
|
totalSize?: number;
|
|
297
297
|
}
|
|
298
298
|
/**
|
|
299
|
-
* All possible error types in the ShipStatic platform
|
|
300
|
-
*
|
|
299
|
+
* All possible error types in the ShipStatic platform.
|
|
300
|
+
*
|
|
301
|
+
* Developer-friendly key names map to stable wire-format string values.
|
|
302
|
+
* Both the value and the type are exported under the same name so callers
|
|
303
|
+
* can use `ErrorType.Validation` (value comparison) and `: ErrorType` (type
|
|
304
|
+
* annotation) without ceremony — matching the pattern other status objects
|
|
305
|
+
* (`DeploymentStatus`, `DomainStatus`, `AccountPlan`, `AuthMethod`) follow.
|
|
301
306
|
*/
|
|
302
|
-
export declare
|
|
307
|
+
export declare const ErrorType: {
|
|
303
308
|
/** Validation failed (400) */
|
|
304
|
-
Validation
|
|
309
|
+
readonly Validation: "validation_failed";
|
|
305
310
|
/** Resource not found (404) */
|
|
306
|
-
NotFound
|
|
311
|
+
readonly NotFound: "not_found";
|
|
307
312
|
/** Rate limit exceeded (429) */
|
|
308
|
-
RateLimit
|
|
313
|
+
readonly RateLimit: "rate_limit_exceeded";
|
|
309
314
|
/** Authentication required (401) */
|
|
310
|
-
Authentication
|
|
315
|
+
readonly Authentication: "authentication_failed";
|
|
311
316
|
/** Business logic error (400) */
|
|
312
|
-
Business
|
|
313
|
-
/** API server error (500)
|
|
314
|
-
Api
|
|
317
|
+
readonly Business: "business_logic_error";
|
|
318
|
+
/** API server error (500) */
|
|
319
|
+
readonly Api: "internal_server_error";
|
|
315
320
|
/** Network/connection error */
|
|
316
|
-
Network
|
|
321
|
+
readonly Network: "network_error";
|
|
317
322
|
/** Operation was cancelled */
|
|
318
|
-
Cancelled
|
|
323
|
+
readonly Cancelled: "operation_cancelled";
|
|
319
324
|
/** File operation error */
|
|
320
|
-
File
|
|
325
|
+
readonly File: "file_error";
|
|
321
326
|
/** Configuration error */
|
|
322
|
-
Config
|
|
323
|
-
}
|
|
327
|
+
readonly Config: "config_error";
|
|
328
|
+
};
|
|
329
|
+
export type ErrorType = typeof ErrorType[keyof typeof ErrorType];
|
|
324
330
|
/**
|
|
325
331
|
* Standard error response format used everywhere
|
|
326
332
|
*/
|
|
@@ -380,12 +386,22 @@ export declare class ShipError extends Error {
|
|
|
380
386
|
*/
|
|
381
387
|
export declare function isShipError(error: unknown): error is ShipError;
|
|
382
388
|
/**
|
|
383
|
-
*
|
|
384
|
-
*
|
|
389
|
+
* Plan-based platform limits returned by the `/config` endpoint.
|
|
390
|
+
*
|
|
391
|
+
* The SDK fetches these once on first API call to drive client-side
|
|
392
|
+
* file-size / file-count / total-size validation that mirrors what the API
|
|
393
|
+
* would enforce server-side. Limits vary by account plan.
|
|
394
|
+
*
|
|
395
|
+
* Distinct from `ResolvedConfig` (which carries the *client's* credentials
|
|
396
|
+
* and API URL after defaulting); this one carries the *platform's* posted
|
|
397
|
+
* caps for the current account.
|
|
385
398
|
*/
|
|
386
|
-
export interface
|
|
399
|
+
export interface PlatformLimits {
|
|
400
|
+
/** Maximum size in bytes for a single file. */
|
|
387
401
|
maxFileSize: number;
|
|
402
|
+
/** Maximum number of files in a single deployment. */
|
|
388
403
|
maxFilesCount: number;
|
|
404
|
+
/** Maximum total size in bytes across all files in a deployment. */
|
|
389
405
|
maxTotalSize: number;
|
|
390
406
|
}
|
|
391
407
|
/**
|
|
@@ -457,13 +473,32 @@ export interface PingResponse {
|
|
|
457
473
|
/** Optional timestamp */
|
|
458
474
|
timestamp?: number;
|
|
459
475
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
export declare const
|
|
465
|
-
|
|
466
|
-
|
|
476
|
+
/**
|
|
477
|
+
* Shape constants for API keys (`ship-{64 hex chars}`).
|
|
478
|
+
* Single source of truth used by validation utilities and auth middleware.
|
|
479
|
+
*/
|
|
480
|
+
export declare const API_KEY: {
|
|
481
|
+
/** Prefix that identifies an API key. */
|
|
482
|
+
readonly PREFIX: "ship-";
|
|
483
|
+
/** Number of hex characters following the prefix. */
|
|
484
|
+
readonly HEX_LENGTH: 64;
|
|
485
|
+
/** Total length of an API key including prefix (`PREFIX.length + HEX_LENGTH = 69`). */
|
|
486
|
+
readonly TOTAL_LENGTH: 69;
|
|
487
|
+
/** Number of trailing characters used to display a redacted hint (e.g. last 4). */
|
|
488
|
+
readonly HINT_LENGTH: 4;
|
|
489
|
+
};
|
|
490
|
+
/**
|
|
491
|
+
* Shape constants for deploy tokens (`token-{64 hex chars}`).
|
|
492
|
+
* Single source of truth used by validation utilities and auth middleware.
|
|
493
|
+
*/
|
|
494
|
+
export declare const DEPLOY_TOKEN: {
|
|
495
|
+
/** Prefix that identifies a deploy token. */
|
|
496
|
+
readonly PREFIX: "token-";
|
|
497
|
+
/** Number of hex characters following the prefix. */
|
|
498
|
+
readonly HEX_LENGTH: 64;
|
|
499
|
+
/** Total length of a deploy token including prefix (`PREFIX.length + HEX_LENGTH = 70`). */
|
|
500
|
+
readonly TOTAL_LENGTH: 70;
|
|
501
|
+
};
|
|
467
502
|
export declare const AuthMethod: {
|
|
468
503
|
readonly JWT: "jwt";
|
|
469
504
|
readonly API_KEY: "apiKey";
|
|
@@ -584,26 +619,16 @@ export interface ProgressInfo {
|
|
|
584
619
|
/** Default API URL if not otherwise configured. */
|
|
585
620
|
export declare const DEFAULT_API = "https://api.shipstatic.com";
|
|
586
621
|
/**
|
|
587
|
-
*
|
|
588
|
-
*
|
|
589
|
-
*
|
|
590
|
-
|
|
591
|
-
export type BrowserDeployInput = File[];
|
|
592
|
-
/**
|
|
593
|
-
* Node-specific deploy input — file or directory path(s) on disk. A single
|
|
594
|
-
* path or an array of paths; directories are walked recursively. The Node
|
|
595
|
-
* SDK rejects any other shape at runtime.
|
|
596
|
-
*/
|
|
597
|
-
export type NodeDeployInput = string | string[];
|
|
598
|
-
/**
|
|
599
|
-
* Universal deploy input — the union of every platform's accepted shape.
|
|
622
|
+
* Universal deploy input — the union of every shape the SDK accepts.
|
|
623
|
+
*
|
|
624
|
+
* - **Browser**: `File[]` (typically from `<input type="file">` or drag-and-drop)
|
|
625
|
+
* - **Node**: `string | string[]` (file or directory path(s) on disk; directories are walked)
|
|
600
626
|
*
|
|
601
|
-
*
|
|
602
|
-
*
|
|
603
|
-
*
|
|
604
|
-
* platform's SDK validates at runtime and throws on the wrong shape.
|
|
627
|
+
* Each platform's SDK narrows its `deploy()` signature to the relevant shape
|
|
628
|
+
* and rejects anything else at runtime. Use the structural types directly
|
|
629
|
+
* (`File[]`, `string | string[]`) when writing platform-specific code.
|
|
605
630
|
*/
|
|
606
|
-
export type DeployInput =
|
|
631
|
+
export type DeployInput = File[] | string | string[];
|
|
607
632
|
/**
|
|
608
633
|
* Options for deployment creation at the API contract level.
|
|
609
634
|
* SDK implementations may extend with additional options (timeout, signal, callbacks, etc.).
|
|
@@ -706,32 +731,6 @@ export interface CheckoutSession {
|
|
|
706
731
|
/** URL to redirect user to Creem checkout page */
|
|
707
732
|
url: string;
|
|
708
733
|
}
|
|
709
|
-
/**
|
|
710
|
-
* Billing resource interface - the contract all implementations must follow
|
|
711
|
-
*
|
|
712
|
-
* IMPOSSIBLE SIMPLICITY: No sync() method needed!
|
|
713
|
-
* Webhooks are the single source of truth. Frontend just polls status().
|
|
714
|
-
*/
|
|
715
|
-
export interface BillingResource {
|
|
716
|
-
/**
|
|
717
|
-
* Create a checkout session
|
|
718
|
-
* @returns Checkout session with URL to redirect user
|
|
719
|
-
*/
|
|
720
|
-
checkout: () => Promise<CheckoutSession>;
|
|
721
|
-
/**
|
|
722
|
-
* Get current billing status
|
|
723
|
-
* @returns Billing status and usage information
|
|
724
|
-
*/
|
|
725
|
-
status: () => Promise<BillingStatus>;
|
|
726
|
-
}
|
|
727
|
-
/**
|
|
728
|
-
* Keys resource interface - the contract all implementations must follow
|
|
729
|
-
*/
|
|
730
|
-
export interface KeysResource {
|
|
731
|
-
create: () => Promise<{
|
|
732
|
-
apiKey: string;
|
|
733
|
-
}>;
|
|
734
|
-
}
|
|
735
734
|
/**
|
|
736
735
|
* All activity event types logged in the system.
|
|
737
736
|
* Uses dot notation consistently: {resource}.{action}
|
package/dist/index.js
CHANGED
|
@@ -50,34 +50,40 @@ export const AccountPlan = {
|
|
|
50
50
|
// ERROR SYSTEM
|
|
51
51
|
// =============================================================================
|
|
52
52
|
/**
|
|
53
|
-
* All possible error types in the ShipStatic platform
|
|
54
|
-
*
|
|
53
|
+
* All possible error types in the ShipStatic platform.
|
|
54
|
+
*
|
|
55
|
+
* Developer-friendly key names map to stable wire-format string values.
|
|
56
|
+
* Both the value and the type are exported under the same name so callers
|
|
57
|
+
* can use `ErrorType.Validation` (value comparison) and `: ErrorType` (type
|
|
58
|
+
* annotation) without ceremony — matching the pattern other status objects
|
|
59
|
+
* (`DeploymentStatus`, `DomainStatus`, `AccountPlan`, `AuthMethod`) follow.
|
|
55
60
|
*/
|
|
56
|
-
export
|
|
57
|
-
(function (ErrorType) {
|
|
61
|
+
export const ErrorType = {
|
|
58
62
|
/** Validation failed (400) */
|
|
59
|
-
|
|
63
|
+
Validation: 'validation_failed',
|
|
60
64
|
/** Resource not found (404) */
|
|
61
|
-
|
|
65
|
+
NotFound: 'not_found',
|
|
62
66
|
/** Rate limit exceeded (429) */
|
|
63
|
-
|
|
67
|
+
RateLimit: 'rate_limit_exceeded',
|
|
64
68
|
/** Authentication required (401) */
|
|
65
|
-
|
|
69
|
+
Authentication: 'authentication_failed',
|
|
66
70
|
/** Business logic error (400) */
|
|
67
|
-
|
|
68
|
-
/** API server error (500)
|
|
69
|
-
|
|
71
|
+
Business: 'business_logic_error',
|
|
72
|
+
/** API server error (500) */
|
|
73
|
+
Api: 'internal_server_error',
|
|
70
74
|
/** Network/connection error */
|
|
71
|
-
|
|
75
|
+
Network: 'network_error',
|
|
72
76
|
/** Operation was cancelled */
|
|
73
|
-
|
|
77
|
+
Cancelled: 'operation_cancelled',
|
|
74
78
|
/** File operation error */
|
|
75
|
-
|
|
79
|
+
File: 'file_error',
|
|
76
80
|
/** Configuration error */
|
|
77
|
-
|
|
78
|
-
}
|
|
81
|
+
Config: 'config_error',
|
|
82
|
+
};
|
|
79
83
|
/**
|
|
80
|
-
* Categorizes error types for
|
|
84
|
+
* Categorizes error types for the `isClientError` / `isNetworkError` /
|
|
85
|
+
* `isAuthError` helpers. Each `Set` is typed against the wider `ErrorType`
|
|
86
|
+
* union so `.has(error.type)` accepts any value from the union.
|
|
81
87
|
*/
|
|
82
88
|
const ERROR_CATEGORIES = {
|
|
83
89
|
client: new Set([ErrorType.Business, ErrorType.Config, ErrorType.File, ErrorType.Validation]),
|
|
@@ -299,15 +305,32 @@ export function hasUnbuiltMarker(filePath) {
|
|
|
299
305
|
const segments = filePath.replace(/\\/g, '/').split('/').filter(Boolean);
|
|
300
306
|
return segments.some(s => UNBUILT_PROJECT_MARKERS.has(s));
|
|
301
307
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
export const
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
308
|
+
/**
|
|
309
|
+
* Shape constants for API keys (`ship-{64 hex chars}`).
|
|
310
|
+
* Single source of truth used by validation utilities and auth middleware.
|
|
311
|
+
*/
|
|
312
|
+
export const API_KEY = {
|
|
313
|
+
/** Prefix that identifies an API key. */
|
|
314
|
+
PREFIX: 'ship-',
|
|
315
|
+
/** Number of hex characters following the prefix. */
|
|
316
|
+
HEX_LENGTH: 64,
|
|
317
|
+
/** Total length of an API key including prefix (`PREFIX.length + HEX_LENGTH = 69`). */
|
|
318
|
+
TOTAL_LENGTH: 69,
|
|
319
|
+
/** Number of trailing characters used to display a redacted hint (e.g. last 4). */
|
|
320
|
+
HINT_LENGTH: 4,
|
|
321
|
+
};
|
|
322
|
+
/**
|
|
323
|
+
* Shape constants for deploy tokens (`token-{64 hex chars}`).
|
|
324
|
+
* Single source of truth used by validation utilities and auth middleware.
|
|
325
|
+
*/
|
|
326
|
+
export const DEPLOY_TOKEN = {
|
|
327
|
+
/** Prefix that identifies a deploy token. */
|
|
328
|
+
PREFIX: 'token-',
|
|
329
|
+
/** Number of hex characters following the prefix. */
|
|
330
|
+
HEX_LENGTH: 64,
|
|
331
|
+
/** Total length of a deploy token including prefix (`PREFIX.length + HEX_LENGTH = 70`). */
|
|
332
|
+
TOTAL_LENGTH: 70,
|
|
333
|
+
};
|
|
311
334
|
// Authentication Method Constants
|
|
312
335
|
export const AuthMethod = {
|
|
313
336
|
JWT: 'jwt',
|
|
@@ -327,30 +350,30 @@ export const SPA_DEFAULT_CONFIG = { rewrites: [{ source: '/(.*)', destination: '
|
|
|
327
350
|
* Validate API key format
|
|
328
351
|
*/
|
|
329
352
|
export function validateApiKey(apiKey) {
|
|
330
|
-
if (!apiKey.startsWith(
|
|
331
|
-
throw ShipError.validation(`API key must start with "${
|
|
353
|
+
if (!apiKey.startsWith(API_KEY.PREFIX)) {
|
|
354
|
+
throw ShipError.validation(`API key must start with "${API_KEY.PREFIX}"`);
|
|
332
355
|
}
|
|
333
|
-
if (apiKey.length !==
|
|
334
|
-
throw ShipError.validation(`API key must be ${
|
|
356
|
+
if (apiKey.length !== API_KEY.TOTAL_LENGTH) {
|
|
357
|
+
throw ShipError.validation(`API key must be ${API_KEY.TOTAL_LENGTH} characters total (${API_KEY.PREFIX} + ${API_KEY.HEX_LENGTH} hex chars)`);
|
|
335
358
|
}
|
|
336
|
-
const hexPart = apiKey.slice(
|
|
359
|
+
const hexPart = apiKey.slice(API_KEY.PREFIX.length);
|
|
337
360
|
if (!/^[a-f0-9]{64}$/i.test(hexPart)) {
|
|
338
|
-
throw ShipError.validation(`API key must contain ${
|
|
361
|
+
throw ShipError.validation(`API key must contain ${API_KEY.HEX_LENGTH} hexadecimal characters after "${API_KEY.PREFIX}" prefix`);
|
|
339
362
|
}
|
|
340
363
|
}
|
|
341
364
|
/**
|
|
342
365
|
* Validate deploy token format
|
|
343
366
|
*/
|
|
344
367
|
export function validateDeployToken(deployToken) {
|
|
345
|
-
if (!deployToken.startsWith(
|
|
346
|
-
throw ShipError.validation(`Deploy token must start with "${
|
|
368
|
+
if (!deployToken.startsWith(DEPLOY_TOKEN.PREFIX)) {
|
|
369
|
+
throw ShipError.validation(`Deploy token must start with "${DEPLOY_TOKEN.PREFIX}"`);
|
|
347
370
|
}
|
|
348
|
-
if (deployToken.length !==
|
|
349
|
-
throw ShipError.validation(`Deploy token must be ${
|
|
371
|
+
if (deployToken.length !== DEPLOY_TOKEN.TOTAL_LENGTH) {
|
|
372
|
+
throw ShipError.validation(`Deploy token must be ${DEPLOY_TOKEN.TOTAL_LENGTH} characters total (${DEPLOY_TOKEN.PREFIX} + ${DEPLOY_TOKEN.HEX_LENGTH} hex chars)`);
|
|
350
373
|
}
|
|
351
|
-
const hexPart = deployToken.slice(
|
|
374
|
+
const hexPart = deployToken.slice(DEPLOY_TOKEN.PREFIX.length);
|
|
352
375
|
if (!/^[a-f0-9]{64}$/i.test(hexPart)) {
|
|
353
|
-
throw ShipError.validation(`Deploy token must contain ${
|
|
376
|
+
throw ShipError.validation(`Deploy token must contain ${DEPLOY_TOKEN.HEX_LENGTH} hexadecimal characters after "${DEPLOY_TOKEN.PREFIX}" prefix`);
|
|
354
377
|
}
|
|
355
378
|
}
|
|
356
379
|
/**
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -341,39 +341,48 @@ export interface AccountOverrides {
|
|
|
341
341
|
// =============================================================================
|
|
342
342
|
|
|
343
343
|
/**
|
|
344
|
-
* All possible error types in the ShipStatic platform
|
|
345
|
-
*
|
|
344
|
+
* All possible error types in the ShipStatic platform.
|
|
345
|
+
*
|
|
346
|
+
* Developer-friendly key names map to stable wire-format string values.
|
|
347
|
+
* Both the value and the type are exported under the same name so callers
|
|
348
|
+
* can use `ErrorType.Validation` (value comparison) and `: ErrorType` (type
|
|
349
|
+
* annotation) without ceremony — matching the pattern other status objects
|
|
350
|
+
* (`DeploymentStatus`, `DomainStatus`, `AccountPlan`, `AuthMethod`) follow.
|
|
346
351
|
*/
|
|
347
|
-
export
|
|
352
|
+
export const ErrorType = {
|
|
348
353
|
/** Validation failed (400) */
|
|
349
|
-
Validation
|
|
354
|
+
Validation: 'validation_failed',
|
|
350
355
|
/** Resource not found (404) */
|
|
351
|
-
NotFound
|
|
356
|
+
NotFound: 'not_found',
|
|
352
357
|
/** Rate limit exceeded (429) */
|
|
353
|
-
RateLimit
|
|
358
|
+
RateLimit: 'rate_limit_exceeded',
|
|
354
359
|
/** Authentication required (401) */
|
|
355
|
-
Authentication
|
|
360
|
+
Authentication: 'authentication_failed',
|
|
356
361
|
/** Business logic error (400) */
|
|
357
|
-
Business
|
|
358
|
-
/** API server error (500)
|
|
359
|
-
Api
|
|
362
|
+
Business: 'business_logic_error',
|
|
363
|
+
/** API server error (500) */
|
|
364
|
+
Api: 'internal_server_error',
|
|
360
365
|
/** Network/connection error */
|
|
361
|
-
Network
|
|
366
|
+
Network: 'network_error',
|
|
362
367
|
/** Operation was cancelled */
|
|
363
|
-
Cancelled
|
|
368
|
+
Cancelled: 'operation_cancelled',
|
|
364
369
|
/** File operation error */
|
|
365
|
-
File
|
|
370
|
+
File: 'file_error',
|
|
366
371
|
/** Configuration error */
|
|
367
|
-
Config
|
|
368
|
-
}
|
|
372
|
+
Config: 'config_error',
|
|
373
|
+
} as const;
|
|
374
|
+
|
|
375
|
+
export type ErrorType = typeof ErrorType[keyof typeof ErrorType];
|
|
369
376
|
|
|
370
377
|
/**
|
|
371
|
-
* Categorizes error types for
|
|
378
|
+
* Categorizes error types for the `isClientError` / `isNetworkError` /
|
|
379
|
+
* `isAuthError` helpers. Each `Set` is typed against the wider `ErrorType`
|
|
380
|
+
* union so `.has(error.type)` accepts any value from the union.
|
|
372
381
|
*/
|
|
373
382
|
const ERROR_CATEGORIES = {
|
|
374
|
-
client: new Set([ErrorType.Business, ErrorType.Config, ErrorType.File, ErrorType.Validation]),
|
|
375
|
-
network: new Set([ErrorType.Network]),
|
|
376
|
-
auth: new Set([ErrorType.Authentication]),
|
|
383
|
+
client: new Set<ErrorType>([ErrorType.Business, ErrorType.Config, ErrorType.File, ErrorType.Validation]),
|
|
384
|
+
network: new Set<ErrorType>([ErrorType.Network]),
|
|
385
|
+
auth: new Set<ErrorType>([ErrorType.Authentication]),
|
|
377
386
|
} as const;
|
|
378
387
|
|
|
379
388
|
/**
|
|
@@ -536,12 +545,22 @@ export function isShipError(error: unknown): error is ShipError {
|
|
|
536
545
|
// =============================================================================
|
|
537
546
|
|
|
538
547
|
/**
|
|
539
|
-
*
|
|
540
|
-
*
|
|
548
|
+
* Plan-based platform limits returned by the `/config` endpoint.
|
|
549
|
+
*
|
|
550
|
+
* The SDK fetches these once on first API call to drive client-side
|
|
551
|
+
* file-size / file-count / total-size validation that mirrors what the API
|
|
552
|
+
* would enforce server-side. Limits vary by account plan.
|
|
553
|
+
*
|
|
554
|
+
* Distinct from `ResolvedConfig` (which carries the *client's* credentials
|
|
555
|
+
* and API URL after defaulting); this one carries the *platform's* posted
|
|
556
|
+
* caps for the current account.
|
|
541
557
|
*/
|
|
542
|
-
export interface
|
|
558
|
+
export interface PlatformLimits {
|
|
559
|
+
/** Maximum size in bytes for a single file. */
|
|
543
560
|
maxFileSize: number;
|
|
561
|
+
/** Maximum number of files in a single deployment. */
|
|
544
562
|
maxFilesCount: number;
|
|
563
|
+
/** Maximum total size in bytes across all files in a deployment. */
|
|
545
564
|
maxTotalSize: number;
|
|
546
565
|
}
|
|
547
566
|
|
|
@@ -667,16 +686,33 @@ export interface PingResponse {
|
|
|
667
686
|
timestamp?: number;
|
|
668
687
|
}
|
|
669
688
|
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
export const
|
|
689
|
+
/**
|
|
690
|
+
* Shape constants for API keys (`ship-{64 hex chars}`).
|
|
691
|
+
* Single source of truth used by validation utilities and auth middleware.
|
|
692
|
+
*/
|
|
693
|
+
export const API_KEY = {
|
|
694
|
+
/** Prefix that identifies an API key. */
|
|
695
|
+
PREFIX: 'ship-',
|
|
696
|
+
/** Number of hex characters following the prefix. */
|
|
697
|
+
HEX_LENGTH: 64,
|
|
698
|
+
/** Total length of an API key including prefix (`PREFIX.length + HEX_LENGTH = 69`). */
|
|
699
|
+
TOTAL_LENGTH: 69,
|
|
700
|
+
/** Number of trailing characters used to display a redacted hint (e.g. last 4). */
|
|
701
|
+
HINT_LENGTH: 4,
|
|
702
|
+
} as const;
|
|
675
703
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
704
|
+
/**
|
|
705
|
+
* Shape constants for deploy tokens (`token-{64 hex chars}`).
|
|
706
|
+
* Single source of truth used by validation utilities and auth middleware.
|
|
707
|
+
*/
|
|
708
|
+
export const DEPLOY_TOKEN = {
|
|
709
|
+
/** Prefix that identifies a deploy token. */
|
|
710
|
+
PREFIX: 'token-',
|
|
711
|
+
/** Number of hex characters following the prefix. */
|
|
712
|
+
HEX_LENGTH: 64,
|
|
713
|
+
/** Total length of a deploy token including prefix (`PREFIX.length + HEX_LENGTH = 70`). */
|
|
714
|
+
TOTAL_LENGTH: 70,
|
|
715
|
+
} as const;
|
|
680
716
|
|
|
681
717
|
// Authentication Method Constants
|
|
682
718
|
export const AuthMethod = {
|
|
@@ -703,17 +739,17 @@ export const SPA_DEFAULT_CONFIG = { rewrites: [{ source: '/(.*)', destination: '
|
|
|
703
739
|
* Validate API key format
|
|
704
740
|
*/
|
|
705
741
|
export function validateApiKey(apiKey: string): void {
|
|
706
|
-
if (!apiKey.startsWith(
|
|
707
|
-
throw ShipError.validation(`API key must start with "${
|
|
742
|
+
if (!apiKey.startsWith(API_KEY.PREFIX)) {
|
|
743
|
+
throw ShipError.validation(`API key must start with "${API_KEY.PREFIX}"`);
|
|
708
744
|
}
|
|
709
745
|
|
|
710
|
-
if (apiKey.length !==
|
|
711
|
-
throw ShipError.validation(`API key must be ${
|
|
746
|
+
if (apiKey.length !== API_KEY.TOTAL_LENGTH) {
|
|
747
|
+
throw ShipError.validation(`API key must be ${API_KEY.TOTAL_LENGTH} characters total (${API_KEY.PREFIX} + ${API_KEY.HEX_LENGTH} hex chars)`);
|
|
712
748
|
}
|
|
713
749
|
|
|
714
|
-
const hexPart = apiKey.slice(
|
|
750
|
+
const hexPart = apiKey.slice(API_KEY.PREFIX.length);
|
|
715
751
|
if (!/^[a-f0-9]{64}$/i.test(hexPart)) {
|
|
716
|
-
throw ShipError.validation(`API key must contain ${
|
|
752
|
+
throw ShipError.validation(`API key must contain ${API_KEY.HEX_LENGTH} hexadecimal characters after "${API_KEY.PREFIX}" prefix`);
|
|
717
753
|
}
|
|
718
754
|
}
|
|
719
755
|
|
|
@@ -721,17 +757,17 @@ export function validateApiKey(apiKey: string): void {
|
|
|
721
757
|
* Validate deploy token format
|
|
722
758
|
*/
|
|
723
759
|
export function validateDeployToken(deployToken: string): void {
|
|
724
|
-
if (!deployToken.startsWith(
|
|
725
|
-
throw ShipError.validation(`Deploy token must start with "${
|
|
760
|
+
if (!deployToken.startsWith(DEPLOY_TOKEN.PREFIX)) {
|
|
761
|
+
throw ShipError.validation(`Deploy token must start with "${DEPLOY_TOKEN.PREFIX}"`);
|
|
726
762
|
}
|
|
727
763
|
|
|
728
|
-
if (deployToken.length !==
|
|
729
|
-
throw ShipError.validation(`Deploy token must be ${
|
|
764
|
+
if (deployToken.length !== DEPLOY_TOKEN.TOTAL_LENGTH) {
|
|
765
|
+
throw ShipError.validation(`Deploy token must be ${DEPLOY_TOKEN.TOTAL_LENGTH} characters total (${DEPLOY_TOKEN.PREFIX} + ${DEPLOY_TOKEN.HEX_LENGTH} hex chars)`);
|
|
730
766
|
}
|
|
731
767
|
|
|
732
|
-
const hexPart = deployToken.slice(
|
|
768
|
+
const hexPart = deployToken.slice(DEPLOY_TOKEN.PREFIX.length);
|
|
733
769
|
if (!/^[a-f0-9]{64}$/i.test(hexPart)) {
|
|
734
|
-
throw ShipError.validation(`Deploy token must contain ${
|
|
770
|
+
throw ShipError.validation(`Deploy token must contain ${DEPLOY_TOKEN.HEX_LENGTH} hexadecimal characters after "${DEPLOY_TOKEN.PREFIX}" prefix`);
|
|
735
771
|
}
|
|
736
772
|
}
|
|
737
773
|
|
|
@@ -886,28 +922,16 @@ export const DEFAULT_API = 'https://api.shipstatic.com';
|
|
|
886
922
|
// =============================================================================
|
|
887
923
|
|
|
888
924
|
/**
|
|
889
|
-
*
|
|
890
|
-
*
|
|
891
|
-
*
|
|
892
|
-
|
|
893
|
-
export type BrowserDeployInput = File[];
|
|
894
|
-
|
|
895
|
-
/**
|
|
896
|
-
* Node-specific deploy input — file or directory path(s) on disk. A single
|
|
897
|
-
* path or an array of paths; directories are walked recursively. The Node
|
|
898
|
-
* SDK rejects any other shape at runtime.
|
|
899
|
-
*/
|
|
900
|
-
export type NodeDeployInput = string | string[];
|
|
901
|
-
|
|
902
|
-
/**
|
|
903
|
-
* Universal deploy input — the union of every platform's accepted shape.
|
|
925
|
+
* Universal deploy input — the union of every shape the SDK accepts.
|
|
926
|
+
*
|
|
927
|
+
* - **Browser**: `File[]` (typically from `<input type="file">` or drag-and-drop)
|
|
928
|
+
* - **Node**: `string | string[]` (file or directory path(s) on disk; directories are walked)
|
|
904
929
|
*
|
|
905
|
-
*
|
|
906
|
-
*
|
|
907
|
-
*
|
|
908
|
-
* platform's SDK validates at runtime and throws on the wrong shape.
|
|
930
|
+
* Each platform's SDK narrows its `deploy()` signature to the relevant shape
|
|
931
|
+
* and rejects anything else at runtime. Use the structural types directly
|
|
932
|
+
* (`File[]`, `string | string[]`) when writing platform-specific code.
|
|
909
933
|
*/
|
|
910
|
-
export type DeployInput =
|
|
934
|
+
export type DeployInput = File[] | string | string[];
|
|
911
935
|
|
|
912
936
|
/**
|
|
913
937
|
* Options for deployment creation at the API contract level.
|
|
@@ -1010,34 +1034,6 @@ export interface CheckoutSession {
|
|
|
1010
1034
|
url: string;
|
|
1011
1035
|
}
|
|
1012
1036
|
|
|
1013
|
-
/**
|
|
1014
|
-
* Billing resource interface - the contract all implementations must follow
|
|
1015
|
-
*
|
|
1016
|
-
* IMPOSSIBLE SIMPLICITY: No sync() method needed!
|
|
1017
|
-
* Webhooks are the single source of truth. Frontend just polls status().
|
|
1018
|
-
*/
|
|
1019
|
-
export interface BillingResource {
|
|
1020
|
-
/**
|
|
1021
|
-
* Create a checkout session
|
|
1022
|
-
* @returns Checkout session with URL to redirect user
|
|
1023
|
-
*/
|
|
1024
|
-
checkout: () => Promise<CheckoutSession>;
|
|
1025
|
-
|
|
1026
|
-
/**
|
|
1027
|
-
* Get current billing status
|
|
1028
|
-
* @returns Billing status and usage information
|
|
1029
|
-
*/
|
|
1030
|
-
status: () => Promise<BillingStatus>;
|
|
1031
|
-
}
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
/**
|
|
1035
|
-
* Keys resource interface - the contract all implementations must follow
|
|
1036
|
-
*/
|
|
1037
|
-
export interface KeysResource {
|
|
1038
|
-
create: () => Promise<{ apiKey: string }>;
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
1037
|
// =============================================================================
|
|
1042
1038
|
// ACTIVITY TYPES
|
|
1043
1039
|
// =============================================================================
|