Skip to content

Repository files navigation

@shipstatic/types

Shared TypeScript types for the ShipStatic platform.

Single source of truth for types used across API, SDK, CLI, and web applications.

Installation

# Included with the ShipStatic SDK
npm install @shipstatic/ship
# Direct installation
npm install @shipstatic/types

What's included

Core entities

importtype{ListResponse,ListOptions,Deployment,DeploymentListResponse,DeploymentDeleteResponse,DeploymentSetOptions,Domain,DomainSetResult,DomainSetOptions,DomainListResponse,DnsRecord,DnsLookup,DomainDnsResponse,DomainRecordsResponse,DomainShareResponse,DomainValidateResponse,DomainDeleteResponse,DomainVerifyResponse,Token,TokenListResponse,TokenCreateResponse,TokenCreateOptions,TokenDeleteResponse,Account,Caps,AccountDeleteResponse,AccountKeyResponse,LabelsResponse,SetupInstructionsResponse,StaticFile}from'@shipstatic/types';// Every public path, declared once — the API mounts from it, clients request against it.import{API_PATHS}from'@shipstatic/types';

A mutation answers with the resource it affected — the entity when it survives, otherwise the *DeleteResponse shape: the resource noun carrying the canonical key, plus the resource's own state field where the resource is mid-transition. No message, no success, no constant flags.

Error system

import{ShipError,ErrorType,isShipError}from'@shipstatic/types';throwShipError.validation('File too large');throwShipError.notFound('Deployment',id);throwShipError.forbidden('Account terminated');throwShipError.authentication();throwShipError.business('Plan limit reached');if(isShipError(error)){console.log(error.status,error.type,error.message);}if(error.isClientError()){/* Business | Config | File | Validation */}if(error.isAuthError()){/* handle auth */}if(error.type===ErrorType.Validation){/* specific-type checks */}

HTTP client integration. Both producer and consumer sides of the wire have first-class helpers, so every HTTP client across the platform reconstructs the same ShipError shape:

// Producer side (API workers): serialize a ShipError to JSONreturnc.json(error.toResponse(),error.status??500);// Consumer side — two symmetric helpers cover both HTTP error modes:// Both helpers take an optional operationName for context-aware fallback messages.// 1. Server returned a non-OK responseif(!response.ok){throwawaitShipError.fromHttpResponse(response,'Get account');}// 2. fetch itself threw (offline, abort, CORS, ...)try{response=awaitfetch(url);}catch(cause){throwShipError.fromFetchError(cause,'Get account');}

fromHttpResponse trusts the body's error field when it's a known server-producible ErrorType — so a server's ShipError.validation(...) round-trips back to ErrorType.Validation on the client. For non-API responses (CDN errors, intermediaries) or malformed bodies it falls back to status-derived (401 → Authentication, 403 → Forbidden, 429 → RateLimit, else → Api). Client-only types (Network, Timeout, Cancelled, File, Config) are filtered out of the trusted set. Body's message and details are preserved best-effort.

fromFetchError routes by the thrown cause: an existing ShipError is returned unchanged, AbortError becomes Cancelled, TimeoutError becomes Timeout, a fetch TypeError becomes Network, anything else becomes Api (with no HTTP status — the request never reached the server). Timeout is a distinct type inside the network category — isNetworkError() is true for it — so a surface can retry it like any transport failure while still saying "timed out" rather than "check your connection".

Both helpers accept an optional operation-name string for contextual messages ("Get account was cancelled", "Get account failed: ...").

Status constants

import{DeploymentStatus,// pending | success | failed | deletingDomainStatus,// pending | partial | success | pausedAccountPlan,// free | pro | scale | sponsored — tiers only; suspension and deletion are account factsFileValidationStatus,// pending | processing_error | excluded | validation_failed | readyAuthMethod,// session | apiKey | token | agent | oauth | webhook | system}from'@shipstatic/types';

API Response Types

importtype{PlatformLimits,// per-request size limits from /limits (file size, file count, total size)Plan,PlansResponse,// the public plan menu from /plansBillingInterval,// 'month' | 'year' — Stripe's own recurring intervalCheckoutSession,BillingPortalSession,// the two hosted Stripe pagesActivityListResponse,PingResponse,}from'@shipstatic/types';

Resource contracts

SDK interface definitions:

importtype{DeploymentResource,DomainResource,AccountResource,TokenResource,}from'@shipstatic/types';

Validation utilities

import{validateApiKey,validateDeployToken,validateIdempotencyKey,validateApiUrl,isDeployment,isBlockedExtension,}from'@shipstatic/types';

isBlockedExtension(filename, blocked) takes the blocklist rather than owning one — the platform's list is hosting policy that the API owns and evolves, and it reaches clients as PlatformLimits.blockedExtensions from GET /limits. The field is optional: an API that predates it sends nothing, which means "no client-side check", never "an empty policy".

constlimits=awaitship.getLimits();isBlockedExtension('virus.exe',limits.blockedExtensions??[]);

File upload types

importtype{ValidatableFile,FileValidationResult,ValidationIssue,UploadedFile,}from'@shipstatic/types';

Domain utilities

import{isPlatformDomain,isCustomDomain,extractSubdomain,generateDeploymentUrl,generateDomainUrl,}from'@shipstatic/types';

Label utilities

import{LABEL_CONSTRAINTS,LABEL_PATTERN,serializeLabels,deserializeLabels,}from'@shipstatic/types';

Password utilities

import{PASSWORD_CONSTRAINTS,// { MIN_LENGTH: 6, MAX_LENGTH: 128 }validatePassword,// (value: unknown) => string | undefined}from'@shipstatic/types';

Constants

import{DEFAULT_API,API_KEY,// { PREFIX, HEX_LENGTH, TOTAL_LENGTH, HINT_LENGTH }DEPLOY_TOKEN,// { PREFIX, HEX_LENGTH, TOTAL_LENGTH }DEPLOYMENT_CONFIG_FILENAME,}from'@shipstatic/types';

Usage

import{ShipError,isShipError,typeDeployment,DeploymentStatus}from'@shipstatic/types';functionprocessDeployment(deployment: Deployment){if(deployment.status===DeploymentStatus.FAILED){throwShipError.business('Deployment failed');}}

Also available

Part of ShipStatic. This package is a building block; the ways to actually deploy something are listed at shipstatic.com.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages