{"version":3,"sources":["../node_modules/.pnpm/@shipstatic+types@3.15.0/node_modules/@shipstatic/types/dist/index.js","../src/files.ts","../src/source.ts","../node_modules/.pnpm/fflate@0.8.3/node_modules/fflate/esm/browser.js","../src/zip.ts","../src/process.ts","../src/entries.ts","../src/useDrop.ts"],"names":["filePath","segments","optimizeDeployPaths","ignore","err","l","td","dat","_a","i","e","filterJunk","pluralize","validateFiles","useState","useRef","useMemo","useCallback","processFiles","unreadable"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * @file Shared TypeScript types, constants, and utilities for the ShipStatic platform.\n * This package is the single source of truth for all shared data structures.\n */\n// =============================================================================\n// DEPLOYMENT TYPES\n// =============================================================================\n/**\n * Deployment status constants\n */\nexport const DeploymentStatus = {\n    PENDING: 'pending',\n    SUCCESS: 'success',\n    FAILED: 'failed',\n    DELETING: 'deleting',\n};\n/**\n * Where a deployment came from — the origin-tracking vocabulary.\n *\n * A closed set with many authors. It lived in the API's config until\n * 2026-08-06, where being server-side made it unenforceable in the one\n * direction that matters — every client wrote a bare string, and a value\n * outside the set was **silently dropped** by the server, so a typo did not\n * fail anywhere. It stopped recording where deploys came from and said nothing.\n *\n * **The origin law: origin is declared by whatever we control — our code where\n * we ship code, our URL where we ship only a URL.** One rule decides every\n * member here and every future one:\n *\n * - **Where the platform ships CODE, the code declares it.** `web`, `sdk`,\n *   `cli`, `git`, `n8n`, `vsc` and `gmn` are surfaces this platform authors,\n *   so each names itself in its own source and nothing external is needed to\n *   tell them apart. A first-party WRAPPER counts as code even when it is a\n *   manifest: the GitHub Action and the Gemini extension each compose an\n *   invocation of a platform executable and relabel it through\n *   {@link SHIP_VIA_ENV}.\n *\n * **And only a surface that DEPLOYS gets a member — `@shipstatic/drop` is the\n * recorded refusal.** The widget collects and validates files and hands raw\n * `File[]` to its embedder, whose own SDK call is the deploy; drop makes no\n * upload call anywhere, so a `drp` member would be a word nothing can emit.\n * Those deploys read `sdk`, which is the truth: the embedder is a program\n * embedding the SDK directly. Mint the member the day drop grows an upload\n * arm, not before.\n * - **Where the platform ships only a URL, the URL declares it.** A\n *   marketplace listing runs somebody else's client against a bare endpoint —\n *   every one of them the same server speaking the same protocol, and\n *   indistinguishable in a request. The only thing such a listing's traffic\n *   has in common is the URL its users were handed, so the hosted MCP serves\n *   one DOOR per listing and the door's path IS the value: `gpt`, `cld`,\n *   `crs`.\n *\n * **A member names the most specific surface the platform can honestly\n * claim**, which is what makes the two FALLBACKS fallbacks rather than peers\n * of the named surfaces. `mcp` is any MCP host that was never handed a door of\n * its own; `api` is a call that reached the REST API naming nothing at all.\n * Guessing past either would be inventing attribution rather than recording\n * it, which is the one thing this vocabulary exists to prevent.\n *\n * Every member is three lowercase characters — the property that lets a\n * channel door's path and its attribution be spelled the same. The suite pins\n * both the width and the channel members by name.\n */\nexport const DeploymentVia = {\n    /** The web dashboard. */\n    WEB: 'web',\n    /** A program embedding the SDK directly. */\n    SDK: 'sdk',\n    /** The `ship` CLI. */\n    CLI: 'cli',\n    /** Any MCP host with no door of its own — the stdio server included. The family fallback. */\n    MCP: 'mcp',\n    /** The GitHub Action. */\n    GIT: 'git',\n    /** The n8n community node. */\n    N8N: 'n8n',\n    /** Channel: the ChatGPT plugin → `mcp.<domain>/gpt`. */\n    GPT: 'gpt',\n    /** The VS Code extension. */\n    VSC: 'vsc',\n    /** Channel: the Claude connectors directory listing → `mcp.<domain>/cld`. */\n    CLD: 'cld',\n    /** Channel: the Cursor marketplace listing → `mcp.<domain>/crs`. */\n    CRS: 'crs',\n    /** The Gemini CLI extension. */\n    GMN: 'gmn',\n    /**\n     * A deploy that reached the REST API naming no origin at all — the\n     * platform-wide fallback, one altitude below `mcp`'s family fallback.\n     *\n     * **The API stamps it, since 2026-08-15.** A deploy that names no origin —\n     * or names one this vocabulary does not know — is stored as `api`, so a\n     * stored `null` now means only that the row predates attribution.\n     *\n     * It was declared one wave ahead of that decision, deliberately: vocabulary\n     * must exist before a consumer can adopt it, and adding a member costs a\n     * full constellation convoy, so the word shipped first and the server\n     * adopted it with no convoy standing between the decision and the deploy.\n     */\n    API: 'api',\n};\n// =============================================================================\n// DOMAIN TYPES\n// =============================================================================\n/**\n * A domain's STANDING: the one derived word, and what it asks of the owner.\n *\n * Not a DNS state and not a lifecycle. It answers the only question a reader\n * of a domain actually has, which is \"what, if anything, do I have to do about\n * this one\":\n *\n * - `live`: it serves the linked deployment. Nothing to do. Open it.\n * - `unlinked`: DNS is verified and nothing is published there, so a visitor\n *   meets the platform's reserved page. Link a deployment.\n * - `unverified`: the required DNS records are not all in place yet, in full\n *   or in part. Configure DNS.\n * - `paused`: the plan no longer has room for it. DNS is intact and the\n *   platform has stopped serving it; nothing DNS-shaped will help.\n *\n * **Derived, with exactly one owner: `domainStatus(row)` in the platform's\n * `shared/db/domains.ts`, beside `domainMapping(row)`.** The precedence is\n * policy rather than arithmetic, and it is stated here ONCE so that no\n * consumer has to restate it:\n *\n * ```\n * paused !== null               -> 'paused'\n * verification !== 'verified'   -> 'unverified'   (DNS comes first)\n * deployment === null           -> 'unlinked'\n * otherwise                     -> 'live'\n * ```\n *\n * This constant is the PUBLISHED RECORD of that rule, not a second\n * implementation of it. A consumer reads the word off the wire and switches\n * on it; a consumer that recomputes it from `deployment` and `verification`\n * has become the fourth copy of a precedence that drifts, which is exactly\n * how an unlinked domain wore a green \"success\" dot for months.\n *\n * The raw facts are still on the row, each said once, for a reader who wants\n * one of them specifically: {@link Domain.verification}, {@link Domain.verified},\n * {@link Domain.deployment}, {@link Domain.paused}.\n *\n * Note this is a repurposing of a wire name, which the API compatibility law\n * otherwise forbids: until types 3.0.0 `status` carried the DNS enum\n * (`pending`, `partial`, `success`) with `paused` glued on at the API's\n * projection. The exception was granted deliberately on 2026-09-20, on the\n * grounds that `status` is the right name for this and a `standing` beside a\n * deprecated `status` would preserve the half-design forever. It is recorded\n * beside the law it bends and is not precedent.\n */\nexport const DomainStatus = {\n    LIVE: 'live',\n    UNLINKED: 'unlinked',\n    UNVERIFIED: 'unverified',\n    PAUSED: 'paused',\n};\n/**\n * The DNS fact: how far the platform's one verifying act has got.\n *\n * - `pending`: the site's CNAME does not point at the platform.\n * - `partial`: it does, and the rest does not. Only a `www` domain has a\n *   rest, the apex A record, which serves nothing but the redirect to `www`.\n * - `verified`: every required record does. Platform names are born here,\n *   having no records to configure.\n *\n * **The CNAME divides the three because it is the record that serves the\n * site.** `partial` says the site is served and only the redirect is missing;\n * an apex A record without the CNAME serves nothing, so it is `pending`. The\n * verifier's drift line depends on exactly that: on a domain that has verified\n * before, a move into `pending` is the site no longer being served, and it is\n * the drift the operator is told about (`cloudflare/consumer`'s\n * `verifyDnsMapping`).\n *\n * Written by the DNS verifier and at birth, and by nothing else. **It is the\n * only field that says whether DNS is verified NOW**: its sibling instant\n * {@link Domain.verified} is monotonic and answers when it last was. A reader\n * who only wants to know whether to go and fix DNS reads {@link Domain.status};\n * this field is the diagnostic underneath it, and it is the ONLY place\n * `partial` is distinguishable from `pending`. Do not fold that distinction\n * into `status`: the standing says what to do, and \"configure DNS\" is the\n * same instruction either way.\n *\n * **On the noun, decided twice (2026-09-20), with the refusals recorded here\n * because an unrecorded one gets re-proposed forever.** `records` was the\n * first choice and is refused: on this same resource it would be a state word\n * on {@link Domain} and an array of DNS records on `DomainRecordsResponse`,\n * and the audience reading both schemas is largely agents. `dns` is refused\n * because it is taken twice over, by the provider lookup on\n * `GET /domains/:domain/dns` and by the column of that name. `verification`\n * is the platform's own family noun, shared by the `verify_dns` job, the\n * `POST /domains/:domain/verify` route, the {@link Domain.verified} instant\n * and the {@link Domain.verifications} count, so the three read as one act.\n * Its near-twin with `verifications` survives only in prose: in code the\n * compiler separates a string from a number.\n */\nexport const DomainVerification = {\n    PENDING: 'pending',\n    PARTIAL: 'partial',\n    VERIFIED: 'verified',\n};\n/**\n * The anchor of the troubleshooting section on a domain's setup instructions\n * page, so a link can open the page there: `${share.url}#troubleshooting`.\n *\n * The API's instructions template gives the section this id and the console's\n * connect page links to it: two repos, one spelling, which is why it lives\n * here. The section is written for the domain's own DNS provider, which is why\n * the console sends a stuck reader to it rather than to the general docs. If\n * the spellings ever diverged, nothing would fail: the link would open the page\n * at its top and nobody would be told, the silent-drift class this\n * constitution exists to delete.\n */\nexport const SETUP_TROUBLESHOOTING_ANCHOR = 'troubleshooting';\n/**\n * The envelope an `Idempotency-Key` must fit, and how long a replay lasts.\n *\n * Format lives here rather than on the server alone by the format-vs-policy\n * rule: a client can decide offline whether a key is well-formed, and the\n * API would reject the same value the same way.\n */\nexport const IDEMPOTENCY_KEY_CONSTRAINTS = {\n    /**\n     * HTTP header name. Here for the same reason {@link CALLER.HEADER} is: a\n     * wire header has two ends, and the package that owns the value's format\n     * is the only place both ends can read its name from.\n     */\n    HEADER: 'Idempotency-Key',\n    MAX_LENGTH: 256,\n    /** How long a stored 201 stays replayable. */\n    WINDOW_SECONDS: 24 * 60 * 60,\n};\n/**\n * The most one deploy request may carry, and the framing a client counts\n * toward it. A deployment larger than one request arrives in several: a\n * declaration with its {@link DEPLOY_FIELDS.MANIFEST}, then\n * {@link API_PATHS.DEPLOYMENT_FILES} for the rest.\n *\n * Framing, not plan policy, which is why it is static rather than delivered\n * by `/limits`: a client splitting at a smaller number is always correct.\n *\n * **`MAX_BYTES` is a one-way door.** This package is bundled into every\n * published client, so an installed client keeps its cap forever. Raising it\n * is free (an older client splits smaller, which is always valid); lowering\n * it turns every installed client's largest request into a refusal.\n *\n * 64 MiB because it holds the largest file any plan allows (50 MiB) with its\n * framing, keeps a request inside the API's memory, finishes within the\n * SDK's request timeout at 2.5 Mbit/s, and sits under the edge's 100 MiB\n * request limit. Measured on the development environment at the boundary\n * (2026-10-18), a request of exactly 64 MiB, one 50 MiB file and 14 MiB of\n * others, stored in under half a second of CPU, sent with or without a\n * `Content-Length`, alone or two at once. What a request costs when its\n * files are rewritten is the API's to bound, and it does so per file.\n */\nexport const DEPLOY_REQUEST_CONSTRAINTS = {\n    /** The most one deploy request may carry, as `Content-Length` counts it. */\n    MAX_BYTES: 64 * 1024 * 1024,\n    /**\n     * The most multipart framing one part adds beyond its bytes and its name,\n     * and the body's closing delimiter at most the same. A ceiling by the\n     * multipart standard (a boundary is at most 70 characters), not a\n     * measurement.\n     */\n    PART_OVERHEAD: 256,\n};\n/**\n * Normalize a `via` value from any transport — trimmed, lowercased, and a\n * member of {@link DeploymentVia}, or `undefined`.\n *\n * A format rule by this package's own test: a client can decide offline\n * whether a value is well-formed, and the API reaches the same verdict on the\n * same input. It lived server-side until 2026-08-06, which meant clients could\n * only learn their label was unusable by noticing analytics had gone quiet.\n *\n * **Not knowing your `via` is not an error** — an unrecognized value yields\n * `undefined` rather than throwing, because origin tracking is telemetry and a\n * deploy must never fail over it. A caller that has an honest default should\n * prefer it (`normalizeVia(process.env.SHIP_VIA) ?? DeploymentVia.CLI`): the\n * deploy really did come from the CLI, so recording that beats recording\n * nothing.\n */\nexport function normalizeVia(value) {\n    if (!value || typeof value !== 'string')\n        return undefined;\n    const via = value.trim().toLowerCase();\n    return Object.values(DeploymentVia).includes(via)\n        ? via\n        : undefined;\n}\n/**\n * Validate an idempotency key, returning the trimmed value or `undefined`\n * when none was supplied. Throws {@link ShipError.validation} when the value\n * cannot be sent — the same verdict the API would reach, reached earlier.\n */\nexport function validateIdempotencyKey(value) {\n    if (value === undefined || value === null)\n        return undefined;\n    if (typeof value !== 'string') {\n        throw ShipError.validation('Idempotency key must be a string.');\n    }\n    const key = value.trim();\n    if (!key) {\n        throw ShipError.validation('Idempotency key must not be empty.');\n    }\n    if (key.length > IDEMPOTENCY_KEY_CONSTRAINTS.MAX_LENGTH) {\n        throw ShipError.validation(`Idempotency key must be at most ${IDEMPOTENCY_KEY_CONSTRAINTS.MAX_LENGTH} characters.`);\n    }\n    return key;\n}\n// =============================================================================\n// ACCOUNT TYPES\n// =============================================================================\n/**\n * Every plan an account can hold — the platform's whole plan vocabulary, in\n * one place, and nothing about what a plan is WORTH.\n *\n * A plan is a TIER and nothing else. Whether an account may act is a separate\n * fact (`Account.suspended`; deletion ends the session outright), so an\n * account keeps its tier through suspension and into deletion.\n *\n * - **Free** — `free`.\n * - **Billed** — `pro`, `team`. The plans a customer buys; the only plans\n *   Stripe knows about, and the only ones the platform never sets by hand —\n *   each is derived from the Stripe Subscription, which names its plan on the\n *   Price it is on. They form a ladder: a dearer tier is a superset of the one\n *   below it, and the API says which is next in {@link Account.upgrade}.\n * - **Granted** — `scale`, `sponsored`. Paid plans the operator confers by\n *   hand, never reached through Checkout: no Stripe subscription and no\n *   Stripe object behind them. These and `free` are the only plans an\n *   operator can set; a billed plan is only ever Stripe's to confer.\n *\n * The numbers each plan confers — caps, sizes — are POLICY and are delivered\n * by the API (`GET /plans`, `GET /account`, `GET /limits`), never published\n * here: a price or a cap in a published package is pinned to whatever version\n * a client installed (`CLAUDE.md`, \"Validation: format vs policy\").\n */\nexport const AccountPlan = {\n    FREE: 'free',\n    PRO: 'pro',\n    TEAM: 'team',\n    SCALE: 'scale',\n    SPONSORED: 'sponsored',\n};\n/** The member places an account has taken: its members, and its pending invitations. */\nexport function placesTaken(usage) {\n    return usage.members + usage.invitations;\n}\n/**\n * The kind each count of {@link AccountUsage} names, as a person reads it:\n * one and many. The one vocabulary every surface that says a count uses, the\n * api's cap refusals and the console's room notes alike, so \"custom domain\"\n * is one word wherever it is met. A person reads \"ShipStatic domain\" where\n * the code says platform domain; the code's word never reaches them.\n */\nexport const USAGE_KIND = {\n    deployments: { one: 'deployment', many: 'deployments' },\n    platformDomains: { one: 'ShipStatic domain', many: 'ShipStatic domains' },\n    customDomains: { one: 'custom domain', many: 'custom domains' },\n    members: { one: 'member', many: 'members' },\n    invitations: { one: 'invitation', many: 'invitations' },\n};\n/**\n * What an account holds beyond a set of caps, per kind, only the kinds that\n * are over: what a move down a tier must shed before it is booked, and what\n * the console notes on a cheaper card.\n *\n * Member places are read against `caps.members`: the places over the cap are\n * counted once ({@link placesTaken} less the cap), members are named first,\n * because a member over the cap has to go whatever else the account holds,\n * and what is over after them is the invitations to cancel. So two members\n * and one invitation against a cap of one is one member and one invitation,\n * and five members against the same cap is four members and no invitation.\n * The two domain kinds are read against their own caps. Deployments are not\n * read at all: nothing pauses them, and above their cap they only block\n * creation (see {@link Caps}).\n */\nexport function excessOver(usage, caps) {\n    const places = Math.max(0, placesTaken(usage) - caps.members);\n    const members = Math.max(0, usage.members - caps.members);\n    const over = {\n        members,\n        invitations: places - members,\n        customDomains: usage.customDomains - caps.customDomains,\n        platformDomains: usage.platformDomains - caps.platformDomains,\n    };\n    return Object.fromEntries(Object.entries(over).filter(([, count]) => count > 0));\n}\n/**\n * Counts of kinds in words, people first: \"4 members and 2 custom domains\",\n * or nothing. The order is {@link USAGE_KIND}'s minus the two kinds a count never\n * names here, deployments and invitations, which have their own sentence\n * ({@link fitPhrase}).\n */\nexport function countPhrase(excess) {\n    return listOf(['members', 'customDomains', 'platformDomains']\n        .filter((kind) => (excess[kind] ?? 0) > 0)\n        .map((kind) => counted(kind, excess[kind] ?? 0)));\n}\n/**\n * What to do before an account fits a set of caps, in words: \"remove 1\n * member and cancel 1 invitation\", \"remove 2 custom domains\", \"cancel 2\n * invitations\", or nothing when it fits. Two verbs, because a member place is\n * freed two ways: a member is removed, a pending invitation is cancelled. The\n * api's change door and the console's room notes say this one phrase, so a\n * refusal and the note that preceded it cannot differ.\n */\nexport function fitPhrase(excess) {\n    const remove = countPhrase(excess);\n    const invitations = excess.invitations ?? 0;\n    return listOf([\n        ...(remove ? [`remove ${remove}`] : []),\n        ...(invitations > 0 ? [`cancel ${counted('invitations', invitations)}`] : []),\n    ]);\n}\n/** \"4 members\", \"1 custom domain\". */\nconst counted = (kind, count) => `${count} ${count === 1 ? USAGE_KIND[kind].one : USAGE_KIND[kind].many}`;\n/** \"a\", \"a and b\", \"a, b and c\". */\nconst listOf = (parts) => parts.length > 1\n    ? `${parts.slice(0, -1).join(', ')} and ${parts[parts.length - 1]}`\n    : (parts[0] ?? '');\n/**\n * The word a refusal about the account carries in `details.account`, so a\n * client can tell the two apart without reading the sentence:\n *\n * - `paused`: a 403. The person is a member, and the account holds more\n *   members than its plan allows (see {@link AccountAccess}).\n * - `unknown`: a 404. The account the request names ({@link ACCOUNT_HEADER})\n *   is one the person is not a member of, or one that does not exist; the\n *   two are indistinguishable by design. A tab whose person was removed from\n *   the account meets it on its next request.\n */\nexport const AccountRefusal = {\n    PAUSED: 'paused',\n    UNKNOWN: 'unknown',\n};\n// =============================================================================\n// PERSON NAME\n// =============================================================================\n/**\n * The name a person is ADDRESSED by: their name, else their address. A\n * person always has an email and only sometimes a name (a magic-link signup\n * has none), so every surface that addresses one needs the same fallback,\n * and it lives here because two independent holders applied it, the API in\n * its letters and pulses and the console in its labels, with nothing but\n * their docblocks holding the copies together. The console cannot avoid\n * deriving it: a roster's rows come from the identity provider's own member\n * list, not from this wire.\n *\n * Coalesced with `||` rather than `??` deliberately: a provider that hands\n * back an empty or whitespace-only name is a name nobody can be called by.\n *\n * This is the ADDRESSING register. A surface that STATES the name as a fact\n * (an operator table, a CLI printout, a machine payload) shows it as stored\n * and marks absence its own way, and does not call this.\n */\nexport function personName(person) {\n    return person.name?.trim() || person.email;\n}\n/**\n * The short form, where the room is narrow: the first word of the name, else\n * the address. The whole address rather than its local part, since a\n * truncated address still reads as an address while a bare local part reads\n * as a username the platform does not have. The sidebar, a greeting, and the\n * name an account is born with all read this.\n */\nexport function personShortName(person) {\n    return person.name?.trim().split(' ')[0] || person.email;\n}\n// =============================================================================\n// WIRE SURFACE\n// =============================================================================\n/**\n * Every path the public API answers on, declared once.\n *\n * The URL surface was written out in four places — the API's mounts, the\n * SDK's client, the dashboard's client, and the post-deploy smoke — so a\n * rename meant finding all four. The first three now read this table.\n *\n * The smoke (`cloudflare/api/smoke.mjs`) deliberately still spells its own:\n * five of its nine paths are `/admin/*`, which this table excludes by\n * design, and splitting one list between a registry and literals reads worse\n * than keeping it uniform.\n *\n * **What this guarantees, exactly.** Collection paths are mounted from here,\n * so producer and consumer cannot diverge. Item paths are declared here and\n * consumed by clients, but the API spells them relative to their mount\n * (`/:deployment/config`), so the table does not *generate* them — it is\n * held to them by `api/tests/architecture/api-paths.test.ts`, which fails if\n * any entry names a path no route answers. Some entries have no client yet\n * (`DEPLOYMENT_CONFIG`, `DOMAIN_PROPAGATION` — endpoints the SDK\n * deliberately does not reach); the fence is what keeps those honest rather\n * than merely asserted.\n *\n * **The operator surface is deliberately absent.** `/admin/*` paths belong\n * to `web/my`, for the same reason its row types do: this package is\n * published, and the operator surface is not public (see `CLAUDE.md`, \"Admin\n * types\"). A path here is a promise to every npm consumer; `/admin` is a\n * promise to one dashboard.\n *\n * Item paths are functions rather than templates so the key is interpolated\n * in one place, encoded the same way by every caller.\n */\nexport const API_PATHS = {\n    DEPLOYMENTS: '/deployments',\n    DEPLOYMENT: (deployment) => `/deployments/${deployment}`,\n    DEPLOYMENT_CONFIG: (deployment) => `/deployments/${deployment}/config`,\n    /** Fills a declared deployment with more of its files. */\n    DEPLOYMENT_FILES: (deployment) => `/deployments/${deployment}/files`,\n    DOMAINS: '/domains',\n    DOMAIN: (domain) => `/domains/${domain}`,\n    DOMAIN_VERIFY: (domain) => `/domains/${domain}/verify`,\n    DOMAIN_DNS: (domain) => `/domains/${domain}/dns`,\n    DOMAIN_RECORDS: (domain) => `/domains/${domain}/records`,\n    DOMAIN_SHARE: (domain) => `/domains/${domain}/share`,\n    DOMAIN_PROPAGATION: (domain) => `/domains/${domain}/propagation`,\n    DOMAINS_VALIDATE: '/domains/validate',\n    TOKENS: '/tokens',\n    TOKEN: (token) => `/tokens/${token}`,\n    ACCOUNT: '/account',\n    ACCOUNT_KEY: '/account/key',\n    ACCOUNT_CLAIM: '/account/claim',\n    ACTIVITIES: '/activities',\n    LABELS: '/labels',\n    LIMITS: '/limits',\n    PLANS: '/plans',\n    PING: '/ping',\n    SETUP: '/setup',\n    /**\n     * The single-page question, asked without deploying. A deploy that sends\n     * {@link DEPLOY_FIELDS.SPA} `true` is asked it at its declaration, so\n     * a client never needs this path to get the routing config: it answers the\n     * clients that predate the field, which ask here and write the config\n     * themselves.\n     */\n    SPA_CHECK: '/spa-check',\n    UPLOAD: '/upload',\n};\n/**\n * The deploy request's multipart field names: the other half of the wire\n * surface beside {@link API_PATHS}. These are the names the API reads from a\n * multipart body on `POST /deployments` and the first-party `/upload`.\n *\n * Declared once because the body has three independent WRITERS — the SDK's\n * Node and browser body builders, and the n8n community node's hand-rolled\n * client (which cannot import this under n8n Cloud's zero-dependency rule,\n * and fences its restated copy instead) — and until this export every writer\n * restated the strings the API parses, with nothing comparing them.\n *\n * `FILES` carries one entry per file (the API reads it with `getAll`); every\n * other field is single. Flags are serialized as the literal string\n * `'true'`; the `@internal` ones belong to first-party surfaces only.\n */\nexport const DEPLOY_FIELDS = {\n    /** One entry per file — read with `getAll`. */\n    FILES: 'files[]',\n    /**\n     * JSON array of {@link ManifestEntry}, one per file of the deployment: its\n     * declaration. Optional; a request without one is the whole deployment.\n     */\n    MANIFEST: 'manifest',\n    /** JSON array of label strings. */\n    LABELS: 'labels',\n    /** The deploying surface's {@link DeploymentVia} member. */\n    VIA: 'via',\n    /** Plaintext password — the API hashes it server-side. */\n    PASSWORD: 'password',\n    /**\n     * Requested lifetime in SECONDS — a duration, never an instant. The API\n     * computes and stores the expiry, so the wire carries no client clock.\n     * See {@link validateTtl}.\n     */\n    TTL: 'ttl',\n    /** @internal Server-processing flag — first-party `/upload` only. */\n    BUILD: 'build',\n    /** @internal Server-processing flag — first-party `/upload` only. */\n    PRERENDER: 'prerender',\n    /**\n     * Whether the platform asks the single-page question of the deployment's\n     * files: `true` asks, and `false` or absence does not, so a request that\n     * names nothing is never given a config it did not ask for. Asked, when the\n     * root `index.html` is an empty application shell and no `ship.json` is\n     * shipped, the platform adds the routing config that serves every path from\n     * `index.html`. The question is asked of the `index.html` the asking request\n     * carries. A client sends `true` unless\n     * {@link DeploymentUploadOptions.spaDetect} is `false`: the option and the\n     * field are two names for two layers. The name and its `true` are the ones\n     * production's console has always sent; the field is read on both endpoints\n     * and by a deploy split across several requests.\n     */\n    SPA: 'spa',\n    /**\n     * @internal The build settings, first-party `/upload` only and meaningful\n     * only with `BUILD`: the command to run instead of the manifest's build\n     * script, and the folder the site lands in. See {@link BUILD_SETTINGS}.\n     */\n    BUILD_COMMAND: 'buildCommand',\n    /** @internal See {@link DEPLOY_FIELDS.BUILD_COMMAND}. */\n    OUTPUT_DIR: 'outputDir',\n    /** @internal reCAPTCHA proof — `web/www`'s public uploader only. */\n    CAPTCHA: 'captcha',\n};\n/**\n * The JSON deploy body's file grammar: the OTHER body both deploy doors\n * accept, beside the multipart one {@link DEPLOY_FIELDS} names. A JSON caller\n * sends `{ files: [{ path, content, encoding? }] }`, and this is the whole\n * of what one entry may say: three field names, two encodings, one default.\n *\n * Declared once because the grammar has three independent holders that the\n * wire forces to restate it: the API's zod schema (the original), the hosted\n * MCP's tool input, and the n8n community node, which cannot import this\n * under n8n Cloud's zero-dependency rule and fences its copy against this\n * object instead. Each had its own literal table until 2.24.0; the last two\n * types convoys walked without minting the owner, which is exactly the drift\n * the No-Fourth-Category Law's deferral clause names.\n *\n * `content` is the file's bytes as text: raw for `utf-8` (the default, and\n * the right choice for HTML, CSS, JS, JSON and SVG), base64 for binary.\n */\nexport const DEPLOY_FILE_GRAMMAR = {\n    /** Relative path within the site, no leading slash. */\n    PATH: 'path',\n    /** The file's bytes, as text in the entry's encoding. */\n    CONTENT: 'content',\n    /** Optional; one of {@link DEPLOY_FILE_GRAMMAR.ENCODINGS}. */\n    ENCODING: 'encoding',\n    /** What an entry that names no encoding means. */\n    DEFAULT_ENCODING: 'utf-8',\n    /** The closed set. `utf-8` is raw text; `base64` is for binary only. */\n    ENCODINGS: ['utf-8', 'base64'],\n};\n// =============================================================================\n// ERROR SYSTEM\n// =============================================================================\n/**\n * All possible error types in the ShipStatic platform.\n *\n * Developer-friendly key names map to stable wire-format string values.\n * Both the value and the type are exported under the same name so callers\n * can use `ErrorType.Validation` (value comparison) and `: ErrorType` (type\n * annotation) without ceremony — matching the pattern other status objects\n * (`DeploymentStatus`, `DomainStatus`, `AccountPlan`, `AuthMethod`) follow.\n */\nexport const ErrorType = {\n    /**\n     * Validation failed. Input shape is wrong.\n     *\n     * Carries 400 when an API judged it — including a client-side pre-check of a\n     * rule the server enforces too, which keeps the error identical wherever it\n     * was caught. **Statusless** when a client rejects something no API judges,\n     * such as a CLI's own command grammar: `status` is documented \"(API\n     * contexts)\" on `ErrorResponse`, so there is none to report.\n     */\n    Validation: 'validation_failed',\n    /** Resource not found (404). */\n    NotFound: 'not_found',\n    /** Authenticated but not allowed (403). User lacks permission for this action. */\n    Forbidden: 'forbidden',\n    /** Rate limit exceeded (429). */\n    RateLimit: 'rate_limit_exceeded',\n    /** Authentication required or failed (401). Missing/invalid credentials. */\n    Authentication: 'authentication_failed',\n    /** Business rule violation. Catch-all for 4xx state-rule errors that aren't more specific. */\n    Business: 'business_logic_error',\n    /** API server error (500). Generic server-side fault. */\n    Api: 'internal_server_error',\n    /**\n     * The platform is closed for maintenance (503). A deliberate operator\n     * state, not a fault — nothing errored; the API is refusing work on\n     * purpose, and deployed sites keep serving throughout.\n     *\n     * Distinct from `Api` at 503, which the platform already uses for a\n     * dependency that failed. A consumer has to tell\n     * \"we closed the door\" from \"something broke\": the two get opposite words\n     * and opposite retry behaviour.\n     */\n    Maintenance: 'maintenance',\n    /**\n     * The project could not be built as submitted (422). The platform ran the\n     * caller's own instructions, the dependency install and then the build\n     * script, and they failed. So the verdict is the caller's: deterministic,\n     * not worth a retry, and answered with the evidence. `details` is a\n     * `BuildFailureDetails`, and the message is the one sentence the builder\n     * authored for the person who will fix the project.\n     *\n     * Distinct from `Api` at 500, which is what the platform answers when it\n     * could not RUN the build at all (the sandbox failed to start, a host\n     * fault). A consumer has to tell \"your project cannot be built\" from \"we\n     * could not build it\": the two get opposite words, opposite retry\n     * behaviour, and only the second pages an operator.\n     */\n    Build: 'build_failed',\n    /** Network/connection error. Client-side only — set by HTTP clients on fetch failure; never produced server-side. */\n    Network: 'network_error',\n    /**\n     * A deadline expired before the exchange completed. Client-side only — set\n     * by HTTP clients when a timeout signal fires; never produced server-side.\n     *\n     * A member of the NETWORK category rather than a sibling of it:\n     * `isNetworkError()` answers \"nothing was exchanged\", which is true of a\n     * deadline exactly as it is of a refused connection, so every consumer that\n     * retries, declines to report, or declines to relay a wire message on that\n     * category is already right about a timeout. The distinct TYPE exists for\n     * the one decision the category cannot make — what to SAY. \"Check your\n     * internet connection\" is the wrong sentence for a five-minute deploy\n     * ceiling, and a surface can only tell the two apart by type.\n     *\n     * The same relationship every comparable SDK ships:\n     * `APIConnectionTimeoutError extends APIConnectionError`.\n     */\n    Timeout: 'timeout_error',\n    /** Operation was cancelled. Client-side only — set on `AbortSignal` abort; never produced server-side. */\n    Cancelled: 'operation_cancelled',\n    /** File operation error. Client-side only — set by SDK during local file processing; never produced server-side. */\n    File: 'file_error',\n    /** Configuration error. Client-side only — set by SDK during config parsing/validation; never produced server-side. */\n    Config: 'config_error',\n};\n/**\n * Error types that originate exclusively on the client (HTTP clients, SDK\n * file processing, local config parsing). These never appear on the wire\n * from the server, so `fromHttpResponse` will not trust them even if a\n * misbehaving server claims one in `body.error`.\n */\nconst CLIENT_ONLY_ERROR_TYPES = new Set([\n    ErrorType.Network,\n    ErrorType.Timeout,\n    ErrorType.Cancelled,\n    ErrorType.File,\n    ErrorType.Config,\n]);\n/**\n * Categorizes error types for the `isClientError` / `isNetworkError` /\n * `isAuthError` helpers. Each `Set` is typed against the wider `ErrorType`\n * union so `.has(error.type)` accepts any value from the union.\n */\nconst ERROR_CATEGORIES = {\n    /**\n     * Client-attributable types. Exhaustive over the 4xx-carrying types, and\n     * over the statusless ones too — those are raised locally and have no\n     * status for `isClientError`'s second arm to read, so omitting one makes it\n     * read as a server fault. The rule is the membership test: every type in\n     * `CLIENT_ONLY_ERROR_TYPES` except the two `isNetworkError` owns belongs\n     * here.\n     *\n     * `Cancelled` was missing until 2026-07-29, which is exactly that failure:\n     * a caller who aborted their own deploy was told \"server error: please try\n     * again\" — the CLI's fallback for everything this set does not claim.\n     *\n     * `Timeout` is deliberately NOT here, and it is the sharper case, because\n     * it is the one client-only type that is not the client's fault: the\n     * caller set a ceiling, but what exhausted it was the network or the\n     * server. Reading it as client-attributable would say the caller erred,\n     * and it would silently disarm every consumer whose retry predicate\n     * declines `isClientError()` — a deadline is precisely the failure worth\n     * a second attempt.\n     */\n    client: new Set([\n        ErrorType.Build,\n        ErrorType.Business,\n        ErrorType.Cancelled,\n        ErrorType.Config,\n        ErrorType.File,\n        ErrorType.Forbidden,\n        ErrorType.NotFound,\n        ErrorType.RateLimit,\n        ErrorType.Validation,\n    ]),\n    /**\n     * The exchange never happened. Two types, one category: a refused\n     * connection and an expired deadline differ in what a surface should SAY\n     * and in nothing else a consumer decides on — both are retryable, neither\n     * carries a wire message to relay, neither is worth reporting as an\n     * incident. See `ErrorType.Timeout` for why the type is distinct anyway.\n     */\n    network: new Set([ErrorType.Network, ErrorType.Timeout]),\n    auth: new Set([ErrorType.Authentication]),\n};\n/**\n * Error types the server can legitimately produce on the wire. Used by\n * `ShipError.fromHttpResponse` to validate the body's `error` field before\n * trusting it as `ShipError.type`. Derived by exclusion from\n * `CLIENT_ONLY_ERROR_TYPES` so adding a new server-producible type to\n * `ErrorType` is automatically picked up.\n */\nconst SERVER_PRODUCIBLE_ERROR_TYPES = new Set(Object.values(ErrorType).filter((t) => !CLIENT_ONLY_ERROR_TYPES.has(t)));\n/**\n * Ceiling on a message adopted from a **non-JSON** error body — a foreign\n * responder's, never this platform's. Generous for the plain-text one-liners\n * intermediaries actually send (`error code: 1015`), far below a document.\n * Our own messages are never measured against it: a JSON body is the API's\n * contract, and truncating a long validation message would be the bug.\n */\nconst MAX_FOREIGN_MESSAGE_LENGTH = 200;\n/**\n * Did the runtime say the exchange never completed?\n *\n * Clients branch on the TYPE, never on message strings, so a misclassified\n * transport failure is a lie every consumer inherits — and the one that costs\n * most: `Api` claims a server answered when nothing was exchanged, and a\n * retrying caller will not retry it.\n *\n * **Every row below is a transcript, not a belief.** Captured 2026-08-12\n * against real runtimes — Node and Bun by direct run, the three engines by a\n * one-off playwright probe, workerd through miniflare. The capture scripts are\n * in `tests/errors.test.ts`, \"runtime failure shapes\".\n *\n * | runtime          | connection refused / DNS failure                     | malformed URL                                    |\n * |------------------|------------------------------------------------------|--------------------------------------------------|\n * | Node 22 / undici | `TypeError: fetch failed`                             | `TypeError: Failed to parse URL from …`          |\n * | Bun 1.3.14       | `Error` `code:'ConnectionRefused'`                    | `TypeError` `code:'ERR_INVALID_URL'`             |\n * | Chromium 151     | `TypeError: Failed to fetch`                          | `TypeError: …Failed to parse URL from …`         |\n * | Firefox 153      | `TypeError: NetworkError when attempting to fetch …`  | `TypeError: … is not a valid URL.`               |\n * | WebKit 26.5      | `TypeError: Load failed`                              | `TypeError: URL is not valid or contains user …` |\n * | workerd          | `Error: Network connection lost.` (DNS: `internal error; reference = …`) | `TypeError: Invalid URL: …`   |\n *\n * Reading that table gives the rule, and it is the INVERSE of the obvious one.\n * The transport class is unbounded — every OS, TLS and DNS failure any engine\n * will ever name — while the class fetch raises for its own ARGUMENTS is\n * small, and every runtime names the URL when it complains about one. So the\n * bounded side is the one worth testing, and the residual risk points the safe\n * way: an unrecognised sentence lands on `Network`, which says only that\n * nothing was exchanged.\n *\n * That inversion is what fixes **WebKit**, whose `Load failed` carries no code\n * and no \"fetch\", and which every browser-SDK and `@shipstatic/drop` user on\n * Safari was hitting as `Api`. It also makes the six runtimes AGREE about a\n * malformed URL, which they did not before: the previous rule tested the\n * message for \"fetch\", and Chromium's and Firefox's URL complaints both\n * contain it, so the same mistake was `Network` on three engines and `Api` on\n * three.\n *\n * **workerd is the recorded gap.** It rejects with a plain `Error`, no code\n * and no shared sentence — and its two failure modes produce two unrelated\n * ones — so nothing here can classify it and it lands on `Api`. Left alone\n * rather than patched with a dialect string: the one consumer running ship in\n * that runtime (`cloudflare/mcp`) reaches the API through a service BINDING,\n * which is in-process and does not produce transport rejections at all.\n *\n * **The `TokenProvider` case stopped being a trade when clients gained\n * retries.** A caller's provider that throws a coded error is typed `Network`\n * here, which was recorded as \"both are wrong for it; `Network` is the cheaper\n * wrong\" — written when the classification decided only what a surface would\n * SAY. It now also decides whether the call is retried, and that turns the\n * cheaper wrong into the right answer: a `TokenProvider` is where minting and\n * refresh live, so the common one is an OAuth refresh over the network, and a\n * transient failure there is precisely what another attempt repairs.\n *\n * The residual cost is a deterministic provider fault — a genuinely missing\n * keychain entry — invoking the provider three times over a few hundred\n * milliseconds before failing with the same error. No request leaves the\n * process on any of them. That is the cheap direction of a bet whose other\n * side is a refused deploy, and suppressing it would need a way to mark\n * credential faults non-retryable: machinery with one holder, refused by the\n * estate's stopping rule. Provider failures that carry no code are `Api` and\n * are not retried at all, and a provider yielding nothing is `Authentication`\n * by the fail-closed invariant, which is likewise terminal.\n */\nfunction isTransportFailure(cause) {\n    const code = cause.code;\n    // Bun is the one runtime that puts a CODE on an argument error, so it is\n    // excluded before the code arm can claim it.\n    if (code === 'ERR_INVALID_URL')\n        return false;\n    // A string `code` is a runtime naming a transport-level failure. An\n    // allowlist of codes was written first and rejected — the TLS row alone\n    // would mean enumerating BoringSSL's certificate table, and a code nobody\n    // guessed is precisely the bug this closes. A `DOMException`'s code is a\n    // NUMBER, so aborts and timeouts never reach here.\n    if (typeof code === 'string')\n        return true;\n    // WHATWG has fetch reject with a TypeError for BOTH halves — network error\n    // and argument error — so among TypeErrors the URL is the discriminator.\n    if (cause instanceof TypeError)\n        return !/\\burl\\b/i.test(cause.message);\n    // Anything else — an ordinary JS fault, or workerd — is not evidence.\n    return false;\n}\n/**\n * Simple unified error class for both API and SDK\n */\nexport class ShipError extends Error {\n    type;\n    status;\n    details;\n    constructor(type, message, status, details) {\n        super(message);\n        this.type = type;\n        this.status = status;\n        this.details = details;\n        this.name = 'ShipError';\n    }\n    /** Convert to wire format */\n    toResponse() {\n        // Strip authentication details when they carry an `internal` telemetry\n        // tag (see `ShipError.authentication` JSDoc) — these are server-side\n        // diagnostics like 'session_invalid' that must not leak to clients.\n        const authDetails = this.details;\n        const details = this.type === ErrorType.Authentication && authDetails?.internal ? undefined : this.details;\n        return {\n            error: this.type,\n            message: this.message,\n            status: this.status,\n            details,\n        };\n    }\n    /**\n     * Construct a `ShipError` from an HTTP error response.\n     *\n     * Best-effort body parse for `{ message, error?, details? }`. Message\n     * resolution: `body.message` → `body.error` → `\"<operationName> failed with\n     * status <N>\"`.\n     *\n     * Type resolution: trusts `body.error` when it's a known server-producible\n     * `ErrorType` (preserves the wire's intent — server's\n     * `ShipError.validation(...)` round-trips back to `ErrorType.Validation`\n     * on the client). Falls back to status-derived (401 → Authentication,\n     * 403 → Forbidden, 429 → RateLimit, else → Api) for non-API responses\n     * (CDN errors, intermediaries) or malformed bodies. Client-only types\n     * (`Network`, `Timeout`, `Cancelled`, `File`, `Config`) are filtered out of the\n     * trusted set — a misbehaving server claiming one of those is ignored.\n     *\n     * `operationName` (e.g. `\"Get account\"`) is used to compose the fallback\n     * message. Defaults to `\"Request\"`. Same convention as `fromFetchError`.\n     *\n     * Async because it reads the response body. Returns rather than throws so\n     * callers can compose; most will `throw await ShipError.fromHttpResponse(...)`.\n     */\n    static async fromHttpResponse(response, operationName) {\n        let message;\n        let details;\n        let bodyType;\n        try {\n            const contentType = response.headers.get('content-type');\n            if (contentType?.includes('application/json')) {\n                const json = await response.json();\n                if (json && typeof json === 'object') {\n                    const obj = json;\n                    if (typeof obj.message === 'string')\n                        message = obj.message;\n                    else if (typeof obj.error === 'string')\n                        message = obj.error;\n                    details = obj.details;\n                    if (typeof obj.error === 'string' && SERVER_PRODUCIBLE_ERROR_TYPES.has(obj.error)) {\n                        bodyType = obj.error;\n                    }\n                }\n            }\n            else {\n                // A non-JSON body did not come from this platform — every API error\n                // is `ErrorResponse` JSON — so it is an intermediary's output, and\n                // the two kinds it produces need opposite treatment. A CDN's plain\n                // `error code: 1015` is the most useful thing there is to say. A\n                // proxy's HTML error page is a *document*, not a message: adopting it\n                // verbatim made a misconfigured `apiUrl` print 2,059 characters of\n                // markup as the error. Trust it only when it reads as a message.\n                const text = (await response.text()).trim();\n                if (text && !text.startsWith('<') && text.length <= MAX_FOREIGN_MESSAGE_LENGTH) {\n                    message = text;\n                }\n            }\n        }\n        catch {\n            // Body unreadable; fall through to operationName-derived message.\n        }\n        // Rate-limit (and 503) timing rides the `Retry-After` HEADER, which a\n        // body-only reader would drop. Lift it into `details` as seconds so\n        // consumers can back off from the typed error alone, without keeping the\n        // raw Response around. Body-carried fields are preserved and win.\n        const retryAfterHeader = response.headers.get('retry-after');\n        if (retryAfterHeader !== null) {\n            const value = retryAfterHeader.trim();\n            const seconds = /^\\d+$/.test(value)\n                ? Number(value)\n                : Math.ceil((Date.parse(value) - Date.now()) / 1000);\n            if (Number.isFinite(seconds) && seconds >= 0) {\n                const existing = details && typeof details === 'object' ? details : {};\n                if (existing.retryAfter === undefined) {\n                    details = { ...existing, retryAfter: seconds };\n                }\n            }\n        }\n        message = message || `${operationName || 'Request'} failed with status ${response.status}`;\n        const type = bodyType ??\n            (response.status === 401\n                ? ErrorType.Authentication\n                : response.status === 403\n                    ? ErrorType.Forbidden\n                    : response.status === 429\n                        ? ErrorType.RateLimit\n                        : ErrorType.Api);\n        return new ShipError(type, message, response.status, details);\n    }\n    /**\n     * Construct a `ShipError` from an error caught around a `fetch()` call.\n     *\n     * The mirror of `fromHttpResponse` for the *other* side of the HTTP error\n     * story — the network layer failing (offline, CORS, abort) rather than the\n     * server returning a non-OK response.\n     *\n     * Routing:\n     * - Already a `ShipError` → returned as-is (caller's intent preserved)\n     * - `AbortError` → `ShipError.cancelled(...)` — someone stopped it on purpose\n     * - `TimeoutError` → `ShipError.timeout(...)` — a deadline expired; the\n     *   message names the timeout, and the type is in the network CATEGORY\n     *   because nothing was exchanged\n     * - A transport failure → `ShipError.network(...)` — see `isTransportFailure`\n     *   for what each runtime offers as evidence\n     * - Any other `Error` → `ShipError(Api, ...)` (no HTTP status — fetch never reached the server)\n     * - Anything else (string, undefined, etc.) → `ShipError(Api, ...)`\n     *\n     * **Abort and timeout are read from `name` BEFORE any `instanceof Error`\n     * gate.** A `DOMException` satisfies that gate in every runtime measured\n     * (Node, Bun, Chromium, Firefox, WebKit, workerd — all six), but the\n     * inheritance is a comparatively recent spec change and this classification\n     * has no reason to depend on it: `name` is where the meaning lives, and\n     * reading it first costs nothing. The suite plants a non-`Error`\n     * `DOMException` shape to hold the arm, since no runtime on the table\n     * produces one.\n     *\n     * A caller's own `AbortSignal.timeout()` is the reachable source of\n     * `TimeoutError` — and the two are NOT interchangeable per runtime: WebKit\n     * reports a fired `AbortSignal.timeout()` as `AbortError`, so on Safari a\n     * deadline is indistinguishable from a cancellation and lands on\n     * `Cancelled`. Recorded rather than worked around; `Cancelled` is honest\n     * there, since the caller's signal is what stopped it.\n     *\n     * The optional `operationName` is composed into the message for context:\n     * `\"Get account was cancelled\"`, `\"Get account failed: ...\"`. Defaults to\n     * `\"Request\"` when omitted.\n     */\n    static fromFetchError(cause, operationName) {\n        if (isShipError(cause))\n            return cause;\n        const op = operationName || 'Request';\n        // Read by NAME, ahead of the Error gate — see the note above.\n        const name = cause?.name;\n        if (name === 'AbortError') {\n            return ShipError.cancelled(`${op} was cancelled`);\n        }\n        if (name === 'TimeoutError') {\n            // A deadline: not a fault, not a cancellation, and — since it has its\n            // own type — no longer merely \"network\". Nothing was exchanged, which\n            // is what keeps it in the network CATEGORY and therefore retryable; the\n            // type is what lets a surface say \"timed out\" instead of sending\n            // someone to check their Wi-Fi. The runtime's own sentence is dropped\n            // rather than relayed: \"The operation was aborted due to timeout\" is\n            // the mechanism, not the news.\n            return ShipError.timeout(`${op} timed out`, { cause });\n        }\n        if (cause instanceof Error) {\n            if (isTransportFailure(cause)) {\n                return ShipError.network(`${op} failed: ${cause.message}`, { cause });\n            }\n            return new ShipError(ErrorType.Api, `${op} failed: ${cause.message}`);\n        }\n        return new ShipError(ErrorType.Api, `${op} failed: Unknown error`);\n    }\n    // Factory methods. Uniform shape `(message, details?)` with two principled\n    // exceptions: `notFound` composes its message from (resource, id?), and\n    // `business` / `api` accept an optional status because they're the\n    // multi-status fallbacks.\n    static validation(message, details) {\n        return new ShipError(ErrorType.Validation, message, 400, details);\n    }\n    static notFound(resource, id) {\n        const message = id ? `${resource} ${id} not found` : `${resource} not found`;\n        return new ShipError(ErrorType.NotFound, message, 404);\n    }\n    static forbidden(message, details) {\n        return new ShipError(ErrorType.Forbidden, message, 403, details);\n    }\n    static rateLimit(message = 'Too many requests', details) {\n        return new ShipError(ErrorType.RateLimit, message, 429, details);\n    }\n    /**\n     * Construct an Authentication (401) error.\n     *\n     * **Telemetry pattern — `details: { internal: '<tag>' }`.** When the\n     * server creates an auth error with an `internal` key in `details`\n     * (e.g. `{ internal: 'session_invalid' }`), `toResponse()` strips the\n     * entire `details` object before serialization. This keeps the wire\n     * response a clean \"Authentication failed\" while preserving granular\n     * server-side telemetry (which strategy/check failed) for logs and tests.\n     *\n     * Use this pattern in API auth code; do not put client-visible info under\n     * `internal`. Other `details` keys round-trip normally.\n     */\n    static authentication(message = 'Authentication required', details) {\n        return new ShipError(ErrorType.Authentication, message, 401, details);\n    }\n    static business(message, status = 400, details) {\n        return new ShipError(ErrorType.Business, message, status, details);\n    }\n    static network(message, details) {\n        return new ShipError(ErrorType.Network, message, undefined, details);\n    }\n    /**\n     * A deadline expired before the exchange completed.\n     *\n     * Statusless like its four client-only siblings: no exchange completed, so\n     * there is no HTTP status to report. `isNetworkError()` is true — see\n     * `ErrorType.Timeout` for why the category is shared and the type is not.\n     */\n    static timeout(message, details) {\n        return new ShipError(ErrorType.Timeout, message, undefined, details);\n    }\n    static cancelled(message, details) {\n        return new ShipError(ErrorType.Cancelled, message, undefined, details);\n    }\n    static file(message, details) {\n        return new ShipError(ErrorType.File, message, undefined, details);\n    }\n    static config(message, details) {\n        return new ShipError(ErrorType.Config, message, undefined, details);\n    }\n    static api(message, status = 500, details) {\n        return new ShipError(ErrorType.Api, message, status, details);\n    }\n    /**\n     * The platform is closed for maintenance (503).\n     *\n     * `message` is REQUIRED and has no default here. The API is the only\n     * producer of that sentence, and a default in this file would be a second\n     * owner of one fact — see CLAUDE.md, \"The Constellation Law\" (stopping\n     * rule). It is also the first factory whose status is fixed rather than\n     * defaulted: a maintenance refusal is 503 or it is not this error\n     * (`build` is the second, on the same reasoning).\n     */\n    static maintenance(message, details) {\n        return new ShipError(ErrorType.Maintenance, message, 503, details);\n    }\n    /**\n     * The project could not be built as submitted (422).\n     *\n     * The second factory with a FIXED status, on Maintenance's reasoning: a\n     * build verdict is 422 or it is not this error. `message` is the builder's\n     * own sentence, relayed rather than rewritten, since the builder is the\n     * throw site and the only party that knows why; `details` carries the log\n     * (`BuildFailureDetails`), which is required for the same reason a verdict\n     * without evidence is an opinion.\n     */\n    static build(message, details) {\n        return new ShipError(ErrorType.Build, message, 422, details);\n    }\n    // Semantic-category guards. For specific-type checks, use\n    // `error.type === ErrorType.X` directly or the generic `isType(t)`.\n    /**\n     * The caller is at fault — by HTTP's own definition of a 4xx, or by a type\n     * that is client-attributable without ever having a status (`Config`,\n     * `File`, raised locally by the SDK).\n     *\n     * Both arms are load-bearing, because type and status are independent\n     * axes. `fromHttpResponse` trusts `body.error` only when it names a\n     * server-producible type; a non-OK response without one is status-derived,\n     * so a CDN 404 or any intermediary error arrives as `Api` — a server-fault\n     * *type* carrying a client *status*. Judging by type alone would report it\n     * as a platform failure and bury the server's own message.\n     */\n    isClientError() {\n        if (ERROR_CATEGORIES.client.has(this.type))\n            return true;\n        return this.status !== undefined && this.status >= 400 && this.status < 500;\n    }\n    isNetworkError() {\n        return ERROR_CATEGORIES.network.has(this.type);\n    }\n    isAuthError() {\n        return ERROR_CATEGORIES.auth.has(this.type);\n    }\n    isType(errorType) {\n        return this.type === errorType;\n    }\n}\n/**\n * Type guard to check if an unknown value is a ShipError.\n *\n * Uses structural checking instead of instanceof to handle module duplication\n * in bundled applications where multiple copies of the ShipError class may exist.\n *\n * @example\n * if (isShipError(error)) {\n *   console.log(error.status, error.message);\n * }\n */\nexport function isShipError(error) {\n    return (error !== null &&\n        typeof error === 'object' &&\n        'name' in error &&\n        error.name === 'ShipError' &&\n        'status' in error);\n}\n// =============================================================================\n// EXTENSION MATCHING\n// =============================================================================\n/**\n * The rule for reading a file's extension: lowercase, after the last dot of\n * the last path segment. `null` when there is no extension to read.\n *\n * A leading dot names the file rather than its type, so `.gitignore` and\n * `.htaccess` have no extension — but `.env.exe` has `exe`.\n *\n * Segment-aware on purpose: the callers pass deploy PATHS, not basenames, and\n * a naive `lastIndexOf('.')` over `dir.v1/README` reads the extension\n * `v1/README` — safe only by accident, since no entry in a real blocklist\n * contains a slash, which is the kind of correctness nobody should have to\n * re-derive.\n *\n * **Private, and the reason is the asymmetry rather than any hazard.** Nothing\n * outside this file reads it: `isBlockedExtension` is the only question anyone\n * asks, and the API's refusal names the FILE, not its extension. Exporting a\n * pure function is harmless, which is exactly the argument that talks a\n * published package into surface it has not earned — and the costs do not\n * match, since adding an export later is free under the additive law while\n * removing one is a major. So it stays private until a caller exists. Its\n * behaviour is fenced through `isBlockedExtension`, which is where it is\n * observable.\n *\n * (`WEB_FILE_EXTENSIONS` above is private for a different reason — publishing\n * it would invite a wrong question. Both are private; only one is a hazard.)\n *\n * @example\n * fileExtension('virus.exe')          // 'exe'\n * fileExtension('assets/style.CSS')   // 'css'\n * fileExtension('dir.v1/README')      // null\n * fileExtension('.gitignore')         // null\n * fileExtension('file.')              // null\n */\nfunction fileExtension(filename) {\n    const basename = filename.replace(/\\\\/g, '/').split('/').pop() ?? '';\n    const dotIndex = basename.lastIndexOf('.');\n    if (dotIndex <= 0 || dotIndex === basename.length - 1)\n        return null;\n    return basename.slice(dotIndex + 1).toLowerCase();\n}\n/**\n * Whether a file is one the platform refuses to host.\n *\n * **The list is not this package's, and that separation is the point.** What\n * counts as a blocked extension is hosting POLICY — it evolves, it is enforced\n * at one security boundary, and `virus.exe` is a perfectly well-formed\n * filename that breaks nothing about the upload→serve round-trip. So the API\n * owns the list (`cloudflare/api/src/lib/blocklist.ts`) and delivers it as\n * `PlatformLimits.blockedExtensions`; a client passes what it was given.\n *\n * What lives here is the MATCHING RULE, and it earns its place by the\n * constellation law's own test. The list's drift is loud in both directions —\n * a stale client uploads a file the API refuses by name, on the first try.\n * A second *matcher* drifts SILENTLY in the one direction that matters: a\n * client stricter than the server refuses a legal file without the server ever\n * being asked, and no error names it. Two holders, silent drift, one owner.\n *\n * The `blocked` collection is required rather than defaulted: this predicate\n * guards a security boundary in the API, and a defaulted-empty argument there\n * would block nothing while reading as though it did. Callers holding a\n * possibly-absent wire field spell the fail-open themselves.\n *\n * @example\n * isBlockedExtension('virus.exe', ['exe'])   // true\n * isBlockedExtension('virus.EXE', ['exe'])   // true — case-insensitive\n * isBlockedExtension('style.css', ['exe'])   // false\n * isBlockedExtension('README', ['exe'])      // false — no extension\n */\nexport function isBlockedExtension(filename, blocked) {\n    const ext = fileExtension(filename);\n    if (ext === null)\n        return false;\n    return Array.isArray(blocked) ? blocked.includes(ext) : blocked.has(ext);\n}\n// =============================================================================\n// PICKER ACCEPT HINT\n// =============================================================================\n/**\n * The extensions a browser file picker offers by default, grouped by role.\n *\n * Private on purpose: the only published form is `WEB_FILE_ACCEPT`, the\n * attribute value itself. A published set would invite a call site to ask it\n * whether a file is allowed — which is the one thing this list must never\n * answer. See `WEB_FILE_ACCEPT`.\n *\n * Extensionless files (`LICENSE`, most `.well-known` entries) are inexpressible\n * in `accept`, and reach a deployment by folder pick, ZIP, or drag-and-drop.\n */\nconst WEB_FILE_EXTENSIONS = [\n    // Markup & documents\n    'html',\n    'htm',\n    'xhtml',\n    'xml',\n    'txt',\n    'md',\n    'markdown',\n    'pdf',\n    'csv',\n    // Data & config\n    'json',\n    'jsonc',\n    'webmanifest',\n    'map',\n    'toml',\n    'yaml',\n    'yml',\n    'rss',\n    'atom',\n    // Styles\n    'css',\n    'scss',\n    'sass',\n    'less',\n    // Scripts & modules\n    'js',\n    'mjs',\n    'cjs',\n    'jsx',\n    'ts',\n    'tsx',\n    'wasm',\n    'vue',\n    'svelte',\n    // Images\n    'png',\n    'jpg',\n    'jpeg',\n    'gif',\n    'webp',\n    'avif',\n    'svg',\n    'ico',\n    'bmp',\n    'tif',\n    'tiff',\n    'heic',\n    'heif',\n    // Fonts\n    'woff',\n    'woff2',\n    'ttf',\n    'otf',\n    'eot',\n    // Audio\n    'mp3',\n    'wav',\n    'ogg',\n    'oga',\n    'opus',\n    'm4a',\n    'aac',\n    'flac',\n    'weba',\n    // Video\n    'mp4',\n    'webm',\n    'ogv',\n    'mov',\n    'm4v',\n    'avi',\n    // 3D models\n    'glb',\n    'gltf',\n    'usdz',\n    // Text tracks\n    'vtt',\n    'srt',\n    // Archive — a whole site in one file\n    'zip',\n];\n/**\n * The `accept` attribute value for a browser file picker offering web files.\n *\n * **This is a hint, never a rule.** The API's blocklist is the platform's gate\n * and the only thing that decides what may be hosted; this constant decides\n * what a *file dialog* shows first. The two are not two halves of one policy,\n * and this one must never be consulted to accept or reject a file.\n *\n * The distinction is structural, not stylistic. `accept` can express only an\n * allowlist, while the platform's rule is a blocklist — so this list is\n * necessarily *narrower* than what the platform hosts, and reading it as\n * authority would reject files the platform serves happily. It is also not\n * enforcement in the browser's own terms: every file dialog offers an\n * all-files escape, and **drag-and-drop ignores `accept` entirely**. The\n * dropzone and the picker must reach the same verdict on the same files, and\n * they do — because the verdict is `validateFiles`, downstream of both.\n *\n * The invariant that matters — the picker must never offer a file the platform\n * will refuse — is fenced where the authority lives, in the API's own suite\n * (`cloudflare/api/tests/lib/blocklist.test.ts`), which reads this published\n * string and holds it against the list it owns. It sat here until the\n * blocklist became the API's, and moving it was the price of that: a fence\n * belongs with whichever side can change and break it.\n */\nexport const WEB_FILE_ACCEPT = WEB_FILE_EXTENSIONS.map((ext) => `.${ext}`).join(',');\n// =============================================================================\n// FILENAME CHARACTER VALIDATION\n// =============================================================================\n/**\n * Characters that are unsafe in filenames for static hosting.\n *\n * Blocks only characters that genuinely break the upload→serve round-trip:\n * - # ? %        URL round-trip breakers (fragment, query, encoding ambiguity)\n * - \\            Path separator confusion (upload splits on backslash)\n * - < > \"        XSS vectors with zero legitimate use in filenames\n * - \\x00-\\x1f \\x7f  Control characters (header injection, display corruption)\n *\n * Everything else is allowed — browser percent-encodes, Worker decodes, R2 matches.\n */\n// biome-ignore lint/suspicious/noControlCharactersInRegex: blocking control characters is this regex's purpose\nexport const UNSAFE_FILENAME_CHARS = /[\\x00-\\x1f\\x7f#?%\\\\<>\"]/;\n/**\n * Check if a filename contains unsafe characters.\n *\n * @example\n * hasUnsafeChars('saved_resource(1).html')  // false — parentheses are safe\n * hasUnsafeChars('page[slug].js')           // false — brackets are safe\n * hasUnsafeChars('file#anchor.html')        // true  — # breaks URL resolution\n * hasUnsafeChars('file<tag>.html')          // true  — < is an XSS vector\n */\nexport function hasUnsafeChars(filename) {\n    return UNSAFE_FILENAME_CHARS.test(filename);\n}\n// =============================================================================\n// UNBUILT PROJECT MARKERS\n// =============================================================================\n/**\n * Path segment names that indicate an unbuilt project was uploaded instead of build output.\n * Used for early detection in CLI, browser, and server validation.\n */\nexport const UNBUILT_PROJECT_MARKERS = new Set([\n    'node_modules',\n    'package.json',\n]);\n/**\n * Check if a file path contains an unbuilt project marker.\n *\n * @example\n * hasUnbuiltMarker('node_modules/react/index.js')  // true\n * hasUnbuiltMarker('package.json')                  // true\n * hasUnbuiltMarker('dist/index.html')               // false\n */\nexport function hasUnbuiltMarker(filePath) {\n    const segments = filePath.replace(/\\\\/g, '/').split('/').filter(Boolean);\n    return segments.some((s) => UNBUILT_PROJECT_MARKERS.has(s));\n}\n// =============================================================================\n// DEPLOY RULES\n// =============================================================================\n/**\n * The page a deployment serves at `/`. Every deployment has one at its root:\n * ShipStatic publishes websites, and a website starts at its home page.\n * Beside {@link DEPLOYMENT_CONFIG_FILENAME}, the other file that sets a\n * deployment up.\n */\nexport const DEPLOYMENT_INDEX_FILENAME = 'index.html';\n/** Max deploy-path bytes: R2 keys cap at 1024 bytes and the deployment prefix consumes up to 22. */\nexport const MAX_PATH_BYTES = 1000;\n/**\n * A deploy path as the deployment stores it: ONE leading slash names the same\n * path, so it is dropped. Every rule and every store compares paths in this\n * form, so `index.html` and `/index.html` are one file wherever they are\n * judged. Two leading slashes are not one, so `//index.html` is left as it is\n * and {@link isDeployablePath} refuses its empty segment. That makes the\n * function idempotent: a path canonical once is canonical however many times\n * a boundary asks again, so every judge and every store sees one identity.\n */\nexport function canonicalDeployPath(path) {\n    return path.startsWith('/') && !path.startsWith('//') ? path.slice(1) : path;\n}\n/**\n * What a deployment is told when it names one path twice: two files where\n * the deployment holds one. The deploy rules say it, and so does the API's\n * intake, which refuses the repeat before it can index the files by path.\n */\nexport function namedTwice(path) {\n    return `The file ${path} appears twice.`;\n}\n/**\n * Whether a deploy path can be served as it is: within {@link MAX_PATH_BYTES},\n * with no empty segment, none over 255 characters, and none starting with a\n * dot, root-level `.well-known` excepted (RFC 8615). The router refuses to\n * serve a hidden segment, so a file at one could never be reached. Read in\n * its canonical form ({@link canonicalDeployPath}).\n */\nexport function isDeployablePath(path) {\n    const normalized = canonicalDeployPath(path);\n    if (new TextEncoder().encode(normalized).length > MAX_PATH_BYTES)\n        return false;\n    return normalized\n        .split('/')\n        .every((segment, index) => segment !== '' &&\n        segment.length <= 255 &&\n        (!segment.startsWith('.') || (segment === '.well-known' && index === 0)));\n}\n/**\n * Whether a file name can make the upload-to-serve round trip, and if not, the\n * sentence that says why, naming the file. Only what genuinely breaks it is\n * refused: characters that break a URL or open an XSS vector\n * ({@link hasUnsafeChars}), a leading or trailing space, a trailing dot, and\n * a reserved system name. A `..` segment is a segment starting with a dot,\n * which {@link isDeployablePath} refuses, so `report..final.pdf` is a name.\n */\nexport function validateFileName(filename) {\n    const refuse = (why) => ({ valid: false, reason: `File name \"${filename}\" ${why}.` });\n    if (filename.trim() === '')\n        return { valid: false, reason: 'A file has no name.' };\n    if (hasUnsafeChars(filename))\n        return refuse('contains unsafe characters');\n    if (filename.startsWith(' ') || filename.endsWith(' ')) {\n        return refuse('cannot start or end with spaces');\n    }\n    if (filename.endsWith('.'))\n        return refuse('cannot end with dots');\n    const name = filename.split('/').pop() || filename;\n    if (/^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(\\.|$)/i.test(name)) {\n        return refuse('uses a reserved system name');\n    }\n    return { valid: true };\n}\n/**\n * Whether a file sent to a deployment is published. An empty one is not: no\n * deployment stores an empty file, so it is left out rather than refused, by\n * every judge and every store alike. The rules about the deployment as a whole\n * still see it, which is how an empty `index.html` is told apart from a\n * missing one.\n */\nexport function isPublishedFile(file) {\n    return file.size > 0;\n}\n/**\n * A limit's sentence, followed by the way forward the API delivered for that\n * limit ({@link PlatformLimits.suggestions}), verbatim. The API writes it with\n * the function its own plans answer to, so a refusal ends the same way\n * wherever it is made, and no client learns what a plan is.\n */\nfunction withSuggestion(sentence, limits, key) {\n    const suggestion = limits.suggestions?.[key];\n    return suggestion ? `${sentence} ${suggestion}` : sentence;\n}\n/**\n * Every rule each file of a deployment is held to, in the order they apply:\n * a file that breaks two reports the first, because fixing it may fix the\n * other. Every sentence names its file once and is complete on its own, so\n * every surface shows it as it is.\n *\n * The API judges a deployment by these rules at its declaration, and every\n * client judges its files by them before sending a byte, so a refusal reads\n * the same wherever it is made. Read through {@link deployRefusal}, or\n * {@link firstBrokenRule} and {@link brokenSetRule} where a caller judges a\n * deployment as it walks it.\n */\nexport const FILE_RULES = [\n    {\n        name: 'name',\n        broken: ({ path }) => !validateFileName(path).valid,\n        sentence: ({ path }) => validateFileName(path).reason ?? `File name \"${path}\" is not allowed.`,\n    },\n    {\n        // The list is the platform's, delivered through `/limits`. Absent means\n        // no check here, never an empty policy: the API holds the list.\n        name: 'extension',\n        broken: ({ path }, limits) => isBlockedExtension(path, limits.blockedExtensions ?? []),\n        sentence: ({ path }) => `File \"${path}\" has an extension that is not allowed.`,\n    },\n    {\n        name: 'project',\n        broken: ({ path }) => hasUnbuiltMarker(path),\n        sentence: ({ path }) => `File \"${path}\" belongs to a project that isn't built yet. Build it, then publish the folder the build makes, like dist.`,\n    },\n    {\n        name: 'path',\n        broken: ({ path }) => !isDeployablePath(path),\n        sentence: ({ path }) => `File \"${path}\" can't be published: a folder or file name in its path starts with a dot, is empty, or is too long.`,\n    },\n    {\n        name: 'fileSize',\n        broken: ({ size }, limits) => size > limits.maxFileSize,\n        sentence: ({ path }, limits) => withSuggestion(`File \"${path}\" is too large. Maximum ${formatFileSize(limits.maxFileSize)} allowed.`, limits, 'maxFileSize'),\n    },\n    {\n        name: 'totalSize',\n        broken: ({ totalSize }, limits) => totalSize > limits.maxTotalSize,\n        sentence: ({ totalSize }, limits) => withSuggestion(`Files add up to ${formatFileSize(totalSize)}. Maximum ${formatFileSize(limits.maxTotalSize)} allowed.`, limits, 'maxTotalSize'),\n    },\n];\n/** Whether a path names an HTML page, the kind of file a site's main page is. */\nfunction isPagePath(path) {\n    return /\\.html?$/i.test(path);\n}\n/**\n * What to do about a missing home page, read from what the files show, so\n * the refusal names the step that fits: the folder that holds the site when\n * it sits one folder down (the site published from the folder above its\n * build), the page to rename when there are pages but none is the home page\n * (a single `report.html`), and the small page to add when there is no page\n * at all (an image or a PDF published on its own, measured as the most\n * common case).\n */\nfunction missingIndexAdvice(paths) {\n    const folder = nestedIndexFolder(paths);\n    if (folder)\n        return `There's one in ${folder}/. If that's your site, publish that folder instead.`;\n    if (paths.some(isPagePath)) {\n        return `If one of your pages is the main one, put it at the top and name it ${DEPLOYMENT_INDEX_FILENAME}.`;\n    }\n    return `To publish a file on its own, like an image or a PDF, add a small ${DEPLOYMENT_INDEX_FILENAME} that links to it.`;\n}\n/**\n * Where the home page is, when it is one folder down: the shallowest nested\n * `index.html`, if exactly one folder holds it. A site deployed from the\n * folder above its build is the common way to miss the root, so the refusal\n * names the folder to publish instead.\n */\nfunction nestedIndexFolder(paths) {\n    const suffix = `/${DEPLOYMENT_INDEX_FILENAME}`;\n    const depth = (path) => path.split('/').length;\n    const nested = paths.filter((path) => path.endsWith(suffix));\n    if (nested.length === 0)\n        return undefined;\n    const shallowest = Math.min(...nested.map(depth));\n    const top = nested.filter((path) => depth(path) === shallowest);\n    return top.length === 1 ? top[0]?.slice(0, -suffix.length) : undefined;\n}\n/** The paths a deployment publishes, out of the files it was sent, in their canonical form. */\nfunction publishedPaths(files) {\n    return files.filter(isPublishedFile).map((file) => canonicalDeployPath(file.path));\n}\n/** The first path the files name twice, empty files included, or `undefined`. */\nfunction repeatedPath(files) {\n    const seen = new Set();\n    for (const { path } of files) {\n        const canonical = canonicalDeployPath(path);\n        if (seen.has(canonical))\n            return canonical;\n        seen.add(canonical);\n    }\n    return undefined;\n}\n/**\n * The rules asked of the deployment as a whole, after every file has passed\n * {@link FILE_RULES}: it has files, it names each path once, it has not more\n * than the plan allows, and it has a home page at its root. They read the\n * files as SENT, an empty one included, and count only what is published\n * ({@link isPublishedFile}), so the home-page rule can say an `index.html` is\n * empty rather than missing. Paths compare in their canonical form\n * ({@link canonicalDeployPath}). These name no one file, so a surface that\n * lists refusals per file files them under the deployment.\n */\nexport const SET_RULES = [\n    {\n        name: 'files',\n        broken: (files) => publishedPaths(files).length === 0,\n        sentence: () => 'There are no files to publish.',\n    },\n    {\n        name: 'unique',\n        broken: (files) => repeatedPath(files) !== undefined,\n        sentence: (files) => namedTwice(repeatedPath(files) ?? ''),\n    },\n    {\n        name: 'filesCount',\n        broken: (files, limits) => publishedPaths(files).length > limits.maxFilesCount,\n        sentence: (files, limits) => withSuggestion(`Too many files (${publishedPaths(files).length}). Maximum ${limits.maxFilesCount} files allowed.`, limits, 'maxFilesCount'),\n    },\n    {\n        name: 'index',\n        broken: (files) => !publishedPaths(files).includes(DEPLOYMENT_INDEX_FILENAME),\n        sentence: (files) => {\n            if (files.some((file) => canonicalDeployPath(file.path) === DEPLOYMENT_INDEX_FILENAME)) {\n                return `The ${DEPLOYMENT_INDEX_FILENAME} at the top of your site is empty. It's the page visitors see first, so it needs content.`;\n            }\n            return `There's no ${DEPLOYMENT_INDEX_FILENAME} at the top of your site. It's the page visitors see first, so your site needs one. ${missingIndexAdvice(publishedPaths(files))}`;\n        },\n    },\n];\n/** The first rule a file breaks, or `undefined`. */\nexport function firstBrokenRule(file, limits) {\n    return FILE_RULES.find((rule) => rule.broken(file, limits));\n}\n/** The first rule the deployment as a whole breaks, or `undefined`. */\nexport function brokenSetRule(files, limits) {\n    return SET_RULES.find((rule) => rule.broken(files, limits));\n}\n/**\n * Why a deployment of these files is refused, as the one sentence a person\n * reads, or `undefined` when every rule holds: each published file in order\n * against {@link FILE_RULES}, then the whole against {@link SET_RULES}. Pass\n * the files as sent, empty ones included: an empty file is left out of the\n * per-file rules and the totals, never refused.\n */\nexport function deployRefusal(files, limits) {\n    let totalSize = 0;\n    for (const { path, size } of files.filter(isPublishedFile)) {\n        totalSize += size;\n        const file = { path, size, totalSize };\n        const rule = firstBrokenRule(file, limits);\n        if (rule)\n            return rule.sentence(file, limits);\n    }\n    return brokenSetRule(files, limits)?.sentence(files, limits);\n}\n// =============================================================================\n// CREDENTIAL SHAPES\n// =============================================================================\n// The one address for credential vocabulary: where human identity lives\n// (AUTH_BASE_PATH), how a request is authorized (AuthMethod), the shapes\n// that distinguish populations on the wire (API_KEY, DEPLOY_TOKEN,\n// OAUTH_TOKEN, CALLER), the two halves of the one Bearer slot\n// (readBearerValue reads it, classifyToken/TokenKind dispatch on what came\n// out), and the delegated-access scopes (OAuthScope).\n//\n// THE SHAPE LAW, in three clauses, over the `Authorization: Bearer` slot's\n// three populations below. The deployment claim code is the API's own\n// (`AUTH.CLAIM`, server-side: the API mints it and the API validates it, so\n// it has one holder and stays there) and shares only clause 1 — it is the\n// platform's one deliberately BARE secret, because it never enters the\n// Bearer slot: minted into one URL, consumed by one endpoint's one field,\n// its context names it and a prefix would restate its route.\n// `tests/validation-constants.test.ts` holds the clauses over this file's\n// populations; the API's suite holds its own.\n//\n//  1. ONE ENTROPY STANDARD. Every minted secret is `HEX_LENGTH` hex characters\n//     — one width for the whole platform, so \"how long is a credential\" has a\n//     single answer rather than one per population. Generators read the width\n//     from the population's own constant, so a minted value and an accepted\n//     value cannot differ.\n//\n//  2. EVERY BEARER POPULATION IS NAMED BY ITS PREFIX. A credential says what\n//     it is before anything parses it — which is what lets `classifyToken`\n//     below dispatch three populations sharing one `Authorization: Bearer`\n//     slot, and what lets a value found in a log, a support ticket or a\n//     pasted URL be recognised and revoked on sight. The OAuth access token\n//     was this clause's one standing exception until 2026-08-14 — the\n//     authorization server it was born on had no mint hook to give it a\n//     prefix, and its successor does.\n//\n//  3. NO PREFIX IS A PREFIX OF ANOTHER. This is what makes the dispatch\n//     order-independent, and it is the reason the populations are named on\n//     different axes (`ship-` for the product, `deploy-` for the capability)\n//     rather than sharing a stem. A `ship-` / `ship-deploy-` pair\n//     reads tidier and is a trap: every deploy token would also match the\n//     API-key branch, leaving correctness resting on the order of two `if`s.\n/**\n * Where human identity is mounted on the API host. The API mounts Better\n * Auth at this path (sign-in, sign-out, session reads, admin impersonation)\n * and the web console's auth client posts to it — shared here so the two\n * halves of the auth pair agree by construction, the same way both sides\n * already share the credential prefixes below.\n */\nexport const AUTH_BASE_PATH = '/auth';\n/**\n * How a request (or recorded activity) was authorized.\n *\n * Client populations: `SESSION` (first-party cookie), `API_KEY` (`ship-`\n * key), `TOKEN` (`deploy-` deploy token), `AGENT` (anonymous, no credential:\n * public deploys are granted the public-account identity per request),\n * `OAUTH` (delegated access token). The one server population:\n * `SYSTEM` (scheduled/background jobs). Webhook receipt is deliberately not\n * a population: a signed delivery is verified, never authorized — it acts\n * as no one and audits as no one.\n */\nexport const AuthMethod = {\n    SESSION: 'session',\n    API_KEY: 'apiKey',\n    TOKEN: 'token',\n    AGENT: 'agent',\n    OAUTH: 'oauth',\n    SYSTEM: 'system',\n};\n/**\n * Shape constants for API keys (`ship-{32 hex chars}`).\n * Single source of truth used by validation utilities and auth middleware.\n */\nexport const API_KEY = {\n    /** Prefix that identifies an API key. */\n    PREFIX: 'ship-',\n    /** Number of hex characters following the prefix. */\n    HEX_LENGTH: 32,\n    /** Total length of an API key including prefix (`PREFIX.length + HEX_LENGTH = 37`). */\n    TOTAL_LENGTH: 37,\n    /** Number of trailing characters used to display a redacted hint (e.g. last 4). */\n    HINT_LENGTH: 4,\n};\n/**\n * Shape constants for deploy tokens (`deploy-{32 hex chars}`).\n * Single source of truth used by validation utilities and auth middleware.\n *\n * Deliberately the same width as `API_KEY`: both are minted by one generator\n * and classified by prefix alone, so a length that differed between them\n * would be a second thing to know about a credential whose prefix already\n * says what it is.\n */\nexport const DEPLOY_TOKEN = {\n    /** Prefix that identifies a deploy token. */\n    PREFIX: 'deploy-',\n    /** Number of hex characters following the prefix. */\n    HEX_LENGTH: 32,\n    /** Total length of a deploy token including prefix (`PREFIX.length + HEX_LENGTH = 39`). */\n    TOTAL_LENGTH: 39,\n};\n/**\n * Shape constants for OAuth access tokens (`oauth-{32 hex chars}`) — the\n * delegated population, minted by the platform's own authorization server\n * for a connected app acting on a user's behalf.\n *\n * Same width as the other two, and for the same reason: one entropy standard\n * across the platform, so \"how long is a credential\" has one answer.\n *\n * **This population is the access token alone.** Refresh tokens, authorization\n * codes and client secrets are deliberately NOT here and are deliberately not\n * prefixed by this constant: none of them ever enters the `Authorization:\n * Bearer` slot — a refresh token is posted as a form field to the token\n * endpoint, which knows what it is receiving — so `classifyToken` never sees\n * one and a prefix would name a population no dispatcher dispatches. The same\n * reasoning that keeps the deployment claim code bare.\n *\n * **The prefix must be applied at the MINT, never as a display wrapper.** The\n * authorization server hashes what it stores and the API hashes what it is\n * presented, so the prefix has to be inside the hashed string on both sides.\n * `@better-auth/oauth-provider` offers a `prefix.opaqueAccessToken` option\n * that prepends AFTER hashing and strips on its own read paths; using it would\n * store a hash of the UNPREFIXED token and silently break the platform's read\n * arm. The API therefore mints through `generateOpaqueAccessToken` — recorded\n * beside the config in `cloudflare/api/src/lib/auth/instance.ts`.\n */\nexport const OAUTH_TOKEN = {\n    /** Prefix that identifies an OAuth access token. */\n    PREFIX: 'oauth-',\n    /** Number of hex characters following the prefix. */\n    HEX_LENGTH: 32,\n    /** Total length including prefix (`PREFIX.length + HEX_LENGTH = 38`). */\n    TOTAL_LENGTH: 38,\n};\n/**\n * Shape constants for caller identifiers (the `X-Caller` instance-identity\n * header — rate-limit bucketing for multi-tenant orchestrators). The API\n * normalizes case and silently ignores malformed values (the header is\n * unauthenticated); clients validate at the boundary via `validateCaller`,\n * so a value the server would drop fails fast instead.\n */\nexport const CALLER = {\n    /** HTTP header name. */\n    HEADER: 'X-Caller',\n    /** Maximum identifier length. */\n    MAX_LENGTH: 128,\n    /** Allowed characters: alphanumeric, dot, underscore, hyphen. */\n    PATTERN: /^[a-zA-Z0-9._-]+$/,\n};\n/**\n * The account a session request is about.\n *\n * A person may belong to several accounts, so a request made with a browser\n * session names the one it means, on every request to an account route; the\n * console takes the value from its URL (`/<account>/`). The header names and\n * membership authorizes: the API resolves the person's membership in the\n * account named, answers 404 `details.account: 'unknown'` for an account the\n * person is not in (or one that does not exist), and 400 when a session\n * request names none. Machine credentials never send it, since a key, a\n * deploy token or an OAuth grant already belongs to one account. One owner\n * for the name, since the API's CORS allowlist and every browser transport\n * spell it.\n */\nexport const ACCOUNT_HEADER = 'X-Account';\n/**\n * Token populations distinguishable by shape. The platform carries every\n * client token in one wire slot (`Authorization: Bearer <value>`) and\n * classifies by value, never by a side channel — this is the classifier.\n *\n * `API_KEY`, `DEPLOY_TOKEN` and `OAUTH` *are* `AuthMethod.API_KEY`,\n * `AuthMethod.TOKEN` and `AuthMethod.OAUTH` — the equality is structural, so\n * a classification flows straight into an auth method and the trio can never\n * drift.\n *\n * `OPAQUE` is any other value, and since 2026-08-14 it names NO population:\n * every credential this platform mints for the Bearer slot carries a prefix,\n * so an opaque bearer is a bearer we did not mint. It stays a member rather\n * than becoming a `null` return because a dispatcher with a total codomain\n * reads better than one with an absence in it — and because it is where a\n * future population would land before anyone gave it a shape, which is\n * exactly what the OAuth token itself did until its prefix existed.\n */\nexport const TokenKind = {\n    API_KEY: AuthMethod.API_KEY,\n    DEPLOY_TOKEN: AuthMethod.TOKEN,\n    OAUTH: AuthMethod.OAUTH,\n    OPAQUE: 'opaque',\n};\n/**\n * Classify a client token by shape. The single dispatch used by both sides\n * of the wire: API auth middleware (which population is this credential?)\n * and SDK validation (which format rules apply before sending?). Sharing it\n * is what guarantees client and server can never disagree on dispatch.\n */\nexport function classifyToken(token) {\n    if (token.startsWith(API_KEY.PREFIX))\n        return TokenKind.API_KEY;\n    if (token.startsWith(DEPLOY_TOKEN.PREFIX))\n        return TokenKind.DEPLOY_TOKEN;\n    if (token.startsWith(OAUTH_TOKEN.PREFIX))\n        return TokenKind.OAUTH;\n    return TokenKind.OPAQUE;\n}\n/** The auth-scheme, lowercased — the form the comparison is made in. */\nconst BEARER_SCHEME = 'bearer ';\n/**\n * Read the credential out of an `Authorization` header value — the step\n * BEFORE `classifyToken`, and the other half of the one wire slot this\n * section owns.\n *\n * Returns the credential's own bytes, or `null` when the header carries a\n * foreign scheme or nothing after the scheme.\n *\n * **The scheme is folded; the credential is not.** RFC 7235 §2.1 makes the\n * auth-scheme case-insensitive, so `bearer`, `Bearer` and `BEARER` are the\n * same header. The value after it is opaque and is compared literally\n * everywhere it is used — `ship-`/`deploy-`/`oauth-` are lowercase hex, and\n * folding them would make a credential match values it is not.\n *\n * **This platform has paid for the rule twice, which is why it has an owner\n * rather than a convention.** A spec-conformant `bearer ship-…` client was\n * refused for as long as the API's scheme test was spelled case-sensitively;\n * and `@better-auth/oauth-provider` carries the same defect in four places\n * today (`startsWith(\"Bearer \")`), which is precisely why the platform folds\n * the scheme itself and hands the provider a bare token.\n *\n * **ABSENCE is deliberately not this function's business.** A missing header\n * and an unreadable one are different facts, and the callers that care split\n * on them: the API worker's middleware distinguishes `absent` (the only\n * anonymous path) from `unreadable` (a presented credential that is refused),\n * and collapsing the two here would take that distinction away from the layer\n * that needs it. Callers check for the header themselves and pass its value.\n *\n * **Why this lives in the constitution rather than in a worker's `shared/`.**\n * It is the same wire boundary `classifyToken` already owns — one reads the\n * slot, the other dispatches on what came out — and a rule with two holders\n * whose drift is silent earns exactly one owner regardless of what the\n * convoy costs. The estate's recorded refusal to own a `Bearer` CONSTANT\n * stands and is a different thing: that is RFC vocabulary, the same reason\n * this package owns no `\"POST\"`. A parser is not a spelling.\n */\nexport function readBearerValue(header) {\n    if (header.slice(0, BEARER_SCHEME.length).toLowerCase() !== BEARER_SCHEME)\n        return null;\n    return header.slice(BEARER_SCHEME.length) || null;\n}\n/**\n * OAuth scope vocabulary for delegated third-party access tokens.\n * Single source of truth used by the authorization server (advertised in\n * `scopes_supported`), the API's scope-enforcement middleware, and consent UI\n * copy. The standard `offline_access` scope (refresh tokens) is not platform\n * vocabulary and is deliberately absent — the middleware never checks it.\n *\n * Deliberately absent by design: any `tokens:*` scope, `account:write`, or\n * admin scope — a delegated app must never mint credentials, delete the\n * account, or act as admin.\n */\nexport const OAuthScope = {\n    ACCOUNT_READ: 'account:read',\n    DEPLOYMENTS_READ: 'deployments:read',\n    DEPLOYMENTS_WRITE: 'deployments:write',\n    DOMAINS_READ: 'domains:read',\n    DOMAINS_WRITE: 'domains:write',\n};\n// =============================================================================\n// DEPLOYMENT CONFIGURATION CONSTANTS\n// =============================================================================\nexport const DEPLOYMENT_CONFIG_FILENAME = 'ship.json';\n/**\n * Assert that a ship.json file is *syntactically* loadable. Syntax only —\n * never schema.\n *\n * ship.json is validated and compiled on the server, deliberately: the schema\n * and the compiler evolve, and a client that judged them would reject configs\n * a newer platform accepts. That reasoning bounds what a client may check to\n * the properties which are true of *every* past and future schema:\n *\n *   1. it parses as JSON — JSON syntax is frozen (RFC 8259), so text that\n *      does not parse can never be a valid config;\n *   2. its top level is an object — ship.json is `{ ... }` in every version.\n *\n * Both are monotonic: neither can ever reject something the server would\n * accept. Everything beyond them (field names, types, rule semantics, which\n * keys are permitted) stays server-side, where it can change.\n *\n * The payoff is the common case. Hand-edited JSON fails on a trailing comma,\n * a `//` comment, single quotes, unquoted keys, or smart quotes pasted from\n * documentation — mistakes that otherwise cost a full upload round-trip to\n * discover. A UTF-8 BOM (Windows editors, PowerShell redirects) is stripped\n * before parsing rather than rejected, because the server accepts it too;\n * diverging there would reintroduce exactly the false rejection this\n * function exists to avoid.\n *\n * @throws {ShipError} `ErrorType.Config` — the same type the server's own\n * config rejection carries, so the error contract is identical wherever the\n * failure is detected.\n */\nexport function assertShipJsonSyntax(text) {\n    const withoutBom = text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;\n    let parsed;\n    try {\n        parsed = JSON.parse(withoutBom);\n    }\n    catch (error) {\n        throw ShipError.config(`invalid JSON format in config: ${error.message}`, {\n            filePath: DEPLOYMENT_CONFIG_FILENAME,\n        });\n    }\n    if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n        throw ShipError.config(`${DEPLOYMENT_CONFIG_FILENAME} must contain a JSON object`, {\n            filePath: DEPLOYMENT_CONFIG_FILENAME,\n        });\n    }\n}\n// =============================================================================\n// VALIDATION UTILITIES\n// =============================================================================\n/**\n * Shared rule for prefixed credentials: `{PREFIX}{HEX_LENGTH hex chars}`.\n * The regex derives from the shape constants, so the validators can never\n * drift from the shapes `classifyToken` dispatches on.\n */\nfunction validatePrefixedCredential(value, shape, label) {\n    if (!value.startsWith(shape.PREFIX)) {\n        throw ShipError.validation(`${label} must start with \"${shape.PREFIX}\"`);\n    }\n    if (value.length !== shape.TOTAL_LENGTH) {\n        throw ShipError.validation(`${label} must be ${shape.TOTAL_LENGTH} characters total (${shape.PREFIX} + ${shape.HEX_LENGTH} hex chars)`);\n    }\n    const hexPart = value.slice(shape.PREFIX.length);\n    if (!new RegExp(`^[a-f0-9]{${shape.HEX_LENGTH}}$`, 'i').test(hexPart)) {\n        throw ShipError.validation(`${label} must contain ${shape.HEX_LENGTH} hexadecimal characters after \"${shape.PREFIX}\" prefix`);\n    }\n}\n/**\n * Validate API key format\n */\nexport function validateApiKey(apiKey) {\n    validatePrefixedCredential(apiKey, API_KEY, 'API key');\n}\n/**\n * Validate deploy token format\n */\nexport function validateDeployToken(deployToken) {\n    validatePrefixedCredential(deployToken, DEPLOY_TOKEN, 'Deploy token');\n}\n/**\n * Validate OAuth access token format\n */\nexport function validateOAuthToken(oauthToken) {\n    validatePrefixedCredential(oauthToken, OAUTH_TOKEN, 'OAuth access token');\n}\n/**\n * Validate a client token of any population. Classifies by shape and applies\n * the matching format rules: all three prefixed populations are validated\n * strictly; an OPAQUE token only needs to be non-empty.\n *\n * **The OPAQUE arm stays permissive on purpose**, even though the platform no\n * longer mints an unprefixed credential. It is the fallback for a population\n * that does not exist yet, and a client refusing a shape the server would\n * accept is the one failure mode this boundary must never have — the server\n * decides, and it refuses an unrecognised bearer anyway. Unprefixed OAuth\n * tokens from before 2026-08-14 land here and are refused server-side, which\n * is correct: they were revoked by the change, not grandfathered.\n */\nexport function validateToken(token) {\n    switch (classifyToken(token)) {\n        case TokenKind.API_KEY:\n            validateApiKey(token);\n            return;\n        case TokenKind.DEPLOY_TOKEN:\n            validateDeployToken(token);\n            return;\n        case TokenKind.OAUTH:\n            validateOAuthToken(token);\n            return;\n        case TokenKind.OPAQUE:\n            if (!token)\n                throw ShipError.validation('Token must be a non-empty string');\n    }\n}\n/**\n * Validate a caller identifier against the `CALLER` shape. The server\n * silently ignores malformed values (the header is unauthenticated); clients\n * call this at configuration time so the drop never silently happens.\n */\nexport function validateCaller(caller) {\n    if (!caller || caller.length > CALLER.MAX_LENGTH || !CALLER.PATTERN.test(caller)) {\n        throw ShipError.validation(`Caller must be 1-${CALLER.MAX_LENGTH} characters: letters, digits, dots, underscores, or hyphens`);\n    }\n}\n/**\n * Validate API URL format\n */\nexport function validateApiUrl(apiUrl) {\n    try {\n        const url = new URL(apiUrl);\n        if (!['http:', 'https:'].includes(url.protocol)) {\n            throw ShipError.validation('API URL must use http:// or https:// protocol');\n        }\n        if (url.pathname !== '/' && url.pathname !== '') {\n            throw ShipError.validation('API URL must not contain a path');\n        }\n        if (url.search || url.hash) {\n            throw ShipError.validation('API URL must not contain query parameters or fragments');\n        }\n    }\n    catch (error) {\n        if (isShipError(error)) {\n            throw error;\n        }\n        throw ShipError.validation('API URL must be a valid URL');\n    }\n}\n/**\n * Check if a string matches the deployment identifier pattern (word-word-alphanumeric7).\n * Example: \"happy-cat-abc1234.shipstatic.com\"\n */\nexport function isDeployment(input) {\n    return /^[a-z]+-[a-z]+-[a-z0-9]{7}(\\.[a-z0-9.-]+)?$/i.test(input);\n}\n/**\n * The envelope a requested lifetime must fit — one word, one grammar, wherever\n * the platform lets a caller choose how long something lives.\n *\n * Two resources wear it: `TokenCreateOptions.ttl` and\n * `DeploymentUploadOptions.ttl`. It lives here rather than on the server by\n * the format-vs-policy rule — a client can decide offline whether a duration\n * is well-formed, and the API rejects the same value the same way. What is\n * NOT here is any per-plan ceiling: no such policy exists, and one delivered\n * speculatively through `/limits` would be an owner for a decision nobody has\n * made.\n */\nexport const TTL_CONSTRAINTS = {\n    /**\n     * Shortest requestable lifetime, in seconds. One rather than zero: a\n     * deployment that expires the instant it is created is not a shorter lease,\n     * it is a deploy that was never live, and `0` is how an unset variable\n     * arrives.\n     */\n    MIN_SECONDS: 1,\n    /** Longest requestable lifetime, in seconds — one year. */\n    MAX_SECONDS: 365 * 24 * 60 * 60,\n};\n/**\n * Validate a requested lifetime in SECONDS and return it, or `undefined` when\n * none was asked for.\n *\n * **A duration, never an instant.** The caller says how long; the server owns\n * what time it is and stamps the expiry — so a client's clock, however wrong,\n * cannot shorten or extend a lease. That is the tokens precedent, and it is\n * why this rule measures a count of seconds rather than checking a timestamp\n * against `now`.\n *\n * Fractions are refused rather than rounded: a caller who wrote `1.5` meant\n * something the wire cannot carry, and silently choosing `1` or `2` for them\n * is a decision the platform has no standing to make.\n *\n * Single source of truth shared by the API (the tokens route and the deploy\n * schema), the SDK's request boundary, and the CLI's parser.\n */\nexport function validateTtl(value) {\n    if (value === undefined || value === null)\n        return undefined;\n    if (typeof value !== 'number' || !Number.isFinite(value)) {\n        throw ShipError.validation('TTL must be a number of seconds');\n    }\n    if (!Number.isInteger(value)) {\n        throw ShipError.validation('TTL must be a whole number of seconds');\n    }\n    if (value < TTL_CONSTRAINTS.MIN_SECONDS || value > TTL_CONSTRAINTS.MAX_SECONDS) {\n        throw ShipError.validation(`TTL must be between ${TTL_CONSTRAINTS.MIN_SECONDS} and ${TTL_CONSTRAINTS.MAX_SECONDS} seconds`);\n    }\n    return value;\n}\n// =============================================================================\n// CONSOLE PATHS\n// =============================================================================\n// The console's path grammar: every console path a server producer emits,\n// and the readers that tell those paths apart.\n//\n// One fact, two holders. The console mounts these paths as routes, and the\n// API, its letters and its billing returns emit them as links; a drift\n// between the two is a link that 404s with nothing to report it, and no\n// fence can reach across the two repositories. So the grammar lives here\n// and both import it.\n//\n// The console's URL names the account: every page inside an account lives\n// under `/<account>/`, where `<account>` is the account's id\n// (`Account.account`). Every section is also reachable at the root, where\n// the console opens it in the account the person entered last (or, for a\n// section flagged `owner`, in their own); that bare form is what a producer\n// whose subject is a person emits. Outside both sit the doors, which exist\n// before an account is known, and the operator partition.\n/**\n * The sections of an account, by first segment, each mounted twice by the\n * console: under `/<account>/` and at the root.\n *\n * `owner` marks a section that means the person's OWN account: a bare path\n * into it opens the person's own account rather than the one entered last.\n * A pricing link's `/upgrade/pro` and the published API-key link speak about\n * the reader's plan and key, and `/success` is where a purchase lands: only\n * an owner buys, and a person owns exactly one account. Modals inside a\n * section carry their own owner rule in the console; this flag is the\n * section's alone.\n */\nexport const SECTIONS = {\n    new: { owner: false },\n    deployments: { owner: false },\n    domains: { owner: false },\n    settings: { owner: false },\n    // A claim link (`/claim/<code>`) is mailed and answered without an account,\n    // so it opens where `/` opens: the account the person is standing in. The\n    // site is kept there. Not an owner section, since a member may keep a\n    // site in a team.\n    claim: { owner: false },\n    upgrade: { owner: true },\n    success: { owner: true },\n    'api-key': { owner: true },\n};\n/** The pages that exist before an account is known, by first segment. */\nconst DOOR_SEGMENTS = ['login', 'register', 'logout', 'invitation', 'consent'];\n/** The operator partition's first segment. */\nconst ADMIN_SEGMENT = 'admin';\n// Sections, doors and the operator partition are disjoint sets of first\n// segments: a path's first segment decides which of the three it is, and\n// anything that is none of them names an account. A shared name fails the\n// build here.\nconst disjoint = true;\nvoid disjoint;\n/**\n * The query markers a Stripe return lands with, each written by a builder\n * below and read by `billingReturnOf`, so neither side spells one.\n */\nconst BILLING_RETURNS = {\n    checkout: ['upgrading', 'true'],\n    portal: ['billing', 'returned'],\n};\nconst marker = (kind) => BILLING_RETURNS[kind].join('=');\n/** A link with an optional `?next=`, the console's own return path. */\nconst withNext = (door, next) => next ? `${door}?next=${encodeURIComponent(next)}` : door;\n/**\n * The paths inside one account, or, with no account, the bare form the\n * console opens in the account entered last.\n *\n * ```ts\n * consolePaths(account).domains.connect('www.example.com')\n * // '/<account>/domains/www.example.com/connect'\n * consolePaths().apiKey()\n * // '/api-key'\n * ```\n */\nexport function consolePaths(account) {\n    const base = account ? `/${account}` : '';\n    const at = (path) => `${base}${path}`;\n    return {\n        dashboard: () => base || '/',\n        newSite: () => at('/new'),\n        deployments: Object.assign(() => at('/deployments'), {\n            upload: () => at('/deployments/upload'),\n        }),\n        domains: Object.assign(() => at('/domains'), {\n            connect: (domain) => at(`/domains/${domain}/connect`),\n            deployment: (domain) => at(`/domains/${domain}/deployment`),\n        }),\n        settings: (fragment) => at(fragment ? `/settings#${fragment}` : '/settings'),\n        /** The claim of an anonymous deployment into this account; the API mails the bare form. */\n        claim: (code) => at(`/claim/${code}`),\n        /** Settings, marked as the landing of a Stripe Customer Portal return. */\n        settingsAfterBilling: () => at(`/settings?${marker('portal')}`),\n        upgrade: (plan) => at(plan ? `/upgrade/${plan}` : '/upgrade'),\n        success: () => at('/success'),\n        /** The success page, marked as the landing of a Stripe Checkout return. */\n        successAfterCheckout: () => at(`/success?${marker('checkout')}`),\n        apiKey: () => at('/api-key'),\n    };\n}\n/**\n * The login door: `/login`, the journey on its query. `login.link` is the page\n * a sign-in email's link opens, `/login/link/<token>`: the door's object, the\n * link's token, rides the path, and the journey still rides the query.\n */\nconst login = Object.assign(({ next } = {}) => withNext('/login', next), {\n    link: ({ token, next }) => withNext(`/login/link/${token}`, next),\n});\n/**\n * The doors: the pages a PERSON stands on before an account is known, one\n * builder per door segment and named for it: signing in and out, joining an\n * account, granting an app access. A door's object rides its path (the\n * sign-in link's token, the invitation's id), and the journey rides the\n * query, so the three doors a sign-in moves through take it by name. What a\n * person does IN an account is a section (`consolePaths`), the claim among\n * them.\n *\n * ```ts\n * doors.login.link({ token, next: '/claim/abc' })\n * // '/login/link/<token>?next=%2Fclaim%2Fabc'\n * ```\n */\nexport const doors = {\n    login,\n    register: ({ next } = {}) => withNext('/register', next),\n    logout: ({ next } = {}) => withNext('/logout', next),\n    invitation: (invitation) => `/invitation/${invitation}`,\n    consent: () => '/consent',\n};\n/**\n * Which Stripe return a query string marks: `checkout` for the success page\n * after Checkout, `portal` for settings after the Customer Portal, or null.\n */\nexport function billingReturnOf(search) {\n    const params = new URLSearchParams(search);\n    for (const [kind, [key, value]] of Object.entries(BILLING_RETURNS)) {\n        if (params.get(key) === value)\n            return kind;\n    }\n    return null;\n}\nconst isDoor = (segment) => DOOR_SEGMENTS.includes(segment);\nconst isSection = (segment) => Object.hasOwn(SECTIONS, segment);\nfunction placeOf(path) {\n    const pathname = path.split(/[?#]/)[0].toLowerCase();\n    const [first = '', second = ''] = pathname.split('/').filter(Boolean);\n    if (isDoor(first))\n        return { kind: 'door', door: first };\n    if (first === ADMIN_SEGMENT)\n        return { kind: 'admin' };\n    if (first === '' || isSection(first)) {\n        return { kind: 'account', account: null, section: first === '' ? null : first };\n    }\n    return { kind: 'account', account: first, section: isSection(second) ? second : null };\n}\n/**\n * The account a path names, or null for a door, the operator partition, or\n * the bare form. Any first segment that is not a section, a door or the\n * partition is an account: the grammar has no other reading, and whether\n * the account exists is the server's answer, never the path's.\n */\nexport function accountOfPath(path) {\n    const place = placeOf(path);\n    return place.kind === 'account' ? place.account : null;\n}\n/**\n * The door a path names, or null for an account place or the operator\n * partition. Every question about doors reads this one answer: which page is\n * an auth page, which errand a destination carries, what a vendor must not\n * see. `/login/link/<token>` is the login door, as `/invitation/<id>` is the\n * invitation door: a door's object is the rest of its path.\n */\nexport function doorOf(path) {\n    const place = placeOf(path);\n    return place.kind === 'door' ? place.door : null;\n}\n/**\n * Whether a path names the claim section, in either form: `/claim/:code`, and\n * the same under `/<account>/`. The code is a bearer credential, which is why\n * a reader asks about this section by name: the doors title their visitor by\n * it, and analytics elides it.\n */\nexport const isClaimPath = (path) => {\n    const place = placeOf(path);\n    return place.kind === 'account' && place.section === 'claim';\n};\n/**\n * Whether a path names the upgrade section, in either form: `/upgrade`,\n * `/upgrade/:plan`, and the same under `/<account>/`.\n */\nexport const isUpgradePath = (path) => {\n    const place = placeOf(path);\n    return place.kind === 'account' && place.section === 'upgrade';\n};\n/**\n * The errand a destination path carries, in specificity order: a pricing\n * link is the broadest, and the narrower ones do not normally coexist with\n * it.\n */\nexport function errandOf(path) {\n    if (isClaimPath(path))\n        return 'claim';\n    if (doorOf(path) === 'invitation')\n        return 'invite';\n    if (isUpgradePath(path))\n        return 'upgrade';\n    return null;\n}\n// =============================================================================\n// PLATFORM CONSTANTS\n// =============================================================================\n/** Default API URL if not otherwise configured. */\nexport const DEFAULT_API = 'https://api.shipstatic.com';\n/**\n * The Node SDK's ambient configuration pair — the ONLY environment variables\n * the SDK reads, and therefore the COMPLETE list an embedding host must\n * scrub (per `npm/ship`'s strict-isolation contract, scrubbing is the host's\n * job, not the SDK's). A host that derives its scrub from this object's\n * values — as the VS Code extension's child-process env block does — picks\n * up a grown contract at the next pin bump instead of by remembered prose.\n *\n * Browser builds read no environment at all, and the wrapper-tier variables\n * are deliberately NOT here: `SHIP_PASSWORD` stays the CLI's own operational\n * lever (see `npm/ship/CLAUDE.md`, \"CLI-only env vars\"), and the origin\n * relabel slot has its own owner beside this object ({@link SHIP_VIA_ENV})\n * because two executables read it and neither reading is the SDK's.\n */\nexport const SHIP_ENV = {\n    /** The one credential slot — any platform token. */\n    TOKEN: 'SHIP_TOKEN',\n    /** The API endpoint override. */\n    API_URL: 'SHIP_API_URL',\n};\n/**\n * The origin-relabel slot for integrations that wrap a first-party\n * executable as a subprocess. A wrapper composes an argv and an env it does\n * not otherwise reach, so this variable is its one way to name the surface\n * the traffic is really from. Two executables read it through\n * {@link normalizeVia}: the `ship` CLI (default `cli`; the GitHub Action\n * sets `git`) and the stdio MCP bin (default `mcp`; the Gemini CLI\n * extension sets `gmn`). In-process SDK consumers pass the programmatic\n * `via` option instead: same destination, different mechanism.\n *\n * Deliberately not a member of {@link SHIP_ENV}, which is the SDK's ambient\n * contract; the SDK never reads this. The name earned an owner the day the\n * stdio bin became its second reader: one spelling, two executables, and a\n * misspelling on either side drops attribution silently.\n */\nexport const SHIP_VIA_ENV = 'SHIP_VIA';\n/**\n * Where a human creates an API key: the console deep link quoted by every\n * surface that teaches authentication (the CLI's config wizard, the VS Code\n * and n8n listings, the n8n rate-limit hint and credential copy). The bare\n * form of the path, which the console opens in the reader's own account.\n *\n * Production-branded by design: published artifacts name the product, never\n * an environment (root `CLAUDE.md`, \"Environment-Aware URLs\").\n */\nexport const MY_API_KEY_URL = `https://my.shipstatic.com${consolePaths().apiKey()}`;\n/**\n * How long an anonymous deployment lives before it expires.\n *\n * The lifetime of the public tier, and one fact with several readers. The API\n * stamps a deployment's `expires` from it and gives a claim code exactly the\n * same window — a live site with a dead claim link is a coherence bug, so the\n * two are one constant rather than two that agree. Both MCP transports quote\n * the duration in prose an agent reads, and derive it from here rather than\n * writing it out, which they did in eight places until this export existed.\n *\n * Seconds, spelled in the name: this platform has both second- and\n * millisecond-valued durations, and the pair is only safe when each says which\n * it is.\n */\nexport const PUBLIC_DEPLOYMENT_TTL_SECONDS = 3 * 24 * 60 * 60;\n/**\n * How long a build may take, start to finish: installing, building and\n * prerendering together.\n *\n * The platform reaches its build service through a proxy that ends a request\n * after 125 seconds of silence, and only an Enterprise plan can change that,\n * so a build answers inside this limit or is refused with a sentence that\n * names it. One number with several readers: the API waits a little longer\n * than it before giving up, the SDK waits for the upload plus it, the build\n * service enforces it (its `config.env`, held to this by `builds/check.sh`),\n * and the docs state it in minutes (held by `scripts/check-doc-limits.sh`).\n *\n * The day builds are sold by plan, this moves to `/limits`, where a plan's\n * numbers are delivered.\n */\nexport const BUILD_TIME_LIMIT_SECONDS = 120;\n// =============================================================================\n// TIME REMAINING\n// =============================================================================\n/**\n * A span of time in words: `\"3 days\"`, `\"5 hours\"`, `\"45 minutes\"`.\n *\n * Minutes under two hours, hours under two days, and days beyond, each rounded\n * to the nearest. The unit changes exactly where the larger one rounds to two,\n * so the number never jumps as time passes (119 minutes, then 2 hours), and\n * the two vaguest things a rounded clock can say, \"1 hour\" and \"1 day\", are\n * never said. Rounding rather than truncating is what lets a deployment made a\n * second ago read the lifetime it was given: \"3 days\", not \"2 days\". Days are\n * the largest unit because nobody counts a deadline in weeks, and a month has\n * no fixed length.\n *\n * A span that rounds to no minutes at all, zero and negative included, reads\n * \"less than a minute\".\n */\nexport function formatDuration(seconds) {\n    const minutes = Math.round(seconds / 60);\n    if (!(minutes >= 1))\n        return 'less than a minute';\n    if (minutes < 120)\n        return countOf(minutes, 'minute');\n    const hours = Math.round(seconds / 3_600);\n    if (hours < 48)\n        return countOf(hours, 'hour');\n    return countOf(Math.round(seconds / 86_400), 'day');\n}\n/**\n * The time left before a deadline, in words (`\"3 days\"`), or `null` once it\n * has passed.\n *\n * `expires` is unix SECONDS, the wire's own field, taken as it arrives so that\n * no caller converts it: the deploy card once read it as a date string and\n * showed the same three days on every deployment for months. `now` is seconds\n * too, and defaults to the clock.\n *\n * A surface that tells a person how long a deployment has left says it with\n * this, so one deployment reads the same everywhere, whenever it is looked at.\n * What a surface says around the words is its own (\"Expires in\", \"It stays\n * live for\"), and so is what it says once the deadline has passed, which is\n * why that case is `null` rather than a sentence.\n */\nexport function formatTimeRemaining(expires, now = Date.now() / 1_000) {\n    const seconds = expires - now;\n    return seconds > 0 ? formatDuration(seconds) : null;\n}\nfunction countOf(count, unit) {\n    return `${count} ${unit}${count === 1 ? '' : 's'}`;\n}\n// =============================================================================\n// FILE SIZE\n// =============================================================================\n/**\n * A byte count as a person reads it: `\"180 KB\"`, `\"2.5 MB\"`, `\"0 Bytes\"`.\n *\n * Binary units, one decimal by default, and `decimals` for a surface with its\n * own density (a dense table reads `\"3 MB\"` at 0). A deployment's size reads\n * this way on every surface that states one: the console, the CLI, the deploy\n * card and the API's own refusals, so one deployment is one number everywhere.\n */\nexport function formatFileSize(bytes, decimals = 1) {\n    if (bytes === 0)\n        return '0 Bytes';\n    const k = 1024;\n    const sizes = ['Bytes', 'KB', 'MB', 'GB'];\n    const i = Math.floor(Math.log(bytes) / Math.log(k));\n    return `${Number.parseFloat((bytes / k ** i).toFixed(decimals))} ${sizes[i]}`;\n}\n// The billing boundary: the stream records the PLATFORM'S own acts, and\n// Stripe records the subscription's life. `checkout.open` is ours — the\n// platform mints the Session, and it is the one billing act that exists\n// before Stripe holds anything. `account.plan.transition` is ours — what a\n// change MEANS, entitlement crossing our threshold. Everything between those\n// two edges (invoices, refunds, disputes, retries, scheduled changes) is the\n// subscription's own history, which belongs to Stripe as merchant of record\n// and is shown to the customer in the Customer Portal; none of it is\n// restated here. Refusals write no history either: the stream records what\n// happened to resources, never what was declined — a detection\n// (`deployment.flagged`) is a fact discovered about content, not a refusal.\n/**\n * The events an account's own feed shows: curated meaning, where everything\n * else in the stream is the operator's forensics. One list, the owner of\n * both the API's filter and the type; the retention floor covers exactly\n * these, since the floor exists to keep a dormant account's feed from\n * reading empty.\n */\nexport const USER_VISIBLE_EVENTS = [\n    'account.create',\n    'account.update',\n    'account.delete',\n    'account.key.generate',\n    'account.plan.transition',\n    'deployment.create',\n    'deployment.update',\n    'deployment.delete',\n    'deployment.claim',\n    'domain.create',\n    'domain.update',\n    'domain.delete',\n    'domain.verify',\n    'token.create',\n    'token.consume',\n    'token.delete',\n    'member.join',\n    'member.leave',\n    'consent.grant',\n];\n// =============================================================================\n// FILE UPLOAD TYPES\n// =============================================================================\n/**\n * File status constants for validation state tracking\n */\nexport const FileValidationStatus = {\n    /** File is pending validation */\n    PENDING: 'pending',\n    /** File failed during processing (before validation) */\n    PROCESSING_ERROR: 'processing_error',\n    /** File was excluded by validation warning (not an error) */\n    EXCLUDED: 'excluded',\n    /** File failed validation (blocks deployment) */\n    VALIDATION_FAILED: 'validation_failed',\n    /** File passed validation and is ready for deployment */\n    READY: 'ready',\n};\n// =============================================================================\n// DOMAIN UTILITIES\n// =============================================================================\n/**\n * Check if a domain is a platform domain (subdomain of our platform).\n * Platform domains are free and don't require DNS verification.\n *\n * @example isPlatformDomain(\"www.shipstatic.com\", \"shipstatic.com\") → true\n * @example isPlatformDomain(\"example.com\", \"shipstatic.com\") → false\n */\nexport function isPlatformDomain(domain, platformDomain) {\n    return domain.endsWith(`.${platformDomain}`);\n}\n/**\n * Check if a domain is a custom domain (not a platform domain).\n * Custom domains are billable and require DNS verification.\n *\n * @example isCustomDomain(\"example.com\", \"shipstatic.com\") → true\n * @example isCustomDomain(\"www.shipstatic.com\", \"shipstatic.com\") → false\n */\nexport function isCustomDomain(domain, platformDomain) {\n    return !isPlatformDomain(domain, platformDomain);\n}\n/**\n * Extract subdomain from a platform domain.\n * Returns null if not a platform domain.\n *\n * @example extractSubdomain(\"www.shipstatic.com\", \"shipstatic.com\") → \"www\"\n * @example extractSubdomain(\"example.com\", \"shipstatic.com\") → null\n */\nexport function extractSubdomain(domain, platformDomain) {\n    if (!isPlatformDomain(domain, platformDomain)) {\n        return null;\n    }\n    return domain.slice(0, -(platformDomain.length + 1)); // +1 for the dot\n}\n/**\n * Generate HTTPS URL for a deployment hostname.\n */\nexport function generateDeploymentUrl(deployment) {\n    return `https://${deployment}`;\n}\n/**\n * Generate HTTPS URL for a domain.\n */\nexport function generateDomainUrl(domain) {\n    return `https://${domain}`;\n}\n// =============================================================================\n// LABEL UTILITIES\n// =============================================================================\n/**\n * A label is a short identifier attached to a deployment, a domain or a token.\n * It has one of two forms:\n *\n * - a word: `production`, `v1.2.3`, `us-east-1`\n * - a key and a value, split by one `:`: `env:production`, `team:web`\n *\n * Each side is lowercase letters and digits, with single `.`, `_` or `-`\n * between them. The whole label, the key and the `:` and the value together,\n * counts toward {@link LABEL_CONSTRAINTS.MAX_LENGTH}.\n *\n * The platform stores a label in lowercase and shows it as stored. It reads\n * nothing from a key or a value and changes no behaviour because of one: a\n * label describes a resource and lets its owner find it. So a resource may carry several\n * values for one key (`team:web` and `team:api`), and only the same label\n * twice is refused.\n *\n * Labels stay a list of strings on the wire and in storage. A caller that\n * wants a key's value splits on the `:` itself.\n */\nexport const LABEL_CONSTRAINTS = {\n    /** Minimum label length in characters. */\n    MIN_LENGTH: 3,\n    /**\n     * Maximum label length in characters. A key, its `:` and its value share it,\n     * and it fits a key with a UUID (36 characters) or a full git SHA (40).\n     */\n    MAX_LENGTH: 63,\n    /** Maximum number of labels on one resource. */\n    MAX_COUNT: 10,\n};\n/**\n * The shape of a label: one side, or two with a `:` between them. A side is\n * lowercase letters and digits with single `.`, `_` or `-` between them, and\n * the pattern spells it twice. Length is {@link LABEL_CONSTRAINTS}' rule, and\n * {@link validateLabel} applies both.\n *\n * Matches: `production`, `v1.2.3`, `env:production`, `commit:3f9c2ab`\n * Refuses: `-prod`, `foo--bar`, `:production`, `env:`, `a:b:c`, `Env:Prod`\n */\nexport const LABEL_PATTERN = /^[a-z0-9]+(?:[._-][a-z0-9]+)*(?::[a-z0-9]+(?:[._-][a-z0-9]+)*)?$/;\n/**\n * Validate one label and return it normalized: trimmed and lowercased, then\n * held to {@link LABEL_CONSTRAINTS}' length and to {@link LABEL_PATTERN}.\n * Throws `ShipError.validation` when it does not fit.\n *\n * Lowercasing is the one normalization and it applies to both sides of a\n * `:`, so `Env:Prod` is stored as `env:prod`. A value that must keep its\n * case does not belong in a label.\n *\n * The one label check on the platform: the SDK and the console call it for\n * fast feedback and the API calls it as the boundary, so all three refuse\n * the same strings in the same words.\n */\nexport function validateLabel(value) {\n    if (typeof value !== 'string') {\n        throw ShipError.validation('Labels must be strings');\n    }\n    const label = value.trim().toLowerCase();\n    if (label.length < LABEL_CONSTRAINTS.MIN_LENGTH) {\n        throw ShipError.validation(`Labels must be at least ${LABEL_CONSTRAINTS.MIN_LENGTH} characters long`);\n    }\n    if (label.length > LABEL_CONSTRAINTS.MAX_LENGTH) {\n        throw ShipError.validation(`Labels must be no more than ${LABEL_CONSTRAINTS.MAX_LENGTH} characters long`);\n    }\n    if (!LABEL_PATTERN.test(label)) {\n        throw ShipError.validation('Labels use letters and numbers, with . _ or - between them, and can have one : between a key and a value, like env:production');\n    }\n    return label;\n}\nexport function validateLabels(labels) {\n    if (labels === undefined || labels === null)\n        return undefined;\n    if (!Array.isArray(labels)) {\n        throw ShipError.validation('Labels must be an array');\n    }\n    if (labels.length > LABEL_CONSTRAINTS.MAX_COUNT) {\n        throw ShipError.validation(`Maximum ${LABEL_CONSTRAINTS.MAX_COUNT} labels allowed`);\n    }\n    const normalized = labels.map(validateLabel);\n    if (new Set(normalized).size !== normalized.length) {\n        throw ShipError.validation('Duplicate labels are not allowed');\n    }\n    return normalized;\n}\n/**\n * Serialize labels array to JSON string for database storage.\n * Returns null for empty or undefined arrays.\n *\n * @example serializeLabels(['web', 'production']) → '[\"web\",\"production\"]'\n * @example serializeLabels([]) → null\n * @example serializeLabels(undefined) → null\n */\nexport function serializeLabels(labels) {\n    if (!labels || labels.length === 0)\n        return null;\n    return JSON.stringify(labels);\n}\n/**\n * Deserialize labels from JSON string to array.\n * Always returns an array — empty array for null/empty/invalid input.\n *\n * @example deserializeLabels('[\"web\",\"production\"]') → ['web', 'production']\n * @example deserializeLabels(null) → []\n * @example deserializeLabels('') → []\n */\nexport function deserializeLabels(labelsJson) {\n    if (!labelsJson)\n        return [];\n    try {\n        const parsed = JSON.parse(labelsJson);\n        return Array.isArray(parsed) ? parsed : [];\n    }\n    catch {\n        return [];\n    }\n}\n// =============================================================================\n// BUILD SETTINGS\n// =============================================================================\n/**\n * The format of the two per-deploy build settings a caller may name when the\n * builder's own detection is not enough: the command to run and the folder\n * the site lands in. Format rules only, the format/policy split this file\n * keeps everywhere: WHAT a value may look like lives here so both the console\n * (fast feedback) and the API (the boundary) refuse the same strings; whether\n * the command builds anything is the build's verdict, not a rule.\n *\n * Both are read only by first-party `/upload`, only with `build`, and both\n * run inside the throwaway container that already runs the project's own\n * arbitrary code, which is why the command's format is a shape rule (one\n * line, bounded) and not a safety rule. The folder's rule is what keeps it a\n * folder OF the project: relative, no parent segments, no leading slash.\n */\nexport const BUILD_SETTINGS = {\n    /** A build command is one line, non-empty, and bounded. */\n    COMMAND_MAX_LENGTH: 200,\n    /** An output folder is a bounded relative path. */\n    OUTPUT_DIR_MAX_LENGTH: 100,\n    /** Path segments and separators only: `dist`, `dist/site`, `.output/public`. */\n    OUTPUT_DIR_PATTERN: /^[A-Za-z0-9._-]+(\\/[A-Za-z0-9._-]+)*$/,\n};\n/**\n * Validate an optional build command and return it normalized (trimmed).\n * Absent → `undefined`. Present → one line, 1 to\n * {@link BUILD_SETTINGS.COMMAND_MAX_LENGTH} characters, no control characters.\n */\nexport function validateBuildCommand(value) {\n    if (value === undefined || value === null || value === '')\n        return undefined;\n    if (typeof value !== 'string') {\n        throw ShipError.validation('Build command must be a string');\n    }\n    const trimmed = value.trim();\n    if (trimmed.length === 0 || trimmed.length > BUILD_SETTINGS.COMMAND_MAX_LENGTH) {\n        throw ShipError.validation(`Build command must be between 1 and ${BUILD_SETTINGS.COMMAND_MAX_LENGTH} characters`);\n    }\n    // biome-ignore lint/suspicious/noControlCharactersInRegex: a command is one line; a newline or any other control character is a second one\n    if (/[\\x00-\\x1f\\x7f]/.test(trimmed)) {\n        throw ShipError.validation('Build command must be a single line');\n    }\n    return trimmed;\n}\n/**\n * Validate an optional output folder and return it normalized (trimmed, no\n * trailing slash). Absent → `undefined`. Present → a relative path of plain\n * segments, no `..`, no leading slash, at most\n * {@link BUILD_SETTINGS.OUTPUT_DIR_MAX_LENGTH} characters.\n */\nexport function validateOutputDir(value) {\n    if (value === undefined || value === null || value === '')\n        return undefined;\n    if (typeof value !== 'string') {\n        throw ShipError.validation('Output folder must be a string');\n    }\n    const trimmed = value.trim().replace(/\\/+$/, '');\n    if (trimmed.length === 0 || trimmed.length > BUILD_SETTINGS.OUTPUT_DIR_MAX_LENGTH) {\n        throw ShipError.validation(`Output folder must be between 1 and ${BUILD_SETTINGS.OUTPUT_DIR_MAX_LENGTH} characters`);\n    }\n    if (!BUILD_SETTINGS.OUTPUT_DIR_PATTERN.test(trimmed) ||\n        trimmed.split('/').some((segment) => segment === '..' || segment === '.')) {\n        throw ShipError.validation('Output folder must be a relative path inside the project, like dist or dist/site');\n    }\n    return trimmed;\n}\n// =============================================================================\n// PASSWORD UTILITIES\n// =============================================================================\n/**\n * Length constraints for the optional deployment password\n * (`DeploymentUploadOptions.password`). Single source of truth shared across\n * platform consumers.\n */\nexport const PASSWORD_CONSTRAINTS = {\n    /** Minimum password length in characters */\n    MIN_LENGTH: 6,\n    /** Maximum password length in characters */\n    MAX_LENGTH: 128,\n};\n/**\n * Validate an optional deployment password and return it normalized.\n *\n * Absent (`undefined` / `null`) → returns `undefined`. Present → trim\n * leading/trailing whitespace, then validate against `PASSWORD_CONSTRAINTS`\n * length bounds (internal whitespace is significant and counts toward\n * length). Throws `ShipError.validation` on breach; returns the trimmed\n * value.\n *\n * The trim is canonical: at upload, the API hashes the trimmed value; at\n * unlock, the router trims submissions before hashing. Submission and storage\n * agree byte-for-byte. Length validation runs on the trimmed value because\n * that's the user's actual intent — and it disarms a class of invisible\n * foot-guns (trailing newlines from copy/paste, mobile auto-spacing,\n * password-manager artifacts).\n *\n * Single source of truth shared by SDK (client-side validation, return\n * ignored) and API (server-side enforcement, return threaded into config).\n * Length is part of the wire-format contract; strength rules, if added later,\n * stay server-side. See `CLAUDE.md` \"Validation: format vs policy\".\n */\nexport function validatePassword(value) {\n    if (value === undefined || value === null)\n        return undefined;\n    if (typeof value !== 'string') {\n        throw ShipError.validation('Password must be a string');\n    }\n    const trimmed = value.trim();\n    if (trimmed.length < PASSWORD_CONSTRAINTS.MIN_LENGTH ||\n        trimmed.length > PASSWORD_CONSTRAINTS.MAX_LENGTH) {\n        throw ShipError.validation(`Password must be between ${PASSWORD_CONSTRAINTS.MIN_LENGTH} and ${PASSWORD_CONSTRAINTS.MAX_LENGTH} characters`);\n    }\n    return trimmed;\n}\n","/**\n * The `File` ↔ `ProcessedFile` boundary, and the path rules that govern it.\n */\nimport { optimizeDeployPaths } from '@shipstatic/ship';\nimport { FileValidationStatus, type FileValidationStatusType } from '@shipstatic/types';\nimport type { ProcessedFile } from './types';\n\n/**\n * Patch a File's `webkitRelativePath` so the Ship SDK reads our resolved deploy\n * path. The browser-set property is read-only, so it must be redefined;\n * `configurable: true` allows re-patching when prefixes are stripped later.\n */\nexport function setRelativePath(file: File, path: string): void {\n  Object.defineProperty(file, 'webkitRelativePath', {\n    value: path,\n    writable: false,\n    configurable: true,\n  });\n}\n\n/**\n * The deploy path of a raw File: its folder-relative path when the browser gave\n * us one, otherwise its bare name. Every caller goes through here.\n */\nexport function filePath(file: File): string {\n  return file.webkitRelativePath?.trim() || file.name;\n}\n\n/**\n * The single conversion point from `File` to `ProcessedFile`.\n *\n * `type` is the browser's own report: the platform derives Content-Type\n * server-side from the path, so there is nothing to gain from second-guessing it\n * here. MD5 is Ship's job, during upload.\n */\nexport function createProcessedFile(file: File, options?: { path?: string }): ProcessedFile {\n  const path = options?.path || filePath(file);\n\n  return {\n    id: crypto.randomUUID(),\n    file,\n    path,\n    size: file.size,\n    name: path.split('/').pop() || file.name,\n    type: file.type,\n    lastModified: file.lastModified,\n    status: FileValidationStatus.PENDING,\n  };\n}\n\n/**\n * Strip the common directory prefix from a set of deploy paths.\n *\n * The path algorithm is Ship's `optimizeDeployPaths` — the single source of\n * truth for deploy-path normalization. The stripped path is written back onto\n * each underlying File, because Ship reads `webkitRelativePath` from the raw\n * File objects it is handed.\n */\nexport function stripCommonPrefix(files: ProcessedFile[]): ProcessedFile[] {\n  if (files.length === 0) return files;\n\n  const deployFiles = optimizeDeployPaths(files.map((f) => f.path));\n\n  return files.map((f, i) => {\n    const newPath = deployFiles[i].path;\n    setRelativePath(f.file, newPath);\n    return { ...f, path: newPath, name: newPath.split('/').pop() || f.name };\n  });\n}\n\n/**\n * Stamp a status across a file set.\n *\n * Validation is atomic — every file carries the same verdict — so this is the\n * one place that shape is built.\n */\nexport function applyStatus(\n  files: ProcessedFile[],\n  status: FileValidationStatusType,\n  statusMessage?: string,\n): ProcessedFile[] {\n  return files.map((f) => ({\n    ...f,\n    status,\n    ...(statusMessage === undefined ? {} : { statusMessage }),\n  }));\n}\n","/**\n * What a project sent for building carries: the project as its repository\n * holds it.\n *\n * The build starts from a clean copy of the project, so what a clean copy\n * would not hold stays behind: `node_modules`, which the build installs; `.git`,\n * git's own record, which no checkout lists; `__MACOSX`, the Finder's metadata\n * inside a ZIP made on a Mac, whose `._` files a build that reads a whole folder\n * would trip on; and whatever the project's `.gitignore` lists, which the\n * project itself marks as generated. Everything else is sent, dot files and\n * empty files included: a build reads `.npmrc` and `.vitepress/`, and imports\n * an empty stylesheet, so nothing after this decides again. A `.env` is sent\n * unless the `.gitignore` lists it, like any other file the project holds.\n *\n * The first reason is which site gets published, not size. An old `dist/`\n * beside the source can be found by the build service's output search before\n * the folder the build just wrote, and published in its place. Leaving it out\n * also keeps the upload the size of the source, and keeps a file the project\n * keeps out of git (a key, a service account) on the person's machine. The\n * cost is the one a clean CI checkout has: an app that imports an ignored file\n * fails its build, and the build names the file.\n *\n * `.gitignore` is read the way git reads it. The matching is the `ignore`\n * package's, which follows git's rules, \"a file cannot be re-included if its\n * parent folder is excluded\" among them. It reads one set of patterns, while\n * git reads each `.gitignore` from its own folder, so every file's patterns\n * are rewritten to the root of the drop and added shallowest first: a deeper\n * file then wins, as it does in git. `tests/source.test.ts` holds the result\n * to git itself.\n *\n * Matching ignores case, as git does on the Mac and Windows machines these\n * projects are made on. What git alone can see is not read: its index (a file\n * committed despite `.gitignore` is left out) and `.git/info/exclude`, which\n * no clean copy carries.\n */\nimport ignore from 'ignore';\nimport { filePath } from './files';\n\n/** Folders no clean copy of a project holds (see the header). */\nconst NEVER_SOURCE = new Set(['node_modules', '.git', '__MACOSX']);\n\n/** A file's path as segments, whatever separator the browser or archive used. */\nfunction segments(file: File): string[] {\n  return filePath(file).replace(/\\\\/g, '/').split('/').filter(Boolean);\n}\n\n/**\n * One `.gitignore` line, rewritten from its own folder to the root of the drop.\n * Null for a line that holds no pattern.\n *\n * A pattern with no slash but a trailing one matches at any depth below its\n * folder; any other slash, a leading one included, anchors it to the folder.\n */\nexport function rebase(line: string, base: string): string | null {\n  // Trailing spaces end a pattern unless a backslash escapes the last one.\n  // No lookbehind: Safari parses one only from 16.4, and a bundle carrying one\n  // fails to load before that.\n  const pattern = line.replace(/(\\\\ )? *$/, (_, escaped: string | undefined) => escaped ?? '');\n  if (pattern === '' || pattern.startsWith('#')) return null;\n  if (base === '') return pattern;\n\n  // The folder is a literal path, never a pattern: a name such as `[slug]`,\n  // `#1-app` or `!important` would otherwise be read as glob syntax.\n  const folder = base.replace(/[\\\\*?[\\]]/g, '\\\\$&').replace(/^[#!]/, '\\\\$&');\n  const negated = pattern.startsWith('!');\n  let body = negated ? pattern.slice(1) : pattern;\n  const directoryOnly = body.endsWith('/');\n  if (directoryOnly) body = body.slice(0, -1);\n  // A line such as `!` or `/` names nothing, and git reads it as no pattern.\n  // Rewritten, it would name the whole folder.\n  if (body.replace(/^\\//, '') === '') return null;\n\n  const rebased = body.includes('/')\n    ? `${folder}/${body.replace(/^\\//, '')}`\n    : `${folder}/**/${body}`;\n  return `${negated ? '!' : ''}${rebased}${directoryOnly ? '/' : ''}`;\n}\n\n/**\n * The files of a project sent for building, without `node_modules` and\n * without whatever its `.gitignore` files list. Paths are read as dropped,\n * before the common folder is stripped, so each `.gitignore` applies from its\n * own folder whether the person dropped the repository, a folder holding it,\n * or a folder inside it.\n */\nexport async function projectSource(files: File[]): Promise<File[]> {\n  // What a clean copy never holds, by name; the folder picker hands\n  // `node_modules` over whole, and none of these reaches the matcher.\n  const source = files.filter((file) => !segments(file).some((part) => NEVER_SOURCE.has(part)));\n\n  const rules = source\n    .map((file) => ({ file, parts: segments(file) }))\n    .filter(({ parts }) => parts.at(-1) === '.gitignore')\n    .sort((a, b) => a.parts.length - b.parts.length);\n  if (rules.length === 0) return source;\n\n  const matcher = ignore({ allowRelativePaths: true });\n  for (const { file, parts } of rules) {\n    const base = parts.slice(0, -1).join('/');\n    // A line break ends a pattern and gitignore cannot escape one, so a folder\n    // named with one cannot be written into its rules. Refused rather than\n    // matched wrongly: wrongly means its private files are sent.\n    if (/[\\r\\n]/.test(base)) {\n      throw new Error(\n        \"A folder in this project has a line break in its name, so its .gitignore can't be read. Rename the folder, then try again.\",\n      );\n    }\n    // Git skips a byte order mark and reads CRLF line endings as LF.\n    const text = (await file.text()).replace(/^\\uFEFF/, '');\n    for (const line of text.split(/\\r?\\n/)) {\n      const pattern = rebase(line, base);\n      if (pattern !== null) matcher.add(pattern);\n    }\n  }\n  return source.filter((file) => !matcher.ignores(segments(file).join('/')));\n}\n","// DEFLATE is a complex format; to read this code, you should probably check the RFC first:\n// https://tools.ietf.org/html/rfc1951\n// You may also wish to take a look at the guide I made about this program:\n// https://gist.github.com/101arrowz/253f31eb5abc3d9275ab943003ffecad\n// Some of the following code is similar to that of UZIP.js:\n// https://github.com/photopea/UZIP.js\n// However, the vast majority of the codebase has diverged from UZIP.js to increase performance and reduce bundle size.\n// Sometimes 0 will appear where -1 would be more appropriate. This is because using a uint\n// is better for memory in most engines (I *think*).\nvar ch2 = {};\nvar wk = (function (c, id, msg, transfer, cb) {\n    var w = new Worker(ch2[id] || (ch2[id] = URL.createObjectURL(new Blob([\n        c + ';addEventListener(\"error\",function(e){e=e.error;postMessage({$e$:[e.message,e.code,e.stack]})})'\n    ], { type: 'text/javascript' }))));\n    w.onmessage = function (e) {\n        var d = e.data, ed = d.$e$;\n        if (ed) {\n            var err = new Error(ed[0]);\n            err['code'] = ed[1];\n            err.stack = ed[2];\n            cb(err, null);\n        }\n        else\n            cb(null, d);\n    };\n    w.postMessage(msg, transfer);\n    return w;\n});\n\n// aliases for shorter compressed code (most minifers don't do this)\nvar u8 = Uint8Array, u16 = Uint16Array, i32 = Int32Array;\n// fixed length extra bits\nvar fleb = new u8([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, /* unused */ 0, 0, /* impossible */ 0]);\n// fixed distance extra bits\nvar fdeb = new u8([0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, /* unused */ 0, 0]);\n// code length index map\nvar clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);\n// get base, reverse index map from extra bits\nvar freb = function (eb, start) {\n    var b = new u16(31);\n    for (var i = 0; i < 31; ++i) {\n        b[i] = start += 1 << eb[i - 1];\n    }\n    // numbers here are at max 18 bits\n    var r = new i32(b[30]);\n    for (var i = 1; i < 30; ++i) {\n        for (var j = b[i]; j < b[i + 1]; ++j) {\n            r[j] = ((j - b[i]) << 5) | i;\n        }\n    }\n    return { b: b, r: r };\n};\nvar _a = freb(fleb, 2), fl = _a.b, revfl = _a.r;\n// we can ignore the fact that the other numbers are wrong; they never happen anyway\nfl[28] = 258, revfl[258] = 28;\nvar _b = freb(fdeb, 0), fd = _b.b, revfd = _b.r;\n// map of value to reverse (assuming 16 bits)\nvar rev = new u16(32768);\nfor (var i = 0; i < 32768; ++i) {\n    // reverse table algorithm from SO\n    var x = ((i & 0xAAAA) >> 1) | ((i & 0x5555) << 1);\n    x = ((x & 0xCCCC) >> 2) | ((x & 0x3333) << 2);\n    x = ((x & 0xF0F0) >> 4) | ((x & 0x0F0F) << 4);\n    rev[i] = (((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8)) >> 1;\n}\n// create huffman tree from u8 \"map\": index -> code length for code index\n// mb (max bits) must be at most 15\n// TODO: optimize/split up?\nvar hMap = (function (cd, mb, r) {\n    var s = cd.length;\n    // index\n    var i = 0;\n    // u16 \"map\": index -> # of codes with bit length = index\n    var l = new u16(mb);\n    // length of cd must be 288 (total # of codes)\n    for (; i < s; ++i) {\n        if (cd[i])\n            ++l[cd[i] - 1];\n    }\n    // u16 \"map\": index -> minimum code for bit length = index\n    var le = new u16(mb);\n    for (i = 1; i < mb; ++i) {\n        le[i] = (le[i - 1] + l[i - 1]) << 1;\n    }\n    var co;\n    if (r) {\n        // u16 \"map\": index -> number of actual bits, symbol for code\n        co = new u16(1 << mb);\n        // bits to remove for reverser\n        var rvb = 15 - mb;\n        for (i = 0; i < s; ++i) {\n            // ignore 0 lengths\n            if (cd[i]) {\n                // num encoding both symbol and bits read\n                var sv = (i << 4) | cd[i];\n                // free bits\n                var r_1 = mb - cd[i];\n                // start value\n                var v = le[cd[i] - 1]++ << r_1;\n                // m is end value\n                for (var m = v | ((1 << r_1) - 1); v <= m; ++v) {\n                    // every 16 bit value starting with the code yields the same result\n                    co[rev[v] >> rvb] = sv;\n                }\n            }\n        }\n    }\n    else {\n        co = new u16(s);\n        for (i = 0; i < s; ++i) {\n            if (cd[i]) {\n                co[i] = rev[le[cd[i] - 1]++] >> (15 - cd[i]);\n            }\n        }\n    }\n    return co;\n});\n// fixed length tree\nvar flt = new u8(288);\nfor (var i = 0; i < 144; ++i)\n    flt[i] = 8;\nfor (var i = 144; i < 256; ++i)\n    flt[i] = 9;\nfor (var i = 256; i < 280; ++i)\n    flt[i] = 7;\nfor (var i = 280; i < 288; ++i)\n    flt[i] = 8;\n// fixed distance tree\nvar fdt = new u8(32);\nfor (var i = 0; i < 32; ++i)\n    fdt[i] = 5;\n// fixed length map\nvar flm = /*#__PURE__*/ hMap(flt, 9, 0), flrm = /*#__PURE__*/ hMap(flt, 9, 1);\n// fixed distance map\nvar fdm = /*#__PURE__*/ hMap(fdt, 5, 0), fdrm = /*#__PURE__*/ hMap(fdt, 5, 1);\n// find max of array\nvar max = function (a) {\n    var m = a[0];\n    for (var i = 1; i < a.length; ++i) {\n        if (a[i] > m)\n            m = a[i];\n    }\n    return m;\n};\n// read d, starting at bit p and mask with m\nvar bits = function (d, p, m) {\n    var o = (p / 8) | 0;\n    return ((d[o] | (d[o + 1] << 8)) >> (p & 7)) & m;\n};\n// read d, starting at bit p continuing for at least 16 bits\nvar bits16 = function (d, p) {\n    var o = (p / 8) | 0;\n    return ((d[o] | (d[o + 1] << 8) | (d[o + 2] << 16)) >> (p & 7));\n};\n// get end of byte\nvar shft = function (p) { return ((p + 7) / 8) | 0; };\n// typed array slice - allows garbage collector to free original reference,\n// while being more compatible than .slice\nvar slc = function (v, s, e) {\n    if (s == null || s < 0)\n        s = 0;\n    if (e == null || e > v.length)\n        e = v.length;\n    // can't use .constructor in case user-supplied\n    return new u8(v.subarray(s, e));\n};\n/**\n * Codes for errors generated within this library\n */\nexport var FlateErrorCode = {\n    UnexpectedEOF: 0,\n    InvalidBlockType: 1,\n    InvalidLengthLiteral: 2,\n    InvalidDistance: 3,\n    StreamFinished: 4,\n    NoStreamHandler: 5,\n    InvalidHeader: 6,\n    NoCallback: 7,\n    InvalidUTF8: 8,\n    ExtraFieldTooLong: 9,\n    InvalidDate: 10,\n    FilenameTooLong: 11,\n    StreamFinishing: 12,\n    InvalidZipData: 13,\n    UnknownCompressionMethod: 14\n};\n// error codes\nvar ec = [\n    'unexpected EOF',\n    'invalid block type',\n    'invalid length/literal',\n    'invalid distance',\n    'stream finished',\n    'no stream handler',\n    , // determined by compression function\n    'no callback',\n    'invalid UTF-8 data',\n    'extra field too long',\n    'date not in range 1980-2099',\n    'filename too long',\n    'stream finishing',\n    'invalid zip data'\n    // determined by unknown compression method\n];\n;\nvar err = function (ind, msg, nt) {\n    var e = new Error(msg || ec[ind]);\n    e.code = ind;\n    if (Error.captureStackTrace)\n        Error.captureStackTrace(e, err);\n    if (!nt)\n        throw e;\n    return e;\n};\n// expands raw DEFLATE data\nvar inflt = function (dat, st, buf, dict) {\n    // source length       dict length\n    var sl = dat.length, dl = dict ? dict.length : 0;\n    if (!sl || st.f && !st.l)\n        return buf || new u8(0);\n    var noBuf = !buf;\n    // have to estimate size\n    var resize = noBuf || st.i != 2;\n    // no state\n    var noSt = st.i;\n    // Assumes roughly 33% compression ratio average\n    if (noBuf)\n        buf = new u8(sl * 3);\n    // ensure buffer can fit at least l elements\n    var cbuf = function (l) {\n        var bl = buf.length;\n        // need to increase size to fit\n        if (l > bl) {\n            // Double or set to necessary, whichever is greater\n            var nbuf = new u8(Math.max(bl * 2, l));\n            nbuf.set(buf);\n            buf = nbuf;\n        }\n    };\n    //  last chunk         bitpos           bytes\n    var final = st.f || 0, pos = st.p || 0, bt = st.b || 0, lm = st.l, dm = st.d, lbt = st.m, dbt = st.n;\n    // total bits\n    var tbts = sl * 8;\n    do {\n        if (!lm) {\n            // BFINAL - this is only 1 when last chunk is next\n            final = bits(dat, pos, 1);\n            // type: 0 = no compression, 1 = fixed huffman, 2 = dynamic huffman\n            var type = bits(dat, pos + 1, 3);\n            pos += 3;\n            if (!type) {\n                // go to end of byte boundary\n                var s = shft(pos) + 4, l = dat[s - 4] | (dat[s - 3] << 8), t = s + l;\n                if (t > sl) {\n                    if (noSt)\n                        err(0);\n                    break;\n                }\n                // ensure size\n                if (resize)\n                    cbuf(bt + l);\n                // Copy over uncompressed data\n                buf.set(dat.subarray(s, t), bt);\n                // Get new bitpos, update byte count\n                st.b = bt += l, st.p = pos = t * 8, st.f = final;\n                continue;\n            }\n            else if (type == 1)\n                lm = flrm, dm = fdrm, lbt = 9, dbt = 5;\n            else if (type == 2) {\n                //  literal                            lengths\n                var hLit = bits(dat, pos, 31) + 257, hcLen = bits(dat, pos + 10, 15) + 4;\n                var tl = hLit + bits(dat, pos + 5, 31) + 1;\n                pos += 14;\n                // length+distance tree\n                var ldt = new u8(tl);\n                // code length tree\n                var clt = new u8(19);\n                for (var i = 0; i < hcLen; ++i) {\n                    // use index map to get real code\n                    clt[clim[i]] = bits(dat, pos + i * 3, 7);\n                }\n                pos += hcLen * 3;\n                // code lengths bits\n                var clb = max(clt), clbmsk = (1 << clb) - 1;\n                // code lengths map\n                var clm = hMap(clt, clb, 1);\n                for (var i = 0; i < tl;) {\n                    var r = clm[bits(dat, pos, clbmsk)];\n                    // bits read\n                    pos += r & 15;\n                    // symbol\n                    var s = r >> 4;\n                    // code length to copy\n                    if (s < 16) {\n                        ldt[i++] = s;\n                    }\n                    else {\n                        //  copy   count\n                        var c = 0, n = 0;\n                        if (s == 16)\n                            n = 3 + bits(dat, pos, 3), pos += 2, c = ldt[i - 1];\n                        else if (s == 17)\n                            n = 3 + bits(dat, pos, 7), pos += 3;\n                        else if (s == 18)\n                            n = 11 + bits(dat, pos, 127), pos += 7;\n                        while (n--)\n                            ldt[i++] = c;\n                    }\n                }\n                //    length tree                 distance tree\n                var lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit);\n                // max length bits\n                lbt = max(lt);\n                // max dist bits\n                dbt = max(dt);\n                lm = hMap(lt, lbt, 1);\n                dm = hMap(dt, dbt, 1);\n            }\n            else\n                err(1);\n            if (pos > tbts) {\n                if (noSt)\n                    err(0);\n                break;\n            }\n        }\n        // Make sure the buffer can hold this + the largest possible addition\n        // Maximum chunk size (practically, theoretically infinite) is 2^17\n        if (resize)\n            cbuf(bt + 131072);\n        var lms = (1 << lbt) - 1, dms = (1 << dbt) - 1;\n        var lpos = pos;\n        for (;; lpos = pos) {\n            // bits read, code\n            var c = lm[bits16(dat, pos) & lms], sym = c >> 4;\n            pos += c & 15;\n            if (pos > tbts) {\n                if (noSt)\n                    err(0);\n                break;\n            }\n            if (!c)\n                err(2);\n            if (sym < 256)\n                buf[bt++] = sym;\n            else if (sym == 256) {\n                lpos = pos, lm = null;\n                break;\n            }\n            else {\n                var add = sym - 254;\n                // no extra bits needed if less\n                if (sym > 264) {\n                    // index\n                    var i = sym - 257, b = fleb[i];\n                    add = bits(dat, pos, (1 << b) - 1) + fl[i];\n                    pos += b;\n                }\n                // dist\n                var d = dm[bits16(dat, pos) & dms], dsym = d >> 4;\n                if (!d)\n                    err(3);\n                pos += d & 15;\n                var dt = fd[dsym];\n                if (dsym > 3) {\n                    var b = fdeb[dsym];\n                    dt += bits16(dat, pos) & (1 << b) - 1, pos += b;\n                }\n                if (pos > tbts) {\n                    if (noSt)\n                        err(0);\n                    break;\n                }\n                if (resize)\n                    cbuf(bt + 131072);\n                var end = bt + add;\n                if (bt < dt) {\n                    var shift = dl - dt, dend = Math.min(dt, end);\n                    if (shift + bt < 0)\n                        err(3);\n                    for (; bt < dend; ++bt)\n                        buf[bt] = dict[shift + bt];\n                }\n                for (; bt < end; ++bt)\n                    buf[bt] = buf[bt - dt];\n            }\n        }\n        st.l = lm, st.p = lpos, st.b = bt, st.f = final;\n        if (lm)\n            final = 1, st.m = lbt, st.d = dm, st.n = dbt;\n    } while (!final);\n    // don't reallocate for streams or user buffers\n    return bt != buf.length && noBuf ? slc(buf, 0, bt) : buf.subarray(0, bt);\n};\n// starting at p, write the minimum number of bits that can hold v to d\nvar wbits = function (d, p, v) {\n    v <<= p & 7;\n    var o = (p / 8) | 0;\n    d[o] |= v;\n    d[o + 1] |= v >> 8;\n};\n// starting at p, write the minimum number of bits (>8) that can hold v to d\nvar wbits16 = function (d, p, v) {\n    v <<= p & 7;\n    var o = (p / 8) | 0;\n    d[o] |= v;\n    d[o + 1] |= v >> 8;\n    d[o + 2] |= v >> 16;\n};\n// creates code lengths from a frequency table\nvar hTree = function (d, mb) {\n    // Need extra info to make a tree\n    var t = [];\n    for (var i = 0; i < d.length; ++i) {\n        if (d[i])\n            t.push({ s: i, f: d[i] });\n    }\n    var s = t.length;\n    var t2 = t.slice();\n    if (!s)\n        return { t: et, l: 0 };\n    if (s == 1) {\n        var v = new u8(t[0].s + 1);\n        v[t[0].s] = 1;\n        return { t: v, l: 1 };\n    }\n    t.sort(function (a, b) { return a.f - b.f; });\n    // after i2 reaches last ind, will be stopped\n    // freq must be greater than largest possible number of symbols\n    t.push({ s: -1, f: 25001 });\n    var l = t[0], r = t[1], i0 = 0, i1 = 1, i2 = 2;\n    t[0] = { s: -1, f: l.f + r.f, l: l, r: r };\n    // efficient algorithm from UZIP.js\n    // i0 is lookbehind, i2 is lookahead - after processing two low-freq\n    // symbols that combined have high freq, will start processing i2 (high-freq,\n    // non-composite) symbols instead\n    // see https://reddit.com/r/photopea/comments/ikekht/uzipjs_questions/\n    while (i1 != s - 1) {\n        l = t[t[i0].f < t[i2].f ? i0++ : i2++];\n        r = t[i0 != i1 && t[i0].f < t[i2].f ? i0++ : i2++];\n        t[i1++] = { s: -1, f: l.f + r.f, l: l, r: r };\n    }\n    var maxSym = t2[0].s;\n    for (var i = 1; i < s; ++i) {\n        if (t2[i].s > maxSym)\n            maxSym = t2[i].s;\n    }\n    // code lengths\n    var tr = new u16(maxSym + 1);\n    // max bits in tree\n    var mbt = ln(t[i1 - 1], tr, 0);\n    if (mbt > mb) {\n        // more algorithms from UZIP.js\n        // TODO: find out how this code works (debt)\n        //  ind    debt\n        var i = 0, dt = 0;\n        //    left            cost\n        var lft = mbt - mb, cst = 1 << lft;\n        t2.sort(function (a, b) { return tr[b.s] - tr[a.s] || a.f - b.f; });\n        for (; i < s; ++i) {\n            var i2_1 = t2[i].s;\n            if (tr[i2_1] > mb) {\n                dt += cst - (1 << (mbt - tr[i2_1]));\n                tr[i2_1] = mb;\n            }\n            else\n                break;\n        }\n        dt >>= lft;\n        while (dt > 0) {\n            var i2_2 = t2[i].s;\n            if (tr[i2_2] < mb)\n                dt -= 1 << (mb - tr[i2_2]++ - 1);\n            else\n                ++i;\n        }\n        for (; i >= 0 && dt; --i) {\n            var i2_3 = t2[i].s;\n            if (tr[i2_3] == mb) {\n                --tr[i2_3];\n                ++dt;\n            }\n        }\n        mbt = mb;\n    }\n    return { t: new u8(tr), l: mbt };\n};\n// get the max length and assign length codes\nvar ln = function (n, l, d) {\n    return n.s == -1\n        ? Math.max(ln(n.l, l, d + 1), ln(n.r, l, d + 1))\n        : (l[n.s] = d);\n};\n// length codes generation\nvar lc = function (c) {\n    var s = c.length;\n    // Note that the semicolon was intentional\n    while (s && !c[--s])\n        ;\n    var cl = new u16(++s);\n    //  ind      num         streak\n    var cli = 0, cln = c[0], cls = 1;\n    var w = function (v) { cl[cli++] = v; };\n    for (var i = 1; i <= s; ++i) {\n        if (c[i] == cln && i != s)\n            ++cls;\n        else {\n            if (!cln && cls > 2) {\n                for (; cls > 138; cls -= 138)\n                    w(32754);\n                if (cls > 2) {\n                    w(cls > 10 ? ((cls - 11) << 5) | 28690 : ((cls - 3) << 5) | 12305);\n                    cls = 0;\n                }\n            }\n            else if (cls > 3) {\n                w(cln), --cls;\n                for (; cls > 6; cls -= 6)\n                    w(8304);\n                if (cls > 2)\n                    w(((cls - 3) << 5) | 8208), cls = 0;\n            }\n            while (cls--)\n                w(cln);\n            cls = 1;\n            cln = c[i];\n        }\n    }\n    return { c: cl.subarray(0, cli), n: s };\n};\n// calculate the length of output from tree, code lengths\nvar clen = function (cf, cl) {\n    var l = 0;\n    for (var i = 0; i < cl.length; ++i)\n        l += cf[i] * cl[i];\n    return l;\n};\n// writes a fixed block\n// returns the new bit pos\nvar wfblk = function (out, pos, dat) {\n    // no need to write 00 as type: TypedArray defaults to 0\n    var s = dat.length;\n    var o = shft(pos + 2);\n    out[o] = s & 255;\n    out[o + 1] = s >> 8;\n    out[o + 2] = out[o] ^ 255;\n    out[o + 3] = out[o + 1] ^ 255;\n    for (var i = 0; i < s; ++i)\n        out[o + i + 4] = dat[i];\n    return (o + 4 + s) * 8;\n};\n// writes a block\nvar wblk = function (dat, out, final, syms, lf, df, eb, li, bs, bl, p) {\n    wbits(out, p++, final);\n    ++lf[256];\n    var _a = hTree(lf, 15), dlt = _a.t, mlb = _a.l;\n    var _b = hTree(df, 15), ddt = _b.t, mdb = _b.l;\n    var _c = lc(dlt), lclt = _c.c, nlc = _c.n;\n    var _d = lc(ddt), lcdt = _d.c, ndc = _d.n;\n    var lcfreq = new u16(19);\n    for (var i = 0; i < lclt.length; ++i)\n        ++lcfreq[lclt[i] & 31];\n    for (var i = 0; i < lcdt.length; ++i)\n        ++lcfreq[lcdt[i] & 31];\n    var _e = hTree(lcfreq, 7), lct = _e.t, mlcb = _e.l;\n    var nlcc = 19;\n    for (; nlcc > 4 && !lct[clim[nlcc - 1]]; --nlcc)\n        ;\n    var flen = (bl + 5) << 3;\n    var ftlen = clen(lf, flt) + clen(df, fdt) + eb;\n    var dtlen = clen(lf, dlt) + clen(df, ddt) + eb + 14 + 3 * nlcc + clen(lcfreq, lct) + 2 * lcfreq[16] + 3 * lcfreq[17] + 7 * lcfreq[18];\n    if (bs >= 0 && flen <= ftlen && flen <= dtlen)\n        return wfblk(out, p, dat.subarray(bs, bs + bl));\n    var lm, ll, dm, dl;\n    wbits(out, p, 1 + (dtlen < ftlen)), p += 2;\n    if (dtlen < ftlen) {\n        lm = hMap(dlt, mlb, 0), ll = dlt, dm = hMap(ddt, mdb, 0), dl = ddt;\n        var llm = hMap(lct, mlcb, 0);\n        wbits(out, p, nlc - 257);\n        wbits(out, p + 5, ndc - 1);\n        wbits(out, p + 10, nlcc - 4);\n        p += 14;\n        for (var i = 0; i < nlcc; ++i)\n            wbits(out, p + 3 * i, lct[clim[i]]);\n        p += 3 * nlcc;\n        var lcts = [lclt, lcdt];\n        for (var it = 0; it < 2; ++it) {\n            var clct = lcts[it];\n            for (var i = 0; i < clct.length; ++i) {\n                var len = clct[i] & 31;\n                wbits(out, p, llm[len]), p += lct[len];\n                if (len > 15)\n                    wbits(out, p, (clct[i] >> 5) & 127), p += clct[i] >> 12;\n            }\n        }\n    }\n    else {\n        lm = flm, ll = flt, dm = fdm, dl = fdt;\n    }\n    for (var i = 0; i < li; ++i) {\n        var sym = syms[i];\n        if (sym > 255) {\n            var len = (sym >> 18) & 31;\n            wbits16(out, p, lm[len + 257]), p += ll[len + 257];\n            if (len > 7)\n                wbits(out, p, (sym >> 23) & 31), p += fleb[len];\n            var dst = sym & 31;\n            wbits16(out, p, dm[dst]), p += dl[dst];\n            if (dst > 3)\n                wbits16(out, p, (sym >> 5) & 8191), p += fdeb[dst];\n        }\n        else {\n            wbits16(out, p, lm[sym]), p += ll[sym];\n        }\n    }\n    wbits16(out, p, lm[256]);\n    return p + ll[256];\n};\n// deflate options (nice << 13) | chain\nvar deo = /*#__PURE__*/ new i32([65540, 131080, 131088, 131104, 262176, 1048704, 1048832, 2114560, 2117632]);\n// empty\nvar et = /*#__PURE__*/ new u8(0);\n// compresses data into a raw DEFLATE buffer\nvar dflt = function (dat, lvl, plvl, pre, post, st) {\n    var s = st.z || dat.length;\n    var o = new u8(pre + s + 5 * (1 + Math.ceil(s / 7000)) + post);\n    // writing to this writes to the output buffer\n    var w = o.subarray(pre, o.length - post);\n    var lst = st.l;\n    var pos = (st.r || 0) & 7;\n    if (lvl) {\n        if (pos)\n            w[0] = st.r >> 3;\n        var opt = deo[lvl - 1];\n        var n = opt >> 13, c = opt & 8191;\n        var msk_1 = (1 << plvl) - 1;\n        //    prev 2-byte val map    curr 2-byte val map\n        var prev = st.p || new u16(32768), head = st.h || new u16(msk_1 + 1);\n        var bs1_1 = Math.ceil(plvl / 3), bs2_1 = 2 * bs1_1;\n        var hsh = function (i) { return (dat[i] ^ (dat[i + 1] << bs1_1) ^ (dat[i + 2] << bs2_1)) & msk_1; };\n        // 24576 is an arbitrary number of maximum symbols per block\n        // 424 buffer for last block\n        var syms = new i32(25000);\n        // length/literal freq   distance freq\n        var lf = new u16(288), df = new u16(32);\n        //  l/lcnt  exbits  index          l/lind  waitdx          blkpos\n        var lc_1 = 0, eb = 0, i = st.i || 0, li = 0, wi = st.w || 0, bs = 0;\n        for (; i + 2 < s; ++i) {\n            // hash value\n            var hv = hsh(i);\n            // index mod 32768    previous index mod\n            var imod = i & 32767, pimod = head[hv];\n            prev[imod] = pimod;\n            head[hv] = imod;\n            // We always should modify head and prev, but only add symbols if\n            // this data is not yet processed (\"wait\" for wait index)\n            if (wi <= i) {\n                // bytes remaining\n                var rem = s - i;\n                if ((lc_1 > 7000 || li > 24576) && (rem > 423 || !lst)) {\n                    pos = wblk(dat, w, 0, syms, lf, df, eb, li, bs, i - bs, pos);\n                    li = lc_1 = eb = 0, bs = i;\n                    for (var j = 0; j < 286; ++j)\n                        lf[j] = 0;\n                    for (var j = 0; j < 30; ++j)\n                        df[j] = 0;\n                }\n                //  len    dist   chain\n                var l = 2, d = 0, ch_1 = c, dif = imod - pimod & 32767;\n                if (rem > 2 && hv == hsh(i - dif)) {\n                    var maxn = Math.min(n, rem) - 1;\n                    var maxd = Math.min(32767, i);\n                    // max possible length\n                    // not capped at dif because decompressors implement \"rolling\" index population\n                    var ml = Math.min(258, rem);\n                    while (dif <= maxd && --ch_1 && imod != pimod) {\n                        if (dat[i + l] == dat[i + l - dif]) {\n                            var nl = 0;\n                            for (; nl < ml && dat[i + nl] == dat[i + nl - dif]; ++nl)\n                                ;\n                            if (nl > l) {\n                                l = nl, d = dif;\n                                // break out early when we reach \"nice\" (we are satisfied enough)\n                                if (nl > maxn)\n                                    break;\n                                // now, find the rarest 2-byte sequence within this\n                                // length of literals and search for that instead.\n                                // Much faster than just using the start\n                                var mmd = Math.min(dif, nl - 2);\n                                var md = 0;\n                                for (var j = 0; j < mmd; ++j) {\n                                    var ti = i - dif + j & 32767;\n                                    var pti = prev[ti];\n                                    var cd = ti - pti & 32767;\n                                    if (cd > md)\n                                        md = cd, pimod = ti;\n                                }\n                            }\n                        }\n                        // check the previous match\n                        imod = pimod, pimod = prev[imod];\n                        dif += imod - pimod & 32767;\n                    }\n                }\n                // d will be nonzero only when a match was found\n                if (d) {\n                    // store both dist and len data in one int32\n                    // Make sure this is recognized as a len/dist with 28th bit (2^28)\n                    syms[li++] = 268435456 | (revfl[l] << 18) | revfd[d];\n                    var lin = revfl[l] & 31, din = revfd[d] & 31;\n                    eb += fleb[lin] + fdeb[din];\n                    ++lf[257 + lin];\n                    ++df[din];\n                    wi = i + l;\n                    ++lc_1;\n                }\n                else {\n                    syms[li++] = dat[i];\n                    ++lf[dat[i]];\n                }\n            }\n        }\n        for (i = Math.max(i, wi); i < s; ++i) {\n            syms[li++] = dat[i];\n            ++lf[dat[i]];\n        }\n        pos = wblk(dat, w, lst, syms, lf, df, eb, li, bs, i - bs, pos);\n        if (!lst) {\n            st.r = (pos & 7) | w[(pos / 8) | 0] << 3;\n            // shft(pos) now 1 less if pos & 7 != 0\n            pos -= 7;\n            st.h = head, st.p = prev, st.i = i, st.w = wi;\n        }\n    }\n    else {\n        for (var i = st.w || 0; i < s + lst; i += 65535) {\n            // end\n            var e = i + 65535;\n            if (e >= s) {\n                // write final block\n                w[(pos / 8) | 0] = lst;\n                e = s;\n            }\n            pos = wfblk(w, pos + 1, dat.subarray(i, e));\n        }\n        st.i = s;\n    }\n    return slc(o, 0, pre + shft(pos) + post);\n};\n// CRC32 table\nvar crct = /*#__PURE__*/ (function () {\n    var t = new Int32Array(256);\n    for (var i = 0; i < 256; ++i) {\n        var c = i, k = 9;\n        while (--k)\n            c = ((c & 1) && -306674912) ^ (c >>> 1);\n        t[i] = c;\n    }\n    return t;\n})();\n// CRC32\nvar crc = function () {\n    var c = -1;\n    return {\n        p: function (d) {\n            // closures have awful performance\n            var cr = c;\n            for (var i = 0; i < d.length; ++i)\n                cr = crct[(cr & 255) ^ d[i]] ^ (cr >>> 8);\n            c = cr;\n        },\n        d: function () { return ~c; }\n    };\n};\n// Adler32\nvar adler = function () {\n    var a = 1, b = 0;\n    return {\n        p: function (d) {\n            // closures have awful performance\n            var n = a, m = b;\n            var l = d.length | 0;\n            for (var i = 0; i != l;) {\n                var e = Math.min(i + 2655, l);\n                for (; i < e; ++i)\n                    m += n += d[i];\n                n = (n & 65535) + 15 * (n >> 16), m = (m & 65535) + 15 * (m >> 16);\n            }\n            a = n, b = m;\n        },\n        d: function () {\n            a %= 65521, b %= 65521;\n            return (a & 255) << 24 | (a & 0xFF00) << 8 | (b & 255) << 8 | (b >> 8);\n        }\n    };\n};\n;\n// deflate with opts\nvar dopt = function (dat, opt, pre, post, st) {\n    if (!st) {\n        st = { l: 1 };\n        if (opt.dictionary) {\n            var dict = opt.dictionary.subarray(-32768);\n            var newDat = new u8(dict.length + dat.length);\n            newDat.set(dict);\n            newDat.set(dat, dict.length);\n            dat = newDat;\n            st.w = dict.length;\n        }\n    }\n    return dflt(dat, opt.level == null ? 6 : opt.level, opt.mem == null ? (st.l ? Math.ceil(Math.max(8, Math.min(13, Math.log(dat.length))) * 1.5) : 20) : (12 + opt.mem), pre, post, st);\n};\n// Walmart object spread\nvar mrg = function (a, b) {\n    var o = {};\n    for (var k in a)\n        o[k] = a[k];\n    for (var k in b)\n        o[k] = b[k];\n    return o;\n};\n// worker clone\n// This is possibly the craziest part of the entire codebase, despite how simple it may seem.\n// The only parameter to this function is a closure that returns an array of variables outside of the function scope.\n// We're going to try to figure out the variable names used in the closure as strings because that is crucial for workerization.\n// We will return an object mapping of true variable name to value (basically, the current scope as a JS object).\n// The reason we can't just use the original variable names is minifiers mangling the toplevel scope.\n// This took me three weeks to figure out how to do.\nvar wcln = function (fn, fnStr, td) {\n    var dt = fn();\n    var st = fn.toString();\n    var ks = st.slice(st.indexOf('[') + 1, st.lastIndexOf(']')).replace(/\\s+/g, '').split(',');\n    for (var i = 0; i < dt.length; ++i) {\n        var v = dt[i], k = ks[i];\n        if (typeof v == 'function') {\n            fnStr += ';' + k + '=';\n            var st_1 = v.toString();\n            if (v.prototype) {\n                // for global objects\n                if (st_1.indexOf('[native code]') != -1) {\n                    var spInd = st_1.indexOf(' ', 8) + 1;\n                    fnStr += st_1.slice(spInd, st_1.indexOf('(', spInd));\n                }\n                else {\n                    fnStr += st_1;\n                    for (var t in v.prototype)\n                        fnStr += ';' + k + '.prototype.' + t + '=' + v.prototype[t].toString();\n                }\n            }\n            else\n                fnStr += st_1;\n        }\n        else\n            td[k] = v;\n    }\n    return fnStr;\n};\nvar ch = [];\n// clone bufs\nvar cbfs = function (v) {\n    var tl = [];\n    for (var k in v) {\n        if (v[k].buffer) {\n            tl.push((v[k] = new v[k].constructor(v[k])).buffer);\n        }\n    }\n    return tl;\n};\n// use a worker to execute code\nvar wrkr = function (fns, init, id, cb) {\n    if (!ch[id]) {\n        var fnStr = '', td_1 = {}, m = fns.length - 1;\n        for (var i = 0; i < m; ++i)\n            fnStr = wcln(fns[i], fnStr, td_1);\n        ch[id] = { c: wcln(fns[m], fnStr, td_1), e: td_1 };\n    }\n    var td = mrg({}, ch[id].e);\n    return wk(ch[id].c + ';onmessage=function(e){for(var k in e.data)self[k]=e.data[k];onmessage=' + init.toString() + '}', id, td, cbfs(td), cb);\n};\n// base async inflate fn\nvar bInflt = function () { return [u8, u16, i32, fleb, fdeb, clim, fl, fd, flrm, fdrm, rev, ec, hMap, max, bits, bits16, shft, slc, err, inflt, inflateSync, pbf, gopt]; };\nvar bDflt = function () { return [u8, u16, i32, fleb, fdeb, clim, revfl, revfd, flm, flt, fdm, fdt, rev, deo, et, hMap, wbits, wbits16, hTree, ln, lc, clen, wfblk, wblk, shft, slc, dflt, dopt, deflateSync, pbf]; };\n// gzip extra\nvar gze = function () { return [gzh, gzhl, wbytes, crc, crct]; };\n// gunzip extra\nvar guze = function () { return [gzs, gzl]; };\n// zlib extra\nvar zle = function () { return [zlh, wbytes, adler]; };\n// unzlib extra\nvar zule = function () { return [zls]; };\n// post buf\nvar pbf = function (msg) { return postMessage(msg, [msg.buffer]); };\n// get opts\nvar gopt = function (o) { return o && {\n    out: o.size && new u8(o.size),\n    dictionary: o.dictionary\n}; };\n// async helper\nvar cbify = function (dat, opts, fns, init, id, cb) {\n    var w = wrkr(fns, init, id, function (err, dat) {\n        w.terminate();\n        cb(err, dat);\n    });\n    w.postMessage([dat, opts], opts.consume ? [dat.buffer] : []);\n    return function () { w.terminate(); };\n};\n// auto stream\nvar astrm = function (strm) {\n    strm.ondata = function (dat, final) { return postMessage([dat, final], [dat.buffer]); };\n    return function (ev) {\n        if (ev.data[0]) {\n            strm.push(ev.data[0], ev.data[1]);\n            postMessage([ev.data[0].length]);\n        }\n        else\n            strm.flush(ev.data[1]);\n    };\n};\n// async stream attach\nvar astrmify = function (fns, strm, opts, init, id, flush, ext) {\n    var t;\n    var w = wrkr(fns, init, id, function (err, dat) {\n        if (err)\n            w.terminate(), strm.ondata.call(strm, err);\n        else if (!Array.isArray(dat))\n            ext(dat);\n        else if (dat.length == 1) {\n            strm.queuedSize -= dat[0];\n            if (strm.ondrain)\n                strm.ondrain(dat[0]);\n        }\n        else {\n            if (dat[1])\n                w.terminate();\n            strm.ondata.call(strm, err, dat[0], dat[1]);\n        }\n    });\n    w.postMessage(opts);\n    strm.queuedSize = 0;\n    strm.push = function (d, f) {\n        if (!strm.ondata)\n            err(5);\n        if (t)\n            strm.ondata(err(4, 0, 1), null, !!f);\n        strm.queuedSize += d.length;\n        // can fail for cross-realm Uint8Array, but ok - only a small performance penalty\n        w.postMessage([d, t = f], d.buffer instanceof ArrayBuffer ? [d.buffer] : []);\n    };\n    strm.terminate = function () { w.terminate(); };\n    if (flush) {\n        strm.flush = function (sync) { w.postMessage([0, sync]); };\n    }\n};\n// read 2 bytes\nvar b2 = function (d, b) { return d[b] | (d[b + 1] << 8); };\n// read 4 bytes\nvar b4 = function (d, b) { return (d[b] | (d[b + 1] << 8) | (d[b + 2] << 16) | (d[b + 3] << 24)) >>> 0; };\n// read 8 bytes\nvar b8 = function (d, b) { return b4(d, b) + (b4(d, b + 4) * 4294967296); };\n// write bytes\nvar wbytes = function (d, b, v) {\n    for (; v; ++b)\n        d[b] = v, v >>>= 8;\n};\n// gzip header\nvar gzh = function (c, o) {\n    var fn = o.filename;\n    c[0] = 31, c[1] = 139, c[2] = 8, c[8] = o.level < 2 ? 4 : o.level == 9 ? 2 : 0, c[9] = 3; // assume Unix\n    if (o.mtime != 0)\n        wbytes(c, 4, Math.floor(new Date(o.mtime || Date.now()) / 1000));\n    if (fn) {\n        c[3] = 8;\n        for (var i = 0; i <= fn.length; ++i)\n            c[i + 10] = fn.charCodeAt(i);\n    }\n};\n// gzip footer: -8 to -4 = CRC, -4 to -0 is length\n// gzip start\nvar gzs = function (d) {\n    if (d[0] != 31 || d[1] != 139 || d[2] != 8)\n        err(6, 'invalid gzip data');\n    var flg = d[3];\n    var st = 10;\n    if (flg & 4)\n        st += (d[10] | d[11] << 8) + 2;\n    for (var zs = (flg >> 3 & 1) + (flg >> 4 & 1); zs > 0; zs -= !d[st++])\n        ;\n    return st + (flg & 2);\n};\n// gzip length\nvar gzl = function (d) {\n    var l = d.length;\n    return (d[l - 4] | d[l - 3] << 8 | d[l - 2] << 16 | d[l - 1] << 24) >>> 0;\n};\n// gzip header length\nvar gzhl = function (o) { return 10 + (o.filename ? o.filename.length + 1 : 0); };\n// zlib header\nvar zlh = function (c, o) {\n    var lv = o.level, fl = lv == 0 ? 0 : lv < 6 ? 1 : lv == 9 ? 3 : 2;\n    c[0] = 120, c[1] = (fl << 6) | (o.dictionary && 32);\n    c[1] |= 31 - ((c[0] << 8) | c[1]) % 31;\n    if (o.dictionary) {\n        var h = adler();\n        h.p(o.dictionary);\n        wbytes(c, 2, h.d());\n    }\n};\n// zlib start\nvar zls = function (d, dict) {\n    if ((d[0] & 15) != 8 || (d[0] >> 4) > 7 || ((d[0] << 8 | d[1]) % 31))\n        err(6, 'invalid zlib data');\n    if ((d[1] >> 5 & 1) == +!dict)\n        err(6, 'invalid zlib data: ' + (d[1] & 32 ? 'need' : 'unexpected') + ' dictionary');\n    return (d[1] >> 3 & 4) + 2;\n};\nfunction StrmOpt(opts, cb) {\n    if (typeof opts == 'function')\n        cb = opts, opts = {};\n    this.ondata = cb;\n    return opts;\n}\n/**\n * Streaming DEFLATE compression\n */\nvar Deflate = /*#__PURE__*/ (function () {\n    function Deflate(opts, cb) {\n        if (typeof opts == 'function')\n            cb = opts, opts = {};\n        this.ondata = cb;\n        this.o = opts || {};\n        this.s = { l: 0, i: 32768, w: 32768, z: 32768 };\n        // Buffer length must always be 0 mod 32768 for index calculations to be correct when modifying head and prev\n        // 98304 = 32768 (lookback) + 65536 (common chunk size)\n        this.b = new u8(98304);\n        if (this.o.dictionary) {\n            var dict = this.o.dictionary.subarray(-32768);\n            this.b.set(dict, 32768 - dict.length);\n            this.s.i = 32768 - dict.length;\n        }\n    }\n    Deflate.prototype.p = function (c, f) {\n        this.ondata(dopt(c, this.o, 0, 0, this.s), f);\n    };\n    /**\n     * Pushes a chunk to be deflated\n     * @param chunk The chunk to push\n     * @param final Whether this is the last chunk\n     */\n    Deflate.prototype.push = function (chunk, final) {\n        if (!this.ondata)\n            err(5);\n        if (this.s.l)\n            err(4);\n        var endLen = chunk.length + this.s.z;\n        if (endLen > this.b.length) {\n            if (endLen > 2 * this.b.length - 32768) {\n                var newBuf = new u8(endLen & -32768);\n                newBuf.set(this.b.subarray(0, this.s.z));\n                this.b = newBuf;\n            }\n            var split = this.b.length - this.s.z;\n            this.b.set(chunk.subarray(0, split), this.s.z);\n            this.s.z = this.b.length;\n            this.p(this.b, false);\n            this.b.set(this.b.subarray(-32768));\n            this.b.set(chunk.subarray(split), 32768);\n            this.s.z = chunk.length - split + 32768;\n            this.s.i = 32766, this.s.w = 32768;\n        }\n        else {\n            this.b.set(chunk, this.s.z);\n            this.s.z += chunk.length;\n        }\n        this.s.l = final & 1;\n        if (this.s.z > this.s.w + 8191 || final) {\n            this.p(this.b, final || false);\n            this.s.w = this.s.i, this.s.i -= 2;\n        }\n        if (final) {\n            // cleanup unneeded buffers/state to reduce memory usage\n            this.s = this.o = {};\n            this.b = et;\n        }\n    };\n    /**\n     * Flushes buffered uncompressed data. Useful to immediately retrieve the\n     * deflated output for small inputs.\n     * @param sync Whether to flush to a byte boundary. A sync flush takes 4-5\n     *             extra bytes, but guarantees all pushed data is immediately\n     *             decompressible. A separate DEFLATE stream may be concatenated\n     *             with the current output after a sync flush.\n     */\n    Deflate.prototype.flush = function (sync) {\n        if (!this.ondata)\n            err(5);\n        if (this.s.l)\n            err(4);\n        this.p(this.b, false);\n        this.s.w = this.s.i, this.s.i -= 2;\n        // could technically skip writing the type-0 block for (this.s.r & 7) == 0,\n        // but the deterministic trailer (00 00 FF FF) is useful in some situations\n        if (sync) {\n            var c = new u8(6);\n            c[0] = this.s.r >> 3;\n            // write empty, non-final type-0 block\n            var ep = wfblk(c, this.s.r, et);\n            this.s.r = 0;\n            this.ondata(c.subarray(0, ep >> 3), false);\n        }\n    };\n    return Deflate;\n}());\nexport { Deflate };\n/**\n * Asynchronous streaming DEFLATE compression\n */\nvar AsyncDeflate = /*#__PURE__*/ (function () {\n    function AsyncDeflate(opts, cb) {\n        astrmify([\n            bDflt,\n            function () { return [astrm, Deflate]; }\n        ], this, StrmOpt.call(this, opts, cb), function (ev) {\n            var strm = new Deflate(ev.data);\n            onmessage = astrm(strm);\n        }, 6, 1);\n    }\n    return AsyncDeflate;\n}());\nexport { AsyncDeflate };\nexport function deflate(data, opts, cb) {\n    if (!cb)\n        cb = opts, opts = {};\n    if (typeof cb != 'function')\n        err(7);\n    return cbify(data, opts, [\n        bDflt,\n    ], function (ev) { return pbf(deflateSync(ev.data[0], ev.data[1])); }, 0, cb);\n}\n/**\n * Compresses data with DEFLATE without any wrapper\n * @param data The data to compress\n * @param opts The compression options\n * @returns The deflated version of the data\n */\nexport function deflateSync(data, opts) {\n    return dopt(data, opts || {}, 0, 0);\n}\n/**\n * Streaming DEFLATE decompression\n */\nvar Inflate = /*#__PURE__*/ (function () {\n    function Inflate(opts, cb) {\n        // no StrmOpt here to avoid adding to workerizer\n        if (typeof opts == 'function')\n            cb = opts, opts = {};\n        this.ondata = cb;\n        var dict = opts && opts.dictionary && opts.dictionary.subarray(-32768);\n        this.s = { i: 0, b: dict ? dict.length : 0 };\n        this.o = new u8(32768);\n        this.p = new u8(0);\n        if (dict)\n            this.o.set(dict);\n    }\n    Inflate.prototype.e = function (c) {\n        if (!this.ondata)\n            err(5);\n        if (this.d)\n            err(4);\n        if (!this.p.length)\n            this.p = c;\n        else if (c.length) {\n            var n = new u8(this.p.length + c.length);\n            n.set(this.p), n.set(c, this.p.length), this.p = n;\n        }\n    };\n    Inflate.prototype.c = function (final) {\n        this.s.i = +(this.d = final || false);\n        var bts = this.s.b;\n        var dt = inflt(this.p, this.s, this.o);\n        this.ondata(slc(dt, bts, this.s.b), this.d);\n        this.o = slc(dt, this.s.b - 32768), this.s.b = this.o.length;\n        this.p = slc(this.p, (this.s.p / 8) | 0), this.s.p &= 7;\n    };\n    /**\n     * Pushes a chunk to be inflated\n     * @param chunk The chunk to push\n     * @param final Whether this is the final chunk\n     */\n    Inflate.prototype.push = function (chunk, final) {\n        this.e(chunk), this.c(final);\n    };\n    return Inflate;\n}());\nexport { Inflate };\n/**\n * Asynchronous streaming DEFLATE decompression\n */\nvar AsyncInflate = /*#__PURE__*/ (function () {\n    function AsyncInflate(opts, cb) {\n        astrmify([\n            bInflt,\n            function () { return [astrm, Inflate]; }\n        ], this, StrmOpt.call(this, opts, cb), function (ev) {\n            var strm = new Inflate(ev.data);\n            onmessage = astrm(strm);\n        }, 7, 0);\n    }\n    return AsyncInflate;\n}());\nexport { AsyncInflate };\nexport function inflate(data, opts, cb) {\n    if (!cb)\n        cb = opts, opts = {};\n    if (typeof cb != 'function')\n        err(7);\n    return cbify(data, opts, [\n        bInflt\n    ], function (ev) { return pbf(inflateSync(ev.data[0], gopt(ev.data[1]))); }, 1, cb);\n}\nexport function inflateSync(data, opts) {\n    return inflt(data, { i: 2 }, opts && opts.out, opts && opts.dictionary);\n}\n// before you yell at me for not just using extends, my reason is that TS inheritance is hard to workerize.\n/**\n * Streaming GZIP compression\n */\nvar Gzip = /*#__PURE__*/ (function () {\n    function Gzip(opts, cb) {\n        this.c = crc();\n        this.l = 0;\n        this.v = 1;\n        Deflate.call(this, opts, cb);\n    }\n    /**\n     * Pushes a chunk to be GZIPped\n     * @param chunk The chunk to push\n     * @param final Whether this is the last chunk\n     */\n    Gzip.prototype.push = function (chunk, final) {\n        this.c.p(chunk);\n        this.l += chunk.length;\n        Deflate.prototype.push.call(this, chunk, final);\n    };\n    Gzip.prototype.p = function (c, f) {\n        var raw = dopt(c, this.o, this.v && gzhl(this.o), f && 8, this.s);\n        if (this.v)\n            gzh(raw, this.o), this.v = 0;\n        if (f)\n            wbytes(raw, raw.length - 8, this.c.d()), wbytes(raw, raw.length - 4, this.l);\n        this.ondata(raw, f);\n    };\n    /**\n     * Flushes buffered uncompressed data. Useful to immediately retrieve the\n     * GZIPped output for small inputs.\n     * @param sync Whether to flush to a byte boundary. A sync flush takes 4-5\n     *             extra bytes, but guarantees all pushed data is immediately\n     *             decompressible.\n     */\n    Gzip.prototype.flush = function (sync) {\n        Deflate.prototype.flush.call(this, sync);\n    };\n    return Gzip;\n}());\nexport { Gzip };\n/**\n * Asynchronous streaming GZIP compression\n */\nvar AsyncGzip = /*#__PURE__*/ (function () {\n    function AsyncGzip(opts, cb) {\n        astrmify([\n            bDflt,\n            gze,\n            function () { return [astrm, Deflate, Gzip]; }\n        ], this, StrmOpt.call(this, opts, cb), function (ev) {\n            var strm = new Gzip(ev.data);\n            onmessage = astrm(strm);\n        }, 8, 1);\n    }\n    return AsyncGzip;\n}());\nexport { AsyncGzip };\nexport function gzip(data, opts, cb) {\n    if (!cb)\n        cb = opts, opts = {};\n    if (typeof cb != 'function')\n        err(7);\n    return cbify(data, opts, [\n        bDflt,\n        gze,\n        function () { return [gzipSync]; }\n    ], function (ev) { return pbf(gzipSync(ev.data[0], ev.data[1])); }, 2, cb);\n}\n/**\n * Compresses data with GZIP\n * @param data The data to compress\n * @param opts The compression options\n * @returns The gzipped version of the data\n */\nexport function gzipSync(data, opts) {\n    if (!opts)\n        opts = {};\n    var c = crc(), l = data.length;\n    c.p(data);\n    var d = dopt(data, opts, gzhl(opts), 8), s = d.length;\n    return gzh(d, opts), wbytes(d, s - 8, c.d()), wbytes(d, s - 4, l), d;\n}\n/**\n * Streaming single or multi-member GZIP decompression\n */\nvar Gunzip = /*#__PURE__*/ (function () {\n    function Gunzip(opts, cb) {\n        this.v = 1;\n        this.r = 0;\n        Inflate.call(this, opts, cb);\n    }\n    /**\n     * Pushes a chunk to be GUNZIPped\n     * @param chunk The chunk to push\n     * @param final Whether this is the last chunk\n     */\n    Gunzip.prototype.push = function (chunk, final) {\n        Inflate.prototype.e.call(this, chunk);\n        this.r += chunk.length;\n        if (this.v) {\n            var p = this.p.subarray(this.v - 1);\n            var s = p.length > 3 ? gzs(p) : 4;\n            if (s > p.length) {\n                if (!final)\n                    return;\n            }\n            else if (this.v > 1 && this.onmember) {\n                this.onmember(this.r - p.length);\n            }\n            this.p = p.subarray(s), this.v = 0;\n        }\n        // necessary to prevent TS from using the closure value\n        // This allows for workerization to function correctly\n        Inflate.prototype.c.call(this, 0);\n        // process concatenated GZIP\n        if (this.s.f && !this.s.l) {\n            this.v = shft(this.s.p) + 9;\n            this.s = { i: 0 };\n            this.o = new u8(0);\n            this.push(new u8(0), final);\n        }\n        else if (final) {\n            Inflate.prototype.c.call(this, final);\n        }\n    };\n    return Gunzip;\n}());\nexport { Gunzip };\n/**\n * Asynchronous streaming single or multi-member GZIP decompression\n */\nvar AsyncGunzip = /*#__PURE__*/ (function () {\n    function AsyncGunzip(opts, cb) {\n        var _this = this;\n        astrmify([\n            bInflt,\n            guze,\n            function () { return [astrm, Inflate, Gunzip]; }\n        ], this, StrmOpt.call(this, opts, cb), function (ev) {\n            var strm = new Gunzip(ev.data);\n            strm.onmember = function (offset) { return postMessage(offset); };\n            onmessage = astrm(strm);\n        }, 9, 0, function (offset) { return _this.onmember && _this.onmember(offset); });\n    }\n    return AsyncGunzip;\n}());\nexport { AsyncGunzip };\nexport function gunzip(data, opts, cb) {\n    if (!cb)\n        cb = opts, opts = {};\n    if (typeof cb != 'function')\n        err(7);\n    return cbify(data, opts, [\n        bInflt,\n        guze,\n        function () { return [gunzipSync]; }\n    ], function (ev) { return pbf(gunzipSync(ev.data[0], ev.data[1])); }, 3, cb);\n}\nexport function gunzipSync(data, opts) {\n    var st = gzs(data);\n    if (st + 8 > data.length)\n        err(6, 'invalid gzip data');\n    return inflt(data.subarray(st, -8), { i: 2 }, opts && opts.out || new u8(gzl(data)), opts && opts.dictionary);\n}\n/**\n * Streaming Zlib compression\n */\nvar Zlib = /*#__PURE__*/ (function () {\n    function Zlib(opts, cb) {\n        this.c = adler();\n        this.v = 1;\n        Deflate.call(this, opts, cb);\n    }\n    /**\n     * Pushes a chunk to be zlibbed\n     * @param chunk The chunk to push\n     * @param final Whether this is the last chunk\n     */\n    Zlib.prototype.push = function (chunk, final) {\n        this.c.p(chunk);\n        Deflate.prototype.push.call(this, chunk, final);\n    };\n    Zlib.prototype.p = function (c, f) {\n        var raw = dopt(c, this.o, this.v && (this.o.dictionary ? 6 : 2), f && 4, this.s);\n        if (this.v)\n            zlh(raw, this.o), this.v = 0;\n        if (f)\n            wbytes(raw, raw.length - 4, this.c.d());\n        this.ondata(raw, f);\n    };\n    /**\n     * Flushes buffered uncompressed data. Useful to immediately retrieve the\n     * zlibbed output for small inputs.\n     * @param sync Whether to flush to a byte boundary. A sync flush takes 4-5\n     *             extra bytes, but guarantees all pushed data is immediately\n     *             decompressible.\n     */\n    Zlib.prototype.flush = function (sync) {\n        Deflate.prototype.flush.call(this, sync);\n    };\n    return Zlib;\n}());\nexport { Zlib };\n/**\n * Asynchronous streaming Zlib compression\n */\nvar AsyncZlib = /*#__PURE__*/ (function () {\n    function AsyncZlib(opts, cb) {\n        astrmify([\n            bDflt,\n            zle,\n            function () { return [astrm, Deflate, Zlib]; }\n        ], this, StrmOpt.call(this, opts, cb), function (ev) {\n            var strm = new Zlib(ev.data);\n            onmessage = astrm(strm);\n        }, 10, 1);\n    }\n    return AsyncZlib;\n}());\nexport { AsyncZlib };\nexport function zlib(data, opts, cb) {\n    if (!cb)\n        cb = opts, opts = {};\n    if (typeof cb != 'function')\n        err(7);\n    return cbify(data, opts, [\n        bDflt,\n        zle,\n        function () { return [zlibSync]; }\n    ], function (ev) { return pbf(zlibSync(ev.data[0], ev.data[1])); }, 4, cb);\n}\n/**\n * Compress data with Zlib\n * @param data The data to compress\n * @param opts The compression options\n * @returns The zlib-compressed version of the data\n */\nexport function zlibSync(data, opts) {\n    if (!opts)\n        opts = {};\n    var a = adler();\n    a.p(data);\n    var d = dopt(data, opts, opts.dictionary ? 6 : 2, 4);\n    return zlh(d, opts), wbytes(d, d.length - 4, a.d()), d;\n}\n/**\n * Streaming Zlib decompression\n */\nvar Unzlib = /*#__PURE__*/ (function () {\n    function Unzlib(opts, cb) {\n        Inflate.call(this, opts, cb);\n        this.v = opts && opts.dictionary ? 2 : 1;\n    }\n    /**\n     * Pushes a chunk to be unzlibbed\n     * @param chunk The chunk to push\n     * @param final Whether this is the last chunk\n     */\n    Unzlib.prototype.push = function (chunk, final) {\n        Inflate.prototype.e.call(this, chunk);\n        if (this.v) {\n            if (this.p.length < 6 && !final)\n                return;\n            this.p = this.p.subarray(zls(this.p, this.v - 1)), this.v = 0;\n        }\n        if (final) {\n            if (this.p.length < 4)\n                err(6, 'invalid zlib data');\n            this.p = this.p.subarray(0, -4);\n        }\n        // necessary to prevent TS from using the closure value\n        // This allows for workerization to function correctly\n        Inflate.prototype.c.call(this, final);\n    };\n    return Unzlib;\n}());\nexport { Unzlib };\n/**\n * Asynchronous streaming Zlib decompression\n */\nvar AsyncUnzlib = /*#__PURE__*/ (function () {\n    function AsyncUnzlib(opts, cb) {\n        astrmify([\n            bInflt,\n            zule,\n            function () { return [astrm, Inflate, Unzlib]; }\n        ], this, StrmOpt.call(this, opts, cb), function (ev) {\n            var strm = new Unzlib(ev.data);\n            onmessage = astrm(strm);\n        }, 11, 0);\n    }\n    return AsyncUnzlib;\n}());\nexport { AsyncUnzlib };\nexport function unzlib(data, opts, cb) {\n    if (!cb)\n        cb = opts, opts = {};\n    if (typeof cb != 'function')\n        err(7);\n    return cbify(data, opts, [\n        bInflt,\n        zule,\n        function () { return [unzlibSync]; }\n    ], function (ev) { return pbf(unzlibSync(ev.data[0], gopt(ev.data[1]))); }, 5, cb);\n}\nexport function unzlibSync(data, opts) {\n    return inflt(data.subarray(zls(data, opts && opts.dictionary), -4), { i: 2 }, opts && opts.out, opts && opts.dictionary);\n}\n// Default algorithm for compression (used because having a known output size allows faster decompression)\nexport { gzip as compress, AsyncGzip as AsyncCompress };\nexport { gzipSync as compressSync, Gzip as Compress };\n/**\n * Streaming GZIP, Zlib, or raw DEFLATE decompression\n */\nvar Decompress = /*#__PURE__*/ (function () {\n    function Decompress(opts, cb) {\n        this.o = StrmOpt.call(this, opts, cb) || {};\n        this.G = Gunzip;\n        this.I = Inflate;\n        this.Z = Unzlib;\n    }\n    // init substream\n    // overriden by AsyncDecompress\n    Decompress.prototype.i = function () {\n        var _this = this;\n        this.s.ondata = function (dat, final) {\n            _this.ondata(dat, final);\n        };\n    };\n    /**\n     * Pushes a chunk to be decompressed\n     * @param chunk The chunk to push\n     * @param final Whether this is the last chunk\n     */\n    Decompress.prototype.push = function (chunk, final) {\n        if (!this.ondata)\n            err(5);\n        if (!this.s) {\n            if (this.p && this.p.length) {\n                var n = new u8(this.p.length + chunk.length);\n                n.set(this.p), n.set(chunk, this.p.length);\n            }\n            else\n                this.p = chunk;\n            if (this.p.length > 2) {\n                this.s = (this.p[0] == 31 && this.p[1] == 139 && this.p[2] == 8)\n                    ? new this.G(this.o)\n                    : ((this.p[0] & 15) != 8 || (this.p[0] >> 4) > 7 || ((this.p[0] << 8 | this.p[1]) % 31))\n                        ? new this.I(this.o)\n                        : new this.Z(this.o);\n                this.i();\n                this.s.push(this.p, final);\n                this.p = null;\n            }\n        }\n        else\n            this.s.push(chunk, final);\n    };\n    return Decompress;\n}());\nexport { Decompress };\n/**\n * Asynchronous streaming GZIP, Zlib, or raw DEFLATE decompression\n */\nvar AsyncDecompress = /*#__PURE__*/ (function () {\n    function AsyncDecompress(opts, cb) {\n        Decompress.call(this, opts, cb);\n        this.queuedSize = 0;\n        this.G = AsyncGunzip;\n        this.I = AsyncInflate;\n        this.Z = AsyncUnzlib;\n    }\n    AsyncDecompress.prototype.i = function () {\n        var _this = this;\n        this.s.ondata = function (err, dat, final) {\n            _this.ondata(err, dat, final);\n        };\n        this.s.ondrain = function (size) {\n            _this.queuedSize -= size;\n            if (_this.ondrain)\n                _this.ondrain(size);\n        };\n    };\n    /**\n     * Pushes a chunk to be decompressed\n     * @param chunk The chunk to push\n     * @param final Whether this is the last chunk\n     */\n    AsyncDecompress.prototype.push = function (chunk, final) {\n        this.queuedSize += chunk.length;\n        Decompress.prototype.push.call(this, chunk, final);\n    };\n    return AsyncDecompress;\n}());\nexport { AsyncDecompress };\nexport function decompress(data, opts, cb) {\n    if (!cb)\n        cb = opts, opts = {};\n    if (typeof cb != 'function')\n        err(7);\n    return (data[0] == 31 && data[1] == 139 && data[2] == 8)\n        ? gunzip(data, opts, cb)\n        : ((data[0] & 15) != 8 || (data[0] >> 4) > 7 || ((data[0] << 8 | data[1]) % 31))\n            ? inflate(data, opts, cb)\n            : unzlib(data, opts, cb);\n}\n/**\n * Expands compressed GZIP, Zlib, or raw DEFLATE data, automatically detecting the format\n * @param data The data to decompress\n * @param opts The decompression options\n * @returns The decompressed version of the data\n */\nexport function decompressSync(data, opts) {\n    return (data[0] == 31 && data[1] == 139 && data[2] == 8)\n        ? gunzipSync(data, opts)\n        : ((data[0] & 15) != 8 || (data[0] >> 4) > 7 || ((data[0] << 8 | data[1]) % 31))\n            ? inflateSync(data, opts)\n            : unzlibSync(data, opts);\n}\n// flatten a directory structure\nvar fltn = function (d, p, t, o) {\n    for (var k in d) {\n        var val = d[k], n = p + k, op = o;\n        if (Array.isArray(val))\n            op = mrg(o, val[1]), val = val[0];\n        if (ArrayBuffer.isView(val))\n            t[n] = [val, op];\n        else {\n            t[n += '/'] = [new u8(0), op];\n            fltn(val, n, t, o);\n        }\n    }\n};\n// text encoder\nvar te = typeof TextEncoder != 'undefined' && /*#__PURE__*/ new TextEncoder();\n// text decoder\nvar td = typeof TextDecoder != 'undefined' && /*#__PURE__*/ new TextDecoder();\n// text decoder stream\nvar tds = 0;\ntry {\n    td.decode(et, { stream: true });\n    tds = 1;\n}\ncatch (e) { }\n// decode UTF8\nvar dutf8 = function (d) {\n    for (var r = '', i = 0;;) {\n        var c = d[i++];\n        var eb = (c > 127) + (c > 223) + (c > 239);\n        if (i + eb > d.length)\n            return { s: r, r: slc(d, i - 1) };\n        if (!eb)\n            r += String.fromCharCode(c);\n        else if (eb == 3) {\n            c = ((c & 15) << 18 | (d[i++] & 63) << 12 | (d[i++] & 63) << 6 | (d[i++] & 63)) - 65536,\n                r += String.fromCharCode(55296 | (c >> 10), 56320 | (c & 1023));\n        }\n        else if (eb & 1)\n            r += String.fromCharCode((c & 31) << 6 | (d[i++] & 63));\n        else\n            r += String.fromCharCode((c & 15) << 12 | (d[i++] & 63) << 6 | (d[i++] & 63));\n    }\n};\n/**\n * Streaming UTF-8 decoding\n */\nvar DecodeUTF8 = /*#__PURE__*/ (function () {\n    /**\n     * Creates a UTF-8 decoding stream\n     * @param cb The callback to call whenever data is decoded\n     */\n    function DecodeUTF8(cb) {\n        this.ondata = cb;\n        if (tds)\n            this.t = new TextDecoder();\n        else\n            this.p = et;\n    }\n    /**\n     * Pushes a chunk to be decoded from UTF-8 binary\n     * @param chunk The chunk to push\n     * @param final Whether this is the last chunk\n     */\n    DecodeUTF8.prototype.push = function (chunk, final) {\n        if (!this.ondata)\n            err(5);\n        final = !!final;\n        if (this.t) {\n            this.ondata(this.t.decode(chunk, { stream: true }), final);\n            if (final) {\n                if (this.t.decode().length)\n                    err(8);\n                this.t = null;\n            }\n            return;\n        }\n        if (!this.p)\n            err(4);\n        var dat = new u8(this.p.length + chunk.length);\n        dat.set(this.p);\n        dat.set(chunk, this.p.length);\n        var _a = dutf8(dat), s = _a.s, r = _a.r;\n        if (final) {\n            if (r.length)\n                err(8);\n            this.p = null;\n        }\n        else\n            this.p = r;\n        this.ondata(s, final);\n    };\n    return DecodeUTF8;\n}());\nexport { DecodeUTF8 };\n/**\n * Streaming UTF-8 encoding\n */\nvar EncodeUTF8 = /*#__PURE__*/ (function () {\n    /**\n     * Creates a UTF-8 decoding stream\n     * @param cb The callback to call whenever data is encoded\n     */\n    function EncodeUTF8(cb) {\n        this.ondata = cb;\n    }\n    /**\n     * Pushes a chunk to be encoded to UTF-8\n     * @param chunk The string data to push\n     * @param final Whether this is the last chunk\n     */\n    EncodeUTF8.prototype.push = function (chunk, final) {\n        if (!this.ondata)\n            err(5);\n        if (this.d)\n            err(4);\n        this.ondata(strToU8(chunk), this.d = final || false);\n    };\n    return EncodeUTF8;\n}());\nexport { EncodeUTF8 };\n/**\n * Converts a string into a Uint8Array for use with compression/decompression methods\n * @param str The string to encode\n * @param latin1 Whether or not to interpret the data as Latin-1. This should\n *               not need to be true unless decoding a binary string.\n * @returns The string encoded in UTF-8/Latin-1 binary\n */\nexport function strToU8(str, latin1) {\n    if (latin1) {\n        var ar_1 = new u8(str.length);\n        for (var i = 0; i < str.length; ++i)\n            ar_1[i] = str.charCodeAt(i);\n        return ar_1;\n    }\n    if (te)\n        return te.encode(str);\n    var l = str.length;\n    var ar = new u8(str.length + (str.length >> 1));\n    var ai = 0;\n    var w = function (v) { ar[ai++] = v; };\n    for (var i = 0; i < l; ++i) {\n        if (ai + 5 > ar.length) {\n            var n = new u8(ai + 8 + ((l - i) << 1));\n            n.set(ar);\n            ar = n;\n        }\n        var c = str.charCodeAt(i);\n        if (c < 128 || latin1)\n            w(c);\n        else if (c < 2048)\n            w(192 | (c >> 6)), w(128 | (c & 63));\n        else if (c > 55295 && c < 57344)\n            c = 65536 + (c & 1023 << 10) | (str.charCodeAt(++i) & 1023),\n                w(240 | (c >> 18)), w(128 | ((c >> 12) & 63)), w(128 | ((c >> 6) & 63)), w(128 | (c & 63));\n        else\n            w(224 | (c >> 12)), w(128 | ((c >> 6) & 63)), w(128 | (c & 63));\n    }\n    return slc(ar, 0, ai);\n}\n/**\n * Converts a Uint8Array to a string\n * @param dat The data to decode to string\n * @param latin1 Whether or not to interpret the data as Latin-1. This should\n *               not need to be true unless encoding to binary string.\n * @returns The original UTF-8/Latin-1 string\n */\nexport function strFromU8(dat, latin1) {\n    if (latin1) {\n        var r = '';\n        for (var i = 0; i < dat.length; i += 16384)\n            r += String.fromCharCode.apply(null, dat.subarray(i, i + 16384));\n        return r;\n    }\n    else if (td) {\n        return td.decode(dat);\n    }\n    else {\n        var _a = dutf8(dat), s = _a.s, r = _a.r;\n        if (r.length)\n            err(8);\n        return s;\n    }\n}\n;\n// deflate bit flag\nvar dbf = function (l) { return l == 1 ? 3 : l < 6 ? 2 : l == 9 ? 1 : 0; };\n// skip local zip header\nvar slzh = function (d, b) { return b + 30 + b2(d, b + 26) + b2(d, b + 28); };\n// read zip header\nvar zh = function (d, b, z) {\n    var fnl = b2(d, b + 28), efl = b2(d, b + 30), fn = strFromU8(d.subarray(b + 46, b + 46 + fnl), !(b2(d, b + 8) & 2048)), es = b + 46 + fnl;\n    var _a = z64hs(d, es, efl, z, b4(d, b + 20), b4(d, b + 24), b4(d, b + 42)), sc = _a[0], su = _a[1], off = _a[2];\n    return [b2(d, b + 10), sc, su, fn, es + efl + b2(d, b + 32), off];\n};\n// read zip64 header sizes\nvar z64hs = function (d, b, l, z, sc, su, off) {\n    var nsc = sc == 4294967295, nsu = su == 4294967295, noff = off == 4294967295, e = b + l;\n    var nf = nsc + nsu + noff;\n    if (z && nf) {\n        for (; b + 4 < e; b += 4 + b2(d, b + 2)) {\n            if (b2(d, b) == 1) {\n                return [\n                    nsc ? b8(d, b + 4 + 8 * nsu) : sc,\n                    nsu ? b8(d, b + 4) : su,\n                    noff ? b8(d, b + 4 + 8 * (nsu + nsc)) : off,\n                    1\n                ];\n            }\n        }\n        // z == 2 for unknown whether or not zip64\n        if (z < 2)\n            err(13);\n    }\n    return [sc, su, off, 0];\n};\n// extra field length\nvar exfl = function (ex) {\n    var le = 0;\n    if (ex) {\n        for (var k in ex) {\n            var l = ex[k].length;\n            if (l > 65535)\n                err(9);\n            le += l + 4;\n        }\n    }\n    return le;\n};\n// write zip header\nvar wzh = function (d, b, f, fn, u, c, ce, co) {\n    var fl = fn.length, ex = f.extra, col = co && co.length;\n    var exl = exfl(ex);\n    wbytes(d, b, ce != null ? 0x2014B50 : 0x4034B50), b += 4;\n    if (ce != null)\n        d[b++] = 20, d[b++] = f.os;\n    d[b] = 20, b += 2; // spec compliance? what's that?\n    d[b++] = (f.flag << 1) | (c < 0 && 8), d[b++] = u && 8;\n    d[b++] = f.compression & 255, d[b++] = f.compression >> 8;\n    var dt = new Date(f.mtime == null ? Date.now() : f.mtime), y = dt.getFullYear() - 1980;\n    if (y < 0 || y > 119)\n        err(10);\n    wbytes(d, b, (y << 25) | ((dt.getMonth() + 1) << 21) | (dt.getDate() << 16) | (dt.getHours() << 11) | (dt.getMinutes() << 5) | (dt.getSeconds() >> 1)), b += 4;\n    if (c != -1) {\n        wbytes(d, b, f.crc);\n        wbytes(d, b + 4, c < 0 ? -c - 2 : c);\n        wbytes(d, b + 8, f.size);\n    }\n    wbytes(d, b + 12, fl);\n    wbytes(d, b + 14, exl), b += 16;\n    if (ce != null) {\n        wbytes(d, b, col);\n        wbytes(d, b + 6, f.attrs);\n        wbytes(d, b + 10, ce), b += 14;\n    }\n    d.set(fn, b);\n    b += fl;\n    if (exl) {\n        for (var k in ex) {\n            var exf = ex[k], l = exf.length;\n            wbytes(d, b, +k);\n            wbytes(d, b + 2, l);\n            d.set(exf, b + 4), b += 4 + l;\n        }\n    }\n    if (col)\n        d.set(co, b), b += col;\n    return b;\n};\n// write zip footer (end of central directory)\nvar wzf = function (o, b, c, d, e) {\n    wbytes(o, b, 0x6054B50); // skip disk\n    wbytes(o, b + 8, c);\n    wbytes(o, b + 10, c);\n    wbytes(o, b + 12, d);\n    wbytes(o, b + 16, e);\n};\n/**\n * A pass-through stream to keep data uncompressed in a ZIP archive.\n */\nvar ZipPassThrough = /*#__PURE__*/ (function () {\n    /**\n     * Creates a pass-through stream that can be added to ZIP archives\n     * @param filename The filename to associate with this data stream\n     */\n    function ZipPassThrough(filename) {\n        this.filename = filename;\n        this.c = crc();\n        this.size = 0;\n        this.compression = 0;\n    }\n    /**\n     * Processes a chunk and pushes to the output stream. You can override this\n     * method in a subclass for custom behavior, but by default this passes\n     * the data through. You must call this.ondata(err, chunk, final) at some\n     * point in this method.\n     * @param chunk The chunk to process\n     * @param final Whether this is the last chunk\n     */\n    ZipPassThrough.prototype.process = function (chunk, final) {\n        this.ondata(null, chunk, final);\n    };\n    /**\n     * Pushes a chunk to be added. If you are subclassing this with a custom\n     * compression algorithm, note that you must push data from the source\n     * file only, pre-compression.\n     * @param chunk The chunk to push\n     * @param final Whether this is the last chunk\n     */\n    ZipPassThrough.prototype.push = function (chunk, final) {\n        if (!this.ondata)\n            err(5);\n        this.c.p(chunk);\n        this.size += chunk.length;\n        if (final)\n            this.crc = this.c.d();\n        // we shouldn't really do this cast, but properly handling ArrayBufferLike\n        // makes the API unergonomic with Buffer\n        this.process(chunk, final || false);\n    };\n    return ZipPassThrough;\n}());\nexport { ZipPassThrough };\n// I don't extend because TypeScript extension adds 1kB of runtime bloat\n/**\n * Streaming DEFLATE compression for ZIP archives. Prefer using AsyncZipDeflate\n * for better performance\n */\nvar ZipDeflate = /*#__PURE__*/ (function () {\n    /**\n     * Creates a DEFLATE stream that can be added to ZIP archives\n     * @param filename The filename to associate with this data stream\n     * @param opts The compression options\n     */\n    function ZipDeflate(filename, opts) {\n        var _this = this;\n        if (!opts)\n            opts = {};\n        ZipPassThrough.call(this, filename);\n        this.d = new Deflate(opts, function (dat, final) {\n            _this.ondata(null, dat, final);\n        });\n        this.compression = 8;\n        this.flag = dbf(opts.level);\n    }\n    ZipDeflate.prototype.process = function (chunk, final) {\n        try {\n            this.d.push(chunk, final);\n        }\n        catch (e) {\n            this.ondata(e, null, final);\n        }\n    };\n    /**\n     * Pushes a chunk to be deflated\n     * @param chunk The chunk to push\n     * @param final Whether this is the last chunk\n     */\n    ZipDeflate.prototype.push = function (chunk, final) {\n        ZipPassThrough.prototype.push.call(this, chunk, final);\n    };\n    return ZipDeflate;\n}());\nexport { ZipDeflate };\n/**\n * Asynchronous streaming DEFLATE compression for ZIP archives\n */\nvar AsyncZipDeflate = /*#__PURE__*/ (function () {\n    /**\n     * Creates an asynchronous DEFLATE stream that can be added to ZIP archives\n     * @param filename The filename to associate with this data stream\n     * @param opts The compression options\n     */\n    function AsyncZipDeflate(filename, opts) {\n        var _this = this;\n        if (!opts)\n            opts = {};\n        ZipPassThrough.call(this, filename);\n        this.d = new AsyncDeflate(opts, function (err, dat, final) {\n            _this.ondata(err, dat, final);\n        });\n        this.compression = 8;\n        this.flag = dbf(opts.level);\n        this.terminate = this.d.terminate;\n    }\n    AsyncZipDeflate.prototype.process = function (chunk, final) {\n        this.d.push(chunk, final);\n    };\n    /**\n     * Pushes a chunk to be deflated\n     * @param chunk The chunk to push\n     * @param final Whether this is the last chunk\n     */\n    AsyncZipDeflate.prototype.push = function (chunk, final) {\n        ZipPassThrough.prototype.push.call(this, chunk, final);\n    };\n    return AsyncZipDeflate;\n}());\nexport { AsyncZipDeflate };\n// TODO: Better tree shaking\n/**\n * A zippable archive to which files can incrementally be added\n */\nvar Zip = /*#__PURE__*/ (function () {\n    /**\n     * Creates an empty ZIP archive to which files can be added\n     * @param cb The callback to call whenever data for the generated ZIP archive\n     *           is available\n     */\n    function Zip(cb) {\n        this.ondata = cb;\n        this.u = [];\n        this.d = 1;\n    }\n    /**\n     * Adds a file to the ZIP archive\n     * @param file The file stream to add\n     */\n    Zip.prototype.add = function (file) {\n        var _this = this;\n        if (!this.ondata)\n            err(5);\n        // finishing or finished\n        if (this.d & 2)\n            this.ondata(err(4 + (this.d & 1) * 8, 0, 1), null, false);\n        else {\n            var f = strToU8(file.filename), fl_1 = f.length;\n            var com = file.comment, o = com && strToU8(com);\n            var u = fl_1 != file.filename.length || (o && (com.length != o.length));\n            var hl_1 = fl_1 + exfl(file.extra) + 30;\n            if (fl_1 > 65535)\n                this.ondata(err(11, 0, 1), null, false);\n            var header = new u8(hl_1);\n            wzh(header, 0, file, f, u, -1);\n            var chks_1 = [header];\n            var pAll_1 = function () {\n                for (var _i = 0, chks_2 = chks_1; _i < chks_2.length; _i++) {\n                    var chk = chks_2[_i];\n                    _this.ondata(null, chk, false);\n                }\n                chks_1 = [];\n            };\n            var tr_1 = this.d;\n            this.d = 0;\n            var ind_1 = this.u.length;\n            var uf_1 = mrg(file, {\n                f: f,\n                u: u,\n                o: o,\n                t: function () {\n                    if (file.terminate)\n                        file.terminate();\n                },\n                r: function () {\n                    pAll_1();\n                    if (tr_1) {\n                        var nxt = _this.u[ind_1 + 1];\n                        if (nxt)\n                            nxt.r();\n                        else\n                            _this.d = 1;\n                    }\n                    tr_1 = 1;\n                }\n            });\n            var cl_1 = 0;\n            file.ondata = function (err, dat, final) {\n                if (err) {\n                    _this.ondata(err, dat, final);\n                    _this.terminate();\n                }\n                else {\n                    cl_1 += dat.length;\n                    chks_1.push(dat);\n                    if (final) {\n                        var dd = new u8(16);\n                        wbytes(dd, 0, 0x8074B50);\n                        wbytes(dd, 4, file.crc);\n                        wbytes(dd, 8, cl_1);\n                        wbytes(dd, 12, file.size);\n                        chks_1.push(dd);\n                        uf_1.c = cl_1, uf_1.b = hl_1 + cl_1 + 16, uf_1.crc = file.crc, uf_1.size = file.size;\n                        if (tr_1)\n                            uf_1.r();\n                        tr_1 = 1;\n                    }\n                    else if (tr_1)\n                        pAll_1();\n                }\n            };\n            this.u.push(uf_1);\n        }\n    };\n    /**\n     * Ends the process of adding files and prepares to emit the final chunks.\n     * This *must* be called after adding all desired files for the resulting\n     * ZIP file to work properly.\n     */\n    Zip.prototype.end = function () {\n        var _this = this;\n        if (this.d & 2) {\n            this.ondata(err(4 + (this.d & 1) * 8, 0, 1), null, true);\n            return;\n        }\n        if (this.d)\n            this.e();\n        else\n            this.u.push({\n                r: function () {\n                    if (!(_this.d & 1))\n                        return;\n                    _this.u.splice(-1, 1);\n                    _this.e();\n                },\n                t: function () { }\n            });\n        this.d = 3;\n    };\n    Zip.prototype.e = function () {\n        var bt = 0, l = 0, tl = 0;\n        for (var _i = 0, _a = this.u; _i < _a.length; _i++) {\n            var f = _a[_i];\n            tl += 46 + f.f.length + exfl(f.extra) + (f.o ? f.o.length : 0);\n        }\n        var out = new u8(tl + 22);\n        for (var _b = 0, _c = this.u; _b < _c.length; _b++) {\n            var f = _c[_b];\n            wzh(out, bt, f, f.f, f.u, -f.c - 2, l, f.o);\n            bt += 46 + f.f.length + exfl(f.extra) + (f.o ? f.o.length : 0), l += f.b;\n        }\n        wzf(out, bt, this.u.length, tl, l);\n        this.ondata(null, out, true);\n        this.d = 2;\n    };\n    /**\n     * A method to terminate any internal workers used by the stream. Subsequent\n     * calls to add() will fail.\n     */\n    Zip.prototype.terminate = function () {\n        for (var _i = 0, _a = this.u; _i < _a.length; _i++) {\n            var f = _a[_i];\n            f.t();\n        }\n        this.d = 2;\n    };\n    return Zip;\n}());\nexport { Zip };\nexport function zip(data, opts, cb) {\n    if (!cb)\n        cb = opts, opts = {};\n    if (typeof cb != 'function')\n        err(7);\n    var r = {};\n    fltn(data, '', r, opts);\n    var k = Object.keys(r);\n    var lft = k.length, o = 0, tot = 0;\n    var slft = lft, files = new Array(lft);\n    var term = [];\n    var tAll = function () {\n        for (var i = 0; i < term.length; ++i)\n            term[i]();\n    };\n    var cbd = function (a, b) {\n        mt(function () { cb(a, b); });\n    };\n    mt(function () { cbd = cb; });\n    var cbf = function () {\n        var out = new u8(tot + 22), oe = o, cdl = tot - o;\n        tot = 0;\n        for (var i = 0; i < slft; ++i) {\n            var f = files[i];\n            try {\n                var l = f.c.length;\n                wzh(out, tot, f, f.f, f.u, l);\n                var badd = 30 + f.f.length + exfl(f.extra);\n                var loc = tot + badd;\n                out.set(f.c, loc);\n                wzh(out, o, f, f.f, f.u, l, tot, f.m), o += 16 + badd + (f.m ? f.m.length : 0), tot = loc + l;\n            }\n            catch (e) {\n                return cbd(e, null);\n            }\n        }\n        wzf(out, o, files.length, cdl, oe);\n        cbd(null, out);\n    };\n    if (!lft)\n        cbf();\n    var _loop_1 = function (i) {\n        var fn = k[i];\n        var _a = r[fn], file = _a[0], p = _a[1];\n        var c = crc(), size = file.length;\n        c.p(file);\n        var f = strToU8(fn), s = f.length;\n        var com = p.comment, m = com && strToU8(com), ms = m && m.length;\n        var exl = exfl(p.extra);\n        var compression = p.level == 0 ? 0 : 8;\n        var cbl = function (e, d) {\n            if (e) {\n                tAll();\n                cbd(e, null);\n            }\n            else {\n                var l = d.length;\n                files[i] = mrg(p, {\n                    size: size,\n                    crc: c.d(),\n                    c: d,\n                    f: f,\n                    m: m,\n                    u: s != fn.length || (m && (com.length != ms)),\n                    compression: compression\n                });\n                o += 30 + s + exl + l;\n                tot += 76 + 2 * (s + exl) + (ms || 0) + l;\n                if (!--lft)\n                    cbf();\n            }\n        };\n        if (s > 65535)\n            cbl(err(11, 0, 1), null);\n        if (!compression)\n            cbl(null, file);\n        else if (size < 160000) {\n            try {\n                cbl(null, deflateSync(file, p));\n            }\n            catch (e) {\n                cbl(e, null);\n            }\n        }\n        else\n            term.push(deflate(file, p, cbl));\n    };\n    // Cannot use lft because it can decrease\n    for (var i = 0; i < slft; ++i) {\n        _loop_1(i);\n    }\n    return tAll;\n}\n/**\n * Synchronously creates a ZIP file. Prefer using `zip` for better performance\n * with more than one file.\n * @param data The directory structure for the ZIP archive\n * @param opts The main options, merged with per-file options\n * @returns The generated ZIP archive\n */\nexport function zipSync(data, opts) {\n    if (!opts)\n        opts = {};\n    var r = {};\n    var files = [];\n    fltn(data, '', r, opts);\n    var o = 0;\n    var tot = 0;\n    for (var fn in r) {\n        var _a = r[fn], file = _a[0], p = _a[1];\n        var compression = p.level == 0 ? 0 : 8;\n        var f = strToU8(fn), s = f.length;\n        var com = p.comment, m = com && strToU8(com), ms = m && m.length;\n        var exl = exfl(p.extra);\n        if (s > 65535)\n            err(11);\n        var d = compression ? deflateSync(file, p) : file, l = d.length;\n        var c = crc();\n        c.p(file);\n        files.push(mrg(p, {\n            size: file.length,\n            crc: c.d(),\n            c: d,\n            f: f,\n            m: m,\n            u: s != fn.length || (m && (com.length != ms)),\n            o: o,\n            compression: compression\n        }));\n        o += 30 + s + exl + l;\n        tot += 76 + 2 * (s + exl) + (ms || 0) + l;\n    }\n    var out = new u8(tot + 22), oe = o, cdl = tot - o;\n    for (var i = 0; i < files.length; ++i) {\n        var f = files[i];\n        wzh(out, f.o, f, f.f, f.u, f.c.length);\n        var badd = 30 + f.f.length + exfl(f.extra);\n        out.set(f.c, f.o + badd);\n        wzh(out, o, f, f.f, f.u, f.c.length, f.o, f.m), o += 16 + badd + (f.m ? f.m.length : 0);\n    }\n    wzf(out, o, files.length, cdl, oe);\n    return out;\n}\n/**\n * Streaming pass-through decompression for ZIP archives\n */\nvar UnzipPassThrough = /*#__PURE__*/ (function () {\n    function UnzipPassThrough() {\n    }\n    UnzipPassThrough.prototype.push = function (chunk, final) {\n        // same as ZipPassThrough: cast to retain Buffer ergonomics\n        this.ondata(null, chunk, final);\n    };\n    UnzipPassThrough.compression = 0;\n    return UnzipPassThrough;\n}());\nexport { UnzipPassThrough };\n/**\n * Streaming DEFLATE decompression for ZIP archives. Prefer AsyncZipInflate for\n * better performance.\n */\nvar UnzipInflate = /*#__PURE__*/ (function () {\n    /**\n     * Creates a DEFLATE decompression that can be used in ZIP archives\n     */\n    function UnzipInflate() {\n        var _this = this;\n        this.i = new Inflate(function (dat, final) {\n            _this.ondata(null, dat, final);\n        });\n    }\n    UnzipInflate.prototype.push = function (chunk, final) {\n        try {\n            this.i.push(chunk, final);\n        }\n        catch (e) {\n            this.ondata(e, null, final);\n        }\n    };\n    UnzipInflate.compression = 8;\n    return UnzipInflate;\n}());\nexport { UnzipInflate };\n/**\n * Asynchronous streaming DEFLATE decompression for ZIP archives\n */\nvar AsyncUnzipInflate = /*#__PURE__*/ (function () {\n    /**\n     * Creates a DEFLATE decompression that can be used in ZIP archives\n     */\n    function AsyncUnzipInflate(_, sz) {\n        var _this = this;\n        if (sz < 320000) {\n            this.i = new Inflate(function (dat, final) {\n                _this.ondata(null, dat, final);\n            });\n        }\n        else {\n            this.i = new AsyncInflate(function (err, dat, final) {\n                _this.ondata(err, dat, final);\n            });\n            this.terminate = this.i.terminate;\n        }\n    }\n    AsyncUnzipInflate.prototype.push = function (chunk, final) {\n        if (this.i.terminate)\n            chunk = slc(chunk, 0);\n        this.i.push(chunk, final);\n    };\n    AsyncUnzipInflate.compression = 8;\n    return AsyncUnzipInflate;\n}());\nexport { AsyncUnzipInflate };\n/**\n * A ZIP archive decompression stream that emits files as they are discovered\n */\nvar Unzip = /*#__PURE__*/ (function () {\n    /**\n     * Creates a ZIP decompression stream\n     * @param cb The callback to call whenever a file in the ZIP archive is found\n     */\n    function Unzip(cb) {\n        this.onfile = cb;\n        this.k = [];\n        this.o = {\n            0: UnzipPassThrough\n        };\n        this.p = et;\n    }\n    /**\n     * Pushes a chunk to be unzipped\n     * @param chunk The chunk to push\n     * @param final Whether this is the last chunk\n     */\n    Unzip.prototype.push = function (chunk, final) {\n        var _this = this;\n        if (!this.onfile)\n            err(5);\n        if (!this.p)\n            err(4);\n        if (this.c > 0) {\n            var len = Math.min(this.c, chunk.length);\n            var toAdd = chunk.subarray(0, len);\n            this.c -= len;\n            if (this.d)\n                this.d.push(toAdd, !this.c);\n            else\n                this.k[0].push(toAdd);\n            chunk = chunk.subarray(len);\n            if (chunk.length)\n                return this.push(chunk, final);\n        }\n        else {\n            var f = 0, i = 0, is = void 0, buf = void 0;\n            if (!this.p.length)\n                buf = chunk;\n            else if (!chunk.length)\n                buf = this.p;\n            else {\n                buf = new u8(this.p.length + chunk.length);\n                buf.set(this.p), buf.set(chunk, this.p.length);\n            }\n            var l = buf.length, oc = this.c, add = oc && this.d;\n            var _loop_2 = function () {\n                var sig = b4(buf, i);\n                if (sig == 0x4034B50) {\n                    f = 1, is = i;\n                    this_1.d = null;\n                    this_1.c = 0;\n                    var bf = b2(buf, i + 6), cmp_1 = b2(buf, i + 8), u = bf & 2048, dd = bf & 8, fnl = b2(buf, i + 26), es = b2(buf, i + 28);\n                    if (l > i + 30 + fnl + es) {\n                        var chks_3 = [];\n                        this_1.k.unshift(chks_3);\n                        f = 2;\n                        var lsc = b4(buf, i + 18), lsu = b4(buf, i + 22);\n                        var fn_1 = strFromU8(buf.subarray(i + 30, i += 30 + fnl), !u);\n                        var _a = z64hs(buf, i, es, 2, lsc, lsu, 0), sc_1 = _a[0], su_1 = _a[1], z64 = _a[3];\n                        if (dd)\n                            sc_1 = -1 - z64;\n                        i += es;\n                        this_1.c = sc_1;\n                        var d_1;\n                        var file_1 = {\n                            name: fn_1,\n                            compression: cmp_1,\n                            start: function () {\n                                if (!file_1.ondata)\n                                    err(5);\n                                if (!sc_1)\n                                    file_1.ondata(null, et, true);\n                                else {\n                                    var ctr = _this.o[cmp_1];\n                                    if (!ctr)\n                                        file_1.ondata(err(14, 'unknown compression type ' + cmp_1, 1), null, false);\n                                    d_1 = sc_1 < 0 ? new ctr(fn_1) : new ctr(fn_1, sc_1, su_1);\n                                    d_1.ondata = function (err, dat, final) { file_1.ondata(err, dat, final); };\n                                    for (var _i = 0, chks_4 = chks_3; _i < chks_4.length; _i++) {\n                                        var dat = chks_4[_i];\n                                        d_1.push(dat, false);\n                                    }\n                                    if (_this.k[0] == chks_3 && _this.c)\n                                        _this.d = d_1;\n                                    else\n                                        d_1.push(et, true);\n                                }\n                            },\n                            terminate: function () {\n                                if (d_1 && d_1.terminate)\n                                    d_1.terminate();\n                            }\n                        };\n                        if (sc_1 >= 0)\n                            file_1.size = sc_1, file_1.originalSize = su_1;\n                        this_1.onfile(file_1);\n                    }\n                    return \"break\";\n                }\n                else if (oc) {\n                    if (sig == 0x8074B50) {\n                        is = i += 12 + (oc == -2 && 8), f = 3, this_1.c = 0;\n                        return \"break\";\n                    }\n                    else if (sig == 0x2014B50) {\n                        is = i -= 4, f = 3, this_1.c = 0;\n                        return \"break\";\n                    }\n                }\n            };\n            var this_1 = this;\n            for (; i < l - 4; ++i) {\n                var state_1 = _loop_2();\n                if (state_1 === \"break\")\n                    break;\n            }\n            this.p = et;\n            if (oc < 0) {\n                var dat = f ? buf.subarray(0, is - 12 - (oc == -2 && 8) - (b4(buf, is - 16) == 0x8074B50 && 4)) : buf.subarray(0, i);\n                if (add)\n                    add.push(dat, !!f);\n                else\n                    this.k[+(f == 2)].push(dat);\n            }\n            if (f & 2)\n                return this.push(buf.subarray(i), final);\n            this.p = buf.subarray(i);\n        }\n        if (final) {\n            if (this.c)\n                err(13);\n            this.p = null;\n        }\n    };\n    /**\n     * Registers a decoder with the stream, allowing for files compressed with\n     * the compression type provided to be expanded correctly\n     * @param decoder The decoder constructor\n     */\n    Unzip.prototype.register = function (decoder) {\n        this.o[decoder.compression] = decoder;\n    };\n    return Unzip;\n}());\nexport { Unzip };\nvar mt = typeof queueMicrotask == 'function' ? queueMicrotask : typeof setTimeout == 'function' ? setTimeout : function (fn) { fn(); };\nexport function unzip(data, opts, cb) {\n    if (!cb)\n        cb = opts, opts = {};\n    if (typeof cb != 'function')\n        err(7);\n    var term = [];\n    var tAll = function () {\n        for (var i = 0; i < term.length; ++i)\n            term[i]();\n    };\n    var files = {};\n    var cbd = function (a, b) {\n        mt(function () { cb(a, b); });\n    };\n    mt(function () { cbd = cb; });\n    var e = data.length - 22;\n    for (; b4(data, e) != 0x6054B50; --e) {\n        if (!e || data.length - e > 65558) {\n            cbd(err(13, 0, 1), null);\n            return tAll;\n        }\n    }\n    ;\n    var lft = b2(data, e + 8);\n    if (lft) {\n        var c = lft;\n        var o = b4(data, e + 16);\n        var z = b4(data, e - 20) == 0x7064B50;\n        if (z) {\n            var ze = b4(data, e - 12);\n            z = b4(data, ze) == 0x6064B50;\n            if (z) {\n                c = lft = b4(data, ze + 32);\n                o = b4(data, ze + 48);\n            }\n        }\n        var fltr = opts && opts.filter;\n        var _loop_3 = function (i) {\n            var _a = zh(data, o, z), c_1 = _a[0], sc = _a[1], su = _a[2], fn = _a[3], no = _a[4], off = _a[5], b = slzh(data, off);\n            o = no;\n            var cbl = function (e, d) {\n                if (e) {\n                    tAll();\n                    cbd(e, null);\n                }\n                else {\n                    if (d)\n                        files[fn] = d;\n                    if (!--lft)\n                        cbd(null, files);\n                }\n            };\n            if (!fltr || fltr({\n                name: fn,\n                size: sc,\n                originalSize: su,\n                compression: c_1\n            })) {\n                if (!c_1)\n                    cbl(null, slc(data, b, b + sc));\n                else if (c_1 == 8) {\n                    var infl = data.subarray(b, b + sc);\n                    // Synchronously decompress under 512KB, or barely-compressed data\n                    if (su < 524288 || sc > 0.8 * su) {\n                        try {\n                            cbl(null, inflateSync(infl, { out: new u8(su) }));\n                        }\n                        catch (e) {\n                            cbl(e, null);\n                        }\n                    }\n                    else\n                        term.push(inflate(infl, { size: su }, cbl));\n                }\n                else\n                    cbl(err(14, 'unknown compression type ' + c_1, 1), null);\n            }\n            else\n                cbl(null, null);\n        };\n        for (var i = 0; i < c; ++i) {\n            _loop_3(i);\n        }\n    }\n    else\n        cbd(null, {});\n    return tAll;\n}\n/**\n * Synchronously decompresses a ZIP archive. Prefer using `unzip` for better\n * performance with more than one file.\n * @param data The raw compressed ZIP file\n * @param opts The ZIP extraction options\n * @returns The decompressed files\n */\nexport function unzipSync(data, opts) {\n    var files = {};\n    var e = data.length - 22;\n    for (; b4(data, e) != 0x6054B50; --e) {\n        if (!e || data.length - e > 65558)\n            err(13);\n    }\n    ;\n    var c = b2(data, e + 8);\n    if (!c)\n        return {};\n    var o = b4(data, e + 16);\n    var z = b4(data, e - 20) == 0x7064B50;\n    if (z) {\n        var ze = b4(data, e - 12);\n        z = b4(data, ze) == 0x6064B50;\n        if (z) {\n            c = b4(data, ze + 32);\n            o = b4(data, ze + 48);\n        }\n    }\n    var fltr = opts && opts.filter;\n    for (var i = 0; i < c; ++i) {\n        var _a = zh(data, o, z), c_2 = _a[0], sc = _a[1], su = _a[2], fn = _a[3], no = _a[4], off = _a[5], b = slzh(data, off);\n        o = no;\n        if (!fltr || fltr({\n            name: fn,\n            size: sc,\n            originalSize: su,\n            compression: c_2\n        })) {\n            if (!c_2)\n                files[fn] = slc(data, b, b + sc);\n            else if (c_2 == 8)\n                files[fn] = inflateSync(data.subarray(b, b + sc), { out: new u8(su) });\n            else\n                err(14, 'unknown compression type ' + c_2);\n        }\n    }\n    return files;\n}\n","/**\n * ZIP extraction — archive bytes in, regular File objects out.\n */\nimport { type Unzipped, unzip } from 'fflate';\nimport { setRelativePath } from './files';\n\nexport interface ZipExtractionResult {\n  /** Extracted files as regular File objects */\n  files: File[];\n  /** Any errors encountered during extraction */\n  errors: string[];\n}\n\n/**\n * Extracts all files from a ZIP archive.\n *\n * Uses fflate's ASYNCHRONOUS `unzip`, which inflates off the main thread. The\n * synchronous variant would block the tab for the duration — unacceptable on\n * this package's headline interaction, where a large folder is the normal case.\n */\nexport async function extractZipToFiles(zipFile: File): Promise<ZipExtractionResult> {\n  try {\n    const bytes = new Uint8Array(await zipFile.arrayBuffer());\n    const entries = await new Promise<Unzipped>((resolve, reject) => {\n      unzip(bytes, (err, data) => (err ? reject(err) : resolve(data)));\n    });\n\n    const files: File[] = [];\n    const errors: string[] = [];\n\n    for (const [path, data] of Object.entries(entries)) {\n      // Skip directory entries\n      if (path.endsWith('/') && data.length === 0) continue;\n\n      const sanitizedPath = normalizePath(path);\n\n      // Empty after normalization (e.g. all \"../..\") has no servable address\n      if (!sanitizedPath) {\n        errors.push(`Skipped invalid path: ${path}`);\n        continue;\n      }\n\n      const filename = sanitizedPath.split('/').pop() || sanitizedPath;\n\n      // Copy to own ArrayBuffer (fflate shares backing buffers across entries).\n      // No `type` is set: the platform derives Content-Type from the path\n      // server-side, and nothing between here and the wire reads it.\n      const file = new File([new Uint8Array(data)], filename);\n\n      // Set webkitRelativePath to the full path — same contract as drag-and-drop\n      // files. This unifies the path mechanism: every file source carries its\n      // deploy path on webkitRelativePath and its bare name on file.name.\n      setRelativePath(file, sanitizedPath);\n\n      files.push(file);\n    }\n\n    return { files, errors };\n  } catch (error) {\n    return {\n      files: [],\n      errors: [\n        `Failed to load ZIP file: ${error instanceof Error ? error.message : String(error)}`,\n      ],\n    };\n  }\n}\n\n/**\n * Sanitize and normalize an archive entry path to prevent directory traversal.\n * Removes: .., ., leading/trailing slashes, absolute paths, and empty segments.\n *\n * @example\n * normalizePath('../../etc/passwd') → 'etc/passwd'\n * normalizePath('foo/./bar/../baz.txt') → 'foo/baz.txt'\n * normalizePath('/absolute/path.txt') → 'absolute/path.txt'\n */\nexport function normalizePath(path: string): string {\n  const normalized: string[] = [];\n\n  for (const segment of path.split('/')) {\n    if (segment === '' || segment === '.') continue;\n\n    if (segment === '..') {\n      // Pop only when there is somewhere to go back to — this is what prevents\n      // traversal above the archive root.\n      normalized.pop();\n      continue;\n    }\n\n    normalized.push(segment);\n  }\n\n  return normalized.join('/');\n}\n\n/**\n * Check if a file is a ZIP file based on MIME type or extension\n */\nexport function isZipFile(file: File): boolean {\n  return (\n    file.type === 'application/zip' ||\n    file.type === 'application/x-zip-compressed' ||\n    file.name.toLowerCase().endsWith('.zip')\n  );\n}\n","/**\n * The drop pipeline — everything between \"here are some Files\" and \"here is a\n * verdict\", with no React in sight.\n *\n * It takes `PlatformLimits` rather than a `Ship` client, which is what makes it\n * a plain function: source-name detection, ZIP extraction, unbuilt-project\n * detection and the project's source, junk filtering, path normalization,\n * entry-point and limit validation, all reachable by direct call. `useDrop` is a state machine over\n * this; a non-React consumer can call it directly.\n */\nimport { filterJunk, pluralize, validateFiles } from '@shipstatic/ship';\nimport {\n  FileValidationStatus,\n  hasUnbuiltMarker,\n  type PlatformLimits,\n  type ValidatableFile,\n} from '@shipstatic/types';\nimport { applyStatus, createProcessedFile, filePath, stripCommonPrefix } from './files';\nimport { projectSource } from './source';\nimport type { DropStatus, ProcessedFile } from './types';\nimport { extractZipToFiles, isZipFile } from './zip';\n\n/**\n * The two headings an error outcome can carry, in plain words. `details` and\n * `errors` beneath them are Ship's sentences, shown verbatim.\n */\n/** The drop was understood and the platform will not take it, an empty folder included. */\nexport const CANT_DEPLOY = \"Can't deploy this\";\n/** The drop could not be read or the platform could not be asked what it accepts. */\nexport const COULDNT_PREPARE = \"Couldn't prepare the files\";\n\nexport interface ProcessFilesOptions {\n  /** Platform limits, from `ship.getLimits()` */\n  limits: PlatformLimits;\n  /** Progress reporter for long steps */\n  onStatus?: (status: DropStatus) => void;\n}\n\n/**\n * The verdict. Mirrors the hook's state minus `isDragging`, which is a pointer\n * concern the pipeline knows nothing about.\n *\n * Ready files are `files.filter(f => f.status === FileValidationStatus.READY)` — kept as\n * one derivation rather than a second field that could disagree with the first.\n */\nexport interface DropOutcome {\n  phase: 'ready' | 'error';\n  files: ProcessedFile[];\n  sourceName: string;\n  status: DropStatus;\n  needsBuild: boolean;\n}\n\n/**\n * The exact shape drop hands to Ship's validator.\n *\n * **The deploy path is the name.** Server-side validation runs on full paths, so\n * sending the basename would validate a different string than the platform will.\n * `ProcessedFile` is not passed through directly even though it satisfies\n * `ValidatableFile`, because its `name` is the display basename.\n */\nexport function toValidatable(file: ProcessedFile): ValidatableFile {\n  return { name: file.path, size: file.size };\n}\n\n/** A friendly name for whatever the user dropped. */\nexport function detectSourceName(files: File[]): string {\n  if (files.length === 0) return '';\n\n  const [first] = files;\n  if (files.length === 1 && isZipFile(first)) return first.name.replace(/\\.zip$/i, '');\n\n  // A folder drop/selection carries its root in webkitRelativePath\n  const path = first.webkitRelativePath || '';\n  return path.includes('/') ? path.split('/')[0] : first.name;\n}\n\nfunction failure(params: {\n  title: string;\n  details: string;\n  errors?: string[];\n  files?: ProcessedFile[];\n  sourceName: string;\n}): DropOutcome {\n  const { title, details, errors, files = [], sourceName } = params;\n  // An error outcome is never a project to build: a project to be built is\n  // ready as it stands, and its build gives the verdict.\n  return {\n    phase: 'error',\n    files,\n    sourceName,\n    needsBuild: false,\n    // `details` carries the single user-facing message; `errors` is for per-item\n    // breakdowns. Omitted when empty, otherwise consumers that render both\n    // fields show the message twice.\n    status: { title, details, ...(errors?.length ? { errors } : {}) },\n  };\n}\n\n/**\n * Run the pipeline.\n *\n * Never throws: a missing entry point, a file over the limit, and an\n * unexpected host-object failure all come back as an `error` outcome. Callers\n * need no try/catch.\n */\nexport async function processFiles(\n  input: File[],\n  { limits, onStatus }: ProcessFilesOptions,\n): Promise<DropOutcome> {\n  // Assigned inside the try: reading `webkitRelativePath` touches host objects,\n  // and the no-throw guarantee has to cover the very first one.\n  let sourceName = '';\n\n  try {\n    sourceName = detectSourceName(input);\n\n    // Step 1: a lone ZIP is extracted; ZIPs among several files stay as files\n    let files: File[];\n    if (input.length === 1 && isZipFile(input[0])) {\n      onStatus?.({ title: 'Extracting...', details: `Extracting ${input[0].name}...` });\n      const { files: extracted, errors } = await extractZipToFiles(input[0]);\n      if (errors.length > 0) console.warn('ZIP extraction errors:', errors);\n      files = extracted;\n    } else {\n      files = input;\n    }\n\n    // Step 2: unbuilt-project detection. When the server will build, source\n    // files are legitimate input rather than a mistake, and the project is\n    // sent as its repository holds it: `projectSource` decides which files\n    // that is, once.\n    const needsBuild = files.some((f) => hasUnbuiltMarker(filePath(f)));\n    if (needsBuild) files = await projectSource(files);\n\n    // Step 3: junk filtering, for a built site only. A project's source is\n    // never filtered again: a build reads its dot files.\n    if (!needsBuild) {\n      const kept = new Set(filterJunk(files.map(filePath)));\n      files = files.filter((f) => kept.has(filePath(f)));\n    }\n\n    // Step 4: convert to ProcessedFile, then strip the common directory prefix.\n    // Empty files are kept: a built site's are marked EXCLUDED with a warning\n    // by validation, and a project's are source the build may import.\n    const finalFiles = stripCommonPrefix(files.map((f) => createProcessedFile(f)));\n\n    // Step 5: a project to be built is ready as it stands. The build decides\n    // what the site is, so neither the entry point nor the deploy limits apply\n    // to its source: many frameworks (Astro, Next.js, SvelteKit, Eleventy) have\n    // no index.html until they are built, and the build service refuses a build\n    // that produced no site, in its own words.\n    if (needsBuild) {\n      const ready = applyStatus(finalFiles, FileValidationStatus.READY);\n      return {\n        phase: 'ready',\n        files: ready,\n        sourceName,\n        needsBuild: true,\n        status: {\n          title: 'Ready',\n          details: `${pluralize(ready.length, 'file', 'files', true)} ready. We'll build the project.`,\n        },\n      };\n    }\n\n    // Step 6: the platform's deploy rules, through Ship: each file, then the\n    // site as a whole, a home page (index.html at its root) among them.\n    const validation = validateFiles(finalFiles.map(toValidatable), limits);\n\n    const validated = finalFiles.map((file, i) => ({\n      ...file,\n      status: validation.files[i]?.status ?? file.status,\n      statusMessage: validation.files[i]?.statusMessage ?? file.statusMessage,\n    }));\n\n    // Atomic validation: any error fails the whole set. Each issue is Ship's\n    // sentence as written: it already names its file, or the site when it is\n    // about the site, so nothing is prefixed. One issue is the message itself;\n    // several are listed under their count, since `errors` is a breakdown and\n    // one item is not one.\n    if (!validation.canDeploy) {\n      const issues = validation.errors.map((e) => e.message);\n      return failure({\n        title: CANT_DEPLOY,\n        ...(issues.length === 1\n          ? { details: issues[0] }\n          : { details: `${issues.length} things to fix`, errors: issues }),\n        files: validated,\n        sourceName,\n      });\n    }\n\n    // Deployable means the deploy rules found files to publish, a home page\n    // among them, so at least one file is ready; empty files are excluded\n    // beside them with a warning.\n    const readyCount = validated.filter((f) => f.status === FileValidationStatus.READY).length;\n    const warnings = validation.warnings.map((w) => w.message);\n    let details = `${pluralize(readyCount, 'file', 'files', true)} ready`;\n    if (validation.warnings.length > 0) {\n      details += ` (${pluralize(validation.warnings.length, 'empty file', 'empty files', true)} excluded)`;\n    }\n    return {\n      phase: 'ready',\n      files: validated,\n      sourceName,\n      needsBuild: false,\n      status: { title: 'Ready', details, ...(warnings.length ? { warnings } : {}) },\n    };\n  } catch (error) {\n    // Every refusal above is returned, never thrown, so what lands here is a\n    // failure to read the files: a host object, an archive, a .gitignore.\n    const message = error instanceof Error ? error.message : String(error);\n    return failure({\n      title: COULDNT_PREPARE,\n      details: message,\n      sourceName,\n    });\n  }\n}\n","/**\n * `FileSystemEntry` traversal — the drag-and-drop folder API.\n *\n * This module is alone in its file for a testing reason that is also an\n * architectural one: `FileSystemEntry` objects cannot be constructed. They come\n * from a real user gesture over real OS paths, so no browser — Chromium\n * included — lets a test produce one. Every OTHER module in this package is\n * exercised against real platform objects; this is the single boundary where a\n * fake is unavoidable, and keeping it to one file keeps that statement true.\n */\nimport { setRelativePath } from './files';\n\n/**\n * What a person is told when a dropped item gives neither a folder nor a file,\n * which leaves no name to give.\n */\nexport const UNREADABLE_DROP =\n  \"We couldn't read everything you dropped. Make sure the files are on this computer, then try again.\";\n\n/** What a person is told when part of a dropped folder cannot be read. */\nexport function unreadable(path: string): string {\n  return `We couldn't read ${path}. Make sure it's on this computer, then try again.`;\n}\n\n/** A read that either succeeds or fails naming what could not be read. */\nasync function readOrRefuse<T>(path: string, read: () => Promise<T>): Promise<T> {\n  try {\n    return await read();\n  } catch {\n    throw new Error(unreadable(path));\n  }\n}\n\n/**\n * Recursively collect Files from a dropped entry, setting `webkitRelativePath`\n * so folder structure survives.\n *\n * `node_modules` directories are skipped wholesale — never part of a valid\n * deployment, and traversing one costs real time on a source-project drop\n * (50K+ files).\n *\n * A file or folder that cannot be read fails the whole collection, naming it.\n * Skipping it would deploy a site without it, or send a project without its\n * `.gitignore` and so with every file that `.gitignore` keeps private. The\n * folder picker fails the same way, at upload.\n */\nexport async function traverseFileTree(\n  entry: FileSystemEntry,\n  files: File[],\n  currentPath = '',\n): Promise<void> {\n  if (entry.isFile) {\n    const path = currentPath ? `${currentPath}/${entry.name}` : entry.name;\n    const file = await readOrRefuse(\n      path,\n      () =>\n        new Promise<File>((resolve, reject) => {\n          (entry as FileSystemFileEntry).file(resolve, reject);\n        }),\n    );\n    setRelativePath(file, path);\n    files.push(file);\n    return;\n  }\n\n  if (!entry.isDirectory) return;\n\n  const children = await readOrRefuse(currentPath || entry.name, () =>\n    readDirectory(entry as FileSystemDirectoryEntry),\n  );\n  for (const child of children) {\n    if (child.isDirectory && child.name === 'node_modules') continue;\n\n    // Entering a directory extends the path; a file's own name is appended by\n    // the branch above, so it inherits the current path unchanged.\n    const childPath = child.isDirectory\n      ? currentPath\n        ? `${currentPath}/${child.name}`\n        : child.name\n      : currentPath;\n    await traverseFileTree(child, files, childPath);\n  }\n}\n\n/**\n * Read a directory to exhaustion.\n *\n * `readEntries` yields at most 100 entries per call and signals the end with an\n * empty batch, so a single call silently truncates any larger folder. Looping\n * until empty is the contract, not an optimization.\n */\nasync function readDirectory(directory: FileSystemDirectoryEntry): Promise<FileSystemEntry[]> {\n  const reader = directory.createReader();\n  const entries: FileSystemEntry[] = [];\n\n  for (;;) {\n    const batch = await new Promise<FileSystemEntry[]>((resolve, reject) => {\n      reader.readEntries(resolve, reject);\n    });\n    if (batch.length === 0) return entries;\n    entries.push(...batch);\n  }\n}\n","/**\n * Headless drop hook for file upload workflows.\n *\n * This file owns React state, DOM events, and prop getters — nothing else. The\n * rules live in `./process` as a plain function.\n *\n * ```tsx\n * const drop = useDrop({ ship });\n *\n * <div {...drop.getDropzoneProps()}>\n *   <input {...drop.getInputProps()} />\n *   {drop.isDragging ? 'Drop here' : 'Click to upload'}\n * </div>\n * ```\n */\nimport type { Ship } from '@shipstatic/ship';\nimport { FileValidationStatus, WEB_FILE_ACCEPT } from '@shipstatic/types';\nimport { useCallback, useMemo, useRef, useState } from 'react';\nimport { traverseFileTree, UNREADABLE_DROP } from './entries';\nimport { setRelativePath } from './files';\nimport { CANT_DEPLOY, COULDNT_PREPARE, processFiles as runPipeline } from './process';\nimport type { DropPhase, DropStatus, ProcessedFile } from './types';\n\nexport interface DropOptions {\n  /**\n   * The Ship client, for platform limits.\n   *\n   * Typed as only what drop calls, mirroring the SDK's own resource-factory\n   * doctrine — a real `Ship` satisfies it, and nothing else has to be faked.\n   */\n  ship: Pick<Ship, 'getLimits'>;\n}\n\n/** Options for `getDropzoneProps()` */\nexport interface DropzonePropsOptions {\n  /** Whether clicking the dropzone opens the file picker (default: true) */\n  clickable?: boolean;\n}\n\n/**\n * Which picker `getInputProps()` describes and `open()` opens.\n *\n * **Folder is the default**, so a bare `getInputProps()` / `open()` — and the\n * dropzone's own click — address the folder picker exactly as they always have.\n *\n * The singular/plural mix is deliberate: you pick one folder or many files, and\n * these are the words the buttons above them carry.\n */\nexport type PickerMode = 'folder' | 'files';\n\n/**\n * The hidden input to spread onto an `<input>`.\n *\n * One shape for both modes, because exactly one attribute distinguishes them:\n * `webkitdirectory` makes the dialog a folder picker, and `accept` biases a file\n * picker's default view. Never both — a folder picker ignores `accept`, so\n * emitting it there would advertise a filter that does not apply.\n */\nexport interface DropInputProps {\n  ref: React.RefObject<HTMLInputElement | null>;\n  type: 'file';\n  style: { display: string };\n  multiple: boolean;\n  /** Folder mode only — the attribute that makes it a folder picker. */\n  webkitdirectory?: string;\n  /**\n   * Files mode only. A HINT, not a gate: every dialog offers an all-files\n   * escape and drag-and-drop ignores `accept` outright, so the verdict on any\n   * file is `validateFiles` downstream — the same one the dropzone reaches.\n   */\n  accept?: string;\n  onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n}\n\nexport interface DropReturn {\n  /** Current phase of the lifecycle */\n  phase: DropPhase;\n  /** Whether files are being processed (extraction, validation) */\n  isProcessing: boolean;\n  /** Whether the user is currently dragging over the dropzone */\n  isDragging: boolean;\n  /** Whether the dropzone is idle or holding a ready set */\n  isInteractive: boolean;\n  /** Whether an error occurred during processing */\n  hasError: boolean;\n  /** All processed files */\n  files: ProcessedFile[];\n  /** Friendly name of what was dropped (ZIP name, folder name, or filename) */\n  sourceName: string;\n  /** Current status for display */\n  status: DropStatus | null;\n  /** Whether the dropped files need server-side building before deployment */\n  needsBuild: boolean;\n\n  /** Props to spread on the dropzone element (drag & drop, optionally click) */\n  getDropzoneProps: (options?: DropzonePropsOptions) => {\n    onDragOver: (e: React.DragEvent) => void;\n    onDragLeave: (e: React.DragEvent) => void;\n    onDrop: (e: React.DragEvent) => void;\n    onClick?: () => void;\n  };\n  /**\n   * Props to spread on a hidden file input element, one per picker mode.\n   *\n   * Each mode owns its own element and its own ref, so a UI offering both\n   * renders both inputs — `open(mode)` clicks whichever is mounted.\n   */\n  getInputProps: (mode?: PickerMode) => DropInputProps;\n\n  /** Programmatically trigger a picker (default: the folder picker) */\n  open: (mode?: PickerMode) => void;\n  /** Process files directly (advanced — loses folder traversal) */\n  processFiles: (files: File[]) => Promise<void>;\n  /** Reset state and clear all files */\n  reset: () => void;\n\n  /** Only the files that passed validation */\n  validFiles: ProcessedFile[];\n  /** Raw File objects ready for Ship SDK upload */\n  getFilesForUpload: () => File[];\n}\n\ninterface DropState {\n  phase: DropPhase;\n  isDragging: boolean;\n  files: ProcessedFile[];\n  sourceName: string;\n  status: DropStatus | null;\n  needsBuild: boolean;\n}\n\nconst initialState: DropState = {\n  phase: 'idle',\n  isDragging: false,\n  files: [],\n  sourceName: '',\n  status: null,\n  needsBuild: false,\n};\n\nexport function useDrop({ ship }: DropOptions): DropReturn {\n  const [state, setState] = useState<DropState>(initialState);\n\n  // The preparation run in flight, if any. A run is one selection from the\n  // moment it is made: collecting its files (a dropped folder is read\n  // asynchronously), reading the limits, the pipeline. One controller per run\n  // does three jobs: its presence is the synchronous re-entry guard (React\n  // state is too late to gate a second drop), its signal stops the limits read\n  // when the run is cancelled, and its `aborted` flag is how a run that was\n  // cancelled knows to say nothing more. Preparation outlives a cancel (a\n  // folder being read, an archive being inflated, a request already sent), so\n  // without that last one a retired run would finish over whatever the person\n  // selected next.\n  const runRef = useRef<AbortController | null>(null);\n  // One ref per picker: an <input> is either a folder picker or a file picker,\n  // and toggling `webkitdirectory` on a live node to reuse a single element\n  // would mean writing an attribute behind React's back.\n  const folderInputRef = useRef<HTMLInputElement>(null);\n  const filesInputRef = useRef<HTMLInputElement>(null);\n\n  const isProcessing = state.phase === 'processing';\n  const hasError = state.phase === 'error';\n  const isInteractive = state.phase === 'idle' || state.phase === 'ready';\n\n  const validFiles = useMemo(\n    () => state.files.filter((f) => f.status === FileValidationStatus.READY),\n    [state.files],\n  );\n\n  const getFilesForUpload = useCallback(() => validFiles.map((f) => f.file), [validFiles]);\n\n  // One selection, start to finish. `collect` is how its files arrive: at once\n  // from a picker, or after a dropped folder has been read.\n  const prepare = useCallback(\n    async (collect: () => Promise<File[]>) => {\n      if (runRef.current) {\n        console.warn('File processing already in progress. Ignoring duplicate call.');\n        return;\n      }\n\n      const run = new AbortController();\n      runRef.current = run;\n      setState({\n        ...initialState,\n        phase: 'processing',\n        status: { title: 'Processing...', details: 'Validating and preparing files.' },\n      });\n\n      try {\n        // The files and the limits are independent, so they are gathered\n        // together: the platform is asked while a dropped folder is read.\n        const [files, limits] = await Promise.all([\n          collect(),\n          ship.getLimits({ signal: run.signal }),\n        ]);\n        if (run.signal.aborted) return;\n        // A dropped folder with nothing in it to read. The pipeline is never\n        // asked, since there is no file to give a verdict on; the heading is\n        // the pipeline's own, because the platform cannot take an empty drop.\n        if (files.length === 0) {\n          setState({\n            ...initialState,\n            phase: 'error',\n            status: { title: CANT_DEPLOY, details: 'The folder has no files.' },\n          });\n          return;\n        }\n\n        const outcome = await runPipeline(files, {\n          limits,\n          // The pipeline says its status before its first wait, so a\n          // cancelled run has none left to say.\n          onStatus: (status) => setState((prev) => ({ ...prev, status })),\n        });\n        if (run.signal.aborted) return;\n\n        setState({\n          phase: outcome.phase,\n          isDragging: false,\n          files: outcome.files,\n          sourceName: outcome.sourceName,\n          status: outcome.status,\n          needsBuild: outcome.needsBuild,\n        });\n      } catch (error) {\n        // The pipeline never throws, so this is a dropped folder that could\n        // not be read whole (its sentence names what), or the limits read:\n        // the platform could not be asked what it accepts. Said in the error\n        // state like any other failed preparation, in the client's own words;\n        // a cancelled run's rejection is the cancel itself and says nothing.\n        if (run.signal.aborted) return;\n        setState({\n          ...initialState,\n          phase: 'error',\n          status: {\n            title: COULDNT_PREPARE,\n            details: error instanceof Error ? error.message : String(error),\n          },\n        });\n      } finally {\n        // Only its own slot: a run cancelled long ago must not free the guard\n        // of the run that replaced it.\n        if (runRef.current === run) runRef.current = null;\n      }\n    },\n    [ship],\n  );\n\n  const processFiles = useCallback(\n    async (newFiles: File[]) => {\n      if (!newFiles || newFiles.length === 0) return;\n      await prepare(async () => newFiles);\n    },\n    [prepare],\n  );\n\n  const reset = useCallback(() => {\n    runRef.current?.abort();\n    runRef.current = null;\n    setState(initialState);\n  }, []);\n\n  // Dragging is orthogonal to the phase: the flag flips, the phase is untouched.\n  const handleDragOver = useCallback((e: React.DragEvent) => {\n    e.preventDefault();\n    setState((prev) => (prev.isDragging ? prev : { ...prev, isDragging: true }));\n  }, []);\n\n  const handleDragLeave = useCallback((e: React.DragEvent) => {\n    e.preventDefault();\n    setState((prev) => (prev.isDragging ? { ...prev, isDragging: false } : prev));\n  }, []);\n\n  const handleDrop = useCallback(\n    async (e: React.DragEvent) => {\n      e.preventDefault();\n      setState((prev) => (prev.isDragging ? { ...prev, isDragging: false } : prev));\n\n      const files: File[] = [];\n      const directories: { entry: FileSystemEntry; path: string }[] = [];\n      let unreadable = false;\n\n      // The drag data is only valid synchronously: the browser invalidates it\n      // at the first await, so every entry is captured here and the folders are\n      // read afterwards, inside the run.\n      for (const item of Array.from(e.dataTransfer.items)) {\n        if (item.kind !== 'file') continue;\n        let entry: FileSystemEntry | null | undefined;\n        try {\n          entry = item.webkitGetAsEntry?.();\n        } catch {\n          // The file itself, below, is the fallback.\n        }\n        if (entry?.isDirectory) {\n          directories.push({ entry, path: entry.name });\n          continue;\n        }\n        const file = item.getAsFile();\n        if (file) {\n          // Root files carry their own name as path, matching traverseFileTree\n          setRelativePath(file, file.name);\n          files.push(file);\n        } else {\n          unreadable = true;\n        }\n      }\n\n      // A drop that carries no files is not a selection, and leaves the\n      // current one alone.\n      if (directories.length === 0 && files.length === 0 && !unreadable) return;\n\n      // A drop is read whole or refused, as a dropped folder is: an item that\n      // gave neither a folder nor a file fails the run rather than leaving\n      // its siblings to deploy without it.\n      await prepare(async () => {\n        if (unreadable) throw new Error(UNREADABLE_DROP);\n        await Promise.all(directories.map((d) => traverseFileTree(d.entry, files, d.path)));\n        return files;\n      });\n    },\n    [prepare],\n  );\n\n  const handleInputChange = useCallback(\n    (e: React.ChangeEvent<HTMLInputElement>) => {\n      const files = Array.from(e.target.files || []);\n      if (files.length > 0) processFiles(files);\n      // Clear the input so re-selecting the same folder fires onChange again\n      e.target.value = '';\n    },\n    [processFiles],\n  );\n\n  // `files` is the exception, so any other value — including a stray argument —\n  // resolves to the folder picker, and the default is written once.\n  const open = useCallback((mode?: PickerMode) => {\n    const input = mode === 'files' ? filesInputRef.current : folderInputRef.current;\n    if (!input) {\n      console.warn(\n        `No ${mode === 'files' ? 'files' : 'folder'} input is mounted. Spread getInputProps('${mode === 'files' ? 'files' : 'folder'}') onto an <input> to open this picker.`,\n      );\n      return;\n    }\n    input.click();\n  }, []);\n\n  const getDropzoneProps = useCallback(\n    (options?: DropzonePropsOptions) => {\n      const { clickable = true } = options ?? {};\n      return {\n        onDragOver: handleDragOver,\n        onDragLeave: handleDragLeave,\n        onDrop: handleDrop,\n        // Wrapped rather than passed by reference: `open` takes a mode, and a\n        // click handler would hand it a MouseEvent.\n        ...(clickable && { onClick: () => open() }),\n      };\n    },\n    [handleDragOver, handleDragLeave, handleDrop, open],\n  );\n\n  const getInputProps = useCallback(\n    (mode?: PickerMode): DropInputProps => ({\n      ref: mode === 'files' ? filesInputRef : folderInputRef,\n      type: 'file' as const,\n      style: { display: 'none' },\n      multiple: true,\n      ...(mode === 'files' ? { accept: WEB_FILE_ACCEPT } : { webkitdirectory: '' }),\n      onChange: handleInputChange,\n    }),\n    [handleInputChange],\n  );\n\n  return {\n    phase: state.phase,\n    isProcessing,\n    isDragging: state.isDragging,\n    isInteractive,\n    hasError,\n    files: state.files,\n    sourceName: state.sourceName,\n    status: state.status,\n    needsBuild: state.needsBuild,\n\n    getDropzoneProps,\n    getInputProps,\n\n    open,\n    processFiles,\n    reset,\n\n    validFiles,\n    getFilesForUpload,\n  };\n}\n"]}