@shipstatic/ship 2.0.0-beta.2 → 2.0.0-beta.4
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 +10 -10
- package/dist/browser.d.ts +126 -81
- package/dist/browser.js +1 -1
- package/dist/browser.js.map +1 -1
- package/dist/cli.cjs +29 -29
- package/dist/cli.cjs.map +1 -1
- package/dist/completions/ship.fish +1 -1
- package/dist/completions/ship.zsh +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +129 -81
- package/dist/index.d.ts +126 -81
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +35 -29
package/dist/index.d.ts
CHANGED
|
@@ -201,6 +201,8 @@ interface TokenListItem {
|
|
|
201
201
|
interface TokenListResponse {
|
|
202
202
|
/** Array of tokens (security-redacted for list display) */
|
|
203
203
|
tokens: TokenListItem[];
|
|
204
|
+
/** Cursor for pagination, null if no more pages */
|
|
205
|
+
cursor: string | null;
|
|
204
206
|
/** Total number of tokens */
|
|
205
207
|
total: number;
|
|
206
208
|
}
|
|
@@ -258,6 +260,13 @@ interface Account {
|
|
|
258
260
|
readonly activated: number | null;
|
|
259
261
|
/** Last 4 characters of the API key for identification, null when no key generated */
|
|
260
262
|
readonly hint: string | null;
|
|
263
|
+
/**
|
|
264
|
+
* Unix timestamp (seconds) of the API key's last use, null when never
|
|
265
|
+
* used or no key generated. Optional on the type by the additive-evolution
|
|
266
|
+
* law: published SDK versions may predate the field, so consumers read it
|
|
267
|
+
* when present rather than forcing a lockstep SDK release.
|
|
268
|
+
*/
|
|
269
|
+
readonly used?: number | null;
|
|
261
270
|
/** Grace period expiration (unix seconds), null if no grace period active */
|
|
262
271
|
readonly grace: number | null;
|
|
263
272
|
}
|
|
@@ -414,6 +423,18 @@ declare class ShipError extends Error {
|
|
|
414
423
|
static file(message: string, details?: unknown): ShipError;
|
|
415
424
|
static config(message: string, details?: unknown): ShipError;
|
|
416
425
|
static api(message: string, status?: number, details?: unknown): ShipError;
|
|
426
|
+
/**
|
|
427
|
+
* The caller is at fault — by HTTP's own definition of a 4xx, or by a type
|
|
428
|
+
* that is client-attributable without ever having a status (`Config`,
|
|
429
|
+
* `File`, raised locally by the SDK).
|
|
430
|
+
*
|
|
431
|
+
* Both arms are load-bearing, because type and status are independent
|
|
432
|
+
* axes. `fromHttpResponse` trusts `body.error` only when it names a
|
|
433
|
+
* server-producible type; a non-OK response without one is status-derived,
|
|
434
|
+
* so a CDN 404 or any intermediary error arrives as `Api` — a server-fault
|
|
435
|
+
* *type* carrying a client *status*. Judging by type alone would report it
|
|
436
|
+
* as a platform failure and bury the server's own message.
|
|
437
|
+
*/
|
|
417
438
|
isClientError(): boolean;
|
|
418
439
|
isNetworkError(): boolean;
|
|
419
440
|
isAuthError(): boolean;
|
|
@@ -515,9 +536,17 @@ declare function hasUnbuiltMarker(filePath: string): boolean;
|
|
|
515
536
|
interface PingResponse {
|
|
516
537
|
/** Always true if service is healthy */
|
|
517
538
|
success: boolean;
|
|
518
|
-
/**
|
|
539
|
+
/** Server time in unix seconds — the one wire unit for timestamps. */
|
|
519
540
|
timestamp?: number;
|
|
520
541
|
}
|
|
542
|
+
/**
|
|
543
|
+
* Where human identity is mounted on the API host. The API mounts Better
|
|
544
|
+
* Auth at this path (sign-in, sign-out, session reads, admin impersonation)
|
|
545
|
+
* and the web console's auth client posts to it — shared here so the two
|
|
546
|
+
* halves of the auth pair agree by construction, the same way both sides
|
|
547
|
+
* already share the credential prefixes below.
|
|
548
|
+
*/
|
|
549
|
+
declare const AUTH_BASE_PATH = "/auth";
|
|
521
550
|
/**
|
|
522
551
|
* How a request (or recorded activity) was authorized.
|
|
523
552
|
*
|
|
@@ -630,6 +659,36 @@ declare const SPA_DEFAULT_CONFIG: {
|
|
|
630
659
|
readonly destination: "/index.html";
|
|
631
660
|
}];
|
|
632
661
|
};
|
|
662
|
+
/**
|
|
663
|
+
* Assert that a ship.json file is *syntactically* loadable. Syntax only —
|
|
664
|
+
* never schema.
|
|
665
|
+
*
|
|
666
|
+
* ship.json is validated and compiled on the server, deliberately: the schema
|
|
667
|
+
* and the compiler evolve, and a client that judged them would reject configs
|
|
668
|
+
* a newer platform accepts. That reasoning bounds what a client may check to
|
|
669
|
+
* the properties which are true of *every* past and future schema:
|
|
670
|
+
*
|
|
671
|
+
* 1. it parses as JSON — JSON syntax is frozen (RFC 8259), so text that
|
|
672
|
+
* does not parse can never be a valid config;
|
|
673
|
+
* 2. its top level is an object — ship.json is `{ ... }` in every version.
|
|
674
|
+
*
|
|
675
|
+
* Both are monotonic: neither can ever reject something the server would
|
|
676
|
+
* accept. Everything beyond them (field names, types, rule semantics, which
|
|
677
|
+
* keys are permitted) stays server-side, where it can change.
|
|
678
|
+
*
|
|
679
|
+
* The payoff is the common case. Hand-edited JSON fails on a trailing comma,
|
|
680
|
+
* a `//` comment, single quotes, unquoted keys, or smart quotes pasted from
|
|
681
|
+
* documentation — mistakes that otherwise cost a full upload round-trip to
|
|
682
|
+
* discover. A UTF-8 BOM (Windows editors, PowerShell redirects) is stripped
|
|
683
|
+
* before parsing rather than rejected, because the server accepts it too;
|
|
684
|
+
* diverging there would reintroduce exactly the false rejection this
|
|
685
|
+
* function exists to avoid.
|
|
686
|
+
*
|
|
687
|
+
* @throws {ShipError} `ErrorType.Config` — the same type the server's own
|
|
688
|
+
* config rejection carries, so the error contract is identical wherever the
|
|
689
|
+
* failure is detected.
|
|
690
|
+
*/
|
|
691
|
+
declare function assertShipJsonSyntax(text: string): void;
|
|
633
692
|
/**
|
|
634
693
|
* Validate API key format
|
|
635
694
|
*/
|
|
@@ -712,20 +771,6 @@ interface StaticFile {
|
|
|
712
771
|
/** The size of the file in bytes. */
|
|
713
772
|
size: number;
|
|
714
773
|
}
|
|
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
774
|
/** Default API URL if not otherwise configured. */
|
|
730
775
|
declare const DEFAULT_API = "https://api.shipstatic.com";
|
|
731
776
|
/**
|
|
@@ -769,11 +814,28 @@ interface DeploymentUploadOptions {
|
|
|
769
814
|
captcha?: string;
|
|
770
815
|
}
|
|
771
816
|
/**
|
|
772
|
-
*
|
|
817
|
+
* Pagination options for the paginated list endpoints (`GET /deployments`,
|
|
818
|
+
* `GET /domains`). The response's `cursor` feeds the next request; a `null`
|
|
819
|
+
* cursor on the response means the last page. Omitting both returns the
|
|
820
|
+
* server's default first page.
|
|
821
|
+
*/
|
|
822
|
+
interface ListOptions {
|
|
823
|
+
/** Maximum number of items to return in one page. */
|
|
824
|
+
limit?: number;
|
|
825
|
+
/** Opaque cursor from the previous page's response. */
|
|
826
|
+
cursor?: string;
|
|
827
|
+
}
|
|
828
|
+
/**
|
|
829
|
+
* Deployment resource interface - the contract all implementations must follow.
|
|
830
|
+
*
|
|
831
|
+
* The interface defines the minimal wire contract; SDK implementations may
|
|
832
|
+
* extend the upload options with runtime concerns (timeout, signal, progress
|
|
833
|
+
* callbacks) by parameterizing: `DeploymentResource<MyUploadOptions>`. The
|
|
834
|
+
* default keeps plain `DeploymentResource` valid for wire-only consumers.
|
|
773
835
|
*/
|
|
774
|
-
interface DeploymentResource {
|
|
775
|
-
upload: (input: DeployInput, options?:
|
|
776
|
-
list: () => Promise<DeploymentListResponse>;
|
|
836
|
+
interface DeploymentResource<UploadOptions extends DeploymentUploadOptions = DeploymentUploadOptions> {
|
|
837
|
+
upload: (input: DeployInput, options?: UploadOptions) => Promise<DeploymentCreateResponse>;
|
|
838
|
+
list: (options?: ListOptions) => Promise<DeploymentListResponse>;
|
|
777
839
|
get: (id: string) => Promise<Deployment>;
|
|
778
840
|
set: (id: string, options: {
|
|
779
841
|
labels: string[];
|
|
@@ -788,7 +850,7 @@ interface DomainResource {
|
|
|
788
850
|
deployment?: string;
|
|
789
851
|
labels?: string[];
|
|
790
852
|
}) => Promise<DomainSetResult>;
|
|
791
|
-
list: () => Promise<DomainListResponse>;
|
|
853
|
+
list: (options?: ListOptions) => Promise<DomainListResponse>;
|
|
792
854
|
get: (name: string) => Promise<Domain>;
|
|
793
855
|
remove: (name: string) => Promise<void>;
|
|
794
856
|
verify: (name: string) => Promise<{
|
|
@@ -816,7 +878,7 @@ interface TokenResource {
|
|
|
816
878
|
ttl?: number;
|
|
817
879
|
labels?: string[];
|
|
818
880
|
}) => Promise<TokenCreateResponse>;
|
|
819
|
-
list: () => Promise<TokenListResponse>;
|
|
881
|
+
list: (options?: ListOptions) => Promise<TokenListResponse>;
|
|
820
882
|
remove: (token: string) => Promise<void>;
|
|
821
883
|
}
|
|
822
884
|
/**
|
|
@@ -848,11 +910,11 @@ interface CheckoutSession {
|
|
|
848
910
|
* All activity event types logged in the system.
|
|
849
911
|
* Uses dot notation consistently: {resource}.{action}
|
|
850
912
|
*/
|
|
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';
|
|
913
|
+
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' | 'token.delete' | '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
914
|
/**
|
|
853
915
|
* Activity events visible to users in the dashboard
|
|
854
916
|
*/
|
|
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';
|
|
917
|
+
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' | 'token.delete';
|
|
856
918
|
/**
|
|
857
919
|
* Activity record returned from the API
|
|
858
920
|
*/
|
|
@@ -871,6 +933,12 @@ interface Activity {
|
|
|
871
933
|
/**
|
|
872
934
|
* Parsed activity metadata.
|
|
873
935
|
* Different events populate different fields.
|
|
936
|
+
*
|
|
937
|
+
* Naming convention: meta booleans are event-scoped predicates and carry
|
|
938
|
+
* their prefix (`isUpdate`, `wasVerified`, `hasConfig`, `hasPassword`),
|
|
939
|
+
* while entity booleans are bare nouns (`Deployment.config`,
|
|
940
|
+
* `Deployment.password`). Two vocabularies, each internally consistent —
|
|
941
|
+
* deliberate, not drift.
|
|
874
942
|
*/
|
|
875
943
|
interface ActivityMeta {
|
|
876
944
|
/** Number of files in deployment */
|
|
@@ -908,6 +976,10 @@ interface ActivityMeta {
|
|
|
908
976
|
interface ActivityListResponse {
|
|
909
977
|
/** Array of activities */
|
|
910
978
|
activities: Activity[];
|
|
979
|
+
/** Cursor for pagination, null if no more pages */
|
|
980
|
+
cursor: string | null;
|
|
981
|
+
/** Total number of activities */
|
|
982
|
+
total: number;
|
|
911
983
|
}
|
|
912
984
|
/**
|
|
913
985
|
* File status constants for validation state tracking
|
|
@@ -1109,20 +1181,17 @@ declare function validatePassword(value: unknown): string | undefined;
|
|
|
1109
1181
|
* Extends the API contract (DeploymentUploadOptions) with SDK-specific options.
|
|
1110
1182
|
*/
|
|
1111
1183
|
interface DeploymentOptions extends DeploymentUploadOptions {
|
|
1112
|
-
/**
|
|
1184
|
+
/**
|
|
1185
|
+
* An AbortSignal to allow cancellation of the deploy operation. The one
|
|
1186
|
+
* cancellation mechanism — abort the signal and the request rejects with
|
|
1187
|
+
* a typed `Cancelled` error. Request timeouts are a client concern
|
|
1188
|
+
* (`ShipClientOptions.timeout`), not a per-deploy one.
|
|
1189
|
+
*/
|
|
1113
1190
|
signal?: AbortSignal;
|
|
1114
|
-
/** Callback invoked if the deploy is cancelled via the AbortSignal. */
|
|
1115
|
-
onCancel?: () => void;
|
|
1116
|
-
/** Maximum number of concurrent operations. */
|
|
1117
|
-
maxConcurrency?: number;
|
|
1118
|
-
/** Timeout in milliseconds for the deploy request. */
|
|
1119
|
-
timeout?: number;
|
|
1120
1191
|
/** Whether to auto-detect and optimize file paths by flattening common directories. Defaults to true. */
|
|
1121
1192
|
pathDetect?: boolean;
|
|
1122
1193
|
/** Whether to auto-detect SPAs and generate ship.json configuration. Defaults to true. */
|
|
1123
1194
|
spaDetect?: boolean;
|
|
1124
|
-
/** Callback for deploy progress with detailed statistics. */
|
|
1125
|
-
onProgress?: (info: ProgressInfo) => void;
|
|
1126
1195
|
}
|
|
1127
1196
|
type ApiDeployOptions = Omit<DeploymentOptions, 'pathDetect'>;
|
|
1128
1197
|
/**
|
|
@@ -1177,7 +1246,7 @@ type Fetch = typeof fetch;
|
|
|
1177
1246
|
type TokenProvider = () => string | Promise<string>;
|
|
1178
1247
|
/**
|
|
1179
1248
|
* Options for configuring a `Ship` instance.
|
|
1180
|
-
* Sets
|
|
1249
|
+
* Sets the API host, the client credential, the request timeout, and the transport.
|
|
1181
1250
|
*/
|
|
1182
1251
|
interface ShipClientOptions {
|
|
1183
1252
|
/** Default API URL for the client instance. */
|
|
@@ -1198,19 +1267,8 @@ interface ShipClientOptions {
|
|
|
1198
1267
|
*/
|
|
1199
1268
|
token?: string | TokenProvider | undefined;
|
|
1200
1269
|
/**
|
|
1201
|
-
*
|
|
1202
|
-
*
|
|
1203
|
-
*/
|
|
1204
|
-
onProgress?: ((info: ProgressInfo) => void) | undefined;
|
|
1205
|
-
/**
|
|
1206
|
-
* Default for maximum concurrent deploys.
|
|
1207
|
-
* Used if an deploy operation doesn't specify its own `maxConcurrency`.
|
|
1208
|
-
* Defaults to 4 if not set here or in the specific deploy call.
|
|
1209
|
-
*/
|
|
1210
|
-
maxConcurrency?: number | undefined;
|
|
1211
|
-
/**
|
|
1212
|
-
* Default timeout in milliseconds for API requests made by this client instance.
|
|
1213
|
-
* Used if an deploy operation doesn't specify its own timeout.
|
|
1270
|
+
* Timeout in milliseconds for every API request made by this client
|
|
1271
|
+
* instance. Defaults to 30 seconds.
|
|
1214
1272
|
*/
|
|
1215
1273
|
timeout?: number | undefined;
|
|
1216
1274
|
/**
|
|
@@ -1277,7 +1335,19 @@ interface ShipEvents {
|
|
|
1277
1335
|
request: [url: string, init: RequestInit];
|
|
1278
1336
|
/** Emitted after successful API response */
|
|
1279
1337
|
response: [response: Response, url: string];
|
|
1280
|
-
/**
|
|
1338
|
+
/**
|
|
1339
|
+
* Emitted when something fails. TWO populations arrive here, which is why
|
|
1340
|
+
* the type is `Error` and not `ShipError`:
|
|
1341
|
+
*
|
|
1342
|
+
* - a failed request — always a `ShipError` (`executeRequest` normalizes
|
|
1343
|
+
* every failure through `ShipError.fromFetchError` before emitting), so
|
|
1344
|
+
* `isShipError(error)` narrows and `.type` / `.status` are readable;
|
|
1345
|
+
* - a THROWING HANDLER of yours — `SimpleEvents.emit` evicts it and
|
|
1346
|
+
* re-emits the raw failure here, which is a plain `Error`.
|
|
1347
|
+
*
|
|
1348
|
+
* Narrowing this to `ShipError` was tried on 2026-07-27 and reverted: it
|
|
1349
|
+
* made the second population a lie.
|
|
1350
|
+
*/
|
|
1281
1351
|
error: [error: Error, url: string];
|
|
1282
1352
|
}
|
|
1283
1353
|
|
|
@@ -1352,12 +1422,12 @@ declare class ApiHttp extends SimpleEvents {
|
|
|
1352
1422
|
private safeClone;
|
|
1353
1423
|
private parseResponse;
|
|
1354
1424
|
deploy(files: StaticFile[], options?: ApiDeployOptions): Promise<DeploymentCreateResponse>;
|
|
1355
|
-
listDeployments(): Promise<DeploymentListResponse>;
|
|
1425
|
+
listDeployments(options?: ListOptions): Promise<DeploymentListResponse>;
|
|
1356
1426
|
getDeployment(id: string): Promise<Deployment>;
|
|
1357
1427
|
updateDeploymentLabels(id: string, labels: string[]): Promise<Deployment>;
|
|
1358
1428
|
removeDeployment(id: string): Promise<void>;
|
|
1359
1429
|
setDomain(name: string, deployment?: string, labels?: string[]): Promise<DomainSetResult>;
|
|
1360
|
-
listDomains(): Promise<DomainListResponse>;
|
|
1430
|
+
listDomains(options?: ListOptions): Promise<DomainListResponse>;
|
|
1361
1431
|
getDomain(name: string): Promise<Domain>;
|
|
1362
1432
|
removeDomain(name: string): Promise<void>;
|
|
1363
1433
|
verifyDomain(name: string): Promise<{
|
|
@@ -1371,7 +1441,7 @@ declare class ApiHttp extends SimpleEvents {
|
|
|
1371
1441
|
}>;
|
|
1372
1442
|
validateDomain(name: string): Promise<DomainValidateResponse>;
|
|
1373
1443
|
createToken(ttl?: number, labels?: string[]): Promise<TokenCreateResponse>;
|
|
1374
|
-
listTokens(): Promise<TokenListResponse>;
|
|
1444
|
+
listTokens(options?: ListOptions): Promise<TokenListResponse>;
|
|
1375
1445
|
removeToken(token: string): Promise<void>;
|
|
1376
1446
|
getAccount(): Promise<AccountGetResponse>;
|
|
1377
1447
|
getLimits(): Promise<PlatformLimits>;
|
|
@@ -1395,7 +1465,6 @@ interface ResourceContext {
|
|
|
1395
1465
|
*/
|
|
1396
1466
|
interface DeploymentResourceContext extends ResourceContext {
|
|
1397
1467
|
processInput: (input: DeployInput, options: DeploymentOptions) => Promise<StaticFile[]>;
|
|
1398
|
-
clientDefaults?: ShipClientOptions;
|
|
1399
1468
|
}
|
|
1400
1469
|
/**
|
|
1401
1470
|
* Upload deployment resource with all CRUD operations.
|
|
@@ -1405,7 +1474,7 @@ interface DeploymentResourceContext extends ResourceContext {
|
|
|
1405
1474
|
* public-account agent identity per request (claim URL + expiry on the
|
|
1406
1475
|
* response). The SDK stays a transparent pipe either way.
|
|
1407
1476
|
*/
|
|
1408
|
-
declare function createDeploymentResource(ctx: DeploymentResourceContext): DeploymentResource
|
|
1477
|
+
declare function createDeploymentResource(ctx: DeploymentResourceContext): DeploymentResource<DeploymentOptions>;
|
|
1409
1478
|
/**
|
|
1410
1479
|
* Create domain resource with all CRUD operations.
|
|
1411
1480
|
*
|
|
@@ -1427,7 +1496,7 @@ declare function createTokenResource(ctx: ResourceContext): TokenResource;
|
|
|
1427
1496
|
* Abstract base class for Ship SDK implementations.
|
|
1428
1497
|
*/
|
|
1429
1498
|
declare abstract class Ship$1 {
|
|
1430
|
-
readonly deployments: DeploymentResource
|
|
1499
|
+
readonly deployments: DeploymentResource<DeploymentOptions>;
|
|
1431
1500
|
readonly domains: DomainResource;
|
|
1432
1501
|
readonly account: AccountResource;
|
|
1433
1502
|
readonly tokens: TokenResource;
|
|
@@ -1452,7 +1521,7 @@ declare abstract class Ship$1 {
|
|
|
1452
1521
|
/**
|
|
1453
1522
|
* Deploy project (convenience shortcut to `ship.deployments.upload()`).
|
|
1454
1523
|
*/
|
|
1455
|
-
deploy(input: DeployInput, options?: DeploymentOptions): Promise<
|
|
1524
|
+
deploy(input: DeployInput, options?: DeploymentOptions): Promise<DeploymentCreateResponse>;
|
|
1456
1525
|
/**
|
|
1457
1526
|
* Get current account information (convenience shortcut to `ship.account.get()`).
|
|
1458
1527
|
*/
|
|
@@ -1494,30 +1563,6 @@ declare abstract class Ship$1 {
|
|
|
1494
1563
|
private getAuthHeaders;
|
|
1495
1564
|
}
|
|
1496
1565
|
|
|
1497
|
-
/**
|
|
1498
|
-
* @file Cross-platform configuration helpers.
|
|
1499
|
-
*
|
|
1500
|
-
* One pure helper used by the deployment resource:
|
|
1501
|
-
*
|
|
1502
|
-
* - `mergeDeployOptions(perCallOptions, clientDefaults)` — overlays
|
|
1503
|
-
* instance-level defaults under per-call overrides for a single deploy.
|
|
1504
|
-
*
|
|
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.
|
|
1510
|
-
*/
|
|
1511
|
-
|
|
1512
|
-
/**
|
|
1513
|
-
* Overlay client-level defaults under per-call deploy options.
|
|
1514
|
-
*
|
|
1515
|
-
* Per-call options always win — they're the explicit override for a single
|
|
1516
|
-
* `deployments.upload()`. Defaults fill in only when the per-call option is
|
|
1517
|
-
* `undefined` (an explicit `null` / empty value passes through).
|
|
1518
|
-
*/
|
|
1519
|
-
declare function mergeDeployOptions(options: DeploymentOptions, clientDefaults: ShipClientOptions): DeploymentOptions;
|
|
1520
|
-
|
|
1521
1566
|
/**
|
|
1522
1567
|
* @file Deploy path optimization - the core logic that makes Ship deployments clean and intuitive.
|
|
1523
1568
|
* Automatically strips common parent directories to create clean deployment URLs.
|
|
@@ -1775,7 +1820,7 @@ declare function pluralize(count: number, singular: string, plural: string, incl
|
|
|
1775
1820
|
* @param paths - File or directory paths to scan and process.
|
|
1776
1821
|
* @param options - Processing options (pathDetect, etc.).
|
|
1777
1822
|
* @param platformLimits - Per-instance platform limits (file-size / count /
|
|
1778
|
-
* total-size caps) from the originating Ship's `GET /
|
|
1823
|
+
* total-size caps) from the originating Ship's `GET /limits` fetch. Passed
|
|
1779
1824
|
* in rather than read from a module global so concurrent Ships against
|
|
1780
1825
|
* different API URLs cannot clobber each other's caps.
|
|
1781
1826
|
* @returns Promise resolving to an array of StaticFile objects.
|
|
@@ -1827,9 +1872,9 @@ declare class Ship extends Ship$1 {
|
|
|
1827
1872
|
* intentional: the convenience shortcut narrows; the resource-layer
|
|
1828
1873
|
* contract stays platform-neutral.
|
|
1829
1874
|
*/
|
|
1830
|
-
deploy(input: string | string[], options?: DeploymentOptions): Promise<
|
|
1875
|
+
deploy(input: string | string[], options?: DeploymentOptions): Promise<DeploymentCreateResponse>;
|
|
1831
1876
|
protected processInput(input: DeployInput, options: DeploymentOptions): Promise<StaticFile[]>;
|
|
1832
1877
|
protected getDeployBodyCreator(): DeployBodyCreator;
|
|
1833
1878
|
}
|
|
1834
1879
|
|
|
1835
|
-
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
|
|
1880
|
+
export { API_KEY, AUTH_BASE_PATH, 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 ListOptions, type MD5Result, OAuthScope, type OAuthScopeType, PASSWORD_CONSTRAINTS, type PingResponse, type PlatformLimits, 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, assertShipJsonSyntax, calculateMD5, classifyToken, createAccountResource, createDeploymentResource, createDomainResource, createTokenResource, Ship as default, deserializeLabels, extractSubdomain, filterJunk, formatFileSize, generateDeploymentUrl, generateDomainUrl, getENV, getValidFiles, hasUnbuiltMarker, hasUnsafeChars, isBlockedExtension, isCustomDomain, isDeployment, isPlatformDomain, isShipError, optimizeDeployPaths, pluralize, processFilesForNode, serializeLabels, validateApiKey, validateApiUrl, validateCaller, validateDeployFile, validateDeployPath, validateDeployToken, validateFileName, validateFiles, validatePassword, validateToken };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var _e=Object.defineProperty;var w=(n,t)=>()=>(n&&(t=n(n=0)),t);var ke=(n,t)=>{for(var e in t)_e(n,e,{get:t[e],enumerable:!0})};function L(n){return n!==null&&typeof n=="object"&&"name"in n&&n.name==="ShipError"&&"status"in n}function $(n){let t=n.lastIndexOf(".");if(t===-1||t===n.length-1)return!1;let e=n.slice(t+1).toLowerCase();return Be.has(e)}function le(n){return He.test(n)}function _(n){return n.replace(/\\/g,"/").split("/").filter(Boolean).some(e=>j.has(e))}function Ge(n){return n.startsWith(pe.PREFIX)?x.API_KEY:n.startsWith(ce.PREFIX)?x.DEPLOY_TOKEN:x.OPAQUE}function de(n,t,e){if(!n.startsWith(t.PREFIX))throw a.validation(`${e} must start with "${t.PREFIX}"`);if(n.length!==t.TOTAL_LENGTH)throw a.validation(`${e} must be ${t.TOTAL_LENGTH} characters total (${t.PREFIX} + ${t.HEX_LENGTH} hex chars)`);let i=n.slice(t.PREFIX.length);if(!new RegExp(`^[a-f0-9]{${t.HEX_LENGTH}}$`,"i").test(i))throw a.validation(`${e} must contain ${t.HEX_LENGTH} hexadecimal characters after "${t.PREFIX}" prefix`)}function ze(n){de(n,pe,"API key")}function Ve(n){de(n,ce,"Deploy token")}function K(n){switch(Ge(n)){case x.API_KEY:ze(n);return;case x.DEPLOY_TOKEN:Ve(n);return;case x.OPAQUE:if(!n)throw a.validation("Token must be a non-empty string")}}function me(n){if(!n||n.length>V.MAX_LENGTH||!V.PATTERN.test(n))throw a.validation(`Caller must be 1-${V.MAX_LENGTH} characters: letters, digits, dots, underscores, or hyphens`)}function pt(n){try{let t=new URL(n);if(!["http:","https:"].includes(t.protocol))throw a.validation("API URL must use http:// or https:// protocol");if(t.pathname!=="/"&&t.pathname!=="")throw a.validation("API URL must not contain a path");if(t.search||t.hash)throw a.validation("API URL must not contain query parameters or fragments")}catch(t){throw L(t)?t:a.validation("API URL must be a valid URL")}}function ct(n){return/^[a-z]+-[a-z]+-[a-z0-9]{7}(\.[a-z0-9.-]+)?$/i.test(n)}function fe(n,t){return n.endsWith(`.${t}`)}function ut(n,t){return!fe(n,t)}function dt(n,t){return fe(n,t)?n.slice(0,-(t.length+1)):null}function mt(n){return`https://${n}`}function ft(n){return`https://${n}`}function ht(n){return!n||n.length===0?null:JSON.stringify(n)}function yt(n){if(!n)return[];try{let t=JSON.parse(n);return Array.isArray(t)?t:[]}catch{return[]}}function Y(n){if(n==null)return;if(typeof n!="string")throw a.validation("Password must be a string");let t=n.trim();if(t.length<C.MIN_LENGTH||t.length>C.MAX_LENGTH)throw a.validation(`Password must be between ${C.MIN_LENGTH} and ${C.MAX_LENGTH} characters`);return t}var st,ot,at,m,Ue,z,Me,a,Be,He,j,ae,pe,ce,V,x,lt,q,ue,X,y,P,he,C,g=w(()=>{"use strict";st={PENDING:"pending",SUCCESS:"success",FAILED:"failed",DELETING:"deleting"},ot={PENDING:"pending",PARTIAL:"partial",SUCCESS:"success",PAUSED:"paused"},at={FREE:"free",STANDARD:"standard",SPONSORED:"sponsored",ENTERPRISE:"enterprise",SUSPENDED:"suspended",TERMINATING:"terminating",TERMINATED:"terminated"},m={Validation:"validation_failed",NotFound:"not_found",Forbidden:"forbidden",RateLimit:"rate_limit_exceeded",Authentication:"authentication_failed",Business:"business_logic_error",Api:"internal_server_error",Network:"network_error",Cancelled:"operation_cancelled",File:"file_error",Config:"config_error"},Ue=new Set([m.Network,m.Cancelled,m.File,m.Config]),z={client:new Set([m.Business,m.Config,m.File,m.Forbidden,m.Validation]),network:new Set([m.Network]),auth:new Set([m.Authentication])},Me=new Set(Object.values(m).filter(n=>!Ue.has(n))),a=class n extends Error{type;status;details;constructor(t,e,i,r){super(e),this.type=t,this.status=i,this.details=r,this.name="ShipError"}toResponse(){let t=this.details,e=this.type===m.Authentication&&t?.internal?void 0:this.details;return{error:this.type,message:this.message,status:this.status,details:e}}static async fromHttpResponse(t,e){let i,r,s;try{if(t.headers.get("content-type")?.includes("application/json")){let o=await t.json();if(o&&typeof o=="object"){let p=o;typeof p.message=="string"?i=p.message:typeof p.error=="string"&&(i=p.error),r=p.details,typeof p.error=="string"&&Me.has(p.error)&&(s=p.error)}}else{let o=await t.text();o&&(i=o)}}catch{}i=i||`${e||"Request"} failed with status ${t.status}`;let l=s??(t.status===401?m.Authentication:t.status===403?m.Forbidden:t.status===429?m.RateLimit:m.Api);return new n(l,i,t.status,r)}static fromFetchError(t,e){if(L(t))return t;let i=e||"Request";return t instanceof Error?t.name==="AbortError"?n.cancelled(`${i} was cancelled`):t instanceof TypeError&&t.message.includes("fetch")?n.network(`${i} failed: ${t.message}`,{cause:t}):new n(m.Api,`${i} failed: ${t.message}`):new n(m.Api,`${i} failed: Unknown error`)}static validation(t,e){return new n(m.Validation,t,400,e)}static notFound(t,e){let i=e?`${t} ${e} not found`:`${t} not found`;return new n(m.NotFound,i,404)}static forbidden(t,e){return new n(m.Forbidden,t,403,e)}static rateLimit(t="Too many requests",e){return new n(m.RateLimit,t,429,e)}static authentication(t="Authentication required",e){return new n(m.Authentication,t,401,e)}static business(t,e=400,i){return new n(m.Business,t,e,i)}static network(t,e){return new n(m.Network,t,void 0,e)}static cancelled(t,e){return new n(m.Cancelled,t,void 0,e)}static file(t,e){return new n(m.File,t,void 0,e)}static config(t,e){return new n(m.Config,t,void 0,e)}static api(t,e=500,i){return new n(m.Api,t,e,i)}isClientError(){return z.client.has(this.type)}isNetworkError(){return z.network.has(this.type)}isAuthError(){return z.auth.has(this.type)}isType(t){return this.type===t}};Be=new Set(["exe","msi","dll","scr","bat","cmd","com","pif","app","deb","rpm","pkg","mpkg","dmg","iso","img","cab","cpl","chm","ps1","vbs","vbe","ws","wsf","wsc","wsh","reg","jar","jnlp","apk","crx","lnk","inf","hta"]);He=/[\x00-\x1f\x7f#?%\\<>"]/;j=new Set(["node_modules","package.json"]);ae={SESSION:"session",API_KEY:"apiKey",TOKEN:"token",AGENT:"agent",OAUTH:"oauth",WEBHOOK:"webhook",SYSTEM:"system"},pe={PREFIX:"ship-",HEX_LENGTH:64,TOTAL_LENGTH:69,HINT_LENGTH:4},ce={PREFIX:"deploy-",HEX_LENGTH:64,TOTAL_LENGTH:71},V={HEADER:"X-Caller",MAX_LENGTH:128,PATTERN:/^[a-zA-Z0-9._-]+$/},x={API_KEY:ae.API_KEY,DEPLOY_TOKEN:ae.TOKEN,OPAQUE:"opaque"};lt={ACCOUNT_READ:"account:read",DEPLOYMENTS_READ:"deployments:read",DEPLOYMENTS_WRITE:"deployments:write",DOMAINS_READ:"domains:read",DOMAINS_WRITE:"domains:write"},q="ship.json",ue={rewrites:[{source:"/(.*)",destination:"/index.html"}]};X="https://api.shipstatic.com",y={PENDING:"pending",PROCESSING_ERROR:"processing_error",EXCLUDED:"excluded",VALIDATION_FAILED:"validation_failed",READY:"ready"};P={MIN_LENGTH:3,MAX_LENGTH:25,MAX_COUNT:10,SEPARATORS:"._-"},he=/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/;C={MIN_LENGTH:6,MAX_LENGTH:128}});async function qe(n){let t=(await import("spark-md5")).default,e=new t.ArrayBuffer,i=2097152;for(let r=0;r<n.size;r+=i){let s=Math.min(r+i,n.size);e.append(await n.slice(r,s).arrayBuffer())}return{md5:e.end()}}async function Ke(n){let{createHash:t}=await import("crypto"),e=t("md5");return e.update(n),{md5:e.digest("hex")}}async function Xe(n){let{createHash:t}=await import("crypto"),{createReadStream:e}=await import("fs");return new Promise((i,r)=>{let s=t("md5"),l=e(n);l.on("error",u=>r(a.business(`Failed to read file for MD5: ${u.message}`))),l.on("data",u=>s.update(u)),l.on("end",()=>i({md5:s.digest("hex")}))})}async function M(n){if(n instanceof Blob)return qe(n);if(typeof Buffer<"u"&&Buffer.isBuffer(n))return Ke(n);if(typeof n=="string")return Xe(n);throw a.business("Invalid input for MD5 calculation")}var B=w(()=>{"use strict";g()});function Bt(n){W=n}function We(){return typeof process<"u"&&process.versions&&process.versions.node?"node":typeof window<"u"||typeof self<"u"?"browser":"unknown"}function I(){return W||We()}var W,F=w(()=>{"use strict";W=null});function xe(n){if(!n||n.length===0)return"";let t=n.filter(s=>s&&typeof s=="string").map(s=>s.replace(/\\/g,"/"));if(t.length===0)return"";if(t.length===1)return t[0];let e=t.map(s=>s.split("/").filter(Boolean)),i=[],r=Math.min(...e.map(s=>s.length));for(let s=0;s<r;s++){let l=e[0][s];if(e.every(u=>u[s]===l))i.push(l);else break}return i.join("/")}function G(n){return n.replace(/\\/g,"/").replace(/\/+/g,"/").replace(/^\/+/,"")}var J=w(()=>{"use strict"});function Ie(n,t={}){if(t.flatten===!1)return n.map(i=>({path:G(i),name:Q(i)}));let e=Ze(n);return n.map(i=>{let r=G(i);if(e){let s=e.endsWith("/")?e:`${e}/`;r.startsWith(s)&&(r=r.substring(s.length))}return r||(r=Q(i)),{path:r,name:Q(i)}})}function Ze(n){if(!n.length)return"";let e=n.map(s=>G(s)).map(s=>s.split("/")),i=[],r=Math.min(...e.map(s=>s.length));for(let s=0;s<r-1;s++){let l=e[0][s];if(e.every(u=>u[s]===l))i.push(l);else break}return i.join("/")}function Q(n){return n.split(/[/\\]/).pop()||n}var Z=w(()=>{"use strict";J()});function ee(n,t=1){if(n===0)return"0 Bytes";let e=1024,i=["Bytes","KB","MB","GB"],r=Math.floor(Math.log(n)/Math.log(e));return`${parseFloat((n/e**r).toFixed(t))} ${i[r]}`}function te(n){if(le(n))return{valid:!1,reason:"File name contains unsafe characters"};if(n.startsWith(" ")||n.endsWith(" "))return{valid:!1,reason:"File name cannot start/end with spaces"};if(n.endsWith("."))return{valid:!1,reason:"File name cannot end with dots"};let t=/^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(\.|$)/i,e=n.split("/").pop()||n;return t.test(e)?{valid:!1,reason:"File name uses a reserved system name"}:n.includes("..")?{valid:!1,reason:"File name contains path traversal pattern"}:{valid:!0}}function rn(n,t){let e=[],i=[],r=[];if(n.length===0){let o={file:"(no files)",message:"At least one file must be provided"};return e.push(o),{files:[],validFiles:[],errors:e,warnings:[],canDeploy:!1}}for(let o of n)if(_(o.name))return e.push({file:o.name,message:"Unbuilt project detected \u2014 deploy your build output (dist/, build/, out/), not the project folder"}),{files:n.map(p=>({...p,status:y.VALIDATION_FAILED,statusMessage:"Unbuilt project detected"})),validFiles:[],errors:e,warnings:[],canDeploy:!1};if(n.length>t.maxFilesCount){let o={file:`(${n.length} files)`,message:`File count (${n.length}) exceeds limit of ${t.maxFilesCount}`};return e.push(o),{files:n.map(p=>({...p,status:y.VALIDATION_FAILED,statusMessage:o.message})),validFiles:[],errors:e,warnings:[],canDeploy:!1}}let s=0;for(let o of n){let p=y.READY,d="Ready for upload",A=o.name?te(o.name):{valid:!1,reason:"File name cannot be empty"};if(o.status===y.PROCESSING_ERROR)p=y.VALIDATION_FAILED,d=o.statusMessage||"File failed during processing",e.push({file:o.name,message:d});else if(o.size===0){p=y.EXCLUDED,d="File is empty (0 bytes) and cannot be deployed due to storage limitations",i.push({file:o.name,message:d}),r.push({...o,status:p,statusMessage:d});continue}else o.size<0?(p=y.VALIDATION_FAILED,d="File size must be positive",e.push({file:o.name,message:d})):!o.name||o.name.trim().length===0?(p=y.VALIDATION_FAILED,d="File name cannot be empty",e.push({file:o.name||"(empty)",message:d})):o.name.includes("\0")?(p=y.VALIDATION_FAILED,d="File name contains invalid characters (null byte)",e.push({file:o.name,message:d})):A.valid?$(o.name)?(p=y.VALIDATION_FAILED,d=`File extension not allowed: "${o.name}"`,e.push({file:o.name,message:d})):o.size>t.maxFileSize?(p=y.VALIDATION_FAILED,d=`File size (${ee(o.size)}) exceeds limit of ${ee(t.maxFileSize)}`,e.push({file:o.name,message:d})):(s+=o.size,s>t.maxTotalSize&&(p=y.VALIDATION_FAILED,d=`Total size would exceed limit of ${ee(t.maxTotalSize)}`,e.push({file:o.name,message:d}))):(p=y.VALIDATION_FAILED,d=A.reason||"Invalid file name",e.push({file:o.name,message:d}));r.push({...o,status:p,statusMessage:d})}e.length>0&&(r=r.map(o=>o.status===y.EXCLUDED?o:{...o,status:y.VALIDATION_FAILED,statusMessage:o.status===y.VALIDATION_FAILED?o.statusMessage:"Deployment failed due to validation errors in bundle"}));let l=e.length===0?r.filter(o=>o.status===y.READY):[],u=e.length===0;return{files:r,validFiles:l,errors:e,warnings:i,canDeploy:u}}function et(n){return n.filter(t=>t.status===y.READY)}function sn(n){return et(n).length>0}var ne=w(()=>{"use strict";g()});import{isJunk as tt}from"junk";function be(n,t){if(!n||n.length===0)return[];if(!t?.allowUnbuilt&&n.find(i=>i&&_(i)))throw a.business("Unbuilt project detected \u2014 deploy your build output (dist/, build/, out/), not the project folder");return n.filter(e=>{if(!e)return!1;let i=e.replace(/\\/g,"/").split("/").filter(Boolean);if(i.length===0)return!0;let r=i[i.length-1];if(tt(r))return!1;for(let l of i)if(l!==".well-known"&&(l.startsWith(".")||l.length>255))return!1;let s=i.slice(0,-1);for(let l of s)if(nt.some(u=>l.toLowerCase()===u.toLowerCase()))return!1;return!0})}var nt,ie=w(()=>{"use strict";g();nt=["__MACOSX",".Trashes",".fseventsd",".Spotlight-V100"]});function Ne(n,t){if(n.includes("\0")||n.includes("/../")||n.startsWith("../")||n.endsWith("/.."))throw a.business(`Security error: Unsafe file path "${n}" for file: ${t}`)}function Le(n,t){let e=te(n);if(!e.valid)throw a.business(e.reason||"Invalid file name");if($(n))throw a.business(`File extension not allowed: "${t}"`)}var re=w(()=>{"use strict";g();ne()});var Ce={};ke(Ce,{processFilesForNode:()=>Fe});import*as E from"fs";import*as D from"path";function Oe(n,t=new Set){let e=[],i=E.realpathSync(n);if(t.has(i))return e;t.add(i);let r=E.readdirSync(n);for(let s of r){let l=D.join(n,s),u=E.statSync(l);if(u.isDirectory()){let o=Oe(l,t);e.push(...o)}else u.isFile()&&e.push(l)}return e}async function Fe(n,t={},e){if(I()!=="node")throw a.business("processFilesForNode can only be called in Node.js environment.");for(let c of n){let f=D.resolve(c);try{if(E.statSync(f).isDirectory()){let S=E.readdirSync(f).find(T=>j.has(T));if(S)throw a.business(`"${S}" detected \u2014 deploy your build output (dist/, build/, out/), not the project folder`)}}catch(S){if(L(S))throw S}}let i=n.flatMap(c=>{let f=D.resolve(c);try{return E.statSync(f).isDirectory()?Oe(f):[f]}catch{throw a.file(`Path does not exist: ${c}`,{filePath:c})}}),r=[...new Set(i)],s=n.map(c=>D.resolve(c)),l=xe(s.map(c=>{try{return E.statSync(c).isDirectory()?c:D.dirname(c)}catch{return D.dirname(c)}})),u=r.map(c=>{if(l&&l.length>0){let f=D.relative(l,c);if(f&&typeof f=="string"&&!f.startsWith(".."))return f.replace(/\\/g,"/")}return D.basename(c)}),p=Ie(u,{flatten:t.pathDetect!==!1}).map(c=>c.path),d=new Set(be(p));if(d.size===0)return[];let A=[],b=[];for(let c=0;c<r.length;c++)d.has(p[c])&&(A.push(r[c]),b.push(p[c]));let v=[],R=0;if(!e)throw a.config("Platform limits not provided. processFilesForNode requires the limits argument \u2014 pass `ship.getLimits()` result.");for(let c=0;c<A.length;c++){let f=A[c],S=b[c];try{Ne(S,f);let T=E.statSync(f);if(T.size===0)continue;if(Le(S,f),T.size>e.maxFileSize)throw a.business(`File ${f} is too large. Maximum allowed size is ${e.maxFileSize/(1024*1024)}MB.`);if(R+=T.size,R>e.maxTotalSize)throw a.business(`Total deploy size is too large. Maximum allowed is ${e.maxTotalSize/(1024*1024)}MB.`);let N=E.readFileSync(f),{md5:$e}=await M(N);v.push({path:S,content:N,size:N.length,md5:$e})}catch(T){if(L(T))throw T;let N=T instanceof Error?T.message:String(T);throw a.file(`Failed to read file "${f}": ${N}`,{filePath:f})}}if(v.length>e.maxFilesCount)throw a.business(`Too many files to deploy. Maximum allowed is ${e.maxFilesCount} files.`);return v}var se=w(()=>{"use strict";g();Z();F();ie();B();J();re()});g();g();g();var k=class{constructor(){this.handlers=new Map}on(t,e){this.handlers.has(t)||this.handlers.set(t,new Set),this.handlers.get(t)?.add(e)}off(t,e){let i=this.handlers.get(t);i&&(i.delete(e),i.size===0&&this.handlers.delete(t))}emit(t,...e){let i=this.handlers.get(t);if(!i)return;let r=Array.from(i);for(let s of r)try{s(...e)}catch(l){i.delete(s),t!=="error"&&setTimeout(()=>{let u=l instanceof Error?l:new Error(String(l));this.emit("error",u,String(t))},0)}}};g();g();function O(n){if(n==null)return;if(n.length===0)return n;if(n.length>P.MAX_COUNT)throw a.validation(`Maximum ${P.MAX_COUNT} labels allowed`);let t=n.map((i,r)=>{if(typeof i!="string")throw a.validation(`Label at index ${r} must be a string`);let s=i.trim().toLowerCase();if(s.length<P.MIN_LENGTH)throw a.validation(`Labels must be at least ${P.MIN_LENGTH} characters long`);if(s.length>P.MAX_LENGTH)throw a.validation(`Labels must be no more than ${P.MAX_LENGTH} characters long`);if(!he.test(s))throw a.validation(`Labels must start and end with alphanumeric characters, with optional separators (${P.SEPARATORS}) between segments`);return s}),e=[...new Set(t)];if(e.length!==t.length)throw a.validation("Duplicate labels are not allowed");return e}var h={DEPLOYMENTS:"/deployments",DOMAINS:"/domains",TOKENS:"/tokens",ACCOUNT:"/account",LIMITS:"/limits",PING:"/ping",SPA_CHECK:"/spa-check"},je=3e4,U=class extends k{constructor(e){super();this.globalHeaders={};this.apiUrl=e.apiUrl||X,this.getAuthHeadersCallback=e.getAuthHeaders,this.session=e.session??!1,this.caller=e.caller,this.timeout=e.timeout??je,this.fetch=e.fetch??globalThis.fetch.bind(globalThis),this.createDeployBody=e.createDeployBody,this.deployEndpoint=e.deployEndpoint||h.DEPLOYMENTS}setGlobalHeaders(e){this.globalHeaders=e}async executeRequest(e,i,r){let s=()=>{};try{let l=await this.mergeHeaders(i.headers),u=this.createTimeoutSignal(i.signal);s=u.cleanup;let o={...i,headers:l,credentials:this.session&&!l.Authorization?"include":void 0,signal:u.signal};this.emit("request",e,o);let p=await this.fetch(e,o);if(s(),!p.ok)throw await a.fromHttpResponse(p,r);return this.emit("response",this.safeClone(p),e),{data:await this.parseResponse(this.safeClone(p)),status:p.status}}catch(l){s();let u=a.fromFetchError(l,r);throw this.emit("error",u,e),u}}async request(e,i,r){let{data:s}=await this.executeRequest(e,i,r);return s}async requestWithStatus(e,i,r){return this.executeRequest(e,i,r)}async mergeHeaders(e={}){return{...this.globalHeaders,...this.caller?{"X-Caller":this.caller}:{},...await this.getAuthHeadersCallback(),...e}}createTimeoutSignal(e){let i=new AbortController,r=setTimeout(()=>i.abort(),this.timeout);if(e){let s=()=>i.abort();e.addEventListener("abort",s),e.aborted&&i.abort()}return{signal:i.signal,cleanup:()=>clearTimeout(r)}}safeClone(e){try{return e.clone()}catch{return e}}async parseResponse(e){if(!(e.headers.get("Content-Length")==="0"||e.status===204))return e.json()}async deploy(e,i={}){if(!e.length)throw a.business("No files to deploy");for(let o of e)if(!o.md5)throw a.file(`MD5 checksum missing for file: ${o.path}`,{filePath:o.path});Y(i.password);let r=O(i.labels),s=i.build||i.prerender||i.spa?{build:i.build,prerender:i.prerender,spa:i.spa}:void 0,{body:l,headers:u}=await this.createDeployBody(e,{labels:r,via:i.via,password:i.password,flags:s,captcha:i.captcha});return this.request(`${this.apiUrl}${this.deployEndpoint}`,{method:"POST",body:l,headers:u,signal:i.signal||null},"Deploy")}async listDeployments(){return this.request(`${this.apiUrl}${h.DEPLOYMENTS}`,{method:"GET"},"List deployments")}async getDeployment(e){return this.request(`${this.apiUrl}${h.DEPLOYMENTS}/${encodeURIComponent(e)}`,{method:"GET"},"Get deployment")}async updateDeploymentLabels(e,i){let r=O(i);return this.request(`${this.apiUrl}${h.DEPLOYMENTS}/${encodeURIComponent(e)}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({labels:r})},"Update deployment labels")}async removeDeployment(e){await this.request(`${this.apiUrl}${h.DEPLOYMENTS}/${encodeURIComponent(e)}`,{method:"DELETE"},"Remove deployment")}async setDomain(e,i,r){let s=O(r),l={};i&&(l.deployment=i),s!==void 0&&(l.labels=s);let{data:u,status:o}=await this.requestWithStatus(`${this.apiUrl}${h.DOMAINS}/${encodeURIComponent(e)}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)},"Set domain");return{...u,isCreate:o===201}}async listDomains(){return this.request(`${this.apiUrl}${h.DOMAINS}`,{method:"GET"},"List domains")}async getDomain(e){return this.request(`${this.apiUrl}${h.DOMAINS}/${encodeURIComponent(e)}`,{method:"GET"},"Get domain")}async removeDomain(e){await this.request(`${this.apiUrl}${h.DOMAINS}/${encodeURIComponent(e)}`,{method:"DELETE"},"Remove domain")}async verifyDomain(e){return this.request(`${this.apiUrl}${h.DOMAINS}/${encodeURIComponent(e)}/verify`,{method:"POST"},"Verify domain")}async getDomainDns(e){return this.request(`${this.apiUrl}${h.DOMAINS}/${encodeURIComponent(e)}/dns`,{method:"GET"},"Get domain DNS")}async getDomainRecords(e){return this.request(`${this.apiUrl}${h.DOMAINS}/${encodeURIComponent(e)}/records`,{method:"GET"},"Get domain records")}async getDomainShare(e){return this.request(`${this.apiUrl}${h.DOMAINS}/${encodeURIComponent(e)}/share`,{method:"GET"},"Get domain share")}async validateDomain(e){return this.request(`${this.apiUrl}${h.DOMAINS}/validate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({domain:e})},"Validate domain")}async createToken(e,i){let r=O(i),s={};return e!==void 0&&(s.ttl=e),r!==void 0&&(s.labels=r),this.request(`${this.apiUrl}${h.TOKENS}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)},"Create token")}async listTokens(){return this.request(`${this.apiUrl}${h.TOKENS}`,{method:"GET"},"List tokens")}async removeToken(e){await this.request(`${this.apiUrl}${h.TOKENS}/${encodeURIComponent(e)}`,{method:"DELETE"},"Remove token")}async getAccount(){return this.request(`${this.apiUrl}${h.ACCOUNT}`,{method:"GET"},"Get account")}async getLimits(){return this.request(`${this.apiUrl}${h.LIMITS}`,{method:"GET"},"Get limits")}async ping(){return(await this.request(`${this.apiUrl}${h.PING}`,{method:"GET"},"Ping"))?.success||!1}async checkSPA(e,i={}){let r=e.find(o=>o.path==="index.html"||o.path==="/index.html");if(!r||r.size>100*1024)return!1;let s;if(typeof Buffer<"u"&&Buffer.isBuffer(r.content))s=r.content.toString("utf-8");else if(typeof Blob<"u"&&r.content instanceof Blob)s=await r.content.text();else if(typeof File<"u"&&r.content instanceof File)s=await r.content.text();else return!1;let l={files:e.map(o=>o.path),index:s};return(await this.request(`${this.apiUrl}${h.SPA_CHECK}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)},"SPA check")).isSPA}};g();function ye(n,t){let e={...n};return e.timeout===void 0&&t.timeout!==void 0&&(e.timeout=t.timeout),e.maxConcurrency===void 0&&t.maxConcurrency!==void 0&&(e.maxConcurrency=t.maxConcurrency),e.onProgress===void 0&&t.onProgress!==void 0&&(e.onProgress=t.onProgress),e}g();B();async function Ye(){let n=JSON.stringify(ue,null,2),t;typeof Buffer<"u"?t=Buffer.from(n,"utf-8"):t=new Blob([n],{type:"application/json"});let{md5:e}=await M(t);return{path:q,content:t,size:n.length,md5:e}}async function ge(n,t,e){if(e.spaDetect===!1||e.spa||e.build||e.prerender||n.some(i=>i.path===q))return n;try{if(await t.checkSPA(n,e)){let r=await Ye();return[...n,r]}}catch{}return n}function Ee(n){let{getApi:t,ensureInit:e,processInput:i,clientDefaults:r}=n;return{upload:async(s,l={})=>{await e();let u=r?ye(l,r):l;if(!i)throw a.config("processInput function is not provided.");let o=t(),p=await i(s,u);return p=await ge(p,o,u),o.deploy(p,u)},list:async()=>(await e(),t().listDeployments()),get:async s=>(await e(),t().getDeployment(s)),set:async(s,l)=>(await e(),t().updateDeploymentLabels(s,l.labels)),remove:async s=>{await e(),await t().removeDeployment(s)}}}function De(n){let{getApi:t,ensureInit:e}=n;return{set:async(i,r={})=>(await e(),t().setDomain(i,r.deployment,r.labels)),list:async()=>(await e(),t().listDomains()),get:async i=>(await e(),t().getDomain(i)),remove:async i=>{await e(),await t().removeDomain(i)},verify:async i=>(await e(),t().verifyDomain(i)),validate:async i=>(await e(),t().validateDomain(i)),dns:async i=>(await e(),t().getDomainDns(i)),records:async i=>(await e(),t().getDomainRecords(i)),share:async i=>(await e(),t().getDomainShare(i))}}function Se(n){let{getApi:t,ensureInit:e}=n;return{get:async()=>(await e(),t().getAccount())}}function Te(n){let{getApi:t,ensureInit:e}=n;return{create:async(i={})=>(await e(),t().createToken(i.ttl,i.labels)),list:async()=>(await e(),t().listTokens()),remove:async i=>{await e(),await t().removeToken(i)}}}var H=class{constructor(t={}){this.initPromise=null;this.platformLimits=null;this.credential=null;if(t={...t,apiUrl:t.apiUrl||void 0,token:t.token||void 0,caller:t.caller||void 0},this.clientOptions=t,t.caller!==void 0&&me(t.caller),t.token&&t.session)throw a.config("Provide either `token` or `session`, not both.");typeof t.token=="string"?(K(t.token),this.credential=t.token):t.token&&(this.credential=t.token),this.http=new U({...t,getAuthHeaders:()=>this.getAuthHeaders(),createDeployBody:this.getDeployBodyCreator()});let e={getApi:()=>this.http,ensureInit:()=>this.ensureInitialized()};this.deployments=Ee({...e,processInput:(i,r)=>this.processInput(i,r),clientDefaults:this.clientOptions}),this.domains=De(e),this.account=Se(e),this.tokens=Te(e)}async ensureInitialized(){return this.initPromise||(this.initPromise=this.fetchPlatformLimits()),this.initPromise}async fetchPlatformLimits(){try{this.platformLimits=await this.http.getLimits()}catch(t){throw this.initPromise=null,t}}async ping(){return await this.ensureInitialized(),this.http.ping()}async deploy(t,e){return this.deployments.upload(t,e)}async whoami(){return this.account.get()}async getLimits(){return this.platformLimits?this.platformLimits:(await this.ensureInitialized(),this.platformLimits)}on(t,e){this.http.on(t,e)}off(t,e){this.http.off(t,e)}setHeaders(t){this.http.setGlobalHeaders(t)}clearHeaders(){this.http.setGlobalHeaders({})}setToken(t){if(this.clientOptions.session)throw a.config("Provide either `token` or `session`, not both.");if(typeof t=="string"){if(!t)throw a.business("Invalid token provided. Token must be a non-empty string.");K(t),this.credential=t;return}if(typeof t!="function")throw a.business("Invalid token provided. Token must be a non-empty string or a provider function.");this.credential=t}async getAuthHeaders(){if(this.credential===null)return{};let t=typeof this.credential=="function"?await this.credential():this.credential;if(!t)throw a.authentication("Token provider returned no token.");if(typeof t!="string")throw a.authentication("Token provider returned a non-string value.");return{Authorization:`Bearer ${t}`}}};F();g();import{z as Re}from"zod";import{z as Ae}from"zod";var we={apiUrl:Ae.string().url().optional(),token:Ae.string().min(1).optional()};F();var Je=Re.object(we).strict(),Qe={apiUrl:"SHIP_API_URL",token:"SHIP_TOKEN"};function Pe(){if(I()!=="node")return{};let n={apiUrl:process.env.SHIP_API_URL||void 0,token:process.env.SHIP_TOKEN||void 0};try{return Je.parse(n)}catch(t){if(t instanceof Re.ZodError){let e=t.issues[0],i=e.path[0],r=(i&&Qe[i])??"SHIP environment configuration";throw a.config(`Invalid ${r}: ${e.message}`)}throw a.config("Invalid environment configuration")}}g();async function ve(n,t={}){let{FormData:e,File:i}=await import("formdata-node"),{FormDataEncoder:r}=await import("form-data-encoder"),{labels:s,via:l,password:u,flags:o,captcha:p}=t,d=new e,A=[];for(let c of n){if(!Buffer.isBuffer(c.content)&&!(typeof Blob<"u"&&c.content instanceof Blob))throw a.file(`Unsupported file.content type for Node.js: ${c.path}`,{filePath:c.path});if(!c.md5)throw a.file(`File missing md5 checksum: ${c.path}`,{filePath:c.path});let f=new i([c.content],c.path,{type:"application/octet-stream"});d.append("files[]",f),A.push(c.md5)}d.append("checksums",JSON.stringify(A)),s&&s.length>0&&d.append("labels",JSON.stringify(s)),l&&d.append("via",l),u&&d.append("password",u),o?.build&&d.append("build","true"),o?.prerender&&d.append("prerender","true"),o?.spa&&d.append("spa","true"),p&&d.append("captcha",p);let b=new r(d),v=[];for await(let c of b.encode())v.push(Buffer.from(c));let R=Buffer.concat(v);return{body:R.buffer.slice(R.byteOffset,R.byteOffset+R.byteLength),headers:{"Content-Type":b.contentType,"Content-Length":Buffer.byteLength(R).toString()}}}g();g();Z();F();ne();ie();B();re();function mn(n,t,e,i=!0){let r=n===1?t:e;return i?`${n} ${r}`:r}se();var oe=class extends H{constructor(t={}){if(I()!=="node")throw a.business("Node.js Ship class can only be used in Node.js environment.");let e=Pe();super({...t,apiUrl:t.apiUrl||e.apiUrl,token:t.token||(t.session?void 0:e.token)})}async deploy(t,e){return super.deploy(t,e)}async processInput(t,e){let i=typeof t=="string"?[t]:t;if(!Array.isArray(i)||!i.every(s=>typeof s=="string"))throw a.business("Invalid input type for Node.js environment. Expected string or string[].");if(i.length===0)throw a.business("No files to deploy.");let{processFilesForNode:r}=await Promise.resolve().then(()=>(se(),Ce));return r(i,e,this.platformLimits??void 0)}getDeployBodyCreator(){return ve}},it=oe;export{pe as API_KEY,at as AccountPlan,U as ApiHttp,ae as AuthMethod,Be as BLOCKED_EXTENSIONS,V as CALLER,X as DEFAULT_API,q as DEPLOYMENT_CONFIG_FILENAME,ce as DEPLOY_TOKEN,st as DeploymentStatus,ot as DomainStatus,m as ErrorType,y as FILE_VALIDATION_STATUS,y as FileValidationStatus,nt as JUNK_DIRECTORIES,P as LABEL_CONSTRAINTS,he as LABEL_PATTERN,lt as OAuthScope,C as PASSWORD_CONSTRAINTS,ue as SPA_DEFAULT_CONFIG,oe as Ship,a as ShipError,x as TokenKind,j as UNBUILT_PROJECT_MARKERS,He as UNSAFE_FILENAME_CHARS,Bt as __setTestEnvironment,sn as allValidFilesReady,M as calculateMD5,Ge as classifyToken,Se as createAccountResource,Ee as createDeploymentResource,De as createDomainResource,Te as createTokenResource,it as default,yt as deserializeLabels,dt as extractSubdomain,be as filterJunk,ee as formatFileSize,mt as generateDeploymentUrl,ft as generateDomainUrl,I as getENV,et as getValidFiles,_ as hasUnbuiltMarker,le as hasUnsafeChars,$ as isBlockedExtension,ut as isCustomDomain,ct as isDeployment,fe as isPlatformDomain,L as isShipError,ye as mergeDeployOptions,Ie as optimizeDeployPaths,mn as pluralize,Fe as processFilesForNode,ht as serializeLabels,ze as validateApiKey,pt as validateApiUrl,me as validateCaller,Le as validateDeployFile,Ne as validateDeployPath,Ve as validateDeployToken,te as validateFileName,rn as validateFiles,Y as validatePassword,K as validateToken};
|
|
1
|
+
var Ue=Object.defineProperty;var w=(n,t)=>()=>(n&&(t=n(n=0)),t);var Me=(n,t)=>{for(var e in t)Ue(n,e,{get:t[e],enumerable:!0})};function O(n){return n!==null&&typeof n=="object"&&"name"in n&&n.name==="ShipError"&&"status"in n}function _(n){let t=n.lastIndexOf(".");if(t===-1||t===n.length-1)return!1;let e=n.slice(t+1).toLowerCase();return Ge.has(e)}function ce(n){return ze.test(n)}function k(n){return n.replace(/\\/g,"/").split("/").filter(Boolean).some(e=>q.has(e))}function Ve(n){return n.startsWith(pe.PREFIX)?I.API_KEY:n.startsWith(ue.PREFIX)?I.DEPLOY_TOKEN:I.OPAQUE}function me(n){let t=n.charCodeAt(0)===65279?n.slice(1):n,e;try{e=JSON.parse(t)}catch(i){throw a.config(`invalid JSON format in config: ${i.message}`,{filePath:R})}if(e===null||typeof e!="object"||Array.isArray(e))throw a.config(`${R} must contain a JSON object`,{filePath:R})}function fe(n,t,e){if(!n.startsWith(t.PREFIX))throw a.validation(`${e} must start with "${t.PREFIX}"`);if(n.length!==t.TOTAL_LENGTH)throw a.validation(`${e} must be ${t.TOTAL_LENGTH} characters total (${t.PREFIX} + ${t.HEX_LENGTH} hex chars)`);let i=n.slice(t.PREFIX.length);if(!new RegExp(`^[a-f0-9]{${t.HEX_LENGTH}}$`,"i").test(i))throw a.validation(`${e} must contain ${t.HEX_LENGTH} hexadecimal characters after "${t.PREFIX}" prefix`)}function je(n){fe(n,pe,"API key")}function qe(n){fe(n,ue,"Deploy token")}function K(n){switch(Ve(n)){case I.API_KEY:je(n);return;case I.DEPLOY_TOKEN:qe(n);return;case I.OPAQUE:if(!n)throw a.validation("Token must be a non-empty string")}}function he(n){if(!n||n.length>j.MAX_LENGTH||!j.PATTERN.test(n))throw a.validation(`Caller must be 1-${j.MAX_LENGTH} characters: letters, digits, dots, underscores, or hyphens`)}function mt(n){try{let t=new URL(n);if(!["http:","https:"].includes(t.protocol))throw a.validation("API URL must use http:// or https:// protocol");if(t.pathname!=="/"&&t.pathname!=="")throw a.validation("API URL must not contain a path");if(t.search||t.hash)throw a.validation("API URL must not contain query parameters or fragments")}catch(t){throw O(t)?t:a.validation("API URL must be a valid URL")}}function ft(n){return/^[a-z]+-[a-z]+-[a-z0-9]{7}(\.[a-z0-9.-]+)?$/i.test(n)}function ye(n,t){return n.endsWith(`.${t}`)}function ht(n,t){return!ye(n,t)}function yt(n,t){return ye(n,t)?n.slice(0,-(t.length+1)):null}function gt(n){return`https://${n}`}function Et(n){return`https://${n}`}function Dt(n){return!n||n.length===0?null:JSON.stringify(n)}function St(n){if(!n)return[];try{let t=JSON.parse(n);return Array.isArray(t)?t:[]}catch{return[]}}function Y(n){if(n==null)return;if(typeof n!="string")throw a.validation("Password must be a string");let t=n.trim();if(t.length<$.MIN_LENGTH||t.length>$.MAX_LENGTH)throw a.validation(`Password must be between ${$.MIN_LENGTH} and ${$.MAX_LENGTH} characters`);return t}var lt,ct,pt,m,Be,V,He,a,Ge,ze,q,ut,le,pe,ue,j,I,dt,R,de,X,y,P,ge,$,g=w(()=>{"use strict";lt={PENDING:"pending",SUCCESS:"success",FAILED:"failed",DELETING:"deleting"},ct={PENDING:"pending",PARTIAL:"partial",SUCCESS:"success",PAUSED:"paused"},pt={FREE:"free",STANDARD:"standard",SPONSORED:"sponsored",ENTERPRISE:"enterprise",SUSPENDED:"suspended",TERMINATING:"terminating",TERMINATED:"terminated"},m={Validation:"validation_failed",NotFound:"not_found",Forbidden:"forbidden",RateLimit:"rate_limit_exceeded",Authentication:"authentication_failed",Business:"business_logic_error",Api:"internal_server_error",Network:"network_error",Cancelled:"operation_cancelled",File:"file_error",Config:"config_error"},Be=new Set([m.Network,m.Cancelled,m.File,m.Config]),V={client:new Set([m.Business,m.Config,m.File,m.Forbidden,m.NotFound,m.RateLimit,m.Validation]),network:new Set([m.Network]),auth:new Set([m.Authentication])},He=new Set(Object.values(m).filter(n=>!Be.has(n))),a=class n extends Error{type;status;details;constructor(t,e,i,r){super(e),this.type=t,this.status=i,this.details=r,this.name="ShipError"}toResponse(){let t=this.details,e=this.type===m.Authentication&&t?.internal?void 0:this.details;return{error:this.type,message:this.message,status:this.status,details:e}}static async fromHttpResponse(t,e){let i,r,s;try{if(t.headers.get("content-type")?.includes("application/json")){let u=await t.json();if(u&&typeof u=="object"){let c=u;typeof c.message=="string"?i=c.message:typeof c.error=="string"&&(i=c.error),r=c.details,typeof c.error=="string"&&He.has(c.error)&&(s=c.error)}}else{let u=await t.text();u&&(i=u)}}catch{}let l=t.headers.get("retry-after");if(l!==null){let o=l.trim(),u=/^\d+$/.test(o)?Number(o):Math.ceil((Date.parse(o)-Date.now())/1e3);if(Number.isFinite(u)&&u>=0){let c=r&&typeof r=="object"?r:{};c.retryAfter===void 0&&(r={...c,retryAfter:u})}}i=i||`${e||"Request"} failed with status ${t.status}`;let d=s??(t.status===401?m.Authentication:t.status===403?m.Forbidden:t.status===429?m.RateLimit:m.Api);return new n(d,i,t.status,r)}static fromFetchError(t,e){if(O(t))return t;let i=e||"Request";return t instanceof Error?t.name==="AbortError"?n.cancelled(`${i} was cancelled`):t instanceof TypeError&&t.message.includes("fetch")?n.network(`${i} failed: ${t.message}`,{cause:t}):new n(m.Api,`${i} failed: ${t.message}`):new n(m.Api,`${i} failed: Unknown error`)}static validation(t,e){return new n(m.Validation,t,400,e)}static notFound(t,e){let i=e?`${t} ${e} not found`:`${t} not found`;return new n(m.NotFound,i,404)}static forbidden(t,e){return new n(m.Forbidden,t,403,e)}static rateLimit(t="Too many requests",e){return new n(m.RateLimit,t,429,e)}static authentication(t="Authentication required",e){return new n(m.Authentication,t,401,e)}static business(t,e=400,i){return new n(m.Business,t,e,i)}static network(t,e){return new n(m.Network,t,void 0,e)}static cancelled(t,e){return new n(m.Cancelled,t,void 0,e)}static file(t,e){return new n(m.File,t,void 0,e)}static config(t,e){return new n(m.Config,t,void 0,e)}static api(t,e=500,i){return new n(m.Api,t,e,i)}isClientError(){return V.client.has(this.type)?!0:this.status!==void 0&&this.status>=400&&this.status<500}isNetworkError(){return V.network.has(this.type)}isAuthError(){return V.auth.has(this.type)}isType(t){return this.type===t}};Ge=new Set(["exe","msi","dll","scr","bat","cmd","com","pif","app","deb","rpm","pkg","mpkg","dmg","iso","img","cab","cpl","chm","ps1","vbs","vbe","ws","wsf","wsc","wsh","reg","jar","jnlp","apk","crx","lnk","inf","hta"]);ze=/[\x00-\x1f\x7f#?%\\<>"]/;q=new Set(["node_modules","package.json"]);ut="/auth",le={SESSION:"session",API_KEY:"apiKey",TOKEN:"token",AGENT:"agent",OAUTH:"oauth",WEBHOOK:"webhook",SYSTEM:"system"},pe={PREFIX:"ship-",HEX_LENGTH:64,TOTAL_LENGTH:69,HINT_LENGTH:4},ue={PREFIX:"deploy-",HEX_LENGTH:64,TOTAL_LENGTH:71},j={HEADER:"X-Caller",MAX_LENGTH:128,PATTERN:/^[a-zA-Z0-9._-]+$/},I={API_KEY:le.API_KEY,DEPLOY_TOKEN:le.TOKEN,OPAQUE:"opaque"};dt={ACCOUNT_READ:"account:read",DEPLOYMENTS_READ:"deployments:read",DEPLOYMENTS_WRITE:"deployments:write",DOMAINS_READ:"domains:read",DOMAINS_WRITE:"domains:write"},R="ship.json",de={rewrites:[{source:"/(.*)",destination:"/index.html"}]};X="https://api.shipstatic.com",y={PENDING:"pending",PROCESSING_ERROR:"processing_error",EXCLUDED:"excluded",VALIDATION_FAILED:"validation_failed",READY:"ready"};P={MIN_LENGTH:3,MAX_LENGTH:25,MAX_COUNT:10,SEPARATORS:"._-"},ge=/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/;$={MIN_LENGTH:6,MAX_LENGTH:128}});async function Ye(n){let t=(await import("spark-md5")).default,e=new t.ArrayBuffer,i=2097152;for(let r=0;r<n.size;r+=i){let s=Math.min(r+i,n.size);e.append(await n.slice(r,s).arrayBuffer())}return{md5:e.end()}}async function We(n){let{createHash:t}=await import("crypto"),e=t("md5");return e.update(n),{md5:e.digest("hex")}}async function Je(n){let{createHash:t}=await import("crypto"),{createReadStream:e}=await import("fs");return new Promise((i,r)=>{let s=t("md5"),l=e(n);l.on("error",d=>r(a.business(`Failed to read file for MD5: ${d.message}`))),l.on("data",d=>s.update(d)),l.on("end",()=>i({md5:s.digest("hex")}))})}async function B(n){if(n instanceof Blob)return Ye(n);if(typeof Buffer<"u"&&Buffer.isBuffer(n))return We(n);if(typeof n=="string")return Je(n);throw a.business("Invalid input for MD5 calculation")}var H=w(()=>{"use strict";g()});function Gt(n){J=n}function Ze(){return typeof process<"u"&&process.versions&&process.versions.node?"node":typeof window<"u"||typeof self<"u"?"browser":"unknown"}function b(){return J||Ze()}var J,C=w(()=>{"use strict";J=null});function be(n){if(!n||n.length===0)return"";let t=n.filter(s=>s&&typeof s=="string").map(s=>s.replace(/\\/g,"/"));if(t.length===0)return"";if(t.length===1)return t[0];let e=t.map(s=>s.split("/").filter(Boolean)),i=[],r=Math.min(...e.map(s=>s.length));for(let s=0;s<r;s++){let l=e[0][s];if(e.every(d=>d[s]===l))i.push(l);else break}return i.join("/")}function z(n){return n.replace(/\\/g,"/").replace(/\/+/g,"/").replace(/^\/+/,"")}var Q=w(()=>{"use strict"});function Le(n,t={}){if(t.flatten===!1)return n.map(i=>({path:z(i),name:Z(i)}));let e=nt(n);return n.map(i=>{let r=z(i);if(e){let s=e.endsWith("/")?e:`${e}/`;r.startsWith(s)&&(r=r.substring(s.length))}return r||(r=Z(i)),{path:r,name:Z(i)}})}function nt(n){if(!n.length)return"";let e=n.map(s=>z(s)).map(s=>s.split("/")),i=[],r=Math.min(...e.map(s=>s.length));for(let s=0;s<r-1;s++){let l=e[0][s];if(e.every(d=>d[s]===l))i.push(l);else break}return i.join("/")}function Z(n){return n.split(/[/\\]/).pop()||n}var ee=w(()=>{"use strict";Q()});function te(n,t=1){if(n===0)return"0 Bytes";let e=1024,i=["Bytes","KB","MB","GB"],r=Math.floor(Math.log(n)/Math.log(e));return`${parseFloat((n/e**r).toFixed(t))} ${i[r]}`}function ne(n){if(ce(n))return{valid:!1,reason:"File name contains unsafe characters"};if(n.startsWith(" ")||n.endsWith(" "))return{valid:!1,reason:"File name cannot start/end with spaces"};if(n.endsWith("."))return{valid:!1,reason:"File name cannot end with dots"};let t=/^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(\.|$)/i,e=n.split("/").pop()||n;return t.test(e)?{valid:!1,reason:"File name uses a reserved system name"}:n.includes("..")?{valid:!1,reason:"File name contains path traversal pattern"}:{valid:!0}}function on(n,t){let e=[],i=[],r=[];if(n.length===0){let o={file:"(no files)",message:"At least one file must be provided"};return e.push(o),{files:[],validFiles:[],errors:e,warnings:[],canDeploy:!1}}for(let o of n)if(k(o.name))return e.push({file:o.name,message:"Unbuilt project detected \u2014 deploy your build output (dist/, build/, out/), not the project folder"}),{files:n.map(u=>({...u,status:y.VALIDATION_FAILED,statusMessage:"Unbuilt project detected"})),validFiles:[],errors:e,warnings:[],canDeploy:!1};if(n.length>t.maxFilesCount){let o={file:`(${n.length} files)`,message:`File count (${n.length}) exceeds limit of ${t.maxFilesCount}`};return e.push(o),{files:n.map(u=>({...u,status:y.VALIDATION_FAILED,statusMessage:o.message})),validFiles:[],errors:e,warnings:[],canDeploy:!1}}let s=0;for(let o of n){let u=y.READY,c="Ready for upload",T=o.name?ne(o.name):{valid:!1,reason:"File name cannot be empty"};if(o.status===y.PROCESSING_ERROR)u=y.VALIDATION_FAILED,c=o.statusMessage||"File failed during processing",e.push({file:o.name,message:c});else if(o.size===0){u=y.EXCLUDED,c="File is empty (0 bytes) and cannot be deployed due to storage limitations",i.push({file:o.name,message:c}),r.push({...o,status:u,statusMessage:c});continue}else o.size<0?(u=y.VALIDATION_FAILED,c="File size must be positive",e.push({file:o.name,message:c})):!o.name||o.name.trim().length===0?(u=y.VALIDATION_FAILED,c="File name cannot be empty",e.push({file:o.name||"(empty)",message:c})):o.name.includes("\0")?(u=y.VALIDATION_FAILED,c="File name contains invalid characters (null byte)",e.push({file:o.name,message:c})):T.valid?_(o.name)?(u=y.VALIDATION_FAILED,c=`File extension not allowed: "${o.name}"`,e.push({file:o.name,message:c})):o.size>t.maxFileSize?(u=y.VALIDATION_FAILED,c=`File size (${te(o.size)}) exceeds limit of ${te(t.maxFileSize)}`,e.push({file:o.name,message:c})):(s+=o.size,s>t.maxTotalSize&&(u=y.VALIDATION_FAILED,c=`Total size would exceed limit of ${te(t.maxTotalSize)}`,e.push({file:o.name,message:c}))):(u=y.VALIDATION_FAILED,c=T.reason||"Invalid file name",e.push({file:o.name,message:c}));r.push({...o,status:u,statusMessage:c})}e.length>0&&(r=r.map(o=>o.status===y.EXCLUDED?o:{...o,status:y.VALIDATION_FAILED,statusMessage:o.status===y.VALIDATION_FAILED?o.statusMessage:"Deployment failed due to validation errors in bundle"}));let l=e.length===0?r.filter(o=>o.status===y.READY):[],d=e.length===0;return{files:r,validFiles:l,errors:e,warnings:i,canDeploy:d}}function it(n){return n.filter(t=>t.status===y.READY)}function an(n){return it(n).length>0}var ie=w(()=>{"use strict";g()});import{isJunk as rt}from"junk";function Ne(n,t){if(!n||n.length===0)return[];if(!t?.allowUnbuilt&&n.find(i=>i&&k(i)))throw a.business("Unbuilt project detected \u2014 deploy your build output (dist/, build/, out/), not the project folder");return n.filter(e=>{if(!e)return!1;let i=e.replace(/\\/g,"/").split("/").filter(Boolean);if(i.length===0)return!0;let r=i[i.length-1];if(rt(r))return!1;for(let l of i)if(l!==".well-known"&&(l.startsWith(".")||l.length>255))return!1;let s=i.slice(0,-1);for(let l of s)if(st.some(d=>l.toLowerCase()===d.toLowerCase()))return!1;return!0})}var st,re=w(()=>{"use strict";g();st=["__MACOSX",".Trashes",".fseventsd",".Spotlight-V100"]});function Oe(n,t){if(n.includes("\0")||n.includes("/../")||n.startsWith("../")||n.endsWith("/.."))throw a.business(`Security error: Unsafe file path "${n}" for file: ${t}`)}function Fe(n,t){let e=ne(n);if(!e.valid)throw a.business(e.reason||"Invalid file name");if(_(n))throw a.business(`File extension not allowed: "${t}"`)}var se=w(()=>{"use strict";g();ie()});var _e={};Me(_e,{processFilesForNode:()=>$e});import*as E from"fs";import*as D from"path";function Ce(n,t=new Set){let e=[],i=E.realpathSync(n);if(t.has(i))return e;t.add(i);let r=E.readdirSync(n);for(let s of r){let l=D.join(n,s),d=E.statSync(l);if(d.isDirectory()){let o=Ce(l,t);e.push(...o)}else d.isFile()&&e.push(l)}return e}async function $e(n,t={},e){if(b()!=="node")throw a.business("processFilesForNode can only be called in Node.js environment.");for(let p of n){let f=D.resolve(p);try{if(E.statSync(f).isDirectory()){let S=E.readdirSync(f).find(A=>q.has(A));if(S)throw a.business(`"${S}" detected \u2014 deploy your build output (dist/, build/, out/), not the project folder`)}}catch(S){if(O(S))throw S}}let i=n.flatMap(p=>{let f=D.resolve(p);try{return E.statSync(f).isDirectory()?Ce(f):[f]}catch{throw a.file(`Path does not exist: ${p}`,{filePath:p})}}),r=[...new Set(i)],s=n.map(p=>D.resolve(p)),l=be(s.map(p=>{try{return E.statSync(p).isDirectory()?p:D.dirname(p)}catch{return D.dirname(p)}})),d=r.map(p=>{if(l&&l.length>0){let f=D.relative(l,p);if(f&&typeof f=="string"&&!f.startsWith(".."))return f.replace(/\\/g,"/")}return D.basename(p)}),u=Le(d,{flatten:t.pathDetect!==!1}).map(p=>p.path),c=new Set(Ne(u));if(c.size===0)return[];let T=[],L=[];for(let p=0;p<r.length;p++)c.has(u[p])&&(T.push(r[p]),L.push(u[p]));let x=[],v=0;if(!e)throw a.config("Platform limits not provided. processFilesForNode requires the limits argument \u2014 pass `ship.getLimits()` result.");for(let p=0;p<T.length;p++){let f=T[p],S=L[p];try{Oe(S,f);let A=E.statSync(f);if(A.size===0)continue;if(Fe(S,f),A.size>e.maxFileSize)throw a.business(`File ${f} is too large. Maximum allowed size is ${e.maxFileSize/(1024*1024)}MB.`);if(v+=A.size,v>e.maxTotalSize)throw a.business(`Total deploy size is too large. Maximum allowed is ${e.maxTotalSize/(1024*1024)}MB.`);let N=E.readFileSync(f),{md5:ke}=await B(N);x.push({path:S,content:N,size:N.length,md5:ke})}catch(A){if(O(A))throw A;let N=A instanceof Error?A.message:String(A);throw a.file(`Failed to read file "${f}": ${N}`,{filePath:f})}}if(x.length>e.maxFilesCount)throw a.business(`Too many files to deploy. Maximum allowed is ${e.maxFilesCount} files.`);return x}var oe=w(()=>{"use strict";g();ee();C();re();H();Q();se()});g();g();g();var U=class{constructor(){this.handlers=new Map}on(t,e){this.handlers.has(t)||this.handlers.set(t,new Set),this.handlers.get(t)?.add(e)}off(t,e){let i=this.handlers.get(t);i&&(i.delete(e),i.size===0&&this.handlers.delete(t))}emit(t,...e){let i=this.handlers.get(t);if(!i)return;let r=Array.from(i);for(let s of r)try{s(...e)}catch(l){i.delete(s),t!=="error"&&setTimeout(()=>{let d=l instanceof Error?l:new Error(String(l));this.emit("error",d,String(t))},0)}}};g();g();function F(n){if(n==null)return;if(n.length===0)return n;if(n.length>P.MAX_COUNT)throw a.validation(`Maximum ${P.MAX_COUNT} labels allowed`);let t=n.map((i,r)=>{if(typeof i!="string")throw a.validation(`Label at index ${r} must be a string`);let s=i.trim().toLowerCase();if(s.length<P.MIN_LENGTH)throw a.validation(`Labels must be at least ${P.MIN_LENGTH} characters long`);if(s.length>P.MAX_LENGTH)throw a.validation(`Labels must be no more than ${P.MAX_LENGTH} characters long`);if(!ge.test(s))throw a.validation(`Labels must start and end with alphanumeric characters, with optional separators (${P.SEPARATORS}) between segments`);return s}),e=[...new Set(t)];if(e.length!==t.length)throw a.validation("Duplicate labels are not allowed");return e}async function Ee(n){let t=n.find(r=>r.path===R||r.path===`/${R}`);if(!t)return;let e=t.content,i=typeof e.text=="function"?await e.text():t.content.toString("utf8");me(i)}var h={DEPLOYMENTS:"/deployments",DOMAINS:"/domains",TOKENS:"/tokens",ACCOUNT:"/account",LIMITS:"/limits",PING:"/ping",SPA_CHECK:"/spa-check"},Ke=3e4,Xe="sdk";function W(n){let t=new URLSearchParams;n?.limit!==void 0&&t.set("limit",String(n.limit)),n?.cursor!==void 0&&t.set("cursor",n.cursor);let e=t.toString();return e?`?${e}`:""}var M=class extends U{constructor(e){super();this.globalHeaders={};this.apiUrl=e.apiUrl||X,this.getAuthHeadersCallback=e.getAuthHeaders,this.session=e.session??!1,this.caller=e.caller,this.timeout=e.timeout??Ke,this.fetch=e.fetch??globalThis.fetch.bind(globalThis),this.createDeployBody=e.createDeployBody,this.deployEndpoint=e.deployEndpoint||h.DEPLOYMENTS}setGlobalHeaders(e){this.globalHeaders=e}async executeRequest(e,i,r){let s=()=>{};try{let l=await this.mergeHeaders(i.headers),d=this.createTimeoutSignal(i.signal);s=d.cleanup;let o={...i,headers:l,credentials:this.session&&!l.Authorization?"include":void 0,signal:d.signal};this.emit("request",e,o);let u=await this.fetch(e,o);if(s(),!u.ok)throw await a.fromHttpResponse(u,r);return this.emit("response",this.safeClone(u),e),{data:await this.parseResponse(this.safeClone(u)),status:u.status}}catch(l){s();let d=a.fromFetchError(l,r);throw this.emit("error",d,e),d}}async request(e,i,r){let{data:s}=await this.executeRequest(e,i,r);return s}async requestWithStatus(e,i,r){return this.executeRequest(e,i,r)}async mergeHeaders(e={}){return{...this.globalHeaders,...this.caller?{"X-Caller":this.caller}:{},...await this.getAuthHeadersCallback(),...e}}createTimeoutSignal(e){let i=new AbortController,r=setTimeout(()=>i.abort(),this.timeout);if(e){let s=()=>i.abort();e.addEventListener("abort",s),e.aborted&&i.abort()}return{signal:i.signal,cleanup:()=>clearTimeout(r)}}safeClone(e){try{return e.clone()}catch{return e}}async parseResponse(e){if(!(e.headers.get("Content-Length")==="0"||e.status===204))return e.json()}async deploy(e,i={}){if(!e.length)throw a.business("No files to deploy");for(let o of e)if(!o.md5)throw a.file(`MD5 checksum missing for file: ${o.path}`,{filePath:o.path});Y(i.password);let r=F(i.labels);await Ee(e);let s=i.build||i.prerender||i.spa?{build:i.build,prerender:i.prerender,spa:i.spa}:void 0,{body:l,headers:d}=await this.createDeployBody(e,{labels:r,via:i.via??Xe,password:i.password,flags:s,captcha:i.captcha});return this.request(`${this.apiUrl}${this.deployEndpoint}`,{method:"POST",body:l,headers:d,signal:i.signal||null},"Deploy")}async listDeployments(e){return this.request(`${this.apiUrl}${h.DEPLOYMENTS}${W(e)}`,{method:"GET"},"List deployments")}async getDeployment(e){return this.request(`${this.apiUrl}${h.DEPLOYMENTS}/${encodeURIComponent(e)}`,{method:"GET"},"Get deployment")}async updateDeploymentLabels(e,i){let r=F(i);return this.request(`${this.apiUrl}${h.DEPLOYMENTS}/${encodeURIComponent(e)}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({labels:r})},"Update deployment labels")}async removeDeployment(e){await this.request(`${this.apiUrl}${h.DEPLOYMENTS}/${encodeURIComponent(e)}`,{method:"DELETE"},"Remove deployment")}async setDomain(e,i,r){let s=F(r),l={};i&&(l.deployment=i),s!==void 0&&(l.labels=s);let{data:d,status:o}=await this.requestWithStatus(`${this.apiUrl}${h.DOMAINS}/${encodeURIComponent(e)}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)},"Set domain");return{...d,isCreate:o===201}}async listDomains(e){return this.request(`${this.apiUrl}${h.DOMAINS}${W(e)}`,{method:"GET"},"List domains")}async getDomain(e){return this.request(`${this.apiUrl}${h.DOMAINS}/${encodeURIComponent(e)}`,{method:"GET"},"Get domain")}async removeDomain(e){await this.request(`${this.apiUrl}${h.DOMAINS}/${encodeURIComponent(e)}`,{method:"DELETE"},"Remove domain")}async verifyDomain(e){return this.request(`${this.apiUrl}${h.DOMAINS}/${encodeURIComponent(e)}/verify`,{method:"POST"},"Verify domain")}async getDomainDns(e){return this.request(`${this.apiUrl}${h.DOMAINS}/${encodeURIComponent(e)}/dns`,{method:"GET"},"Get domain DNS")}async getDomainRecords(e){return this.request(`${this.apiUrl}${h.DOMAINS}/${encodeURIComponent(e)}/records`,{method:"GET"},"Get domain records")}async getDomainShare(e){return this.request(`${this.apiUrl}${h.DOMAINS}/${encodeURIComponent(e)}/share`,{method:"GET"},"Get domain share")}async validateDomain(e){return this.request(`${this.apiUrl}${h.DOMAINS}/validate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({domain:e})},"Validate domain")}async createToken(e,i){let r=F(i),s={};return e!==void 0&&(s.ttl=e),r!==void 0&&(s.labels=r),this.request(`${this.apiUrl}${h.TOKENS}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)},"Create token")}async listTokens(e){return this.request(`${this.apiUrl}${h.TOKENS}${W(e)}`,{method:"GET"},"List tokens")}async removeToken(e){await this.request(`${this.apiUrl}${h.TOKENS}/${encodeURIComponent(e)}`,{method:"DELETE"},"Remove token")}async getAccount(){return this.request(`${this.apiUrl}${h.ACCOUNT}`,{method:"GET"},"Get account")}async getLimits(){return this.request(`${this.apiUrl}${h.LIMITS}`,{method:"GET"},"Get limits")}async ping(){return(await this.request(`${this.apiUrl}${h.PING}`,{method:"GET"},"Ping"))?.success||!1}async checkSPA(e,i={}){let r=e.find(o=>o.path==="index.html"||o.path==="/index.html");if(!r||r.size>100*1024)return!1;let s;if(typeof Buffer<"u"&&Buffer.isBuffer(r.content))s=r.content.toString("utf-8");else if(typeof Blob<"u"&&r.content instanceof Blob)s=await r.content.text();else if(typeof File<"u"&&r.content instanceof File)s=await r.content.text();else return!1;let l={files:e.map(o=>o.path),index:s};return(await this.request(`${this.apiUrl}${h.SPA_CHECK}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)},"SPA check")).isSPA}};g();g();H();async function Qe(){let n=JSON.stringify(de,null,2),t;typeof Buffer<"u"?t=Buffer.from(n,"utf-8"):t=new Blob([n],{type:"application/json"});let{md5:e}=await B(t);return{path:R,content:t,size:n.length,md5:e}}async function De(n,t,e){if(e.spaDetect===!1||e.spa||e.build||e.prerender||n.some(i=>i.path===R))return n;try{if(await t.checkSPA(n,e)){let r=await Qe();return[...n,r]}}catch{}return n}function Se(n){let{getApi:t,ensureInit:e,processInput:i}=n;return{upload:async(r,s={})=>{if(await e(),!i)throw a.config("processInput function is not provided.");let l=t(),d=await i(r,s);return d=await De(d,l,s),l.deploy(d,s)},list:async r=>(await e(),t().listDeployments(r)),get:async r=>(await e(),t().getDeployment(r)),set:async(r,s)=>(await e(),t().updateDeploymentLabels(r,s.labels)),remove:async r=>{await e(),await t().removeDeployment(r)}}}function Ae(n){let{getApi:t,ensureInit:e}=n;return{set:async(i,r={})=>(await e(),t().setDomain(i,r.deployment,r.labels)),list:async i=>(await e(),t().listDomains(i)),get:async i=>(await e(),t().getDomain(i)),remove:async i=>{await e(),await t().removeDomain(i)},verify:async i=>(await e(),t().verifyDomain(i)),validate:async i=>(await e(),t().validateDomain(i)),dns:async i=>(await e(),t().getDomainDns(i)),records:async i=>(await e(),t().getDomainRecords(i)),share:async i=>(await e(),t().getDomainShare(i))}}function Te(n){let{getApi:t,ensureInit:e}=n;return{get:async()=>(await e(),t().getAccount())}}function we(n){let{getApi:t,ensureInit:e}=n;return{create:async(i={})=>(await e(),t().createToken(i.ttl,i.labels)),list:async i=>(await e(),t().listTokens(i)),remove:async i=>{await e(),await t().removeToken(i)}}}var G=class{constructor(t={}){this.initPromise=null;this.platformLimits=null;this.credential=null;if(t={...t,apiUrl:t.apiUrl||void 0,token:t.token||void 0,caller:t.caller||void 0},this.clientOptions=t,t.caller!==void 0&&he(t.caller),t.token&&t.session)throw a.config("Provide either `token` or `session`, not both.");typeof t.token=="string"?(K(t.token),this.credential=t.token):t.token&&(this.credential=t.token),this.http=new M({...t,getAuthHeaders:()=>this.getAuthHeaders(),createDeployBody:this.getDeployBodyCreator()});let e={getApi:()=>this.http,ensureInit:()=>this.ensureInitialized()};this.deployments=Se({...e,processInput:(i,r)=>this.processInput(i,r)}),this.domains=Ae(e),this.account=Te(e),this.tokens=we(e)}async ensureInitialized(){return this.initPromise||(this.initPromise=this.fetchPlatformLimits()),this.initPromise}async fetchPlatformLimits(){try{this.platformLimits=await this.http.getLimits()}catch(t){throw this.initPromise=null,t}}async ping(){return await this.ensureInitialized(),this.http.ping()}async deploy(t,e){return this.deployments.upload(t,e)}async whoami(){return this.account.get()}async getLimits(){return this.platformLimits?this.platformLimits:(await this.ensureInitialized(),this.platformLimits)}on(t,e){this.http.on(t,e)}off(t,e){this.http.off(t,e)}setHeaders(t){this.http.setGlobalHeaders(t)}clearHeaders(){this.http.setGlobalHeaders({})}setToken(t){if(this.clientOptions.session)throw a.config("Provide either `token` or `session`, not both.");if(typeof t=="string"){if(!t)throw a.business("Invalid token provided. Token must be a non-empty string.");K(t),this.credential=t;return}if(typeof t!="function")throw a.business("Invalid token provided. Token must be a non-empty string or a provider function.");this.credential=t}async getAuthHeaders(){if(this.credential===null)return{};let t=typeof this.credential=="function"?await this.credential():this.credential;if(!t)throw a.authentication("Token provider returned no token.");if(typeof t!="string")throw a.authentication("Token provider returned a non-string value.");return{Authorization:`Bearer ${t}`}}};C();g();import{z as Pe}from"zod";import{z as Re}from"zod";var ve={apiUrl:Re.string().url().optional(),token:Re.string().min(1).optional()};C();var et=Pe.object(ve).strict(),tt={apiUrl:"SHIP_API_URL",token:"SHIP_TOKEN"};function xe(){if(b()!=="node")return{};let n={apiUrl:process.env.SHIP_API_URL||void 0,token:process.env.SHIP_TOKEN||void 0};try{return et.parse(n)}catch(t){if(t instanceof Pe.ZodError){let e=t.issues[0],i=e.path[0],r=(i&&tt[i])??"SHIP environment configuration";throw a.config(`Invalid ${r}: ${e.message}`)}throw a.config("Invalid environment configuration")}}g();async function Ie(n,t={}){let{FormData:e,File:i}=await import("formdata-node"),{FormDataEncoder:r}=await import("form-data-encoder"),{labels:s,via:l,password:d,flags:o,captcha:u}=t,c=new e,T=[];for(let p of n){if(!Buffer.isBuffer(p.content)&&!(typeof Blob<"u"&&p.content instanceof Blob))throw a.file(`Unsupported file.content type for Node.js: ${p.path}`,{filePath:p.path});if(!p.md5)throw a.file(`File missing md5 checksum: ${p.path}`,{filePath:p.path});let f=new i([p.content],p.path,{type:"application/octet-stream"});c.append("files[]",f),T.push(p.md5)}c.append("checksums",JSON.stringify(T)),s&&s.length>0&&c.append("labels",JSON.stringify(s)),l&&c.append("via",l),d&&c.append("password",d),o?.build&&c.append("build","true"),o?.prerender&&c.append("prerender","true"),o?.spa&&c.append("spa","true"),u&&c.append("captcha",u);let L=new r(c),x=[];for await(let p of L.encode())x.push(Buffer.from(p));let v=Buffer.concat(x);return{body:v.buffer.slice(v.byteOffset,v.byteOffset+v.byteLength),headers:{"Content-Type":L.contentType,"Content-Length":Buffer.byteLength(v).toString()}}}g();g();ee();C();ie();re();H();se();function hn(n,t,e,i=!0){let r=n===1?t:e;return i?`${n} ${r}`:r}oe();var ae=class extends G{constructor(t={}){if(b()!=="node")throw a.business("Node.js Ship class can only be used in Node.js environment.");let e=xe();super({...t,apiUrl:t.apiUrl||e.apiUrl,token:t.token||(t.session?void 0:e.token)})}async deploy(t,e){return super.deploy(t,e)}async processInput(t,e){let i=typeof t=="string"?[t]:t;if(!Array.isArray(i)||!i.every(s=>typeof s=="string"))throw a.business("Invalid input type for Node.js environment. Expected string or string[].");if(i.length===0)throw a.business("No files to deploy.");let{processFilesForNode:r}=await Promise.resolve().then(()=>(oe(),_e));return r(i,e,this.platformLimits??void 0)}getDeployBodyCreator(){return Ie}},ot=ae;export{pe as API_KEY,ut as AUTH_BASE_PATH,pt as AccountPlan,M as ApiHttp,le as AuthMethod,Ge as BLOCKED_EXTENSIONS,j as CALLER,X as DEFAULT_API,R as DEPLOYMENT_CONFIG_FILENAME,ue as DEPLOY_TOKEN,lt as DeploymentStatus,ct as DomainStatus,m as ErrorType,y as FILE_VALIDATION_STATUS,y as FileValidationStatus,st as JUNK_DIRECTORIES,P as LABEL_CONSTRAINTS,ge as LABEL_PATTERN,dt as OAuthScope,$ as PASSWORD_CONSTRAINTS,de as SPA_DEFAULT_CONFIG,ae as Ship,a as ShipError,I as TokenKind,q as UNBUILT_PROJECT_MARKERS,ze as UNSAFE_FILENAME_CHARS,Gt as __setTestEnvironment,an as allValidFilesReady,me as assertShipJsonSyntax,B as calculateMD5,Ve as classifyToken,Te as createAccountResource,Se as createDeploymentResource,Ae as createDomainResource,we as createTokenResource,ot as default,St as deserializeLabels,yt as extractSubdomain,Ne as filterJunk,te as formatFileSize,gt as generateDeploymentUrl,Et as generateDomainUrl,b as getENV,it as getValidFiles,k as hasUnbuiltMarker,ce as hasUnsafeChars,_ as isBlockedExtension,ht as isCustomDomain,ft as isDeployment,ye as isPlatformDomain,O as isShipError,Le as optimizeDeployPaths,hn as pluralize,$e as processFilesForNode,Dt as serializeLabels,je as validateApiKey,mt as validateApiUrl,he as validateCaller,Fe as validateDeployFile,Oe as validateDeployPath,qe as validateDeployToken,ne as validateFileName,on as validateFiles,Y as validatePassword,K as validateToken};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|