@shipstatic/ship 2.6.0-beta.1 → 2.6.0-beta.3
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/THIRD-PARTY-LICENSES.md +1 -1
- package/dist/browser.d.ts +103 -25
- package/dist/browser.js +1 -1
- package/dist/browser.js.map +1 -1
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +103 -25
- package/dist/index.d.ts +103 -25
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -518,11 +518,15 @@ interface TokenDeleteResponse {
|
|
|
518
518
|
* account keeps its tier through suspension and into deletion.
|
|
519
519
|
*
|
|
520
520
|
* - **Free** — `free`.
|
|
521
|
-
* - **Billed** — `pro`. The
|
|
522
|
-
* knows about, and the only
|
|
523
|
-
* derived from the Stripe
|
|
521
|
+
* - **Billed** — `pro`, `team`. The plans a customer buys; the only plans
|
|
522
|
+
* Stripe knows about, and the only ones the platform never sets by hand —
|
|
523
|
+
* each is derived from the Stripe Subscription, which names its plan on the
|
|
524
|
+
* Price it is on. They form a ladder: a dearer tier is a superset of the one
|
|
525
|
+
* below it, and the API says which is next in {@link Account.upgrade}.
|
|
524
526
|
* - **Granted** — `scale`, `sponsored`. Paid plans the operator confers by
|
|
525
|
-
* hand; no Stripe subscription, no Checkout, no Stripe object at all.
|
|
527
|
+
* hand; no Stripe subscription, no Checkout, no Stripe object at all. These
|
|
528
|
+
* and `free` are the only plans an operator can set; a billed plan is only
|
|
529
|
+
* ever Stripe's to confer.
|
|
526
530
|
*
|
|
527
531
|
* The numbers each plan confers — caps, sizes — are POLICY and are delivered
|
|
528
532
|
* by the API (`GET /plans`, `GET /account`, `GET /limits`), never published
|
|
@@ -532,23 +536,31 @@ interface TokenDeleteResponse {
|
|
|
532
536
|
declare const AccountPlan: {
|
|
533
537
|
readonly FREE: "free";
|
|
534
538
|
readonly PRO: "pro";
|
|
539
|
+
readonly TEAM: "team";
|
|
535
540
|
readonly SCALE: "scale";
|
|
536
541
|
readonly SPONSORED: "sponsored";
|
|
537
542
|
};
|
|
538
543
|
type AccountPlanType = (typeof AccountPlan)[keyof typeof AccountPlan];
|
|
539
544
|
/**
|
|
540
|
-
* The
|
|
541
|
-
* caps. One word for the count and for the ceiling: `Account.usage` and
|
|
545
|
+
* The three things an account ACCUMULATES, and therefore the three things a
|
|
546
|
+
* plan caps. One word for the count and for the ceiling: `Account.usage` and
|
|
542
547
|
* `Account.caps` are the same shape, so a surface renders "2 of 3" by
|
|
543
548
|
* dividing one by the other and can never divide by a different denominator
|
|
544
549
|
* than the 403 uses.
|
|
545
550
|
*
|
|
546
|
-
*
|
|
547
|
-
* is
|
|
548
|
-
* plan bounds how many
|
|
551
|
+
* All three are counts plans SELL, and every plan publishes a number for each.
|
|
552
|
+
* A platform subdomain (`my-app.shipstatic.com`) is among them: the namespace
|
|
553
|
+
* is the platform's, so every plan bounds how many names one account may take
|
|
554
|
+
* from it — which is not the address every deployment gets by construction
|
|
555
|
+
* (`happy-cat-abc1234.shipstatic.com`), one per deployment and bounded by
|
|
556
|
+
* `deployments` already.
|
|
549
557
|
*
|
|
550
558
|
* Every cap carries a number on every plan — never `null`, never
|
|
551
|
-
* "unlimited" — so no consumer needs an "is it bounded?" branch.
|
|
559
|
+
* "unlimited" — so no consumer needs an "is it bounded?" branch. A cap of `0`
|
|
560
|
+
* means the plan does not have the feature at all; a cap of `N` bounds
|
|
561
|
+
* creation, and what an account already holds above a cap stays until a plan
|
|
562
|
+
* TRANSITION fits it (excess paused, newest first — a domain is the only kind
|
|
563
|
+
* that pauses).
|
|
552
564
|
*
|
|
553
565
|
* A count is an aggregate over a collection, so it lives on the summary
|
|
554
566
|
* resource that owns the collection: `GET /account` for one caller, `GET
|
|
@@ -562,6 +574,12 @@ interface Caps {
|
|
|
562
574
|
* different question asked of a different resource.)
|
|
563
575
|
*/
|
|
564
576
|
readonly deployments: number;
|
|
577
|
+
/**
|
|
578
|
+
* Names the customer chose under the platform's own suffix
|
|
579
|
+
* (`my-app.shipstatic.com`) — every row, paused ones included, by the same
|
|
580
|
+
* rule as custom domains.
|
|
581
|
+
*/
|
|
582
|
+
readonly platformDomains: number;
|
|
565
583
|
/**
|
|
566
584
|
* Hostnames the customer owns — every row, paused ones included. A paused
|
|
567
585
|
* domain still occupies its slot, so deleting one is what frees capacity.
|
|
@@ -620,6 +638,37 @@ interface Account {
|
|
|
620
638
|
* mirrored on the account row for the operator surface.
|
|
621
639
|
*/
|
|
622
640
|
readonly pastDue: boolean;
|
|
641
|
+
/**
|
|
642
|
+
* Does Stripe bill this plan — is there a Subscription behind it? True for
|
|
643
|
+
* every billed tier, including one no longer on the menu (a grandfathered
|
|
644
|
+
* row keeps its subscribers), so a console cannot derive it from `/plans`.
|
|
645
|
+
* It is what sends the account to the Customer Portal rather than to
|
|
646
|
+
* Checkout, and what a granted plan (`scale`, `sponsored`) never is.
|
|
647
|
+
*/
|
|
648
|
+
readonly billed: boolean;
|
|
649
|
+
/**
|
|
650
|
+
* The next plan up the ladder this account could move to, or `null` when
|
|
651
|
+
* there is none: the top billed tier, every granted plan, and any plan not
|
|
652
|
+
* on the menu answer `null`. One server-side fact so that no surface
|
|
653
|
+
* derives "can this account upgrade, and to what" from the menu — a
|
|
654
|
+
* grandfathered row has no menu price to compare, and a granted account
|
|
655
|
+
* must never be sent to Checkout.
|
|
656
|
+
*/
|
|
657
|
+
readonly upgrade: AccountPlanType | null;
|
|
658
|
+
/**
|
|
659
|
+
* The live Subscription's billing interval — Stripe's
|
|
660
|
+
* `Price.recurring.interval`, mirrored — or `null` when no Subscription
|
|
661
|
+
* bills the account (free and granted plans). It is what lets the console
|
|
662
|
+
* offer the current plan's OTHER interval as a switch.
|
|
663
|
+
*/
|
|
664
|
+
readonly interval: BillingInterval | null;
|
|
665
|
+
/**
|
|
666
|
+
* The pending plan change, or `null`. *Up is now, down is at period end*:
|
|
667
|
+
* a downgrade is a Stripe Subscription Schedule that applies at `at`, and
|
|
668
|
+
* until then the account keeps everything it paid for. Reversible —
|
|
669
|
+
* `DELETE /billing/change` releases it.
|
|
670
|
+
*/
|
|
671
|
+
readonly scheduled: ScheduledChange | null;
|
|
623
672
|
}
|
|
624
673
|
/**
|
|
625
674
|
* Account as returned by `GET /account` — the entity plus how the request
|
|
@@ -1748,11 +1797,11 @@ interface TokenResource {
|
|
|
1748
1797
|
delete: (token: string) => Promise<TokenDeleteResponse>;
|
|
1749
1798
|
}
|
|
1750
1799
|
/**
|
|
1751
|
-
* How often a subscription renews.
|
|
1752
|
-
* intervals, so
|
|
1800
|
+
* How often a subscription renews. Every billed plan is sold at both
|
|
1801
|
+
* intervals, so a buyer chooses a plan and an interval, and nothing else.
|
|
1753
1802
|
*
|
|
1754
1803
|
* It never branches business logic — monthly and yearly confer identical
|
|
1755
|
-
* caps. It exists to be displayed and to pick a
|
|
1804
|
+
* caps. It exists to be displayed and to pick a Price at checkout.
|
|
1756
1805
|
*/
|
|
1757
1806
|
type BillingInterval = 'month' | 'year';
|
|
1758
1807
|
/**
|
|
@@ -1808,23 +1857,52 @@ interface PlansResponse {
|
|
|
1808
1857
|
readonly plans: readonly Plan[];
|
|
1809
1858
|
}
|
|
1810
1859
|
/**
|
|
1811
|
-
* The
|
|
1812
|
-
*
|
|
1860
|
+
* The body of `POST /billing/change` — the one door for "get me onto this
|
|
1861
|
+
* plan". Both fields required: with more than one billed plan there is no
|
|
1862
|
+
* honest default, and the console always knows which card was clicked.
|
|
1813
1863
|
*
|
|
1814
|
-
*
|
|
1815
|
-
*
|
|
1816
|
-
*
|
|
1817
|
-
*
|
|
1864
|
+
* The SERVER decides what the change means — the rule is *up is now, down is
|
|
1865
|
+
* at period end* — so the client holds no copy of the ladder: a free account
|
|
1866
|
+
* is sent to Stripe Checkout, a billed account moving up is sent to the
|
|
1867
|
+
* Portal's confirmation page (money moves now, so Stripe's page takes the
|
|
1868
|
+
* consent), and a billed account moving down gets a Stripe Subscription
|
|
1869
|
+
* Schedule that applies the change at period end. The answer says which
|
|
1870
|
+
* happened ({@link PlanChangeResponse}).
|
|
1818
1871
|
*/
|
|
1819
|
-
interface
|
|
1872
|
+
interface PlanChangeRequest {
|
|
1873
|
+
readonly plan: AccountPlanType;
|
|
1874
|
+
readonly interval: BillingInterval;
|
|
1875
|
+
}
|
|
1876
|
+
/**
|
|
1877
|
+
* The pending plan change — a Stripe Subscription Schedule the platform
|
|
1878
|
+
* minted, mirrored onto the account. `at` is when it applies (the current
|
|
1879
|
+
* period's end, Unix seconds). Reversible until then: `DELETE
|
|
1880
|
+
* /billing/change` releases it.
|
|
1881
|
+
*/
|
|
1882
|
+
interface ScheduledChange {
|
|
1883
|
+
readonly plan: AccountPlanType;
|
|
1884
|
+
readonly interval: BillingInterval;
|
|
1885
|
+
readonly at: number;
|
|
1886
|
+
}
|
|
1887
|
+
/**
|
|
1888
|
+
* The answer of `POST /billing/change` — exactly one field is set.
|
|
1889
|
+
*
|
|
1890
|
+
* `url` means GO: a Stripe page (Checkout, or the Portal's confirmation page)
|
|
1891
|
+
* finishes the change and the browser must be redirected to it. `scheduled`
|
|
1892
|
+
* means DONE: the downgrade is booked for period end, nothing to visit, and
|
|
1893
|
+
* the account's `scheduled` field now carries it.
|
|
1894
|
+
*/
|
|
1895
|
+
interface PlanChangeResponse {
|
|
1820
1896
|
/** Absolute URL to redirect the browser to. Single use, short-lived. */
|
|
1821
|
-
readonly url
|
|
1897
|
+
readonly url?: string;
|
|
1898
|
+
/** The pending change, when the platform scheduled it instead. */
|
|
1899
|
+
readonly scheduled?: ScheduledChange;
|
|
1822
1900
|
}
|
|
1823
1901
|
/**
|
|
1824
1902
|
* The answer of `POST /billing/portal` — Stripe's `BillingPortal.Session`,
|
|
1825
|
-
* projected the
|
|
1826
|
-
*
|
|
1827
|
-
*
|
|
1903
|
+
* projected to the one field a client needs. The Portal home: cards,
|
|
1904
|
+
* invoices, cancellation. Plan changes have their own door
|
|
1905
|
+
* ({@link PlanChangeRequest}).
|
|
1828
1906
|
*/
|
|
1829
1907
|
interface BillingPortalSession {
|
|
1830
1908
|
/** Absolute URL to redirect the browser to. Single use, short-lived. */
|
|
@@ -3027,6 +3105,6 @@ declare class Ship extends Ship$1 {
|
|
|
3027
3105
|
}
|
|
3028
3106
|
|
|
3029
3107
|
declare namespace Ship {
|
|
3030
|
-
export { API_KEY, API_PATHS, AUTH_BASE_PATH, Account, AccountDeleteResponse, AccountGetResponse, AccountKeyResponse, AccountPlan, AccountPlanType, AccountResource, Activity, ActivityEvent, ActivityListResponse, ActivityMeta, ApiDeployOptions, ApiHttp, ApiHttpOptions, AuthMethod, AuthMethodType, BillingInterval, BillingPortalSession, BillingSyncResponse, CALLER, Caps,
|
|
3108
|
+
export { API_KEY, API_PATHS, AUTH_BASE_PATH, Account, AccountDeleteResponse, AccountGetResponse, AccountKeyResponse, AccountPlan, AccountPlanType, AccountResource, Activity, ActivityEvent, ActivityListResponse, ActivityMeta, ApiDeployOptions, ApiHttp, ApiHttpOptions, AuthMethod, AuthMethodType, BillingInterval, BillingPortalSession, BillingSyncResponse, CALLER, Caps, DEFAULT_API, DEPLOYMENT_CONFIG_FILENAME, DEPLOY_FIELDS, DEPLOY_TOKEN, DeployBodyContext, DeployFile, DeployInput, DeployTransport, Deployment, DeploymentCreateResponse, DeploymentDeleteResponse, DeploymentListResponse, DeploymentOptions, DeploymentResource, DeploymentResourceContext, DeploymentSetOptions, DeploymentStatus, DeploymentStatusType, DeploymentUploadOptions, DeploymentVia, DeploymentViaType, DnsLookup, DnsProvider, DnsRecord, DnsRecordType, Domain, DomainDeleteResponse, DomainDnsResponse, DomainListResponse, DomainRecordsResponse, DomainResource, DomainSetOptions, DomainSetResult, DomainShareResponse, DomainStatus, DomainStatusType, DomainValidateResponse, DomainVerifyResponse, ErrorResponse, ErrorType, ExecutionEnvironment, FileValidationStatus as FILE_VALIDATION_STATUS, Fetch, FileValidationResult, FileValidationStatus, FileValidationStatusType, IDEMPOTENCY_KEY_CONSTRAINTS, JUNK_DIRECTORIES, LABEL_CONSTRAINTS, LABEL_PATTERN, LabelsResponse, ListOptions, ListResponse, MD5Result, MY_API_KEY_URL, OAUTH_TOKEN, OAuthScope, OAuthScopeType, PASSWORD_CONSTRAINTS, PUBLIC_DEPLOYMENT_TTL_SECONDS, PingResponse, Plan, PlanChangeRequest, PlanChangeResponse, PlansResponse, PlatformLimits, RequestResult, ResourceContext, SHIP_ENV, SIGN_IN_RETURN_PARAM, SPACheckDebug, SPACheckRequest, SPACheckResponse, SPA_CHECK_CONSTRAINTS, SPA_DEFAULT_CONFIG, ScheduledChange, SetupInstructionsResponse, ShipClientOptions, ShipError, ShipEvents, ShipRequestInit, StaticFile, TTL_CONSTRAINTS, Token, TokenCreateOptions, TokenCreateResponse, TokenDeleteResponse, TokenKind, TokenKindType, TokenListResponse, TokenProvider, TokenResource, Transport, UNBUILT_PROJECT_MARKERS, UNSAFE_FILENAME_CHARS, UploadedFile, UserVisibleActivityEvent, ValidatableFile, ValidationIssue, WEB_FILE_ACCEPT, __setTestEnvironment, allValidFilesReady, assertShipJsonSyntax, calculateMD5, classifyToken, createAccountResource, createDeploymentResource, createDomainResource, createTokenResource, deserializeLabels, extractSubdomain, filterJunk, formatFileSize, generateDeploymentUrl, generateDomainUrl, getENV, getValidFiles, hasUnbuiltMarker, hasUnsafeChars, isBlockedExtension, isCustomDomain, isDeployment, isPlatformDomain, isShipError, normalizeVia, optimizeDeployPaths, pluralize, processFilesForNode, readBearerValue, serializeLabels, validateApiKey, validateApiUrl, validateCaller, validateDeployFile, validateDeployPath, validateDeployToken, validateFileName, validateFiles, validateIdempotencyKey, validateOAuthToken, validatePassword, validateToken, validateTtl };
|
|
3031
3109
|
}
|
|
3032
3110
|
export = Ship;
|
package/dist/index.d.ts
CHANGED
|
@@ -518,11 +518,15 @@ interface TokenDeleteResponse {
|
|
|
518
518
|
* account keeps its tier through suspension and into deletion.
|
|
519
519
|
*
|
|
520
520
|
* - **Free** — `free`.
|
|
521
|
-
* - **Billed** — `pro`. The
|
|
522
|
-
* knows about, and the only
|
|
523
|
-
* derived from the Stripe
|
|
521
|
+
* - **Billed** — `pro`, `team`. The plans a customer buys; the only plans
|
|
522
|
+
* Stripe knows about, and the only ones the platform never sets by hand —
|
|
523
|
+
* each is derived from the Stripe Subscription, which names its plan on the
|
|
524
|
+
* Price it is on. They form a ladder: a dearer tier is a superset of the one
|
|
525
|
+
* below it, and the API says which is next in {@link Account.upgrade}.
|
|
524
526
|
* - **Granted** — `scale`, `sponsored`. Paid plans the operator confers by
|
|
525
|
-
* hand; no Stripe subscription, no Checkout, no Stripe object at all.
|
|
527
|
+
* hand; no Stripe subscription, no Checkout, no Stripe object at all. These
|
|
528
|
+
* and `free` are the only plans an operator can set; a billed plan is only
|
|
529
|
+
* ever Stripe's to confer.
|
|
526
530
|
*
|
|
527
531
|
* The numbers each plan confers — caps, sizes — are POLICY and are delivered
|
|
528
532
|
* by the API (`GET /plans`, `GET /account`, `GET /limits`), never published
|
|
@@ -532,23 +536,31 @@ interface TokenDeleteResponse {
|
|
|
532
536
|
declare const AccountPlan: {
|
|
533
537
|
readonly FREE: "free";
|
|
534
538
|
readonly PRO: "pro";
|
|
539
|
+
readonly TEAM: "team";
|
|
535
540
|
readonly SCALE: "scale";
|
|
536
541
|
readonly SPONSORED: "sponsored";
|
|
537
542
|
};
|
|
538
543
|
type AccountPlanType = (typeof AccountPlan)[keyof typeof AccountPlan];
|
|
539
544
|
/**
|
|
540
|
-
* The
|
|
541
|
-
* caps. One word for the count and for the ceiling: `Account.usage` and
|
|
545
|
+
* The three things an account ACCUMULATES, and therefore the three things a
|
|
546
|
+
* plan caps. One word for the count and for the ceiling: `Account.usage` and
|
|
542
547
|
* `Account.caps` are the same shape, so a surface renders "2 of 3" by
|
|
543
548
|
* dividing one by the other and can never divide by a different denominator
|
|
544
549
|
* than the 403 uses.
|
|
545
550
|
*
|
|
546
|
-
*
|
|
547
|
-
* is
|
|
548
|
-
* plan bounds how many
|
|
551
|
+
* All three are counts plans SELL, and every plan publishes a number for each.
|
|
552
|
+
* A platform subdomain (`my-app.shipstatic.com`) is among them: the namespace
|
|
553
|
+
* is the platform's, so every plan bounds how many names one account may take
|
|
554
|
+
* from it — which is not the address every deployment gets by construction
|
|
555
|
+
* (`happy-cat-abc1234.shipstatic.com`), one per deployment and bounded by
|
|
556
|
+
* `deployments` already.
|
|
549
557
|
*
|
|
550
558
|
* Every cap carries a number on every plan — never `null`, never
|
|
551
|
-
* "unlimited" — so no consumer needs an "is it bounded?" branch.
|
|
559
|
+
* "unlimited" — so no consumer needs an "is it bounded?" branch. A cap of `0`
|
|
560
|
+
* means the plan does not have the feature at all; a cap of `N` bounds
|
|
561
|
+
* creation, and what an account already holds above a cap stays until a plan
|
|
562
|
+
* TRANSITION fits it (excess paused, newest first — a domain is the only kind
|
|
563
|
+
* that pauses).
|
|
552
564
|
*
|
|
553
565
|
* A count is an aggregate over a collection, so it lives on the summary
|
|
554
566
|
* resource that owns the collection: `GET /account` for one caller, `GET
|
|
@@ -562,6 +574,12 @@ interface Caps {
|
|
|
562
574
|
* different question asked of a different resource.)
|
|
563
575
|
*/
|
|
564
576
|
readonly deployments: number;
|
|
577
|
+
/**
|
|
578
|
+
* Names the customer chose under the platform's own suffix
|
|
579
|
+
* (`my-app.shipstatic.com`) — every row, paused ones included, by the same
|
|
580
|
+
* rule as custom domains.
|
|
581
|
+
*/
|
|
582
|
+
readonly platformDomains: number;
|
|
565
583
|
/**
|
|
566
584
|
* Hostnames the customer owns — every row, paused ones included. A paused
|
|
567
585
|
* domain still occupies its slot, so deleting one is what frees capacity.
|
|
@@ -620,6 +638,37 @@ interface Account {
|
|
|
620
638
|
* mirrored on the account row for the operator surface.
|
|
621
639
|
*/
|
|
622
640
|
readonly pastDue: boolean;
|
|
641
|
+
/**
|
|
642
|
+
* Does Stripe bill this plan — is there a Subscription behind it? True for
|
|
643
|
+
* every billed tier, including one no longer on the menu (a grandfathered
|
|
644
|
+
* row keeps its subscribers), so a console cannot derive it from `/plans`.
|
|
645
|
+
* It is what sends the account to the Customer Portal rather than to
|
|
646
|
+
* Checkout, and what a granted plan (`scale`, `sponsored`) never is.
|
|
647
|
+
*/
|
|
648
|
+
readonly billed: boolean;
|
|
649
|
+
/**
|
|
650
|
+
* The next plan up the ladder this account could move to, or `null` when
|
|
651
|
+
* there is none: the top billed tier, every granted plan, and any plan not
|
|
652
|
+
* on the menu answer `null`. One server-side fact so that no surface
|
|
653
|
+
* derives "can this account upgrade, and to what" from the menu — a
|
|
654
|
+
* grandfathered row has no menu price to compare, and a granted account
|
|
655
|
+
* must never be sent to Checkout.
|
|
656
|
+
*/
|
|
657
|
+
readonly upgrade: AccountPlanType | null;
|
|
658
|
+
/**
|
|
659
|
+
* The live Subscription's billing interval — Stripe's
|
|
660
|
+
* `Price.recurring.interval`, mirrored — or `null` when no Subscription
|
|
661
|
+
* bills the account (free and granted plans). It is what lets the console
|
|
662
|
+
* offer the current plan's OTHER interval as a switch.
|
|
663
|
+
*/
|
|
664
|
+
readonly interval: BillingInterval | null;
|
|
665
|
+
/**
|
|
666
|
+
* The pending plan change, or `null`. *Up is now, down is at period end*:
|
|
667
|
+
* a downgrade is a Stripe Subscription Schedule that applies at `at`, and
|
|
668
|
+
* until then the account keeps everything it paid for. Reversible —
|
|
669
|
+
* `DELETE /billing/change` releases it.
|
|
670
|
+
*/
|
|
671
|
+
readonly scheduled: ScheduledChange | null;
|
|
623
672
|
}
|
|
624
673
|
/**
|
|
625
674
|
* Account as returned by `GET /account` — the entity plus how the request
|
|
@@ -1748,11 +1797,11 @@ interface TokenResource {
|
|
|
1748
1797
|
delete: (token: string) => Promise<TokenDeleteResponse>;
|
|
1749
1798
|
}
|
|
1750
1799
|
/**
|
|
1751
|
-
* How often a subscription renews.
|
|
1752
|
-
* intervals, so
|
|
1800
|
+
* How often a subscription renews. Every billed plan is sold at both
|
|
1801
|
+
* intervals, so a buyer chooses a plan and an interval, and nothing else.
|
|
1753
1802
|
*
|
|
1754
1803
|
* It never branches business logic — monthly and yearly confer identical
|
|
1755
|
-
* caps. It exists to be displayed and to pick a
|
|
1804
|
+
* caps. It exists to be displayed and to pick a Price at checkout.
|
|
1756
1805
|
*/
|
|
1757
1806
|
type BillingInterval = 'month' | 'year';
|
|
1758
1807
|
/**
|
|
@@ -1808,23 +1857,52 @@ interface PlansResponse {
|
|
|
1808
1857
|
readonly plans: readonly Plan[];
|
|
1809
1858
|
}
|
|
1810
1859
|
/**
|
|
1811
|
-
* The
|
|
1812
|
-
*
|
|
1860
|
+
* The body of `POST /billing/change` — the one door for "get me onto this
|
|
1861
|
+
* plan". Both fields required: with more than one billed plan there is no
|
|
1862
|
+
* honest default, and the console always knows which card was clicked.
|
|
1813
1863
|
*
|
|
1814
|
-
*
|
|
1815
|
-
*
|
|
1816
|
-
*
|
|
1817
|
-
*
|
|
1864
|
+
* The SERVER decides what the change means — the rule is *up is now, down is
|
|
1865
|
+
* at period end* — so the client holds no copy of the ladder: a free account
|
|
1866
|
+
* is sent to Stripe Checkout, a billed account moving up is sent to the
|
|
1867
|
+
* Portal's confirmation page (money moves now, so Stripe's page takes the
|
|
1868
|
+
* consent), and a billed account moving down gets a Stripe Subscription
|
|
1869
|
+
* Schedule that applies the change at period end. The answer says which
|
|
1870
|
+
* happened ({@link PlanChangeResponse}).
|
|
1818
1871
|
*/
|
|
1819
|
-
interface
|
|
1872
|
+
interface PlanChangeRequest {
|
|
1873
|
+
readonly plan: AccountPlanType;
|
|
1874
|
+
readonly interval: BillingInterval;
|
|
1875
|
+
}
|
|
1876
|
+
/**
|
|
1877
|
+
* The pending plan change — a Stripe Subscription Schedule the platform
|
|
1878
|
+
* minted, mirrored onto the account. `at` is when it applies (the current
|
|
1879
|
+
* period's end, Unix seconds). Reversible until then: `DELETE
|
|
1880
|
+
* /billing/change` releases it.
|
|
1881
|
+
*/
|
|
1882
|
+
interface ScheduledChange {
|
|
1883
|
+
readonly plan: AccountPlanType;
|
|
1884
|
+
readonly interval: BillingInterval;
|
|
1885
|
+
readonly at: number;
|
|
1886
|
+
}
|
|
1887
|
+
/**
|
|
1888
|
+
* The answer of `POST /billing/change` — exactly one field is set.
|
|
1889
|
+
*
|
|
1890
|
+
* `url` means GO: a Stripe page (Checkout, or the Portal's confirmation page)
|
|
1891
|
+
* finishes the change and the browser must be redirected to it. `scheduled`
|
|
1892
|
+
* means DONE: the downgrade is booked for period end, nothing to visit, and
|
|
1893
|
+
* the account's `scheduled` field now carries it.
|
|
1894
|
+
*/
|
|
1895
|
+
interface PlanChangeResponse {
|
|
1820
1896
|
/** Absolute URL to redirect the browser to. Single use, short-lived. */
|
|
1821
|
-
readonly url
|
|
1897
|
+
readonly url?: string;
|
|
1898
|
+
/** The pending change, when the platform scheduled it instead. */
|
|
1899
|
+
readonly scheduled?: ScheduledChange;
|
|
1822
1900
|
}
|
|
1823
1901
|
/**
|
|
1824
1902
|
* The answer of `POST /billing/portal` — Stripe's `BillingPortal.Session`,
|
|
1825
|
-
* projected the
|
|
1826
|
-
*
|
|
1827
|
-
*
|
|
1903
|
+
* projected to the one field a client needs. The Portal home: cards,
|
|
1904
|
+
* invoices, cancellation. Plan changes have their own door
|
|
1905
|
+
* ({@link PlanChangeRequest}).
|
|
1828
1906
|
*/
|
|
1829
1907
|
interface BillingPortalSession {
|
|
1830
1908
|
/** Absolute URL to redirect the browser to. Single use, short-lived. */
|
|
@@ -3026,4 +3104,4 @@ declare class Ship extends Ship$1 {
|
|
|
3026
3104
|
protected processInput(input: DeployInput, options: DeploymentOptions): Promise<StaticFile[]>;
|
|
3027
3105
|
}
|
|
3028
3106
|
|
|
3029
|
-
export { API_KEY, API_PATHS, AUTH_BASE_PATH, type Account, type AccountDeleteResponse, type AccountGetResponse, type AccountKeyResponse, AccountPlan, type AccountPlanType, type AccountResource, type Activity, type ActivityEvent, type ActivityListResponse, type ActivityMeta, type ApiDeployOptions, ApiHttp, type ApiHttpOptions, AuthMethod, type AuthMethodType, type BillingInterval, type BillingPortalSession, type BillingSyncResponse, CALLER, type Caps,
|
|
3107
|
+
export { API_KEY, API_PATHS, AUTH_BASE_PATH, type Account, type AccountDeleteResponse, type AccountGetResponse, type AccountKeyResponse, AccountPlan, type AccountPlanType, type AccountResource, type Activity, type ActivityEvent, type ActivityListResponse, type ActivityMeta, type ApiDeployOptions, ApiHttp, type ApiHttpOptions, AuthMethod, type AuthMethodType, type BillingInterval, type BillingPortalSession, type BillingSyncResponse, CALLER, type Caps, DEFAULT_API, DEPLOYMENT_CONFIG_FILENAME, DEPLOY_FIELDS, DEPLOY_TOKEN, type DeployBodyContext, type DeployFile, type DeployInput, type DeployTransport, type Deployment, type DeploymentCreateResponse, type DeploymentDeleteResponse, type DeploymentListResponse, type DeploymentOptions, type DeploymentResource, type DeploymentResourceContext, type DeploymentSetOptions, DeploymentStatus, type DeploymentStatusType, type DeploymentUploadOptions, DeploymentVia, type DeploymentViaType, type DnsLookup, type DnsProvider, type DnsRecord, type DnsRecordType, type Domain, type DomainDeleteResponse, type DomainDnsResponse, type DomainListResponse, type DomainRecordsResponse, type DomainResource, type DomainSetOptions, type DomainSetResult, type DomainShareResponse, DomainStatus, type DomainStatusType, type DomainValidateResponse, type DomainVerifyResponse, type ErrorResponse, ErrorType, type ExecutionEnvironment, FileValidationStatus as FILE_VALIDATION_STATUS, type Fetch, type FileValidationResult, FileValidationStatus, type FileValidationStatusType, IDEMPOTENCY_KEY_CONSTRAINTS, JUNK_DIRECTORIES, LABEL_CONSTRAINTS, LABEL_PATTERN, type LabelsResponse, type ListOptions, type ListResponse, type MD5Result, MY_API_KEY_URL, OAUTH_TOKEN, OAuthScope, type OAuthScopeType, PASSWORD_CONSTRAINTS, PUBLIC_DEPLOYMENT_TTL_SECONDS, type PingResponse, type Plan, type PlanChangeRequest, type PlanChangeResponse, type PlansResponse, type PlatformLimits, type RequestResult, type ResourceContext, SHIP_ENV, SIGN_IN_RETURN_PARAM, type SPACheckDebug, type SPACheckRequest, type SPACheckResponse, SPA_CHECK_CONSTRAINTS, SPA_DEFAULT_CONFIG, type ScheduledChange, type SetupInstructionsResponse, Ship, type ShipClientOptions, ShipError, type ShipEvents, type ShipRequestInit, type StaticFile, TTL_CONSTRAINTS, type Token, type TokenCreateOptions, type TokenCreateResponse, type TokenDeleteResponse, TokenKind, type TokenKindType, type TokenListResponse, type TokenProvider, type TokenResource, type Transport, UNBUILT_PROJECT_MARKERS, UNSAFE_FILENAME_CHARS, type UploadedFile, type UserVisibleActivityEvent, type ValidatableFile, type ValidationIssue, WEB_FILE_ACCEPT, __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, normalizeVia, optimizeDeployPaths, pluralize, processFilesForNode, readBearerValue, serializeLabels, validateApiKey, validateApiUrl, validateCaller, validateDeployFile, validateDeployPath, validateDeployToken, validateFileName, validateFiles, validateIdempotencyKey, validateOAuthToken, validatePassword, validateToken, validateTtl };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var qe=Object.defineProperty;var T=(e,t)=>()=>(e&&(t=e(e=0)),t);var Ye=(e,t)=>{for(var n in t)qe(e,n,{get:t[n],enumerable:!0})};function Mt(e){if(!e||typeof e!="string")return;let t=e.trim().toLowerCase();return Object.values(je).includes(t)?t:void 0}function me(e){if(e==null)return;if(typeof e!="string")throw a.validation("Idempotency key must be a string.");let t=e.trim();if(!t)throw a.validation("Idempotency key must not be empty.");if(t.length>L.MAX_LENGTH)throw a.validation(`Idempotency key must be at most ${L.MAX_LENGTH} characters.`);return t}function Qe(e){let t=e.code;return t==="ERR_INVALID_URL"?!1:typeof t=="string"?!0:e instanceof TypeError?!/\burl\b/i.test(e.message):!1}function C(e){return e!==null&&typeof e=="object"&&"name"in e&&e.name==="ShipError"&&"status"in e}function Ze(e){let t=e.replace(/\\/g,"/").split("/").pop()??"",n=t.lastIndexOf(".");return n<=0||n===t.length-1?null:t.slice(n+1).toLowerCase()}function fe(e,t){let n=Ze(e);return n===null?!1:Array.isArray(t)?t.includes(n):t.has(n)}function he(e){return tt.test(e)}function F(e){return e.replace(/\\/g,"/").split("/").filter(Boolean).some(n=>X.has(n))}function nt(e){return e.startsWith(ye.PREFIX)?D.API_KEY:e.startsWith(Ee.PREFIX)?D.DEPLOY_TOKEN:e.startsWith(ge.PREFIX)?D.OAUTH:D.OPAQUE}function Gt(e){return e.slice(0,j.length).toLowerCase()!==j?null:e.slice(j.length)||null}function Se(e){let t=e.charCodeAt(0)===65279?e.slice(1):e,n;try{n=JSON.parse(t)}catch(r){throw a.config(`invalid JSON format in config: ${r.message}`,{filePath:A})}if(n===null||typeof n!="object"||Array.isArray(n))throw a.config(`${A} must contain a JSON object`,{filePath:A})}function W(e,t,n){if(!e.startsWith(t.PREFIX))throw a.validation(`${n} must start with "${t.PREFIX}"`);if(e.length!==t.TOTAL_LENGTH)throw a.validation(`${n} must be ${t.TOTAL_LENGTH} characters total (${t.PREFIX} + ${t.HEX_LENGTH} hex chars)`);let r=e.slice(t.PREFIX.length);if(!new RegExp(`^[a-f0-9]{${t.HEX_LENGTH}}$`,"i").test(r))throw a.validation(`${n} must contain ${t.HEX_LENGTH} hexadecimal characters after "${t.PREFIX}" prefix`)}function rt(e){W(e,ye,"API key")}function it(e){W(e,Ee,"Deploy token")}function ot(e){W(e,ge,"OAuth access token")}function J(e){switch(nt(e)){case D.API_KEY:rt(e);return;case D.DEPLOY_TOKEN:it(e);return;case D.OAUTH:ot(e);return;case D.OPAQUE:if(!e)throw a.validation("Token must be a non-empty string")}}function Ae(e){if(!e||e.length>b.MAX_LENGTH||!b.PATTERN.test(e))throw a.validation(`Caller must be 1-${b.MAX_LENGTH} characters: letters, digits, dots, underscores, or hyphens`)}function zt(e){try{let t=new URL(e);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 C(t)?t:a.validation("API URL must be a valid URL")}}function Kt(e){return/^[a-z]+-[a-z]+-[a-z0-9]{7}(\.[a-z0-9.-]+)?$/i.test(e)}function Q(e){if(e!=null){if(typeof e!="number"||!Number.isFinite(e))throw a.validation("TTL must be a number of seconds");if(!Number.isInteger(e))throw a.validation("TTL must be a whole number of seconds");if(e<_.MIN_SECONDS||e>_.MAX_SECONDS)throw a.validation(`TTL must be between ${_.MIN_SECONDS} and ${_.MAX_SECONDS} seconds`);return e}}function Re(e,t){return e.endsWith(`.${t}`)}function Yt(e,t){return!Re(e,t)}function jt(e,t){return Re(e,t)?e.slice(0,-(t.length+1)):null}function Xt(e){return`https://${e}`}function Wt(e){return`https://${e}`}function Jt(e){return!e||e.length===0?null:JSON.stringify(e)}function Qt(e){if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}function ee(e){if(e==null)return;if(typeof e!="string")throw a.validation("Password must be a string");let t=e.trim();if(t.length<v.MIN_LENGTH||t.length>v.MAX_LENGTH)throw a.validation(`Password must be between ${v.MIN_LENGTH} and ${v.MAX_LENGTH} characters`);return t}var Ct,je,Ft,L,kt,m,S,d,Xe,q,We,Je,a,et,Ut,tt,X,Ht,$t,Y,ye,Ee,ge,b,D,j,Bt,A,Te,M,_,Z,x,Vt,qt,h,I,De,v,f=T(()=>{"use strict";Ct={PENDING:"pending",SUCCESS:"success",FAILED:"failed",DELETING:"deleting"},je={WEB:"web",SDK:"sdk",CLI:"cli",MCP:"mcp",GIT:"git",N8N:"n8n",GPT:"gpt",VSC:"vsc",CLD:"cld",CRS:"crs",API:"api"},Ft={PENDING:"pending",PARTIAL:"partial",SUCCESS:"success",PAUSED:"paused"},L={HEADER:"Idempotency-Key",MAX_LENGTH:256,WINDOW_SECONDS:1440*60};kt={FREE:"free",PRO:"pro",SCALE:"scale",SPONSORED:"sponsored"},m={DEPLOYMENTS:"/deployments",DEPLOYMENT:e=>`/deployments/${e}`,DEPLOYMENT_CONFIG:e=>`/deployments/${e}/config`,DOMAINS:"/domains",DOMAIN:e=>`/domains/${e}`,DOMAIN_VERIFY:e=>`/domains/${e}/verify`,DOMAIN_DNS:e=>`/domains/${e}/dns`,DOMAIN_RECORDS:e=>`/domains/${e}/records`,DOMAIN_SHARE:e=>`/domains/${e}/share`,DOMAIN_PROPAGATION:e=>`/domains/${e}/propagation`,DOMAINS_VALIDATE:"/domains/validate",TOKENS:"/tokens",TOKEN:e=>`/tokens/${e}`,ACCOUNT:"/account",ACCOUNT_KEY:"/account/key",ACCOUNT_CLAIM:"/account/claim",ACTIVITIES:"/activities",LABELS:"/labels",LIMITS:"/limits",PLANS:"/plans",PING:"/ping",SETUP:"/setup",SPA_CHECK:"/spa-check",UPLOAD:"/upload"},S={FILES:"files[]",CHECKSUMS:"checksums",LABELS:"labels",VIA:"via",PASSWORD:"password",TTL:"ttl",BUILD:"build",PRERENDER:"prerender",SPA:"spa",CAPTCHA:"captcha"},d={Validation:"validation_failed",NotFound:"not_found",Forbidden:"forbidden",RateLimit:"rate_limit_exceeded",Authentication:"authentication_failed",Business:"business_logic_error",Api:"internal_server_error",Maintenance:"maintenance",Network:"network_error",Timeout:"timeout_error",Cancelled:"operation_cancelled",File:"file_error",Config:"config_error"},Xe=new Set([d.Network,d.Timeout,d.Cancelled,d.File,d.Config]),q={client:new Set([d.Business,d.Cancelled,d.Config,d.File,d.Forbidden,d.NotFound,d.RateLimit,d.Validation]),network:new Set([d.Network,d.Timeout]),auth:new Set([d.Authentication])},We=new Set(Object.values(d).filter(e=>!Xe.has(e))),Je=200;a=class e extends Error{type;status;details;constructor(t,n,r,i){super(n),this.type=t,this.status=r,this.details=i,this.name="ShipError"}toResponse(){let t=this.details,n=this.type===d.Authentication&&t?.internal?void 0:this.details;return{error:this.type,message:this.message,status:this.status,details:n}}static async fromHttpResponse(t,n){let r,i,o;try{if(t.headers.get("content-type")?.includes("application/json")){let u=await t.json();if(u&&typeof u=="object"){let p=u;typeof p.message=="string"?r=p.message:typeof p.error=="string"&&(r=p.error),i=p.details,typeof p.error=="string"&&We.has(p.error)&&(o=p.error)}}else{let u=(await t.text()).trim();u&&!u.startsWith("<")&&u.length<=Je&&(r=u)}}catch{}let l=t.headers.get("retry-after");if(l!==null){let s=l.trim(),u=/^\d+$/.test(s)?Number(s):Math.ceil((Date.parse(s)-Date.now())/1e3);if(Number.isFinite(u)&&u>=0){let p=i&&typeof i=="object"?i:{};p.retryAfter===void 0&&(i={...p,retryAfter:u})}}r=r||`${n||"Request"} failed with status ${t.status}`;let c=o??(t.status===401?d.Authentication:t.status===403?d.Forbidden:t.status===429?d.RateLimit:d.Api);return new e(c,r,t.status,i)}static fromFetchError(t,n){if(C(t))return t;let r=n||"Request",i=t?.name;return i==="AbortError"?e.cancelled(`${r} was cancelled`):i==="TimeoutError"?e.timeout(`${r} timed out`,{cause:t}):t instanceof Error?Qe(t)?e.network(`${r} failed: ${t.message}`,{cause:t}):new e(d.Api,`${r} failed: ${t.message}`):new e(d.Api,`${r} failed: Unknown error`)}static validation(t,n){return new e(d.Validation,t,400,n)}static notFound(t,n){let r=n?`${t} ${n} not found`:`${t} not found`;return new e(d.NotFound,r,404)}static forbidden(t,n){return new e(d.Forbidden,t,403,n)}static rateLimit(t="Too many requests",n){return new e(d.RateLimit,t,429,n)}static authentication(t="Authentication required",n){return new e(d.Authentication,t,401,n)}static business(t,n=400,r){return new e(d.Business,t,n,r)}static network(t,n){return new e(d.Network,t,void 0,n)}static timeout(t,n){return new e(d.Timeout,t,void 0,n)}static cancelled(t,n){return new e(d.Cancelled,t,void 0,n)}static file(t,n){return new e(d.File,t,void 0,n)}static config(t,n){return new e(d.Config,t,void 0,n)}static api(t,n=500,r){return new e(d.Api,t,n,r)}static maintenance(t,n){return new e(d.Maintenance,t,503,n)}isClientError(){return q.client.has(this.type)?!0:this.status!==void 0&&this.status>=400&&this.status<500}isNetworkError(){return q.network.has(this.type)}isAuthError(){return q.auth.has(this.type)}isType(t){return this.type===t}};et=["html","htm","xhtml","xml","txt","md","markdown","pdf","csv","json","jsonc","webmanifest","map","toml","yaml","yml","rss","atom","css","scss","sass","less","js","mjs","cjs","jsx","ts","tsx","wasm","vue","svelte","png","jpg","jpeg","gif","webp","avif","svg","ico","bmp","tif","tiff","heic","heif","woff","woff2","ttf","otf","eot","mp3","wav","ogg","oga","opus","m4a","aac","flac","weba","mp4","webm","ogv","mov","m4v","avi","glb","gltf","usdz","vtt","srt","zip"],Ut=et.map(e=>`.${e}`).join(","),tt=/[\x00-\x1f\x7f#?%\\<>"]/;X=new Set(["node_modules","package.json"]);Ht="/auth",$t="signing-in",Y={SESSION:"session",API_KEY:"apiKey",TOKEN:"token",AGENT:"agent",OAUTH:"oauth",WEBHOOK:"webhook",SYSTEM:"system"},ye={PREFIX:"ship-",HEX_LENGTH:32,TOTAL_LENGTH:37,HINT_LENGTH:4},Ee={PREFIX:"deploy-",HEX_LENGTH:32,TOTAL_LENGTH:39},ge={PREFIX:"oauth-",HEX_LENGTH:32,TOTAL_LENGTH:38},b={HEADER:"X-Caller",MAX_LENGTH:128,PATTERN:/^[a-zA-Z0-9._-]+$/},D={API_KEY:Y.API_KEY,DEPLOY_TOKEN:Y.TOKEN,OAUTH:Y.OAUTH,OPAQUE:"opaque"};j="bearer ";Bt={ACCOUNT_READ:"account:read",DEPLOYMENTS_READ:"deployments:read",DEPLOYMENTS_WRITE:"deployments:write",DOMAINS_READ:"domains:read",DOMAINS_WRITE:"domains:write"},A="ship.json",Te={rewrites:[{source:"/(.*)",destination:"/index.html"}]},M={INDEX_FILE:"index.html",MAX_INDEX_BYTES:100*1024};_={MIN_SECONDS:1,MAX_SECONDS:365*24*60*60};Z="https://api.shipstatic.com",x={TOKEN:"SHIP_TOKEN",API_URL:"SHIP_API_URL"},Vt="https://my.shipstatic.com/api-key",qt=4320*60,h={PENDING:"pending",PROCESSING_ERROR:"processing_error",EXCLUDED:"excluded",VALIDATION_FAILED:"validation_failed",READY:"ready"};I={MIN_LENGTH:3,MAX_LENGTH:25,MAX_COUNT:10,SEPARATORS:"._-"},De=/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/;v={MIN_LENGTH:6,MAX_LENGTH:128}});async function ft(e){let t=(await import("spark-md5")).default,n=new t.ArrayBuffer,r=2097152;for(let i=0;i<e.size;i+=r){let o=Math.min(i+r,e.size);n.append(await e.slice(i,o).arrayBuffer())}return{md5:n.end()}}async function ht(e){let{createHash:t}=await import("crypto"),n=t("md5");return n.update(e),{md5:n.digest("hex")}}async function yt(e){let{createHash:t}=await import("crypto"),{createReadStream:n}=await import("fs");return new Promise((r,i)=>{let o=t("md5"),l=n(e);l.on("error",c=>i(a.file(`Failed to read file for MD5: ${c.message}`,{filePath:e}))),l.on("data",c=>o.update(c)),l.on("end",()=>r({md5:o.digest("hex")}))})}async function H(e){if(e instanceof Blob)return ft(e);if(typeof Buffer<"u"&&Buffer.isBuffer(e))return ht(e);if(typeof e=="string")return yt(e);throw a.business("Invalid input for MD5 calculation")}var $=T(()=>{"use strict";f()});function In(e){ne=e}function St(){return typeof process<"u"&&process.versions&&process.versions.node?"node":typeof window<"u"||typeof self<"u"?"browser":"unknown"}function N(){return ne||St()}var ne,w=T(()=>{"use strict";ne=null});function Me(e){if(!e||e.length===0)return"";let t=e.filter(o=>o&&typeof o=="string").map(o=>o.replace(/\\/g,"/"));if(t.length===0)return"";if(t.length===1)return t[0];let n=t.map(o=>o.split("/").filter(Boolean)),r=[],i=Math.min(...n.map(o=>o.length));for(let o=0;o<i;o++){let l=n[0][o];if(n.every(c=>c[o]===l))r.push(l);else break}return r.join("/")}function z(e){return e.replace(/\\/g,"/").replace(/\/+/g,"/").replace(/^\/+/,"")}var re=T(()=>{"use strict"});function ke(e,t={}){if(t.flatten===!1)return e.map(r=>({path:z(r),name:ie(r)}));let n=Dt(e);return e.map(r=>{let i=z(r);if(n){let o=n.endsWith("/")?n:`${n}/`;i.startsWith(o)&&(i=i.substring(o.length))}return i||(i=ie(r)),{path:i,name:ie(r)}})}function Dt(e){if(!e.length)return"";let n=e.map(o=>z(o)).map(o=>o.split("/")),r=[],i=Math.min(...n.map(o=>o.length));for(let o=0;o<i-1;o++){let l=n[0][o];if(n.every(c=>c[o]===l))r.push(l);else break}return r.join("/")}function ie(e){return e.split(/[/\\]/).pop()||e}var oe=T(()=>{"use strict";re()});function V(e,t){return It.find(n=>n.broken(e,t))}var It,ae=T(()=>{"use strict";f();le();It=[{name:"name",broken:({path:e})=>!se(e).valid,sentence:({path:e})=>se(e).reason??"Invalid file name"},{name:"extension",broken:({path:e},t)=>fe(e,t.blockedExtensions??[]),sentence:({path:e})=>`File extension not allowed: "${e}"`},{name:"fileSize",broken:({size:e},t)=>e>t.maxFileSize,sentence:({path:e},t)=>`File "${e}" too large. Maximum ${K(t.maxFileSize)} allowed`},{name:"totalSize",broken:({totalSize:e},t)=>e>t.maxTotalSize,sentence:({totalSize:e},t)=>`Total upload size too large. ${K(e)} exceeds maximum of ${K(t.maxTotalSize)}`}]});function K(e,t=1){if(e===0)return"0 Bytes";let n=1024,r=["Bytes","KB","MB","GB"],i=Math.floor(Math.log(e)/Math.log(n));return`${parseFloat((e/n**i).toFixed(t))} ${r[i]}`}function se(e){if(he(e))return{valid:!1,reason:"File name contains unsafe characters"};if(e.startsWith(" ")||e.endsWith(" "))return{valid:!1,reason:"File name cannot start/end with spaces"};if(e.endsWith("."))return{valid:!1,reason:"File name cannot end with dots"};let t=/^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(\.|$)/i,n=e.split("/").pop()||e;return t.test(n)?{valid:!1,reason:"File name uses a reserved system name"}:e.includes("..")?{valid:!1,reason:"File name contains path traversal pattern"}:{valid:!0}}function zn(e,t){let n=[],r=[],i=[];if(e.length===0){let s={file:"(no files)",message:"At least one file must be provided"};return n.push(s),{files:[],validFiles:[],errors:n,warnings:[],canDeploy:!1}}for(let s of e)if(F(s.name))return n.push({file:s.name,message:"Unbuilt project detected \u2014 deploy your build output (dist/, build/, out/), not the project folder"}),{files:e.map(u=>({...u,status:h.VALIDATION_FAILED,statusMessage:"Unbuilt project detected"})),validFiles:[],errors:n,warnings:[],canDeploy:!1};if(e.length>t.maxFilesCount){let s={file:`(${e.length} files)`,message:`File count (${e.length}) exceeds limit of ${t.maxFilesCount}`};return n.push(s),{files:e.map(u=>({...u,status:h.VALIDATION_FAILED,statusMessage:s.message})),validFiles:[],errors:n,warnings:[],canDeploy:!1}}let o=0;for(let s of e){let u=h.READY,p="Ready for upload";if(s.status===h.PROCESSING_ERROR)u=h.VALIDATION_FAILED,p=s.statusMessage||"File failed during processing",n.push({file:s.name,message:p});else if(s.size===0){u=h.EXCLUDED,p="File is empty (0 bytes) and cannot be deployed due to storage limitations",r.push({file:s.name,message:p}),i.push({...s,status:u,statusMessage:p});continue}else if(s.size<0)u=h.VALIDATION_FAILED,p="File size must be positive",n.push({file:s.name,message:p});else if(!s.name||s.name.trim().length===0)u=h.VALIDATION_FAILED,p="File name cannot be empty",n.push({file:s.name||"(empty)",message:p});else if(s.name.includes("\0"))u=h.VALIDATION_FAILED,p="File name contains invalid characters (null byte)",n.push({file:s.name,message:p});else{let y={path:s.name,size:s.size,totalSize:o+s.size},R=V(y,t);R?(u=h.VALIDATION_FAILED,p=R.sentence(y,t),n.push({file:R.name==="totalSize"?`(${e.length} files)`:s.name,message:p})):o=y.totalSize}i.push({...s,status:u,statusMessage:p})}n.length>0&&(i=i.map(s=>s.status===h.EXCLUDED?s:{...s,status:h.VALIDATION_FAILED,statusMessage:s.status===h.VALIDATION_FAILED?s.statusMessage:"Deployment failed due to validation errors in bundle"}));let l=n.length===0?i.filter(s=>s.status===h.READY):[],c=n.length===0;return{files:i,validFiles:l,errors:n,warnings:r,canDeploy:c}}function Lt(e){return e.filter(t=>t.status===h.READY)}function Kn(e){return Lt(e).length>0}var le=T(()=>{"use strict";f();ae()});import{isJunk as Nt}from"junk";function Ue(e,t){if(!e||e.length===0)return[];if(!t?.allowUnbuilt&&e.find(r=>r&&F(r)))throw a.business("Unbuilt project detected \u2014 deploy your build output (dist/, build/, out/), not the project folder");return e.filter(n=>{if(!n)return!1;let r=n.replace(/\\/g,"/").split("/").filter(Boolean);if(r.length===0)return!0;let i=r[r.length-1];if(Nt(i))return!1;for(let l of r)if(l!==".well-known"&&(l.startsWith(".")||l.length>255))return!1;let o=r.slice(0,-1);for(let l of o)if(Pt.some(c=>l.toLowerCase()===c.toLowerCase()))return!1;return!0})}var Pt,pe=T(()=>{"use strict";f();Pt=["__MACOSX",".Trashes",".fseventsd",".Spotlight-V100"]});function He(e,t){if(e.includes("\0")||e.includes("/../")||e.startsWith("../")||e.endsWith("/.."))throw a.business(`Security error: Unsafe file path "${e}" for file: ${t}`)}function $e(e,t){let n=V(e,t);if(n)throw a.business(n.sentence(e,t))}var ce=T(()=>{"use strict";f();ae()});async function Ge(e,t={},n){let r=!!(t.build||t.prerender),i=ke(e.map(p=>p.path),{flatten:t.pathDetect!==!1}).map(p=>p.path),o=new Set(Ue(i,{allowUnbuilt:r})),l=e.map((p,y)=>({source:p,deployPath:i[y]})).filter(({deployPath:p})=>o.has(p));if(l.length===0)return[];let c=r?null:bt(n),s=[],u=0;for(let{source:p,deployPath:y}of l){if(c&&He(y,p.origin),p.size===0)continue;c&&(u+=p.size,$e({path:y,size:p.size,totalSize:u},c));let R=await p.read(),{md5:P}=await H(R);s.push({path:y,content:R,size:p.size,md5:P})}if(c&&s.length>c.maxFilesCount)throw a.business(`Too many files to deploy. Maximum allowed is ${c.maxFilesCount} files.`);return s}function bt(e){if(!e)throw a.config("Platform limits not provided. Deploy-mode validation requires the limits argument \u2014 pass `ship.getLimits()` result.");return e}var Be=T(()=>{"use strict";f();oe();pe();$();ce()});var Ve={};Ye(Ve,{processFilesForNode:()=>Ke});import*as g from"fs";import*as E from"path";function ze(e,t=new Set){let n=[],r=g.realpathSync(e);if(t.has(r))return n;t.add(r);for(let i of g.readdirSync(e)){let o=E.join(e,i),l=g.statSync(o);l.isDirectory()?n.push(...ze(o,t)):l.isFile()&&n.push({absPath:o,size:l.size})}return n}async function xt(e){try{return g.readFileSync(e)}catch(t){let n=t instanceof Error?t.message:String(t);throw a.file(`Failed to read file "${e}": ${n}`,{filePath:e})}}function Ot(e){for(let t of e){let n=E.resolve(t);try{if(g.statSync(n).isDirectory()){let r=g.readdirSync(n).find(i=>X.has(i));if(r)throw a.business(`"${r}" detected \u2014 deploy your build output (dist/, build/, out/), not the project folder`)}}catch(r){if(C(r))throw r}}}async function Ke(e,t={},n){if(N()!=="node")throw a.business("processFilesForNode can only be called in Node.js environment.");Ot(e);let r=e.flatMap(c=>{let s=E.resolve(c);try{let u=g.statSync(s);return u.isDirectory()?ze(s):[{absPath:s,size:u.size}]}catch{throw a.file(`Path does not exist: ${c}`,{filePath:c})}}),i=new Map(r.map(c=>[c.absPath,c.size])),o=Me(e.map(c=>E.resolve(c)).map(c=>{try{return g.statSync(c).isDirectory()?c:E.dirname(c)}catch{return E.dirname(c)}})),l=[...i].map(([c,s])=>({path:wt(c,o),origin:c,size:s,read:()=>xt(c)}));return Ge(l,t,n)}function wt(e,t){if(t&&t.length>0){let n=E.relative(t,e);if(n&&typeof n=="string"&&!n.startsWith(".."))return n.replace(/\\/g,"/")}return E.basename(e)}var ue=T(()=>{"use strict";f();Be();w();re()});f();f();f();var k=class{constructor(){this.handlers=new Map}on(t,n){this.handlers.has(t)||this.handlers.set(t,new Set),this.handlers.get(t)?.add(n)}off(t,n){let r=this.handlers.get(t);r&&(r.delete(n),r.size===0&&this.handlers.delete(t))}emit(t,...n){let r=this.handlers.get(t);if(!r)return;let i=Array.from(r);for(let o of i)try{o(...n)}catch(l){r.delete(o),t!=="error"&&setTimeout(()=>{let c=l instanceof Error?l:new Error(String(l));this.emit("error",c,String(t))},0)}}};var st=3e4,at=2,lt=300,pt=2e3,ct=new Set([500,502,503,504]);function ut(e,t){return new Promise((n,r)=>{if(t?.aborted){r(t.reason);return}let i=()=>{clearTimeout(l),t?.removeEventListener("abort",o)},o=()=>{i(),r(t?.reason)},l=setTimeout(()=>{i(),n()},e);t?.addEventListener("abort",o)})}var Ie=3e5,dt=3e5,mt=Ie+dt,U=class extends k{constructor(n){super();this.globalHeaders={};this.apiUrl=n.apiUrl||Z,this.getAuthHeadersCallback=n.getAuthHeaders,this.session=n.session??!1,this.caller=n.caller,this.timeout=n.timeout??st,this.maxRetries=Math.max(0,n.maxRetries??at),this.fetch=n.fetch??globalThis.fetch.bind(globalThis),this.deploy={endpoint:n.deployEndpoint||m.DEPLOYMENTS,timeout:n.timeout??Ie,buildTimeout:n.timeout??mt}}setGlobalHeaders(n){this.globalHeaders=n}async executeRequest(n,r,i,o=this.timeout){for(let l=0;;l++)try{return await this.attemptOnce(n,r,i,o)}catch(c){let s=a.fromFetchError(c,i);if(l>=this.maxRetries||!this.isRetryable(s,r))throw this.emit("error",s,n),s;this.emit("retry",s,n,l+1);let u=Math.min(pt,lt*2**l);try{await ut(Math.random()*u,r.signal)}catch(p){let y=a.fromFetchError(p,i);throw this.emit("error",y,n),y}}}isRetryable(n,r){if(r.signal?.aborted||n.isType(d.Maintenance)||n.isType(d.Cancelled)||!(n.isNetworkError()||n.status!==void 0&&ct.has(n.status)))return!1;let o=(r.method??"GET").toUpperCase();return o==="GET"||o==="HEAD"?!0:o==="PUT"||o==="DELETE"?!1:this.hasIdempotencyKey(r.headers)}hasIdempotencyKey(n){if(!n)return!1;let r=L.HEADER.toLowerCase();return Object.keys(n).some(i=>i.toLowerCase()===r)}async attemptOnce(n,r,i,o=this.timeout){let l=()=>{};try{let c=await this.mergeHeaders(r.headers),s=this.createTimeoutSignal(r.signal,o);l=s.cleanup;let u={...r,headers:c,credentials:this.session&&!c.Authorization?"include":void 0,signal:s.signal};this.emit("request",n,u);let p=await this.fetch(n,u);if(l(),!p.ok)throw await a.fromHttpResponse(p,i);return this.emit("response",this.safeClone(p),n),{data:await this.parseResponse(this.safeClone(p)),status:p.status}}catch(c){throw l(),a.fromFetchError(c,i)}}async request(n,r,i,o){let{data:l}=await this.executeRequest(`${this.apiUrl}${n}`,r,i,o);return l}async requestWithStatus(n,r,i){return this.executeRequest(`${this.apiUrl}${n}`,r,i)}async mergeHeaders(n={}){return{...this.globalHeaders,...this.caller?{[b.HEADER]:this.caller}:{},...await this.getAuthHeadersCallback(),...n}}createTimeoutSignal(n,r=this.timeout){let i=new AbortController,o=setTimeout(()=>i.abort(new DOMException(`Timed out after ${r}ms`,"TimeoutError")),r),l=n?()=>i.abort(n.reason):void 0;return n&&l&&(n.addEventListener("abort",l),n.aborted&&i.abort(n.reason)),{signal:i.signal,cleanup:()=>{clearTimeout(o),n&&l&&n.removeEventListener("abort",l)}}}safeClone(n){try{return n.clone()}catch{return n}}async parseResponse(n){if(!(n.headers.get("Content-Length")==="0"||n.status===204))return n.json()}};f();f();async function Le(e,t={}){let{labels:n,via:r,password:i,ttl:o,flags:l,captcha:c}=t,s=new FormData,u=[];for(let p of e){if(typeof p.content=="string"||p.content===null||p.content===void 0)throw a.file(`Unsupported file.content type: ${p.path}`,{filePath:p.path});if(!p.md5)throw a.file(`File missing md5 checksum: ${p.path}`,{filePath:p.path});s.append(S.FILES,new File([p.content],p.path,{type:"application/octet-stream"})),u.push(p.md5)}return s.append(S.CHECKSUMS,JSON.stringify(u)),n&&n.length>0&&s.append(S.LABELS,JSON.stringify(n)),r&&s.append(S.VIA,r),i&&s.append(S.PASSWORD,i),o!==void 0&&s.append(S.TTL,String(o)),l?.build&&s.append(S.BUILD,"true"),l?.prerender&&s.append(S.PRERENDER,"true"),l?.spa&&s.append(S.SPA,"true"),c&&s.append(S.CAPTCHA,c),s}f();$();async function Et(){let e=JSON.stringify(Te,null,2),t;typeof Buffer<"u"?t=Buffer.from(e,"utf-8"):t=new Blob([e],{type:"application/json"});let{md5:n}=await H(t);return{path:A,content:t,size:e.length,md5:n}}async function gt(e,t){let n=e.find(l=>l.path===M.INDEX_FILE||l.path===`/${M.INDEX_FILE}`);if(!n||n.size>M.MAX_INDEX_BYTES)return!1;let r;if(typeof Buffer<"u"&&Buffer.isBuffer(n.content))r=n.content.toString("utf-8");else if(typeof Blob<"u"&&n.content instanceof Blob)r=await n.content.text();else if(typeof File<"u"&&n.content instanceof File)r=await n.content.text();else return!1;let i={files:e.map(l=>l.path),index:r};return(await t.request(m.SPA_CHECK,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)},"SPA check")).isSPA}async function Ne(e,t,n){if(n.spaDetect===!1||n.spa||n.build||n.prerender||e.some(r=>r.path===A))return e;try{if(await gt(e,t)){let i=await Et();return[...e,i]}}catch{}return e}f();f();function O(e){if(e==null)return;if(e.length===0)return e;if(e.length>I.MAX_COUNT)throw a.validation(`Maximum ${I.MAX_COUNT} labels allowed`);let t=e.map((r,i)=>{if(typeof r!="string")throw a.validation(`Label at index ${i} must be a string`);let o=r.trim().toLowerCase();if(o.length<I.MIN_LENGTH)throw a.validation(`Labels must be at least ${I.MIN_LENGTH} characters long`);if(o.length>I.MAX_LENGTH)throw a.validation(`Labels must be no more than ${I.MAX_LENGTH} characters long`);if(!De.test(o))throw a.validation(`Labels must start and end with alphanumeric characters, with optional separators (${I.SEPARATORS}) between segments`);return o}),n=[...new Set(t)];if(n.length!==t.length)throw a.validation("Duplicate labels are not allowed");return n}async function Pe(e){let t=e.find(i=>i.path===A||i.path===`/${A}`);if(!t)return;let n=t.content,r=typeof n.text=="function"?await n.text():t.content.toString("utf8");Se(r)}var G={"Content-Type":"application/json"},Tt="sdk";function te(e){let t=new URLSearchParams;e?.limit!==void 0&&t.set("limit",String(e.limit)),e?.cursor!==void 0&&t.set("cursor",e.cursor);let n=t.toString();return n?`?${n}`:""}function be(e){let{getApi:t,processInput:n}=e;return{upload:async(r,i={})=>{if(!n)throw a.config("processInput function is not provided.");let o=t(),l=await n(r,i),c=await Ne(l,o,i);if(!c.length)throw a.business("No files to deploy");for(let P of c)if(!P.md5)throw a.file(`MD5 checksum missing for file: ${P.path}`,{filePath:P.path});ee(i.password);let s=Q(i.ttl),u=me(i.idempotencyKey),p=O(i.labels);await Pe(c);let y=i.build||i.prerender||i.spa?{build:i.build,prerender:i.prerender,spa:i.spa}:void 0,R=await Le(c,{labels:p,via:i.via??Tt,password:i.password,ttl:s,flags:y,captcha:i.captcha});return o.request(o.deploy.endpoint,{method:"POST",body:R,...u?{headers:{[L.HEADER]:u}}:{},signal:i.signal||null},"Deploy",i.build||i.prerender?o.deploy.buildTimeout:o.deploy.timeout)},list:async r=>t().request(`${m.DEPLOYMENTS}${te(r)}`,{method:"GET"},"List deployments"),get:async r=>t().request(m.DEPLOYMENT(encodeURIComponent(r)),{method:"GET"},"Get deployment"),set:async(r,i)=>t().request(m.DEPLOYMENT(encodeURIComponent(r)),{method:"PATCH",headers:G,body:JSON.stringify({labels:O(i.labels)})},"Update deployment labels"),delete:async r=>t().request(m.DEPLOYMENT(encodeURIComponent(r)),{method:"DELETE"},"Delete deployment")}}function xe(e){let{getApi:t}=e;return{set:async(n,r={})=>{let i=O(r.labels),o={};r.deployment&&(o.deployment=r.deployment),i!==void 0&&(o.labels=i);let{data:l,status:c}=await t().requestWithStatus(m.DOMAIN(encodeURIComponent(n)),{method:"PUT",headers:G,body:JSON.stringify(o)},"Set domain");return{...l,isCreate:c===201}},list:async n=>t().request(`${m.DOMAINS}${te(n)}`,{method:"GET"},"List domains"),get:async n=>t().request(m.DOMAIN(encodeURIComponent(n)),{method:"GET"},"Get domain"),delete:async n=>t().request(m.DOMAIN(encodeURIComponent(n)),{method:"DELETE"},"Delete domain"),verify:async n=>t().request(m.DOMAIN_VERIFY(encodeURIComponent(n)),{method:"POST"},"Verify domain"),validate:async n=>t().request(m.DOMAINS_VALIDATE,{method:"POST",headers:G,body:JSON.stringify({domain:n})},"Validate domain"),dns:async n=>t().request(m.DOMAIN_DNS(encodeURIComponent(n)),{method:"GET"},"Get domain DNS"),records:async n=>t().request(m.DOMAIN_RECORDS(encodeURIComponent(n)),{method:"GET"},"Get domain records"),share:async n=>t().request(m.DOMAIN_SHARE(encodeURIComponent(n)),{method:"GET"},"Get domain share")}}function Oe(e){let{getApi:t}=e;return{get:async()=>t().request(m.ACCOUNT,{method:"GET"},"Get account")}}function we(e){let{getApi:t}=e;return{create:async(n={})=>{let r=Q(n.ttl),i=O(n.labels),o={};return r!==void 0&&(o.ttl=r),i!==void 0&&(o.labels=i),t().request(m.TOKENS,{method:"POST",headers:G,body:JSON.stringify(o)},"Create token")},list:async n=>t().request(`${m.TOKENS}${te(n)}`,{method:"GET"},"List tokens"),get:async n=>t().request(m.TOKEN(encodeURIComponent(n)),{method:"GET"},"Get token"),delete:async n=>t().request(m.TOKEN(encodeURIComponent(n)),{method:"DELETE"},"Delete token")}}var B=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&&Ae(t.caller),t.token&&t.session)throw a.config("Provide either `token` or `session`, not both.");typeof t.token=="string"?(J(t.token),this.credential=t.token):t.token&&(this.credential=t.token),this.http=new U({...t,getAuthHeaders:()=>this.getAuthHeaders()});let n={getApi:()=>this.http};this.deployments=be({...n,processInput:async(r,i)=>(await this.ensureInitialized(),this.processInput(r,i))}),this.domains=xe(n),this.account=Oe(n),this.tokens=we(n)}async ensureInitialized(){return this.initPromise||(this.initPromise=this.fetchPlatformLimits()),this.initPromise}async fetchPlatformLimits(){try{this.platformLimits=await this.http.request(m.LIMITS,{method:"GET"},"Get limits")}catch(t){throw this.initPromise=null,t}}async ping(){return this.http.request(m.PING,{method:"GET"},"Ping")}async deploy(t,n){return this.deployments.upload(t,n)}async whoami(){return this.account.get()}async getLimits(){return this.platformLimits?this.platformLimits:(await this.ensureInitialized(),this.platformLimits)}on(t,n){this.http.on(t,n)}off(t,n){this.http.off(t,n)}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.");J(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}`}}};w();f();import{z as Ce}from"zod";import{z as _e}from"zod";var ve={apiUrl:_e.string().url().optional(),token:_e.string().min(1).optional()};w();var At=Ce.object(ve).strict(),Rt={apiUrl:x.API_URL,token:x.TOKEN};function Fe(){if(N()!=="node")return{};let e={apiUrl:process.env[x.API_URL]||void 0,token:process.env[x.TOKEN]||void 0};try{return At.parse(e)}catch(t){if(t instanceof Ce.ZodError){let n=t.issues[0],r=n.path[0],i=(r&&Rt[r])??"SHIP environment configuration";throw a.config(`Invalid ${i}: ${n.message}`)}throw a.config("Invalid environment configuration")}}f();f();oe();w();le();pe();$();ce();function Qn(e,t,n,r=!0){let i=e===1?t:n;return r?`${e} ${i}`:i}ue();var de=class extends B{constructor(t={}){if(N()!=="node")throw a.business("Node.js Ship class can only be used in Node.js environment.");let n=Fe();super({...t,apiUrl:t.apiUrl||n.apiUrl,token:t.token||(t.session?void 0:n.token)})}async deploy(t,n){return super.deploy(t,n)}async processInput(t,n){let r=typeof t=="string"?[t]:t;if(!Array.isArray(r)||!r.every(o=>typeof o=="string"))throw a.business("Invalid input type for Node.js environment. Expected string or string[].");if(r.length===0)throw a.business("No files to deploy.");let{processFilesForNode:i}=await Promise.resolve().then(()=>(ue(),Ve));return i(r,n,this.platformLimits??void 0)}},_t=de;export{ye as API_KEY,m as API_PATHS,Ht as AUTH_BASE_PATH,kt as AccountPlan,U as ApiHttp,Y as AuthMethod,b as CALLER,Z as DEFAULT_API,A as DEPLOYMENT_CONFIG_FILENAME,S as DEPLOY_FIELDS,Ee as DEPLOY_TOKEN,Ct as DeploymentStatus,je as DeploymentVia,Ft as DomainStatus,d as ErrorType,h as FILE_VALIDATION_STATUS,h as FileValidationStatus,L as IDEMPOTENCY_KEY_CONSTRAINTS,Pt as JUNK_DIRECTORIES,I as LABEL_CONSTRAINTS,De as LABEL_PATTERN,Vt as MY_API_KEY_URL,ge as OAUTH_TOKEN,Bt as OAuthScope,v as PASSWORD_CONSTRAINTS,qt as PUBLIC_DEPLOYMENT_TTL_SECONDS,x as SHIP_ENV,$t as SIGN_IN_RETURN_PARAM,M as SPA_CHECK_CONSTRAINTS,Te as SPA_DEFAULT_CONFIG,de as Ship,a as ShipError,_ as TTL_CONSTRAINTS,D as TokenKind,X as UNBUILT_PROJECT_MARKERS,tt as UNSAFE_FILENAME_CHARS,Ut as WEB_FILE_ACCEPT,In as __setTestEnvironment,Kn as allValidFilesReady,Se as assertShipJsonSyntax,H as calculateMD5,nt as classifyToken,Oe as createAccountResource,be as createDeploymentResource,xe as createDomainResource,we as createTokenResource,_t as default,Qt as deserializeLabels,jt as extractSubdomain,Ue as filterJunk,K as formatFileSize,Xt as generateDeploymentUrl,Wt as generateDomainUrl,N as getENV,Lt as getValidFiles,F as hasUnbuiltMarker,he as hasUnsafeChars,fe as isBlockedExtension,Yt as isCustomDomain,Kt as isDeployment,Re as isPlatformDomain,C as isShipError,Mt as normalizeVia,ke as optimizeDeployPaths,Qn as pluralize,Ke as processFilesForNode,Gt as readBearerValue,Jt as serializeLabels,rt as validateApiKey,zt as validateApiUrl,Ae as validateCaller,$e as validateDeployFile,He as validateDeployPath,it as validateDeployToken,se as validateFileName,zn as validateFiles,me as validateIdempotencyKey,ot as validateOAuthToken,ee as validatePassword,J as validateToken,Q as validateTtl};
|
|
1
|
+
var qe=Object.defineProperty;var T=(e,t)=>()=>(e&&(t=e(e=0)),t);var Ye=(e,t)=>{for(var n in t)qe(e,n,{get:t[n],enumerable:!0})};function Mt(e){if(!e||typeof e!="string")return;let t=e.trim().toLowerCase();return Object.values(je).includes(t)?t:void 0}function me(e){if(e==null)return;if(typeof e!="string")throw a.validation("Idempotency key must be a string.");let t=e.trim();if(!t)throw a.validation("Idempotency key must not be empty.");if(t.length>L.MAX_LENGTH)throw a.validation(`Idempotency key must be at most ${L.MAX_LENGTH} characters.`);return t}function Qe(e){let t=e.code;return t==="ERR_INVALID_URL"?!1:typeof t=="string"?!0:e instanceof TypeError?!/\burl\b/i.test(e.message):!1}function C(e){return e!==null&&typeof e=="object"&&"name"in e&&e.name==="ShipError"&&"status"in e}function Ze(e){let t=e.replace(/\\/g,"/").split("/").pop()??"",n=t.lastIndexOf(".");return n<=0||n===t.length-1?null:t.slice(n+1).toLowerCase()}function fe(e,t){let n=Ze(e);return n===null?!1:Array.isArray(t)?t.includes(n):t.has(n)}function he(e){return tt.test(e)}function F(e){return e.replace(/\\/g,"/").split("/").filter(Boolean).some(n=>X.has(n))}function nt(e){return e.startsWith(ye.PREFIX)?D.API_KEY:e.startsWith(Ee.PREFIX)?D.DEPLOY_TOKEN:e.startsWith(ge.PREFIX)?D.OAUTH:D.OPAQUE}function Gt(e){return e.slice(0,j.length).toLowerCase()!==j?null:e.slice(j.length)||null}function Se(e){let t=e.charCodeAt(0)===65279?e.slice(1):e,n;try{n=JSON.parse(t)}catch(r){throw a.config(`invalid JSON format in config: ${r.message}`,{filePath:A})}if(n===null||typeof n!="object"||Array.isArray(n))throw a.config(`${A} must contain a JSON object`,{filePath:A})}function W(e,t,n){if(!e.startsWith(t.PREFIX))throw a.validation(`${n} must start with "${t.PREFIX}"`);if(e.length!==t.TOTAL_LENGTH)throw a.validation(`${n} must be ${t.TOTAL_LENGTH} characters total (${t.PREFIX} + ${t.HEX_LENGTH} hex chars)`);let r=e.slice(t.PREFIX.length);if(!new RegExp(`^[a-f0-9]{${t.HEX_LENGTH}}$`,"i").test(r))throw a.validation(`${n} must contain ${t.HEX_LENGTH} hexadecimal characters after "${t.PREFIX}" prefix`)}function rt(e){W(e,ye,"API key")}function it(e){W(e,Ee,"Deploy token")}function ot(e){W(e,ge,"OAuth access token")}function J(e){switch(nt(e)){case D.API_KEY:rt(e);return;case D.DEPLOY_TOKEN:it(e);return;case D.OAUTH:ot(e);return;case D.OPAQUE:if(!e)throw a.validation("Token must be a non-empty string")}}function Ae(e){if(!e||e.length>b.MAX_LENGTH||!b.PATTERN.test(e))throw a.validation(`Caller must be 1-${b.MAX_LENGTH} characters: letters, digits, dots, underscores, or hyphens`)}function zt(e){try{let t=new URL(e);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 C(t)?t:a.validation("API URL must be a valid URL")}}function Kt(e){return/^[a-z]+-[a-z]+-[a-z0-9]{7}(\.[a-z0-9.-]+)?$/i.test(e)}function Q(e){if(e!=null){if(typeof e!="number"||!Number.isFinite(e))throw a.validation("TTL must be a number of seconds");if(!Number.isInteger(e))throw a.validation("TTL must be a whole number of seconds");if(e<_.MIN_SECONDS||e>_.MAX_SECONDS)throw a.validation(`TTL must be between ${_.MIN_SECONDS} and ${_.MAX_SECONDS} seconds`);return e}}function Re(e,t){return e.endsWith(`.${t}`)}function Yt(e,t){return!Re(e,t)}function jt(e,t){return Re(e,t)?e.slice(0,-(t.length+1)):null}function Xt(e){return`https://${e}`}function Wt(e){return`https://${e}`}function Jt(e){return!e||e.length===0?null:JSON.stringify(e)}function Qt(e){if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}function ee(e){if(e==null)return;if(typeof e!="string")throw a.validation("Password must be a string");let t=e.trim();if(t.length<v.MIN_LENGTH||t.length>v.MAX_LENGTH)throw a.validation(`Password must be between ${v.MIN_LENGTH} and ${v.MAX_LENGTH} characters`);return t}var Ct,je,Ft,L,kt,m,S,d,Xe,q,We,Je,a,et,Ut,tt,X,Ht,$t,Y,ye,Ee,ge,b,D,j,Bt,A,Te,M,_,Z,x,Vt,qt,h,I,De,v,f=T(()=>{"use strict";Ct={PENDING:"pending",SUCCESS:"success",FAILED:"failed",DELETING:"deleting"},je={WEB:"web",SDK:"sdk",CLI:"cli",MCP:"mcp",GIT:"git",N8N:"n8n",GPT:"gpt",VSC:"vsc",CLD:"cld",CRS:"crs",API:"api"},Ft={PENDING:"pending",PARTIAL:"partial",SUCCESS:"success",PAUSED:"paused"},L={HEADER:"Idempotency-Key",MAX_LENGTH:256,WINDOW_SECONDS:1440*60};kt={FREE:"free",PRO:"pro",TEAM:"team",SCALE:"scale",SPONSORED:"sponsored"},m={DEPLOYMENTS:"/deployments",DEPLOYMENT:e=>`/deployments/${e}`,DEPLOYMENT_CONFIG:e=>`/deployments/${e}/config`,DOMAINS:"/domains",DOMAIN:e=>`/domains/${e}`,DOMAIN_VERIFY:e=>`/domains/${e}/verify`,DOMAIN_DNS:e=>`/domains/${e}/dns`,DOMAIN_RECORDS:e=>`/domains/${e}/records`,DOMAIN_SHARE:e=>`/domains/${e}/share`,DOMAIN_PROPAGATION:e=>`/domains/${e}/propagation`,DOMAINS_VALIDATE:"/domains/validate",TOKENS:"/tokens",TOKEN:e=>`/tokens/${e}`,ACCOUNT:"/account",ACCOUNT_KEY:"/account/key",ACCOUNT_CLAIM:"/account/claim",ACTIVITIES:"/activities",LABELS:"/labels",LIMITS:"/limits",PLANS:"/plans",PING:"/ping",SETUP:"/setup",SPA_CHECK:"/spa-check",UPLOAD:"/upload"},S={FILES:"files[]",CHECKSUMS:"checksums",LABELS:"labels",VIA:"via",PASSWORD:"password",TTL:"ttl",BUILD:"build",PRERENDER:"prerender",SPA:"spa",CAPTCHA:"captcha"},d={Validation:"validation_failed",NotFound:"not_found",Forbidden:"forbidden",RateLimit:"rate_limit_exceeded",Authentication:"authentication_failed",Business:"business_logic_error",Api:"internal_server_error",Maintenance:"maintenance",Network:"network_error",Timeout:"timeout_error",Cancelled:"operation_cancelled",File:"file_error",Config:"config_error"},Xe=new Set([d.Network,d.Timeout,d.Cancelled,d.File,d.Config]),q={client:new Set([d.Business,d.Cancelled,d.Config,d.File,d.Forbidden,d.NotFound,d.RateLimit,d.Validation]),network:new Set([d.Network,d.Timeout]),auth:new Set([d.Authentication])},We=new Set(Object.values(d).filter(e=>!Xe.has(e))),Je=200;a=class e extends Error{type;status;details;constructor(t,n,r,i){super(n),this.type=t,this.status=r,this.details=i,this.name="ShipError"}toResponse(){let t=this.details,n=this.type===d.Authentication&&t?.internal?void 0:this.details;return{error:this.type,message:this.message,status:this.status,details:n}}static async fromHttpResponse(t,n){let r,i,o;try{if(t.headers.get("content-type")?.includes("application/json")){let u=await t.json();if(u&&typeof u=="object"){let p=u;typeof p.message=="string"?r=p.message:typeof p.error=="string"&&(r=p.error),i=p.details,typeof p.error=="string"&&We.has(p.error)&&(o=p.error)}}else{let u=(await t.text()).trim();u&&!u.startsWith("<")&&u.length<=Je&&(r=u)}}catch{}let l=t.headers.get("retry-after");if(l!==null){let s=l.trim(),u=/^\d+$/.test(s)?Number(s):Math.ceil((Date.parse(s)-Date.now())/1e3);if(Number.isFinite(u)&&u>=0){let p=i&&typeof i=="object"?i:{};p.retryAfter===void 0&&(i={...p,retryAfter:u})}}r=r||`${n||"Request"} failed with status ${t.status}`;let c=o??(t.status===401?d.Authentication:t.status===403?d.Forbidden:t.status===429?d.RateLimit:d.Api);return new e(c,r,t.status,i)}static fromFetchError(t,n){if(C(t))return t;let r=n||"Request",i=t?.name;return i==="AbortError"?e.cancelled(`${r} was cancelled`):i==="TimeoutError"?e.timeout(`${r} timed out`,{cause:t}):t instanceof Error?Qe(t)?e.network(`${r} failed: ${t.message}`,{cause:t}):new e(d.Api,`${r} failed: ${t.message}`):new e(d.Api,`${r} failed: Unknown error`)}static validation(t,n){return new e(d.Validation,t,400,n)}static notFound(t,n){let r=n?`${t} ${n} not found`:`${t} not found`;return new e(d.NotFound,r,404)}static forbidden(t,n){return new e(d.Forbidden,t,403,n)}static rateLimit(t="Too many requests",n){return new e(d.RateLimit,t,429,n)}static authentication(t="Authentication required",n){return new e(d.Authentication,t,401,n)}static business(t,n=400,r){return new e(d.Business,t,n,r)}static network(t,n){return new e(d.Network,t,void 0,n)}static timeout(t,n){return new e(d.Timeout,t,void 0,n)}static cancelled(t,n){return new e(d.Cancelled,t,void 0,n)}static file(t,n){return new e(d.File,t,void 0,n)}static config(t,n){return new e(d.Config,t,void 0,n)}static api(t,n=500,r){return new e(d.Api,t,n,r)}static maintenance(t,n){return new e(d.Maintenance,t,503,n)}isClientError(){return q.client.has(this.type)?!0:this.status!==void 0&&this.status>=400&&this.status<500}isNetworkError(){return q.network.has(this.type)}isAuthError(){return q.auth.has(this.type)}isType(t){return this.type===t}};et=["html","htm","xhtml","xml","txt","md","markdown","pdf","csv","json","jsonc","webmanifest","map","toml","yaml","yml","rss","atom","css","scss","sass","less","js","mjs","cjs","jsx","ts","tsx","wasm","vue","svelte","png","jpg","jpeg","gif","webp","avif","svg","ico","bmp","tif","tiff","heic","heif","woff","woff2","ttf","otf","eot","mp3","wav","ogg","oga","opus","m4a","aac","flac","weba","mp4","webm","ogv","mov","m4v","avi","glb","gltf","usdz","vtt","srt","zip"],Ut=et.map(e=>`.${e}`).join(","),tt=/[\x00-\x1f\x7f#?%\\<>"]/;X=new Set(["node_modules","package.json"]);Ht="/auth",$t="signing-in",Y={SESSION:"session",API_KEY:"apiKey",TOKEN:"token",AGENT:"agent",OAUTH:"oauth",WEBHOOK:"webhook",SYSTEM:"system"},ye={PREFIX:"ship-",HEX_LENGTH:32,TOTAL_LENGTH:37,HINT_LENGTH:4},Ee={PREFIX:"deploy-",HEX_LENGTH:32,TOTAL_LENGTH:39},ge={PREFIX:"oauth-",HEX_LENGTH:32,TOTAL_LENGTH:38},b={HEADER:"X-Caller",MAX_LENGTH:128,PATTERN:/^[a-zA-Z0-9._-]+$/},D={API_KEY:Y.API_KEY,DEPLOY_TOKEN:Y.TOKEN,OAUTH:Y.OAUTH,OPAQUE:"opaque"};j="bearer ";Bt={ACCOUNT_READ:"account:read",DEPLOYMENTS_READ:"deployments:read",DEPLOYMENTS_WRITE:"deployments:write",DOMAINS_READ:"domains:read",DOMAINS_WRITE:"domains:write"},A="ship.json",Te={rewrites:[{source:"/(.*)",destination:"/index.html"}]},M={INDEX_FILE:"index.html",MAX_INDEX_BYTES:100*1024};_={MIN_SECONDS:1,MAX_SECONDS:365*24*60*60};Z="https://api.shipstatic.com",x={TOKEN:"SHIP_TOKEN",API_URL:"SHIP_API_URL"},Vt="https://my.shipstatic.com/api-key",qt=4320*60,h={PENDING:"pending",PROCESSING_ERROR:"processing_error",EXCLUDED:"excluded",VALIDATION_FAILED:"validation_failed",READY:"ready"};I={MIN_LENGTH:3,MAX_LENGTH:25,MAX_COUNT:10,SEPARATORS:"._-"},De=/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/;v={MIN_LENGTH:6,MAX_LENGTH:128}});async function ft(e){let t=(await import("spark-md5")).default,n=new t.ArrayBuffer,r=2097152;for(let i=0;i<e.size;i+=r){let o=Math.min(i+r,e.size);n.append(await e.slice(i,o).arrayBuffer())}return{md5:n.end()}}async function ht(e){let{createHash:t}=await import("crypto"),n=t("md5");return n.update(e),{md5:n.digest("hex")}}async function yt(e){let{createHash:t}=await import("crypto"),{createReadStream:n}=await import("fs");return new Promise((r,i)=>{let o=t("md5"),l=n(e);l.on("error",c=>i(a.file(`Failed to read file for MD5: ${c.message}`,{filePath:e}))),l.on("data",c=>o.update(c)),l.on("end",()=>r({md5:o.digest("hex")}))})}async function H(e){if(e instanceof Blob)return ft(e);if(typeof Buffer<"u"&&Buffer.isBuffer(e))return ht(e);if(typeof e=="string")return yt(e);throw a.business("Invalid input for MD5 calculation")}var $=T(()=>{"use strict";f()});function In(e){ne=e}function St(){return typeof process<"u"&&process.versions&&process.versions.node?"node":typeof window<"u"||typeof self<"u"?"browser":"unknown"}function N(){return ne||St()}var ne,w=T(()=>{"use strict";ne=null});function Me(e){if(!e||e.length===0)return"";let t=e.filter(o=>o&&typeof o=="string").map(o=>o.replace(/\\/g,"/"));if(t.length===0)return"";if(t.length===1)return t[0];let n=t.map(o=>o.split("/").filter(Boolean)),r=[],i=Math.min(...n.map(o=>o.length));for(let o=0;o<i;o++){let l=n[0][o];if(n.every(c=>c[o]===l))r.push(l);else break}return r.join("/")}function z(e){return e.replace(/\\/g,"/").replace(/\/+/g,"/").replace(/^\/+/,"")}var re=T(()=>{"use strict"});function ke(e,t={}){if(t.flatten===!1)return e.map(r=>({path:z(r),name:ie(r)}));let n=Dt(e);return e.map(r=>{let i=z(r);if(n){let o=n.endsWith("/")?n:`${n}/`;i.startsWith(o)&&(i=i.substring(o.length))}return i||(i=ie(r)),{path:i,name:ie(r)}})}function Dt(e){if(!e.length)return"";let n=e.map(o=>z(o)).map(o=>o.split("/")),r=[],i=Math.min(...n.map(o=>o.length));for(let o=0;o<i-1;o++){let l=n[0][o];if(n.every(c=>c[o]===l))r.push(l);else break}return r.join("/")}function ie(e){return e.split(/[/\\]/).pop()||e}var oe=T(()=>{"use strict";re()});function V(e,t){return It.find(n=>n.broken(e,t))}var It,ae=T(()=>{"use strict";f();le();It=[{name:"name",broken:({path:e})=>!se(e).valid,sentence:({path:e})=>se(e).reason??"Invalid file name"},{name:"extension",broken:({path:e},t)=>fe(e,t.blockedExtensions??[]),sentence:({path:e})=>`File extension not allowed: "${e}"`},{name:"fileSize",broken:({size:e},t)=>e>t.maxFileSize,sentence:({path:e},t)=>`File "${e}" too large. Maximum ${K(t.maxFileSize)} allowed`},{name:"totalSize",broken:({totalSize:e},t)=>e>t.maxTotalSize,sentence:({totalSize:e},t)=>`Total upload size too large. ${K(e)} exceeds maximum of ${K(t.maxTotalSize)}`}]});function K(e,t=1){if(e===0)return"0 Bytes";let n=1024,r=["Bytes","KB","MB","GB"],i=Math.floor(Math.log(e)/Math.log(n));return`${parseFloat((e/n**i).toFixed(t))} ${r[i]}`}function se(e){if(he(e))return{valid:!1,reason:"File name contains unsafe characters"};if(e.startsWith(" ")||e.endsWith(" "))return{valid:!1,reason:"File name cannot start/end with spaces"};if(e.endsWith("."))return{valid:!1,reason:"File name cannot end with dots"};let t=/^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(\.|$)/i,n=e.split("/").pop()||e;return t.test(n)?{valid:!1,reason:"File name uses a reserved system name"}:e.includes("..")?{valid:!1,reason:"File name contains path traversal pattern"}:{valid:!0}}function zn(e,t){let n=[],r=[],i=[];if(e.length===0){let s={file:"(no files)",message:"At least one file must be provided"};return n.push(s),{files:[],validFiles:[],errors:n,warnings:[],canDeploy:!1}}for(let s of e)if(F(s.name))return n.push({file:s.name,message:"Unbuilt project detected \u2014 deploy your build output (dist/, build/, out/), not the project folder"}),{files:e.map(u=>({...u,status:h.VALIDATION_FAILED,statusMessage:"Unbuilt project detected"})),validFiles:[],errors:n,warnings:[],canDeploy:!1};if(e.length>t.maxFilesCount){let s={file:`(${e.length} files)`,message:`File count (${e.length}) exceeds limit of ${t.maxFilesCount}`};return n.push(s),{files:e.map(u=>({...u,status:h.VALIDATION_FAILED,statusMessage:s.message})),validFiles:[],errors:n,warnings:[],canDeploy:!1}}let o=0;for(let s of e){let u=h.READY,p="Ready for upload";if(s.status===h.PROCESSING_ERROR)u=h.VALIDATION_FAILED,p=s.statusMessage||"File failed during processing",n.push({file:s.name,message:p});else if(s.size===0){u=h.EXCLUDED,p="File is empty (0 bytes) and cannot be deployed due to storage limitations",r.push({file:s.name,message:p}),i.push({...s,status:u,statusMessage:p});continue}else if(s.size<0)u=h.VALIDATION_FAILED,p="File size must be positive",n.push({file:s.name,message:p});else if(!s.name||s.name.trim().length===0)u=h.VALIDATION_FAILED,p="File name cannot be empty",n.push({file:s.name||"(empty)",message:p});else if(s.name.includes("\0"))u=h.VALIDATION_FAILED,p="File name contains invalid characters (null byte)",n.push({file:s.name,message:p});else{let y={path:s.name,size:s.size,totalSize:o+s.size},R=V(y,t);R?(u=h.VALIDATION_FAILED,p=R.sentence(y,t),n.push({file:R.name==="totalSize"?`(${e.length} files)`:s.name,message:p})):o=y.totalSize}i.push({...s,status:u,statusMessage:p})}n.length>0&&(i=i.map(s=>s.status===h.EXCLUDED?s:{...s,status:h.VALIDATION_FAILED,statusMessage:s.status===h.VALIDATION_FAILED?s.statusMessage:"Deployment failed due to validation errors in bundle"}));let l=n.length===0?i.filter(s=>s.status===h.READY):[],c=n.length===0;return{files:i,validFiles:l,errors:n,warnings:r,canDeploy:c}}function Lt(e){return e.filter(t=>t.status===h.READY)}function Kn(e){return Lt(e).length>0}var le=T(()=>{"use strict";f();ae()});import{isJunk as Nt}from"junk";function Ue(e,t){if(!e||e.length===0)return[];if(!t?.allowUnbuilt&&e.find(r=>r&&F(r)))throw a.business("Unbuilt project detected \u2014 deploy your build output (dist/, build/, out/), not the project folder");return e.filter(n=>{if(!n)return!1;let r=n.replace(/\\/g,"/").split("/").filter(Boolean);if(r.length===0)return!0;let i=r[r.length-1];if(Nt(i))return!1;for(let l of r)if(l!==".well-known"&&(l.startsWith(".")||l.length>255))return!1;let o=r.slice(0,-1);for(let l of o)if(Pt.some(c=>l.toLowerCase()===c.toLowerCase()))return!1;return!0})}var Pt,pe=T(()=>{"use strict";f();Pt=["__MACOSX",".Trashes",".fseventsd",".Spotlight-V100"]});function He(e,t){if(e.includes("\0")||e.includes("/../")||e.startsWith("../")||e.endsWith("/.."))throw a.business(`Security error: Unsafe file path "${e}" for file: ${t}`)}function $e(e,t){let n=V(e,t);if(n)throw a.business(n.sentence(e,t))}var ce=T(()=>{"use strict";f();ae()});async function Ge(e,t={},n){let r=!!(t.build||t.prerender),i=ke(e.map(p=>p.path),{flatten:t.pathDetect!==!1}).map(p=>p.path),o=new Set(Ue(i,{allowUnbuilt:r})),l=e.map((p,y)=>({source:p,deployPath:i[y]})).filter(({deployPath:p})=>o.has(p));if(l.length===0)return[];let c=r?null:bt(n),s=[],u=0;for(let{source:p,deployPath:y}of l){if(c&&He(y,p.origin),p.size===0)continue;c&&(u+=p.size,$e({path:y,size:p.size,totalSize:u},c));let R=await p.read(),{md5:P}=await H(R);s.push({path:y,content:R,size:p.size,md5:P})}if(c&&s.length>c.maxFilesCount)throw a.business(`Too many files to deploy. Maximum allowed is ${c.maxFilesCount} files.`);return s}function bt(e){if(!e)throw a.config("Platform limits not provided. Deploy-mode validation requires the limits argument \u2014 pass `ship.getLimits()` result.");return e}var Be=T(()=>{"use strict";f();oe();pe();$();ce()});var Ve={};Ye(Ve,{processFilesForNode:()=>Ke});import*as g from"fs";import*as E from"path";function ze(e,t=new Set){let n=[],r=g.realpathSync(e);if(t.has(r))return n;t.add(r);for(let i of g.readdirSync(e)){let o=E.join(e,i),l=g.statSync(o);l.isDirectory()?n.push(...ze(o,t)):l.isFile()&&n.push({absPath:o,size:l.size})}return n}async function xt(e){try{return g.readFileSync(e)}catch(t){let n=t instanceof Error?t.message:String(t);throw a.file(`Failed to read file "${e}": ${n}`,{filePath:e})}}function Ot(e){for(let t of e){let n=E.resolve(t);try{if(g.statSync(n).isDirectory()){let r=g.readdirSync(n).find(i=>X.has(i));if(r)throw a.business(`"${r}" detected \u2014 deploy your build output (dist/, build/, out/), not the project folder`)}}catch(r){if(C(r))throw r}}}async function Ke(e,t={},n){if(N()!=="node")throw a.business("processFilesForNode can only be called in Node.js environment.");Ot(e);let r=e.flatMap(c=>{let s=E.resolve(c);try{let u=g.statSync(s);return u.isDirectory()?ze(s):[{absPath:s,size:u.size}]}catch{throw a.file(`Path does not exist: ${c}`,{filePath:c})}}),i=new Map(r.map(c=>[c.absPath,c.size])),o=Me(e.map(c=>E.resolve(c)).map(c=>{try{return g.statSync(c).isDirectory()?c:E.dirname(c)}catch{return E.dirname(c)}})),l=[...i].map(([c,s])=>({path:wt(c,o),origin:c,size:s,read:()=>xt(c)}));return Ge(l,t,n)}function wt(e,t){if(t&&t.length>0){let n=E.relative(t,e);if(n&&typeof n=="string"&&!n.startsWith(".."))return n.replace(/\\/g,"/")}return E.basename(e)}var ue=T(()=>{"use strict";f();Be();w();re()});f();f();f();var k=class{constructor(){this.handlers=new Map}on(t,n){this.handlers.has(t)||this.handlers.set(t,new Set),this.handlers.get(t)?.add(n)}off(t,n){let r=this.handlers.get(t);r&&(r.delete(n),r.size===0&&this.handlers.delete(t))}emit(t,...n){let r=this.handlers.get(t);if(!r)return;let i=Array.from(r);for(let o of i)try{o(...n)}catch(l){r.delete(o),t!=="error"&&setTimeout(()=>{let c=l instanceof Error?l:new Error(String(l));this.emit("error",c,String(t))},0)}}};var st=3e4,at=2,lt=300,pt=2e3,ct=new Set([500,502,503,504]);function ut(e,t){return new Promise((n,r)=>{if(t?.aborted){r(t.reason);return}let i=()=>{clearTimeout(l),t?.removeEventListener("abort",o)},o=()=>{i(),r(t?.reason)},l=setTimeout(()=>{i(),n()},e);t?.addEventListener("abort",o)})}var Ie=3e5,dt=3e5,mt=Ie+dt,U=class extends k{constructor(n){super();this.globalHeaders={};this.apiUrl=n.apiUrl||Z,this.getAuthHeadersCallback=n.getAuthHeaders,this.session=n.session??!1,this.caller=n.caller,this.timeout=n.timeout??st,this.maxRetries=Math.max(0,n.maxRetries??at),this.fetch=n.fetch??globalThis.fetch.bind(globalThis),this.deploy={endpoint:n.deployEndpoint||m.DEPLOYMENTS,timeout:n.timeout??Ie,buildTimeout:n.timeout??mt}}setGlobalHeaders(n){this.globalHeaders=n}async executeRequest(n,r,i,o=this.timeout){for(let l=0;;l++)try{return await this.attemptOnce(n,r,i,o)}catch(c){let s=a.fromFetchError(c,i);if(l>=this.maxRetries||!this.isRetryable(s,r))throw this.emit("error",s,n),s;this.emit("retry",s,n,l+1);let u=Math.min(pt,lt*2**l);try{await ut(Math.random()*u,r.signal)}catch(p){let y=a.fromFetchError(p,i);throw this.emit("error",y,n),y}}}isRetryable(n,r){if(r.signal?.aborted||n.isType(d.Maintenance)||n.isType(d.Cancelled)||!(n.isNetworkError()||n.status!==void 0&&ct.has(n.status)))return!1;let o=(r.method??"GET").toUpperCase();return o==="GET"||o==="HEAD"?!0:o==="PUT"||o==="DELETE"?!1:this.hasIdempotencyKey(r.headers)}hasIdempotencyKey(n){if(!n)return!1;let r=L.HEADER.toLowerCase();return Object.keys(n).some(i=>i.toLowerCase()===r)}async attemptOnce(n,r,i,o=this.timeout){let l=()=>{};try{let c=await this.mergeHeaders(r.headers),s=this.createTimeoutSignal(r.signal,o);l=s.cleanup;let u={...r,headers:c,credentials:this.session&&!c.Authorization?"include":void 0,signal:s.signal};this.emit("request",n,u);let p=await this.fetch(n,u);if(l(),!p.ok)throw await a.fromHttpResponse(p,i);return this.emit("response",this.safeClone(p),n),{data:await this.parseResponse(this.safeClone(p)),status:p.status}}catch(c){throw l(),a.fromFetchError(c,i)}}async request(n,r,i,o){let{data:l}=await this.executeRequest(`${this.apiUrl}${n}`,r,i,o);return l}async requestWithStatus(n,r,i){return this.executeRequest(`${this.apiUrl}${n}`,r,i)}async mergeHeaders(n={}){return{...this.globalHeaders,...this.caller?{[b.HEADER]:this.caller}:{},...await this.getAuthHeadersCallback(),...n}}createTimeoutSignal(n,r=this.timeout){let i=new AbortController,o=setTimeout(()=>i.abort(new DOMException(`Timed out after ${r}ms`,"TimeoutError")),r),l=n?()=>i.abort(n.reason):void 0;return n&&l&&(n.addEventListener("abort",l),n.aborted&&i.abort(n.reason)),{signal:i.signal,cleanup:()=>{clearTimeout(o),n&&l&&n.removeEventListener("abort",l)}}}safeClone(n){try{return n.clone()}catch{return n}}async parseResponse(n){if(!(n.headers.get("Content-Length")==="0"||n.status===204))return n.json()}};f();f();async function Le(e,t={}){let{labels:n,via:r,password:i,ttl:o,flags:l,captcha:c}=t,s=new FormData,u=[];for(let p of e){if(typeof p.content=="string"||p.content===null||p.content===void 0)throw a.file(`Unsupported file.content type: ${p.path}`,{filePath:p.path});if(!p.md5)throw a.file(`File missing md5 checksum: ${p.path}`,{filePath:p.path});s.append(S.FILES,new File([p.content],p.path,{type:"application/octet-stream"})),u.push(p.md5)}return s.append(S.CHECKSUMS,JSON.stringify(u)),n&&n.length>0&&s.append(S.LABELS,JSON.stringify(n)),r&&s.append(S.VIA,r),i&&s.append(S.PASSWORD,i),o!==void 0&&s.append(S.TTL,String(o)),l?.build&&s.append(S.BUILD,"true"),l?.prerender&&s.append(S.PRERENDER,"true"),l?.spa&&s.append(S.SPA,"true"),c&&s.append(S.CAPTCHA,c),s}f();$();async function Et(){let e=JSON.stringify(Te,null,2),t;typeof Buffer<"u"?t=Buffer.from(e,"utf-8"):t=new Blob([e],{type:"application/json"});let{md5:n}=await H(t);return{path:A,content:t,size:e.length,md5:n}}async function gt(e,t){let n=e.find(l=>l.path===M.INDEX_FILE||l.path===`/${M.INDEX_FILE}`);if(!n||n.size>M.MAX_INDEX_BYTES)return!1;let r;if(typeof Buffer<"u"&&Buffer.isBuffer(n.content))r=n.content.toString("utf-8");else if(typeof Blob<"u"&&n.content instanceof Blob)r=await n.content.text();else if(typeof File<"u"&&n.content instanceof File)r=await n.content.text();else return!1;let i={files:e.map(l=>l.path),index:r};return(await t.request(m.SPA_CHECK,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)},"SPA check")).isSPA}async function Ne(e,t,n){if(n.spaDetect===!1||n.spa||n.build||n.prerender||e.some(r=>r.path===A))return e;try{if(await gt(e,t)){let i=await Et();return[...e,i]}}catch{}return e}f();f();function O(e){if(e==null)return;if(e.length===0)return e;if(e.length>I.MAX_COUNT)throw a.validation(`Maximum ${I.MAX_COUNT} labels allowed`);let t=e.map((r,i)=>{if(typeof r!="string")throw a.validation(`Label at index ${i} must be a string`);let o=r.trim().toLowerCase();if(o.length<I.MIN_LENGTH)throw a.validation(`Labels must be at least ${I.MIN_LENGTH} characters long`);if(o.length>I.MAX_LENGTH)throw a.validation(`Labels must be no more than ${I.MAX_LENGTH} characters long`);if(!De.test(o))throw a.validation(`Labels must start and end with alphanumeric characters, with optional separators (${I.SEPARATORS}) between segments`);return o}),n=[...new Set(t)];if(n.length!==t.length)throw a.validation("Duplicate labels are not allowed");return n}async function Pe(e){let t=e.find(i=>i.path===A||i.path===`/${A}`);if(!t)return;let n=t.content,r=typeof n.text=="function"?await n.text():t.content.toString("utf8");Se(r)}var G={"Content-Type":"application/json"},Tt="sdk";function te(e){let t=new URLSearchParams;e?.limit!==void 0&&t.set("limit",String(e.limit)),e?.cursor!==void 0&&t.set("cursor",e.cursor);let n=t.toString();return n?`?${n}`:""}function be(e){let{getApi:t,processInput:n}=e;return{upload:async(r,i={})=>{if(!n)throw a.config("processInput function is not provided.");let o=t(),l=await n(r,i),c=await Ne(l,o,i);if(!c.length)throw a.business("No files to deploy");for(let P of c)if(!P.md5)throw a.file(`MD5 checksum missing for file: ${P.path}`,{filePath:P.path});ee(i.password);let s=Q(i.ttl),u=me(i.idempotencyKey),p=O(i.labels);await Pe(c);let y=i.build||i.prerender||i.spa?{build:i.build,prerender:i.prerender,spa:i.spa}:void 0,R=await Le(c,{labels:p,via:i.via??Tt,password:i.password,ttl:s,flags:y,captcha:i.captcha});return o.request(o.deploy.endpoint,{method:"POST",body:R,...u?{headers:{[L.HEADER]:u}}:{},signal:i.signal||null},"Deploy",i.build||i.prerender?o.deploy.buildTimeout:o.deploy.timeout)},list:async r=>t().request(`${m.DEPLOYMENTS}${te(r)}`,{method:"GET"},"List deployments"),get:async r=>t().request(m.DEPLOYMENT(encodeURIComponent(r)),{method:"GET"},"Get deployment"),set:async(r,i)=>t().request(m.DEPLOYMENT(encodeURIComponent(r)),{method:"PATCH",headers:G,body:JSON.stringify({labels:O(i.labels)})},"Update deployment labels"),delete:async r=>t().request(m.DEPLOYMENT(encodeURIComponent(r)),{method:"DELETE"},"Delete deployment")}}function xe(e){let{getApi:t}=e;return{set:async(n,r={})=>{let i=O(r.labels),o={};r.deployment&&(o.deployment=r.deployment),i!==void 0&&(o.labels=i);let{data:l,status:c}=await t().requestWithStatus(m.DOMAIN(encodeURIComponent(n)),{method:"PUT",headers:G,body:JSON.stringify(o)},"Set domain");return{...l,isCreate:c===201}},list:async n=>t().request(`${m.DOMAINS}${te(n)}`,{method:"GET"},"List domains"),get:async n=>t().request(m.DOMAIN(encodeURIComponent(n)),{method:"GET"},"Get domain"),delete:async n=>t().request(m.DOMAIN(encodeURIComponent(n)),{method:"DELETE"},"Delete domain"),verify:async n=>t().request(m.DOMAIN_VERIFY(encodeURIComponent(n)),{method:"POST"},"Verify domain"),validate:async n=>t().request(m.DOMAINS_VALIDATE,{method:"POST",headers:G,body:JSON.stringify({domain:n})},"Validate domain"),dns:async n=>t().request(m.DOMAIN_DNS(encodeURIComponent(n)),{method:"GET"},"Get domain DNS"),records:async n=>t().request(m.DOMAIN_RECORDS(encodeURIComponent(n)),{method:"GET"},"Get domain records"),share:async n=>t().request(m.DOMAIN_SHARE(encodeURIComponent(n)),{method:"GET"},"Get domain share")}}function Oe(e){let{getApi:t}=e;return{get:async()=>t().request(m.ACCOUNT,{method:"GET"},"Get account")}}function we(e){let{getApi:t}=e;return{create:async(n={})=>{let r=Q(n.ttl),i=O(n.labels),o={};return r!==void 0&&(o.ttl=r),i!==void 0&&(o.labels=i),t().request(m.TOKENS,{method:"POST",headers:G,body:JSON.stringify(o)},"Create token")},list:async n=>t().request(`${m.TOKENS}${te(n)}`,{method:"GET"},"List tokens"),get:async n=>t().request(m.TOKEN(encodeURIComponent(n)),{method:"GET"},"Get token"),delete:async n=>t().request(m.TOKEN(encodeURIComponent(n)),{method:"DELETE"},"Delete token")}}var B=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&&Ae(t.caller),t.token&&t.session)throw a.config("Provide either `token` or `session`, not both.");typeof t.token=="string"?(J(t.token),this.credential=t.token):t.token&&(this.credential=t.token),this.http=new U({...t,getAuthHeaders:()=>this.getAuthHeaders()});let n={getApi:()=>this.http};this.deployments=be({...n,processInput:async(r,i)=>(await this.ensureInitialized(),this.processInput(r,i))}),this.domains=xe(n),this.account=Oe(n),this.tokens=we(n)}async ensureInitialized(){return this.initPromise||(this.initPromise=this.fetchPlatformLimits()),this.initPromise}async fetchPlatformLimits(){try{this.platformLimits=await this.http.request(m.LIMITS,{method:"GET"},"Get limits")}catch(t){throw this.initPromise=null,t}}async ping(){return this.http.request(m.PING,{method:"GET"},"Ping")}async deploy(t,n){return this.deployments.upload(t,n)}async whoami(){return this.account.get()}async getLimits(){return this.platformLimits?this.platformLimits:(await this.ensureInitialized(),this.platformLimits)}on(t,n){this.http.on(t,n)}off(t,n){this.http.off(t,n)}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.");J(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}`}}};w();f();import{z as Ce}from"zod";import{z as _e}from"zod";var ve={apiUrl:_e.string().url().optional(),token:_e.string().min(1).optional()};w();var At=Ce.object(ve).strict(),Rt={apiUrl:x.API_URL,token:x.TOKEN};function Fe(){if(N()!=="node")return{};let e={apiUrl:process.env[x.API_URL]||void 0,token:process.env[x.TOKEN]||void 0};try{return At.parse(e)}catch(t){if(t instanceof Ce.ZodError){let n=t.issues[0],r=n.path[0],i=(r&&Rt[r])??"SHIP environment configuration";throw a.config(`Invalid ${i}: ${n.message}`)}throw a.config("Invalid environment configuration")}}f();f();oe();w();le();pe();$();ce();function Qn(e,t,n,r=!0){let i=e===1?t:n;return r?`${e} ${i}`:i}ue();var de=class extends B{constructor(t={}){if(N()!=="node")throw a.business("Node.js Ship class can only be used in Node.js environment.");let n=Fe();super({...t,apiUrl:t.apiUrl||n.apiUrl,token:t.token||(t.session?void 0:n.token)})}async deploy(t,n){return super.deploy(t,n)}async processInput(t,n){let r=typeof t=="string"?[t]:t;if(!Array.isArray(r)||!r.every(o=>typeof o=="string"))throw a.business("Invalid input type for Node.js environment. Expected string or string[].");if(r.length===0)throw a.business("No files to deploy.");let{processFilesForNode:i}=await Promise.resolve().then(()=>(ue(),Ve));return i(r,n,this.platformLimits??void 0)}},_t=de;export{ye as API_KEY,m as API_PATHS,Ht as AUTH_BASE_PATH,kt as AccountPlan,U as ApiHttp,Y as AuthMethod,b as CALLER,Z as DEFAULT_API,A as DEPLOYMENT_CONFIG_FILENAME,S as DEPLOY_FIELDS,Ee as DEPLOY_TOKEN,Ct as DeploymentStatus,je as DeploymentVia,Ft as DomainStatus,d as ErrorType,h as FILE_VALIDATION_STATUS,h as FileValidationStatus,L as IDEMPOTENCY_KEY_CONSTRAINTS,Pt as JUNK_DIRECTORIES,I as LABEL_CONSTRAINTS,De as LABEL_PATTERN,Vt as MY_API_KEY_URL,ge as OAUTH_TOKEN,Bt as OAuthScope,v as PASSWORD_CONSTRAINTS,qt as PUBLIC_DEPLOYMENT_TTL_SECONDS,x as SHIP_ENV,$t as SIGN_IN_RETURN_PARAM,M as SPA_CHECK_CONSTRAINTS,Te as SPA_DEFAULT_CONFIG,de as Ship,a as ShipError,_ as TTL_CONSTRAINTS,D as TokenKind,X as UNBUILT_PROJECT_MARKERS,tt as UNSAFE_FILENAME_CHARS,Ut as WEB_FILE_ACCEPT,In as __setTestEnvironment,Kn as allValidFilesReady,Se as assertShipJsonSyntax,H as calculateMD5,nt as classifyToken,Oe as createAccountResource,be as createDeploymentResource,xe as createDomainResource,we as createTokenResource,_t as default,Qt as deserializeLabels,jt as extractSubdomain,Ue as filterJunk,K as formatFileSize,Xt as generateDeploymentUrl,Wt as generateDomainUrl,N as getENV,Lt as getValidFiles,F as hasUnbuiltMarker,he as hasUnsafeChars,fe as isBlockedExtension,Yt as isCustomDomain,Kt as isDeployment,Re as isPlatformDomain,C as isShipError,Mt as normalizeVia,ke as optimizeDeployPaths,Qn as pluralize,Ke as processFilesForNode,Gt as readBearerValue,Jt as serializeLabels,rt as validateApiKey,zt as validateApiUrl,Ae as validateCaller,$e as validateDeployFile,He as validateDeployPath,it as validateDeployToken,se as validateFileName,zn as validateFiles,me as validateIdempotencyKey,ot as validateOAuthToken,ee as validatePassword,J as validateToken,Q as validateTtl};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|