@shipstatic/ship 2.2.0-beta.7 → 2.2.0-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -1
- package/SKILL.md +26 -1
- package/THIRD-PARTY-LICENSES.md +1 -57
- package/dist/browser.d.ts +182 -66
- package/dist/browser.js +1 -1
- package/dist/browser.js.map +1 -1
- package/dist/cli.cjs +136 -147
- 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 +177 -59
- package/dist/index.d.ts +177 -59
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +4 -6
- package/dist/metafile-cjs.json +0 -1
- package/dist/metafile-esm.json +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -671,6 +671,12 @@ declare const DEPLOY_FIELDS: {
|
|
|
671
671
|
readonly VIA: "via";
|
|
672
672
|
/** Plaintext password — the API hashes it server-side. */
|
|
673
673
|
readonly PASSWORD: "password";
|
|
674
|
+
/**
|
|
675
|
+
* Requested lifetime in SECONDS — a duration, never an instant. The API
|
|
676
|
+
* computes and stores the expiry, so the wire carries no client clock.
|
|
677
|
+
* See {@link validateTtl}.
|
|
678
|
+
*/
|
|
679
|
+
readonly TTL: "ttl";
|
|
674
680
|
/** @internal Server-processing flag — first-party `/upload` only. */
|
|
675
681
|
readonly BUILD: "build";
|
|
676
682
|
/** @internal Server-processing flag — first-party `/upload` only. */
|
|
@@ -1259,6 +1265,47 @@ declare function validateApiUrl(apiUrl: string): void;
|
|
|
1259
1265
|
* Example: "happy-cat-abc1234.shipstatic.com"
|
|
1260
1266
|
*/
|
|
1261
1267
|
declare function isDeployment(input: string): boolean;
|
|
1268
|
+
/**
|
|
1269
|
+
* The envelope a requested lifetime must fit — one word, one grammar, wherever
|
|
1270
|
+
* the platform lets a caller choose how long something lives.
|
|
1271
|
+
*
|
|
1272
|
+
* Two resources wear it: `TokenCreateOptions.ttl` and
|
|
1273
|
+
* `DeploymentUploadOptions.ttl`. It lives here rather than on the server by
|
|
1274
|
+
* the format-vs-policy rule — a client can decide offline whether a duration
|
|
1275
|
+
* is well-formed, and the API rejects the same value the same way. What is
|
|
1276
|
+
* NOT here is any per-plan ceiling: no such policy exists, and one delivered
|
|
1277
|
+
* speculatively through `/limits` would be an owner for a decision nobody has
|
|
1278
|
+
* made.
|
|
1279
|
+
*/
|
|
1280
|
+
declare const TTL_CONSTRAINTS: {
|
|
1281
|
+
/**
|
|
1282
|
+
* Shortest requestable lifetime, in seconds. One rather than zero: a
|
|
1283
|
+
* deployment that expires the instant it is created is not a shorter lease,
|
|
1284
|
+
* it is a deploy that was never live, and `0` is how an unset variable
|
|
1285
|
+
* arrives.
|
|
1286
|
+
*/
|
|
1287
|
+
readonly MIN_SECONDS: 1;
|
|
1288
|
+
/** Longest requestable lifetime, in seconds — one year. */
|
|
1289
|
+
readonly MAX_SECONDS: number;
|
|
1290
|
+
};
|
|
1291
|
+
/**
|
|
1292
|
+
* Validate a requested lifetime in SECONDS and return it, or `undefined` when
|
|
1293
|
+
* none was asked for.
|
|
1294
|
+
*
|
|
1295
|
+
* **A duration, never an instant.** The caller says how long; the server owns
|
|
1296
|
+
* what time it is and stamps the expiry — so a client's clock, however wrong,
|
|
1297
|
+
* cannot shorten or extend a lease. That is the tokens precedent, and it is
|
|
1298
|
+
* why this rule measures a count of seconds rather than checking a timestamp
|
|
1299
|
+
* against `now`.
|
|
1300
|
+
*
|
|
1301
|
+
* Fractions are refused rather than rounded: a caller who wrote `1.5` meant
|
|
1302
|
+
* something the wire cannot carry, and silently choosing `1` or `2` for them
|
|
1303
|
+
* is a decision the platform has no standing to make.
|
|
1304
|
+
*
|
|
1305
|
+
* Single source of truth shared by the API (the tokens route and the deploy
|
|
1306
|
+
* schema), the SDK's request boundary, and the CLI's parser.
|
|
1307
|
+
*/
|
|
1308
|
+
declare function validateTtl(value: unknown): number | undefined;
|
|
1262
1309
|
/**
|
|
1263
1310
|
* Request payload for SPA check endpoint
|
|
1264
1311
|
*/
|
|
@@ -1391,6 +1438,27 @@ interface DeploymentUploadOptions {
|
|
|
1391
1438
|
* into missing analytics rather than an error. See {@link DeploymentVia}.
|
|
1392
1439
|
*/
|
|
1393
1440
|
via?: DeploymentViaType;
|
|
1441
|
+
/**
|
|
1442
|
+
* Seconds until this deployment expires; omit for one that never does.
|
|
1443
|
+
*
|
|
1444
|
+
* The platform reclaims it when the time is up — an ephemeral deployment,
|
|
1445
|
+
* chosen by the deployer rather than by the identity. The same word and the
|
|
1446
|
+
* same grammar as {@link TokenCreateOptions.ttl}, bounded by
|
|
1447
|
+
* {@link TTL_CONSTRAINTS}.
|
|
1448
|
+
*
|
|
1449
|
+
* **Requires a credential.** An anonymous deploy has no deployer, and the
|
|
1450
|
+
* platform owns anonymous lifetime as policy
|
|
1451
|
+
* ({@link PUBLIC_DEPLOYMENT_TTL_SECONDS}) — so a ttl on one is refused
|
|
1452
|
+
* rather than honoured or ignored.
|
|
1453
|
+
*
|
|
1454
|
+
* **A deployment carrying one cannot be linked to a domain.** A domain is a
|
|
1455
|
+
* commitment and a deadline is its opposite; the API refuses the link, which
|
|
1456
|
+
* is what keeps the reaper from tearing a live domain's target away.
|
|
1457
|
+
*
|
|
1458
|
+
* Immutable, like every other field of a deployment: to keep something
|
|
1459
|
+
* longer, redeploy.
|
|
1460
|
+
*/
|
|
1461
|
+
ttl?: number;
|
|
1394
1462
|
/**
|
|
1395
1463
|
* Optional password that protects this deployment.
|
|
1396
1464
|
*
|
|
@@ -1829,14 +1897,6 @@ interface DeploymentOptions extends DeploymentUploadOptions {
|
|
|
1829
1897
|
spaDetect?: boolean;
|
|
1830
1898
|
}
|
|
1831
1899
|
type ApiDeployOptions = Omit<DeploymentOptions, 'pathDetect'>;
|
|
1832
|
-
/**
|
|
1833
|
-
* Prepared request body for deployment.
|
|
1834
|
-
* Created by platform-specific code, consumed by HTTP client.
|
|
1835
|
-
*/
|
|
1836
|
-
interface DeployBody {
|
|
1837
|
-
body: FormData | ArrayBuffer;
|
|
1838
|
-
headers: Record<string, string>;
|
|
1839
|
-
}
|
|
1840
1900
|
/**
|
|
1841
1901
|
* Context passed to the deploy body creator — everything that becomes a
|
|
1842
1902
|
* form field alongside the files themselves.
|
|
@@ -1860,6 +1920,11 @@ interface DeployBodyContext {
|
|
|
1860
1920
|
* characters. Whitespace is preserved verbatim — significant.
|
|
1861
1921
|
*/
|
|
1862
1922
|
password?: string;
|
|
1923
|
+
/**
|
|
1924
|
+
* Requested lifetime in SECONDS — a duration, never an instant, bounded by
|
|
1925
|
+
* `TTL_CONSTRAINTS`. The API stamps the expiry against its own clock.
|
|
1926
|
+
*/
|
|
1927
|
+
ttl?: number;
|
|
1863
1928
|
/** @internal Server-side processing flags. */
|
|
1864
1929
|
flags?: {
|
|
1865
1930
|
build?: boolean;
|
|
@@ -1869,11 +1934,6 @@ interface DeployBodyContext {
|
|
|
1869
1934
|
/** @internal reCAPTCHA proof for the anonymous human deploy channel (/upload). */
|
|
1870
1935
|
captcha?: string;
|
|
1871
1936
|
}
|
|
1872
|
-
/**
|
|
1873
|
-
* Function that creates a deploy request body from files.
|
|
1874
|
-
* Implemented differently for Node.js and Browser.
|
|
1875
|
-
*/
|
|
1876
|
-
type DeployBodyCreator = (files: StaticFile[], context?: DeployBodyContext) => Promise<DeployBody>;
|
|
1877
1937
|
/** Standard `fetch` signature — the type of the `fetch` client option. */
|
|
1878
1938
|
type Fetch = typeof fetch;
|
|
1879
1939
|
/**
|
|
@@ -2071,28 +2131,72 @@ declare class SimpleEvents {
|
|
|
2071
2131
|
emit<K extends keyof ShipEvents>(event: K, ...args: ShipEvents[K]): void;
|
|
2072
2132
|
}
|
|
2073
2133
|
|
|
2074
|
-
/**
|
|
2075
|
-
* @file HTTP client for Ship API.
|
|
2076
|
-
*/
|
|
2077
|
-
|
|
2078
2134
|
interface ApiHttpOptions extends ShipClientOptions {
|
|
2079
2135
|
/** Resolves the credential slot per request — async so token providers can mint/refresh. */
|
|
2080
2136
|
getAuthHeaders: () => Record<string, string> | Promise<Record<string, string>>;
|
|
2081
|
-
createDeployBody: DeployBodyCreator;
|
|
2082
2137
|
}
|
|
2083
|
-
|
|
2138
|
+
interface RequestResult<T> {
|
|
2139
|
+
data: T;
|
|
2140
|
+
status: number;
|
|
2141
|
+
}
|
|
2142
|
+
/**
|
|
2143
|
+
* The deploy's CARRIAGE — the two facts about a deploy that are transport's
|
|
2144
|
+
* rather than the deployment resource's.
|
|
2145
|
+
*
|
|
2146
|
+
* The numbers are transport's because a budget for how long to wait on a wire
|
|
2147
|
+
* is nothing else, and the endpoint is transport's because `deployEndpoint` is
|
|
2148
|
+
* a client option that redirects the route. The CHOICE between the two
|
|
2149
|
+
* ceilings is the resource's, because only it knows that `build`/`prerender`
|
|
2150
|
+
* wait on work the server does after the upload lands.
|
|
2151
|
+
*/
|
|
2152
|
+
interface DeployTransport {
|
|
2153
|
+
/** `/deployments`, or `/upload` where the `@internal` option redirects it. */
|
|
2154
|
+
readonly endpoint: string;
|
|
2155
|
+
/** The ordinary deploy ceiling. */
|
|
2156
|
+
readonly timeout: number;
|
|
2157
|
+
/** The ceiling when the server will also build. */
|
|
2158
|
+
readonly buildTimeout: number;
|
|
2159
|
+
}
|
|
2160
|
+
/**
|
|
2161
|
+
* What a resource may ask of the transport: carry this request, and tell me
|
|
2162
|
+
* what came back.
|
|
2163
|
+
*
|
|
2164
|
+
* This interface is the whole seam. `resources.ts` states WHICH request — the
|
|
2165
|
+
* path, the verb, the body, the response type — and hands it here; nothing
|
|
2166
|
+
* above this line knows the base URL, the credential, the retry policy or the
|
|
2167
|
+
* event vocabulary, and nothing below knows what a domain is.
|
|
2168
|
+
*/
|
|
2169
|
+
interface Transport {
|
|
2170
|
+
request<T>(path: string, options: ShipRequestInit, operationName: string, timeoutMs?: number): Promise<T>;
|
|
2171
|
+
requestWithStatus<T>(path: string, options: ShipRequestInit, operationName: string): Promise<RequestResult<T>>;
|
|
2172
|
+
readonly deploy: DeployTransport;
|
|
2173
|
+
}
|
|
2174
|
+
/**
|
|
2175
|
+
* A request as THIS client composes one.
|
|
2176
|
+
*
|
|
2177
|
+
* Identical to `RequestInit` but for the headers, which are narrowed from the
|
|
2178
|
+
* DOM's three-shaped `HeadersInit` to the one shape every call site here
|
|
2179
|
+
* actually builds. That narrowing is load-bearing twice over: `mergeHeaders`
|
|
2180
|
+
* used to reach its record through an `as` cast, and `hasIdempotencyKey` used
|
|
2181
|
+
* to walk all three shapes to find a key that only ever arrives in one of
|
|
2182
|
+
* them. Narrowing at RUNTIME instead would have turned an unreachable case
|
|
2183
|
+
* into a SILENT no-retry — a deploy that quietly stopped replaying because
|
|
2184
|
+
* someone handed the transport a `Headers`. Here that is a compile error.
|
|
2185
|
+
*/
|
|
2186
|
+
type ShipRequestInit = Omit<RequestInit, 'headers'> & {
|
|
2187
|
+
headers?: Record<string, string>;
|
|
2188
|
+
};
|
|
2189
|
+
declare class ApiHttp extends SimpleEvents implements Transport {
|
|
2084
2190
|
private readonly apiUrl;
|
|
2085
2191
|
private readonly getAuthHeadersCallback;
|
|
2086
2192
|
private readonly session;
|
|
2087
2193
|
private readonly caller;
|
|
2088
2194
|
private readonly timeout;
|
|
2089
2195
|
private readonly maxRetries;
|
|
2090
|
-
private readonly deployTimeout;
|
|
2091
|
-
private readonly deployBuildTimeout;
|
|
2092
2196
|
private readonly fetch;
|
|
2093
|
-
private readonly createDeployBody;
|
|
2094
|
-
private readonly deployEndpoint;
|
|
2095
2197
|
private globalHeaders;
|
|
2198
|
+
/** @see DeployTransport — the carriage facts the deployment resource reads. */
|
|
2199
|
+
readonly deploy: DeployTransport;
|
|
2096
2200
|
constructor(options: ApiHttpOptions);
|
|
2097
2201
|
/**
|
|
2098
2202
|
* Set global headers included in every request.
|
|
@@ -2131,7 +2235,13 @@ declare class ApiHttp extends SimpleEvents {
|
|
|
2131
2235
|
* is one that may be sent twice.
|
|
2132
2236
|
*/
|
|
2133
2237
|
private isRetryable;
|
|
2134
|
-
/**
|
|
2238
|
+
/**
|
|
2239
|
+
* Did this request carry the header that makes a repeat safe?
|
|
2240
|
+
*
|
|
2241
|
+
* Case-insensitively, because HTTP field names are — the CLI's env tier and
|
|
2242
|
+
* the SDK option both spell it canonically, but a caller composing headers
|
|
2243
|
+
* by hand is entitled not to.
|
|
2244
|
+
*/
|
|
2135
2245
|
private hasIdempotencyKey;
|
|
2136
2246
|
/**
|
|
2137
2247
|
* One attempt: headers, timeout signal, the `request`/`response` events, and
|
|
@@ -2143,51 +2253,56 @@ declare class ApiHttp extends SimpleEvents {
|
|
|
2143
2253
|
*/
|
|
2144
2254
|
private attemptOnce;
|
|
2145
2255
|
/**
|
|
2146
|
-
*
|
|
2256
|
+
* Send it; resolve what came back.
|
|
2257
|
+
*
|
|
2258
|
+
* Takes a PATH, not a URL: the base is this client's and nothing above needs
|
|
2259
|
+
* to know it. Twenty-two call sites wrote `${this.apiUrl}${API_PATHS.X}` by
|
|
2260
|
+
* hand before the endpoints moved out, which is twenty-two chances to
|
|
2261
|
+
* assemble it differently.
|
|
2147
2262
|
*/
|
|
2148
|
-
|
|
2263
|
+
request<T>(path: string, options: ShipRequestInit, operationName: string, timeoutMs?: number): Promise<T>;
|
|
2149
2264
|
/**
|
|
2150
|
-
*
|
|
2265
|
+
* The same, plus the HTTP status — for the one operation where the status IS
|
|
2266
|
+
* the answer: a domain upsert says create-or-update in its 201/200 and
|
|
2267
|
+
* nowhere else in the response.
|
|
2151
2268
|
*/
|
|
2152
|
-
|
|
2269
|
+
requestWithStatus<T>(path: string, options: ShipRequestInit, operationName: string): Promise<RequestResult<T>>;
|
|
2153
2270
|
private mergeHeaders;
|
|
2154
2271
|
private createTimeoutSignal;
|
|
2155
2272
|
private safeClone;
|
|
2156
2273
|
private parseResponse;
|
|
2157
|
-
deploy(files: StaticFile[], options?: ApiDeployOptions): Promise<DeploymentCreateResponse>;
|
|
2158
|
-
listDeployments(options?: ListOptions): Promise<DeploymentListResponse>;
|
|
2159
|
-
getDeployment(id: string): Promise<Deployment>;
|
|
2160
|
-
updateDeploymentLabels(id: string, labels: string[]): Promise<Deployment>;
|
|
2161
|
-
deleteDeployment(id: string): Promise<DeploymentDeleteResponse>;
|
|
2162
|
-
setDomain(name: string, deployment?: string, labels?: string[]): Promise<DomainSetResult>;
|
|
2163
|
-
listDomains(options?: ListOptions): Promise<DomainListResponse>;
|
|
2164
|
-
getDomain(name: string): Promise<Domain>;
|
|
2165
|
-
deleteDomain(name: string): Promise<DomainDeleteResponse>;
|
|
2166
|
-
verifyDomain(name: string): Promise<DomainVerifyResponse>;
|
|
2167
|
-
getDomainDns(name: string): Promise<DomainDnsResponse>;
|
|
2168
|
-
getDomainRecords(name: string): Promise<DomainRecordsResponse>;
|
|
2169
|
-
getDomainShare(name: string): Promise<DomainShareResponse>;
|
|
2170
|
-
validateDomain(name: string): Promise<DomainValidateResponse>;
|
|
2171
|
-
createToken(ttl?: number, labels?: string[]): Promise<TokenCreateResponse>;
|
|
2172
|
-
listTokens(options?: ListOptions): Promise<TokenListResponse>;
|
|
2173
|
-
deleteToken(token: string): Promise<TokenDeleteResponse>;
|
|
2174
|
-
getToken(token: string): Promise<Token>;
|
|
2175
|
-
getAccount(): Promise<AccountGetResponse>;
|
|
2176
|
-
getLimits(): Promise<PlatformLimits>;
|
|
2177
|
-
ping(): Promise<PingResponse>;
|
|
2178
|
-
checkSPA(files: StaticFile[], _options?: ApiDeployOptions): Promise<boolean>;
|
|
2179
2274
|
}
|
|
2180
2275
|
|
|
2181
2276
|
/**
|
|
2182
|
-
*
|
|
2277
|
+
* @file The SDK's vocabulary — every request it can make, stated once.
|
|
2278
|
+
*
|
|
2279
|
+
* A resource method IS its endpoint: the path, the verb, the body, the
|
|
2280
|
+
* response type. It hands that to the transport, which knows how to carry a
|
|
2281
|
+
* request and nothing about what one means.
|
|
2282
|
+
*
|
|
2283
|
+
* **These were two layers until 2026-08-12.** `ApiHttp` carried eighteen
|
|
2284
|
+
* endpoint methods and every factory below wrapped one of them 1:1 —
|
|
2285
|
+
* `get: async (name) => getApi().getDomain(name)` — because this SDK mirrors
|
|
2286
|
+
* the wire one method per endpoint BY DESIGN (see CLAUDE.md, "Recorded
|
|
2287
|
+
* absences"). That design is exactly what made the second layer a restatement
|
|
2288
|
+
* rather than an adapter: the two could not diverge without one of them being
|
|
2289
|
+
* wrong. Folding DOWN rather than up is what keeps the public grouping and the
|
|
2290
|
+
* transport separate, which was the whole point of having two files.
|
|
2291
|
+
*
|
|
2292
|
+
* The `*Resource` interfaces come from `@shipstatic/types` and did not move.
|
|
2293
|
+
* They are the published contract; this file is how it is met.
|
|
2183
2294
|
*/
|
|
2184
2295
|
|
|
2185
2296
|
/**
|
|
2186
2297
|
* Shared context for all resource factories.
|
|
2298
|
+
*
|
|
2299
|
+
* A factory receives the callbacks it needs and nothing else — which is what
|
|
2300
|
+
* lets `getApi()` be a THUNK rather than an instance: the transport is built
|
|
2301
|
+
* once in the constructor, but reading it lazily is what keeps the resources
|
|
2302
|
+
* constructible before it exists and swappable in tests.
|
|
2187
2303
|
*/
|
|
2188
2304
|
interface ResourceContext {
|
|
2189
|
-
getApi: () =>
|
|
2190
|
-
ensureInit: () => Promise<void>;
|
|
2305
|
+
getApi: () => Transport;
|
|
2191
2306
|
}
|
|
2192
2307
|
/**
|
|
2193
2308
|
* Extended context for deployment resource.
|
|
@@ -2236,7 +2351,6 @@ declare abstract class Ship$1 {
|
|
|
2236
2351
|
private credential;
|
|
2237
2352
|
constructor(options?: ShipClientOptions);
|
|
2238
2353
|
protected abstract processInput(input: DeployInput, options: DeploymentOptions): Promise<StaticFile[]>;
|
|
2239
|
-
protected abstract getDeployBodyCreator(): DeployBodyCreator;
|
|
2240
2354
|
/**
|
|
2241
2355
|
* Lazy initialization — fetches platform limits (file size / count caps) once,
|
|
2242
2356
|
* on the first API call. Subsequent calls reuse the resolved promise.
|
|
@@ -2601,8 +2715,13 @@ declare function validateDeployFile(input: FileRuleInput, limits: PlatformLimits
|
|
|
2601
2715
|
declare function pluralize(count: number, singular: string, plural: string, includeCount?: boolean): string;
|
|
2602
2716
|
|
|
2603
2717
|
/**
|
|
2604
|
-
* @file Node
|
|
2605
|
-
*
|
|
2718
|
+
* @file The Node half of the deploy pipeline: finding files on a filesystem.
|
|
2719
|
+
*
|
|
2720
|
+
* Everything after the finding is shared (`shared/core/deploy-files.ts`) —
|
|
2721
|
+
* path optimization, junk filtering, the platform's rules, the checksums.
|
|
2722
|
+
* What is genuinely Node here is a directory walk with symlink-cycle
|
|
2723
|
+
* protection, a content path computed against the upload root, and the fact
|
|
2724
|
+
* that a Node user can point at a project folder and mean `dist/`.
|
|
2606
2725
|
*/
|
|
2607
2726
|
|
|
2608
2727
|
/**
|
|
@@ -2617,7 +2736,7 @@ declare function pluralize(count: number, singular: string, plural: string, incl
|
|
|
2617
2736
|
* in rather than read from a module global so concurrent Ships against
|
|
2618
2737
|
* different API URLs cannot clobber each other's caps.
|
|
2619
2738
|
* @returns Promise resolving to an array of StaticFile objects.
|
|
2620
|
-
* @throws {
|
|
2739
|
+
* @throws {ShipError} If called outside Node.js or if fs/path modules fail.
|
|
2621
2740
|
*/
|
|
2622
2741
|
declare function processFilesForNode(paths: string[], options?: DeploymentOptions, platformLimits?: PlatformLimits): Promise<StaticFile[]>;
|
|
2623
2742
|
|
|
@@ -2667,7 +2786,6 @@ declare class Ship extends Ship$1 {
|
|
|
2667
2786
|
*/
|
|
2668
2787
|
deploy(input: string | string[], options?: DeploymentOptions): Promise<DeploymentCreateResponse>;
|
|
2669
2788
|
protected processInput(input: DeployInput, options: DeploymentOptions): Promise<StaticFile[]>;
|
|
2670
|
-
protected getDeployBodyCreator(): DeployBodyCreator;
|
|
2671
2789
|
}
|
|
2672
2790
|
|
|
2673
|
-
export { API_KEY, API_PATHS, AUTH_BASE_PATH, type Account, type AccountDeleteResponse, type AccountGetResponse, type AccountKeyResponse, type AccountOverrides, AccountPlan, type AccountPlanType, type AccountResource, type AccountUsage, type Activity, type ActivityEvent, type ActivityListResponse, type ActivityMeta, type ApiDeployOptions, ApiHttp, type ApiHttpOptions, AuthMethod, type AuthMethodType, type BillingCancelResponse, type BillingStatus, CALLER, type CheckoutSession, DEFAULT_API, DEPLOYMENT_CONFIG_FILENAME, DEPLOY_FIELDS, DEPLOY_TOKEN, type
|
|
2791
|
+
export { API_KEY, API_PATHS, AUTH_BASE_PATH, type Account, type AccountDeleteResponse, type AccountGetResponse, type AccountKeyResponse, type AccountOverrides, AccountPlan, type AccountPlanType, type AccountResource, type AccountUsage, type Activity, type ActivityEvent, type ActivityListResponse, type ActivityMeta, type ApiDeployOptions, ApiHttp, type ApiHttpOptions, AuthMethod, type AuthMethodType, type BillingCancelResponse, type BillingStatus, CALLER, type CheckoutSession, 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, OAuthScope, type OAuthScopeType, PASSWORD_CONSTRAINTS, PUBLIC_DEPLOYMENT_TTL_SECONDS, type PingResponse, type PlatformLimits, type RequestResult, type ResourceContext, SHIP_ENV, type SPACheckDebug, type SPACheckRequest, type SPACheckResponse, SPA_CHECK_CONSTRAINTS, SPA_DEFAULT_CONFIG, 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, serializeLabels, validateApiKey, validateApiUrl, validateCaller, validateDeployFile, validateDeployPath, validateDeployToken, validateFileName, validateFiles, validateIdempotencyKey, validatePassword, validateToken, validateTtl };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var je=Object.defineProperty;var R=(n,t)=>()=>(n&&(t=n(n=0)),t);var Ye=(n,t)=>{for(var e in t)je(n,e,{get:t[e],enumerable:!0})};function xt(n){if(!n||typeof n!="string")return;let t=n.trim().toLowerCase();return Object.values(qe).includes(t)?t:void 0}function fe(n){if(n==null)return;if(typeof n!="string")throw a.validation("Idempotency key must be a string.");let t=n.trim();if(!t)throw a.validation("Idempotency key must not be empty.");if(t.length>_.MAX_LENGTH)throw a.validation(`Idempotency key must be at most ${_.MAX_LENGTH} characters.`);return t}function Qe(n){let t=n.code;return t==="ERR_INVALID_URL"?!1:typeof t=="string"?!0:n instanceof TypeError?!/\burl\b/i.test(n.message):!1}function F(n){return n!==null&&typeof n=="object"&&"name"in n&&n.name==="ShipError"&&"status"in n}function Ze(n){let t=n.replace(/\\/g,"/").split("/").pop()??"",e=t.lastIndexOf(".");return e<=0||e===t.length-1?null:t.slice(e+1).toLowerCase()}function he(n,t){let e=Ze(n);return e===null?!1:Array.isArray(t)?t.includes(e):t.has(e)}function ye(n){return tt.test(n)}function B(n){return n.replace(/\\/g,"/").split("/").filter(Boolean).some(e=>J.has(e))}function nt(n){return n.startsWith(ge.PREFIX)?x.API_KEY:n.startsWith(Ee.PREFIX)?x.DEPLOY_TOKEN:x.OPAQUE}function Te(n){let t=n.charCodeAt(0)===65279?n.slice(1):n,e;try{e=JSON.parse(t)}catch(r){throw a.config(`invalid JSON format in config: ${r.message}`,{filePath:L})}if(e===null||typeof e!="object"||Array.isArray(e))throw a.config(`${L} must contain a JSON object`,{filePath:L})}function Ae(n,t,e){if(!n.startsWith(t.PREFIX))throw a.validation(`${e} must start with "${t.PREFIX}"`);if(n.length!==t.TOTAL_LENGTH)throw a.validation(`${e} must be ${t.TOTAL_LENGTH} characters total (${t.PREFIX} + ${t.HEX_LENGTH} hex chars)`);let r=n.slice(t.PREFIX.length);if(!new RegExp(`^[a-f0-9]{${t.HEX_LENGTH}}$`,"i").test(r))throw a.validation(`${e} must contain ${t.HEX_LENGTH} hexadecimal characters after "${t.PREFIX}" prefix`)}function rt(n){Ae(n,ge,"API key")}function it(n){Ae(n,Ee,"Deploy token")}function Q(n){switch(nt(n)){case x.API_KEY:rt(n);return;case x.DEPLOY_TOKEN:it(n);return;case x.OPAQUE:if(!n)throw a.validation("Token must be a non-empty string")}}function Se(n){if(!n||n.length>C.MAX_LENGTH||!C.PATTERN.test(n))throw a.validation(`Caller must be 1-${C.MAX_LENGTH} characters: letters, digits, dots, underscores, or hyphens`)}function Ft(n){try{let t=new URL(n);if(!["http:","https:"].includes(t.protocol))throw a.validation("API URL must use http:// or https:// protocol");if(t.pathname!=="/"&&t.pathname!=="")throw a.validation("API URL must not contain a path");if(t.search||t.hash)throw a.validation("API URL must not contain query parameters or fragments")}catch(t){throw F(t)?t:a.validation("API URL must be a valid URL")}}function kt(n){return/^[a-z]+-[a-z]+-[a-z0-9]{7}(\.[a-z0-9.-]+)?$/i.test(n)}function Re(n,t){return n.endsWith(`.${t}`)}function Mt(n,t){return!Re(n,t)}function Bt(n,t){return Re(n,t)?n.slice(0,-(t.length+1)):null}function Ht(n){return`https://${n}`}function Gt(n){return`https://${n}`}function zt(n){return!n||n.length===0?null:JSON.stringify(n)}function Kt(n){if(!n)return[];try{let t=JSON.parse(n);return Array.isArray(t)?t:[]}catch{return[]}}function ee(n){if(n==null)return;if(typeof n!="string")throw a.validation("Password must be a string");let t=n.trim();if(t.length<M.MIN_LENGTH||t.length>M.MAX_LENGTH)throw a.validation(`Password must be between ${M.MIN_LENGTH} and ${M.MAX_LENGTH} characters`);return t}var bt,qe,Nt,_,vt,f,I,m,Xe,W,We,Je,a,et,Ot,tt,J,Ct,me,ge,Ee,C,x,_t,L,De,H,Z,k,Ut,$t,g,b,Ie,M,y=R(()=>{"use strict";bt={PENDING:"pending",SUCCESS:"success",FAILED:"failed",DELETING:"deleting"},qe={WEB:"web",SDK:"sdk",CLI:"cli",MCP:"mcp",GIT:"git",N8N:"n8n",GPT:"gpt",VSC:"vsc"},Nt={PENDING:"pending",PARTIAL:"partial",SUCCESS:"success",PAUSED:"paused"},_={HEADER:"Idempotency-Key",MAX_LENGTH:256,WINDOW_SECONDS:1440*60};vt={FREE:"free",STANDARD:"standard",SPONSORED:"sponsored",ENTERPRISE:"enterprise",SUSPENDED:"suspended",TERMINATING:"terminating",TERMINATED:"terminated"},f={DEPLOYMENTS:"/deployments",DEPLOYMENT:n=>`/deployments/${n}`,DEPLOYMENT_CONFIG:n=>`/deployments/${n}/config`,DOMAINS:"/domains",DOMAIN:n=>`/domains/${n}`,DOMAIN_VERIFY:n=>`/domains/${n}/verify`,DOMAIN_DNS:n=>`/domains/${n}/dns`,DOMAIN_RECORDS:n=>`/domains/${n}/records`,DOMAIN_SHARE:n=>`/domains/${n}/share`,DOMAIN_PROPAGATION:n=>`/domains/${n}/propagation`,DOMAINS_VALIDATE:"/domains/validate",TOKENS:"/tokens",TOKEN:n=>`/tokens/${n}`,ACCOUNT:"/account",ACCOUNT_KEY:"/account/key",ACCOUNT_CLAIM:"/account/claim",ACTIVITIES:"/activities",LABELS:"/labels",LIMITS:"/limits",PING:"/ping",SETUP:"/setup",SPA_CHECK:"/spa-check",UPLOAD:"/upload"},I={FILES:"files[]",CHECKSUMS:"checksums",LABELS:"labels",VIA:"via",PASSWORD:"password",BUILD:"build",PRERENDER:"prerender",SPA:"spa",CAPTCHA:"captcha"},m={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([m.Network,m.Timeout,m.Cancelled,m.File,m.Config]),W={client:new Set([m.Business,m.Cancelled,m.Config,m.File,m.Forbidden,m.NotFound,m.RateLimit,m.Validation]),network:new Set([m.Network,m.Timeout]),auth:new Set([m.Authentication])},We=new Set(Object.values(m).filter(n=>!Xe.has(n))),Je=200;a=class n extends Error{type;status;details;constructor(t,e,r,i){super(e),this.type=t,this.status=r,this.details=i,this.name="ShipError"}toResponse(){let t=this.details,e=this.type===m.Authentication&&t?.internal?void 0:this.details;return{error:this.type,message:this.message,status:this.status,details:e}}static async fromHttpResponse(t,e){let r,i,s;try{if(t.headers.get("content-type")?.includes("application/json")){let u=await t.json();if(u&&typeof u=="object"){let c=u;typeof c.message=="string"?r=c.message:typeof c.error=="string"&&(r=c.error),i=c.details,typeof c.error=="string"&&We.has(c.error)&&(s=c.error)}}else{let u=(await t.text()).trim();u&&!u.startsWith("<")&&u.length<=Je&&(r=u)}}catch{}let o=t.headers.get("retry-after");if(o!==null){let l=o.trim(),u=/^\d+$/.test(l)?Number(l):Math.ceil((Date.parse(l)-Date.now())/1e3);if(Number.isFinite(u)&&u>=0){let c=i&&typeof i=="object"?i:{};c.retryAfter===void 0&&(i={...c,retryAfter:u})}}r=r||`${e||"Request"} failed with status ${t.status}`;let p=s??(t.status===401?m.Authentication:t.status===403?m.Forbidden:t.status===429?m.RateLimit:m.Api);return new n(p,r,t.status,i)}static fromFetchError(t,e){if(F(t))return t;let r=e||"Request",i=t?.name;return i==="AbortError"?n.cancelled(`${r} was cancelled`):i==="TimeoutError"?n.timeout(`${r} timed out`,{cause:t}):t instanceof Error?Qe(t)?n.network(`${r} failed: ${t.message}`,{cause:t}):new n(m.Api,`${r} failed: ${t.message}`):new n(m.Api,`${r} failed: Unknown error`)}static validation(t,e){return new n(m.Validation,t,400,e)}static notFound(t,e){let r=e?`${t} ${e} not found`:`${t} not found`;return new n(m.NotFound,r,404)}static forbidden(t,e){return new n(m.Forbidden,t,403,e)}static rateLimit(t="Too many requests",e){return new n(m.RateLimit,t,429,e)}static authentication(t="Authentication required",e){return new n(m.Authentication,t,401,e)}static business(t,e=400,r){return new n(m.Business,t,e,r)}static network(t,e){return new n(m.Network,t,void 0,e)}static timeout(t,e){return new n(m.Timeout,t,void 0,e)}static cancelled(t,e){return new n(m.Cancelled,t,void 0,e)}static file(t,e){return new n(m.File,t,void 0,e)}static config(t,e){return new n(m.Config,t,void 0,e)}static api(t,e=500,r){return new n(m.Api,t,e,r)}static maintenance(t,e){return new n(m.Maintenance,t,503,e)}isClientError(){return W.client.has(this.type)?!0:this.status!==void 0&&this.status>=400&&this.status<500}isNetworkError(){return W.network.has(this.type)}isAuthError(){return W.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"],Ot=et.map(n=>`.${n}`).join(","),tt=/[\x00-\x1f\x7f#?%\\<>"]/;J=new Set(["node_modules","package.json"]);Ct="/auth",me={SESSION:"session",API_KEY:"apiKey",TOKEN:"token",AGENT:"agent",OAUTH:"oauth",WEBHOOK:"webhook",SYSTEM:"system"},ge={PREFIX:"ship-",HEX_LENGTH:32,TOTAL_LENGTH:37,HINT_LENGTH:4},Ee={PREFIX:"deploy-",HEX_LENGTH:32,TOTAL_LENGTH:39},C={HEADER:"X-Caller",MAX_LENGTH:128,PATTERN:/^[a-zA-Z0-9._-]+$/},x={API_KEY:me.API_KEY,DEPLOY_TOKEN:me.TOKEN,OPAQUE:"opaque"};_t={ACCOUNT_READ:"account:read",DEPLOYMENTS_READ:"deployments:read",DEPLOYMENTS_WRITE:"deployments:write",DOMAINS_READ:"domains:read",DOMAINS_WRITE:"domains:write"},L="ship.json",De={rewrites:[{source:"/(.*)",destination:"/index.html"}]},H={INDEX_FILE:"index.html",MAX_INDEX_BYTES:100*1024};Z="https://api.shipstatic.com",k={TOKEN:"SHIP_TOKEN",API_URL:"SHIP_API_URL"},Ut="https://my.shipstatic.com/api-key",$t=4320*60,g={PENDING:"pending",PROCESSING_ERROR:"processing_error",EXCLUDED:"excluded",VALIDATION_FAILED:"validation_failed",READY:"ready"};b={MIN_LENGTH:3,MAX_LENGTH:25,MAX_COUNT:10,SEPARATORS:"._-"},Ie=/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/;M={MIN_LENGTH:6,MAX_LENGTH:128}});async function ft(n){let t=(await import("spark-md5")).default,e=new t.ArrayBuffer,r=2097152;for(let i=0;i<n.size;i+=r){let s=Math.min(i+r,n.size);e.append(await n.slice(i,s).arrayBuffer())}return{md5:e.end()}}async function ht(n){let{createHash:t}=await import("crypto"),e=t("md5");return e.update(n),{md5:e.digest("hex")}}async function yt(n){let{createHash:t}=await import("crypto"),{createReadStream:e}=await import("fs");return new Promise((r,i)=>{let s=t("md5"),o=e(n);o.on("error",p=>i(a.file(`Failed to read file for MD5: ${p.message}`,{filePath:n}))),o.on("data",p=>s.update(p)),o.on("end",()=>r({md5:s.digest("hex")}))})}async function K(n){if(n instanceof Blob)return ft(n);if(typeof Buffer<"u"&&Buffer.isBuffer(n))return ht(n);if(typeof n=="string")return yt(n);throw a.business("Invalid input for MD5 calculation")}var V=R(()=>{"use strict";y()});function mn(n){ne=n}function Et(){return typeof process<"u"&&process.versions&&process.versions.node?"node":typeof window<"u"||typeof self<"u"?"browser":"unknown"}function v(){return ne||Et()}var ne,$=R(()=>{"use strict";ne=null});function Ue(n){if(!n||n.length===0)return"";let t=n.filter(s=>s&&typeof s=="string").map(s=>s.replace(/\\/g,"/"));if(t.length===0)return"";if(t.length===1)return t[0];let e=t.map(s=>s.split("/").filter(Boolean)),r=[],i=Math.min(...e.map(s=>s.length));for(let s=0;s<i;s++){let o=e[0][s];if(e.every(p=>p[s]===o))r.push(o);else break}return r.join("/")}function Y(n){return n.replace(/\\/g,"/").replace(/\/+/g,"/").replace(/^\/+/,"")}var re=R(()=>{"use strict"});function $e(n,t={}){if(t.flatten===!1)return n.map(r=>({path:Y(r),name:ie(r)}));let e=At(n);return n.map(r=>{let i=Y(r);if(e){let s=e.endsWith("/")?e:`${e}/`;i.startsWith(s)&&(i=i.substring(s.length))}return i||(i=ie(r)),{path:i,name:ie(r)}})}function At(n){if(!n.length)return"";let e=n.map(s=>Y(s)).map(s=>s.split("/")),r=[],i=Math.min(...e.map(s=>s.length));for(let s=0;s<i-1;s++){let o=e[0][s];if(e.every(p=>p[s]===o))r.push(o);else break}return r.join("/")}function ie(n){return n.split(/[/\\]/).pop()||n}var se=R(()=>{"use strict";re()});function X(n,t){return St.find(e=>e.broken(n,t))}var St,ae=R(()=>{"use strict";y();le();St=[{name:"name",broken:({path:n})=>!oe(n).valid,sentence:({path:n})=>oe(n).reason??"Invalid file name"},{name:"extension",broken:({path:n},t)=>he(n,t.blockedExtensions??[]),sentence:({path:n})=>`File extension not allowed: "${n}"`},{name:"fileSize",broken:({size:n},t)=>n>t.maxFileSize,sentence:({path:n},t)=>`File "${n}" too large. Maximum ${q(t.maxFileSize)} allowed`},{name:"totalSize",broken:({totalSize:n},t)=>n>t.maxTotalSize,sentence:({totalSize:n},t)=>`Total upload size too large. ${q(n)} exceeds maximum of ${q(t.maxTotalSize)}`}]});function q(n,t=1){if(n===0)return"0 Bytes";let e=1024,r=["Bytes","KB","MB","GB"],i=Math.floor(Math.log(n)/Math.log(e));return`${parseFloat((n/e**i).toFixed(t))} ${r[i]}`}function oe(n){if(ye(n))return{valid:!1,reason:"File name contains unsafe characters"};if(n.startsWith(" ")||n.endsWith(" "))return{valid:!1,reason:"File name cannot start/end with spaces"};if(n.endsWith("."))return{valid:!1,reason:"File name cannot end with dots"};let t=/^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(\.|$)/i,e=n.split("/").pop()||n;return t.test(e)?{valid:!1,reason:"File name uses a reserved system name"}:n.includes("..")?{valid:!1,reason:"File name contains path traversal pattern"}:{valid:!0}}function _n(n,t){let e=[],r=[],i=[];if(n.length===0){let l={file:"(no files)",message:"At least one file must be provided"};return e.push(l),{files:[],validFiles:[],errors:e,warnings:[],canDeploy:!1}}for(let l of n)if(B(l.name))return e.push({file:l.name,message:"Unbuilt project detected \u2014 deploy your build output (dist/, build/, out/), not the project folder"}),{files:n.map(u=>({...u,status:g.VALIDATION_FAILED,statusMessage:"Unbuilt project detected"})),validFiles:[],errors:e,warnings:[],canDeploy:!1};if(n.length>t.maxFilesCount){let l={file:`(${n.length} files)`,message:`File count (${n.length}) exceeds limit of ${t.maxFilesCount}`};return e.push(l),{files:n.map(u=>({...u,status:g.VALIDATION_FAILED,statusMessage:l.message})),validFiles:[],errors:e,warnings:[],canDeploy:!1}}let s=0;for(let l of n){let u=g.READY,c="Ready for upload";if(l.status===g.PROCESSING_ERROR)u=g.VALIDATION_FAILED,c=l.statusMessage||"File failed during processing",e.push({file:l.name,message:c});else if(l.size===0){u=g.EXCLUDED,c="File is empty (0 bytes) and cannot be deployed due to storage limitations",r.push({file:l.name,message:c}),i.push({...l,status:u,statusMessage:c});continue}else if(l.size<0)u=g.VALIDATION_FAILED,c="File size must be positive",e.push({file:l.name,message:c});else if(!l.name||l.name.trim().length===0)u=g.VALIDATION_FAILED,c="File name cannot be empty",e.push({file:l.name||"(empty)",message:c});else if(l.name.includes("\0"))u=g.VALIDATION_FAILED,c="File name contains invalid characters (null byte)",e.push({file:l.name,message:c});else{let E={path:l.name,size:l.size,totalSize:s+l.size},P=X(E,t);P?(u=g.VALIDATION_FAILED,c=P.sentence(E,t),e.push({file:P.name==="totalSize"?`(${n.length} files)`:l.name,message:c})):s=E.totalSize}i.push({...l,status:u,statusMessage:c})}e.length>0&&(i=i.map(l=>l.status===g.EXCLUDED?l:{...l,status:g.VALIDATION_FAILED,statusMessage:l.status===g.VALIDATION_FAILED?l.statusMessage:"Deployment failed due to validation errors in bundle"}));let o=e.length===0?i.filter(l=>l.status===g.READY):[],p=e.length===0;return{files:i,validFiles:o,errors:e,warnings:r,canDeploy:p}}function Rt(n){return n.filter(t=>t.status===g.READY)}function Fn(n){return Rt(n).length>0}var le=R(()=>{"use strict";y();ae()});import{isJunk as It}from"junk";function Me(n,t){if(!n||n.length===0)return[];if(!t?.allowUnbuilt&&n.find(r=>r&&B(r)))throw a.business("Unbuilt project detected \u2014 deploy your build output (dist/, build/, out/), not the project folder");return n.filter(e=>{if(!e)return!1;let r=e.replace(/\\/g,"/").split("/").filter(Boolean);if(r.length===0)return!0;let i=r[r.length-1];if(It(i))return!1;for(let o of r)if(o!==".well-known"&&(o.startsWith(".")||o.length>255))return!1;let s=r.slice(0,-1);for(let o of s)if(Pt.some(p=>o.toLowerCase()===p.toLowerCase()))return!1;return!0})}var Pt,ce=R(()=>{"use strict";y();Pt=["__MACOSX",".Trashes",".fseventsd",".Spotlight-V100"]});function Be(n,t){if(n.includes("\0")||n.includes("/../")||n.startsWith("../")||n.endsWith("/.."))throw a.business(`Security error: Unsafe file path "${n}" for file: ${t}`)}function He(n,t){let e=X(n,t);if(e)throw a.business(e.sentence(n,t))}var pe=R(()=>{"use strict";y();ae()});var Ke={};Ye(Ke,{processFilesForNode:()=>ze});import*as D from"fs";import*as T from"path";function Ge(n,t=new Set){let e=[],r=D.realpathSync(n);if(t.has(r))return e;t.add(r);let i=D.readdirSync(n);for(let s of i){let o=T.join(n,s),p=D.statSync(o);if(p.isDirectory()){let l=Ge(o,t);e.push(...l)}else p.isFile()&&e.push(o)}return e}async function ze(n,t={},e){if(v()!=="node")throw a.business("processFilesForNode can only be called in Node.js environment.");for(let d of n){let h=T.resolve(d);try{if(D.statSync(h).isDirectory()){let A=D.readdirSync(h).find(S=>J.has(S));if(A)throw a.business(`"${A}" detected \u2014 deploy your build output (dist/, build/, out/), not the project folder`)}}catch(A){if(F(A))throw A}}let r=n.flatMap(d=>{let h=T.resolve(d);try{return D.statSync(h).isDirectory()?Ge(h):[h]}catch{throw a.file(`Path does not exist: ${d}`,{filePath:d})}}),i=[...new Set(r)],s=n.map(d=>T.resolve(d)),o=Ue(s.map(d=>{try{return D.statSync(d).isDirectory()?d:T.dirname(d)}catch{return T.dirname(d)}})),p=i.map(d=>{if(o&&o.length>0){let h=T.relative(o,d);if(h&&typeof h=="string"&&!h.startsWith(".."))return h.replace(/\\/g,"/")}return T.basename(d)}),u=$e(p,{flatten:t.pathDetect!==!1}).map(d=>d.path),c=new Set(Me(u));if(c.size===0)return[];let E=[],P=[];for(let d=0;d<i.length;d++)c.has(u[d])&&(E.push(i[d]),P.push(u[d]));let N=[],w=0;if(!e)throw a.config("Platform limits not provided. processFilesForNode requires the limits argument \u2014 pass `ship.getLimits()` result.");for(let d=0;d<E.length;d++){let h=E[d],A=P[d];try{Be(A,h);let S=D.statSync(h);if(S.size===0)continue;w+=S.size,He({path:A,size:S.size,totalSize:w},e);let O=D.readFileSync(h),{md5:Ve}=await K(O);N.push({path:A,content:O,size:O.length,md5:Ve})}catch(S){if(F(S))throw S;let O=S instanceof Error?S.message:String(S);throw a.file(`Failed to read file "${h}": ${O}`,{filePath:h})}}if(N.length>e.maxFilesCount)throw a.business(`Too many files to deploy. Maximum allowed is ${e.maxFilesCount} files.`);return N}var ue=R(()=>{"use strict";y();se();$();ce();V();re();pe()});y();y();y();var G=class{constructor(){this.handlers=new Map}on(t,e){this.handlers.has(t)||this.handlers.set(t,new Set),this.handlers.get(t)?.add(e)}off(t,e){let r=this.handlers.get(t);r&&(r.delete(e),r.size===0&&this.handlers.delete(t))}emit(t,...e){let r=this.handlers.get(t);if(!r)return;let i=Array.from(r);for(let s of i)try{s(...e)}catch(o){r.delete(s),t!=="error"&&setTimeout(()=>{let p=o instanceof Error?o:new Error(String(o));this.emit("error",p,String(t))},0)}}};y();y();function U(n){if(n==null)return;if(n.length===0)return n;if(n.length>b.MAX_COUNT)throw a.validation(`Maximum ${b.MAX_COUNT} labels allowed`);let t=n.map((r,i)=>{if(typeof r!="string")throw a.validation(`Label at index ${i} must be a string`);let s=r.trim().toLowerCase();if(s.length<b.MIN_LENGTH)throw a.validation(`Labels must be at least ${b.MIN_LENGTH} characters long`);if(s.length>b.MAX_LENGTH)throw a.validation(`Labels must be no more than ${b.MAX_LENGTH} characters long`);if(!Ie.test(s))throw a.validation(`Labels must start and end with alphanumeric characters, with optional separators (${b.SEPARATORS}) between segments`);return s}),e=[...new Set(t)];if(e.length!==t.length)throw a.validation("Duplicate labels are not allowed");return e}async function Pe(n){let t=n.find(i=>i.path===L||i.path===`/${L}`);if(!t)return;let e=t.content,r=typeof e.text=="function"?await e.text():t.content.toString("utf8");Te(r)}var st=3e4,ot=2,at=300,lt=2e3,ct=new Set([500,502,503,504]);function pt(n,t){return new Promise((e,r)=>{if(t?.aborted){r(t.reason);return}let i=()=>{clearTimeout(o),t?.removeEventListener("abort",s)},s=()=>{i(),r(t?.reason)},o=setTimeout(()=>{i(),e()},n);t?.addEventListener("abort",s)})}var Le=3e5,ut=3e5,dt=Le+ut,mt="sdk";function te(n){let t=new URLSearchParams;n?.limit!==void 0&&t.set("limit",String(n.limit)),n?.cursor!==void 0&&t.set("cursor",n.cursor);let e=t.toString();return e?`?${e}`:""}var z=class extends G{constructor(e){super();this.globalHeaders={};this.apiUrl=e.apiUrl||Z,this.getAuthHeadersCallback=e.getAuthHeaders,this.session=e.session??!1,this.caller=e.caller,this.timeout=e.timeout??st,this.maxRetries=Math.max(0,e.maxRetries??ot),this.deployTimeout=e.timeout??Le,this.deployBuildTimeout=e.timeout??dt,this.fetch=e.fetch??globalThis.fetch.bind(globalThis),this.createDeployBody=e.createDeployBody,this.deployEndpoint=e.deployEndpoint||f.DEPLOYMENTS}setGlobalHeaders(e){this.globalHeaders=e}async executeRequest(e,r,i,s=this.timeout){for(let o=0;;o++)try{return await this.attemptOnce(e,r,i,s)}catch(p){let l=a.fromFetchError(p,i);if(o>=this.maxRetries||!this.isRetryable(l,r))throw this.emit("error",l,e),l;this.emit("retry",l,e,o+1);let u=Math.min(lt,at*2**o);try{await pt(Math.random()*u,r.signal)}catch(c){let E=a.fromFetchError(c,i);throw this.emit("error",E,e),E}}}isRetryable(e,r){if(r.signal?.aborted||e.isType(m.Maintenance)||e.isType(m.Cancelled)||!(e.isNetworkError()||e.status!==void 0&&ct.has(e.status)))return!1;let s=(r.method??"GET").toUpperCase();return s==="GET"||s==="HEAD"?!0:s==="PUT"||s==="DELETE"?!1:this.hasIdempotencyKey(r.headers)}hasIdempotencyKey(e){if(!e)return!1;let r=_.HEADER.toLowerCase(),i=!1,s=o=>{o.toLowerCase()===r&&(i=!0)};if(e instanceof Headers)e.forEach((o,p)=>{s(p)});else if(Array.isArray(e))for(let[o]of e)s(o);else for(let o of Object.keys(e))s(o);return i}async attemptOnce(e,r,i,s=this.timeout){let o=()=>{};try{let p=await this.mergeHeaders(r.headers),l=this.createTimeoutSignal(r.signal,s);o=l.cleanup;let u={...r,headers:p,credentials:this.session&&!p.Authorization?"include":void 0,signal:l.signal};this.emit("request",e,u);let c=await this.fetch(e,u);if(o(),!c.ok)throw await a.fromHttpResponse(c,i);return this.emit("response",this.safeClone(c),e),{data:await this.parseResponse(this.safeClone(c)),status:c.status}}catch(p){throw o(),a.fromFetchError(p,i)}}async request(e,r,i,s){let{data:o}=await this.executeRequest(e,r,i,s);return o}async requestWithStatus(e,r,i){return this.executeRequest(e,r,i)}async mergeHeaders(e={}){return{...this.globalHeaders,...this.caller?{[C.HEADER]:this.caller}:{},...await this.getAuthHeadersCallback(),...e}}createTimeoutSignal(e,r=this.timeout){let i=new AbortController,s=setTimeout(()=>i.abort(new DOMException(`Timed out after ${r}ms`,"TimeoutError")),r),o=e?()=>i.abort(e.reason):void 0;return e&&o&&(e.addEventListener("abort",o),e.aborted&&i.abort(e.reason)),{signal:i.signal,cleanup:()=>{clearTimeout(s),e&&o&&e.removeEventListener("abort",o)}}}safeClone(e){try{return e.clone()}catch{return e}}async parseResponse(e){if(!(e.headers.get("Content-Length")==="0"||e.status===204))return e.json()}async deploy(e,r={}){if(!e.length)throw a.business("No files to deploy");for(let u of e)if(!u.md5)throw a.file(`MD5 checksum missing for file: ${u.path}`,{filePath:u.path});ee(r.password);let i=fe(r.idempotencyKey),s=U(r.labels);await Pe(e);let o=r.build||r.prerender||r.spa?{build:r.build,prerender:r.prerender,spa:r.spa}:void 0,{body:p,headers:l}=await this.createDeployBody(e,{labels:s,via:r.via??mt,password:r.password,flags:o,captcha:r.captcha});return this.request(`${this.apiUrl}${this.deployEndpoint}`,{method:"POST",body:p,headers:i?{...l,[_.HEADER]:i}:l,signal:r.signal||null},"Deploy",r.build||r.prerender?this.deployBuildTimeout:this.deployTimeout)}async listDeployments(e){return this.request(`${this.apiUrl}${f.DEPLOYMENTS}${te(e)}`,{method:"GET"},"List deployments")}async getDeployment(e){return this.request(`${this.apiUrl}${f.DEPLOYMENT(encodeURIComponent(e))}`,{method:"GET"},"Get deployment")}async updateDeploymentLabels(e,r){let i=U(r);return this.request(`${this.apiUrl}${f.DEPLOYMENT(encodeURIComponent(e))}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({labels:i})},"Update deployment labels")}async deleteDeployment(e){return this.request(`${this.apiUrl}${f.DEPLOYMENT(encodeURIComponent(e))}`,{method:"DELETE"},"Delete deployment")}async setDomain(e,r,i){let s=U(i),o={};r&&(o.deployment=r),s!==void 0&&(o.labels=s);let{data:p,status:l}=await this.requestWithStatus(`${this.apiUrl}${f.DOMAIN(encodeURIComponent(e))}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(o)},"Set domain");return{...p,isCreate:l===201}}async listDomains(e){return this.request(`${this.apiUrl}${f.DOMAINS}${te(e)}`,{method:"GET"},"List domains")}async getDomain(e){return this.request(`${this.apiUrl}${f.DOMAIN(encodeURIComponent(e))}`,{method:"GET"},"Get domain")}async deleteDomain(e){return this.request(`${this.apiUrl}${f.DOMAIN(encodeURIComponent(e))}`,{method:"DELETE"},"Delete domain")}async verifyDomain(e){return this.request(`${this.apiUrl}${f.DOMAIN_VERIFY(encodeURIComponent(e))}`,{method:"POST"},"Verify domain")}async getDomainDns(e){return this.request(`${this.apiUrl}${f.DOMAIN_DNS(encodeURIComponent(e))}`,{method:"GET"},"Get domain DNS")}async getDomainRecords(e){return this.request(`${this.apiUrl}${f.DOMAIN_RECORDS(encodeURIComponent(e))}`,{method:"GET"},"Get domain records")}async getDomainShare(e){return this.request(`${this.apiUrl}${f.DOMAIN_SHARE(encodeURIComponent(e))}`,{method:"GET"},"Get domain share")}async validateDomain(e){return this.request(`${this.apiUrl}${f.DOMAINS_VALIDATE}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({domain:e})},"Validate domain")}async createToken(e,r){let i=U(r),s={};return e!==void 0&&(s.ttl=e),i!==void 0&&(s.labels=i),this.request(`${this.apiUrl}${f.TOKENS}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)},"Create token")}async listTokens(e){return this.request(`${this.apiUrl}${f.TOKENS}${te(e)}`,{method:"GET"},"List tokens")}async deleteToken(e){return this.request(`${this.apiUrl}${f.TOKEN(encodeURIComponent(e))}`,{method:"DELETE"},"Delete token")}async getToken(e){return this.request(`${this.apiUrl}${f.TOKEN(encodeURIComponent(e))}`,{method:"GET"},"Get token")}async getAccount(){return this.request(`${this.apiUrl}${f.ACCOUNT}`,{method:"GET"},"Get account")}async getLimits(){return this.request(`${this.apiUrl}${f.LIMITS}`,{method:"GET"},"Get limits")}async ping(){return this.request(`${this.apiUrl}${f.PING}`,{method:"GET"},"Ping")}async checkSPA(e,r={}){let i=e.find(l=>l.path===H.INDEX_FILE||l.path===`/${H.INDEX_FILE}`);if(!i||i.size>H.MAX_INDEX_BYTES)return!1;let s;if(typeof Buffer<"u"&&Buffer.isBuffer(i.content))s=i.content.toString("utf-8");else if(typeof Blob<"u"&&i.content instanceof Blob)s=await i.content.text();else if(typeof File<"u"&&i.content instanceof File)s=await i.content.text();else return!1;let o={files:e.map(l=>l.path),index:s};return(await this.request(`${this.apiUrl}${f.SPA_CHECK}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o)},"SPA check")).isSPA}};y();y();V();async function gt(){let n=JSON.stringify(De,null,2),t;typeof Buffer<"u"?t=Buffer.from(n,"utf-8"):t=new Blob([n],{type:"application/json"});let{md5:e}=await K(t);return{path:L,content:t,size:n.length,md5:e}}async function we(n,t,e){if(e.spaDetect===!1||e.spa||e.build||e.prerender||n.some(r=>r.path===L))return n;try{if(await t.checkSPA(n,e)){let i=await gt();return[...n,i]}}catch{}return n}function be(n){let{getApi:t,ensureInit:e,processInput:r}=n;return{upload:async(i,s={})=>{if(await e(),!r)throw a.config("processInput function is not provided.");let o=t(),p=await r(i,s);return p=await we(p,o,s),o.deploy(p,s)},list:async i=>(await e(),t().listDeployments(i)),get:async i=>(await e(),t().getDeployment(i)),set:async(i,s)=>(await e(),t().updateDeploymentLabels(i,s.labels)),delete:async i=>(await e(),t().deleteDeployment(i))}}function Ne(n){let{getApi:t,ensureInit:e}=n;return{set:async(r,i={})=>(await e(),t().setDomain(r,i.deployment,i.labels)),list:async r=>(await e(),t().listDomains(r)),get:async r=>(await e(),t().getDomain(r)),delete:async r=>(await e(),t().deleteDomain(r)),verify:async r=>(await e(),t().verifyDomain(r)),validate:async r=>(await e(),t().validateDomain(r)),dns:async r=>(await e(),t().getDomainDns(r)),records:async r=>(await e(),t().getDomainRecords(r)),share:async r=>(await e(),t().getDomainShare(r))}}function xe(n){let{getApi:t,ensureInit:e}=n;return{get:async()=>(await e(),t().getAccount())}}function ve(n){let{getApi:t,ensureInit:e}=n;return{create:async(r={})=>(await e(),t().createToken(r.ttl,r.labels)),list:async r=>(await e(),t().listTokens(r)),get:async r=>(await e(),t().getToken(r)),delete:async r=>(await e(),t().deleteToken(r))}}var j=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&&Se(t.caller),t.token&&t.session)throw a.config("Provide either `token` or `session`, not both.");typeof t.token=="string"?(Q(t.token),this.credential=t.token):t.token&&(this.credential=t.token),this.http=new z({...t,getAuthHeaders:()=>this.getAuthHeaders(),createDeployBody:this.getDeployBodyCreator()});let e={getApi:()=>this.http,ensureInit:()=>this.ensureInitialized()};this.deployments=be({...e,processInput:(r,i)=>this.processInput(r,i)}),this.domains=Ne(e),this.account=xe(e),this.tokens=ve(e)}async ensureInitialized(){return this.initPromise||(this.initPromise=this.fetchPlatformLimits()),this.initPromise}async fetchPlatformLimits(){try{this.platformLimits=await this.http.getLimits()}catch(t){throw this.initPromise=null,t}}async ping(){return await this.ensureInitialized(),this.http.ping()}async deploy(t,e){return this.deployments.upload(t,e)}async whoami(){return this.account.get()}async getLimits(){return this.platformLimits?this.platformLimits:(await this.ensureInitialized(),this.platformLimits)}on(t,e){this.http.on(t,e)}off(t,e){this.http.off(t,e)}setHeaders(t){this.http.setGlobalHeaders(t)}clearHeaders(){this.http.setGlobalHeaders({})}setToken(t){if(this.clientOptions.session)throw a.config("Provide either `token` or `session`, not both.");if(typeof t=="string"){if(!t)throw a.business("Invalid token provided. Token must be a non-empty string.");Q(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}`}}};$();y();import{z as _e}from"zod";import{z as Oe}from"zod";var Ce={apiUrl:Oe.string().url().optional(),token:Oe.string().min(1).optional()};$();var Dt=_e.object(Ce).strict(),Tt={apiUrl:k.API_URL,token:k.TOKEN};function Fe(){if(v()!=="node")return{};let n={apiUrl:process.env[k.API_URL]||void 0,token:process.env[k.TOKEN]||void 0};try{return Dt.parse(n)}catch(t){if(t instanceof _e.ZodError){let e=t.issues[0],r=e.path[0],i=(r&&Tt[r])??"SHIP environment configuration";throw a.config(`Invalid ${i}: ${e.message}`)}throw a.config("Invalid environment configuration")}}y();async function ke(n,t={}){let{FormData:e,File:r}=await import("formdata-node"),{FormDataEncoder:i}=await import("form-data-encoder"),{labels:s,via:o,password:p,flags:l,captcha:u}=t,c=new e,E=[];for(let d of n){if(!Buffer.isBuffer(d.content)&&!(typeof Blob<"u"&&d.content instanceof Blob))throw a.file(`Unsupported file.content type for Node.js: ${d.path}`,{filePath:d.path});if(!d.md5)throw a.file(`File missing md5 checksum: ${d.path}`,{filePath:d.path});let h=new r([d.content],d.path,{type:"application/octet-stream"});c.append(I.FILES,h),E.push(d.md5)}c.append(I.CHECKSUMS,JSON.stringify(E)),s&&s.length>0&&c.append(I.LABELS,JSON.stringify(s)),o&&c.append(I.VIA,o),p&&c.append(I.PASSWORD,p),l?.build&&c.append(I.BUILD,"true"),l?.prerender&&c.append(I.PRERENDER,"true"),l?.spa&&c.append(I.SPA,"true"),u&&c.append(I.CAPTCHA,u);let P=new i(c),N=[];for await(let d of P.encode())N.push(Buffer.from(d));let w=Buffer.concat(N);return{body:w.buffer.slice(w.byteOffset,w.byteOffset+w.byteLength),headers:{"Content-Type":P.contentType,"Content-Length":Buffer.byteLength(w).toString()}}}y();y();se();$();le();ce();V();pe();function zn(n,t,e,r=!0){let i=n===1?t:e;return r?`${n} ${i}`:i}ue();var de=class extends j{constructor(t={}){if(v()!=="node")throw a.business("Node.js Ship class can only be used in Node.js environment.");let e=Fe();super({...t,apiUrl:t.apiUrl||e.apiUrl,token:t.token||(t.session?void 0:e.token)})}async deploy(t,e){return super.deploy(t,e)}async processInput(t,e){let r=typeof t=="string"?[t]:t;if(!Array.isArray(r)||!r.every(s=>typeof s=="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(),Ke));return i(r,e,this.platformLimits??void 0)}getDeployBodyCreator(){return ke}},Lt=de;export{ge as API_KEY,f as API_PATHS,Ct as AUTH_BASE_PATH,vt as AccountPlan,z as ApiHttp,me as AuthMethod,C as CALLER,Z as DEFAULT_API,L as DEPLOYMENT_CONFIG_FILENAME,I as DEPLOY_FIELDS,Ee as DEPLOY_TOKEN,bt as DeploymentStatus,qe as DeploymentVia,Nt as DomainStatus,m as ErrorType,g as FILE_VALIDATION_STATUS,g as FileValidationStatus,_ as IDEMPOTENCY_KEY_CONSTRAINTS,Pt as JUNK_DIRECTORIES,b as LABEL_CONSTRAINTS,Ie as LABEL_PATTERN,Ut as MY_API_KEY_URL,_t as OAuthScope,M as PASSWORD_CONSTRAINTS,$t as PUBLIC_DEPLOYMENT_TTL_SECONDS,k as SHIP_ENV,H as SPA_CHECK_CONSTRAINTS,De as SPA_DEFAULT_CONFIG,de as Ship,a as ShipError,x as TokenKind,J as UNBUILT_PROJECT_MARKERS,tt as UNSAFE_FILENAME_CHARS,Ot as WEB_FILE_ACCEPT,mn as __setTestEnvironment,Fn as allValidFilesReady,Te as assertShipJsonSyntax,K as calculateMD5,nt as classifyToken,xe as createAccountResource,be as createDeploymentResource,Ne as createDomainResource,ve as createTokenResource,Lt as default,Kt as deserializeLabels,Bt as extractSubdomain,Me as filterJunk,q as formatFileSize,Ht as generateDeploymentUrl,Gt as generateDomainUrl,v as getENV,Rt as getValidFiles,B as hasUnbuiltMarker,ye as hasUnsafeChars,he as isBlockedExtension,Mt as isCustomDomain,kt as isDeployment,Re as isPlatformDomain,F as isShipError,xt as normalizeVia,$e as optimizeDeployPaths,zn as pluralize,ze as processFilesForNode,zt as serializeLabels,rt as validateApiKey,Ft as validateApiUrl,Se as validateCaller,He as validateDeployFile,Be as validateDeployPath,it as validateDeployToken,oe as validateFileName,_n as validateFiles,fe as validateIdempotencyKey,ee as validatePassword,Q as validateToken};
|
|
1
|
+
var Ke=Object.defineProperty;var T=(e,t)=>()=>(e&&(t=e(e=0)),t);var Ve=(e,t)=>{for(var n in t)Ke(e,n,{get:t[n],enumerable:!0})};function _t(e){if(!e||typeof e!="string")return;let t=e.trim().toLowerCase();return Object.values(qe).includes(t)?t:void 0}function ue(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 We(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 Je(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 de(e,t){let n=Je(e);return n===null?!1:Array.isArray(t)?t.includes(n):t.has(n)}function me(e){return Ze.test(e)}function F(e){return e.replace(/\\/g,"/").split("/").filter(Boolean).some(n=>Y.has(n))}function et(e){return e.startsWith(fe.PREFIX)?I.API_KEY:e.startsWith(he.PREFIX)?I.DEPLOY_TOKEN:I.OPAQUE}function Ee(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 ge(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 tt(e){ge(e,fe,"API key")}function nt(e){ge(e,he,"Deploy token")}function j(e){switch(et(e)){case I.API_KEY:tt(e);return;case I.DEPLOY_TOKEN:nt(e);return;case I.OPAQUE:if(!e)throw a.validation("Token must be a non-empty string")}}function Te(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 Ut(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 Ht(e){return/^[a-z]+-[a-z]+-[a-z0-9]{7}(\.[a-z0-9.-]+)?$/i.test(e)}function X(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<v.MIN_SECONDS||e>v.MAX_SECONDS)throw a.validation(`TTL must be between ${v.MIN_SECONDS} and ${v.MAX_SECONDS} seconds`);return e}}function Se(e,t){return e.endsWith(`.${t}`)}function Bt(e,t){return!Se(e,t)}function zt(e,t){return Se(e,t)?e.slice(0,-(t.length+1)):null}function Kt(e){return`https://${e}`}function Vt(e){return`https://${e}`}function qt(e){return!e||e.length===0?null:JSON.stringify(e)}function Yt(e){if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}function J(e){if(e==null)return;if(typeof e!="string")throw a.validation("Password must be a string");let t=e.trim();if(t.length<_.MIN_LENGTH||t.length>_.MAX_LENGTH)throw a.validation(`Password must be between ${_.MIN_LENGTH} and ${_.MAX_LENGTH} characters`);return t}var Ot,qe,vt,L,Ct,m,S,d,Ye,q,je,Xe,a,Qe,Ft,Ze,Y,Mt,ce,fe,he,b,I,kt,A,ye,M,v,W,x,$t,Gt,h,R,Ae,_,f=T(()=>{"use strict";Ot={PENDING:"pending",SUCCESS:"success",FAILED:"failed",DELETING:"deleting"},qe={WEB:"web",SDK:"sdk",CLI:"cli",MCP:"mcp",GIT:"git",N8N:"n8n",GPT:"gpt",VSC:"vsc"},vt={PENDING:"pending",PARTIAL:"partial",SUCCESS:"success",PAUSED:"paused"},L={HEADER:"Idempotency-Key",MAX_LENGTH:256,WINDOW_SECONDS:1440*60};Ct={FREE:"free",STANDARD:"standard",SPONSORED:"sponsored",ENTERPRISE:"enterprise",SUSPENDED:"suspended",TERMINATING:"terminating",TERMINATED:"terminated"},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",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"},Ye=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])},je=new Set(Object.values(d).filter(e=>!Ye.has(e))),Xe=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"&&je.has(p.error)&&(o=p.error)}}else{let u=(await t.text()).trim();u&&!u.startsWith("<")&&u.length<=Xe&&(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?We(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}};Qe=["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"],Ft=Qe.map(e=>`.${e}`).join(","),Ze=/[\x00-\x1f\x7f#?%\\<>"]/;Y=new Set(["node_modules","package.json"]);Mt="/auth",ce={SESSION:"session",API_KEY:"apiKey",TOKEN:"token",AGENT:"agent",OAUTH:"oauth",WEBHOOK:"webhook",SYSTEM:"system"},fe={PREFIX:"ship-",HEX_LENGTH:32,TOTAL_LENGTH:37,HINT_LENGTH:4},he={PREFIX:"deploy-",HEX_LENGTH:32,TOTAL_LENGTH:39},b={HEADER:"X-Caller",MAX_LENGTH:128,PATTERN:/^[a-zA-Z0-9._-]+$/},I={API_KEY:ce.API_KEY,DEPLOY_TOKEN:ce.TOKEN,OPAQUE:"opaque"};kt={ACCOUNT_READ:"account:read",DEPLOYMENTS_READ:"deployments:read",DEPLOYMENTS_WRITE:"deployments:write",DOMAINS_READ:"domains:read",DOMAINS_WRITE:"domains:write"},A="ship.json",ye={rewrites:[{source:"/(.*)",destination:"/index.html"}]},M={INDEX_FILE:"index.html",MAX_INDEX_BYTES:100*1024};v={MIN_SECONDS:1,MAX_SECONDS:365*24*60*60};W="https://api.shipstatic.com",x={TOKEN:"SHIP_TOKEN",API_URL:"SHIP_API_URL"},$t="https://my.shipstatic.com/api-key",Gt=4320*60,h={PENDING:"pending",PROCESSING_ERROR:"processing_error",EXCLUDED:"excluded",VALIDATION_FAILED:"validation_failed",READY:"ready"};R={MIN_LENGTH:3,MAX_LENGTH:25,MAX_COUNT:10,SEPARATORS:"._-"},Ae=/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/;_={MIN_LENGTH:6,MAX_LENGTH:128}});async function ut(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 dt(e){let{createHash:t}=await import("crypto"),n=t("md5");return n.update(e),{md5:n.digest("hex")}}async function mt(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 ut(e);if(typeof Buffer<"u"&&Buffer.isBuffer(e))return dt(e);if(typeof e=="string")return mt(e);throw a.business("Invalid input for MD5 calculation")}var $=T(()=>{"use strict";f()});function Tn(e){Z=e}function Et(){return typeof process<"u"&&process.versions&&process.versions.node?"node":typeof window<"u"||typeof self<"u"?"browser":"unknown"}function N(){return Z||Et()}var Z,O=T(()=>{"use strict";Z=null});function Ce(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 ee=T(()=>{"use strict"});function Fe(e,t={}){if(t.flatten===!1)return e.map(r=>({path:z(r),name:te(r)}));let n=St(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=te(r)),{path:i,name:te(r)}})}function St(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 te(e){return e.split(/[/\\]/).pop()||e}var ne=T(()=>{"use strict";ee()});function V(e,t){return At.find(n=>n.broken(e,t))}var At,ie=T(()=>{"use strict";f();oe();At=[{name:"name",broken:({path:e})=>!re(e).valid,sentence:({path:e})=>re(e).reason??"Invalid file name"},{name:"extension",broken:({path:e},t)=>de(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 re(e){if(me(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 Un(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},D=V(y,t);D?(u=h.VALIDATION_FAILED,p=D.sentence(y,t),n.push({file:D.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 Dt(e){return e.filter(t=>t.status===h.READY)}function Hn(e){return Dt(e).length>0}var oe=T(()=>{"use strict";f();ie()});import{isJunk as Rt}from"junk";function Me(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(Rt(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(It.some(c=>l.toLowerCase()===c.toLowerCase()))return!1;return!0})}var It,se=T(()=>{"use strict";f();It=["__MACOSX",".Trashes",".fseventsd",".Spotlight-V100"]});function ke(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 Ue(e,t){let n=V(e,t);if(n)throw a.business(n.sentence(e,t))}var ae=T(()=>{"use strict";f();ie()});async function He(e,t={},n){let r=!!(t.build||t.prerender),i=Fe(e.map(p=>p.path),{flatten:t.pathDetect!==!1}).map(p=>p.path),o=new Set(Me(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:Lt(n),s=[],u=0;for(let{source:p,deployPath:y}of l){if(c&&ke(y,p.origin),p.size===0)continue;c&&(u+=p.size,Ue({path:y,size:p.size,totalSize:u},c));let D=await p.read(),{md5:P}=await H(D);s.push({path:y,content:D,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 Lt(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 $e=T(()=>{"use strict";f();ne();se();$();ae()});var ze={};Ve(ze,{processFilesForNode:()=>Be});import*as g from"fs";import*as E from"path";function Ge(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(...Ge(o,t)):l.isFile()&&n.push({absPath:o,size:l.size})}return n}async function Nt(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 Pt(e){for(let t of e){let n=E.resolve(t);try{if(g.statSync(n).isDirectory()){let r=g.readdirSync(n).find(i=>Y.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 Be(e,t={},n){if(N()!=="node")throw a.business("processFilesForNode can only be called in Node.js environment.");Pt(e);let r=e.flatMap(c=>{let s=E.resolve(c);try{let u=g.statSync(s);return u.isDirectory()?Ge(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=Ce(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:bt(c,o),origin:c,size:s,read:()=>Nt(c)}));return He(l,t,n)}function bt(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 le=T(()=>{"use strict";f();$e();O();ee()});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 rt=3e4,it=2,ot=300,st=2e3,at=new Set([500,502,503,504]);function lt(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 De=3e5,pt=3e5,ct=De+pt,U=class extends k{constructor(n){super();this.globalHeaders={};this.apiUrl=n.apiUrl||W,this.getAuthHeadersCallback=n.getAuthHeaders,this.session=n.session??!1,this.caller=n.caller,this.timeout=n.timeout??rt,this.maxRetries=Math.max(0,n.maxRetries??it),this.fetch=n.fetch??globalThis.fetch.bind(globalThis),this.deploy={endpoint:n.deployEndpoint||m.DEPLOYMENTS,timeout:n.timeout??De,buildTimeout:n.timeout??ct}}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(st,ot*2**l);try{await lt(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&&at.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 Re(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 ft(){let e=JSON.stringify(ye,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 ht(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 Ie(e,t,n){if(n.spaDetect===!1||n.spa||n.build||n.prerender||e.some(r=>r.path===A))return e;try{if(await ht(e,t)){let i=await ft();return[...e,i]}}catch{}return e}f();f();function w(e){if(e==null)return;if(e.length===0)return e;if(e.length>R.MAX_COUNT)throw a.validation(`Maximum ${R.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<R.MIN_LENGTH)throw a.validation(`Labels must be at least ${R.MIN_LENGTH} characters long`);if(o.length>R.MAX_LENGTH)throw a.validation(`Labels must be no more than ${R.MAX_LENGTH} characters long`);if(!Ae.test(o))throw a.validation(`Labels must start and end with alphanumeric characters, with optional separators (${R.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 Le(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");Ee(r)}var G={"Content-Type":"application/json"},yt="sdk";function Q(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 Ne(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 Ie(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});J(i.password);let s=X(i.ttl),u=ue(i.idempotencyKey),p=w(i.labels);await Le(c);let y=i.build||i.prerender||i.spa?{build:i.build,prerender:i.prerender,spa:i.spa}:void 0,D=await Re(c,{labels:p,via:i.via??yt,password:i.password,ttl:s,flags:y,captcha:i.captcha});return o.request(o.deploy.endpoint,{method:"POST",body:D,...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}${Q(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:w(i.labels)})},"Update deployment labels"),delete:async r=>t().request(m.DEPLOYMENT(encodeURIComponent(r)),{method:"DELETE"},"Delete deployment")}}function Pe(e){let{getApi:t}=e;return{set:async(n,r={})=>{let i=w(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}${Q(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 be(e){let{getApi:t}=e;return{get:async()=>t().request(m.ACCOUNT,{method:"GET"},"Get account")}}function xe(e){let{getApi:t}=e;return{create:async(n={})=>{let r=X(n.ttl),i=w(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}${Q(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&&Te(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=Ne({...n,processInput:async(r,i)=>(await this.ensureInitialized(),this.processInput(r,i))}),this.domains=Pe(n),this.account=be(n),this.tokens=xe(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}`}}};O();f();import{z as ve}from"zod";import{z as we}from"zod";var Oe={apiUrl:we.string().url().optional(),token:we.string().min(1).optional()};O();var gt=ve.object(Oe).strict(),Tt={apiUrl:x.API_URL,token:x.TOKEN};function _e(){if(N()!=="node")return{};let e={apiUrl:process.env[x.API_URL]||void 0,token:process.env[x.TOKEN]||void 0};try{return gt.parse(e)}catch(t){if(t instanceof ve.ZodError){let n=t.issues[0],r=n.path[0],i=(r&&Tt[r])??"SHIP environment configuration";throw a.config(`Invalid ${i}: ${n.message}`)}throw a.config("Invalid environment configuration")}}f();f();ne();O();oe();se();$();ae();function Yn(e,t,n,r=!0){let i=e===1?t:n;return r?`${e} ${i}`:i}le();var pe=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=_e();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(()=>(le(),ze));return i(r,n,this.platformLimits??void 0)}},xt=pe;export{fe as API_KEY,m as API_PATHS,Mt as AUTH_BASE_PATH,Ct as AccountPlan,U as ApiHttp,ce as AuthMethod,b as CALLER,W as DEFAULT_API,A as DEPLOYMENT_CONFIG_FILENAME,S as DEPLOY_FIELDS,he as DEPLOY_TOKEN,Ot as DeploymentStatus,qe as DeploymentVia,vt as DomainStatus,d as ErrorType,h as FILE_VALIDATION_STATUS,h as FileValidationStatus,L as IDEMPOTENCY_KEY_CONSTRAINTS,It as JUNK_DIRECTORIES,R as LABEL_CONSTRAINTS,Ae as LABEL_PATTERN,$t as MY_API_KEY_URL,kt as OAuthScope,_ as PASSWORD_CONSTRAINTS,Gt as PUBLIC_DEPLOYMENT_TTL_SECONDS,x as SHIP_ENV,M as SPA_CHECK_CONSTRAINTS,ye as SPA_DEFAULT_CONFIG,pe as Ship,a as ShipError,v as TTL_CONSTRAINTS,I as TokenKind,Y as UNBUILT_PROJECT_MARKERS,Ze as UNSAFE_FILENAME_CHARS,Ft as WEB_FILE_ACCEPT,Tn as __setTestEnvironment,Hn as allValidFilesReady,Ee as assertShipJsonSyntax,H as calculateMD5,et as classifyToken,be as createAccountResource,Ne as createDeploymentResource,Pe as createDomainResource,xe as createTokenResource,xt as default,Yt as deserializeLabels,zt as extractSubdomain,Me as filterJunk,K as formatFileSize,Kt as generateDeploymentUrl,Vt as generateDomainUrl,N as getENV,Dt as getValidFiles,F as hasUnbuiltMarker,me as hasUnsafeChars,de as isBlockedExtension,Bt as isCustomDomain,Ht as isDeployment,Se as isPlatformDomain,C as isShipError,_t as normalizeVia,Fe as optimizeDeployPaths,Yn as pluralize,Be as processFilesForNode,qt as serializeLabels,tt as validateApiKey,Ut as validateApiUrl,Te as validateCaller,Ue as validateDeployFile,ke as validateDeployPath,nt as validateDeployToken,re as validateFileName,Un as validateFiles,ue as validateIdempotencyKey,J as validatePassword,j as validateToken,X as validateTtl};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|