@shipstatic/ship 1.0.2 → 2.0.0-beta.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/dist/browser.d.ts CHANGED
@@ -1,7 +1,1102 @@
1
- import * as _shipstatic_types from '@shipstatic/types';
2
- import { DeploymentUploadOptions, ProgressInfo, StaticFile, DeploymentCreateResponse, DeploymentListResponse, Deployment, DomainSetResult, DomainListResponse, Domain, DomainDnsResponse, DomainRecordsResponse, DomainValidateResponse, TokenCreateResponse, TokenListResponse, Account, PlatformLimits, DeployInput, AccountResource, DeploymentResource, DomainResource, TokenResource, ResolvedConfig, ValidatableFile, FileValidationResult } from '@shipstatic/types';
3
- export * from '@shipstatic/types';
4
- export { Account, AccountResource, DEFAULT_API, DeployInput, Deployment, DeploymentResource, Domain, DomainResource, ErrorType, FileValidationStatus as FILE_VALIDATION_STATUS, PingResponse, ResolvedConfig, ShipError, StaticFile, TokenResource } from '@shipstatic/types';
1
+ /**
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
+ */
5
+ /**
6
+ * Deployment status constants
7
+ */
8
+ declare const DeploymentStatus: {
9
+ readonly PENDING: "pending";
10
+ readonly SUCCESS: "success";
11
+ readonly FAILED: "failed";
12
+ readonly DELETING: "deleting";
13
+ };
14
+ type DeploymentStatusType = (typeof DeploymentStatus)[keyof typeof DeploymentStatus];
15
+ /**
16
+ * Core deployment object - used in both API responses and SDK
17
+ */
18
+ interface Deployment {
19
+ /** The deployment hostname (e.g., 'happy-cat-abc1234.shipstatic.com') */
20
+ readonly deployment: string;
21
+ /** Full URL to the deployment (e.g., 'https://happy-cat-abc1234.shipstatic.com') */
22
+ readonly url: string;
23
+ /** Number of files in this deployment */
24
+ readonly files: number;
25
+ /** Total size of all files in bytes */
26
+ readonly size: number;
27
+ /** Current deployment status */
28
+ status: DeploymentStatusType;
29
+ /** Whether deployment has a ship.json config */
30
+ readonly config: boolean;
31
+ /** Whether deployment has a password set */
32
+ readonly password: boolean;
33
+ /** Labels for categorization and filtering (lowercase, alphanumeric with separators). Always present, empty array when none. */
34
+ labels: string[];
35
+ /** The client/tool used to create this deployment (e.g., 'web', 'sdk', 'cli'), null if unknown */
36
+ readonly via: string | null;
37
+ /** Unix timestamp (seconds) when deployment was created */
38
+ readonly created: number;
39
+ /** Unix timestamp (seconds) when deployment expires, null if never */
40
+ expires: number | null;
41
+ /** Full URL to the deployment screenshot (e.g., 'https://screenshots.shipstatic.com/happy-cat-abc1234/a3f2c1b4d5e6f789') */
42
+ readonly screenshot: string;
43
+ }
44
+ /**
45
+ * Response from deployment creation. Extends Deployment with one-time fields
46
+ * only present on creation (not on subsequent GET requests).
47
+ */
48
+ interface DeploymentCreateResponse extends Deployment {
49
+ /** Claim URL for public deployments. Present when deployed without credentials. */
50
+ readonly claim?: string;
51
+ }
52
+ /**
53
+ * Response for listing deployments
54
+ */
55
+ interface DeploymentListResponse {
56
+ /** Array of deployments */
57
+ deployments: Deployment[];
58
+ /** Cursor for pagination, null if no more pages */
59
+ cursor: string | null;
60
+ /** Total number of deployments */
61
+ total: number;
62
+ }
63
+ /**
64
+ * Domain status constants
65
+ *
66
+ * - PENDING: DNS not configured
67
+ * - PARTIAL: DNS partially configured
68
+ * - SUCCESS: DNS fully verified
69
+ * - PAUSED: Domain paused due to plan enforcement (billing)
70
+ */
71
+ declare const DomainStatus: {
72
+ readonly PENDING: "pending";
73
+ readonly PARTIAL: "partial";
74
+ readonly SUCCESS: "success";
75
+ readonly PAUSED: "paused";
76
+ };
77
+ type DomainStatusType = (typeof DomainStatus)[keyof typeof DomainStatus];
78
+ /**
79
+ * Core domain object - used in both API responses and SDK
80
+ */
81
+ interface Domain {
82
+ /** The domain name */
83
+ readonly domain: string;
84
+ /** Full URL to the domain (e.g., 'https://www.example.com') */
85
+ readonly url: string;
86
+ /** The deployment hostname this domain points to (null = domain added but not yet linked) */
87
+ deployment: string | null;
88
+ /** Current domain status */
89
+ status: DomainStatusType;
90
+ /** Labels for categorization and filtering (lowercase, alphanumeric with separators). Always present, empty array when none. */
91
+ labels: string[];
92
+ /** Unix timestamp (seconds) when domain was created */
93
+ readonly created: number;
94
+ /** When deployment was last linked (Unix timestamp), null if never linked */
95
+ linked: number | null;
96
+ /** Total deployment links */
97
+ links: number;
98
+ }
99
+ /**
100
+ * Return shape of `domains.set()` — `Domain` plus an SDK-derived flag indicating
101
+ * whether the underlying `PUT /domains/:name` created the record (HTTP 201) or
102
+ * updated an existing one (HTTP 200).
103
+ *
104
+ * `isCreate` is not part of the wire format — the API returns a plain `Domain`
105
+ * body. The SDK derives the flag from the HTTP status code so callers (notably
106
+ * the CLI) can format different output for the create vs repoint paths without
107
+ * a second round-trip.
108
+ */
109
+ interface DomainSetResult extends Domain {
110
+ /** `true` when this call created a new domain; `false` when it updated an existing one. */
111
+ isCreate: boolean;
112
+ }
113
+ /**
114
+ * Response for listing domains
115
+ */
116
+ interface DomainListResponse {
117
+ /** Array of domains */
118
+ domains: Domain[];
119
+ /** Cursor for pagination, null if no more pages */
120
+ cursor: string | null;
121
+ /** Total number of domains */
122
+ total: number;
123
+ }
124
+ /**
125
+ * DNS record types supported for domain configuration
126
+ */
127
+ type DnsRecordType = 'A' | 'CNAME';
128
+ /**
129
+ * DNS record required for domain configuration
130
+ */
131
+ interface DnsRecord {
132
+ /** Record type (A for apex, CNAME for subdomains) */
133
+ type: DnsRecordType;
134
+ /** The DNS name to configure */
135
+ name: string;
136
+ /** The value to set (IP for A, hostname for CNAME) */
137
+ value: string;
138
+ }
139
+ /**
140
+ * DNS provider information for a domain
141
+ */
142
+ interface DnsProvider {
143
+ /** Provider name (e.g., "Cloudflare", "GoDaddy"), null if unknown */
144
+ name: string | null;
145
+ }
146
+ /**
147
+ * Response for domain DNS provider lookup
148
+ */
149
+ interface DomainDnsResponse {
150
+ /** The domain name */
151
+ domain: string;
152
+ /** DNS provider information, null if not yet looked up */
153
+ dns: {
154
+ provider?: DnsProvider;
155
+ } | null;
156
+ }
157
+ /**
158
+ * Response for domain DNS records
159
+ */
160
+ interface DomainRecordsResponse {
161
+ /** The domain name */
162
+ domain: string;
163
+ /** The apex (registered) domain where DNS records are managed */
164
+ apex: string;
165
+ /** Required DNS records for configuration */
166
+ records: DnsRecord[];
167
+ }
168
+ /**
169
+ * Response for domain validation
170
+ */
171
+ interface DomainValidateResponse {
172
+ /** Whether the domain is valid */
173
+ valid: boolean;
174
+ /** Normalized domain name, null when invalid */
175
+ normalized: string | null;
176
+ /** Whether the domain is available, null when invalid */
177
+ available: boolean | null;
178
+ /** Error message, null when valid */
179
+ error: string | null;
180
+ }
181
+ /**
182
+ * Token as returned by the list endpoint.
183
+ * The secret is shown once at creation and never again — listings carry
184
+ * only the management identifier and lifecycle metadata.
185
+ */
186
+ interface TokenListItem {
187
+ /** 7-char management identifier (e.g., "a1b2c3d") */
188
+ readonly token: string;
189
+ /** Labels for categorization and filtering. Always present, empty array when none. */
190
+ labels: string[];
191
+ /** Unix timestamp (seconds) when token was created */
192
+ readonly created: number;
193
+ /** Unix timestamp (seconds) when token expires, null for never */
194
+ readonly expires: number | null;
195
+ /** Unix timestamp (seconds) of the last request authenticated with this token, null if never used */
196
+ readonly used: number | null;
197
+ }
198
+ /**
199
+ * Response for listing tokens
200
+ */
201
+ interface TokenListResponse {
202
+ /** Array of tokens (security-redacted for list display) */
203
+ tokens: TokenListItem[];
204
+ /** Total number of tokens */
205
+ total: number;
206
+ }
207
+ /**
208
+ * Response for token creation
209
+ */
210
+ interface TokenCreateResponse {
211
+ /** 7-char management identifier */
212
+ token: string;
213
+ /** The raw credential value (shown once at creation, then never again) */
214
+ secret: string;
215
+ /** Labels for categorization and filtering. Always present, empty array when none. */
216
+ labels: string[];
217
+ /** Unix timestamp (seconds) when token expires, null for never */
218
+ expires: number | null;
219
+ }
220
+ /**
221
+ * Account plan constants
222
+ */
223
+ declare const AccountPlan: {
224
+ readonly FREE: "free";
225
+ readonly STANDARD: "standard";
226
+ readonly SPONSORED: "sponsored";
227
+ readonly ENTERPRISE: "enterprise";
228
+ readonly SUSPENDED: "suspended";
229
+ readonly TERMINATING: "terminating";
230
+ readonly TERMINATED: "terminated";
231
+ };
232
+ type AccountPlanType = (typeof AccountPlan)[keyof typeof AccountPlan];
233
+ /**
234
+ * Account usage metrics — always available regardless of billing provider.
235
+ */
236
+ interface AccountUsage {
237
+ /** Number of active custom domains (excludes paused) */
238
+ customDomains: number;
239
+ }
240
+ /**
241
+ * Core account object - used in both API responses and SDK
242
+ * All fields are readonly to prevent accidental mutations
243
+ */
244
+ interface Account {
245
+ /** User email address */
246
+ readonly email: string;
247
+ /** User display name, null if not set */
248
+ readonly name: string | null;
249
+ /** User profile picture URL, null if not set */
250
+ readonly picture: string | null;
251
+ /** Account plan status */
252
+ readonly plan: AccountPlanType;
253
+ /** Account usage metrics (custom domains, etc.) */
254
+ readonly usage: AccountUsage;
255
+ /** Unix timestamp (seconds) when account was created */
256
+ readonly created: number;
257
+ /** Unix timestamp (seconds) when account was activated (first deployment), null if not yet activated */
258
+ readonly activated: number | null;
259
+ /** Last 4 characters of the API key for identification, null when no key generated */
260
+ readonly hint: string | null;
261
+ /** Grace period expiration (unix seconds), null if no grace period active */
262
+ readonly grace: number | null;
263
+ }
264
+ /**
265
+ * Account as returned by `GET /account` — the entity plus how the request
266
+ * was authorized, so `whoami` can answer "what credential am I holding?".
267
+ * Request-scoped fields live on the response type, never on the entity
268
+ * (the `DeploymentCreateResponse` pattern).
269
+ */
270
+ interface AccountGetResponse extends Account {
271
+ /** How the request that produced this response was authorized. */
272
+ readonly authMethod: AuthMethodType;
273
+ /** Present (and true) only when the caller is an operator acting as themselves. */
274
+ readonly isAdmin?: true;
275
+ /** Present only during read-only admin impersonation: the operator's account id. */
276
+ readonly impersonatedBy?: string;
277
+ }
278
+ /**
279
+ * Account-specific configuration overrides
280
+ * Allows per-account customization of limits without changing plan
281
+ */
282
+ interface AccountOverrides {
283
+ /** Override for maximum number of domains */
284
+ domains?: number;
285
+ /** Override for maximum number of deployments */
286
+ deployments?: number;
287
+ /** Override for maximum individual file size in bytes */
288
+ fileSize?: number;
289
+ /** Override for maximum number of files per deployment */
290
+ filesCount?: number;
291
+ /** Override for maximum total deployment size in bytes */
292
+ totalSize?: number;
293
+ }
294
+ /**
295
+ * All possible error types in the ShipStatic platform.
296
+ *
297
+ * Developer-friendly key names map to stable wire-format string values.
298
+ * Both the value and the type are exported under the same name so callers
299
+ * can use `ErrorType.Validation` (value comparison) and `: ErrorType` (type
300
+ * annotation) without ceremony — matching the pattern other status objects
301
+ * (`DeploymentStatus`, `DomainStatus`, `AccountPlan`, `AuthMethod`) follow.
302
+ */
303
+ declare const ErrorType: {
304
+ /** Validation failed (400). Input shape is wrong. */
305
+ readonly Validation: "validation_failed";
306
+ /** Resource not found (404). */
307
+ readonly NotFound: "not_found";
308
+ /** Authenticated but not allowed (403). User lacks permission for this action. */
309
+ readonly Forbidden: "forbidden";
310
+ /** Rate limit exceeded (429). */
311
+ readonly RateLimit: "rate_limit_exceeded";
312
+ /** Authentication required or failed (401). Missing/invalid credentials. */
313
+ readonly Authentication: "authentication_failed";
314
+ /** Business rule violation. Catch-all for 4xx state-rule errors that aren't more specific. */
315
+ readonly Business: "business_logic_error";
316
+ /** API server error (500). Generic server-side fault. */
317
+ readonly Api: "internal_server_error";
318
+ /** Network/connection error. Client-side only — set by HTTP clients on fetch failure; never produced server-side. */
319
+ readonly Network: "network_error";
320
+ /** Operation was cancelled. Client-side only — set on `AbortSignal` abort; never produced server-side. */
321
+ readonly Cancelled: "operation_cancelled";
322
+ /** File operation error. Client-side only — set by SDK during local file processing; never produced server-side. */
323
+ readonly File: "file_error";
324
+ /** Configuration error. Client-side only — set by SDK during config parsing/validation; never produced server-side. */
325
+ readonly Config: "config_error";
326
+ };
327
+ type ErrorType = (typeof ErrorType)[keyof typeof ErrorType];
328
+ /**
329
+ * Standard error response format used everywhere
330
+ */
331
+ interface ErrorResponse {
332
+ /** Error type identifier */
333
+ error: ErrorType;
334
+ /** Human-readable error message */
335
+ message: string;
336
+ /** HTTP status code (API contexts) */
337
+ status?: number;
338
+ /** Optional additional error details. Untyped by design — narrow at the read site. */
339
+ details?: unknown;
340
+ }
341
+ /**
342
+ * Simple unified error class for both API and SDK
343
+ */
344
+ declare class ShipError extends Error {
345
+ readonly type: ErrorType;
346
+ readonly status?: number | undefined;
347
+ readonly details?: unknown | undefined;
348
+ constructor(type: ErrorType, message: string, status?: number | undefined, details?: unknown | undefined);
349
+ /** Convert to wire format */
350
+ toResponse(): ErrorResponse;
351
+ /**
352
+ * Construct a `ShipError` from an HTTP error response.
353
+ *
354
+ * Best-effort body parse for `{ message, error?, details? }`. Message
355
+ * resolution: `body.message` → `body.error` → `"<operationName> failed with
356
+ * status <N>"`.
357
+ *
358
+ * Type resolution: trusts `body.error` when it's a known server-producible
359
+ * `ErrorType` (preserves the wire's intent — server's
360
+ * `ShipError.validation(...)` round-trips back to `ErrorType.Validation`
361
+ * on the client). Falls back to status-derived (401 → Authentication,
362
+ * 403 → Forbidden, 429 → RateLimit, else → Api) for non-API responses
363
+ * (CDN errors, intermediaries) or malformed bodies. Client-only types
364
+ * (`Network`, `Cancelled`, `File`, `Config`) are filtered out of the
365
+ * trusted set — a misbehaving server claiming one of those is ignored.
366
+ *
367
+ * `operationName` (e.g. `"Get account"`) is used to compose the fallback
368
+ * message. Defaults to `"Request"`. Same convention as `fromFetchError`.
369
+ *
370
+ * Async because it reads the response body. Returns rather than throws so
371
+ * callers can compose; most will `throw await ShipError.fromHttpResponse(...)`.
372
+ */
373
+ static fromHttpResponse(response: Response, operationName?: string): Promise<ShipError>;
374
+ /**
375
+ * Construct a `ShipError` from an error caught around a `fetch()` call.
376
+ *
377
+ * The mirror of `fromHttpResponse` for the *other* side of the HTTP error
378
+ * story — the network layer failing (offline, CORS, abort) rather than the
379
+ * server returning a non-OK response.
380
+ *
381
+ * Routing:
382
+ * - Already a `ShipError` → returned as-is (caller's intent preserved)
383
+ * - `AbortError` → `ShipError.cancelled(...)`
384
+ * - `TypeError` whose message mentions "fetch" → `ShipError.network(...)`
385
+ * - Any other `Error` → `ShipError(Api, ...)` (no HTTP status — fetch never reached the server)
386
+ * - Anything else (string, undefined, etc.) → `ShipError(Api, ...)`
387
+ *
388
+ * The optional `operationName` is composed into the message for context:
389
+ * `"Get account was cancelled"`, `"Get account failed: ..."`. Defaults to
390
+ * `"Request"` when omitted.
391
+ */
392
+ static fromFetchError(cause: unknown, operationName?: string): ShipError;
393
+ static validation(message: string, details?: unknown): ShipError;
394
+ static notFound(resource: string, id?: string): ShipError;
395
+ static forbidden(message: string, details?: unknown): ShipError;
396
+ static rateLimit(message?: string, details?: unknown): ShipError;
397
+ /**
398
+ * Construct an Authentication (401) error.
399
+ *
400
+ * **Telemetry pattern — `details: { internal: '<tag>' }`.** When the
401
+ * server creates an auth error with an `internal` key in `details`
402
+ * (e.g. `{ internal: 'session_invalid' }`), `toResponse()` strips the
403
+ * entire `details` object before serialization. This keeps the wire
404
+ * response a clean "Authentication failed" while preserving granular
405
+ * server-side telemetry (which strategy/check failed) for logs and tests.
406
+ *
407
+ * Use this pattern in API auth code; do not put client-visible info under
408
+ * `internal`. Other `details` keys round-trip normally.
409
+ */
410
+ static authentication(message?: string, details?: unknown): ShipError;
411
+ static business(message: string, status?: number, details?: unknown): ShipError;
412
+ static network(message: string, details?: unknown): ShipError;
413
+ static cancelled(message: string, details?: unknown): ShipError;
414
+ static file(message: string, details?: unknown): ShipError;
415
+ static config(message: string, details?: unknown): ShipError;
416
+ static api(message: string, status?: number, details?: unknown): ShipError;
417
+ isClientError(): boolean;
418
+ isNetworkError(): boolean;
419
+ isAuthError(): boolean;
420
+ isType(errorType: ErrorType): boolean;
421
+ }
422
+ /**
423
+ * Type guard to check if an unknown value is a ShipError.
424
+ *
425
+ * Uses structural checking instead of instanceof to handle module duplication
426
+ * in bundled applications where multiple copies of the ShipError class may exist.
427
+ *
428
+ * @example
429
+ * if (isShipError(error)) {
430
+ * console.log(error.status, error.message);
431
+ * }
432
+ */
433
+ declare function isShipError(error: unknown): error is ShipError;
434
+ /**
435
+ * Plan-based platform limits returned by the `/limits` endpoint.
436
+ *
437
+ * The SDK fetches these once on first API call to drive client-side
438
+ * file-size / file-count / total-size validation that mirrors what the API
439
+ * would enforce server-side. Limits vary by account plan.
440
+ *
441
+ * These are the *platform's* posted caps for the current account — server
442
+ * truth delivered at runtime, never hard-coded on the client.
443
+ */
444
+ interface PlatformLimits {
445
+ /** Maximum size in bytes for a single file. */
446
+ maxFileSize: number;
447
+ /** Maximum number of files in a single deployment. */
448
+ maxFilesCount: number;
449
+ /** Maximum total size in bytes across all files in a deployment. */
450
+ maxTotalSize: number;
451
+ }
452
+ /**
453
+ * Blocked file extensions — files that cannot be uploaded.
454
+ *
455
+ * We accept any file type by default and derive Content-Type from the
456
+ * extension at serve time (via mime-db in the API worker). Unknown extensions
457
+ * are served as `application/octet-stream` with `X-Content-Type-Options: nosniff`.
458
+ *
459
+ * The blocklist targets file types that pose direct security risks when hosted:
460
+ * executables, disk images, malware vectors, dangerous scripts, and shortcuts.
461
+ */
462
+ declare const BLOCKED_EXTENSIONS: ReadonlySet<string>;
463
+ /**
464
+ * Check if a filename has a blocked extension.
465
+ * Extracts the extension from the filename and checks against the blocklist.
466
+ * Case-insensitive. Returns false for files without extensions.
467
+ *
468
+ * @example
469
+ * isBlockedExtension('virus.exe') // true
470
+ * isBlockedExtension('app.dmg') // true
471
+ * isBlockedExtension('style.css') // false
472
+ * isBlockedExtension('data.custom') // false
473
+ * isBlockedExtension('README') // false
474
+ */
475
+ declare function isBlockedExtension(filename: string): boolean;
476
+ /**
477
+ * Characters that are unsafe in filenames for static hosting.
478
+ *
479
+ * Blocks only characters that genuinely break the upload→serve round-trip:
480
+ * - # ? % URL round-trip breakers (fragment, query, encoding ambiguity)
481
+ * - \ Path separator confusion (upload splits on backslash)
482
+ * - < > " XSS vectors with zero legitimate use in filenames
483
+ * - \x00-\x1f \x7f Control characters (header injection, display corruption)
484
+ *
485
+ * Everything else is allowed — browser percent-encodes, Worker decodes, R2 matches.
486
+ */
487
+ declare const UNSAFE_FILENAME_CHARS: RegExp;
488
+ /**
489
+ * Check if a filename contains unsafe characters.
490
+ *
491
+ * @example
492
+ * hasUnsafeChars('saved_resource(1).html') // false — parentheses are safe
493
+ * hasUnsafeChars('page[slug].js') // false — brackets are safe
494
+ * hasUnsafeChars('file#anchor.html') // true — # breaks URL resolution
495
+ * hasUnsafeChars('file<tag>.html') // true — < is an XSS vector
496
+ */
497
+ declare function hasUnsafeChars(filename: string): boolean;
498
+ /**
499
+ * Path segment names that indicate an unbuilt project was uploaded instead of build output.
500
+ * Used for early detection in CLI, browser, and server validation.
501
+ */
502
+ declare const UNBUILT_PROJECT_MARKERS: ReadonlySet<string>;
503
+ /**
504
+ * Check if a file path contains an unbuilt project marker.
505
+ *
506
+ * @example
507
+ * hasUnbuiltMarker('node_modules/react/index.js') // true
508
+ * hasUnbuiltMarker('package.json') // true
509
+ * hasUnbuiltMarker('dist/index.html') // false
510
+ */
511
+ declare function hasUnbuiltMarker(filePath: string): boolean;
512
+ /**
513
+ * Simple ping response for health checks
514
+ */
515
+ interface PingResponse {
516
+ /** Always true if service is healthy */
517
+ success: boolean;
518
+ /** Optional timestamp */
519
+ timestamp?: number;
520
+ }
521
+ /**
522
+ * How a request (or recorded activity) was authorized.
523
+ *
524
+ * Client populations: `SESSION` (first-party cookie), `API_KEY` (`ship-`
525
+ * key), `TOKEN` (`deploy-` deploy token), `AGENT` (anonymous public deploy —
526
+ * no credential; the platform grants the public-account identity per
527
+ * request), `OAUTH` (delegated access token). Server populations: `WEBHOOK`
528
+ * (signed webhook processing), `SYSTEM` (scheduled/background jobs).
529
+ */
530
+ declare const AuthMethod: {
531
+ readonly SESSION: "session";
532
+ readonly API_KEY: "apiKey";
533
+ readonly TOKEN: "token";
534
+ readonly AGENT: "agent";
535
+ readonly OAUTH: "oauth";
536
+ readonly WEBHOOK: "webhook";
537
+ readonly SYSTEM: "system";
538
+ };
539
+ type AuthMethodType = (typeof AuthMethod)[keyof typeof AuthMethod];
540
+ /**
541
+ * Shape constants for API keys (`ship-{64 hex chars}`).
542
+ * Single source of truth used by validation utilities and auth middleware.
543
+ */
544
+ declare const API_KEY: {
545
+ /** Prefix that identifies an API key. */
546
+ readonly PREFIX: "ship-";
547
+ /** Number of hex characters following the prefix. */
548
+ readonly HEX_LENGTH: 64;
549
+ /** Total length of an API key including prefix (`PREFIX.length + HEX_LENGTH = 69`). */
550
+ readonly TOTAL_LENGTH: 69;
551
+ /** Number of trailing characters used to display a redacted hint (e.g. last 4). */
552
+ readonly HINT_LENGTH: 4;
553
+ };
554
+ /**
555
+ * Shape constants for deploy tokens (`deploy-{64 hex chars}`).
556
+ * Single source of truth used by validation utilities and auth middleware.
557
+ */
558
+ declare const DEPLOY_TOKEN: {
559
+ /** Prefix that identifies a deploy token. */
560
+ readonly PREFIX: "deploy-";
561
+ /** Number of hex characters following the prefix. */
562
+ readonly HEX_LENGTH: 64;
563
+ /** Total length of a deploy token including prefix (`PREFIX.length + HEX_LENGTH = 71`). */
564
+ readonly TOTAL_LENGTH: 71;
565
+ };
566
+ /**
567
+ * Shape constants for caller identifiers (the `X-Caller` instance-identity
568
+ * header — rate-limit bucketing for multi-tenant orchestrators). The API
569
+ * normalizes case and silently ignores malformed values (the header is
570
+ * unauthenticated); clients validate at the boundary via `validateCaller`,
571
+ * so a value the server would drop fails fast instead.
572
+ */
573
+ declare const CALLER: {
574
+ /** HTTP header name. */
575
+ readonly HEADER: "X-Caller";
576
+ /** Maximum identifier length. */
577
+ readonly MAX_LENGTH: 128;
578
+ /** Allowed characters: alphanumeric, dot, underscore, hyphen. */
579
+ readonly PATTERN: RegExp;
580
+ };
581
+ /**
582
+ * Token populations distinguishable by shape. The platform carries every
583
+ * client token in one wire slot (`Authorization: Bearer <value>`) and
584
+ * classifies by value, never by a side channel — this is the classifier.
585
+ *
586
+ * `API_KEY` and `DEPLOY_TOKEN` *are* `AuthMethod.API_KEY` and
587
+ * `AuthMethod.TOKEN` — the equality is structural, so a classification flows
588
+ * straight into an auth method and the pair can never drift. `OPAQUE` is any
589
+ * other value — shape says nothing about it, so only a lookup can. Today the
590
+ * server refuses every opaque bearer; the OAuth access-token population
591
+ * resolves there when the authorization server ships.
592
+ */
593
+ declare const TokenKind: {
594
+ readonly API_KEY: "apiKey";
595
+ readonly DEPLOY_TOKEN: "token";
596
+ readonly OPAQUE: "opaque";
597
+ };
598
+ type TokenKindType = (typeof TokenKind)[keyof typeof TokenKind];
599
+ /**
600
+ * Classify a client token by shape. The single dispatch used by both sides
601
+ * of the wire: API auth middleware (which population is this credential?)
602
+ * and SDK validation (which format rules apply before sending?). Sharing it
603
+ * is what guarantees client and server can never disagree on dispatch.
604
+ */
605
+ declare function classifyToken(token: string): TokenKindType;
606
+ /**
607
+ * OAuth scope vocabulary for delegated third-party access tokens.
608
+ * Single source of truth used by the authorization server (advertised in
609
+ * `scopes_supported`), the API's scope-enforcement middleware, and consent UI
610
+ * copy. The standard `offline_access` scope (refresh tokens) is not platform
611
+ * vocabulary and is deliberately absent — the middleware never checks it.
612
+ *
613
+ * Deliberately absent by design: any `tokens:*` scope, `account:write`, or
614
+ * admin scope — a delegated app must never mint credentials, delete the
615
+ * account, or act as admin.
616
+ */
617
+ declare const OAuthScope: {
618
+ readonly ACCOUNT_READ: "account:read";
619
+ readonly DEPLOYMENTS_READ: "deployments:read";
620
+ readonly DEPLOYMENTS_WRITE: "deployments:write";
621
+ readonly DOMAINS_READ: "domains:read";
622
+ readonly DOMAINS_WRITE: "domains:write";
623
+ };
624
+ type OAuthScopeType = (typeof OAuthScope)[keyof typeof OAuthScope];
625
+ declare const DEPLOYMENT_CONFIG_FILENAME = "ship.json";
626
+ /** Default ship.json config for SPA routing. Single source of truth — used by both API and SDK. */
627
+ declare const SPA_DEFAULT_CONFIG: {
628
+ readonly rewrites: readonly [{
629
+ readonly source: "/(.*)";
630
+ readonly destination: "/index.html";
631
+ }];
632
+ };
633
+ /**
634
+ * Validate API key format
635
+ */
636
+ declare function validateApiKey(apiKey: string): void;
637
+ /**
638
+ * Validate deploy token format
639
+ */
640
+ declare function validateDeployToken(deployToken: string): void;
641
+ /**
642
+ * Validate a client token of any population. Classifies by shape and applies
643
+ * the matching format rules: `ship-` keys and `deploy-` deploy tokens are
644
+ * validated strictly; opaque tokens (OAuth access tokens, future populations)
645
+ * only need to be non-empty — their validity is the server's to decide.
646
+ */
647
+ declare function validateToken(token: string): void;
648
+ /**
649
+ * Validate a caller identifier against the `CALLER` shape. The server
650
+ * silently ignores malformed values (the header is unauthenticated); clients
651
+ * call this at configuration time so the drop never silently happens.
652
+ */
653
+ declare function validateCaller(caller: string): void;
654
+ /**
655
+ * Validate API URL format
656
+ */
657
+ declare function validateApiUrl(apiUrl: string): void;
658
+ /**
659
+ * Check if a string matches the deployment identifier pattern (word-word-alphanumeric7).
660
+ * Example: "happy-cat-abc1234.shipstatic.com"
661
+ */
662
+ declare function isDeployment(input: string): boolean;
663
+ /**
664
+ * Request payload for SPA check endpoint
665
+ */
666
+ interface SPACheckRequest {
667
+ /** Array of file paths */
668
+ files: string[];
669
+ /** HTML content of index.html file */
670
+ index: string;
671
+ }
672
+ /**
673
+ * Response from SPA check endpoint
674
+ */
675
+ interface SPACheckResponse {
676
+ /** Whether the project is detected as a Single Page Application */
677
+ isSPA: boolean;
678
+ /** Debugging information about detection */
679
+ debug: {
680
+ /** Which tier made the detection: 'exclusions', 'inclusions', 'scoring', 'ai', or 'fallback' */
681
+ tier: 'exclusions' | 'inclusions' | 'scoring' | 'ai' | 'fallback';
682
+ /** The reason for the detection result */
683
+ reason: string;
684
+ };
685
+ }
686
+ /**
687
+ * Represents a file that has been processed and is ready for deploy.
688
+ * Used across the platform (API, SDK, CLI) for file operations.
689
+ */
690
+ interface StaticFile {
691
+ /**
692
+ * The content of the file.
693
+ * In Node.js, this is typically a `Buffer`.
694
+ * In the browser, this is typically a `File` or `Blob` object.
695
+ */
696
+ content: File | Buffer | Blob;
697
+ /**
698
+ * The desired path for the file on the server, relative to the deployment root.
699
+ * Should include the filename, e.g., `images/photo.jpg`.
700
+ */
701
+ path: string;
702
+ /**
703
+ * The original absolute file system path (primarily used in Node.js environments).
704
+ * This helps in debugging or associating the server path back to its source.
705
+ */
706
+ filePath?: string;
707
+ /**
708
+ * The MD5 hash (checksum) of the file's content.
709
+ * This is calculated by the SDK before deploy if not provided.
710
+ */
711
+ md5?: string;
712
+ /** The size of the file in bytes. */
713
+ size: number;
714
+ }
715
+ /**
716
+ * Progress information for deploy/upload operations.
717
+ * Provides consistent percentage-based progress with byte-level details.
718
+ */
719
+ interface ProgressInfo {
720
+ /** Progress percentage (0-100) */
721
+ percent: number;
722
+ /** Number of bytes loaded so far */
723
+ loaded: number;
724
+ /** Total number of bytes to load. May be 0 if unknown initially */
725
+ total: number;
726
+ /** Current file being processed (optional) */
727
+ file?: string;
728
+ }
729
+ /** Default API URL if not otherwise configured. */
730
+ declare const DEFAULT_API = "https://api.shipstatic.com";
731
+ /**
732
+ * Universal deploy input — the union of every shape the SDK accepts.
733
+ *
734
+ * - **Browser**: `File[]` (typically from `<input type="file">` or drag-and-drop)
735
+ * - **Node**: `string | string[]` (file or directory path(s) on disk; directories are walked)
736
+ *
737
+ * Each platform's SDK narrows its `deploy()` signature to the relevant shape
738
+ * and rejects anything else at runtime. Use the structural types directly
739
+ * (`File[]`, `string | string[]`) when writing platform-specific code.
740
+ */
741
+ type DeployInput = File[] | string | string[];
742
+ /**
743
+ * Options for deployment creation at the API contract level.
744
+ * SDK implementations may extend with additional options (timeout, signal, callbacks, etc.).
745
+ */
746
+ interface DeploymentUploadOptions {
747
+ /** Optional labels for categorization and filtering */
748
+ labels?: string[];
749
+ /** Client identifier (e.g., 'cli', 'sdk', 'web') */
750
+ via?: string;
751
+ /**
752
+ * Optional password that protects this deployment.
753
+ *
754
+ * Length: {@link PASSWORD_CONSTRAINTS.MIN_LENGTH} to
755
+ * {@link PASSWORD_CONSTRAINTS.MAX_LENGTH} characters. Leading and trailing
756
+ * whitespace is trimmed before validation; internal whitespace is
757
+ * significant. Visitors are prompted to enter the password before they can
758
+ * view the deployment — including on any custom domains pointing at it.
759
+ * To remove protection, redeploy without a password.
760
+ */
761
+ password?: string;
762
+ /** @internal Trigger server-side build. Only available via /upload endpoint. */
763
+ build?: boolean;
764
+ /** @internal Trigger server-side prerender. Only available via /upload endpoint. */
765
+ prerender?: boolean;
766
+ /** @internal Trigger server-side SPA detection. Only available via /upload endpoint. */
767
+ spa?: boolean;
768
+ /** @internal reCAPTCHA proof for the anonymous human deploy channel. Only available via /upload endpoint. */
769
+ captcha?: string;
770
+ }
771
+ /**
772
+ * Deployment resource interface - the contract all implementations must follow
773
+ */
774
+ interface DeploymentResource {
775
+ upload: (input: DeployInput, options?: DeploymentUploadOptions) => Promise<DeploymentCreateResponse>;
776
+ list: () => Promise<DeploymentListResponse>;
777
+ get: (id: string) => Promise<Deployment>;
778
+ set: (id: string, options: {
779
+ labels: string[];
780
+ }) => Promise<Deployment>;
781
+ remove: (id: string) => Promise<void>;
782
+ }
783
+ /**
784
+ * Domain resource interface - the contract all implementations must follow
785
+ */
786
+ interface DomainResource {
787
+ set: (name: string, options?: {
788
+ deployment?: string;
789
+ labels?: string[];
790
+ }) => Promise<DomainSetResult>;
791
+ list: () => Promise<DomainListResponse>;
792
+ get: (name: string) => Promise<Domain>;
793
+ remove: (name: string) => Promise<void>;
794
+ verify: (name: string) => Promise<{
795
+ message: string;
796
+ }>;
797
+ validate: (name: string) => Promise<DomainValidateResponse>;
798
+ dns: (name: string) => Promise<DomainDnsResponse>;
799
+ records: (name: string) => Promise<DomainRecordsResponse>;
800
+ share: (name: string) => Promise<{
801
+ domain: string;
802
+ hash: string;
803
+ }>;
804
+ }
805
+ /**
806
+ * Account resource interface - the contract all implementations must follow
807
+ */
808
+ interface AccountResource {
809
+ get: () => Promise<AccountGetResponse>;
810
+ }
811
+ /**
812
+ * Token resource interface - the contract all implementations must follow
813
+ */
814
+ interface TokenResource {
815
+ create: (options?: {
816
+ ttl?: number;
817
+ labels?: string[];
818
+ }) => Promise<TokenCreateResponse>;
819
+ list: () => Promise<TokenListResponse>;
820
+ remove: (token: string) => Promise<void>;
821
+ }
822
+ /**
823
+ * Billing status response from GET /billing/status
824
+ *
825
+ * Note: The user's `plan` comes from Account, not here.
826
+ * This endpoint only returns billing-specific data (usage, portal, etc.)
827
+ *
828
+ * If `billing` is null, the user has no active billing.
829
+ */
830
+ interface BillingStatus {
831
+ /** Creem billing ID, or null if no active billing */
832
+ billing: string | null;
833
+ /** Number of billing units (1 unit = 1 custom domain), null if no billing */
834
+ units: number | null;
835
+ /** Billing status from Creem (active, trialing, canceled, etc.), null if no billing */
836
+ status: string | null;
837
+ /** Link to Creem customer portal for billing management, null if unavailable */
838
+ portal: string | null;
839
+ }
840
+ /**
841
+ * Checkout session response from POST /billing/checkout
842
+ */
843
+ interface CheckoutSession {
844
+ /** URL to redirect user to Creem checkout page */
845
+ url: string;
846
+ }
847
+ /**
848
+ * All activity event types logged in the system.
849
+ * Uses dot notation consistently: {resource}.{action}
850
+ */
851
+ type ActivityEvent = 'account.create' | 'account.update' | 'account.delete' | 'account.key.generate' | 'account.plan.paid' | 'account.plan.transition' | 'account.suspended' | 'deployment.create' | 'deployment.update' | 'deployment.delete' | 'deployment.claim' | 'deployment.flagged' | 'domain.create' | 'domain.update' | 'domain.delete' | 'domain.verify' | 'token.create' | 'token.consume' | 'admin.account.plan.update' | 'admin.account.ref.update' | 'admin.account.billing.update' | 'admin.account.labels.update' | 'admin.deployment.delete' | 'admin.domain.delete' | 'admin.billing.sync' | 'admin.billing.terminated' | 'admin.impersonate' | 'billing.active' | 'billing.canceled' | 'billing.paused' | 'billing.expired' | 'billing.paid' | 'billing.trialing' | 'billing.scheduled_cancel' | 'billing.unpaid' | 'billing.update' | 'billing.past_due' | 'refund.created' | 'dispute.created' | 'billing.sync' | 'billing.stale' | 'billing.race';
852
+ /**
853
+ * Activity events visible to users in the dashboard
854
+ */
855
+ type UserVisibleActivityEvent = 'account.create' | 'account.update' | 'account.delete' | 'account.key.generate' | 'account.plan.transition' | 'deployment.create' | 'deployment.update' | 'deployment.delete' | 'deployment.claim' | 'domain.create' | 'domain.update' | 'domain.delete' | 'domain.verify' | 'token.create' | 'token.consume';
856
+ /**
857
+ * Activity record returned from the API
858
+ */
859
+ interface Activity {
860
+ /** The event type */
861
+ event: ActivityEvent;
862
+ /** Unix timestamp (seconds) when the activity occurred */
863
+ created: number;
864
+ /** Associated deployment ID (if applicable) */
865
+ deployment?: string;
866
+ /** Associated domain name (if applicable) */
867
+ domain?: string;
868
+ /** JSON-encoded metadata (parse with JSON.parse) */
869
+ meta?: string;
870
+ }
871
+ /**
872
+ * Parsed activity metadata.
873
+ * Different events populate different fields.
874
+ */
875
+ interface ActivityMeta {
876
+ /** Number of files in deployment */
877
+ files?: number;
878
+ /** Total size in bytes */
879
+ size?: number;
880
+ /** Whether deployment has a ship.json config */
881
+ hasConfig?: boolean;
882
+ /** Whether deployment has a password set */
883
+ hasPassword?: boolean;
884
+ /** Whether this was an update (vs create) */
885
+ isUpdate?: boolean;
886
+ /** Whether domain was already verified */
887
+ wasVerified?: boolean;
888
+ /** Previous deployment ID before relinking */
889
+ previousDeployment?: string;
890
+ /** Labels that were set/updated */
891
+ labels?: string[];
892
+ /** OAuth provider name */
893
+ provider?: string;
894
+ /** Account email */
895
+ email?: string;
896
+ /** Account display name */
897
+ name?: string;
898
+ /** Previous plan */
899
+ from?: string;
900
+ /** New plan */
901
+ to?: string;
902
+ /** Allow additional fields for future use */
903
+ [key: string]: unknown;
904
+ }
905
+ /**
906
+ * Response from GET /activities endpoint
907
+ */
908
+ interface ActivityListResponse {
909
+ /** Array of activities */
910
+ activities: Activity[];
911
+ }
912
+ /**
913
+ * File status constants for validation state tracking
914
+ */
915
+ declare const FileValidationStatus: {
916
+ /** File is pending validation */
917
+ readonly PENDING: "pending";
918
+ /** File failed during processing (before validation) */
919
+ readonly PROCESSING_ERROR: "processing_error";
920
+ /** File was excluded by validation warning (not an error) */
921
+ readonly EXCLUDED: "excluded";
922
+ /** File failed validation (blocks deployment) */
923
+ readonly VALIDATION_FAILED: "validation_failed";
924
+ /** File passed validation and is ready for deployment */
925
+ readonly READY: "ready";
926
+ };
927
+ type FileValidationStatusType = (typeof FileValidationStatus)[keyof typeof FileValidationStatus];
928
+ /**
929
+ * A validation issue with a display-ready message
930
+ *
931
+ * Issues are either errors (in errors[] array) or warnings (in warnings[] array).
932
+ * The array position determines severity - no need to duplicate it in the object.
933
+ */
934
+ interface ValidationIssue {
935
+ /** File path that triggered this issue */
936
+ file: string;
937
+ /** Display-ready message explaining the issue */
938
+ message: string;
939
+ }
940
+ /**
941
+ * Minimal file interface required for validation
942
+ */
943
+ interface ValidatableFile {
944
+ name: string;
945
+ size: number;
946
+ status?: FileValidationStatusType;
947
+ statusMessage?: string;
948
+ }
949
+ /**
950
+ * File validation result with severity-based issue reporting
951
+ *
952
+ * Validation checks files against constraints and categorizes issues by severity:
953
+ * - **Errors**: Block deployment (file too large, invalid type, etc.)
954
+ * - **Warnings**: Exclude files but allow deployment (empty files, etc.)
955
+ *
956
+ * @example
957
+ * ```typescript
958
+ * const result = validateFiles(files, config);
959
+ *
960
+ * if (!result.canDeploy) {
961
+ * // Has errors - must fix before deploying
962
+ * console.error('Deployment blocked:', result.errors);
963
+ * } else if (result.warnings.length > 0) {
964
+ * // Has warnings - deployment proceeds, some files excluded
965
+ * console.warn('Files excluded:', result.warnings);
966
+ * deploy(result.validFiles);
967
+ * } else {
968
+ * // All files valid
969
+ * deploy(result.validFiles);
970
+ * }
971
+ * ```
972
+ */
973
+ interface FileValidationResult<T extends ValidatableFile> {
974
+ /** All files with updated status */
975
+ files: T[];
976
+ /** Files ready for deployment (status: 'ready') */
977
+ validFiles: T[];
978
+ /** Blocking errors that prevent deployment */
979
+ errors: ValidationIssue[];
980
+ /** Non-blocking warnings (files excluded but deployment allowed) */
981
+ warnings: ValidationIssue[];
982
+ /** Whether deployment can proceed (true if errors.length === 0) */
983
+ canDeploy: boolean;
984
+ }
985
+ /**
986
+ * Represents a file that has been uploaded and stored
987
+ */
988
+ interface UploadedFile {
989
+ key: string;
990
+ etag: string;
991
+ size: number;
992
+ validated?: boolean;
993
+ }
994
+ /**
995
+ * Check if a domain is a platform domain (subdomain of our platform).
996
+ * Platform domains are free and don't require DNS verification.
997
+ *
998
+ * @example isPlatformDomain("www.shipstatic.com", "shipstatic.com") → true
999
+ * @example isPlatformDomain("example.com", "shipstatic.com") → false
1000
+ */
1001
+ declare function isPlatformDomain(domain: string, platformDomain: string): boolean;
1002
+ /**
1003
+ * Check if a domain is a custom domain (not a platform subdomain).
1004
+ * Custom domains are billable and require DNS verification.
1005
+ *
1006
+ * @example isCustomDomain("example.com", "shipstatic.com") → true
1007
+ * @example isCustomDomain("www.shipstatic.com", "shipstatic.com") → false
1008
+ */
1009
+ declare function isCustomDomain(domain: string, platformDomain: string): boolean;
1010
+ /**
1011
+ * Extract subdomain from a platform domain.
1012
+ * Returns null if not a platform domain.
1013
+ *
1014
+ * @example extractSubdomain("www.shipstatic.com", "shipstatic.com") → "www"
1015
+ * @example extractSubdomain("example.com", "shipstatic.com") → null
1016
+ */
1017
+ declare function extractSubdomain(domain: string, platformDomain: string): string | null;
1018
+ /**
1019
+ * Generate HTTPS URL for a deployment hostname.
1020
+ */
1021
+ declare function generateDeploymentUrl(deployment: string): string;
1022
+ /**
1023
+ * Generate HTTPS URL for a domain.
1024
+ */
1025
+ declare function generateDomainUrl(domain: string): string;
1026
+ /**
1027
+ * Label validation constraints shared across UI and API.
1028
+ * These rules define the single source of truth for label validation.
1029
+ */
1030
+ declare const LABEL_CONSTRAINTS: {
1031
+ /** Minimum label length in characters */
1032
+ readonly MIN_LENGTH: 3;
1033
+ /** Maximum label length in characters (concise labels, matches Stack Overflow's original limit) */
1034
+ readonly MAX_LENGTH: 25;
1035
+ /** Maximum number of labels allowed per resource */
1036
+ readonly MAX_COUNT: 10;
1037
+ /** Allowed separator characters between label segments */
1038
+ readonly SEPARATORS: "._-";
1039
+ };
1040
+ /**
1041
+ * Label validation pattern.
1042
+ * Must start and end with alphanumeric (a-z, 0-9).
1043
+ * Can contain separators (. _ -) between segments, but not consecutive.
1044
+ *
1045
+ * Valid examples: 'production', 'v1.2.3', 'api_v2', 'us-east-1'
1046
+ * Invalid examples: 'ab' (too short), '-prod' (starts with separator), 'foo--bar' (consecutive separators)
1047
+ */
1048
+ declare const LABEL_PATTERN: RegExp;
1049
+ /**
1050
+ * Serialize labels array to JSON string for database storage.
1051
+ * Returns null for empty or undefined arrays.
1052
+ *
1053
+ * @example serializeLabels(['web', 'production']) → '["web","production"]'
1054
+ * @example serializeLabels([]) → null
1055
+ * @example serializeLabels(undefined) → null
1056
+ */
1057
+ declare function serializeLabels(labels: string[] | undefined): string | null;
1058
+ /**
1059
+ * Deserialize labels from JSON string to array.
1060
+ * Always returns an array — empty array for null/empty/invalid input.
1061
+ *
1062
+ * @example deserializeLabels('["web","production"]') → ['web', 'production']
1063
+ * @example deserializeLabels(null) → []
1064
+ * @example deserializeLabels('') → []
1065
+ */
1066
+ declare function deserializeLabels(labelsJson: string | null): string[];
1067
+ /**
1068
+ * Length constraints for the optional deployment password
1069
+ * (`DeploymentUploadOptions.password`). Single source of truth shared across
1070
+ * platform consumers.
1071
+ */
1072
+ declare const PASSWORD_CONSTRAINTS: {
1073
+ /** Minimum password length in characters */
1074
+ readonly MIN_LENGTH: 6;
1075
+ /** Maximum password length in characters */
1076
+ readonly MAX_LENGTH: 128;
1077
+ };
1078
+ /**
1079
+ * Validate an optional deployment password and return it normalized.
1080
+ *
1081
+ * Absent (`undefined` / `null`) → returns `undefined`. Present → trim
1082
+ * leading/trailing whitespace, then validate against `PASSWORD_CONSTRAINTS`
1083
+ * length bounds (internal whitespace is significant and counts toward
1084
+ * length). Throws `ShipError.validation` on breach; returns the trimmed
1085
+ * value.
1086
+ *
1087
+ * The trim is canonical: at upload, the API hashes the trimmed value; at
1088
+ * unlock, the router trims submissions before hashing. Submission and storage
1089
+ * agree byte-for-byte. Length validation runs on the trimmed value because
1090
+ * that's the user's actual intent — and it disarms a class of invisible
1091
+ * foot-guns (trailing newlines from copy/paste, mobile auto-spacing,
1092
+ * password-manager artifacts).
1093
+ *
1094
+ * Single source of truth shared by SDK (client-side validation, return
1095
+ * ignored) and API (server-side enforcement, return threaded into config).
1096
+ * Length is part of the wire-format contract; strength rules, if added later,
1097
+ * stay server-side. See `CLAUDE.md` "Validation: format vs policy".
1098
+ */
1099
+ declare function validatePassword(value: unknown): string | undefined;
5
1100
 
6
1101
  /**
7
1102
  * @file SDK-specific type definitions
@@ -14,8 +1109,6 @@ export { Account, AccountResource, DEFAULT_API, DeployInput, Deployment, Deploym
14
1109
  * Extends the API contract (DeploymentUploadOptions) with SDK-specific options.
15
1110
  */
16
1111
  interface DeploymentOptions extends DeploymentUploadOptions {
17
- /** The API URL to use for this specific deploy. Overrides client's default. */
18
- apiUrl?: string;
19
1112
  /** An AbortSignal to allow cancellation of the deploy operation. */
20
1113
  signal?: AbortSignal;
21
1114
  /** Callback invoked if the deploy is cancelled via the AbortSignal. */
@@ -24,18 +1117,12 @@ interface DeploymentOptions extends DeploymentUploadOptions {
24
1117
  maxConcurrency?: number;
25
1118
  /** Timeout in milliseconds for the deploy request. */
26
1119
  timeout?: number;
27
- /** API key for this specific deploy. Overrides client's default (format: ship-<64-char-hex>, total 69 chars). */
28
- apiKey?: string;
29
- /** Deploy token for this specific deploy. Overrides client's default (format: token-<64-char-hex>, total 70 chars). */
30
- deployToken?: string;
31
1120
  /** Whether to auto-detect and optimize file paths by flattening common directories. Defaults to true. */
32
1121
  pathDetect?: boolean;
33
1122
  /** Whether to auto-detect SPAs and generate ship.json configuration. Defaults to true. */
34
1123
  spaDetect?: boolean;
35
1124
  /** Callback for deploy progress with detailed statistics. */
36
1125
  onProgress?: (info: ProgressInfo) => void;
37
- /** Caller identifier for multi-tenant deployments (alphanumeric, dot, underscore, hyphen). */
38
- caller?: string;
39
1126
  }
40
1127
  type ApiDeployOptions = Omit<DeploymentOptions, 'pathDetect'>;
41
1128
  /**
@@ -70,6 +1157,8 @@ interface DeployBodyContext {
70
1157
  prerender?: boolean;
71
1158
  spa?: boolean;
72
1159
  };
1160
+ /** @internal reCAPTCHA proof for the anonymous human deploy channel (/upload). */
1161
+ captcha?: string;
73
1162
  }
74
1163
  /**
75
1164
  * Function that creates a deploy request body from files.
@@ -78,17 +1167,36 @@ interface DeployBodyContext {
78
1167
  type DeployBodyCreator = (files: StaticFile[], context?: DeployBodyContext) => Promise<DeployBody>;
79
1168
  /** Standard `fetch` signature — the type of the `fetch` client option. */
80
1169
  type Fetch = typeof fetch;
1170
+ /**
1171
+ * Supplies the client token per request — synchronously or asynchronously.
1172
+ * The provider owns freshness: callers holding short-lived credentials
1173
+ * (e.g. OAuth access tokens) refresh inside the provider; the SDK just asks.
1174
+ * A provider that yields nothing fails the request — a configured provider
1175
+ * is credential intent, and intent never degrades to an anonymous request.
1176
+ */
1177
+ type TokenProvider = () => string | Promise<string>;
81
1178
  /**
82
1179
  * Options for configuring a `Ship` instance.
83
- * Sets default API host, authentication credentials, progress callbacks, concurrency, and timeouts for the client.
1180
+ * Sets default API host, the client credential, progress callbacks, concurrency, and timeouts for the client.
84
1181
  */
85
1182
  interface ShipClientOptions {
86
1183
  /** Default API URL for the client instance. */
87
1184
  apiUrl?: string | undefined;
88
- /** API key for authenticated deployments (format: ship-<64-char-hex>, total 69 chars). */
89
- apiKey?: string | undefined;
90
- /** Deploy token for authenticated deployments (format: token-<64-char-hex>, total 70 chars). */
91
- deployToken?: string | undefined;
1185
+ /**
1186
+ * The client credential — any platform token, sent verbatim as
1187
+ * `Authorization: Bearer <value>` on every request. The token's prefix says
1188
+ * what it is: `ship-` API key (durable, full account), `deploy-` deploy
1189
+ * token (deploy-scoped, revocable, optional TTL), anything else an opaque
1190
+ * pre-issued bearer such as an OAuth access token. The server classifies by
1191
+ * value — the client never has to say which kind it holds.
1192
+ *
1193
+ * Pass a {@link TokenProvider} function instead of a string when the token
1194
+ * must be minted or refreshed per request.
1195
+ *
1196
+ * Omitted entirely: deploys still work — they land in the public account
1197
+ * with a claim URL and an expiry; every other operation requires a token.
1198
+ */
1199
+ token?: string | TokenProvider | undefined;
92
1200
  /**
93
1201
  * Default callback for deploy progress for deploys made with this client.
94
1202
  * @param info - Progress information including percentage and byte counts.
@@ -106,14 +1214,19 @@ interface ShipClientOptions {
106
1214
  */
107
1215
  timeout?: number | undefined;
108
1216
  /**
109
- * When true, indicates the client should use HTTP-only cookies for authentication
110
- * instead of explicit tokens. This is useful for internal browser applications
111
- * where authentication is handled via secure cookies set by the API.
1217
+ * When true, the client authenticates with the first-party cookie session
1218
+ * (`AuthMethod.SESSION`) requests are sent with `credentials: 'include'`
1219
+ * and carry no `Authorization` header. For browser apps living on the
1220
+ * platform's own domains, where the API sets HTTP-only session cookies.
1221
+ * Mutually exclusive with `token`: a client holds one identity.
112
1222
  *
113
- * When set, the pre-request authentication check is skipped, allowing requests
114
- * to proceed with cookie-based credentials.
1223
+ * Requires a cookie-capable transport. Browsers send first-party cookies
1224
+ * natively; in Node, pair it with an injected `fetch` that forwards the
1225
+ * session cookie (the default fetch has no cookie jar, and `session: true`
1226
+ * deliberately suppresses the `SHIP_TOKEN` fallback — a session client
1227
+ * never silently switches identity).
115
1228
  */
116
- useCredentials?: boolean | undefined;
1229
+ session?: boolean | undefined;
117
1230
  /**
118
1231
  * Custom `fetch` implementation. Defaults to `globalThis.fetch`.
119
1232
  *
@@ -123,14 +1236,19 @@ interface ShipClientOptions {
123
1236
  */
124
1237
  fetch?: Fetch | undefined;
125
1238
  /**
126
- * Default caller identifier for multi-tenant deployments.
127
- * Alphanumeric characters, dots, underscores, and hyphens allowed (max 128 chars).
1239
+ * Caller identifier for multi-tenant orchestration — sent as `X-Caller`
1240
+ * on every request. Validated at construction against the shared `CALLER`
1241
+ * shape (`validateCaller` in `@shipstatic/types`: alphanumeric, dots,
1242
+ * underscores, hyphens; max 128 chars) — a value the API would silently
1243
+ * drop throws here instead.
128
1244
  *
129
- * Used by orchestrators (e.g. n8n nodes processing many tenants from one
130
- * worker) so the API's rate-limit bucket keys per caller rather than per
131
- * shared IP. **Programmatic-only by design** there is no `--caller`
132
- * CLI flag because every CLI invocation belongs to one human; a per-tenant
133
- * rate-limit bucket would defeat the purpose.
1245
+ * Used by orchestrators (e.g. the hosted MCP Worker processing many end
1246
+ * users from one egress) so the API's rate-limit buckets key per caller
1247
+ * rather than per shared IP. Instance identity metadata, like the
1248
+ * credential: one client speaks for one end user, and every write the
1249
+ * client makes is bucketed the same way. **Programmatic-only by design**
1250
+ * — there is no `--caller` CLI flag because every CLI invocation belongs
1251
+ * to one human; a per-tenant rate-limit bucket would defeat the purpose.
134
1252
  *
135
1253
  * Distinct from `via` (the client identifier — `'cli'`, `'sdk'`, `'web'`,
136
1254
  * `'git'`, etc.). `via` is for analytics/origin tracking and is
@@ -197,13 +1315,15 @@ declare class SimpleEvents {
197
1315
  */
198
1316
 
199
1317
  interface ApiHttpOptions extends ShipClientOptions {
200
- getAuthHeaders: () => Record<string, string>;
1318
+ /** Resolves the credential slot per request — async so token providers can mint/refresh. */
1319
+ getAuthHeaders: () => Record<string, string> | Promise<Record<string, string>>;
201
1320
  createDeployBody: DeployBodyCreator;
202
1321
  }
203
1322
  declare class ApiHttp extends SimpleEvents {
204
1323
  private readonly apiUrl;
205
1324
  private readonly getAuthHeadersCallback;
206
- private readonly useCredentials;
1325
+ private readonly session;
1326
+ private readonly caller;
207
1327
  private readonly timeout;
208
1328
  private readonly fetch;
209
1329
  private readonly createDeployBody;
@@ -253,11 +1373,10 @@ declare class ApiHttp extends SimpleEvents {
253
1373
  createToken(ttl?: number, labels?: string[]): Promise<TokenCreateResponse>;
254
1374
  listTokens(): Promise<TokenListResponse>;
255
1375
  removeToken(token: string): Promise<void>;
256
- fetchAgentToken(): Promise<TokenCreateResponse>;
257
- getAccount(): Promise<Account>;
1376
+ getAccount(): Promise<AccountGetResponse>;
258
1377
  getLimits(): Promise<PlatformLimits>;
259
1378
  ping(): Promise<boolean>;
260
- checkSPA(files: StaticFile[], options?: ApiDeployOptions): Promise<boolean>;
1379
+ checkSPA(files: StaticFile[], _options?: ApiDeployOptions): Promise<boolean>;
261
1380
  }
262
1381
 
263
1382
  /**
@@ -277,10 +1396,14 @@ interface ResourceContext {
277
1396
  interface DeploymentResourceContext extends ResourceContext {
278
1397
  processInput: (input: DeployInput, options: DeploymentOptions) => Promise<StaticFile[]>;
279
1398
  clientDefaults?: ShipClientOptions;
280
- hasAuth?: () => boolean;
281
1399
  }
282
1400
  /**
283
1401
  * Upload deployment resource with all CRUD operations.
1402
+ *
1403
+ * There is no client-side auth branching: an upload from a credential-less
1404
+ * client simply carries no `Authorization` header, and the API grants the
1405
+ * public-account agent identity per request (claim URL + expiry on the
1406
+ * response). The SDK stays a transparent pipe either way.
284
1407
  */
285
1408
  declare function createDeploymentResource(ctx: DeploymentResourceContext): DeploymentResource;
286
1409
  /**
@@ -312,7 +1435,7 @@ declare abstract class Ship$1 {
312
1435
  private readonly clientOptions;
313
1436
  private initPromise;
314
1437
  protected platformLimits: PlatformLimits | null;
315
- private auth;
1438
+ private credential;
316
1439
  constructor(options?: ShipClientOptions);
317
1440
  protected abstract processInput(input: DeployInput, options: DeploymentOptions): Promise<StaticFile[]>;
318
1441
  protected abstract getDeployBodyCreator(): DeployBodyCreator;
@@ -333,7 +1456,7 @@ declare abstract class Ship$1 {
333
1456
  /**
334
1457
  * Get current account information (convenience shortcut to `ship.account.get()`).
335
1458
  */
336
- whoami(): Promise<_shipstatic_types.Account>;
1459
+ whoami(): Promise<AccountGetResponse>;
337
1460
  /**
338
1461
  * Get platform limits (max file size, file count, total size).
339
1462
  * Reuses the response fetched during initialization. Per-instance state —
@@ -352,50 +1475,40 @@ declare abstract class Ship$1 {
352
1475
  */
353
1476
  clearHeaders(): void;
354
1477
  /**
355
- * Sets the deploy token for authentication.
356
- * Overrides any previously set API key or deploy token.
357
- * @param token Deploy token (format: `token-<64-char-hex>`)
1478
+ * Sets the client token — any platform token (API key, deploy token, OAuth
1479
+ * access token) or a {@link TokenProvider} invoked per request. Replaces
1480
+ * whatever credential the client held before.
1481
+ * @param token A platform token, sent verbatim, or a provider function
358
1482
  */
359
- setDeployToken(token: string): void;
1483
+ setToken(token: string | TokenProvider): void;
360
1484
  /**
361
- * Sets the API key for authentication.
362
- * Overrides any previously set API key or deploy token.
363
- * @param key API key (format: `ship-<64-char-hex>`)
1485
+ * Resolve the credential slot into request headers. Async because a
1486
+ * provider may mint or refresh its token per request.
1487
+ *
1488
+ * Anonymity requires proven absence of credentials: a configured provider
1489
+ * that yields nothing is an error — the request fails typed rather than
1490
+ * silently proceeding as an anonymous public deploy. Empty-string
1491
+ * normalization at the constructor is the same invariant's boundary
1492
+ * condition: `''` is absence of intent, so it never reaches this point.
364
1493
  */
365
- setApiKey(key: string): void;
366
1494
  private getAuthHeaders;
367
- /**
368
- * Check whether authentication credentials are configured.
369
- * Used by resources to fail fast (or trigger the agent-token fallback) when
370
- * auth is required.
371
- */
372
- private hasAuth;
373
1495
  }
374
1496
 
375
1497
  /**
376
1498
  * @file Cross-platform configuration helpers.
377
1499
  *
378
- * Two pure helpers used by both Node and Browser:
1500
+ * One pure helper used by the deployment resource:
379
1501
  *
380
- * - `resolveConfig(options)` — applies the API-URL default. The Node Ship
381
- * calls this after merging env vars under the user's options; the Browser
382
- * Ship calls it directly (no ambient sources).
383
1502
  * - `mergeDeployOptions(perCallOptions, clientDefaults)` — overlays
384
1503
  * instance-level defaults under per-call overrides for a single deploy.
385
1504
  *
386
- * Credential precedence is owned by callers, not this file:
387
- *
388
- * - SDK (Node): constructor args > `SHIP_*` env vars (see `node/index.ts`)
389
- * - SDK (Browser): constructor args only
390
- * - CLI: `--flag` > env > `.shiprc` / `package.json` (see `cli/create-client.ts`)
1505
+ * Deploy options are pure deploy concerns (progress, timeout, concurrency).
1506
+ * Credentials, the API URL, and the caller identifier are client identity —
1507
+ * they live on the instance, never per call: one client is one principal
1508
+ * speaking for one end user against one API. Callers that need a different
1509
+ * identity construct another Ship.
391
1510
  */
392
1511
 
393
- /**
394
- * Apply the API-URL default and project the credential triplet into a
395
- * `ResolvedConfig` shape. Optional fields are omitted (rather than set to
396
- * `undefined`) so spread merges downstream behave predictably.
397
- */
398
- declare function resolveConfig(options?: ShipClientOptions): ResolvedConfig;
399
1512
  /**
400
1513
  * Overlay client-level defaults under per-call deploy options.
401
1514
  *
@@ -405,91 +1518,6 @@ declare function resolveConfig(options?: ShipClientOptions): ResolvedConfig;
405
1518
  */
406
1519
  declare function mergeDeployOptions(options: DeploymentOptions, clientDefaults: ShipClientOptions): DeploymentOptions;
407
1520
 
408
- interface MD5Result {
409
- md5: string;
410
- }
411
- declare function calculateMD5(input: Blob | Buffer | string): Promise<MD5Result>;
412
-
413
- /**
414
- * Utility functions for string manipulation.
415
- */
416
- /**
417
- * Simple utility to pluralize a word based on a count.
418
- * @param count The number to determine pluralization.
419
- * @param singular The singular form of the word.
420
- * @param plural The plural form of the word.
421
- * @param includeCount Whether to include the count in the returned string. Defaults to true.
422
- * @returns A string with the count and the correctly pluralized word.
423
- */
424
- declare function pluralize(count: number, singular: string, plural: string, includeCount?: boolean): string;
425
-
426
- /**
427
- * List of directory names considered as junk
428
- *
429
- * Files within these directories (at any level in the path hierarchy) will be excluded.
430
- * The comparison is case-insensitive for cross-platform compatibility.
431
- *
432
- * @internal
433
- */
434
- declare const JUNK_DIRECTORIES: readonly ["__MACOSX", ".Trashes", ".fseventsd", ".Spotlight-V100"];
435
- /**
436
- * Filters an array of file paths, removing those considered junk
437
- *
438
- * Throws if any path contains an unbuilt project marker (e.g. `node_modules`, `package.json`).
439
- * This check runs first because the dot-file filter below would strip paths like
440
- * `node_modules/.pnpm/...`, destroying the evidence.
441
- *
442
- * A path is filtered out if any of these conditions are met:
443
- * 1. The basename is identified as junk by the 'junk' package (e.g., .DS_Store, Thumbs.db)
444
- * 2. Any path segment starts with a dot (e.g., .env, .git, .htaccess)
445
- * Exception: `.well-known` is allowed (RFC 8615 — ACME, security.txt, app links)
446
- * 3. Any path segment exceeds 255 characters (filesystem limit)
447
- * 4. Any directory segment in the path matches an entry in JUNK_DIRECTORIES (case-insensitive)
448
- *
449
- * All path separators are normalized to forward slashes for consistent cross-platform behavior.
450
- *
451
- * Dot files are filtered for security — they typically contain sensitive configuration
452
- * (.env, .git) or are not meant to be served publicly. This matches server-side filtering.
453
- *
454
- * @param filePaths - An array of file path strings to filter
455
- * @param options - Optional settings
456
- * @param options.allowUnbuilt - When true, skip the unbuilt project marker check (for server-processed uploads)
457
- * @returns A new array containing only non-junk file paths
458
- * @throws {ShipError} If any path contains an unbuilt project marker (unless allowUnbuilt is true)
459
- *
460
- * @example
461
- * ```typescript
462
- * import { filterJunk } from '@shipstatic/ship';
463
- *
464
- * // Filter an array of file paths
465
- * const paths = ['index.html', '.DS_Store', '.gitattributes', '__MACOSX/file.txt', 'app.js'];
466
- * const clean = filterJunk(paths);
467
- * // Result: ['index.html', 'app.js']
468
- * ```
469
- *
470
- * @example
471
- * ```typescript
472
- * // Use with browser File objects
473
- * import { filterJunk } from '@shipstatic/ship';
474
- *
475
- * const files: File[] = [...]; // From input or drag-drop
476
- *
477
- * // Extract paths from File objects
478
- * const filePaths = files.map(f => f.webkitRelativePath || f.name);
479
- *
480
- * // Filter out junk paths
481
- * const validPaths = new Set(filterJunk(filePaths));
482
- *
483
- * // Filter the original File array
484
- * const validFiles = files.filter(f =>
485
- * validPaths.has(f.webkitRelativePath || f.name)
486
- * );
487
- * ```
488
- */
489
- declare function filterJunk(filePaths: string[], options?: {
490
- allowUnbuilt?: boolean;
491
- }): string[];
492
-
493
1521
  /**
494
1522
  * @file Deploy path optimization - the core logic that makes Ship deployments clean and intuitive.
495
1523
  * Automatically strips common parent directories to create clean deployment URLs.
@@ -614,6 +1642,85 @@ declare function getValidFiles<T extends ValidatableFile>(files: T[]): T[];
614
1642
  */
615
1643
  declare function allValidFilesReady<T extends ValidatableFile>(files: T[]): boolean;
616
1644
 
1645
+ /**
1646
+ * @file Utility for filtering out junk files and directories from file paths
1647
+ *
1648
+ * This module provides functionality to filter out common system junk files and directories
1649
+ * from a list of file paths. It uses the 'junk' package to identify junk filenames and
1650
+ * a custom list to filter out common junk directories.
1651
+ */
1652
+ /**
1653
+ * List of directory names considered as junk
1654
+ *
1655
+ * Files within these directories (at any level in the path hierarchy) will be excluded.
1656
+ * The comparison is case-insensitive for cross-platform compatibility.
1657
+ *
1658
+ * @internal
1659
+ */
1660
+ declare const JUNK_DIRECTORIES: readonly ["__MACOSX", ".Trashes", ".fseventsd", ".Spotlight-V100"];
1661
+ /**
1662
+ * Filters an array of file paths, removing those considered junk
1663
+ *
1664
+ * Throws if any path contains an unbuilt project marker (e.g. `node_modules`, `package.json`).
1665
+ * This check runs first because the dot-file filter below would strip paths like
1666
+ * `node_modules/.pnpm/...`, destroying the evidence.
1667
+ *
1668
+ * A path is filtered out if any of these conditions are met:
1669
+ * 1. The basename is identified as junk by the 'junk' package (e.g., .DS_Store, Thumbs.db)
1670
+ * 2. Any path segment starts with a dot (e.g., .env, .git, .htaccess)
1671
+ * Exception: `.well-known` is allowed (RFC 8615 — ACME, security.txt, app links)
1672
+ * 3. Any path segment exceeds 255 characters (filesystem limit)
1673
+ * 4. Any directory segment in the path matches an entry in JUNK_DIRECTORIES (case-insensitive)
1674
+ *
1675
+ * All path separators are normalized to forward slashes for consistent cross-platform behavior.
1676
+ *
1677
+ * Dot files are filtered for security — they typically contain sensitive configuration
1678
+ * (.env, .git) or are not meant to be served publicly. This matches server-side filtering.
1679
+ *
1680
+ * @param filePaths - An array of file path strings to filter
1681
+ * @param options - Optional settings
1682
+ * @param options.allowUnbuilt - When true, skip the unbuilt project marker check (for server-processed uploads)
1683
+ * @returns A new array containing only non-junk file paths
1684
+ * @throws {ShipError} If any path contains an unbuilt project marker (unless allowUnbuilt is true)
1685
+ *
1686
+ * @example
1687
+ * ```typescript
1688
+ * import { filterJunk } from '@shipstatic/ship';
1689
+ *
1690
+ * // Filter an array of file paths
1691
+ * const paths = ['index.html', '.DS_Store', '.gitattributes', '__MACOSX/file.txt', 'app.js'];
1692
+ * const clean = filterJunk(paths);
1693
+ * // Result: ['index.html', 'app.js']
1694
+ * ```
1695
+ *
1696
+ * @example
1697
+ * ```typescript
1698
+ * // Use with browser File objects
1699
+ * import { filterJunk } from '@shipstatic/ship';
1700
+ *
1701
+ * const files: File[] = [...]; // From input or drag-drop
1702
+ *
1703
+ * // Extract paths from File objects
1704
+ * const filePaths = files.map(f => f.webkitRelativePath || f.name);
1705
+ *
1706
+ * // Filter out junk paths
1707
+ * const validPaths = new Set(filterJunk(filePaths));
1708
+ *
1709
+ * // Filter the original File array
1710
+ * const validFiles = files.filter(f =>
1711
+ * validPaths.has(f.webkitRelativePath || f.name)
1712
+ * );
1713
+ * ```
1714
+ */
1715
+ declare function filterJunk(filePaths: string[], options?: {
1716
+ allowUnbuilt?: boolean;
1717
+ }): string[];
1718
+
1719
+ interface MD5Result {
1720
+ md5: string;
1721
+ }
1722
+ declare function calculateMD5(input: Blob | Buffer | string): Promise<MD5Result>;
1723
+
617
1724
  /**
618
1725
  * Validate a deploy path for security concerns.
619
1726
  * Rejects paths containing path traversal patterns or null bytes.
@@ -642,6 +1749,19 @@ declare function validateDeployPath(deployPath: string, sourceIdentifier: string
642
1749
  */
643
1750
  declare function validateDeployFile(deployPath: string, sourceIdentifier: string): void;
644
1751
 
1752
+ /**
1753
+ * Utility functions for string manipulation.
1754
+ */
1755
+ /**
1756
+ * Simple utility to pluralize a word based on a count.
1757
+ * @param count The number to determine pluralization.
1758
+ * @param singular The singular form of the word.
1759
+ * @param plural The plural form of the word.
1760
+ * @param includeCount Whether to include the count in the returned string. Defaults to true.
1761
+ * @returns A string with the count and the correctly pluralized word.
1762
+ */
1763
+ declare function pluralize(count: number, singular: string, plural: string, includeCount?: boolean): string;
1764
+
645
1765
  /**
646
1766
  * @file Browser-specific file utilities for the Ship SDK.
647
1767
  * Provides helpers for processing browser files into deploy-ready objects.
@@ -676,8 +1796,8 @@ declare function processFilesForBrowser(browserFiles: File[], options?: Deployme
676
1796
  * @file Ship SDK for browser environments.
677
1797
  *
678
1798
  * Configuration is fully explicit — the browser has no env vars or config files
679
- * to inherit. All credentials are supplied via constructor options (or, for
680
- * first-party browser apps, an HTTP-only cookie via `useCredentials: true`).
1799
+ * to inherit. The credential is supplied via the `token` constructor option
1800
+ * (or, for first-party browser apps, the cookie session via `session: true`).
681
1801
  */
682
1802
 
683
1803
  /**
@@ -687,7 +1807,7 @@ declare function processFilesForBrowser(browserFiles: File[], options?: Deployme
687
1807
  * ```typescript
688
1808
  * // Deploy with a token obtained from your server
689
1809
  * const ship = new Ship({
690
- * deployToken: 'token-xxxx',
1810
+ * token: 'deploy-xxxx',
691
1811
  * apiUrl: 'https://api.shipstatic.com',
692
1812
  * });
693
1813
  *
@@ -711,4 +1831,4 @@ declare class Ship extends Ship$1 {
711
1831
  protected getDeployBodyCreator(): DeployBodyCreator;
712
1832
  }
713
1833
 
714
- export { type ApiDeployOptions, ApiHttp, type ApiHttpOptions, type DeployBody, type DeployBodyContext, type DeployBodyCreator, type DeployFile, type DeploymentOptions, type DeploymentResourceContext, type ExecutionEnvironment, type Fetch, JUNK_DIRECTORIES, type MD5Result, type ResourceContext, Ship, type ShipClientOptions, type ShipEvents, __setTestEnvironment, allValidFilesReady, calculateMD5, createAccountResource, createDeploymentResource, createDomainResource, createTokenResource, Ship as default, filterJunk, formatFileSize, getENV, getValidFiles, mergeDeployOptions, optimizeDeployPaths, pluralize, processFilesForBrowser, resolveConfig, validateDeployFile, validateDeployPath, validateFileName, validateFiles };
1834
+ export { API_KEY, type Account, type AccountGetResponse, type AccountOverrides, AccountPlan, type AccountPlanType, type AccountResource, type AccountUsage, type Activity, type ActivityEvent, type ActivityListResponse, type ActivityMeta, type ApiDeployOptions, ApiHttp, type ApiHttpOptions, AuthMethod, type AuthMethodType, BLOCKED_EXTENSIONS, type BillingStatus, CALLER, type CheckoutSession, DEFAULT_API, DEPLOYMENT_CONFIG_FILENAME, DEPLOY_TOKEN, type DeployBody, type DeployBodyContext, type DeployBodyCreator, type DeployFile, type DeployInput, type Deployment, type DeploymentCreateResponse, type DeploymentListResponse, type DeploymentOptions, type DeploymentResource, type DeploymentResourceContext, DeploymentStatus, type DeploymentStatusType, type DeploymentUploadOptions, type DnsProvider, type DnsRecord, type DnsRecordType, type Domain, type DomainDnsResponse, type DomainListResponse, type DomainRecordsResponse, type DomainResource, type DomainSetResult, DomainStatus, type DomainStatusType, type DomainValidateResponse, type ErrorResponse, ErrorType, type ExecutionEnvironment, FileValidationStatus as FILE_VALIDATION_STATUS, type Fetch, type FileValidationResult, FileValidationStatus, type FileValidationStatusType, JUNK_DIRECTORIES, LABEL_CONSTRAINTS, LABEL_PATTERN, type MD5Result, OAuthScope, type OAuthScopeType, PASSWORD_CONSTRAINTS, type PingResponse, type PlatformLimits, type ProgressInfo, type ResourceContext, type SPACheckRequest, type SPACheckResponse, SPA_DEFAULT_CONFIG, Ship, type ShipClientOptions, ShipError, type ShipEvents, type StaticFile, type TokenCreateResponse, TokenKind, type TokenKindType, type TokenListItem, type TokenListResponse, type TokenProvider, type TokenResource, UNBUILT_PROJECT_MARKERS, UNSAFE_FILENAME_CHARS, type UploadedFile, type UserVisibleActivityEvent, type ValidatableFile, type ValidationIssue, __setTestEnvironment, allValidFilesReady, calculateMD5, classifyToken, createAccountResource, createDeploymentResource, createDomainResource, createTokenResource, Ship as default, deserializeLabels, extractSubdomain, filterJunk, formatFileSize, generateDeploymentUrl, generateDomainUrl, getENV, getValidFiles, hasUnbuiltMarker, hasUnsafeChars, isBlockedExtension, isCustomDomain, isDeployment, isPlatformDomain, isShipError, mergeDeployOptions, optimizeDeployPaths, pluralize, processFilesForBrowser, serializeLabels, validateApiKey, validateApiUrl, validateCaller, validateDeployFile, validateDeployPath, validateDeployToken, validateFileName, validateFiles, validatePassword, validateToken };