@shipstatic/ship 0.2.3 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shared/lib/env.ts","../src/node/core/config.ts","../src/shared/lib/md5.ts","../src/node/core/platform-config.ts","../src/shared/lib/junk.ts","../src/shared/lib/path.ts","../src/shared/lib/deploy-paths.ts","../src/node/core/node-files.ts","../src/browser/lib/browser-files.ts","../src/node/core/prepare-input.ts","../src/node/cli/index.ts","../src/node/index.ts","../src/shared/api/http.ts","../src/shared/core/config.ts","../src/shared/lib/prepare-input.ts","../src/shared/resources.ts","../src/shared/base-ship.ts","../src/shared/index.ts","../src/shared/types.ts","../src/shared/core/constants.ts","../src/shared/lib/text.ts","../src/node/cli/utils.ts"],"sourcesContent":["/**\n * @file Environment detection utilities for the Ship SDK.\n * Helps in determining whether the SDK is running in a Node.js, browser, or unknown environment.\n */\n\n/**\n * Represents the detected or simulated JavaScript execution environment.\n */\nexport type ExecutionEnvironment = 'browser' | 'node' | 'unknown';\n\n/** @internal Environment override for testing. */\nlet _testEnvironment: ExecutionEnvironment | null = null;\n\n/**\n * **FOR TESTING PURPOSES ONLY.**\n *\n * Allows tests to override the detected environment, forcing the SDK to behave\n * as if it's running in the specified environment.\n *\n * @param env - The environment to simulate ('node', 'browser', 'unknown'),\n * or `null` to clear the override and revert to actual environment detection.\n * @internal\n */\nexport function __setTestEnvironment(env: ExecutionEnvironment | null): void {\n _testEnvironment = env;\n}\n\n/**\n * Detects the actual JavaScript execution environment (Node.js, browser, or unknown)\n * by checking for characteristic global objects.\n * @returns The detected environment as {@link ExecutionEnvironment}.\n * @internal\n */\nfunction detectEnvironment(): ExecutionEnvironment {\n // Check for Node.js environment\n if (typeof process !== 'undefined' && process.versions && process.versions.node) {\n return 'node';\n }\n\n // Check for Browser environment (including Web Workers)\n if (typeof window !== 'undefined' || typeof self !== 'undefined') {\n return 'browser';\n }\n\n return 'unknown';\n}\n\n/**\n * Gets the current effective execution environment.\n *\n * This function first checks if a test environment override is active via {@link __setTestEnvironment}.\n * If not, it detects the actual environment (Node.js, browser, or unknown).\n *\n * @returns The current execution environment: 'browser', 'node', or 'unknown'.\n * @public\n */\nexport function getENV(): ExecutionEnvironment {\n // Return test override if set\n if (_testEnvironment) {\n return _testEnvironment;\n }\n \n // Detect actual environment\n return detectEnvironment();\n}\n","/**\n * @file Manages loading and validation of client configuration.\n * This module uses `cosmiconfig` to find and load configuration from various\n * file sources (e.g., `.shiprc`, `package.json`) and environment variables.\n * Configuration values are validated using Zod schemas.\n */\n\nimport { z } from 'zod';\nimport type { ShipClientOptions, DeploymentOptions } from '../../shared/types.js';\nimport { ShipError } from '@shipstatic/types';\nimport { getENV } from '../../shared/lib/env.js';\nimport { DEFAULT_API } from '../../shared/core/constants.js';\n\n\n\n/** @internal Name of the module, used by cosmiconfig for config file searching. */\nconst MODULE_NAME = 'ship';\n\n/**\n * Zod schema for validating ship configuration.\n * @internal\n */\nconst ConfigSchema = z.object({\n apiUrl: z.string().url().optional(),\n apiKey: z.string().optional(),\n deployToken: z.string().optional()\n}).strict();\n\n/**\n * Validates configuration using Zod schema.\n * @param config - Configuration object to validate\n * @returns Validated configuration or throws error\n * @internal\n */\nfunction validateConfig(config: any): Partial<ShipClientOptions> {\n try {\n return ConfigSchema.parse(config);\n } catch (error) {\n if (error instanceof z.ZodError) {\n const firstError = error.issues[0];\n const path = firstError.path.length > 0 ? ` at ${firstError.path.join('.')}` : '';\n throw ShipError.config(`Configuration validation failed${path}: ${firstError.message}`);\n }\n throw ShipError.config('Configuration validation failed');\n }\n}\n\n/**\n * Loads client configuration from files.\n * Searches for .shiprc and package.json with ship key.\n * First searches from the current directory, then from the home directory.\n * @param configFile - Optional specific config file path to load\n * @returns Configuration object or empty if not found/invalid\n * @internal\n */\nasync function loadConfigFromFile(configFile?: string): Promise<Partial<ShipClientOptions>> {\n try {\n // Only use cosmiconfig in Node.js environments\n if (getENV() !== 'node') {\n return {};\n }\n \n // Dynamically import cosmiconfig and os only in Node.js environments\n const { cosmiconfigSync } = await import('cosmiconfig');\n const os = await import('os');\n \n const explorer = cosmiconfigSync(MODULE_NAME, {\n searchPlaces: [\n `.${MODULE_NAME}rc`,\n 'package.json',\n `${os.homedir()}/.${MODULE_NAME}rc`, // Always include home directory as fallback\n ],\n stopDir: os.homedir(), // Stop searching at home directory\n });\n \n let result;\n \n // If a specific config file is provided, load it directly\n if (configFile) {\n result = explorer.load(configFile);\n } else {\n // cosmiconfig automatically searches up the directory tree\n // from current directory to stopDir (home directory)\n result = explorer.search();\n }\n \n if (result && result.config) {\n return validateConfig(result.config);\n }\n } catch (error) {\n if (error instanceof ShipError) throw error; // Re-throw all ShipError instances\n // Silently fail for file loading issues - this is optional config\n }\n return {};\n}\n\n/**\n * Simplified configuration loading prioritizing environment variables.\n * Only loads file config if environment variables are not set.\n * Only available in Node.js environments.\n *\n * @param configFile - Optional specific config file path to load\n * @returns Configuration object with loaded values\n * @throws {ShipInvalidConfigError} If the configuration is invalid.\n */\nexport async function loadConfig(configFile?: string): Promise<Partial<ShipClientOptions>> {\n if (getENV() !== 'node') return {};\n\n // Start with environment variables (highest priority)\n const envConfig = {\n apiUrl: process.env.SHIP_API_URL,\n apiKey: process.env.SHIP_API_KEY,\n deployToken: process.env.SHIP_DEPLOY_TOKEN,\n };\n\n // Always try to load file config for fallback values\n const fileConfig = await loadConfigFromFile(configFile);\n\n // Merge with environment variables taking precedence\n const mergedConfig = {\n apiUrl: envConfig.apiUrl ?? fileConfig.apiUrl,\n apiKey: envConfig.apiKey ?? fileConfig.apiKey,\n deployToken: envConfig.deployToken ?? fileConfig.deployToken,\n };\n\n // Validate final config\n return validateConfig(mergedConfig);\n}\n\n","/**\n * @file Simplified MD5 calculation utility with separate environment handlers.\n */\nimport { getENV } from './env.js';\nimport { ShipError } from '@shipstatic/types';\n\nexport interface MD5Result {\n md5: string;\n}\n\n/**\n * Browser-specific MD5 calculation for Blob/File objects\n */\nasync function calculateMD5Browser(blob: Blob): Promise<MD5Result> {\n const SparkMD5 = (await import('spark-md5')).default;\n \n return new Promise((resolve, reject) => {\n const chunkSize = 2097152; // 2MB chunks\n const chunks = Math.ceil(blob.size / chunkSize);\n let currentChunk = 0;\n const spark = new SparkMD5.ArrayBuffer();\n const fileReader = new FileReader();\n\n const loadNext = () => {\n const start = currentChunk * chunkSize;\n const end = Math.min(start + chunkSize, blob.size);\n fileReader.readAsArrayBuffer(blob.slice(start, end));\n };\n\n fileReader.onload = (e) => {\n const result = e.target?.result as ArrayBuffer;\n if (!result) {\n reject(ShipError.business('Failed to read file chunk'));\n return;\n }\n \n spark.append(result);\n currentChunk++;\n \n if (currentChunk < chunks) {\n loadNext();\n } else {\n resolve({ md5: spark.end() });\n }\n };\n\n fileReader.onerror = () => {\n reject(ShipError.business('Failed to calculate MD5: FileReader error'));\n };\n\n loadNext();\n });\n}\n\n/**\n * Node.js-specific MD5 calculation for Buffer or file path\n */\nasync function calculateMD5Node(input: Buffer | string): Promise<MD5Result> {\n const crypto = await import('crypto');\n \n if (Buffer.isBuffer(input)) {\n const hash = crypto.createHash('md5');\n hash.update(input);\n return { md5: hash.digest('hex') };\n }\n \n // Handle file path\n const fs = await import('fs');\n return new Promise((resolve, reject) => {\n const hash = crypto.createHash('md5');\n const stream = fs.createReadStream(input);\n \n stream.on('error', err => \n reject(ShipError.business(`Failed to read file for MD5: ${err.message}`))\n );\n stream.on('data', chunk => hash.update(chunk));\n stream.on('end', () => resolve({ md5: hash.digest('hex') }));\n });\n}\n\n/**\n * Unified MD5 calculation that delegates to environment-specific handlers\n */\nexport async function calculateMD5(input: Blob | Buffer | string): Promise<MD5Result> {\n const env = getENV();\n \n if (env === 'browser') {\n if (!(input instanceof Blob)) {\n throw ShipError.business('Invalid input for browser MD5 calculation: Expected Blob or File.');\n }\n return calculateMD5Browser(input);\n }\n \n if (env === 'node') {\n if (!(Buffer.isBuffer(input) || typeof input === 'string')) {\n throw ShipError.business('Invalid input for Node.js MD5 calculation: Expected Buffer or file path string.');\n }\n return calculateMD5Node(input);\n }\n \n throw ShipError.business('Unknown or unsupported execution environment for MD5 calculation.');\n}\n","/**\n * @file Platform configuration management for the Ship SDK.\n * Implements fail-fast dynamic configuration with mandatory API fetch.\n */\n\nimport type { ConfigResponse } from '@shipstatic/types';\nimport { ShipError } from '@shipstatic/types';\n\n// Dynamic config - must be fetched from API before operations\nlet _config: ConfigResponse | null = null;\n\n/**\n * Set the current config (called after fetching from API)\n */\nexport function setConfig(config: ConfigResponse): void {\n _config = config;\n}\n\n/**\n * Get current config - throws if not initialized (fail-fast approach)\n * @throws {ShipError.config} If configuration hasn't been fetched from API\n */\nexport function getCurrentConfig(): ConfigResponse {\n if (_config === null) {\n throw ShipError.config(\n 'Platform configuration not initialized. The SDK must fetch configuration from the API before performing operations.'\n );\n }\n return _config;\n}\n\n/**\n * Check if config has been initialized from API\n */\nexport function isConfigInitialized(): boolean {\n return _config !== null;\n}\n\n/**\n * Reset config state (primarily for testing)\n * @internal\n */\nexport function resetConfig(): void {\n _config = null;\n}","/**\n * @file Utility for filtering out junk files and directories from file paths\n * \n * This module provides functionality to filter out common system junk files and directories\n * from a list of file paths. It uses the 'junk' package to identify junk filenames and\n * a custom list to filter out common junk directories.\n */\nimport { isJunk } from 'junk';\n\n/**\n * List of directory names considered as junk\n * \n * Files within these directories (at any level in the path hierarchy) will be excluded.\n * The comparison is case-insensitive for cross-platform compatibility.\n * \n * @internal\n */\nexport const JUNK_DIRECTORIES = [\n '__MACOSX',\n '.Trashes',\n '.fseventsd',\n '.Spotlight-V100',\n] as const;\n\n/**\n * Filters an array of file paths, removing those considered junk\n * \n * A path is filtered out if either:\n * 1. The basename is identified as junk by the 'junk' package (e.g., .DS_Store, Thumbs.db)\n * 2. Any directory segment in the path matches an entry in JUNK_DIRECTORIES (case-insensitive)\n *\n * All path separators are normalized to forward slashes for consistent cross-platform behavior.\n * \n * @param filePaths - An array of file path strings to filter\n * @returns A new array containing only non-junk file paths\n */\nexport function filterJunk(filePaths: string[]): string[] {\n if (!filePaths || filePaths.length === 0) {\n return [];\n }\n\n return filePaths.filter(filePath => {\n if (!filePath) {\n return false; // Exclude null or undefined paths\n }\n\n // Normalize path separators to forward slashes and split into segments\n const parts = filePath.replace(/\\\\/g, '/').split('/').filter(Boolean);\n if (parts.length === 0) return true;\n \n // Check if the basename is a junk file (using junk package)\n const basename = parts[parts.length - 1];\n if (isJunk(basename)) {\n return false;\n }\n\n // Check if any directory segment is in our junk directories list\n const directorySegments = parts.slice(0, -1);\n for (const segment of directorySegments) {\n if (JUNK_DIRECTORIES.some(junkDir => \n segment.toLowerCase() === junkDir.toLowerCase())) {\n return false;\n }\n }\n\n return true;\n });\n}\n","/**\n * @file Path helper utilities that work in both browser and Node.js environments.\n * Provides environment-agnostic path manipulation functions.\n */\n\n/**\n * Finds the common parent directory from an array of directory paths.\n * Simple, unified implementation for flattenDirs functionality.\n * \n * @param dirPaths - Array of directory paths (not file paths - directories containing the files)\n * @returns The common parent directory path, or empty string if none found\n */\nexport function findCommonParent(dirPaths: string[]): string {\n if (!dirPaths || dirPaths.length === 0) return '';\n \n // Normalize all paths to use forward slashes\n const normalizedPaths = dirPaths\n .filter(p => p && typeof p === 'string')\n .map(p => p.replace(/\\\\/g, '/'));\n \n if (normalizedPaths.length === 0) return '';\n if (normalizedPaths.length === 1) return normalizedPaths[0];\n \n // Split into segments and find common prefix\n const pathSegments = normalizedPaths.map(p => p.split('/').filter(Boolean));\n const commonSegments = [];\n const minLength = Math.min(...pathSegments.map(p => p.length));\n \n for (let i = 0; i < minLength; i++) {\n const segment = pathSegments[0][i];\n if (pathSegments.every(segments => segments[i] === segment)) {\n commonSegments.push(segment);\n } else {\n break;\n }\n }\n \n return commonSegments.join('/');\n}\n\n\n\n/**\n * Converts backslashes to forward slashes for cross-platform compatibility.\n * Does not remove leading slashes (preserves absolute paths).\n * @param path - The path to normalize\n * @returns Path with forward slashes\n */\nexport function normalizeSlashes(path: string): string {\n return path.replace(/\\\\/g, '/');\n}\n\n/**\n * Normalizes a path for web usage by converting backslashes to forward slashes\n * and removing leading slashes.\n * @param path - The path to normalize\n * @returns Normalized path suitable for web deployment\n */\nexport function normalizeWebPath(path: string): string {\n return path.replace(/\\\\/g, '/').replace(/\\/+/g, '/').replace(/^\\/+/, '');\n}\n\n","/**\n * @file Deploy path optimization - the core logic that makes Ship deployments clean and intuitive.\n * Automatically strips common parent directories to create clean deployment URLs.\n */\n\nimport { normalizeWebPath } from './path.js';\n\n/**\n * Represents a file ready for deployment with its optimized path\n */\nexport interface DeployFile {\n /** The clean deployment path (e.g., \"assets/style.css\") */\n path: string;\n /** Original filename */\n name: string;\n}\n\n/**\n * Core path optimization logic.\n * Transforms messy local paths into clean deployment paths.\n * \n * @example\n * Input: [\"dist/index.html\", \"dist/assets/app.js\"]\n * Output: [\"index.html\", \"assets/app.js\"]\n * \n * @param filePaths - Raw file paths from the local filesystem\n * @param options - Path processing options\n */\nexport function optimizeDeployPaths(\n filePaths: string[], \n options: { flatten?: boolean } = {}\n): DeployFile[] {\n // When flattening is disabled, keep original structure\n if (options.flatten === false) {\n return filePaths.map(path => ({\n path: normalizeWebPath(path),\n name: extractFileName(path)\n }));\n }\n\n // Find the common directory prefix to strip\n const commonPrefix = findCommonDirectory(filePaths);\n \n return filePaths.map(filePath => {\n let deployPath = normalizeWebPath(filePath);\n \n // Strip the common prefix to create clean deployment paths\n if (commonPrefix) {\n const prefixToRemove = commonPrefix.endsWith('/') ? commonPrefix : `${commonPrefix}/`;\n if (deployPath.startsWith(prefixToRemove)) {\n deployPath = deployPath.substring(prefixToRemove.length);\n }\n }\n \n // Fallback to filename if path becomes empty\n if (!deployPath) {\n deployPath = extractFileName(filePath);\n }\n \n return {\n path: deployPath,\n name: extractFileName(filePath)\n };\n });\n}\n\n/**\n * Finds the common directory shared by all file paths.\n * This is what gets stripped to create clean deployment URLs.\n * \n * @example\n * [\"dist/index.html\", \"dist/assets/app.js\"] → \"dist\"\n * [\"src/components/A.tsx\", \"src/utils/B.ts\"] → \"src\"\n * [\"file1.txt\", \"file2.txt\", \"subdir/file3.txt\"] → \"\" (no common directory)\n */\nfunction findCommonDirectory(filePaths: string[]): string {\n if (!filePaths.length) return '';\n \n // Normalize all paths first\n const normalizedPaths = filePaths.map(path => normalizeWebPath(path));\n \n // Find the common prefix among all file paths (not just directories)\n const pathSegments = normalizedPaths.map(path => path.split('/'));\n const commonSegments: string[] = [];\n const minLength = Math.min(...pathSegments.map(segments => segments.length));\n \n // Check each segment level to find the longest common prefix\n for (let i = 0; i < minLength - 1; i++) { // -1 because we don't want to include the filename\n const segment = pathSegments[0][i];\n if (pathSegments.every(segments => segments[i] === segment)) {\n commonSegments.push(segment);\n } else {\n break;\n }\n }\n \n return commonSegments.join('/');\n}\n\n/**\n * Extracts just the filename from a file path\n */\nfunction extractFileName(path: string): string {\n return path.split(/[/\\\\]/).pop() || path;\n}","/**\n * @file Node.js-specific file utilities for the Ship SDK.\n * Provides helpers for recursively discovering, filtering, and preparing files for deploy in Node.js.\n */\nimport { getENV } from '../../shared/lib/env.js';\nimport type { StaticFile, DeploymentOptions } from '../../shared/types.js';\nimport { calculateMD5 } from '../../shared/lib/md5.js';\nimport { filterJunk } from '../../shared/lib/junk.js';\nimport { ShipError } from '@shipstatic/types';\nimport { getCurrentConfig } from './platform-config.js';\nimport { optimizeDeployPaths } from '../../shared/lib/deploy-paths.js';\nimport { findCommonParent } from '../../shared/lib/path.js';\n\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n\n/**\n * Simple recursive function to walk directory and return all file paths.\n * More declarative and focused than the previous implementation.\n * @param dirPath - Directory path to traverse\n * @returns Array of absolute file paths in the directory\n */\nfunction findAllFilePaths(dirPath: string): string[] {\n const results: string[] = [];\n \n try {\n const entries = fs.readdirSync(dirPath);\n \n for (const entry of entries) {\n const fullPath = path.join(dirPath, entry);\n const stats = fs.statSync(fullPath);\n \n if (stats.isDirectory()) {\n const subFiles = findAllFilePaths(fullPath);\n results.push(...subFiles);\n } else if (stats.isFile()) {\n results.push(fullPath);\n }\n }\n } catch (error) {\n console.error(`Error reading directory ${dirPath}:`, error);\n }\n \n return results;\n}\n\n/**\n * Processes Node.js file and directory paths into an array of StaticFile objects ready for deploy.\n * Uses corrected logic to properly handle common parent directory stripping.\n * \n * @param paths - File or directory paths to scan and process.\n * @param options - Processing options (pathDetect, etc.).\n * @returns Promise resolving to an array of StaticFile objects.\n * @throws {ShipClientError} If called outside Node.js or if fs/path modules fail.\n */\nexport async function processFilesForNode(\n paths: string[],\n options: DeploymentOptions = {}\n): Promise<StaticFile[]> {\n if (getENV() !== 'node') {\n throw ShipError.business('processFilesForNode can only be called in Node.js environment.');\n }\n\n // 1. Discover all unique, absolute file paths from the input list\n const absolutePaths = paths.flatMap(p => {\n const absPath = path.resolve(p);\n try {\n const stats = fs.statSync(absPath);\n return stats.isDirectory() ? findAllFilePaths(absPath) : [absPath];\n } catch (error) {\n throw ShipError.file(`Path does not exist: ${p}`, p);\n }\n });\n const uniquePaths = [...new Set(absolutePaths)];\n \n // 2. Filter out junk files from the final list\n const validPaths = filterJunk(uniquePaths);\n if (validPaths.length === 0) {\n return [];\n }\n\n // 3. Determine the base path for calculating relative paths\n // Find the common parent of the INPUT paths (not the discovered file paths)\n const inputAbsolutePaths = paths.map(p => path.resolve(p));\n const inputBasePath = findCommonParent(inputAbsolutePaths.map(p => {\n try {\n const stats = fs.statSync(p);\n return stats.isDirectory() ? p : path.dirname(p);\n } catch {\n return path.dirname(p);\n }\n }));\n\n // 4. Create raw relative paths for optimization\n const relativePaths = validPaths.map(filePath => {\n // If we have a meaningful common base path from inputs, use it\n if (inputBasePath && inputBasePath.length > 0) {\n const rel = path.relative(inputBasePath, filePath);\n if (rel && typeof rel === 'string' && !rel.startsWith('..')) {\n return rel.replace(/\\\\/g, '/');\n }\n }\n \n // Fallback: if no good common parent or relative path goes up, just use basename\n return path.basename(filePath);\n });\n\n // 5. Optimize paths for deployment (flattening)\n const deployFiles = optimizeDeployPaths(relativePaths, {\n flatten: options.pathDetect !== false\n });\n\n // 6. Process files into StaticFile objects\n const results: StaticFile[] = [];\n let totalSize = 0;\n const platformLimits = getCurrentConfig();\n\n for (let i = 0; i < validPaths.length; i++) {\n const filePath = validPaths[i];\n const deployPath = deployFiles[i].path;\n \n try {\n const stats = fs.statSync(filePath);\n if (stats.size === 0) {\n console.warn(`Skipping empty file: ${filePath}`);\n continue; // Skip empty files\n }\n\n // Validate file sizes\n if (stats.size > platformLimits.maxFileSize) {\n throw ShipError.business(`File ${filePath} is too large. Maximum allowed size is ${platformLimits.maxFileSize / (1024 * 1024)}MB.`);\n }\n totalSize += stats.size;\n if (totalSize > platformLimits.maxTotalSize) {\n throw ShipError.business(`Total deploy size is too large. Maximum allowed is ${platformLimits.maxTotalSize / (1024 * 1024)}MB.`);\n }\n\n const content = fs.readFileSync(filePath);\n const { md5 } = await calculateMD5(content);\n \n // Security validation: Ensure no dangerous characters in paths\n if (deployPath.includes('\\0') || deployPath.includes('/../') || deployPath.startsWith('../') || deployPath.endsWith('/..')) {\n throw ShipError.business(`Security error: Unsafe file path \"${deployPath}\" for file: ${filePath}`);\n }\n \n results.push({\n path: deployPath,\n content,\n size: content.length,\n md5,\n });\n } catch (error) {\n if (error instanceof ShipError && error.isClientError && error.isClientError()) {\n throw error;\n }\n console.error(`Could not process file ${filePath}:`, error);\n }\n }\n\n // Final validation\n if (results.length > platformLimits.maxFilesCount) {\n throw ShipError.business(`Too many files to deploy. Maximum allowed is ${platformLimits.maxFilesCount} files.`);\n }\n \n return results;\n}","/**\n * @file Browser-specific file utilities for the Ship SDK.\n * Provides helpers for processing browser files into deploy-ready objects and extracting common directory info.\n */\nimport type { StaticFile, DeploymentOptions } from '../../shared/types.js';\nimport { calculateMD5 } from '../../shared/lib/md5.js';\nimport { ShipError } from '@shipstatic/types';\nimport { filterJunk } from '../../shared/lib/junk.js';\nimport { optimizeDeployPaths } from '../../shared/lib/deploy-paths.js';\n\n\n/**\n * Internal structure representing a browser file to be processed for deploy.\n * @internal\n */\ninterface BrowserFileProcessItem {\n file: File;\n relativePath: string;\n}\n\n/**\n * Processes browser files (FileList or File[]) into an array of StaticFile objects ready for deploy.\n * Calculates MD5, filters junk files, and applies automatic path optimization.\n *\n * @param browserFiles - FileList or File[] to process for deploy.\n * @param options - Processing options including pathDetect for automatic path optimization.\n * @returns Promise resolving to an array of StaticFile objects.\n * @throws {ShipClientError} If called outside a browser or with invalid input.\n */\nexport async function processFilesForBrowser(\n browserFiles: FileList | File[],\n options: DeploymentOptions = {}\n): Promise<StaticFile[]> {\n // Check environment using getENV\n const { getENV } = await import('../../shared/lib/env.js');\n if (getENV() !== 'browser') {\n throw ShipError.business('processFilesForBrowser can only be called in a browser environment.');\n }\n\n const filesArray = Array.isArray(browserFiles) ? browserFiles : Array.from(browserFiles);\n \n // Extract file paths from browser files, preferring webkitRelativePath for directory structure\n const filePaths = filesArray.map(file => (file as any).webkitRelativePath || file.name);\n \n // Optimize paths for clean deployment URLs\n const deployFiles = optimizeDeployPaths(filePaths, { \n flatten: options.pathDetect !== false \n });\n \n // Prepare file information with security validation\n const initialFileInfos: BrowserFileProcessItem[] = [];\n for (let i = 0; i < filesArray.length; i++) {\n const file = filesArray[i];\n const deployPath = deployFiles[i].path;\n \n // Security validation: Ensure no dangerous characters in paths\n if (deployPath.includes('..') || deployPath.includes('\\0')) {\n throw ShipError.business(`Security error: Unsafe file path \"${deployPath}\" for file: ${file.name}`);\n }\n \n initialFileInfos.push({ file, relativePath: deployPath });\n }\n\n // Filter out junk files\n const allRelativePaths = initialFileInfos.map(info => info.relativePath);\n const nonJunkRelativePathsArray = filterJunk(allRelativePaths);\n const nonJunkRelativePathsSet = new Set(nonJunkRelativePathsArray);\n\n // Create StaticFile objects for each valid file\n const result: StaticFile[] = [];\n for (const fileInfo of initialFileInfos) {\n // Skip junk files but NOT empty files (tests expect empty files to be processed)\n if (!nonJunkRelativePathsSet.has(fileInfo.relativePath)) {\n continue;\n }\n \n // Calculate MD5 hash\n const { md5 } = await calculateMD5(fileInfo.file);\n \n // Create and add the StaticFile - keep File as File (impossible simplicity!)\n result.push({\n content: fileInfo.file,\n path: fileInfo.relativePath,\n size: fileInfo.file.size,\n md5,\n });\n }\n \n return result;\n}\n\n","/**\n * @file Input conversion utilities for deployment\n * Converts various input types to StaticFile[] for unified processing\n */\n\nimport type { StaticFile, DeploymentOptions, DeployInput } from '../../shared/types.js';\nimport { ShipError, DEPLOYMENT_CONFIG_FILENAME } from '@shipstatic/types';\nimport { getENV } from '../../shared/lib/env.js';\nimport { processFilesForNode } from './node-files.js';\nimport { processFilesForBrowser } from '../../browser/lib/browser-files.js';\nimport { getCurrentConfig } from './platform-config.js';\nimport { calculateMD5 } from '../../shared/lib/md5.js';\n\n\n/**\n * Fail-fast file validation for both Node.js and browser environments\n * Validates immediately without collecting all files first for better performance\n * @param files - Array of files to validate (can be File[] or file metadata)\n * @param options - Validation options\n * @throws {ShipError} If validation fails\n * @internal\n */\nfunction validateFiles(files: Array<{ name: string; size: number }>, options: { skipEmptyCheck?: boolean } = {}): void {\n const config = getCurrentConfig();\n \n // Check for empty file array - fail fast\n if (!options.skipEmptyCheck && files.length === 0) {\n throw ShipError.business('No files to deploy.');\n }\n \n // Check file count limit - fail fast\n if (files.length > config.maxFilesCount) {\n throw ShipError.business(`Too many files to deploy. Maximum allowed is ${config.maxFilesCount}.`);\n }\n \n // Validate individual files and calculate total size - fail on first violation\n let totalSize = 0;\n for (const file of files) {\n // Individual file size validation - fail immediately\n if (file.size > config.maxFileSize) {\n throw ShipError.business(`File ${file.name} is too large. Maximum allowed size is ${config.maxFileSize / (1024 * 1024)}MB.`);\n }\n \n // Accumulate total size and check incrementally for early failure\n totalSize += file.size;\n if (totalSize > config.maxTotalSize) {\n throw ShipError.business(`Total deploy size is too large. Maximum allowed is ${config.maxTotalSize / (1024 * 1024)}MB.`);\n }\n }\n}\n\n/**\n * Early validation for file count and basic input\n * Used before file processing to fail fast on obvious issues\n * @param input - Input to validate\n * @param environment - Current environment (node/browser)\n * @throws {ShipError} If validation fails\n * @internal\n */\nfunction validateInputEarly(input: any, environment: string): void {\n if (environment === 'node') {\n if (!Array.isArray(input)) {\n throw ShipError.business('Invalid input type for Node.js environment. Expected string[] file paths.');\n }\n if (input.length === 0) {\n throw ShipError.business('No files to deploy.');\n }\n if (!input.every(item => typeof item === 'string')) {\n throw ShipError.business('Invalid input type for Node.js environment. Expected string[] file paths.');\n }\n } else if (environment === 'browser') {\n if (input instanceof HTMLInputElement && !input.files) {\n throw ShipError.business('No files selected in HTMLInputElement');\n }\n }\n}\n\n/**\n * Shared post-processing logic for StaticFile arrays\n * @param files - Array of StaticFile objects to process\n * @returns Processed StaticFile array\n * @internal\n */\nfunction postProcessFiles(files: StaticFile[]): StaticFile[] {\n // Validate processed files - convert StaticFile[] to the expected format\n const validationFiles = files.map(f => ({ name: f.path, size: f.size }));\n validateFiles(validationFiles, { skipEmptyCheck: true });\n \n // Normalize paths to forward slashes\n files.forEach(f => {\n if (f.path) f.path = f.path.replace(/\\\\/g, '/');\n });\n \n return files;\n}\n\n/**\n * Converts Node.js string[] paths to StaticFile[]\n */\nexport async function convertNodeInput(\n input: string[], \n options: DeploymentOptions = {}\n): Promise<StaticFile[]> {\n // Early validation - fail fast before processing\n validateInputEarly(input, 'node');\n\n // Pass options directly to node processor - no conflicting logic here\n const staticFiles: StaticFile[] = await processFilesForNode(input, options);\n \n // Apply shared validation and post-processing\n return postProcessFiles(staticFiles);\n}\n\n/**\n * Converts browser FileList/File[]/HTMLInputElement to StaticFile[]\n */\nexport async function convertBrowserInput(\n input: FileList | File[] | HTMLInputElement,\n options: DeploymentOptions = {}\n): Promise<StaticFile[]> {\n // Early validation - fail fast before processing\n validateInputEarly(input, 'browser');\n\n let fileArray: File[];\n \n if (input instanceof HTMLInputElement) {\n fileArray = Array.from(input.files!);\n } else if (\n typeof input === 'object' &&\n input !== null &&\n typeof (input as any).length === 'number' &&\n typeof (input as any).item === 'function'\n ) {\n fileArray = Array.from(input as FileList);\n } else if (Array.isArray(input)) {\n if (input.length > 0 && typeof input[0] === 'string') {\n throw ShipError.business('Invalid input type for browser environment. Expected File[], FileList, or HTMLInputElement.');\n }\n fileArray = input as File[];\n } else {\n throw ShipError.business('Invalid input type for browser environment. Expected File[], FileList, or HTMLInputElement.');\n }\n\n // Filter out empty files first\n fileArray = fileArray.filter(file => {\n if (file.size === 0) {\n console.warn(`Skipping empty file: ${file.name}`);\n return false;\n }\n return true;\n });\n\n // Early validation using shared logic - fail fast before heavy processing\n validateFiles(fileArray);\n\n // Pass options directly to browser processor - no conflicting logic here\n const staticFiles: StaticFile[] = await processFilesForBrowser(fileArray as File[], options);\n \n // Apply shared validation and post-processing\n return postProcessFiles(staticFiles);\n}\n\n/**\n * Unified input conversion function with automatic SPA detection\n * Converts any DeployInput to StaticFile[] and auto-generates ship.json for SPAs\n */\nexport async function convertDeployInput(\n input: DeployInput,\n options: DeploymentOptions = {},\n apiClient?: any\n): Promise<StaticFile[]> {\n const environment = getENV();\n \n // Early validation at the unified level - fail immediately on environment issues\n if (environment !== 'node' && environment !== 'browser') {\n throw ShipError.business('Unsupported execution environment.');\n }\n \n // Convert input to StaticFile[] based on environment\n let files: StaticFile[];\n if (environment === 'node') {\n // Normalize string to string[] for Node.js processing\n if (typeof input === 'string') {\n files = await convertNodeInput([input], options);\n } else if (Array.isArray(input) && input.every(item => typeof item === 'string')) {\n files = await convertNodeInput(input as string[], options);\n } else {\n throw ShipError.business('Invalid input type for Node.js environment. Expected string[] file paths.');\n }\n } else {\n files = await convertBrowserInput(input as FileList | File[] | HTMLInputElement, options);\n }\n \n return files;\n}\n\n","/**\n * @file Main entry point for the Ship CLI.\n * Ultra-simple CLI with explicit commands and deploy shortcut.\n */\nimport { Command } from 'commander';\nimport { Ship, ShipError } from '../index.js';\nimport { validateApiKey, validateDeployToken, validateApiUrl } from '@shipstatic/types';\nimport { readFileSync, existsSync, statSync } from 'fs';\nimport * as path from 'path';\nimport { formatTable, formatDetails, success, error, info, warn } from './utils.js';\nimport { bold, dim } from 'yoctocolors';\n// Removed tabtab dependency - now using custom completion script\nimport * as fs from 'fs';\nimport * as os from 'os';\n\n// Get package.json data for version information using robust path resolution\nlet packageJson: any = { version: '0.0.0' };\n\ntry {\n // For the built CLI, package.json is always one level up from the dist directory\n // This is more reliable than hardcoded multiple fallback paths\n const packageJsonPath = path.resolve(__dirname, '../package.json');\n packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n} catch (error) {\n // Fallback for development/testing scenarios where the structure might differ\n const developmentPath = path.resolve(__dirname, '../../package.json');\n try {\n packageJson = JSON.parse(readFileSync(developmentPath, 'utf-8'));\n } catch (fallbackError) {\n // Final fallback - use default version\n // This is better than silent failure as it gives visibility into the issue\n }\n}\n\n\n\nconst program = new Command();\n\n// Override Commander.js error handling while preserving help/version behavior\nprogram\n .exitOverride((err) => {\n // Only override actual errors, not help/version exits\n if (err.code === 'commander.help' || err.code === 'commander.version' || err.exitCode === 0) {\n process.exit(err.exitCode || 0);\n }\n \n const globalOptions = program.opts();\n \n // Extract the actual error message from Commander.js error\n let message = err.message || 'unknown command error';\n \n // Clean up common Commander.js error messages\n message = message\n .replace(/^error: /, '') // Remove Commander's error prefix\n .replace(/\\n.*/, '') // Keep only the first line\n .replace(/\\.$/, '') // Remove trailing period\n .toLowerCase(); // Make lowercase\n \n // Route through our error function for consistent formatting\n error(message, globalOptions.json, globalOptions.noColor);\n \n // Show help after error (unless in JSON mode)\n if (!globalOptions.json) {\n displayHelp(globalOptions.noColor);\n }\n \n process.exit(err.exitCode || 1);\n })\n .configureOutput({\n // Suppress Commander's default error output - we handle it in exitOverride\n writeErr: (str) => {\n // Only suppress error output, allow help/version to go through\n if (!str.startsWith('error:')) {\n process.stderr.write(str);\n }\n },\n writeOut: (str) => process.stdout.write(str)\n });\n\n// CLI formatting helpers are imported from utils.js\n\n\n/**\n * Display comprehensive help information for all commands\n */\nfunction displayHelp(noColor?: boolean) {\n const applyBold = (text: string) => noColor ? text : bold(text);\n const applyDim = (text: string) => noColor ? text : dim(text);\n \n const output = `${applyBold('USAGE')}\n ship <path> 🚀 Deploy static sites with simplicity\n\n${applyBold('COMMANDS')}\n 📦 ${applyBold('Deployments')}\n ship deployments list List all deployments\n ship deployments create <path> Create deployment from file or directory\n ship deployments get <deployment> Show deployment information\n ship deployments remove <deployment> Delete deployment permanently\n\n 🌎 ${applyBold('Aliases')}\n ship aliases list List all aliases\n ship aliases set <name> <deployment> Create or update alias pointing to deployment\n ship aliases get <name> Show alias information\n ship aliases check <name> Manually trigger DNS check for external alias\n ship aliases remove <name> Delete alias permanently\n\n 🦸 ${applyBold('Account')}\n ship whoami Get current account information\n\n 🛠️ ${applyBold('Completion')}\n ship completion install Install shell completion script\n ship completion uninstall Uninstall shell completion script\n\n${applyBold('FLAGS')}\n --api-key <key> API key for authenticated deployments\n --deploy-token <token> Deploy token for single-use deployments\n --config <file> Custom config file path\n --no-path-detect Disable automatic path optimization and flattening\n --no-spa-detect Disable automatic SPA detection and configuration\n --no-color Disable colored output\n --json Output results in JSON format\n --version Show version information\n\n${applyDim('Please report any issues to https://github.com/shipstatic/ship/issues')}\n`;\n\n console.log(output);\n}\n\n/**\n * Process CLI options using Commander's built-in option merging.\n * Applies CLI-specific transformations and validations.\n */\nfunction processOptions(command: any): any {\n // Use Commander's built-in option merging - much simpler!\n const options = command.opts();\n \n // Convert Commander.js --no-color flag (color: false) to our convention (noColor: true)\n if (options.color === false) {\n options.noColor = true;\n }\n \n // Validate options early\n try {\n if (options.apiKey && typeof options.apiKey === 'string') {\n validateApiKey(options.apiKey);\n }\n \n if (options.deployToken && typeof options.deployToken === 'string') {\n validateDeployToken(options.deployToken);\n }\n \n if (options.apiUrl && typeof options.apiUrl === 'string') {\n validateApiUrl(options.apiUrl);\n }\n } catch (validationError) {\n if (validationError instanceof ShipError) {\n error(validationError.message, options.json, options.noColor);\n process.exit(1);\n }\n throw validationError;\n }\n \n return options;\n}\n\n/**\n * Error handler using ShipError type guards - all errors should be ShipError instances\n */\nfunction handleError(err: any, context?: { operation?: string; resourceType?: string; resourceId?: string }, options?: any) {\n // Always get options from the root program object to ensure global flags are included.\n const opts = program.opts();\n // All errors in this codebase should be ShipError instances\n if (!(err instanceof ShipError)) {\n const message = err.message || err;\n \n if (opts.json) {\n console.error(JSON.stringify({ \n error: message,\n details: { originalError: message }\n }, null, 2));\n console.error();\n } else {\n error(message, opts.json, opts.noColor);\n // Show help after error (unless in JSON mode)\n displayHelp(opts.noColor);\n }\n process.exit(1);\n }\n\n let message = err.message;\n \n // Handle specific error types based on error details\n if (err.details?.data?.error === 'not_found') {\n if (context?.operation === 'remove') {\n const resourceType = context.resourceType || 'resource';\n const resourceId = context.resourceId || '';\n message = `${resourceId} ${resourceType.toLowerCase()} not found`;\n } else {\n // For other operations (like aliases set), use consistent format\n const originalMessage = err.details.data.message || 'Resource not found';\n // Convert \"Deployment X not found\" to \"Deployment not found: X\" format\n const match = originalMessage.match(/^(.*?)\\s+(.+?)\\s+not found$/);\n if (match) {\n const [, resourceType, resourceId] = match;\n message = `${resourceId} ${resourceType.toLowerCase()} not found`;\n } else {\n message = originalMessage;\n }\n }\n }\n // Handle business logic errors with detailed messages\n else if (err.details?.data?.error === 'business_logic_error') {\n message = err.details.data.message || 'Business logic error occurred';\n }\n // User-friendly messages for common error types \n else if (err.isAuthError()) {\n message = 'authentication failed';\n }\n else if (err.isNetworkError()) {\n message = 'network error';\n }\n // For file, validation, and client errors, trust the original message\n // For server errors, provide generic fallback\n else if (!err.isFileError() && !err.isValidationError() && !err.isClientError()) {\n message = 'server error';\n }\n \n if (opts.json) {\n console.error(JSON.stringify({ \n error: message,\n ...(err.details ? { details: err.details } : {})\n }, null, 2));\n console.error();\n } else {\n error(message, opts.json, opts.noColor);\n // Show help for validation errors related to unknown commands\n if (err.isValidationError() && message.includes('unknown command')) {\n displayHelp(opts.noColor);\n }\n // Don't show help for other ShipError instances - these are API/system errors, not user CLI mistakes\n }\n process.exit(1);\n}\n\n/**\n * Wrapper for CLI actions that handles errors and client creation consistently\n * Reduces boilerplate while preserving context for error handling\n */\nfunction withErrorHandling<T extends any[], R>(\n handler: (client: Ship, ...args: T) => Promise<R>,\n context?: { operation?: string; resourceType?: string; getResourceId?: (...args: T) => string }\n) {\n return async function(this: any, ...args: T) {\n try {\n // Get processed options using Commander's built-in merging (including validation!)\n const globalOptions = processOptions(this);\n \n const client = createClient();\n const result = await handler(client, ...args);\n \n // Build context for output if provided\n const outputContext = context ? {\n operation: context.operation,\n resourceType: context.resourceType,\n resourceId: context.getResourceId ? context.getResourceId(...args) : undefined\n } : undefined;\n \n output(result, outputContext, globalOptions);\n } catch (error: any) {\n const errorContext = context ? {\n operation: context.operation,\n resourceType: context.resourceType,\n resourceId: context.getResourceId ? context.getResourceId(...args) : undefined\n } : undefined;\n \n // Get processed options using Commander's built-in merging\n const globalOptions = processOptions(this);\n \n handleError(error, errorContext, globalOptions);\n }\n };\n}\n\n/**\n * Create Ship client with synchronous constructor\n */\nfunction createClient(): Ship {\n const options = program.opts();\n const shipOptions: any = {};\n \n // Only include options that are actually set (not undefined)\n if (options.config !== undefined) {\n shipOptions.configFile = options.config;\n }\n if (options.apiUrl !== undefined) {\n shipOptions.apiUrl = options.apiUrl;\n }\n if (options.apiKey !== undefined) {\n shipOptions.apiKey = options.apiKey;\n }\n if (options.deployToken !== undefined) {\n shipOptions.deployToken = options.deployToken;\n }\n \n // Use synchronous constructor - initialization happens lazily\n return new Ship(shipOptions);\n}\n\n/**\n * Human-readable formatters for different result types\n */\nconst formatters = {\n deployments: (result: any, context?: { operation?: string }, isJson?: boolean, noColor?: boolean) => {\n if (!result.deployments || result.deployments.length === 0) {\n if (isJson) {\n console.log(JSON.stringify({ deployments: [] }, null, 2));\n } else {\n console.log('no deployments found');\n console.log();\n }\n return;\n }\n \n // For deployments list: hide files, size, status, expires for cleaner output\n const listColumns = ['deployment', 'url', 'created'];\n console.log(formatTable(result.deployments, listColumns, noColor));\n },\n aliases: (result: any, context?: { operation?: string }, isJson?: boolean, noColor?: boolean) => {\n if (!result.aliases || result.aliases.length === 0) {\n if (isJson) {\n console.log(JSON.stringify({ aliases: [] }, null, 2));\n } else {\n console.log('no aliases found');\n console.log();\n }\n return;\n }\n \n // For aliases list: hide status, confirmed for cleaner output\n const listColumns = ['alias', 'deployment', 'url', 'created'];\n console.log(formatTable(result.aliases, listColumns, noColor));\n },\n alias: (result: any, context?: { operation?: string }, isJson?: boolean, noColor?: boolean) => {\n // Always show success message for alias operations, particularly 'set'\n if (result.alias) {\n const operation = result.isCreate ? 'created' : 'updated';\n success(`${result.alias} alias ${operation}`, isJson, noColor);\n }\n \n // Show DNS CNAME warning for external aliases that are not confirmed\n if (!isJson && result.alias && result.alias.includes('.') && !result.confirmed) {\n warn(`To complete setup, create a DNS CNAME record pointing ${result.alias} to cname.statichost.com`, isJson, noColor);\n }\n \n console.log(formatDetails(result, noColor));\n },\n deployment: (result: any, context?: { operation?: string }, isJson?: boolean, noColor?: boolean) => {\n // Show success message for create operations only\n if (result.status && context?.operation === 'create') {\n success(`${result.deployment} deployment created ✨`, isJson, noColor);\n }\n console.log(formatDetails(result, noColor));\n },\n email: (result: any, context?: { operation?: string }, isJson?: boolean, noColor?: boolean) => {\n console.log(formatDetails(result, noColor));\n },\n message: (result: any, context?: { operation?: string }, isJson?: boolean, noColor?: boolean) => {\n // Handle messages from operations like DNS check\n if (result.message) {\n success(result.message, isJson, noColor);\n }\n }\n};\n\n/**\n * Common deploy logic used by both shortcut and explicit commands\n */\nasync function performDeploy(client: Ship, path: string, cmdOptions: any, commandContext?: any): Promise<any> {\n // Validate path exists before proceeding\n if (!existsSync(path)) {\n throw ShipError.file(`${path} path does not exist`, path);\n }\n \n // Check if path is a file or directory\n const stats = statSync(path);\n if (!stats.isDirectory() && !stats.isFile()) {\n throw ShipError.file(`${path} path must be a file or directory`, path);\n }\n \n const deployOptions: any = {};\n \n // Handle path detection flag\n if (cmdOptions?.noPathDetect !== undefined) {\n deployOptions.pathDetect = !cmdOptions.noPathDetect;\n }\n \n // Handle SPA detection flag\n if (cmdOptions?.noSpaDetect !== undefined) {\n deployOptions.spaDetect = !cmdOptions.noSpaDetect;\n }\n \n // Set up cancellation support using SDK's built-in AbortController\n const abortController = new AbortController();\n deployOptions.signal = abortController.signal;\n \n // Display upload pending message\n let spinner: any = null;\n \n // Show spinner only in TTY (not piped), not in JSON mode, and not with --no-color (script parsing)\n const globalOptions = commandContext ? processOptions(commandContext) : {};\n if (process.stdout.isTTY && !globalOptions.json && !globalOptions.noColor) {\n const { default: yoctoSpinner } = await import('yocto-spinner');\n spinner = yoctoSpinner({ text: 'uploading…' }).start();\n }\n \n // Handle Ctrl+C by aborting the request\n const sigintHandler = () => {\n abortController.abort();\n if (spinner) spinner.stop();\n process.exit(130);\n };\n process.on('SIGINT', sigintHandler);\n \n try {\n const result = await client.deployments.create(path, deployOptions);\n \n // Cleanup\n process.removeListener('SIGINT', sigintHandler);\n if (spinner) spinner.stop();\n \n return result;\n } catch (error) {\n // Cleanup on error\n process.removeListener('SIGINT', sigintHandler);\n if (spinner) spinner.stop();\n throw error;\n }\n}\n\n/**\n * Format output based on --json flag\n */\nfunction output(result: any, context?: { operation?: string; resourceType?: string; resourceId?: string }, options?: any) {\n const opts = options || program.opts();\n \n // Handle void/undefined results (removal operations)\n if (result === undefined) {\n if (context?.operation === 'remove' && context.resourceType && context.resourceId) {\n success(`${context.resourceId} ${context.resourceType.toLowerCase()} removed`, opts.json, opts.noColor);\n } else {\n success('removed successfully', opts.json, opts.noColor);\n }\n return;\n }\n \n // Handle ping result (boolean or object with success property)\n if (result === true || (result && typeof result === 'object' && result.hasOwnProperty('success'))) {\n const isSuccess = result === true || result.success;\n if (isSuccess) {\n success('api reachable', opts.json, opts.noColor);\n } else {\n error('api unreachable', opts.json, opts.noColor);\n }\n return;\n }\n \n // For regular results in JSON mode, output the raw JSON\n if (opts.json) {\n console.log(JSON.stringify(result, null, 2));\n console.log();\n return;\n }\n \n // Find appropriate formatter based on result properties (non-JSON mode)\n for (const [key, formatter] of Object.entries(formatters)) {\n if (result[key]) {\n formatter(result, context, opts.json, opts.noColor);\n return;\n }\n }\n \n // Default fallback\n success('success', opts.json, opts.noColor);\n}\n\n\n\nprogram\n .name('ship')\n .description('🚀 Deploy static sites with simplicity')\n .version(packageJson.version, '--version', 'Show version information')\n .option('--api-key <key>', 'API key for authenticated deployments')\n .option('--deploy-token <token>', 'Deploy token for single-use deployments')\n .option('--config <file>', 'Custom config file path')\n .option('--api-url <url>', 'API URL (for development)')\n .option('--json', 'Output results in JSON format')\n .option('--no-color', 'Disable colored output')\n .option('--help', 'Display help for command')\n .helpOption(false); // Disable default help\n\n// Handle --help flag manually to show custom help\nprogram.hook('preAction', (thisCommand, actionCommand) => {\n const options = thisCommand.opts();\n if (options.help) {\n const noColor = options.color === false || options.noColor;\n displayHelp(noColor);\n process.exit(0);\n }\n});\n\n// Validate options early - before any action is executed\nprogram.hook('preAction', (thisCommand, actionCommand) => {\n const options = thisCommand.opts();\n \n try {\n if (options.apiKey && typeof options.apiKey === 'string') {\n validateApiKey(options.apiKey);\n }\n \n if (options.deployToken && typeof options.deployToken === 'string') {\n validateDeployToken(options.deployToken);\n }\n \n if (options.apiUrl && typeof options.apiUrl === 'string') {\n validateApiUrl(options.apiUrl);\n }\n } catch (validationError) {\n if (validationError instanceof ShipError) {\n const noColor = options.color === false || options.noColor;\n error(validationError.message, options.json, noColor);\n process.exit(1);\n }\n throw validationError;\n }\n});\n\n// Ping command\nprogram\n .command('ping')\n .description('Check API connectivity')\n .action(withErrorHandling((client) => client.ping()));\n\n// Whoami shortcut - alias for account get\nprogram\n .command('whoami')\n .description('Get current account information')\n .action(withErrorHandling(\n (client) => client.whoami(),\n { operation: 'get', resourceType: 'Account' }\n ));\n\n// Deployments commands\nconst deploymentsCmd = program\n .command('deployments')\n .description('Manage deployments')\n .action((...args) => {\n const globalOptions = processOptions(program);\n \n // Get the command object (last argument)\n const commandObj = args[args.length - 1];\n \n // Check if an unknown subcommand was provided\n if (commandObj && commandObj.args && commandObj.args.length > 0) {\n const unknownArg = commandObj.args.find((arg: string) => !['list', 'create', 'get', 'remove'].includes(arg));\n if (unknownArg) {\n error(`unknown command '${unknownArg}'`, globalOptions.json, globalOptions.noColor);\n }\n }\n \n displayHelp(globalOptions.noColor);\n process.exit(1);\n });\n\ndeploymentsCmd\n .command('list')\n .description('List all deployments')\n .action(withErrorHandling((client) => client.deployments.list()));\n\ndeploymentsCmd\n .command('create <path>')\n .description('Create deployment from file or directory')\n .option('--no-path-detect', 'Disable automatic path optimization and flattening')\n .option('--no-spa-detect', 'Disable automatic SPA detection and configuration')\n .action(withErrorHandling(\n function(this: any, client: Ship, path: string, cmdOptions: any) { \n return performDeploy(client, path, cmdOptions, this);\n },\n { operation: 'create' }\n ));\n\ndeploymentsCmd\n .command('get <deployment>')\n .description('Show deployment information')\n .action(withErrorHandling(\n (client, deployment: string) => client.deployments.get(deployment),\n { operation: 'get', resourceType: 'Deployment', getResourceId: (deployment: string) => deployment }\n ));\n\ndeploymentsCmd\n .command('remove <deployment>')\n .description('Delete deployment permanently')\n .action(withErrorHandling(\n (client, deployment: string) => client.deployments.remove(deployment),\n { operation: 'remove', resourceType: 'Deployment', getResourceId: (deployment: string) => deployment }\n ));\n\n// Aliases commands\nconst aliasesCmd = program\n .command('aliases')\n .description('Manage aliases')\n .action((...args) => {\n const globalOptions = processOptions(program);\n \n // Get the command object (last argument)\n const commandObj = args[args.length - 1];\n \n // Check if an unknown subcommand was provided\n if (commandObj && commandObj.args && commandObj.args.length > 0) {\n const unknownArg = commandObj.args.find((arg: string) => !['list', 'get', 'set', 'remove'].includes(arg));\n if (unknownArg) {\n error(`unknown command '${unknownArg}'`, globalOptions.json, globalOptions.noColor);\n }\n }\n \n displayHelp(globalOptions.noColor);\n process.exit(1);\n });\n\naliasesCmd\n .command('list')\n .description('List all aliases')\n .action(withErrorHandling((client) => client.aliases.list()));\n\naliasesCmd\n .command('get <name>')\n .description('Show alias information')\n .action(withErrorHandling(\n (client, name: string) => client.aliases.get(name),\n { operation: 'get', resourceType: 'Alias', getResourceId: (name: string) => name }\n ));\n\naliasesCmd\n .command('check <name>')\n .description('Manually trigger DNS check for external alias')\n .action(withErrorHandling(\n (client, name: string) => client.aliases.check(name),\n { operation: 'check', resourceType: 'Alias', getResourceId: (name: string) => name }\n ));\n\naliasesCmd\n .command('set <name> <deployment>')\n .description('Create or update alias pointing to deployment')\n .action(withErrorHandling(\n (client: Ship, name: string, deployment: string) => client.aliases.set(name, deployment),\n { operation: 'set', resourceType: 'Alias', getResourceId: (name: string) => name }\n ));\n\naliasesCmd\n .command('remove <name>')\n .description('Delete alias permanently')\n .action(withErrorHandling(\n (client, name: string) => client.aliases.remove(name),\n { operation: 'remove', resourceType: 'Alias', getResourceId: (name: string) => name }\n ));\n\n// Account commands\nconst accountCmd = program\n .command('account')\n .description('Manage account')\n .action((...args) => {\n const globalOptions = processOptions(program);\n \n // Get the command object (last argument)\n const commandObj = args[args.length - 1];\n \n // Check if an unknown subcommand was provided\n if (commandObj && commandObj.args && commandObj.args.length > 0) {\n const unknownArg = commandObj.args.find((arg: string) => !['get'].includes(arg));\n if (unknownArg) {\n error(`unknown command '${unknownArg}'`, globalOptions.json, globalOptions.noColor);\n }\n }\n \n displayHelp(globalOptions.noColor);\n process.exit(1);\n });\n\naccountCmd\n .command('get')\n .description('Show account information')\n .action(withErrorHandling(\n (client) => client.whoami(),\n { operation: 'get', resourceType: 'Account' }\n ));\n\n// Completion commands\nconst completionCmd = program\n .command('completion')\n .description('Setup shell completion')\n .action((...args) => {\n const globalOptions = processOptions(program);\n \n // Get the command object (last argument)\n const commandObj = args[args.length - 1];\n \n // Check if an unknown subcommand was provided\n if (commandObj && commandObj.args && commandObj.args.length > 0) {\n const unknownArg = commandObj.args.find((arg: string) => !['install', 'uninstall'].includes(arg));\n if (unknownArg) {\n error(`unknown command '${unknownArg}'`, globalOptions.json, globalOptions.noColor);\n }\n }\n \n displayHelp(globalOptions.noColor);\n process.exit(1);\n });\n\ncompletionCmd\n .command('install')\n .description('Install shell completion script')\n .action(async () => {\n const shell = process.env.SHELL || '';\n const homeDir = os.homedir();\n let installPath: string;\n let profileFile: string;\n let sourceLine: string = '';\n\n // Resolve the path to the bundled completion scripts\n const bashScriptPath = path.resolve(__dirname, 'completions/ship.bash');\n const zshScriptPath = path.resolve(__dirname, 'completions/ship.zsh');\n const fishScriptPath = path.resolve(__dirname, 'completions/ship.fish');\n\n try {\n if (shell.includes('bash')) {\n installPath = path.join(homeDir, '.ship_completion.bash');\n profileFile = path.join(homeDir, '.bash_profile');\n sourceLine = `# ship\\nsource '${installPath}'\\n# ship end`;\n fs.copyFileSync(bashScriptPath, installPath);\n } else if (shell.includes('zsh')) {\n installPath = path.join(homeDir, '.ship_completion.zsh');\n profileFile = path.join(homeDir, '.zshrc');\n sourceLine = `# ship\\nsource '${installPath}'\\n# ship end`;\n fs.copyFileSync(zshScriptPath, installPath);\n } else if (shell.includes('fish')) {\n const fishCompletionsDir = path.join(homeDir, '.config/fish/completions');\n if (!fs.existsSync(fishCompletionsDir)) {\n fs.mkdirSync(fishCompletionsDir, { recursive: true });\n }\n installPath = path.join(fishCompletionsDir, 'ship.fish');\n fs.copyFileSync(fishScriptPath, installPath);\n const options = program.opts();\n success('fish completion installed successfully', options.json, options.noColor);\n info('please restart your shell to apply the changes', options.json, options.noColor);\n return;\n } else {\n const options = program.opts();\n error(`unsupported shell: ${shell}. could not install completion script`, options.json, options.noColor);\n return;\n }\n\n // For bash and zsh, we need to add sourcing to profile\n const profileExists = fs.existsSync(profileFile);\n if (profileExists) {\n const profileContent = fs.readFileSync(profileFile, 'utf-8');\n if (!profileContent.includes('# ship') || !profileContent.includes('# ship end')) {\n // Ensure there's a newline before our block if file doesn't end with one\n const needsNewline = profileContent.length > 0 && !profileContent.endsWith('\\n');\n const prefix = needsNewline ? '\\n' : '';\n fs.appendFileSync(profileFile, prefix + sourceLine);\n }\n } else {\n fs.writeFileSync(profileFile, sourceLine);\n }\n\n const options = program.opts();\n success(`completion script installed for ${shell.split('/').pop()}`, options.json, options.noColor);\n warn(`run \"source ${profileFile}\" or restart your shell`, options.json, options.noColor);\n } catch (e: any) {\n const options = program.opts();\n error(`could not install completion script: ${e.message}`, options.json, options.noColor);\n if (shell.includes('bash') || shell.includes('zsh')) {\n warn(`add the following line to your profile file manually\\n${sourceLine}`, options.json, options.noColor);\n }\n }\n });\n\ncompletionCmd\n .command('uninstall')\n .description('Uninstall shell completion script')\n .action(async () => {\n const shell = process.env.SHELL || '';\n const homeDir = os.homedir();\n let installPath: string;\n let profileFile: string;\n\n try {\n if (shell.includes('bash')) {\n installPath = path.join(homeDir, '.ship_completion.bash');\n profileFile = path.join(homeDir, '.bash_profile');\n } else if (shell.includes('zsh')) {\n installPath = path.join(homeDir, '.ship_completion.zsh');\n profileFile = path.join(homeDir, '.zshrc');\n } else if (shell.includes('fish')) {\n const fishCompletionsDir = path.join(homeDir, '.config/fish/completions');\n installPath = path.join(fishCompletionsDir, 'ship.fish');\n \n // Remove fish completion file\n const options = program.opts();\n if (fs.existsSync(installPath)) {\n fs.unlinkSync(installPath);\n success('fish completion uninstalled successfully', options.json, options.noColor);\n } else {\n warn('fish completion was not installed', options.json, options.noColor);\n }\n info('please restart your shell to apply the changes', options.json, options.noColor);\n return;\n } else {\n const options = program.opts();\n error(`unsupported shell: ${shell}. could not uninstall completion script`, options.json, options.noColor);\n return;\n }\n\n // Remove completion script file\n if (fs.existsSync(installPath)) {\n fs.unlinkSync(installPath);\n }\n\n // Remove sourcing line from profile\n if (fs.existsSync(profileFile)) {\n const profileContent = fs.readFileSync(profileFile, 'utf-8');\n const lines = profileContent.split('\\n');\n \n // Find and remove the ship block using start/end markers\n const filteredLines: string[] = [];\n let i = 0;\n let removedSomething = false;\n \n while (i < lines.length) {\n const line = lines[i];\n \n // Check if this is the start of a ship block\n if (line.trim() === '# ship') {\n removedSomething = true;\n // Skip all lines until we find the end marker\n i++;\n while (i < lines.length && lines[i].trim() !== '# ship end') {\n i++;\n }\n // Skip the end marker too\n if (i < lines.length && lines[i].trim() === '# ship end') {\n i++;\n }\n } else {\n // Keep this line\n filteredLines.push(line);\n i++;\n }\n }\n \n const options = program.opts();\n if (removedSomething) {\n // Preserve the original file's ending format (with or without final newline)\n const originalEndsWithNewline = profileContent.endsWith('\\n');\n let newContent;\n if (filteredLines.length === 0) {\n newContent = '';\n } else if (originalEndsWithNewline) {\n newContent = filteredLines.join('\\n') + '\\n';\n } else {\n newContent = filteredLines.join('\\n');\n }\n fs.writeFileSync(profileFile, newContent);\n success(`completion script uninstalled for ${shell.split('/').pop()}`, options.json, options.noColor);\n warn(`run \"source ${profileFile}\" or restart your shell`, options.json, options.noColor);\n } else {\n error('completion was not found in profile', options.json, options.noColor);\n }\n } else {\n const options = program.opts();\n error('profile file not found', options.json, options.noColor);\n }\n } catch (e: any) {\n const options = program.opts();\n error(`could not uninstall completion script: ${e.message}`, options.json, options.noColor);\n }\n });\n\n\n// Deploy shortcut as default action\nprogram\n .argument('[path]', 'Path to deploy')\n .option('--no-path-detect', 'Disable automatic path optimization and flattening')\n .option('--no-spa-detect', 'Disable automatic SPA detection and configuration')\n .action(withErrorHandling(\n async function(this: any, client: Ship, path?: string, cmdOptions?: any) {\n if (!path) {\n const globalOptions = program.opts();\n // Convert Commander.js --no-color flag (color: false) to our convention (noColor: true)\n const noColor = globalOptions.color === false || globalOptions.noColor;\n displayHelp(noColor);\n process.exit(0);\n }\n \n // Check if the argument looks like a path (not a command)\n if (!path.includes('/') && !path.startsWith('.') && !path.startsWith('~')) {\n // This looks like an unknown command, not a path\n throw ShipError.validation(`unknown command '${path}'`);\n }\n \n return performDeploy(client, path, cmdOptions, this);\n },\n { operation: 'create' }\n ));\n\n\n\n/**\n * Simple completion handler - no self-invocation, just static completions\n */\nfunction handleCompletion() {\n const args = process.argv;\n const isBash = args.includes('--compbash');\n const isZsh = args.includes('--compzsh');\n const isFish = args.includes('--compfish');\n \n if (!isBash && !isZsh && !isFish) return;\n\n const completions = ['ping', 'whoami', 'deployments', 'aliases', 'account', 'completion'];\n console.log(completions.join(isFish ? '\\n' : ' '));\n process.exit(0);\n}\n\n// Handle completion requests (before any other processing)\nif (process.env.NODE_ENV !== 'test' && (process.argv.includes('--compbash') || process.argv.includes('--compzsh') || process.argv.includes('--compfish'))) {\n handleCompletion();\n}\n\n// Handle main CLI parsing\nif (process.env.NODE_ENV !== 'test') {\n try {\n program.parse(process.argv);\n } catch (err: any) {\n // Commander.js errors are already handled by exitOverride above\n // This catch is just for safety - exitOverride should handle all Commander errors\n if (err.code && err.code.startsWith('commander.')) {\n process.exit(err.exitCode || 1);\n }\n throw err;\n }\n}","/**\n * @file Ship SDK for Node.js environments with full file system support.\n */\n\nimport { Ship as BaseShip } from '../shared/base-ship.js';\nimport { ShipError } from '@shipstatic/types';\nimport { getENV } from '../shared/lib/env.js';\nimport { loadConfig } from './core/config.js';\nimport { resolveConfig } from '../shared/core/config.js';\nimport { setConfig } from './core/platform-config.js';\nimport { ApiHttp } from '../shared/api/http.js';\nimport type { ShipClientOptions, DeployInput, DeploymentOptions, StaticFile } from '../shared/types.js';\n\n// Export all shared functionality\nexport * from '../shared/index.js';\n\n/**\n * Ship SDK Client for Node.js environments.\n * \n * Provides full file system access, configuration file loading,\n * and environment variable support.\n * \n * @example\n * ```typescript\n * // Authenticated deployments with API key\n * const ship = new Ship({ apiKey: \"ship-xxxx\" });\n * \n * // Single-use deployments with deploy token\n * const ship = new Ship({ deployToken: \"token-xxxx\" });\n * \n * // Deploy a directory\n * await ship.deploy('./dist');\n * ```\n */\nexport class Ship extends BaseShip {\n constructor(options: ShipClientOptions = {}) {\n const environment = getENV();\n \n if (environment !== 'node') {\n throw ShipError.business('Node.js Ship class can only be used in Node.js environment.');\n }\n \n super(options);\n }\n\n protected resolveInitialConfig(options: ShipClientOptions): any {\n return resolveConfig(options, {});\n }\n\n protected async loadFullConfig(): Promise<void> {\n try {\n // Load config from file/env\n const loadedConfig = await loadConfig(this.clientOptions.configFile);\n // Re-resolve and re-create the http client with the full config\n const finalConfig = resolveConfig(this.clientOptions, loadedConfig);\n this.http = new ApiHttp({ ...this.clientOptions, ...finalConfig });\n \n const platformConfig = await this.http.getConfig();\n setConfig(platformConfig);\n } catch (error) {\n // Reset initialization promise so it can be retried\n this.initPromise = null;\n throw error;\n }\n }\n\n protected async processInput(input: DeployInput, options: DeploymentOptions): Promise<StaticFile[]> {\n // Validate input type for Node.js environment\n if (!this.#isValidNodeInput(input)) {\n throw ShipError.business('Invalid input type for Node.js environment. Expected string[] file paths.');\n }\n \n // Check for empty array specifically\n if (Array.isArray(input) && input.length === 0) {\n throw ShipError.business('No files to deploy.');\n }\n \n const { convertDeployInput } = await import('./core/prepare-input.js');\n return convertDeployInput(input, options, this.http);\n }\n\n /**\n * Validates that input is appropriate for Node.js environment\n * @private\n */\n #isValidNodeInput(input: DeployInput): boolean {\n // Check for string or string array (file paths)\n if (typeof input === 'string') {\n return true;\n }\n \n if (Array.isArray(input)) {\n // Allow empty arrays (will be handled as \"No files to deploy\") \n // and arrays of strings only\n return input.every(item => typeof item === 'string');\n }\n \n return false;\n }\n}\n\n// Default export (for import Ship from 'ship')\nexport default Ship;\n\n// Node.js specific exports\nexport { loadConfig } from './core/config.js';\nexport { setConfig, getCurrentConfig } from './core/platform-config.js';\n\n// Node.js utilities\nexport { processFilesForNode } from './core/node-files.js';\nexport { __setTestEnvironment, getENV } from '../shared/lib/env.js';","/**\n * @file Manages HTTP requests to the Ship API using native fetch.\n */\nimport * as _mime from 'mime-types';\nimport type { \n Deployment, \n DeploymentListResponse, \n PingResponse, \n ConfigResponse, \n DeploymentRemoveResponse, \n Alias, \n AliasListResponse, \n Account, \n SPACheckRequest, \n SPACheckResponse,\n StaticFile\n} from '@shipstatic/types';\nimport type { ApiDeployOptions, ShipClientOptions } from '../types.js';\nimport { ShipError, DEFAULT_API } from '@shipstatic/types';\n\nimport { getENV } from '../lib/env.js';\n\n// FormData and File types for Node.js environment\n/**\n * Internal type alias for Node.js FormData implementation used during file deploys.\n * @internal\n */\ntype FormDataNode = any;\n/**\n * Internal type alias for Node.js File implementation used during file deploys.\n * @internal\n */\ntype FileNode = any;\n\n/** Default API host URL if not otherwise configured. */\n/** @internal */\nconst DEPLOY_ENDPOINT = '/deployments';\n/** @internal */\nconst PING_ENDPOINT = '/ping';\n/** @internal */\nconst ALIASES_ENDPOINT = '/aliases';\n/** @internal */\nconst CONFIG_ENDPOINT = '/config';\n/** @internal */\nconst ACCOUNT_ENDPOINT = '/account';\n/** @internal */\nconst SPA_CHECK_ENDPOINT = '/spa-check';\n\n/**\n * Determines the MIME type for a given file (File object or path string) in browser environments.\n * Falls back to 'application/octet-stream' if type cannot be determined.\n * @internal\n * @param file - File object or file path string.\n * @returns The MIME type as a string.\n */\nfunction getBrowserContentType(file: File | string): string {\n if (typeof file === 'string') {\n return _mime.lookup(file) || 'application/octet-stream';\n } else {\n return _mime.lookup(file.name) || file.type || 'application/octet-stream';\n }\n}\n\n/**\n * Collects all items from an AsyncIterable into an array.\n * Useful for converting streaming multipart encoders to Buffer arrays.\n * @internal\n * @template T - The item type yielded by the iterable.\n * @param iterable - The async iterable to collect.\n * @returns A promise resolving to an array of all items.\n */\nasync function collectAsyncIterable<T>(iterable: AsyncIterable<T>): Promise<T[]> {\n const result: T[] = [];\n for await (const x of iterable) {\n result.push(x);\n }\n return result;\n}\n\n/**\n * Handles direct HTTP communication with the Ship API, including deploys and health checks.\n * Responsible for constructing requests, managing authentication, and error translation.\n * @internal\n */\nexport class ApiHttp {\n private readonly apiUrl: string;\n private readonly apiKey: string;\n private readonly deployToken: string;\n\n /**\n * Constructs a new ApiHttp instance with the provided client options.\n * @param options - Client options including API host, authentication credentials, and timeout settings.\n */\n constructor(options: ShipClientOptions) {\n this.apiUrl = options.apiUrl || DEFAULT_API;\n this.apiKey = options.apiKey ?? \"\";\n this.deployToken = options.deployToken ?? \"\";\n }\n\n /**\n * Generates common headers for API requests, including authentication credentials if present.\n * Deploy tokens take precedence over API keys for single-use deployments.\n * @param customHeaders - Optional additional headers to include.\n * @returns Object containing merged headers.\n * @private\n */\n #getAuthHeaders(customHeaders: Record<string, string> = {}): Record<string, string> {\n const headers = { ...customHeaders };\n \n // Deploy tokens take precedence for single-use deployments\n if (this.deployToken) {\n headers['Authorization'] = `Bearer ${this.deployToken}`;\n } else if (this.apiKey) {\n headers['Authorization'] = `Bearer ${this.apiKey}`;\n }\n \n return headers;\n }\n\n /**\n * Low-level fetch wrapper with authentication - used only by #request method.\n * This method only handles the raw fetch request with auth headers.\n * @param url - Request URL\n * @param options - Fetch options\n * @param operationName - Name of operation for error messages\n * @returns Promise resolving to Response object\n * @private\n */\n async #fetchWithAuth(url: string, options: RequestInit = {}, operationName: string): Promise<Response> {\n const headers = this.#getAuthHeaders(options.headers as Record<string, string>);\n \n const fetchOptions: RequestInit = {\n ...options,\n headers,\n };\n\n // If no apiKey, deployToken, or Authorization header is provided, attempt to use cookie-based authentication\n const hasInstanceCredentials = !!(this.apiKey || this.deployToken);\n const hasAuthorizationHeader = !!(headers as any)?.Authorization;\n \n if (!hasInstanceCredentials && !hasAuthorizationHeader) {\n fetchOptions.credentials = 'include';\n }\n\n try {\n const response = await fetch(url, fetchOptions);\n return response;\n } catch (error: any) {\n this.#handleFetchError(error, operationName);\n // This line is unreachable because #handleFetchError always throws\n throw error;\n }\n }\n\n /**\n * Unified HTTP request helper that handles the complete request lifecycle.\n * Makes authenticated requests, checks response status, and handles all errors.\n * Automatically determines whether to parse JSON based on response headers.\n * @param url - Request URL\n * @param options - Fetch options \n * @param operationName - Name of operation for error messages\n * @returns Promise resolving to parsed JSON response or undefined for empty responses\n * @throws {ShipError} Various ShipError types based on the failure mode\n * @private\n */\n async #request<T>(url: string, options: RequestInit = {}, operationName: string): Promise<T> {\n try {\n const response = await this.#fetchWithAuth(url, options, operationName);\n \n if (!response.ok) {\n await this.#handleResponseError(response, operationName);\n }\n \n // Check if response has content to parse\n const contentLength = response.headers.get('Content-Length');\n if (contentLength === '0' || response.status === 204) {\n return undefined as T; // Return undefined for empty responses\n }\n \n return await response.json() as T;\n } catch (error: any) {\n if (error instanceof ShipError) {\n throw error;\n }\n this.#handleFetchError(error, operationName);\n // This line is unreachable because #handleFetchError always throws\n throw error;\n }\n }\n \n /**\n * Sends a ping request to the Ship API server to verify connectivity and authentication.\n * @returns Promise resolving to `true` if the ping is successful, `false` otherwise.\n * @throws {ShipApiError} If the API returns an error response (4xx, 5xx).\n * @throws {ShipNetworkError} If a network error occurs (e.g., DNS failure, connection refused).\n */\n public async ping(): Promise<boolean> {\n const data = await this.#request<PingResponse>(`${this.apiUrl}${PING_ENDPOINT}`, { method: 'GET' }, 'Ping');\n return data?.success || false;\n }\n\n /**\n * Get full ping response from the API server\n * @returns Promise resolving to the full PingResponse object.\n */\n public async getPingResponse(): Promise<PingResponse> {\n return await this.#request<PingResponse>(`${this.apiUrl}${PING_ENDPOINT}`, { method: 'GET' }, 'Ping');\n }\n\n /**\n * Fetches platform configuration from the API.\n * @returns Promise resolving to the config response.\n * @throws {ShipError} If the config request fails.\n */\n public async getConfig(): Promise<ConfigResponse> {\n return await this.#request<ConfigResponse>(`${this.apiUrl}${CONFIG_ENDPOINT}`, { method: 'GET' }, 'Config');\n }\n\n /**\n * Deploys an array of StaticFile objects to the Ship API.\n * Constructs and sends a multipart/form-data POST request, handling both browser and Node.js environments.\n * Validates files and manages deploy progress and error translation.\n * @param files - Array of StaticFile objects to deploy (must include MD5 checksums).\n * @param options - Optional per-deploy configuration (overrides instance defaults).\n * @returns Promise resolving to a full Deployment object on success.\n * @throws {ShipFileError} If a file is missing an MD5 checksum or content type is unsupported.\n * @throws {ShipClientError} If no files are provided or if environment is unknown.\n * @throws {ShipNetworkError} If a network error occurs during deploy.\n * @throws {ShipApiError} If the API returns an error response.\n * @throws {ShipCancelledError} If the deploy is cancelled via an AbortSignal.\n */\n public async deploy(\n files: StaticFile[],\n options: ApiDeployOptions = {}\n ): Promise<Deployment> {\n this.#validateFiles(files);\n\n const {\n apiUrl = this.apiUrl,\n signal,\n apiKey,\n deployToken\n } = options;\n\n const { requestBody, requestHeaders } = await this.#prepareRequestPayload(files);\n \n // Override auth headers if per-deploy credentials are provided\n // Deploy tokens take precedence over API keys\n let authHeaders = {};\n if (deployToken) {\n authHeaders = { 'Authorization': `Bearer ${deployToken}` };\n } else if (apiKey) {\n authHeaders = { 'Authorization': `Bearer ${apiKey}` };\n }\n \n const fetchOptions: RequestInit = {\n method: 'POST',\n body: requestBody,\n headers: { ...requestHeaders, ...authHeaders },\n signal: signal || null\n };\n\n // Use unified request method to eliminate duplication\n return await this.#request<Deployment>(`${apiUrl}${DEPLOY_ENDPOINT}`, fetchOptions, 'Deploy');\n }\n \n /**\n * Validates the files array for deploy requirements.\n * Ensures all files have MD5 checksums and at least one file is present.\n * @param files - Files to validate.\n * @throws {ShipFileError} If a file is missing an MD5 checksum.\n * @throws {ShipClientError} If no files are provided.\n * @private\n */\n #validateFiles(files: StaticFile[]): void {\n if (!files.length) {\n throw ShipError.business('No files to deploy.');\n }\n \n for (const file of files) {\n if (!file.md5) {\n throw ShipError.file(`MD5 checksum missing for file: ${file.path}`, file.path);\n }\n }\n }\n\n\n /**\n * Prepares the request payload (body and headers) for deploy based on execution environment.\n * Selects browser or Node.js multipart construction as needed.\n * @param files - Files to deploy.\n * @returns Promise resolving to request body and headers.\n * @private\n */\n async #prepareRequestPayload(files: StaticFile[]): Promise<{\n requestBody: FormData | ArrayBuffer;\n requestHeaders: Record<string, string>;\n }> {\n let requestBody: FormData | ArrayBuffer;\n let requestHeaders: Record<string, string> = {};\n \n if (getENV() === 'browser') {\n requestBody = this.#createBrowserBody(files);\n } else if (getENV() === 'node') {\n const { body, headers } = await this.#createNodeBody(files);\n requestBody = body.buffer.slice(body.byteOffset, body.byteOffset + body.byteLength) as ArrayBuffer;\n requestHeaders = headers;\n } else {\n throw ShipError.business('Unknown or unsupported execution environment');\n }\n \n return { requestBody, requestHeaders };\n }\n\n /**\n * Creates a FormData object for browser environments, populating it with files and checksums.\n * @param files - Array of StaticFile objects to include in the FormData.\n * @returns FormData object ready for transmission.\n * @throws {ShipFileError} If file content is of an unsupported type for browser FormData.\n * @private\n */\n #createBrowserBody(files: StaticFile[]): FormData {\n const formData = new FormData();\n const checksums: string[] = [];\n \n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n let fileContent: File | Blob;\n \n if (file.content instanceof File || file.content instanceof Blob) {\n fileContent = file.content;\n } else {\n throw ShipError.file(`Unsupported file.content type for browser FormData: ${file.path}`, file.path);\n }\n \n const contentType = getBrowserContentType(fileContent instanceof File ? fileContent : file.path);\n const fileWithPath = new File([fileContent], file.path, { type: contentType });\n formData.append('files[]', fileWithPath);\n checksums.push(file.md5!);\n }\n \n // Add checksums as JSON array\n formData.append('checksums', JSON.stringify(checksums));\n return formData;\n }\n\n /**\n * Creates the multipart request body (Buffer) and headers for Node.js environments using formdata-node and form-data-encoder.\n * @param files - Array of StaticFile objects to include in the multipart body.\n * @returns Promise resolving to an object with the body Buffer and headers.\n * @throws {ShipFileError} If file content is of an unsupported type for Node.js FormData.\n * @private\n */\n async #createNodeBody(files: StaticFile[]): Promise<{body: Buffer, headers: Record<string, string>}> {\n const { FormData: FormDataNodeClass, File: FileNodeClass } = await import('formdata-node');\n const { FormDataEncoder: FormDataEncoderClass } = await import('form-data-encoder');\n const pathImport = await import('path');\n const formDataNodeInstance: FormDataNode = new FormDataNodeClass();\n const checksums: string[] = [];\n\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n const contentType = _mime.lookup(file.path) || 'application/octet-stream';\n let fileNodeInstance: FileNode;\n\n if (Buffer.isBuffer(file.content)) {\n fileNodeInstance = new FileNodeClass([file.content], file.path, { type: contentType });\n } else if (typeof Blob !== \"undefined\" && file.content instanceof Blob) {\n fileNodeInstance = new FileNodeClass([file.content], file.path, { type: contentType });\n } else {\n throw ShipError.file(`Unsupported file.content type for Node.js FormData: ${file.path}`, file.path);\n }\n const preservedPath = file.path.startsWith('/') ? file.path : '/' + file.path;\n formDataNodeInstance.append('files[]', fileNodeInstance, preservedPath);\n checksums.push(file.md5!);\n }\n\n // Add checksums as JSON array\n formDataNodeInstance.append('checksums', JSON.stringify(checksums));\n\n const encoder = new FormDataEncoderClass(formDataNodeInstance);\n const encodedChunks = await collectAsyncIterable(encoder.encode());\n const body = Buffer.concat(encodedChunks.map(chunk => Buffer.from(chunk as Uint8Array)));\n\n const headers = {\n 'Content-Type': encoder.contentType,\n 'Content-Length': Buffer.byteLength(body).toString()\n };\n return { body, headers };\n }\n\n /**\n * Handles fetch response errors and throws appropriate ShipError types.\n * @param response - Fetch Response object with error status\n * @param operationName - Name of the failed operation\n * @throws {ShipApiError} Always throws with API error details\n * @private\n */\n async #handleResponseError(response: Response, operationName: string): Promise<never> {\n let errorData: any = {};\n try {\n const contentType = response.headers.get('content-type');\n if (contentType && contentType.includes('application/json')) {\n errorData = await response.json();\n } else {\n errorData = { message: await response.text() };\n }\n } catch {\n errorData = { message: 'Failed to parse error response' };\n }\n\n // Handle structured error responses (with error field, code, or message)\n if (errorData.error || errorData.code || errorData.message) {\n // Use message if available, otherwise use the error field as the message, or fallback\n const message = errorData.message || errorData.error || `${operationName} failed due to API error`;\n \n // Handle authentication errors specifically\n if (response.status === 401) {\n throw ShipError.authentication(message);\n }\n \n throw ShipError.api(\n message,\n response.status,\n errorData.code,\n errorData\n );\n }\n\n // Fallback for completely unstructured errors\n // Handle authentication errors specifically for unstructured responses too\n if (response.status === 401) {\n throw ShipError.authentication(`Authentication failed for ${operationName}`);\n }\n \n throw ShipError.api(\n `${operationName} failed due to API error`,\n response.status,\n undefined,\n errorData\n );\n }\n\n /**\n * Translates fetch errors into appropriate ShipError types and always throws.\n * Intended for use in catch blocks of API requests; never returns.\n * @param error - The error object caught from fetch.\n * @param operationName - Name of the failed operation (e.g., 'Deploy', 'Ping').\n * @throws {ShipCancelledError} If the request was cancelled.\n * @throws {ShipNetworkError} If a network error occurred (DNS failure, connection refused).\n * @throws {ShipClientError} For other unexpected errors.\n * @private\n */\n #handleFetchError(error: any, operationName: string): never {\n if (error.name === 'AbortError') {\n throw ShipError.cancelled(`${operationName} operation was cancelled.`);\n }\n if (error instanceof TypeError && error.message.includes('fetch')) {\n throw ShipError.network(`${operationName} failed due to network error: ${error.message}`, error);\n }\n if (error instanceof ShipError) {\n throw error;\n }\n throw ShipError.business(`An unexpected error occurred during ${operationName}: ${error.message || 'Unknown error'}`);\n }\n\n /**\n * Lists all deployments for the authenticated account\n * @returns Promise resolving to deployment list response\n */\n public async listDeployments(): Promise<DeploymentListResponse> {\n return await this.#request<DeploymentListResponse>(`${this.apiUrl}${DEPLOY_ENDPOINT}`, { method: 'GET' }, 'List Deployments');\n }\n\n /**\n * Gets a specific deployment by ID\n * @param id - Deployment ID to retrieve\n * @returns Promise resolving to deployment details\n */\n public async getDeployment(id: string): Promise<Deployment> {\n return await this.#request<Deployment>(`${this.apiUrl}${DEPLOY_ENDPOINT}/${id}`, { method: 'GET' }, 'Get Deployment');\n }\n\n /**\n * Removes a deployment by ID\n * @param id - Deployment ID to remove\n * @returns Promise resolving when removal is complete\n */\n public async removeDeployment(id: string): Promise<void> {\n await this.#request<DeploymentRemoveResponse>(`${this.apiUrl}${DEPLOY_ENDPOINT}/${id}`, { method: 'DELETE' }, 'Remove Deployment');\n }\n\n /**\n * Sets an alias (create or update)\n * @param name - Alias name\n * @param deployment - Deployment name to point to\n * @returns Promise resolving to the created/updated alias with operation context\n */\n public async setAlias(name: string, deployment: string): Promise<import('@shipstatic/types').Alias> {\n try {\n const response = await this.#fetchWithAuth(`${this.apiUrl}${ALIASES_ENDPOINT}/${encodeURIComponent(name)}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ deployment: deployment })\n }, 'Set Alias');\n \n if (!response.ok) {\n await this.#handleResponseError(response, 'Set Alias');\n }\n \n const alias = await response.json() as import('@shipstatic/types').Alias;\n \n // 201 = created, 200 = updated\n return {\n ...alias,\n isCreate: response.status === 201\n };\n } catch (error: any) {\n this.#handleFetchError(error, 'Set Alias');\n }\n }\n\n /**\n * Gets a specific alias by name\n * @param name - Alias name to retrieve\n * @returns Promise resolving to alias details\n */\n public async getAlias(name: string): Promise<Alias> {\n return await this.#request<Alias>(`${this.apiUrl}${ALIASES_ENDPOINT}/${encodeURIComponent(name)}`, { method: 'GET' }, 'Get Alias');\n }\n\n /**\n * Lists all aliases for the authenticated account\n * @returns Promise resolving to alias list response\n */\n public async listAliases(): Promise<AliasListResponse> {\n return await this.#request<AliasListResponse>(`${this.apiUrl}${ALIASES_ENDPOINT}`, { method: 'GET' }, 'List Aliases');\n }\n\n /**\n * Removes an alias by name\n * @param name - Alias name to remove\n * @returns Promise resolving to removal confirmation\n */\n public async removeAlias(name: string): Promise<void> {\n await this.#request<void>(`${this.apiUrl}${ALIASES_ENDPOINT}/${encodeURIComponent(name)}`, { method: 'DELETE' }, 'Remove Alias');\n }\n\n /**\n * Triggers a manual DNS check for an external alias\n * @param name - Alias name to check DNS for\n * @returns Promise resolving to confirmation message\n */\n public async checkAlias(name: string): Promise<{ message: string }> {\n return await this.#request<{ message: string }>(`${this.apiUrl}${ALIASES_ENDPOINT}/${encodeURIComponent(name)}/dns-check`, { method: 'POST' }, 'Check Alias');\n }\n\n /**\n * Gets account details for the authenticated user\n * @returns Promise resolving to account details\n */\n public async getAccount(): Promise<Account> {\n return await this.#request<Account>(`${this.apiUrl}${ACCOUNT_ENDPOINT}`, { method: 'GET' }, 'Get Account');\n }\n\n /**\n * Creates a new API key for the authenticated user\n * @returns Promise resolving to the new API key\n */\n public async createApiKey(): Promise<{ apiKey: string }> {\n return await this.#request<{ apiKey: string }>(`${this.apiUrl}/key`, { method: 'POST' }, 'Create API Key');\n }\n\n /**\n * Checks if files represent a SPA structure using AI analysis\n * @param files - Array of StaticFile objects to analyze\n * @returns Promise resolving to boolean indicating if it's a SPA\n */\n public async checkSPA(files: StaticFile[]): Promise<boolean> {\n // Find index.html and extract its content - required for SPA detection\n const indexFile = files.find(f => f.path === 'index.html' || f.path === '/index.html');\n if (!indexFile) {\n return false; // No index.html = not a SPA\n }\n \n // Skip if index.html is too large (unlikely to be a SPA)\n const MAX_INDEX_SIZE = 100 * 1024; // 100KB\n if (indexFile.size > MAX_INDEX_SIZE) {\n return false; // Very large index.html = likely not a SPA\n }\n \n let indexContent: string;\n // Check for Buffer in Node.js environment first (Buffer is not available in browser)\n if (typeof Buffer !== 'undefined' && Buffer.isBuffer(indexFile.content)) {\n indexContent = indexFile.content.toString('utf-8');\n } else if (typeof Blob !== 'undefined' && indexFile.content instanceof Blob) {\n indexContent = await indexFile.content.text();\n } else if (typeof File !== 'undefined' && indexFile.content instanceof File) {\n indexContent = await indexFile.content.text();\n } else {\n return false; // Unsupported content type\n }\n \n // Build file paths list\n const filePaths = files.map(file => file.path);\n \n const requestData: SPACheckRequest = {\n files: filePaths,\n index: indexContent\n };\n \n const response = await this.#request<SPACheckResponse>(\n `${this.apiUrl}${SPA_CHECK_ENDPOINT}`, \n { \n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(requestData)\n }, \n 'SPA Check'\n );\n return response.isSPA;\n }\n}\n","/**\n * @file Shared configuration logic for both environments.\n */\n\nimport { DEFAULT_API, type PlatformConfig } from '@shipstatic/types';\nimport type { ShipClientOptions, DeploymentOptions } from '../types.js';\nimport { getENV } from '../lib/env.js';\n\n// Re-export for backward compatibility\nexport type Config = PlatformConfig;\n\n/**\n * Cross-environment config loader that dispatches to appropriate implementation.\n */\nexport async function loadConfig(configFile?: string): Promise<Config> {\n const env = getENV();\n \n if (env === 'browser') {\n // In browser, return empty config (no file system access)\n return {};\n } else if (env === 'node') {\n // In Node.js, load from environment and files\n const { loadConfig: nodeLoadConfig } = await import('../../node/core/config.js');\n return nodeLoadConfig(configFile);\n } else {\n // Fallback to empty config for unknown environments\n return {};\n }\n}\n\n/**\n * Universal configuration resolver for all environments.\n * This is the single source of truth for config resolution.\n */\nexport function resolveConfig(\n userOptions: ShipClientOptions = {}, \n loadedConfig: Partial<ShipClientOptions> = {}\n): { apiUrl: string; apiKey?: string; deployToken?: string } {\n const finalConfig = {\n apiUrl: userOptions.apiUrl || loadedConfig.apiUrl || DEFAULT_API,\n apiKey: userOptions.apiKey !== undefined ? userOptions.apiKey : loadedConfig.apiKey,\n deployToken: userOptions.deployToken !== undefined ? userOptions.deployToken : loadedConfig.deployToken,\n };\n\n const result: { apiUrl: string; apiKey?: string; deployToken?: string } = {\n apiUrl: finalConfig.apiUrl\n };\n \n if (finalConfig.apiKey !== undefined) result.apiKey = finalConfig.apiKey;\n if (finalConfig.deployToken !== undefined) result.deployToken = finalConfig.deployToken;\n \n return result;\n}\n\n/**\n * Merge deployment options with client defaults.\n * This is shared logic used by both environments.\n */\nexport function mergeDeployOptions(\n options: DeploymentOptions, \n clientDefaults: ShipClientOptions\n): DeploymentOptions {\n const result: DeploymentOptions = { ...options };\n \n // Only add defined values from client defaults\n if (result.apiUrl === undefined && clientDefaults.apiUrl !== undefined) {\n result.apiUrl = clientDefaults.apiUrl;\n }\n if (result.apiKey === undefined && clientDefaults.apiKey !== undefined) {\n result.apiKey = clientDefaults.apiKey;\n }\n if (result.deployToken === undefined && clientDefaults.deployToken !== undefined) {\n result.deployToken = clientDefaults.deployToken;\n }\n if (result.timeout === undefined && clientDefaults.timeout !== undefined) {\n result.timeout = clientDefaults.timeout;\n }\n if (result.maxConcurrency === undefined && clientDefaults.maxConcurrency !== undefined) {\n result.maxConcurrency = clientDefaults.maxConcurrency;\n }\n if (result.onProgress === undefined && clientDefaults.onProgress !== undefined) {\n result.onProgress = clientDefaults.onProgress;\n }\n if (result.onProgressStats === undefined && clientDefaults.onProgressStats !== undefined) {\n result.onProgressStats = clientDefaults.onProgressStats;\n }\n \n return result;\n}","/**\n * @file Shared SPA detection utilities for both environments.\n * \n * Provides SPA detection and auto-configuration functionality\n * that can be used by both Node.js and browser environments.\n */\n\nimport { DEPLOYMENT_CONFIG_FILENAME } from '@shipstatic/types';\nimport { calculateMD5 } from './md5.js';\nimport type { StaticFile, DeploymentOptions } from '../types.js';\nimport type { ApiHttp } from '../api/http.js';\n\n/**\n * Creates ship.json configuration for SPA projects.\n * @returns Promise resolving to StaticFile with SPA configuration\n */\nexport async function createSPAConfig(): Promise<StaticFile> {\n const config = {\n \"rewrites\": [{\n \"source\": \"/(.*)\",\n \"destination\": \"/index.html\"\n }]\n };\n \n const configString = JSON.stringify(config, null, 2);\n \n // Create content that works in both browser and Node.js environments\n let content: Buffer | Blob;\n if (typeof Buffer !== 'undefined') {\n // Node.js environment\n content = Buffer.from(configString, 'utf-8');\n } else {\n // Browser environment\n content = new Blob([configString], { type: 'application/json' });\n }\n \n const { md5 } = await calculateMD5(content);\n \n return {\n path: DEPLOYMENT_CONFIG_FILENAME,\n content,\n size: configString.length,\n md5\n };\n}\n\n/**\n * Detects SPA projects and auto-generates configuration.\n * This function can be used by both Node.js and browser environments.\n * \n * @param files - Array of StaticFiles to analyze\n * @param apiClient - HTTP client for API communication\n * @param options - Deployment options containing SPA detection settings\n * @returns Promise resolving to files array with optional SPA config added\n */\nexport async function detectAndConfigureSPA(\n files: StaticFile[], \n apiClient: ApiHttp, \n options: DeploymentOptions\n): Promise<StaticFile[]> {\n // Skip if disabled or config already exists\n if (options.spaDetect === false || files.some(f => f.path === DEPLOYMENT_CONFIG_FILENAME)) {\n return files;\n }\n \n try {\n const isSPA = await apiClient.checkSPA(files);\n \n if (isSPA) {\n const spaConfig = await createSPAConfig();\n return [...files, spaConfig];\n }\n } catch (error) {\n // SPA detection failed, continue silently without auto-config\n }\n \n return files;\n}","/**\n * @file All Ship SDK resources in one place - impossibly simple.\n */\nimport type { \n Deployment, \n DeploymentListResponse, \n Alias, \n AliasListResponse, \n Account,\n StaticFile,\n DeployInput,\n DeploymentResource,\n AliasResource,\n AccountResource,\n KeysResource\n} from '@shipstatic/types';\nimport type { ApiHttp } from './api/http.js';\nimport type { ShipClientOptions, DeploymentOptions } from './types.js';\nimport { mergeDeployOptions } from './core/config.js';\nimport { detectAndConfigureSPA } from './lib/prepare-input.js';\n\n// Re-export DeployInput for external use\nexport type { DeployInput };\n\nexport function createDeploymentResource(\n getApi: () => ApiHttp, \n clientDefaults?: ShipClientOptions,\n ensureInit?: () => Promise<void>,\n processInput?: (input: DeployInput, options: DeploymentOptions) => Promise<StaticFile[]>\n): DeploymentResource {\n return {\n create: async (input: DeployInput, options: DeploymentOptions = {}) => {\n // Ensure full initialization before proceeding\n if (ensureInit) await ensureInit();\n \n // Merge user options with client defaults\n const mergedOptions = clientDefaults \n ? mergeDeployOptions(options, clientDefaults)\n : options;\n \n // Get API client AFTER initialization is complete to avoid race conditions\n const apiClient = getApi();\n \n // Use environment-specific input processing\n if (!processInput) {\n throw new Error('processInput function is not provided.');\n }\n \n // 1. Process input from the specific environment\n let staticFiles: StaticFile[] = await processInput(input, mergedOptions);\n \n // 2. 🆕 Apply SPA detection universally here (works for both Node.js and Browser!)\n staticFiles = await detectAndConfigureSPA(staticFiles, apiClient, mergedOptions);\n \n // 3. Deploy using the API - now returns the full Deployment object directly\n return await apiClient.deploy(staticFiles, mergedOptions);\n },\n\n list: async () => {\n if (ensureInit) await ensureInit();\n return getApi().listDeployments();\n },\n\n remove: async (id: string) => {\n if (ensureInit) await ensureInit();\n await getApi().removeDeployment(id);\n // Return void for deletion operations\n },\n\n get: async (id: string) => {\n if (ensureInit) await ensureInit();\n return getApi().getDeployment(id);\n }\n };\n}\n\n// =============================================================================\n// ALIAS RESOURCE\n// =============================================================================\n\nexport function createAliasResource(getApi: () => ApiHttp, ensureInit?: () => Promise<void>): AliasResource {\n return {\n set: async (aliasName: string, deployment: string) => {\n if (ensureInit) await ensureInit();\n // Set alias and return the created/updated alias directly\n return getApi().setAlias(aliasName, deployment);\n },\n\n get: async (aliasName: string) => {\n if (ensureInit) await ensureInit();\n return getApi().getAlias(aliasName);\n },\n\n list: async () => {\n if (ensureInit) await ensureInit();\n return getApi().listAliases();\n },\n\n remove: async (aliasName: string) => {\n if (ensureInit) await ensureInit();\n await getApi().removeAlias(aliasName);\n // Return void for deletion operations\n },\n\n check: async (aliasName: string) => {\n if (ensureInit) await ensureInit();\n return getApi().checkAlias(aliasName);\n }\n };\n}\n\n// =============================================================================\n// ACCOUNT RESOURCE\n// =============================================================================\n\nexport function createAccountResource(getApi: () => ApiHttp, ensureInit?: () => Promise<void>): AccountResource {\n return {\n get: async () => {\n if (ensureInit) await ensureInit();\n return getApi().getAccount();\n }\n };\n}\n\n// =============================================================================\n// KEYS RESOURCE\n// =============================================================================\n\nexport function createKeysResource(getApi: () => ApiHttp, ensureInit?: () => Promise<void>): KeysResource {\n return {\n create: async () => {\n if (ensureInit) await ensureInit();\n return getApi().createApiKey();\n }\n };\n}","/**\n * @file Base Ship SDK class - provides shared functionality across environments.\n */\n\nimport { ApiHttp } from './api/http.js';\nimport { ShipError } from '@shipstatic/types';\nimport type { ShipClientOptions } from './types.js';\nimport type { Deployment } from '@shipstatic/types';\n\n// Resource imports\nimport { \n createDeploymentResource, \n createAliasResource, \n createAccountResource, \n createKeysResource,\n type DeployInput\n} from './resources.js';\nimport type { \n DeploymentResource, \n AliasResource, \n AccountResource, \n KeysResource\n} from '@shipstatic/types';\n\nimport type { StaticFile } from '@shipstatic/types';\nimport type { DeploymentOptions } from './types.js';\n\n/**\n * Abstract base class for Ship SDK implementations.\n * \n * Provides shared functionality while allowing environment-specific\n * implementations to handle configuration loading and deployment processing.\n */\nexport abstract class Ship {\n protected http: ApiHttp;\n protected readonly clientOptions: ShipClientOptions;\n protected initPromise: Promise<void> | null = null;\n \n // Resource instances (initialized during creation)\n protected _deployments: DeploymentResource;\n protected _aliases: AliasResource;\n protected _account: AccountResource;\n protected _keys: KeysResource;\n\n constructor(options: ShipClientOptions = {}) {\n this.clientOptions = options;\n \n // Initialize HTTP client with constructor options for immediate use\n const config = this.resolveInitialConfig(options);\n this.http = new ApiHttp({ ...options, ...config });\n \n // Initialize resources with lazy loading support\n const initCallback = () => this.ensureInitialized();\n const getApi = () => this.http;\n \n // Pass the processInput method to deployment resource\n this._deployments = createDeploymentResource(\n getApi, \n this.clientOptions, \n initCallback,\n (input, options) => this.processInput(input, options)\n );\n this._aliases = createAliasResource(getApi, initCallback);\n this._account = createAccountResource(getApi, initCallback);\n this._keys = createKeysResource(getApi, initCallback);\n }\n\n // Abstract methods that environments must implement\n protected abstract resolveInitialConfig(options: ShipClientOptions): any;\n protected abstract loadFullConfig(): Promise<void>;\n protected abstract processInput(input: DeployInput, options: DeploymentOptions): Promise<StaticFile[]>;\n\n /**\n * Ensure full initialization is complete - called lazily by resources\n */\n protected async ensureInitialized(): Promise<void> {\n if (!this.initPromise) {\n this.initPromise = this.loadFullConfig();\n }\n return this.initPromise;\n }\n\n /**\n * Ping the API server to check connectivity\n */\n async ping(): Promise<boolean> {\n await this.ensureInitialized();\n return this.http.ping();\n }\n\n /**\n * Deploy project (convenience shortcut to ship.deployments.create())\n */\n async deploy(input: DeployInput, options?: DeploymentOptions): Promise<Deployment> {\n return this.deployments.create(input, options);\n }\n\n /**\n * Get current account information (convenience shortcut to ship.account.get())\n */\n async whoami() {\n return this.account.get();\n }\n\n /**\n * Get deployments resource (environment-specific)\n */\n get deployments(): DeploymentResource {\n return this._deployments;\n }\n \n /**\n * Get aliases resource\n */\n get aliases(): AliasResource {\n return this._aliases;\n }\n \n /**\n * Get account resource\n */\n get account(): AccountResource {\n return this._account;\n }\n \n /**\n * Get keys resource\n */\n get keys(): KeysResource {\n return this._keys;\n }\n}","/**\n * @file Shared SDK exports - environment agnostic.\n */\n\n// Core functionality\nexport * from './resources.js';\nexport * from './types.js';\nexport * from './api/http.js';\nexport * from './core/constants.js';\nexport * from './core/config.js';\nexport { Ship } from './base-ship.js';\n\n// Shared utilities\nexport * from './lib/md5.js';\nexport * from './lib/text.js';\nexport * from './lib/junk.js';\nexport * from './lib/deploy-paths.js';\nexport * from './lib/env.js';\n\n// Re-export types from @shipstatic/types\nexport { ShipError, ShipErrorType } from '@shipstatic/types';\nexport type { PingResponse, Deployment, Alias, Account } from '@shipstatic/types';","/**\n * @file SDK-specific type definitions\n * Consolidates all Ship SDK types into a single file for clarity.\n * Core types come from @shipstatic/types, while SDK-specific types are defined here.\n */\n\n// Re-export all types from @shipstatic/types for convenience\nexport * from '@shipstatic/types';\n\n// =============================================================================\n// DEPLOYMENT OPTIONS\n// =============================================================================\n\n/**\n * Universal deploy options for both Node.js and Browser environments\n */\nexport interface DeploymentOptions {\n /** The API URL to use for this specific deploy. Overrides client's default. */\n apiUrl?: string;\n /** An AbortSignal to allow cancellation of the deploy operation. */\n signal?: AbortSignal;\n /** An optional subdomain to suggest for the deployment. Availability is subject to the API. */\n subdomain?: string;\n /** Callback invoked if the deploy is cancelled via the AbortSignal. */\n onCancel?: () => void;\n /** Maximum number of concurrent operations. */\n maxConcurrency?: number;\n /** Timeout in milliseconds for the deploy request. */\n timeout?: number;\n /** API key for this specific deploy. Overrides client's default. */\n apiKey?: string;\n /** Deploy token for this specific deploy. Overrides client's default. */\n deployToken?: string;\n /** Whether to auto-detect and optimize file paths by flattening common directories. Defaults to true. */\n pathDetect?: boolean;\n /** Whether to auto-detect SPAs and generate ship.json configuration. Defaults to true. */\n spaDetect?: boolean;\n /** Callback for overall deploy progress (0-100). */\n onProgress?: (progress: number) => void;\n /** Callback for detailed progress statistics. */\n onProgressStats?: (progressStats: ProgressStats) => void;\n}\n\n/**\n * Options for configuring an deploy operation via `apiClient.deployFiles`.\n * Derived from DeploymentOptions but excludes client-side only options.\n */\nexport type ApiDeployOptions = Omit<DeploymentOptions, 'pathDetect'>;\n\n// =============================================================================\n// PROGRESS TRACKING\n// =============================================================================\n\n/**\n * Detailed statistics about the progress of an deploy operation.\n */\nexport interface ProgressStats {\n /** The number of bytes loaded so far. */\n loaded: number;\n /** The total number of bytes to be loaded. May be 0 if unknown initially. */\n total: number;\n /** The progress as a fraction (loaded/total). Value is between 0 and 1. */\n progress: number;\n /** Optional identifier for the file this progress pertains to, if applicable. */\n file?: string;\n}\n\n// =============================================================================\n// CLIENT CONFIGURATION\n// =============================================================================\n\n/**\n * Options for configuring a `Ship` instance.\n * Sets default API host, authentication credentials, progress callbacks, concurrency, and timeouts for the client.\n */\nexport interface ShipClientOptions {\n /** Default API URL for the client instance. */\n apiUrl?: string | undefined;\n /** API key for authenticated deployments. */\n apiKey?: string | undefined;\n /** Deploy token for single-use deployments. */\n deployToken?: string | undefined;\n /** Path to custom config file. */\n configFile?: string | undefined;\n /**\n * Default callback for overall deploy progress for deploys made with this client.\n * @param progress - A number between 0 and 100.\n */\n onProgress?: ((progress: number) => void) | undefined;\n /**\n * Default callback for detailed progress statistics for deploys made with this client.\n * @param progressStats - Progress statistics object.\n */\n onProgressStats?: ((progressStats: ProgressStats) => void) | undefined;\n /**\n * Default for maximum concurrent deploys.\n * Used if an deploy operation doesn't specify its own `maxConcurrency`.\n * Defaults to 4 if not set here or in the specific deploy call.\n */\n maxConcurrency?: number | undefined;\n /**\n * Default timeout in milliseconds for API requests made by this client instance.\n * Used if an deploy operation doesn't specify its own timeout.\n */\n timeout?: number | undefined;\n}\n\n// StaticFile is now imported from @shipstatic/types\n\n// =============================================================================\n// API RESPONSES\n// =============================================================================\n\n// PingResponse is imported from @shipstatic/types (single source of truth)","/**\n * @file SDK-specific constants.\n * Platform constants are now in @shipstatic/types.\n */\n\n// Re-export platform constants for convenience\nexport { DEFAULT_API } from '@shipstatic/types';","/**\n * Utility functions for string manipulation.\n */\n\n/**\n * Simple utility to pluralize a word based on a count.\n * @param count The number to determine pluralization.\n * @param singular The singular form of the word.\n * @param plural The plural form of the word.\n * @param includeCount Whether to include the count in the returned string. Defaults to true.\n * @returns A string with the count and the correctly pluralized word.\n */\nexport function pluralize(\n count: number,\n singular: string,\n plural: string,\n includeCount: boolean = true\n): string {\n const word = count === 1 ? singular : plural;\n return includeCount ? `${count} ${word}` : word;\n}\n","/**\n * Simple CLI utilities following \"impossible simplicity\" mantra\n */\nimport columnify from 'columnify';\nimport { bold, dim, green, red, yellow, blue, inverse, hidden } from 'yoctocolors';\n\n/**\n * Helper to conditionally apply colors based on noColor flag\n */\nconst applyColor = (colorFn: (text: string) => string, text: string, noColor?: boolean): string => {\n return noColor ? text : colorFn(text);\n};\n\n/**\n * Message helper functions for consistent CLI output\n */\nexport const success = (msg: string, isJson?: boolean, noColor?: boolean) => {\n if (isJson) {\n console.log(JSON.stringify({ success: msg }, null, 2) + '\\n');\n } else {\n console.log(`${applyColor(green, msg.toLowerCase().replace(/\\.$/, ''), noColor)}\\n`);\n }\n};\n\nexport const error = (msg: string, isJson?: boolean, noColor?: boolean) => {\n if (isJson) {\n console.error(JSON.stringify({ error: msg }, null, 2) + '\\n');\n } else {\n const errorPrefix = applyColor((text) => inverse(red(text)), `${applyColor(hidden, '[', noColor)}error${applyColor(hidden, ']', noColor)}`, noColor);\n const errorMsg = applyColor(red, msg.toLowerCase().replace(/\\.$/, ''), noColor);\n console.error(`${errorPrefix} ${errorMsg}\\n`);\n }\n};\n\nexport const warn = (msg: string, isJson?: boolean, noColor?: boolean) => {\n if (isJson) {\n console.log(JSON.stringify({ warning: msg }, null, 2) + '\\n');\n } else {\n const warnPrefix = applyColor((text) => inverse(yellow(text)), `${applyColor(hidden, '[', noColor)}warning${applyColor(hidden, ']', noColor)}`, noColor);\n const warnMsg = applyColor(yellow, msg.toLowerCase().replace(/\\.$/, ''), noColor);\n console.log(`${warnPrefix} ${warnMsg}\\n`);\n }\n};\n\nexport const info = (msg: string, isJson?: boolean, noColor?: boolean) => {\n if (isJson) {\n console.log(JSON.stringify({ info: msg }, null, 2) + '\\n');\n } else {\n const infoPrefix = applyColor((text) => inverse(blue(text)), `${applyColor(hidden, '[', noColor)}info${applyColor(hidden, ']', noColor)}`, noColor);\n const infoMsg = applyColor(blue, msg.toLowerCase().replace(/\\.$/, ''), noColor);\n console.log(`${infoPrefix} ${infoMsg}\\n`);\n }\n};\n\n\n/**\n * Format unix timestamp to ISO 8601 string without milliseconds, or return '-' if not provided\n */\nexport const formatTimestamp = (timestamp?: number, context: 'table' | 'details' = 'details', noColor?: boolean): string => {\n if (timestamp === undefined || timestamp === null || timestamp === 0) {\n return '-';\n }\n \n const isoString = new Date(timestamp * 1000).toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n \n // Hide the T and Z characters only in table/list views for cleaner appearance\n if (context === 'table') {\n return isoString.replace(/T/, applyColor(hidden, 'T', noColor)).replace(/Z$/, applyColor(hidden, 'Z', noColor));\n }\n \n return isoString;\n};\n\n/**\n * Format value for display\n */\nconst formatValue = (key: string, value: any, context: 'table' | 'details' = 'details', noColor?: boolean): string => {\n if (typeof value === 'number' && (key === 'created' || key === 'expires' || key === 'confirmed')) {\n return formatTimestamp(value, context, noColor);\n }\n if (key === 'size' && typeof value === 'number') {\n const mb = value / (1024 * 1024);\n return mb >= 1 ? `${mb.toFixed(1)}Mb` : `${(value / 1024).toFixed(1)}Kb`;\n }\n if (key === 'config') {\n // Handle both boolean and number (0/1) values\n if (typeof value === 'boolean') {\n return value ? 'yes' : 'no';\n }\n if (typeof value === 'number') {\n return value === 1 ? 'yes' : 'no';\n }\n }\n return String(value);\n};\n\n/**\n * Format data as table with specified columns for easy parsing\n */\nexport const formatTable = (data: any[], columns?: string[], noColor?: boolean): string => {\n if (!data || data.length === 0) return '';\n \n // Get column order from first item (preserves API order) or use provided columns\n const firstItem = data[0] || {};\n const columnOrder = columns || Object.keys(firstItem).filter(key => \n firstItem[key] !== undefined && key !== 'verified' && key !== 'isCreate'\n );\n \n // Transform data preserving column order\n const transformedData = data.map(item => {\n const transformed: any = {};\n columnOrder.forEach(col => {\n if (col in item && item[col] !== undefined) {\n transformed[col] = formatValue(col, item[col], 'table', noColor);\n }\n });\n return transformed;\n });\n \n const output = columnify(transformedData, {\n columnSplitter: ' ', // Use 3 spaces for visual alignment\n columns: columnOrder, // Explicitly preserve order\n config: columnOrder.reduce((config, col) => {\n config[col] = { headingTransform: (heading: string) => applyColor(dim, heading, noColor) };\n return config;\n }, {} as any)\n });\n \n // Clean output: remove null bytes and ensure clean spacing\n return output\n .split('\\n')\n .map((line: string) => line\n .replace(/\\0/g, '') // Remove any null bytes\n .replace(/\\s+$/, '') // Remove trailing spaces\n )\n .join('\\n') + '\\n';\n};\n\n/**\n * Format object properties as key-value pairs with space separation for readability\n */\nexport const formatDetails = (obj: any, noColor?: boolean): string => {\n const entries = Object.entries(obj).filter(([key, value]) => {\n // Filter out internal properties only\n if (key === 'verified' || key === 'isCreate') return false;\n return value !== undefined;\n });\n \n if (entries.length === 0) return '';\n \n // Transform to columnify format while preserving order\n const data = entries.map(([key, value]) => ({\n property: key + ':',\n value: formatValue(key, value, 'details', noColor)\n }));\n \n const output = columnify(data, {\n columnSplitter: ' ',\n showHeaders: false,\n config: {\n property: { \n dataTransform: (value: string) => applyColor(dim, value, noColor)\n }\n }\n });\n \n // Clean output: remove null bytes and ensure clean spacing\n return output\n .split('\\n')\n .map((line: string) => line.replace(/\\0/g, '')) // Remove any null bytes\n .join('\\n') + '\\n';\n};\n\n"],"mappings":";qnBAAA,IAAAA,GAAA,GAAAC,EAAAD,GAAA,0BAAAE,GAAA,WAAAC,IAuBO,SAASD,GAAqBE,EAAwC,CAC3EC,GAAmBD,CACrB,CAQA,SAASE,IAA0C,CAEjD,OAAI,OAAO,QAAY,KAAe,QAAQ,UAAY,QAAQ,SAAS,KAClE,OAIL,OAAO,OAAW,KAAe,OAAO,KAAS,IAC5C,UAGF,SACT,CAWO,SAASH,GAA+B,CAE7C,OAAIE,IAKGC,GAAkB,CAC3B,CAhEA,IAWID,GAXJE,EAAAC,EAAA,kBAWIH,GAAgD,OCXpD,IAAAI,GAAA,GAAAC,EAAAD,GAAA,gBAAAE,KAkCA,SAASC,GAAeC,EAAyC,CAC/D,GAAI,CACF,OAAOC,GAAa,MAAMD,CAAM,CAClC,OAASE,EAAO,CACd,GAAIA,aAAiB,IAAE,SAAU,CAC/B,IAAMC,EAAaD,EAAM,OAAO,CAAC,EAC3BE,EAAOD,EAAW,KAAK,OAAS,EAAI,OAAOA,EAAW,KAAK,KAAK,GAAG,CAAC,GAAK,GAC/E,MAAM,aAAU,OAAO,kCAAkCC,CAAI,KAAKD,EAAW,OAAO,EAAE,CACxF,CACA,MAAM,aAAU,OAAO,iCAAiC,CAC1D,CACF,CAUA,eAAeE,GAAmBC,EAA0D,CAC1F,GAAI,CAEF,GAAIC,EAAO,IAAM,OACf,MAAO,CAAC,EAIV,GAAM,CAAE,gBAAAC,CAAgB,EAAI,KAAM,QAAO,aAAa,EAChDC,EAAK,KAAM,QAAO,IAAI,EAEtBC,EAAWF,EAAgBG,GAAa,CAC5C,aAAc,CACZ,IAAIA,EAAW,KACf,eACA,GAAGF,EAAG,QAAQ,CAAC,KAAKE,EAAW,IACjC,EACA,QAASF,EAAG,QAAQ,CACtB,CAAC,EAEGG,EAWJ,GARIN,EACFM,EAASF,EAAS,KAAKJ,CAAU,EAIjCM,EAASF,EAAS,OAAO,EAGvBE,GAAUA,EAAO,OACnB,OAAOb,GAAea,EAAO,MAAM,CAEvC,OAASV,EAAO,CACd,GAAIA,aAAiB,aAAW,MAAMA,CAExC,CACA,MAAO,CAAC,CACV,CAWA,eAAsBJ,GAAWQ,EAA0D,CACzF,GAAIC,EAAO,IAAM,OAAQ,MAAO,CAAC,EAGjC,IAAMM,EAAY,CAChB,OAAQ,QAAQ,IAAI,aACpB,OAAQ,QAAQ,IAAI,aACpB,YAAa,QAAQ,IAAI,iBAC3B,EAGMC,EAAa,MAAMT,GAAmBC,CAAU,EAGhDS,EAAe,CACnB,OAAQF,EAAU,QAAUC,EAAW,OACvC,OAAQD,EAAU,QAAUC,EAAW,OACvC,YAAaD,EAAU,aAAeC,EAAW,WACnD,EAGA,OAAOf,GAAegB,CAAY,CACpC,CA/HA,IAOAC,EAEAC,GAOMN,GAMAV,GAtBNiB,GAAAC,EAAA,kBAOAH,EAAkB,eAElBC,GAA0B,6BAC1BG,IAMMT,GAAc,OAMdV,GAAe,IAAE,OAAO,CAC5B,OAAQ,IAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAClC,OAAQ,IAAE,OAAO,EAAE,SAAS,EAC5B,YAAa,IAAE,OAAO,EAAE,SAAS,CACnC,CAAC,EAAE,OAAO,ICbV,eAAeoB,GAAoBC,EAAgC,CACjE,IAAMC,GAAY,KAAM,QAAO,WAAW,GAAG,QAE7C,OAAO,IAAI,QAAQ,CAACC,EAASC,IAAW,CAEtC,IAAMC,EAAS,KAAK,KAAKJ,EAAK,KAAO,OAAS,EAC1CK,EAAe,EACbC,EAAQ,IAAIL,EAAS,YACrBM,EAAa,IAAI,WAEjBC,EAAW,IAAM,CACrB,IAAMC,EAAQJ,EAAe,QACvBK,EAAM,KAAK,IAAID,EAAQ,QAAWT,EAAK,IAAI,EACjDO,EAAW,kBAAkBP,EAAK,MAAMS,EAAOC,CAAG,CAAC,CACrD,EAEAH,EAAW,OAAUI,GAAM,CACzB,IAAMC,EAASD,EAAE,QAAQ,OACzB,GAAI,CAACC,EAAQ,CACXT,EAAO,YAAU,SAAS,2BAA2B,CAAC,EACtD,MACF,CAEAG,EAAM,OAAOM,CAAM,EACnBP,IAEIA,EAAeD,EACjBI,EAAS,EAETN,EAAQ,CAAE,IAAKI,EAAM,IAAI,CAAE,CAAC,CAEhC,EAEAC,EAAW,QAAU,IAAM,CACzBJ,EAAO,YAAU,SAAS,2CAA2C,CAAC,CACxE,EAEAK,EAAS,CACX,CAAC,CACH,CAKA,eAAeK,GAAiBC,EAA4C,CAC1E,IAAMC,EAAS,KAAM,QAAO,QAAQ,EAEpC,GAAI,OAAO,SAASD,CAAK,EAAG,CAC1B,IAAME,EAAOD,EAAO,WAAW,KAAK,EACpC,OAAAC,EAAK,OAAOF,CAAK,EACV,CAAE,IAAKE,EAAK,OAAO,KAAK,CAAE,CACnC,CAGA,IAAMC,EAAK,KAAM,QAAO,IAAI,EAC5B,OAAO,IAAI,QAAQ,CAACf,EAASC,IAAW,CACtC,IAAMa,EAAOD,EAAO,WAAW,KAAK,EAC9BG,EAASD,EAAG,iBAAiBH,CAAK,EAExCI,EAAO,GAAG,QAASC,GACjBhB,EAAO,YAAU,SAAS,gCAAgCgB,EAAI,OAAO,EAAE,CAAC,CAC1E,EACAD,EAAO,GAAG,OAAQE,GAASJ,EAAK,OAAOI,CAAK,CAAC,EAC7CF,EAAO,GAAG,MAAO,IAAMhB,EAAQ,CAAE,IAAKc,EAAK,OAAO,KAAK,CAAE,CAAC,CAAC,CAC7D,CAAC,CACH,CAKA,eAAsBK,EAAaP,EAAmD,CACpF,IAAMQ,EAAMC,EAAO,EAEnB,GAAID,IAAQ,UAAW,CACrB,GAAI,EAAER,aAAiB,MACrB,MAAM,YAAU,SAAS,mEAAmE,EAE9F,OAAOf,GAAoBe,CAAK,CAClC,CAEA,GAAIQ,IAAQ,OAAQ,CAClB,GAAI,EAAE,OAAO,SAASR,CAAK,GAAK,OAAOA,GAAU,UAC/C,MAAM,YAAU,SAAS,iFAAiF,EAE5G,OAAOD,GAAiBC,CAAK,CAC/B,CAEA,MAAM,YAAU,SAAS,mEAAmE,CAC9F,CArGA,IAIAU,EAJAC,GAAAC,EAAA,kBAGAC,IACAH,EAA0B,+BCUnB,SAASI,GAAUC,EAA8B,CACtDC,GAAUD,CACZ,CAMO,SAASE,GAAmC,CACjD,GAAID,KAAY,KACd,MAAM,aAAU,OACd,qHACF,EAEF,OAAOA,EACT,CA7BA,IAMAE,GAGIF,GATJG,GAAAC,EAAA,kBAMAF,GAA0B,6BAGtBF,GAAiC,OC2B9B,SAASK,EAAWC,EAA+B,CACxD,MAAI,CAACA,GAAaA,EAAU,SAAW,EAC9B,CAAC,EAGHA,EAAU,OAAOC,GAAY,CAClC,GAAI,CAACA,EACH,MAAO,GAIT,IAAMC,EAAQD,EAAS,QAAQ,MAAO,GAAG,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO,EACpE,GAAIC,EAAM,SAAW,EAAG,MAAO,GAG/B,IAAMC,EAAWD,EAAMA,EAAM,OAAS,CAAC,EACvC,MAAI,WAAOC,CAAQ,EACjB,MAAO,GAIT,IAAMC,EAAoBF,EAAM,MAAM,EAAG,EAAE,EAC3C,QAAWG,KAAWD,EACpB,GAAIE,GAAiB,KAAKC,GACtBF,EAAQ,YAAY,IAAME,EAAQ,YAAY,CAAC,EACjD,MAAO,GAIX,MAAO,EACT,CAAC,CACH,CAnEA,IAOAC,GAUaF,GAjBbG,GAAAC,EAAA,kBAOAF,GAAuB,gBAUVF,GAAmB,CAC9B,WACA,WACA,aACA,iBACF,ICVO,SAASK,GAAiBC,EAA4B,CAC3D,GAAI,CAACA,GAAYA,EAAS,SAAW,EAAG,MAAO,GAG/C,IAAMC,EAAkBD,EACrB,OAAOE,GAAKA,GAAK,OAAOA,GAAM,QAAQ,EACtC,IAAIA,GAAKA,EAAE,QAAQ,MAAO,GAAG,CAAC,EAEjC,GAAID,EAAgB,SAAW,EAAG,MAAO,GACzC,GAAIA,EAAgB,SAAW,EAAG,OAAOA,EAAgB,CAAC,EAG1D,IAAME,EAAeF,EAAgB,IAAIC,GAAKA,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO,CAAC,EACpEE,EAAiB,CAAC,EAClBC,EAAY,KAAK,IAAI,GAAGF,EAAa,IAAID,GAAKA,EAAE,MAAM,CAAC,EAE7D,QAASI,EAAI,EAAGA,EAAID,EAAWC,IAAK,CAClC,IAAMC,EAAUJ,EAAa,CAAC,EAAEG,CAAC,EACjC,GAAIH,EAAa,MAAMK,GAAYA,EAASF,CAAC,IAAMC,CAAO,EACxDH,EAAe,KAAKG,CAAO,MAE3B,MAEJ,CAEA,OAAOH,EAAe,KAAK,GAAG,CAChC,CAoBO,SAASK,GAAiBC,EAAsB,CACrD,OAAOA,EAAK,QAAQ,MAAO,GAAG,EAAE,QAAQ,OAAQ,GAAG,EAAE,QAAQ,OAAQ,EAAE,CACzE,CA5DA,IAAAC,GAAAC,EAAA,oBC4BO,SAASC,EACdC,EACAC,EAAiC,CAAC,EACpB,CAEd,GAAIA,EAAQ,UAAY,GACtB,OAAOD,EAAU,IAAIE,IAAS,CAC5B,KAAMC,GAAiBD,CAAI,EAC3B,KAAME,GAAgBF,CAAI,CAC5B,EAAE,EAIJ,IAAMG,EAAeC,GAAoBN,CAAS,EAElD,OAAOA,EAAU,IAAIO,GAAY,CAC/B,IAAIC,EAAaL,GAAiBI,CAAQ,EAG1C,GAAIF,EAAc,CAChB,IAAMI,EAAiBJ,EAAa,SAAS,GAAG,EAAIA,EAAe,GAAGA,CAAY,IAC9EG,EAAW,WAAWC,CAAc,IACtCD,EAAaA,EAAW,UAAUC,EAAe,MAAM,EAE3D,CAGA,OAAKD,IACHA,EAAaJ,GAAgBG,CAAQ,GAGhC,CACL,KAAMC,EACN,KAAMJ,GAAgBG,CAAQ,CAChC,CACF,CAAC,CACH,CAWA,SAASD,GAAoBN,EAA6B,CACxD,GAAI,CAACA,EAAU,OAAQ,MAAO,GAM9B,IAAMU,EAHkBV,EAAU,IAAIE,GAAQC,GAAiBD,CAAI,CAAC,EAG/B,IAAIA,GAAQA,EAAK,MAAM,GAAG,CAAC,EAC1DS,EAA2B,CAAC,EAC5BC,EAAY,KAAK,IAAI,GAAGF,EAAa,IAAIG,GAAYA,EAAS,MAAM,CAAC,EAG3E,QAASC,EAAI,EAAGA,EAAIF,EAAY,EAAGE,IAAK,CACtC,IAAMC,EAAUL,EAAa,CAAC,EAAEI,CAAC,EACjC,GAAIJ,EAAa,MAAMG,GAAYA,EAASC,CAAC,IAAMC,CAAO,EACxDJ,EAAe,KAAKI,CAAO,MAE3B,MAEJ,CAEA,OAAOJ,EAAe,KAAK,GAAG,CAChC,CAKA,SAASP,GAAgBF,EAAsB,CAC7C,OAAOA,EAAK,MAAM,OAAO,EAAE,IAAI,GAAKA,CACtC,CAxGA,IAAAc,GAAAC,EAAA,kBAKAC,OCkBA,SAASC,GAAiBC,EAA2B,CACnD,IAAMC,EAAoB,CAAC,EAE3B,GAAI,CACF,IAAMC,EAAa,cAAYF,CAAO,EAEtC,QAAWG,KAASD,EAAS,CAC3B,IAAME,EAAgB,OAAKJ,EAASG,CAAK,EACnCE,EAAW,WAASD,CAAQ,EAElC,GAAIC,EAAM,YAAY,EAAG,CACvB,IAAMC,EAAWP,GAAiBK,CAAQ,EAC1CH,EAAQ,KAAK,GAAGK,CAAQ,CAC1B,MAAWD,EAAM,OAAO,GACtBJ,EAAQ,KAAKG,CAAQ,CAEzB,CACF,OAASG,EAAO,CACd,QAAQ,MAAM,2BAA2BP,CAAO,IAAKO,CAAK,CAC5D,CAEA,OAAON,CACT,CAWA,eAAsBO,GACpBC,EACAC,EAA6B,CAAC,EACP,CACvB,GAAIC,EAAO,IAAM,OACf,MAAM,YAAU,SAAS,gEAAgE,EAI3F,IAAMC,EAAgBH,EAAM,QAAQI,GAAK,CACvC,IAAMC,EAAe,UAAQD,CAAC,EAC9B,GAAI,CAEF,OADiB,WAASC,CAAO,EACpB,YAAY,EAAIf,GAAiBe,CAAO,EAAI,CAACA,CAAO,CACnE,MAAgB,CACd,MAAM,YAAU,KAAK,wBAAwBD,CAAC,GAAIA,CAAC,CACrD,CACF,CAAC,EACKE,EAAc,CAAC,GAAG,IAAI,IAAIH,CAAa,CAAC,EAGxCI,EAAaC,EAAWF,CAAW,EACzC,GAAIC,EAAW,SAAW,EACxB,MAAO,CAAC,EAKV,IAAME,EAAqBT,EAAM,IAAII,GAAU,UAAQA,CAAC,CAAC,EACnDM,EAAgBC,GAAiBF,EAAmB,IAAIL,GAAK,CACjE,GAAI,CAEF,OADiB,WAASA,CAAC,EACd,YAAY,EAAIA,EAAS,UAAQA,CAAC,CACjD,MAAQ,CACN,OAAY,UAAQA,CAAC,CACvB,CACF,CAAC,CAAC,EAGIQ,EAAgBL,EAAW,IAAIM,GAAY,CAE/C,GAAIH,GAAiBA,EAAc,OAAS,EAAG,CAC7C,IAAMI,EAAW,WAASJ,EAAeG,CAAQ,EACjD,GAAIC,GAAO,OAAOA,GAAQ,UAAY,CAACA,EAAI,WAAW,IAAI,EACxD,OAAOA,EAAI,QAAQ,MAAO,GAAG,CAEjC,CAGA,OAAY,WAASD,CAAQ,CAC/B,CAAC,EAGKE,EAAcC,EAAoBJ,EAAe,CACrD,QAASX,EAAQ,aAAe,EAClC,CAAC,EAGKT,EAAwB,CAAC,EAC3ByB,EAAY,EACVC,EAAiBC,EAAiB,EAExC,QAASC,EAAI,EAAGA,EAAIb,EAAW,OAAQa,IAAK,CAC1C,IAAMP,EAAWN,EAAWa,CAAC,EACvBC,EAAaN,EAAYK,CAAC,EAAE,KAElC,GAAI,CACF,IAAMxB,EAAW,WAASiB,CAAQ,EAClC,GAAIjB,EAAM,OAAS,EAAG,CACpB,QAAQ,KAAK,wBAAwBiB,CAAQ,EAAE,EAC/C,QACF,CAGA,GAAIjB,EAAM,KAAOsB,EAAe,YAC9B,MAAM,YAAU,SAAS,QAAQL,CAAQ,0CAA0CK,EAAe,aAAe,KAAO,KAAK,KAAK,EAGpI,GADAD,GAAarB,EAAM,KACfqB,EAAYC,EAAe,aAC7B,MAAM,YAAU,SAAS,sDAAsDA,EAAe,cAAgB,KAAO,KAAK,KAAK,EAGjI,IAAMI,EAAa,eAAaT,CAAQ,EAClC,CAAE,IAAAU,EAAI,EAAI,MAAMC,EAAaF,CAAO,EAG1C,GAAID,EAAW,SAAS,IAAI,GAAKA,EAAW,SAAS,MAAM,GAAKA,EAAW,WAAW,KAAK,GAAKA,EAAW,SAAS,KAAK,EACvH,MAAM,YAAU,SAAS,qCAAqCA,CAAU,eAAeR,CAAQ,EAAE,EAGnGrB,EAAQ,KAAK,CACX,KAAM6B,EACN,QAAAC,EACA,KAAMA,EAAQ,OACd,IAAAC,EACF,CAAC,CACH,OAASzB,EAAO,CACd,GAAIA,aAAiB,aAAaA,EAAM,eAAiBA,EAAM,cAAc,EAC3E,MAAMA,EAER,QAAQ,MAAM,0BAA0Be,CAAQ,IAAKf,CAAK,CAC5D,CACF,CAGA,GAAIN,EAAQ,OAAS0B,EAAe,cAClC,MAAM,YAAU,SAAS,gDAAgDA,EAAe,aAAa,SAAS,EAGhH,OAAO1B,CACT,CAtKA,IAQAiC,EAKAC,EACAC,EAdAC,GAAAC,EAAA,kBAIAC,IAEAC,KACAC,KACAP,EAA0B,6BAC1BQ,KACAC,KACAC,KAEAT,EAAoB,mBACpBC,EAAsB,uBCetB,eAAsBS,GACpBC,EACAC,EAA6B,CAAC,EACP,CAEvB,GAAM,CAAE,OAAAC,CAAO,EAAI,KAAM,sCACzB,GAAIA,EAAO,IAAM,UACf,MAAM,aAAU,SAAS,qEAAqE,EAGhG,IAAMC,EAAa,MAAM,QAAQH,CAAY,EAAIA,EAAe,MAAM,KAAKA,CAAY,EAGjFI,EAAYD,EAAW,IAAIE,GAASA,EAAa,oBAAsBA,EAAK,IAAI,EAGhFC,EAAcC,EAAoBH,EAAW,CACjD,QAASH,EAAQ,aAAe,EAClC,CAAC,EAGKO,EAA6C,CAAC,EACpD,QAASC,EAAI,EAAGA,EAAIN,EAAW,OAAQM,IAAK,CAC1C,IAAMJ,EAAOF,EAAWM,CAAC,EACnBC,EAAaJ,EAAYG,CAAC,EAAE,KAGlC,GAAIC,EAAW,SAAS,IAAI,GAAKA,EAAW,SAAS,IAAI,EACvD,MAAM,aAAU,SAAS,qCAAqCA,CAAU,eAAeL,EAAK,IAAI,EAAE,EAGpGG,EAAiB,KAAK,CAAE,KAAAH,EAAM,aAAcK,CAAW,CAAC,CAC1D,CAGA,IAAMC,EAAmBH,EAAiB,IAAII,GAAQA,EAAK,YAAY,EACjEC,EAA4BC,EAAWH,CAAgB,EACvDI,EAA0B,IAAI,IAAIF,CAAyB,EAG3DG,EAAuB,CAAC,EAC9B,QAAWC,KAAYT,EAAkB,CAEvC,GAAI,CAACO,EAAwB,IAAIE,EAAS,YAAY,EACpD,SAIF,GAAM,CAAE,IAAAC,CAAI,EAAI,MAAMC,EAAaF,EAAS,IAAI,EAGhDD,EAAO,KAAK,CACV,QAASC,EAAS,KAClB,KAAMA,EAAS,aACf,KAAMA,EAAS,KAAK,KACpB,IAAAC,CACF,CAAC,CACH,CAEA,OAAOF,CACT,CAzFA,IAMAI,GANAC,GAAAC,EAAA,kBAKAC,KACAH,GAA0B,6BAC1BI,KACAC,OCRA,IAAAC,GAAA,GAAAC,EAAAD,GAAA,yBAAAE,GAAA,uBAAAC,GAAA,qBAAAC,KAsBA,SAASC,GAAcC,EAA8CC,EAAwC,CAAC,EAAS,CACrH,IAAMC,EAASC,EAAiB,EAGhC,GAAI,CAACF,EAAQ,gBAAkBD,EAAM,SAAW,EAC9C,MAAM,YAAU,SAAS,qBAAqB,EAIhD,GAAIA,EAAM,OAASE,EAAO,cACxB,MAAM,YAAU,SAAS,gDAAgDA,EAAO,aAAa,GAAG,EAIlG,IAAIE,EAAY,EAChB,QAAWC,KAAQL,EAAO,CAExB,GAAIK,EAAK,KAAOH,EAAO,YACrB,MAAM,YAAU,SAAS,QAAQG,EAAK,IAAI,0CAA0CH,EAAO,aAAe,KAAO,KAAK,KAAK,EAK7H,GADAE,GAAaC,EAAK,KACdD,EAAYF,EAAO,aACrB,MAAM,YAAU,SAAS,sDAAsDA,EAAO,cAAgB,KAAO,KAAK,KAAK,CAE3H,CACF,CAUA,SAASI,GAAmBC,EAAYC,EAA2B,CACjE,GAAIA,IAAgB,OAAQ,CAC1B,GAAI,CAAC,MAAM,QAAQD,CAAK,EACtB,MAAM,YAAU,SAAS,2EAA2E,EAEtG,GAAIA,EAAM,SAAW,EACnB,MAAM,YAAU,SAAS,qBAAqB,EAEhD,GAAI,CAACA,EAAM,MAAME,GAAQ,OAAOA,GAAS,QAAQ,EAC/C,MAAM,YAAU,SAAS,2EAA2E,CAExG,SAAWD,IAAgB,WACrBD,aAAiB,kBAAoB,CAACA,EAAM,MAC9C,MAAM,YAAU,SAAS,uCAAuC,CAGtE,CAQA,SAASG,GAAiBV,EAAmC,CAE3D,IAAMW,EAAkBX,EAAM,IAAIY,IAAM,CAAE,KAAMA,EAAE,KAAM,KAAMA,EAAE,IAAK,EAAE,EACvE,OAAAb,GAAcY,EAAiB,CAAE,eAAgB,EAAK,CAAC,EAGvDX,EAAM,QAAQY,GAAK,CACbA,EAAE,OAAMA,EAAE,KAAOA,EAAE,KAAK,QAAQ,MAAO,GAAG,EAChD,CAAC,EAEMZ,CACT,CAKA,eAAsBF,GACpBS,EACAN,EAA6B,CAAC,EACP,CAEvBK,GAAmBC,EAAO,MAAM,EAGhC,IAAMM,EAA4B,MAAMC,GAAoBP,EAAON,CAAO,EAG1E,OAAOS,GAAiBG,CAAW,CACrC,CAKA,eAAsBjB,GACpBW,EACAN,EAA6B,CAAC,EACP,CAEvBK,GAAmBC,EAAO,SAAS,EAEnC,IAAIQ,EAEJ,GAAIR,aAAiB,iBACnBQ,EAAY,MAAM,KAAKR,EAAM,KAAM,UAEnC,OAAOA,GAAU,UACjBA,IAAU,MACV,OAAQA,EAAc,QAAW,UACjC,OAAQA,EAAc,MAAS,WAE/BQ,EAAY,MAAM,KAAKR,CAAiB,UAC/B,MAAM,QAAQA,CAAK,EAAG,CAC/B,GAAIA,EAAM,OAAS,GAAK,OAAOA,EAAM,CAAC,GAAM,SAC1C,MAAM,YAAU,SAAS,6FAA6F,EAExHQ,EAAYR,CACd,KACE,OAAM,YAAU,SAAS,6FAA6F,EAIxHQ,EAAYA,EAAU,OAAOV,GACvBA,EAAK,OAAS,GAChB,QAAQ,KAAK,wBAAwBA,EAAK,IAAI,EAAE,EACzC,IAEF,EACR,EAGDN,GAAcgB,CAAS,EAGvB,IAAMF,EAA4B,MAAMG,GAAuBD,EAAqBd,CAAO,EAG3F,OAAOS,GAAiBG,CAAW,CACrC,CAMA,eAAsBhB,GACpBU,EACAN,EAA6B,CAAC,EAC9BgB,EACuB,CACvB,IAAMT,EAAcU,EAAO,EAG3B,GAAIV,IAAgB,QAAUA,IAAgB,UAC5C,MAAM,YAAU,SAAS,oCAAoC,EAI/D,IAAIR,EACJ,GAAIQ,IAAgB,OAElB,GAAI,OAAOD,GAAU,SACnBP,EAAQ,MAAMF,GAAiB,CAACS,CAAK,EAAGN,CAAO,UACtC,MAAM,QAAQM,CAAK,GAAKA,EAAM,MAAME,GAAQ,OAAOA,GAAS,QAAQ,EAC7ET,EAAQ,MAAMF,GAAiBS,EAAmBN,CAAO,MAEzD,OAAM,YAAU,SAAS,2EAA2E,OAGtGD,EAAQ,MAAMJ,GAAoBW,EAA+CN,CAAO,EAG1F,OAAOD,CACT,CAlMA,IAMAmB,EANAC,GAAAC,EAAA,kBAMAF,EAAsD,6BACtDG,IACAC,KACAC,KACAC,OCNA,IAAAC,GAAwB,qBCJxB,IAAAC,EAAA,GAAAC,EAAAD,EAAA,aAAAE,EAAA,oDAAAC,GAAA,SAAAC,EAAA,qFAAAC,GAAA,iBAAAC,EAAA,0BAAAC,GAAA,wBAAAC,GAAA,6BAAAC,GAAA,uBAAAC,GAAA,YAAAC,GAAA,eAAAC,EAAA,qBAAAC,EAAA,WAAAC,EAAA,eAAAC,GAAA,uBAAAC,GAAA,wBAAAC,EAAA,cAAAC,GAAA,wBAAAC,GAAA,kBAAAC,GAAA,cAAAC,KCGA,IAAAC,GAAuB,2BAevBC,EAAuC,6BAEvCC,IAgBA,IAAMC,GAAkB,eAElBC,GAAgB,QAEhBC,GAAmB,WAEnBC,GAAkB,UAElBC,GAAmB,WAEnBC,GAAqB,aAS3B,SAASC,GAAsBC,EAA6B,CAC1D,OAAI,OAAOA,GAAS,SACL,UAAOA,CAAI,GAAK,2BAEhB,UAAOA,EAAK,IAAI,GAAKA,EAAK,MAAQ,0BAEnD,CAUA,eAAeC,GAAwBC,EAA0C,CAC/E,IAAMC,EAAc,CAAC,EACrB,cAAiBC,KAAKF,EACpBC,EAAO,KAAKC,CAAC,EAEf,OAAOD,CACT,CAOO,IAAME,EAAN,KAAc,CASnB,YAAYC,EAA4B,CACtC,KAAK,OAASA,EAAQ,QAAU,cAChC,KAAK,OAASA,EAAQ,QAAU,GAChC,KAAK,YAAcA,EAAQ,aAAe,EAC5C,CASAC,GAAgBC,EAAwC,CAAC,EAA2B,CAClF,IAAMC,EAAU,CAAE,GAAGD,CAAc,EAGnC,OAAI,KAAK,YACPC,EAAQ,cAAmB,UAAU,KAAK,WAAW,GAC5C,KAAK,SACdA,EAAQ,cAAmB,UAAU,KAAK,MAAM,IAG3CA,CACT,CAWA,KAAMC,GAAeC,EAAaL,EAAuB,CAAC,EAAGM,EAA0C,CACrG,IAAMH,EAAU,KAAKF,GAAgBD,EAAQ,OAAiC,EAExEO,EAA4B,CAChC,GAAGP,EACH,QAAAG,CACF,EAGMK,EAAyB,CAAC,EAAE,KAAK,QAAU,KAAK,aAChDC,EAAyB,CAAC,CAAEN,GAAiB,cAE/C,CAACK,GAA0B,CAACC,IAC9BF,EAAa,YAAc,WAG7B,GAAI,CAEF,OADiB,MAAM,MAAMF,EAAKE,CAAY,CAEhD,OAASG,EAAY,CACnB,WAAKC,GAAkBD,EAAOJ,CAAa,EAErCI,CACR,CACF,CAaA,KAAME,GAAYP,EAAaL,EAAuB,CAAC,EAAGM,EAAmC,CAC3F,GAAI,CACF,IAAMO,EAAW,MAAM,KAAKT,GAAeC,EAAKL,EAASM,CAAa,EAQtE,OANKO,EAAS,IACZ,MAAM,KAAKC,GAAqBD,EAAUP,CAAa,EAInCO,EAAS,QAAQ,IAAI,gBAAgB,IACrC,KAAOA,EAAS,SAAW,IAC/C,OAGK,MAAMA,EAAS,KAAK,CAC7B,OAASH,EAAY,CACnB,MAAIA,aAAiB,aAGrB,KAAKC,GAAkBD,EAAOJ,CAAa,EAErCI,CACR,CACF,CAQA,MAAa,MAAyB,CAEpC,OADa,MAAM,KAAKE,GAAuB,GAAG,KAAK,MAAM,GAAGxB,EAAa,GAAI,CAAE,OAAQ,KAAM,EAAG,MAAM,IAC7F,SAAW,EAC1B,CAMA,MAAa,iBAAyC,CACpD,OAAO,MAAM,KAAKwB,GAAuB,GAAG,KAAK,MAAM,GAAGxB,EAAa,GAAI,CAAE,OAAQ,KAAM,EAAG,MAAM,CACtG,CAOA,MAAa,WAAqC,CAChD,OAAO,MAAM,KAAKwB,GAAyB,GAAG,KAAK,MAAM,GAAGtB,EAAe,GAAI,CAAE,OAAQ,KAAM,EAAG,QAAQ,CAC5G,CAeA,MAAa,OACXyB,EACAf,EAA4B,CAAC,EACR,CACrB,KAAKgB,GAAeD,CAAK,EAEzB,GAAM,CACJ,OAAAE,EAAS,KAAK,OACd,OAAAC,EACA,OAAAC,EACA,YAAAC,CACF,EAAIpB,EAEE,CAAE,YAAAqB,EAAa,eAAAC,CAAe,EAAI,MAAM,KAAKC,GAAuBR,CAAK,EAI3ES,EAAc,CAAC,EACfJ,EACFI,EAAc,CAAE,cAAiB,UAAUJ,CAAW,EAAG,EAChDD,IACTK,EAAc,CAAE,cAAiB,UAAUL,CAAM,EAAG,GAGtD,IAAMZ,EAA4B,CAChC,OAAQ,OACR,KAAMc,EACN,QAAS,CAAE,GAAGC,EAAgB,GAAGE,CAAY,EAC7C,OAAQN,GAAU,IACpB,EAGA,OAAO,MAAM,KAAKN,GAAqB,GAAGK,CAAM,GAAG9B,EAAe,GAAIoB,EAAc,QAAQ,CAC9F,CAUAS,GAAeD,EAA2B,CACxC,GAAI,CAACA,EAAM,OACT,MAAM,YAAU,SAAS,qBAAqB,EAGhD,QAAWrB,KAAQqB,EACjB,GAAI,CAACrB,EAAK,IACR,MAAM,YAAU,KAAK,kCAAkCA,EAAK,IAAI,GAAIA,EAAK,IAAI,CAGnF,CAUA,KAAM6B,GAAuBR,EAG1B,CACD,IAAIM,EACAC,EAAyC,CAAC,EAE9C,GAAIG,EAAO,IAAM,UACfJ,EAAc,KAAKK,GAAmBX,CAAK,UAClCU,EAAO,IAAM,OAAQ,CAC9B,GAAM,CAAE,KAAAE,EAAM,QAAAxB,CAAQ,EAAI,MAAM,KAAKyB,GAAgBb,CAAK,EAC1DM,EAAcM,EAAK,OAAO,MAAMA,EAAK,WAAYA,EAAK,WAAaA,EAAK,UAAU,EAClFL,EAAiBnB,CACnB,KACE,OAAM,YAAU,SAAS,8CAA8C,EAGzE,MAAO,CAAE,YAAAkB,EAAa,eAAAC,CAAe,CACvC,CASAI,GAAmBX,EAA+B,CAChD,IAAMc,EAAW,IAAI,SACfC,EAAsB,CAAC,EAE7B,QAAS,EAAI,EAAG,EAAIf,EAAM,OAAQ,IAAK,CACrC,IAAMrB,EAAOqB,EAAM,CAAC,EAChBgB,EAEJ,GAAIrC,EAAK,mBAAmB,MAAQA,EAAK,mBAAmB,KAC1DqC,EAAcrC,EAAK,YAEnB,OAAM,YAAU,KAAK,uDAAuDA,EAAK,IAAI,GAAIA,EAAK,IAAI,EAGpG,IAAMsC,EAAcvC,GAAsBsC,aAAuB,KAAOA,EAAcrC,EAAK,IAAI,EACzFuC,EAAe,IAAI,KAAK,CAACF,CAAW,EAAGrC,EAAK,KAAM,CAAE,KAAMsC,CAAY,CAAC,EAC7EH,EAAS,OAAO,UAAWI,CAAY,EACvCH,EAAU,KAAKpC,EAAK,GAAI,CAC1B,CAGA,OAAAmC,EAAS,OAAO,YAAa,KAAK,UAAUC,CAAS,CAAC,EAC/CD,CACT,CASA,KAAMD,GAAgBb,EAA+E,CACnG,GAAM,CAAE,SAAUmB,EAAmB,KAAMC,CAAc,EAAI,KAAM,QAAO,eAAe,EACnF,CAAE,gBAAiBC,CAAqB,EAAI,KAAM,QAAO,mBAAmB,EAC5EC,EAAa,KAAM,QAAO,MAAM,EAChCC,EAAqC,IAAIJ,EACzCJ,EAAsB,CAAC,EAE7B,QAASS,EAAI,EAAGA,EAAIxB,EAAM,OAAQwB,IAAK,CACrC,IAAM7C,EAAOqB,EAAMwB,CAAC,EACdP,EAAoB,UAAOtC,EAAK,IAAI,GAAK,2BAC3C8C,EAEJ,GAAI,OAAO,SAAS9C,EAAK,OAAO,EAC9B8C,EAAmB,IAAIL,EAAc,CAACzC,EAAK,OAAO,EAAGA,EAAK,KAAM,CAAE,KAAMsC,CAAY,CAAC,UAC5E,OAAO,KAAS,KAAetC,EAAK,mBAAmB,KAChE8C,EAAmB,IAAIL,EAAc,CAACzC,EAAK,OAAO,EAAGA,EAAK,KAAM,CAAE,KAAMsC,CAAY,CAAC,MAErF,OAAM,YAAU,KAAK,uDAAuDtC,EAAK,IAAI,GAAIA,EAAK,IAAI,EAEpG,IAAM+C,EAAgB/C,EAAK,KAAK,WAAW,GAAG,EAAIA,EAAK,KAAO,IAAMA,EAAK,KACzE4C,EAAqB,OAAO,UAAWE,EAAkBC,CAAa,EACtEX,EAAU,KAAKpC,EAAK,GAAI,CAC1B,CAGA4C,EAAqB,OAAO,YAAa,KAAK,UAAUR,CAAS,CAAC,EAElE,IAAMY,EAAU,IAAIN,EAAqBE,CAAoB,EACvDK,EAAgB,MAAMhD,GAAqB+C,EAAQ,OAAO,CAAC,EAC3Df,EAAO,OAAO,OAAOgB,EAAc,IAAIC,GAAS,OAAO,KAAKA,CAAmB,CAAC,CAAC,EAEjFzC,EAAU,CACd,eAAgBuC,EAAQ,YACxB,iBAAkB,OAAO,WAAWf,CAAI,EAAE,SAAS,CACrD,EACA,MAAO,CAAE,KAAAA,EAAM,QAAAxB,CAAQ,CACzB,CASA,KAAMW,GAAqBD,EAAoBP,EAAuC,CACpF,IAAIuC,EAAiB,CAAC,EACtB,GAAI,CACF,IAAMb,EAAcnB,EAAS,QAAQ,IAAI,cAAc,EACnDmB,GAAeA,EAAY,SAAS,kBAAkB,EACxDa,EAAY,MAAMhC,EAAS,KAAK,EAEhCgC,EAAY,CAAE,QAAS,MAAMhC,EAAS,KAAK,CAAE,CAEjD,MAAQ,CACNgC,EAAY,CAAE,QAAS,gCAAiC,CAC1D,CAGA,GAAIA,EAAU,OAASA,EAAU,MAAQA,EAAU,QAAS,CAE1D,IAAMC,EAAUD,EAAU,SAAWA,EAAU,OAAS,GAAGvC,CAAa,2BAGxE,MAAIO,EAAS,SAAW,IAChB,YAAU,eAAeiC,CAAO,EAGlC,YAAU,IACdA,EACAjC,EAAS,OACTgC,EAAU,KACVA,CACF,CACF,CAIA,MAAIhC,EAAS,SAAW,IAChB,YAAU,eAAe,6BAA6BP,CAAa,EAAE,EAGvE,YAAU,IACd,GAAGA,CAAa,2BAChBO,EAAS,OACT,OACAgC,CACF,CACF,CAYAlC,GAAkBD,EAAYJ,EAA8B,CAC1D,MAAII,EAAM,OAAS,aACX,YAAU,UAAU,GAAGJ,CAAa,2BAA2B,EAEnEI,aAAiB,WAAaA,EAAM,QAAQ,SAAS,OAAO,EACxD,YAAU,QAAQ,GAAGJ,CAAa,iCAAiCI,EAAM,OAAO,GAAIA,CAAK,EAE7FA,aAAiB,YACbA,EAEF,YAAU,SAAS,uCAAuCJ,CAAa,KAAKI,EAAM,SAAW,eAAe,EAAE,CACtH,CAMA,MAAa,iBAAmD,CAC9D,OAAO,MAAM,KAAKE,GAAiC,GAAG,KAAK,MAAM,GAAGzB,EAAe,GAAI,CAAE,OAAQ,KAAM,EAAG,kBAAkB,CAC9H,CAOA,MAAa,cAAc4D,EAAiC,CAC1D,OAAO,MAAM,KAAKnC,GAAqB,GAAG,KAAK,MAAM,GAAGzB,EAAe,IAAI4D,CAAE,GAAI,CAAE,OAAQ,KAAM,EAAG,gBAAgB,CACtH,CAOA,MAAa,iBAAiBA,EAA2B,CACvD,MAAM,KAAKnC,GAAmC,GAAG,KAAK,MAAM,GAAGzB,EAAe,IAAI4D,CAAE,GAAI,CAAE,OAAQ,QAAS,EAAG,mBAAmB,CACnI,CAQA,MAAa,SAASC,EAAcC,EAAgE,CAClG,GAAI,CACF,IAAMpC,EAAW,MAAM,KAAKT,GAAe,GAAG,KAAK,MAAM,GAAGf,EAAgB,IAAI,mBAAmB2D,CAAI,CAAC,GAAI,CAC1G,OAAQ,MACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAU,CAAE,WAAYC,CAAW,CAAC,CACjD,EAAG,WAAW,EAEd,OAAKpC,EAAS,IACZ,MAAM,KAAKC,GAAqBD,EAAU,WAAW,EAMhD,CACL,GAJY,MAAMA,EAAS,KAAK,EAKhC,SAAUA,EAAS,SAAW,GAChC,CACF,OAASH,EAAY,CACnB,KAAKC,GAAkBD,EAAO,WAAW,CAC3C,CACF,CAOA,MAAa,SAASsC,EAA8B,CAClD,OAAO,MAAM,KAAKpC,GAAgB,GAAG,KAAK,MAAM,GAAGvB,EAAgB,IAAI,mBAAmB2D,CAAI,CAAC,GAAI,CAAE,OAAQ,KAAM,EAAG,WAAW,CACnI,CAMA,MAAa,aAA0C,CACrD,OAAO,MAAM,KAAKpC,GAA4B,GAAG,KAAK,MAAM,GAAGvB,EAAgB,GAAI,CAAE,OAAQ,KAAM,EAAG,cAAc,CACtH,CAOA,MAAa,YAAY2D,EAA6B,CACpD,MAAM,KAAKpC,GAAe,GAAG,KAAK,MAAM,GAAGvB,EAAgB,IAAI,mBAAmB2D,CAAI,CAAC,GAAI,CAAE,OAAQ,QAAS,EAAG,cAAc,CACjI,CAOA,MAAa,WAAWA,EAA4C,CAClE,OAAO,MAAM,KAAKpC,GAA8B,GAAG,KAAK,MAAM,GAAGvB,EAAgB,IAAI,mBAAmB2D,CAAI,CAAC,aAAc,CAAE,OAAQ,MAAO,EAAG,aAAa,CAC9J,CAMA,MAAa,YAA+B,CAC1C,OAAO,MAAM,KAAKpC,GAAkB,GAAG,KAAK,MAAM,GAAGrB,EAAgB,GAAI,CAAE,OAAQ,KAAM,EAAG,aAAa,CAC3G,CAMA,MAAa,cAA4C,CACvD,OAAO,MAAM,KAAKqB,GAA6B,GAAG,KAAK,MAAM,OAAQ,CAAE,OAAQ,MAAO,EAAG,gBAAgB,CAC3G,CAOA,MAAa,SAASG,EAAuC,CAE3D,IAAMmC,EAAYnC,EAAM,KAAKoC,GAAKA,EAAE,OAAS,cAAgBA,EAAE,OAAS,aAAa,EACrF,GAAI,CAACD,EACH,MAAO,GAIT,IAAME,EAAiB,IAAM,KAC7B,GAAIF,EAAU,KAAOE,EACnB,MAAO,GAGT,IAAIC,EAEJ,GAAI,OAAO,OAAW,KAAe,OAAO,SAASH,EAAU,OAAO,EACpEG,EAAeH,EAAU,QAAQ,SAAS,OAAO,UACxC,OAAO,KAAS,KAAeA,EAAU,mBAAmB,KACrEG,EAAe,MAAMH,EAAU,QAAQ,KAAK,UACnC,OAAO,KAAS,KAAeA,EAAU,mBAAmB,KACrEG,EAAe,MAAMH,EAAU,QAAQ,KAAK,MAE5C,OAAO,GAMT,IAAMI,EAA+B,CACnC,MAHgBvC,EAAM,IAAIrB,GAAQA,EAAK,IAAI,EAI3C,MAAO2D,CACT,EAWA,OATiB,MAAM,KAAKzC,GAC1B,GAAG,KAAK,MAAM,GAAGpB,EAAkB,GACnC,CACE,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAU8D,CAAW,CAClC,EACA,WACF,GACgB,KAClB,CACF,EC1mBA,IAAAC,GAAiD,6BAEjDC,IAQA,eAAsBC,GAAWC,EAAsC,CACrE,IAAMC,EAAMC,EAAO,EAEnB,GAAID,IAAQ,UAEV,MAAO,CAAC,EACH,GAAIA,IAAQ,OAAQ,CAEzB,GAAM,CAAE,WAAYE,CAAe,EAAI,KAAM,uCAC7C,OAAOA,EAAeH,CAAU,CAClC,KAEE,OAAO,CAAC,CAEZ,CAMO,SAASI,GACdC,EAAiC,CAAC,EAClCC,EAA2C,CAAC,EACe,CAC3D,IAAMC,EAAc,CAClB,OAAQF,EAAY,QAAUC,EAAa,QAAU,eACrD,OAAQD,EAAY,SAAW,OAAYA,EAAY,OAASC,EAAa,OAC7E,YAAaD,EAAY,cAAgB,OAAYA,EAAY,YAAcC,EAAa,WAC9F,EAEME,EAAoE,CACxE,OAAQD,EAAY,MACtB,EAEA,OAAIA,EAAY,SAAW,SAAWC,EAAO,OAASD,EAAY,QAC9DA,EAAY,cAAgB,SAAWC,EAAO,YAAcD,EAAY,aAErEC,CACT,CAMO,SAASC,GACdC,EACAC,EACmB,CACnB,IAAMH,EAA4B,CAAE,GAAGE,CAAQ,EAG/C,OAAIF,EAAO,SAAW,QAAaG,EAAe,SAAW,SAC3DH,EAAO,OAASG,EAAe,QAE7BH,EAAO,SAAW,QAAaG,EAAe,SAAW,SAC3DH,EAAO,OAASG,EAAe,QAE7BH,EAAO,cAAgB,QAAaG,EAAe,cAAgB,SACrEH,EAAO,YAAcG,EAAe,aAElCH,EAAO,UAAY,QAAaG,EAAe,UAAY,SAC7DH,EAAO,QAAUG,EAAe,SAE9BH,EAAO,iBAAmB,QAAaG,EAAe,iBAAmB,SAC3EH,EAAO,eAAiBG,EAAe,gBAErCH,EAAO,aAAe,QAAaG,EAAe,aAAe,SACnEH,EAAO,WAAaG,EAAe,YAEjCH,EAAO,kBAAoB,QAAaG,EAAe,kBAAoB,SAC7EH,EAAO,gBAAkBG,EAAe,iBAGnCH,CACT,CCjFA,IAAAI,GAA2C,6BAC3CC,KAQA,eAAsBC,IAAuC,CAQ3D,IAAMC,EAAe,KAAK,UAPX,CACb,SAAY,CAAC,CACX,OAAU,QACV,YAAe,aACjB,CAAC,CACH,EAE4C,KAAM,CAAC,EAG/CC,EACA,OAAO,OAAW,IAEpBA,EAAU,OAAO,KAAKD,EAAc,OAAO,EAG3CC,EAAU,IAAI,KAAK,CAACD,CAAY,EAAG,CAAE,KAAM,kBAAmB,CAAC,EAGjE,GAAM,CAAE,IAAAE,CAAI,EAAI,MAAMC,EAAaF,CAAO,EAE1C,MAAO,CACL,KAAM,8BACN,QAAAA,EACA,KAAMD,EAAa,OACnB,IAAAE,CACF,CACF,CAWA,eAAsBE,GACpBC,EACAC,EACAC,EACuB,CAEvB,GAAIA,EAAQ,YAAc,IAASF,EAAM,KAAKG,GAAKA,EAAE,OAAS,6BAA0B,EACtF,OAAOH,EAGT,GAAI,CAGF,GAFc,MAAMC,EAAU,SAASD,CAAK,EAEjC,CACT,IAAMI,EAAY,MAAMV,GAAgB,EACxC,MAAO,CAAC,GAAGM,EAAOI,CAAS,CAC7B,CACF,MAAgB,CAEhB,CAEA,OAAOJ,CACT,CCrDO,SAASK,GACdC,EACAC,EACAC,EACAC,EACoB,CACpB,MAAO,CACL,OAAQ,MAAOC,EAAoBC,EAA6B,CAAC,IAAM,CAEjEH,GAAY,MAAMA,EAAW,EAGjC,IAAMI,EAAgBL,EAClBM,GAAmBF,EAASJ,CAAc,EAC1CI,EAGEG,EAAYR,EAAO,EAGzB,GAAI,CAACG,EACH,MAAM,IAAI,MAAM,wCAAwC,EAI1D,IAAIM,EAA4B,MAAMN,EAAaC,EAAOE,CAAa,EAGvE,OAAAG,EAAc,MAAMC,GAAsBD,EAAaD,EAAWF,CAAa,EAGxE,MAAME,EAAU,OAAOC,EAAaH,CAAa,CAC1D,EAEA,KAAM,UACAJ,GAAY,MAAMA,EAAW,EAC1BF,EAAO,EAAE,gBAAgB,GAGlC,OAAQ,MAAOW,GAAe,CACxBT,GAAY,MAAMA,EAAW,EACjC,MAAMF,EAAO,EAAE,iBAAiBW,CAAE,CAEpC,EAEA,IAAK,MAAOA,IACNT,GAAY,MAAMA,EAAW,EAC1BF,EAAO,EAAE,cAAcW,CAAE,EAEpC,CACF,CAMO,SAASC,GAAoBZ,EAAuBE,EAAiD,CAC1G,MAAO,CACL,IAAK,MAAOW,EAAmBC,KACzBZ,GAAY,MAAMA,EAAW,EAE1BF,EAAO,EAAE,SAASa,EAAWC,CAAU,GAGhD,IAAK,MAAOD,IACNX,GAAY,MAAMA,EAAW,EAC1BF,EAAO,EAAE,SAASa,CAAS,GAGpC,KAAM,UACAX,GAAY,MAAMA,EAAW,EAC1BF,EAAO,EAAE,YAAY,GAG9B,OAAQ,MAAOa,GAAsB,CAC/BX,GAAY,MAAMA,EAAW,EACjC,MAAMF,EAAO,EAAE,YAAYa,CAAS,CAEtC,EAEA,MAAO,MAAOA,IACRX,GAAY,MAAMA,EAAW,EAC1BF,EAAO,EAAE,WAAWa,CAAS,EAExC,CACF,CAMO,SAASE,GAAsBf,EAAuBE,EAAmD,CAC9G,MAAO,CACL,IAAK,UACCA,GAAY,MAAMA,EAAW,EAC1BF,EAAO,EAAE,WAAW,EAE/B,CACF,CAMO,SAASgB,GAAmBhB,EAAuBE,EAAgD,CACxG,MAAO,CACL,OAAQ,UACFA,GAAY,MAAMA,EAAW,EAC1BF,EAAO,EAAE,aAAa,EAEjC,CACF,CCtGO,IAAeiB,EAAf,KAAoB,CAWzB,YAAYC,EAA6B,CAAC,EAAG,CAR7C,KAAU,YAAoC,KAS5C,KAAK,cAAgBA,EAGrB,IAAMC,EAAS,KAAK,qBAAqBD,CAAO,EAChD,KAAK,KAAO,IAAIE,EAAQ,CAAE,GAAGF,EAAS,GAAGC,CAAO,CAAC,EAGjD,IAAME,EAAe,IAAM,KAAK,kBAAkB,EAC5CC,EAAS,IAAM,KAAK,KAG1B,KAAK,aAAeC,GAClBD,EACA,KAAK,cACLD,EACA,CAACG,EAAON,IAAY,KAAK,aAAaM,EAAON,CAAO,CACtD,EACA,KAAK,SAAWO,GAAoBH,EAAQD,CAAY,EACxD,KAAK,SAAWK,GAAsBJ,EAAQD,CAAY,EAC1D,KAAK,MAAQM,GAAmBL,EAAQD,CAAY,CACtD,CAUA,MAAgB,mBAAmC,CACjD,OAAK,KAAK,cACR,KAAK,YAAc,KAAK,eAAe,GAElC,KAAK,WACd,CAKA,MAAM,MAAyB,CAC7B,aAAM,KAAK,kBAAkB,EACtB,KAAK,KAAK,KAAK,CACxB,CAKA,MAAM,OAAOG,EAAoBN,EAAkD,CACjF,OAAO,KAAK,YAAY,OAAOM,EAAON,CAAO,CAC/C,CAKA,MAAM,QAAS,CACb,OAAO,KAAK,QAAQ,IAAI,CAC1B,CAKA,IAAI,aAAkC,CACpC,OAAO,KAAK,YACd,CAKA,IAAI,SAAyB,CAC3B,OAAO,KAAK,QACd,CAKA,IAAI,SAA2B,CAC7B,OAAO,KAAK,QACd,CAKA,IAAI,MAAqB,CACvB,OAAO,KAAK,KACd,CACF,EL9HA,IAAAU,GAA0B,6BAC1BC,IACAC,KAEAC,KMTA,IAAAC,EAAA,GAAAC,EAAAD,EAAA,aAAAE,EAAA,oDAAAC,GAAA,SAAAC,EAAA,qFAAAC,GAAA,iBAAAC,EAAA,0BAAAC,GAAA,wBAAAC,GAAA,6BAAAC,GAAA,uBAAAC,GAAA,eAAAC,EAAA,WAAAC,EAAA,eAAAC,GAAA,uBAAAC,GAAA,wBAAAC,EAAA,cAAAC,GAAA,kBAAAC,KCAA,IAAAC,EAAA,GAOAC,EAAAD,EAAc,8BDDdE,EAAAC,EAAcC,GEAd,IAAAC,GAA4B,6BFO5BC,KGDO,SAASC,GACdC,EACAC,EACAC,EACAC,EAAwB,GAChB,CACR,IAAMC,EAAOJ,IAAU,EAAIC,EAAWC,EACtC,OAAOC,EAAe,GAAGH,CAAK,IAAII,CAAI,GAAKA,CAC7C,CHLAC,KACAC,KACAC,IAGA,IAAAC,EAAyC,6BNNzCC,EAAAC,EAAcC,GA2FdC,KACAC,KAGAC,KACAC,IA5EO,IAAMC,EAAN,cAAmBA,CAAS,CACjC,YAAYC,EAA6B,CAAC,EAAG,CAG3C,GAFoBC,EAAO,IAEP,OAClB,MAAM,aAAU,SAAS,6DAA6D,EAGxF,MAAMD,CAAO,CACf,CAEU,qBAAqBA,EAAiC,CAC9D,OAAOE,GAAcF,EAAS,CAAC,CAAC,CAClC,CAEA,MAAgB,gBAAgC,CAC9C,GAAI,CAEF,IAAMG,EAAe,MAAMC,GAAW,KAAK,cAAc,UAAU,EAE7DC,EAAcH,GAAc,KAAK,cAAeC,CAAY,EAClE,KAAK,KAAO,IAAIG,EAAQ,CAAE,GAAG,KAAK,cAAe,GAAGD,CAAY,CAAC,EAEjE,IAAME,EAAiB,MAAM,KAAK,KAAK,UAAU,EACjDC,GAAUD,CAAc,CAC1B,OAASE,EAAO,CAEd,WAAK,YAAc,KACbA,CACR,CACF,CAEA,MAAgB,aAAaC,EAAoBV,EAAmD,CAElG,GAAI,CAAC,KAAKW,GAAkBD,CAAK,EAC/B,MAAM,aAAU,SAAS,2EAA2E,EAItG,GAAI,MAAM,QAAQA,CAAK,GAAKA,EAAM,SAAW,EAC3C,MAAM,aAAU,SAAS,qBAAqB,EAGhD,GAAM,CAAE,mBAAAE,CAAmB,EAAI,KAAM,uCACrC,OAAOA,EAAmBF,EAAOV,EAAS,KAAK,IAAI,CACrD,CAMAW,GAAkBD,EAA6B,CAE7C,OAAI,OAAOA,GAAU,SACZ,GAGL,MAAM,QAAQA,CAAK,EAGdA,EAAM,MAAMG,GAAQ,OAAOA,GAAS,QAAQ,EAG9C,EACT,CACF,EAGOC,GAAQf,EDhGf,IAAAgB,EAAoE,6BACpEC,EAAmD,cACnDC,EAAsB,qBWLtB,IAAAC,GAAsB,0BACtBC,EAAqE,uBAK/DC,EAAa,CAACC,EAAmCC,EAAcC,IAC5DA,EAAUD,EAAOD,EAAQC,CAAI,EAMzBE,EAAU,CAACC,EAAaC,EAAkBH,IAAsB,CAEzE,QAAQ,IADNG,EACU,KAAK,UAAU,CAAE,QAASD,CAAI,EAAG,KAAM,CAAC,EAAI;AAAA,EAE5C,GAAGL,EAAW,QAAOK,EAAI,YAAY,EAAE,QAAQ,MAAO,EAAE,EAAGF,CAAO,CAAC;AAAA,CAFnB,CAIhE,EAEaI,EAAQ,CAACF,EAAaC,EAAkBH,IAAsB,CACzE,GAAIG,EACF,QAAQ,MAAM,KAAK,UAAU,CAAE,MAAOD,CAAI,EAAG,KAAM,CAAC,EAAI;AAAA,CAAI,MACvD,CACL,IAAMG,EAAcR,EAAYE,MAAS,cAAQ,OAAIA,CAAI,CAAC,EAAG,GAAGF,EAAW,SAAQ,IAAKG,CAAO,CAAC,QAAQH,EAAW,SAAQ,IAAKG,CAAO,CAAC,GAAIA,CAAO,EAC7IM,EAAWT,EAAW,MAAKK,EAAI,YAAY,EAAE,QAAQ,MAAO,EAAE,EAAGF,CAAO,EAC9E,QAAQ,MAAM,GAAGK,CAAW,IAAIC,CAAQ;AAAA,CAAI,CAC9C,CACF,EAEaC,EAAO,CAACL,EAAaC,EAAkBH,IAAsB,CACxE,GAAIG,EACF,QAAQ,IAAI,KAAK,UAAU,CAAE,QAASD,CAAI,EAAG,KAAM,CAAC,EAAI;AAAA,CAAI,MACvD,CACL,IAAMM,EAAaX,EAAYE,MAAS,cAAQ,UAAOA,CAAI,CAAC,EAAG,GAAGF,EAAW,SAAQ,IAAKG,CAAO,CAAC,UAAUH,EAAW,SAAQ,IAAKG,CAAO,CAAC,GAAIA,CAAO,EACjJS,EAAUZ,EAAW,SAAQK,EAAI,YAAY,EAAE,QAAQ,MAAO,EAAE,EAAGF,CAAO,EAChF,QAAQ,IAAI,GAAGQ,CAAU,IAAIC,CAAO;AAAA,CAAI,CAC1C,CACF,EAEaC,GAAO,CAACR,EAAaC,EAAkBH,IAAsB,CACxE,GAAIG,EACF,QAAQ,IAAI,KAAK,UAAU,CAAE,KAAMD,CAAI,EAAG,KAAM,CAAC,EAAI;AAAA,CAAI,MACpD,CACL,IAAMS,EAAad,EAAYE,MAAS,cAAQ,QAAKA,CAAI,CAAC,EAAG,GAAGF,EAAW,SAAQ,IAAKG,CAAO,CAAC,OAAOH,EAAW,SAAQ,IAAKG,CAAO,CAAC,GAAIA,CAAO,EAC5IY,EAAUf,EAAW,OAAMK,EAAI,YAAY,EAAE,QAAQ,MAAO,EAAE,EAAGF,CAAO,EAC9E,QAAQ,IAAI,GAAGW,CAAU,IAAIC,CAAO;AAAA,CAAI,CAC1C,CACF,EAMaC,GAAkB,CAACC,EAAoBC,EAA+B,UAAWf,IAA8B,CAC1H,GAA+Bc,GAAc,MAAQA,IAAc,EACjE,MAAO,IAGT,IAAME,EAAY,IAAI,KAAKF,EAAY,GAAI,EAAE,YAAY,EAAE,QAAQ,YAAa,GAAG,EAGnF,OAAIC,IAAY,QACPC,EAAU,QAAQ,IAAKnB,EAAW,SAAQ,IAAKG,CAAO,CAAC,EAAE,QAAQ,KAAMH,EAAW,SAAQ,IAAKG,CAAO,CAAC,EAGzGgB,CACT,EAKMC,GAAc,CAACC,EAAaC,EAAYJ,EAA+B,UAAWf,IAA8B,CACpH,GAAI,OAAOmB,GAAU,WAAaD,IAAQ,WAAaA,IAAQ,WAAaA,IAAQ,aAClF,OAAOL,GAAgBM,EAAOJ,EAASf,CAAO,EAEhD,GAAIkB,IAAQ,QAAU,OAAOC,GAAU,SAAU,CAC/C,IAAMC,EAAKD,EAAS,QACpB,OAAOC,GAAM,EAAI,GAAGA,EAAG,QAAQ,CAAC,CAAC,KAAO,IAAID,EAAQ,MAAM,QAAQ,CAAC,CAAC,IACtE,CACA,GAAID,IAAQ,SAAU,CAEpB,GAAI,OAAOC,GAAU,UACnB,OAAOA,EAAQ,MAAQ,KAEzB,GAAI,OAAOA,GAAU,SACnB,OAAOA,IAAU,EAAI,MAAQ,IAEjC,CACA,OAAO,OAAOA,CAAK,CACrB,EAKaE,GAAc,CAACC,EAAaC,EAAoBvB,IAA8B,CACzF,GAAI,CAACsB,GAAQA,EAAK,SAAW,EAAG,MAAO,GAGvC,IAAME,EAAYF,EAAK,CAAC,GAAK,CAAC,EACxBG,EAAcF,GAAW,OAAO,KAAKC,CAAS,EAAE,OAAON,GAC3DM,EAAUN,CAAG,IAAM,QAAaA,IAAQ,YAAcA,IAAQ,UAChE,EAGMQ,EAAkBJ,EAAK,IAAIK,GAAQ,CACvC,IAAMC,EAAmB,CAAC,EAC1B,OAAAH,EAAY,QAAQI,GAAO,CACrBA,KAAOF,GAAQA,EAAKE,CAAG,IAAM,SAC/BD,EAAYC,CAAG,EAAIZ,GAAYY,EAAKF,EAAKE,CAAG,EAAG,QAAS7B,CAAO,EAEnE,CAAC,EACM4B,CACT,CAAC,EAYD,SAVe,GAAAE,SAAUJ,EAAiB,CACxC,eAAgB,MAChB,QAASD,EACT,OAAQA,EAAY,OAAO,CAACM,EAAQF,KAClCE,EAAOF,CAAG,EAAI,CAAE,iBAAmBG,GAAoBnC,EAAW,MAAKmC,EAAShC,CAAO,CAAE,EAClF+B,GACN,CAAC,CAAQ,CACd,CAAC,EAIE,MAAM;AAAA,CAAI,EACV,IAAKE,GAAiBA,EACpB,QAAQ,MAAO,EAAE,EACjB,QAAQ,OAAQ,EAAE,CACrB,EACC,KAAK;AAAA,CAAI,EAAI;AAAA,CAClB,EAKaC,GAAgB,CAACC,EAAUnC,IAA8B,CACpE,IAAMoC,EAAU,OAAO,QAAQD,CAAG,EAAE,OAAO,CAAC,CAACjB,EAAKC,CAAK,IAEjDD,IAAQ,YAAcA,IAAQ,WAAmB,GAC9CC,IAAU,MAClB,EAED,GAAIiB,EAAQ,SAAW,EAAG,MAAO,GAGjC,IAAMd,EAAOc,EAAQ,IAAI,CAAC,CAAClB,EAAKC,CAAK,KAAO,CAC1C,SAAUD,EAAM,IAChB,MAAOD,GAAYC,EAAKC,EAAO,UAAWnB,CAAO,CACnD,EAAE,EAaF,SAXe,GAAA8B,SAAUR,EAAM,CAC7B,eAAgB,KAChB,YAAa,GACb,OAAQ,CACN,SAAU,CACR,cAAgBH,GAAkBtB,EAAW,MAAKsB,EAAOnB,CAAO,CAClE,CACF,CACF,CAAC,EAIE,MAAM;AAAA,CAAI,EACV,IAAKiC,GAAiBA,EAAK,QAAQ,MAAO,EAAE,CAAC,EAC7C,KAAK;AAAA,CAAI,EAAI;AAAA,CAClB,EXjKA,IAAAI,GAA0B,uBAE1BC,EAAoB,mBACpBC,GAAoB,mBAGhBC,GAAmB,CAAE,QAAS,OAAQ,EAE1C,GAAI,CAGF,IAAMC,EAAuB,UAAQ,UAAW,iBAAiB,EACjED,GAAc,KAAK,SAAM,gBAAaC,EAAiB,OAAO,CAAC,CACjE,MAAgB,CAEd,IAAMC,EAAuB,UAAQ,UAAW,oBAAoB,EACpE,GAAI,CACFF,GAAc,KAAK,SAAM,gBAAaE,EAAiB,OAAO,CAAC,CACjE,MAAwB,CAGxB,CACF,CAIA,IAAMC,EAAU,IAAI,WAGpBA,EACG,aAAcC,GAAQ,EAEjBA,EAAI,OAAS,kBAAoBA,EAAI,OAAS,qBAAuBA,EAAI,WAAa,IACxF,QAAQ,KAAKA,EAAI,UAAY,CAAC,EAGhC,IAAMC,EAAgBF,EAAQ,KAAK,EAG/BG,EAAUF,EAAI,SAAW,wBAG7BE,EAAUA,EACP,QAAQ,WAAY,EAAE,EACtB,QAAQ,OAAQ,EAAE,EAClB,QAAQ,MAAO,EAAE,EACjB,YAAY,EAGfC,EAAMD,EAASD,EAAc,KAAMA,EAAc,OAAO,EAGnDA,EAAc,MACjBG,EAAYH,EAAc,OAAO,EAGnC,QAAQ,KAAKD,EAAI,UAAY,CAAC,CAChC,CAAC,EACA,gBAAgB,CAEf,SAAWK,GAAQ,CAEZA,EAAI,WAAW,QAAQ,GAC1B,QAAQ,OAAO,MAAMA,CAAG,CAE5B,EACA,SAAWA,GAAQ,QAAQ,OAAO,MAAMA,CAAG,CAC7C,CAAC,EAQH,SAASD,EAAYE,EAAmB,CACtC,IAAMC,EAAaC,GAAiBF,EAAUE,KAAO,SAAKA,CAAI,EACxDC,EAAYD,GAAiBF,EAAUE,KAAO,QAAIA,CAAI,EAEtDE,EAAS,GAAGH,EAAU,OAAO,CAAC;AAAA;AAAA;AAAA,EAGpCA,EAAU,UAAU,CAAC;AAAA,cAChBA,EAAU,aAAa,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAMxBA,EAAU,SAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAOpBA,EAAU,SAAS,CAAC;AAAA;AAAA;AAAA,qBAGlBA,EAAU,YAAY,CAAC;AAAA;AAAA;AAAA;AAAA,EAI9BA,EAAU,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUlBE,EAAS,uEAAuE,CAAC;AAAA,EAGjF,QAAQ,IAAIC,CAAM,CACpB,CAMA,SAASC,EAAeC,EAAmB,CAEzC,IAAMC,EAAUD,EAAQ,KAAK,EAGzBC,EAAQ,QAAU,KACpBA,EAAQ,QAAU,IAIpB,GAAI,CACEA,EAAQ,QAAU,OAAOA,EAAQ,QAAW,aAC9C,kBAAeA,EAAQ,MAAM,EAG3BA,EAAQ,aAAe,OAAOA,EAAQ,aAAgB,aACxD,uBAAoBA,EAAQ,WAAW,EAGrCA,EAAQ,QAAU,OAAOA,EAAQ,QAAW,aAC9C,kBAAeA,EAAQ,MAAM,CAEjC,OAASC,EAAiB,CACxB,MAAIA,aAA2B,cAC7BX,EAAMW,EAAgB,QAASD,EAAQ,KAAMA,EAAQ,OAAO,EAC5D,QAAQ,KAAK,CAAC,GAEVC,CACR,CAEA,OAAOD,CACT,CAKA,SAASE,GAAYf,EAAUgB,EAA8EH,EAAe,CAE1H,IAAMI,EAAOlB,EAAQ,KAAK,EAE1B,GAAI,EAAEC,aAAe,aAAY,CAC/B,IAAME,EAAUF,EAAI,SAAWA,EAE3BiB,EAAK,MACP,QAAQ,MAAM,KAAK,UAAU,CAC3B,MAAOf,EACP,QAAS,CAAE,cAAeA,CAAQ,CACpC,EAAG,KAAM,CAAC,CAAC,EACX,QAAQ,MAAM,IAEdC,EAAMD,EAASe,EAAK,KAAMA,EAAK,OAAO,EAEtCb,EAAYa,EAAK,OAAO,GAE1B,QAAQ,KAAK,CAAC,CAChB,CAEA,IAAIf,EAAUF,EAAI,QAGlB,GAAIA,EAAI,SAAS,MAAM,QAAU,YAC/B,GAAIgB,GAAS,YAAc,SAAU,CACnC,IAAME,EAAeF,EAAQ,cAAgB,WAE7Cd,EAAU,GADSc,EAAQ,YAAc,EAClB,IAAIE,EAAa,YAAY,CAAC,YACvD,KAAO,CAEL,IAAMC,EAAkBnB,EAAI,QAAQ,KAAK,SAAW,qBAE9CoB,EAAQD,EAAgB,MAAM,6BAA6B,EACjE,GAAIC,EAAO,CACT,GAAM,CAAC,CAAEF,EAAcG,CAAU,EAAID,EACrClB,EAAU,GAAGmB,CAAU,IAAIH,EAAa,YAAY,CAAC,YACvD,MACEhB,EAAUiB,CAEd,MAGOnB,EAAI,SAAS,MAAM,QAAU,uBACpCE,EAAUF,EAAI,QAAQ,KAAK,SAAW,gCAG/BA,EAAI,YAAY,EACvBE,EAAU,wBAEHF,EAAI,eAAe,EAC1BE,EAAU,gBAIH,CAACF,EAAI,YAAY,GAAK,CAACA,EAAI,kBAAkB,GAAK,CAACA,EAAI,cAAc,IAC5EE,EAAU,gBAGRe,EAAK,MACP,QAAQ,MAAM,KAAK,UAAU,CAC3B,MAAOf,EACP,GAAIF,EAAI,QAAU,CAAE,QAASA,EAAI,OAAQ,EAAI,CAAC,CAChD,EAAG,KAAM,CAAC,CAAC,EACX,QAAQ,MAAM,IAEdG,EAAMD,EAASe,EAAK,KAAMA,EAAK,OAAO,EAElCjB,EAAI,kBAAkB,GAAKE,EAAQ,SAAS,iBAAiB,GAC/DE,EAAYa,EAAK,OAAO,GAI5B,QAAQ,KAAK,CAAC,CAChB,CAMA,SAASK,EACPC,EACAP,EACA,CACA,OAAO,kBAA6BQ,EAAS,CAC3C,GAAI,CAEF,IAAMvB,EAAgBU,EAAe,IAAI,EAEnCc,EAASC,GAAa,EACtBC,EAAS,MAAMJ,EAAQE,EAAQ,GAAGD,CAAI,EAGtCI,EAAgBZ,EAAU,CAC9B,UAAWA,EAAQ,UACnB,aAAcA,EAAQ,aACtB,WAAYA,EAAQ,cAAgBA,EAAQ,cAAc,GAAGQ,CAAI,EAAI,MACvE,EAAI,OAEJd,GAAOiB,EAAQC,EAAe3B,CAAa,CAC7C,OAASE,EAAY,CACnB,IAAM0B,EAAeb,EAAU,CAC7B,UAAWA,EAAQ,UACnB,aAAcA,EAAQ,aACtB,WAAYA,EAAQ,cAAgBA,EAAQ,cAAc,GAAGQ,CAAI,EAAI,MACvE,EAAI,OAGEvB,EAAgBU,EAAe,IAAI,EAEzCI,GAAYZ,EAAO0B,EAAc5B,CAAa,CAChD,CACF,CACF,CAKA,SAASyB,IAAqB,CAC5B,IAAMb,EAAUd,EAAQ,KAAK,EACvB+B,EAAmB,CAAC,EAG1B,OAAIjB,EAAQ,SAAW,SACrBiB,EAAY,WAAajB,EAAQ,QAE/BA,EAAQ,SAAW,SACrBiB,EAAY,OAASjB,EAAQ,QAE3BA,EAAQ,SAAW,SACrBiB,EAAY,OAASjB,EAAQ,QAE3BA,EAAQ,cAAgB,SAC1BiB,EAAY,YAAcjB,EAAQ,aAI7B,IAAIkB,EAAKD,CAAW,CAC7B,CAKA,IAAME,GAAa,CACjB,YAAa,CAACL,EAAaX,EAAkCiB,EAAkB3B,IAAsB,CACnG,GAAI,CAACqB,EAAO,aAAeA,EAAO,YAAY,SAAW,EAAG,CACtDM,EACF,QAAQ,IAAI,KAAK,UAAU,CAAE,YAAa,CAAC,CAAE,EAAG,KAAM,CAAC,CAAC,GAExD,QAAQ,IAAI,sBAAsB,EAClC,QAAQ,IAAI,GAEd,MACF,CAGA,IAAMC,EAAc,CAAC,aAAc,MAAO,SAAS,EACnD,QAAQ,IAAIC,GAAYR,EAAO,YAAaO,EAAa5B,CAAO,CAAC,CACnE,EACA,QAAS,CAACqB,EAAaX,EAAkCiB,EAAkB3B,IAAsB,CAC/F,GAAI,CAACqB,EAAO,SAAWA,EAAO,QAAQ,SAAW,EAAG,CAC9CM,EACF,QAAQ,IAAI,KAAK,UAAU,CAAE,QAAS,CAAC,CAAE,EAAG,KAAM,CAAC,CAAC,GAEpD,QAAQ,IAAI,kBAAkB,EAC9B,QAAQ,IAAI,GAEd,MACF,CAGA,IAAMC,EAAc,CAAC,QAAS,aAAc,MAAO,SAAS,EAC5D,QAAQ,IAAIC,GAAYR,EAAO,QAASO,EAAa5B,CAAO,CAAC,CAC/D,EACA,MAAO,CAACqB,EAAaX,EAAkCiB,EAAkB3B,IAAsB,CAE7F,GAAIqB,EAAO,MAAO,CAChB,IAAMS,EAAYT,EAAO,SAAW,UAAY,UAChDU,EAAQ,GAAGV,EAAO,KAAK,UAAUS,CAAS,GAAIH,EAAQ3B,CAAO,CAC/D,CAGI,CAAC2B,GAAUN,EAAO,OAASA,EAAO,MAAM,SAAS,GAAG,GAAK,CAACA,EAAO,WACnEW,EAAK,yDAAyDX,EAAO,KAAK,2BAA4BM,EAAQ3B,CAAO,EAGvH,QAAQ,IAAIiC,GAAcZ,EAAQrB,CAAO,CAAC,CAC5C,EACA,WAAY,CAACqB,EAAaX,EAAkCiB,EAAkB3B,IAAsB,CAE9FqB,EAAO,QAAUX,GAAS,YAAc,UAC1CqB,EAAQ,GAAGV,EAAO,UAAU,6BAAyBM,EAAQ3B,CAAO,EAEtE,QAAQ,IAAIiC,GAAcZ,EAAQrB,CAAO,CAAC,CAC5C,EACA,MAAO,CAACqB,EAAaX,EAAkCiB,EAAkB3B,IAAsB,CAC7F,QAAQ,IAAIiC,GAAcZ,EAAQrB,CAAO,CAAC,CAC5C,EACA,QAAS,CAACqB,EAAaX,EAAkCiB,EAAkB3B,IAAsB,CAE3FqB,EAAO,SACTU,EAAQV,EAAO,QAASM,EAAQ3B,CAAO,CAE3C,CACF,EAKA,eAAekC,GAAcf,EAAcgB,EAAcC,EAAiBC,EAAoC,CAE5G,GAAI,IAAC,cAAWF,CAAI,EAClB,MAAM,YAAU,KAAK,GAAGA,CAAI,uBAAwBA,CAAI,EAI1D,IAAMG,KAAQ,YAASH,CAAI,EAC3B,GAAI,CAACG,EAAM,YAAY,GAAK,CAACA,EAAM,OAAO,EACxC,MAAM,YAAU,KAAK,GAAGH,CAAI,oCAAqCA,CAAI,EAGvE,IAAMI,EAAqB,CAAC,EAGxBH,GAAY,eAAiB,SAC/BG,EAAc,WAAa,CAACH,EAAW,cAIrCA,GAAY,cAAgB,SAC9BG,EAAc,UAAY,CAACH,EAAW,aAIxC,IAAMI,EAAkB,IAAI,gBAC5BD,EAAc,OAASC,EAAgB,OAGvC,IAAIC,EAAe,KAGb9C,EAAgB0C,EAAiBhC,EAAegC,CAAc,EAAI,CAAC,EACzE,GAAI,QAAQ,OAAO,OAAS,CAAC1C,EAAc,MAAQ,CAACA,EAAc,QAAS,CACzE,GAAM,CAAE,QAAS+C,CAAa,EAAI,KAAM,QAAO,eAAe,EAC9DD,EAAUC,EAAa,CAAE,KAAM,iBAAa,CAAC,EAAE,MAAM,CACvD,CAGA,IAAMC,EAAgB,IAAM,CAC1BH,EAAgB,MAAM,EAClBC,GAASA,EAAQ,KAAK,EAC1B,QAAQ,KAAK,GAAG,CAClB,EACA,QAAQ,GAAG,SAAUE,CAAa,EAElC,GAAI,CACF,IAAMtB,EAAS,MAAMF,EAAO,YAAY,OAAOgB,EAAMI,CAAa,EAGlE,eAAQ,eAAe,SAAUI,CAAa,EAC1CF,GAASA,EAAQ,KAAK,EAEnBpB,CACT,OAASxB,EAAO,CAEd,cAAQ,eAAe,SAAU8C,CAAa,EAC1CF,GAASA,EAAQ,KAAK,EACpB5C,CACR,CACF,CAKA,SAASO,GAAOiB,EAAaX,EAA8EH,EAAe,CACxH,IAAMI,EAAOJ,GAAWd,EAAQ,KAAK,EAGrC,GAAI4B,IAAW,OAAW,CACpBX,GAAS,YAAc,UAAYA,EAAQ,cAAgBA,EAAQ,WACrEqB,EAAQ,GAAGrB,EAAQ,UAAU,IAAIA,EAAQ,aAAa,YAAY,CAAC,WAAYC,EAAK,KAAMA,EAAK,OAAO,EAEtGoB,EAAQ,uBAAwBpB,EAAK,KAAMA,EAAK,OAAO,EAEzD,MACF,CAGA,GAAIU,IAAW,IAASA,GAAU,OAAOA,GAAW,UAAYA,EAAO,eAAe,SAAS,EAAI,CAC/EA,IAAW,IAAQA,EAAO,QAE1CU,EAAQ,gBAAiBpB,EAAK,KAAMA,EAAK,OAAO,EAEhDd,EAAM,kBAAmBc,EAAK,KAAMA,EAAK,OAAO,EAElD,MACF,CAGA,GAAIA,EAAK,KAAM,CACb,QAAQ,IAAI,KAAK,UAAUU,EAAQ,KAAM,CAAC,CAAC,EAC3C,QAAQ,IAAI,EACZ,MACF,CAGA,OAAW,CAACuB,EAAKC,CAAS,IAAK,OAAO,QAAQnB,EAAU,EACtD,GAAIL,EAAOuB,CAAG,EAAG,CACfC,EAAUxB,EAAQX,EAASC,EAAK,KAAMA,EAAK,OAAO,EAClD,MACF,CAIFoB,EAAQ,UAAWpB,EAAK,KAAMA,EAAK,OAAO,CAC5C,CAIAlB,EACG,KAAK,MAAM,EACX,YAAY,+CAAwC,EACpD,QAAQH,GAAY,QAAS,YAAa,0BAA0B,EACpE,OAAO,kBAAmB,uCAAuC,EACjE,OAAO,yBAA0B,yCAAyC,EAC1E,OAAO,kBAAmB,yBAAyB,EACnD,OAAO,kBAAmB,2BAA2B,EACrD,OAAO,SAAU,+BAA+B,EAChD,OAAO,aAAc,wBAAwB,EAC7C,OAAO,SAAU,0BAA0B,EAC3C,WAAW,EAAK,EAGnBG,EAAQ,KAAK,YAAa,CAACqD,EAAaC,IAAkB,CACxD,IAAMxC,EAAUuC,EAAY,KAAK,EACjC,GAAIvC,EAAQ,KAAM,CAChB,IAAMP,EAAUO,EAAQ,QAAU,IAASA,EAAQ,QACnDT,EAAYE,CAAO,EACnB,QAAQ,KAAK,CAAC,CAChB,CACF,CAAC,EAGDP,EAAQ,KAAK,YAAa,CAACqD,EAAaC,IAAkB,CACxD,IAAMxC,EAAUuC,EAAY,KAAK,EAEjC,GAAI,CACEvC,EAAQ,QAAU,OAAOA,EAAQ,QAAW,aAC9C,kBAAeA,EAAQ,MAAM,EAG3BA,EAAQ,aAAe,OAAOA,EAAQ,aAAgB,aACxD,uBAAoBA,EAAQ,WAAW,EAGrCA,EAAQ,QAAU,OAAOA,EAAQ,QAAW,aAC9C,kBAAeA,EAAQ,MAAM,CAEjC,OAASC,EAAiB,CACxB,GAAIA,aAA2B,YAAW,CACxC,IAAMR,EAAUO,EAAQ,QAAU,IAASA,EAAQ,QACnDV,EAAMW,EAAgB,QAASD,EAAQ,KAAMP,CAAO,EACpD,QAAQ,KAAK,CAAC,CAChB,CACA,MAAMQ,CACR,CACF,CAAC,EAGDf,EACG,QAAQ,MAAM,EACd,YAAY,wBAAwB,EACpC,OAAOuB,EAAmBG,GAAWA,EAAO,KAAK,CAAC,CAAC,EAGtD1B,EACG,QAAQ,QAAQ,EAChB,YAAY,iCAAiC,EAC7C,OAAOuB,EACLG,GAAWA,EAAO,OAAO,EAC1B,CAAE,UAAW,MAAO,aAAc,SAAU,CAC9C,CAAC,EAGH,IAAM6B,GAAiBvD,EACpB,QAAQ,aAAa,EACrB,YAAY,oBAAoB,EAChC,OAAO,IAAIyB,IAAS,CACnB,IAAMvB,EAAgBU,EAAeZ,CAAO,EAGtCwD,EAAa/B,EAAKA,EAAK,OAAS,CAAC,EAGvC,GAAI+B,GAAcA,EAAW,MAAQA,EAAW,KAAK,OAAS,EAAG,CAC/D,IAAMC,EAAaD,EAAW,KAAK,KAAME,GAAgB,CAAC,CAAC,OAAQ,SAAU,MAAO,QAAQ,EAAE,SAASA,CAAG,CAAC,EACvGD,GACFrD,EAAM,oBAAoBqD,CAAU,IAAKvD,EAAc,KAAMA,EAAc,OAAO,CAEtF,CAEAG,EAAYH,EAAc,OAAO,EACjC,QAAQ,KAAK,CAAC,CAChB,CAAC,EAEHqD,GACG,QAAQ,MAAM,EACd,YAAY,sBAAsB,EAClC,OAAOhC,EAAmBG,GAAWA,EAAO,YAAY,KAAK,CAAC,CAAC,EAElE6B,GACG,QAAQ,eAAe,EACvB,YAAY,0CAA0C,EACtD,OAAO,mBAAoB,oDAAoD,EAC/E,OAAO,kBAAmB,mDAAmD,EAC7E,OAAOhC,EACN,SAAoBG,EAAcgB,EAAcC,EAAiB,CAC/D,OAAOF,GAAcf,EAAQgB,EAAMC,EAAY,IAAI,CACrD,EACA,CAAE,UAAW,QAAS,CACxB,CAAC,EAEHY,GACG,QAAQ,kBAAkB,EAC1B,YAAY,6BAA6B,EACzC,OAAOhC,EACN,CAACG,EAAQiC,IAAuBjC,EAAO,YAAY,IAAIiC,CAAU,EACjE,CAAE,UAAW,MAAO,aAAc,aAAc,cAAgBA,GAAuBA,CAAW,CACpG,CAAC,EAEHJ,GACG,QAAQ,qBAAqB,EAC7B,YAAY,+BAA+B,EAC3C,OAAOhC,EACN,CAACG,EAAQiC,IAAuBjC,EAAO,YAAY,OAAOiC,CAAU,EACpE,CAAE,UAAW,SAAU,aAAc,aAAc,cAAgBA,GAAuBA,CAAW,CACvG,CAAC,EAGH,IAAMC,GAAa5D,EAChB,QAAQ,SAAS,EACjB,YAAY,gBAAgB,EAC5B,OAAO,IAAIyB,IAAS,CACnB,IAAMvB,EAAgBU,EAAeZ,CAAO,EAGtCwD,EAAa/B,EAAKA,EAAK,OAAS,CAAC,EAGvC,GAAI+B,GAAcA,EAAW,MAAQA,EAAW,KAAK,OAAS,EAAG,CAC/D,IAAMC,EAAaD,EAAW,KAAK,KAAME,GAAgB,CAAC,CAAC,OAAQ,MAAO,MAAO,QAAQ,EAAE,SAASA,CAAG,CAAC,EACpGD,GACFrD,EAAM,oBAAoBqD,CAAU,IAAKvD,EAAc,KAAMA,EAAc,OAAO,CAEtF,CAEAG,EAAYH,EAAc,OAAO,EACjC,QAAQ,KAAK,CAAC,CAChB,CAAC,EAEH0D,GACG,QAAQ,MAAM,EACd,YAAY,kBAAkB,EAC9B,OAAOrC,EAAmBG,GAAWA,EAAO,QAAQ,KAAK,CAAC,CAAC,EAE9DkC,GACG,QAAQ,YAAY,EACpB,YAAY,wBAAwB,EACpC,OAAOrC,EACN,CAACG,EAAQmC,IAAiBnC,EAAO,QAAQ,IAAImC,CAAI,EACjD,CAAE,UAAW,MAAO,aAAc,QAAS,cAAgBA,GAAiBA,CAAK,CACnF,CAAC,EAEHD,GACG,QAAQ,cAAc,EACtB,YAAY,+CAA+C,EAC3D,OAAOrC,EACN,CAACG,EAAQmC,IAAiBnC,EAAO,QAAQ,MAAMmC,CAAI,EACnD,CAAE,UAAW,QAAS,aAAc,QAAS,cAAgBA,GAAiBA,CAAK,CACrF,CAAC,EAEHD,GACG,QAAQ,yBAAyB,EACjC,YAAY,+CAA+C,EAC3D,OAAOrC,EACN,CAACG,EAAcmC,EAAcF,IAAuBjC,EAAO,QAAQ,IAAImC,EAAMF,CAAU,EACvF,CAAE,UAAW,MAAO,aAAc,QAAS,cAAgBE,GAAiBA,CAAK,CACnF,CAAC,EAEHD,GACG,QAAQ,eAAe,EACvB,YAAY,0BAA0B,EACtC,OAAOrC,EACN,CAACG,EAAQmC,IAAiBnC,EAAO,QAAQ,OAAOmC,CAAI,EACpD,CAAE,UAAW,SAAU,aAAc,QAAS,cAAgBA,GAAiBA,CAAK,CACtF,CAAC,EAGH,IAAMC,GAAa9D,EAChB,QAAQ,SAAS,EACjB,YAAY,gBAAgB,EAC5B,OAAO,IAAIyB,IAAS,CACnB,IAAMvB,EAAgBU,EAAeZ,CAAO,EAGtCwD,EAAa/B,EAAKA,EAAK,OAAS,CAAC,EAGvC,GAAI+B,GAAcA,EAAW,MAAQA,EAAW,KAAK,OAAS,EAAG,CAC/D,IAAMC,EAAaD,EAAW,KAAK,KAAME,GAAgB,CAAC,CAAC,KAAK,EAAE,SAASA,CAAG,CAAC,EAC3ED,GACFrD,EAAM,oBAAoBqD,CAAU,IAAKvD,EAAc,KAAMA,EAAc,OAAO,CAEtF,CAEAG,EAAYH,EAAc,OAAO,EACjC,QAAQ,KAAK,CAAC,CAChB,CAAC,EAEH4D,GACG,QAAQ,KAAK,EACb,YAAY,0BAA0B,EACtC,OAAOvC,EACLG,GAAWA,EAAO,OAAO,EAC1B,CAAE,UAAW,MAAO,aAAc,SAAU,CAC9C,CAAC,EAGH,IAAMqC,GAAgB/D,EACnB,QAAQ,YAAY,EACpB,YAAY,wBAAwB,EACpC,OAAO,IAAIyB,IAAS,CACnB,IAAMvB,EAAgBU,EAAeZ,CAAO,EAGtCwD,EAAa/B,EAAKA,EAAK,OAAS,CAAC,EAGvC,GAAI+B,GAAcA,EAAW,MAAQA,EAAW,KAAK,OAAS,EAAG,CAC/D,IAAMC,EAAaD,EAAW,KAAK,KAAME,GAAgB,CAAC,CAAC,UAAW,WAAW,EAAE,SAASA,CAAG,CAAC,EAC5FD,GACFrD,EAAM,oBAAoBqD,CAAU,IAAKvD,EAAc,KAAMA,EAAc,OAAO,CAEtF,CAEAG,EAAYH,EAAc,OAAO,EACjC,QAAQ,KAAK,CAAC,CAChB,CAAC,EAEH6D,GACG,QAAQ,SAAS,EACjB,YAAY,iCAAiC,EAC7C,OAAO,SAAY,CAClB,IAAMC,EAAQ,QAAQ,IAAI,OAAS,GAC7BC,EAAa,WAAQ,EACvBC,EACAC,EACAC,EAAqB,GAGnBC,EAAsB,UAAQ,UAAW,uBAAuB,EAChEC,EAAqB,UAAQ,UAAW,sBAAsB,EAC9DC,EAAsB,UAAQ,UAAW,uBAAuB,EAEtE,GAAI,CACF,GAAIP,EAAM,SAAS,MAAM,EACvBE,EAAmB,OAAKD,EAAS,uBAAuB,EACxDE,EAAmB,OAAKF,EAAS,eAAe,EAChDG,EAAa;AAAA,UAAmBF,CAAW;AAAA,YACxC,eAAaG,EAAgBH,CAAW,UAClCF,EAAM,SAAS,KAAK,EAC7BE,EAAmB,OAAKD,EAAS,sBAAsB,EACvDE,EAAmB,OAAKF,EAAS,QAAQ,EACzCG,EAAa;AAAA,UAAmBF,CAAW;AAAA,YACxC,eAAaI,EAAeJ,CAAW,UACjCF,EAAM,SAAS,MAAM,EAAG,CACjC,IAAMQ,EAA0B,OAAKP,EAAS,0BAA0B,EAChE,aAAWO,CAAkB,GAChC,YAAUA,EAAoB,CAAE,UAAW,EAAK,CAAC,EAEtDN,EAAmB,OAAKM,EAAoB,WAAW,EACpD,eAAaD,EAAgBL,CAAW,EAC3C,IAAMpD,EAAUd,EAAQ,KAAK,EAC7BsC,EAAQ,yCAA0CxB,EAAQ,KAAMA,EAAQ,OAAO,EAC/E2D,GAAK,iDAAkD3D,EAAQ,KAAMA,EAAQ,OAAO,EACpF,MACF,KAAO,CACL,IAAMA,EAAUd,EAAQ,KAAK,EAC7BI,EAAM,sBAAsB4D,CAAK,wCAAyClD,EAAQ,KAAMA,EAAQ,OAAO,EACvG,MACF,CAIA,GADyB,aAAWqD,CAAW,EAC5B,CACjB,IAAMO,EAAoB,eAAaP,EAAa,OAAO,EAC3D,GAAI,CAACO,EAAe,SAAS,QAAQ,GAAK,CAACA,EAAe,SAAS,YAAY,EAAG,CAGhF,IAAMC,EADeD,EAAe,OAAS,GAAK,CAACA,EAAe,SAAS;AAAA,CAAI,EACjD;AAAA,EAAO,GAClC,iBAAeP,EAAaQ,EAASP,CAAU,CACpD,CACF,MACK,gBAAcD,EAAaC,CAAU,EAG1C,IAAMtD,EAAUd,EAAQ,KAAK,EAC7BsC,EAAQ,mCAAmC0B,EAAM,MAAM,GAAG,EAAE,IAAI,CAAC,GAAIlD,EAAQ,KAAMA,EAAQ,OAAO,EAClGyB,EAAK,eAAe4B,CAAW,0BAA2BrD,EAAQ,KAAMA,EAAQ,OAAO,CACzF,OAAS8D,EAAQ,CACf,IAAM9D,EAAUd,EAAQ,KAAK,EAC7BI,EAAM,wCAAwCwE,EAAE,OAAO,GAAI9D,EAAQ,KAAMA,EAAQ,OAAO,GACpFkD,EAAM,SAAS,MAAM,GAAKA,EAAM,SAAS,KAAK,IAChDzB,EAAK;AAAA,EAAyD6B,CAAU,GAAItD,EAAQ,KAAMA,EAAQ,OAAO,CAE7G,CACF,CAAC,EAEHiD,GACG,QAAQ,WAAW,EACnB,YAAY,mCAAmC,EAC/C,OAAO,SAAY,CAClB,IAAMC,EAAQ,QAAQ,IAAI,OAAS,GAC7BC,EAAa,WAAQ,EACvBC,EACAC,EAEJ,GAAI,CACF,GAAIH,EAAM,SAAS,MAAM,EACvBE,EAAmB,OAAKD,EAAS,uBAAuB,EACxDE,EAAmB,OAAKF,EAAS,eAAe,UACvCD,EAAM,SAAS,KAAK,EAC7BE,EAAmB,OAAKD,EAAS,sBAAsB,EACvDE,EAAmB,OAAKF,EAAS,QAAQ,UAChCD,EAAM,SAAS,MAAM,EAAG,CACjC,IAAMQ,EAA0B,OAAKP,EAAS,0BAA0B,EACxEC,EAAmB,OAAKM,EAAoB,WAAW,EAGvD,IAAM1D,EAAUd,EAAQ,KAAK,EACtB,aAAWkE,CAAW,GACxB,aAAWA,CAAW,EACzB5B,EAAQ,2CAA4CxB,EAAQ,KAAMA,EAAQ,OAAO,GAEjFyB,EAAK,oCAAqCzB,EAAQ,KAAMA,EAAQ,OAAO,EAEzE2D,GAAK,iDAAkD3D,EAAQ,KAAMA,EAAQ,OAAO,EACpF,MACF,KAAO,CACL,IAAMA,EAAUd,EAAQ,KAAK,EAC7BI,EAAM,sBAAsB4D,CAAK,0CAA2ClD,EAAQ,KAAMA,EAAQ,OAAO,EACzG,MACF,CAQA,GALO,aAAWoD,CAAW,GACxB,aAAWA,CAAW,EAIpB,aAAWC,CAAW,EAAG,CAC9B,IAAMO,EAAoB,eAAaP,EAAa,OAAO,EACrDU,EAAQH,EAAe,MAAM;AAAA,CAAI,EAGjCI,EAA0B,CAAC,EAC7BC,EAAI,EACJC,EAAmB,GAEvB,KAAOD,EAAIF,EAAM,QAAQ,CACvB,IAAMI,EAAOJ,EAAME,CAAC,EAGpB,GAAIE,EAAK,KAAK,IAAM,SAAU,CAI5B,IAHAD,EAAmB,GAEnBD,IACOA,EAAIF,EAAM,QAAUA,EAAME,CAAC,EAAE,KAAK,IAAM,cAC7CA,IAGEA,EAAIF,EAAM,QAAUA,EAAME,CAAC,EAAE,KAAK,IAAM,cAC1CA,GAEJ,MAEED,EAAc,KAAKG,CAAI,EACvBF,GAEJ,CAEA,IAAMjE,EAAUd,EAAQ,KAAK,EAC7B,GAAIgF,EAAkB,CAEpB,IAAME,EAA0BR,EAAe,SAAS;AAAA,CAAI,EACxDS,EACAL,EAAc,SAAW,EAC3BK,EAAa,GACJD,EACTC,EAAaL,EAAc,KAAK;AAAA,CAAI,EAAI;AAAA,EAExCK,EAAaL,EAAc,KAAK;AAAA,CAAI,EAEnC,gBAAcX,EAAagB,CAAU,EACxC7C,EAAQ,qCAAqC0B,EAAM,MAAM,GAAG,EAAE,IAAI,CAAC,GAAIlD,EAAQ,KAAMA,EAAQ,OAAO,EACpGyB,EAAK,eAAe4B,CAAW,0BAA2BrD,EAAQ,KAAMA,EAAQ,OAAO,CACzF,MACEV,EAAM,sCAAuCU,EAAQ,KAAMA,EAAQ,OAAO,CAE9E,KAAO,CACL,IAAMA,EAAUd,EAAQ,KAAK,EAC7BI,EAAM,yBAA0BU,EAAQ,KAAMA,EAAQ,OAAO,CAC/D,CACF,OAAS8D,EAAQ,CACf,IAAM9D,EAAUd,EAAQ,KAAK,EAC7BI,EAAM,0CAA0CwE,EAAE,OAAO,GAAI9D,EAAQ,KAAMA,EAAQ,OAAO,CAC5F,CACF,CAAC,EAIHd,EACG,SAAS,SAAU,gBAAgB,EACnC,OAAO,mBAAoB,oDAAoD,EAC/E,OAAO,kBAAmB,mDAAmD,EAC7E,OAAOuB,EACN,eAA0BG,EAAcgB,EAAeC,EAAkB,CACvE,GAAI,CAACD,EAAM,CACT,IAAMxC,EAAgBF,EAAQ,KAAK,EAE7BO,EAAUL,EAAc,QAAU,IAASA,EAAc,QAC/DG,EAAYE,CAAO,EACnB,QAAQ,KAAK,CAAC,CAChB,CAGA,GAAI,CAACmC,EAAK,SAAS,GAAG,GAAK,CAACA,EAAK,WAAW,GAAG,GAAK,CAACA,EAAK,WAAW,GAAG,EAEtE,MAAM,YAAU,WAAW,oBAAoBA,CAAI,GAAG,EAGxD,OAAOD,GAAcf,EAAQgB,EAAMC,EAAY,IAAI,CACrD,EACA,CAAE,UAAW,QAAS,CACxB,CAAC,EAOH,SAASyC,IAAmB,CAC1B,IAAM3D,EAAO,QAAQ,KACf4D,EAAS5D,EAAK,SAAS,YAAY,EACnC6D,EAAQ7D,EAAK,SAAS,WAAW,EACjC8D,EAAS9D,EAAK,SAAS,YAAY,EAEzC,GAAI,CAAC4D,GAAU,CAACC,GAAS,CAACC,EAAQ,OAGlC,QAAQ,IADY,CAAC,OAAQ,SAAU,cAAe,UAAW,UAAW,YAAY,EAChE,KAAKA,EAAS;AAAA,EAAO,GAAG,CAAC,EACjD,QAAQ,KAAK,CAAC,CAChB,CAGI,QAAQ,IAAI,WAAa,SAAW,QAAQ,KAAK,SAAS,YAAY,GAAK,QAAQ,KAAK,SAAS,WAAW,GAAK,QAAQ,KAAK,SAAS,YAAY,IACrJH,GAAiB,EAInB,GAAI,QAAQ,IAAI,WAAa,OAC3B,GAAI,CACFpF,EAAQ,MAAM,QAAQ,IAAI,CAC5B,OAASC,EAAU,CAGjB,MAAIA,EAAI,MAAQA,EAAI,KAAK,WAAW,YAAY,GAC9C,QAAQ,KAAKA,EAAI,UAAY,CAAC,EAE1BA,CACR","names":["env_exports","__export","__setTestEnvironment","getENV","env","_testEnvironment","detectEnvironment","init_env","__esmMin","config_exports","__export","loadConfig","validateConfig","config","ConfigSchema","error","firstError","path","loadConfigFromFile","configFile","getENV","cosmiconfigSync","os","explorer","MODULE_NAME","result","envConfig","fileConfig","mergedConfig","import_zod","import_types","init_config","__esmMin","init_env","calculateMD5Browser","blob","SparkMD5","resolve","reject","chunks","currentChunk","spark","fileReader","loadNext","start","end","e","result","calculateMD5Node","input","crypto","hash","fs","stream","err","chunk","calculateMD5","env","getENV","import_types","init_md5","__esmMin","init_env","setConfig","config","_config","getCurrentConfig","import_types","init_platform_config","__esmMin","filterJunk","filePaths","filePath","parts","basename","directorySegments","segment","JUNK_DIRECTORIES","junkDir","import_junk","init_junk","__esmMin","findCommonParent","dirPaths","normalizedPaths","p","pathSegments","commonSegments","minLength","i","segment","segments","normalizeWebPath","path","init_path","__esmMin","optimizeDeployPaths","filePaths","options","path","normalizeWebPath","extractFileName","commonPrefix","findCommonDirectory","filePath","deployPath","prefixToRemove","pathSegments","commonSegments","minLength","segments","i","segment","init_deploy_paths","__esmMin","init_path","findAllFilePaths","dirPath","results","entries","entry","fullPath","stats","subFiles","error","processFilesForNode","paths","options","getENV","absolutePaths","p","absPath","uniquePaths","validPaths","filterJunk","inputAbsolutePaths","inputBasePath","findCommonParent","relativePaths","filePath","rel","deployFiles","optimizeDeployPaths","totalSize","platformLimits","getCurrentConfig","i","deployPath","content","md5","calculateMD5","import_types","fs","path","init_node_files","__esmMin","init_env","init_md5","init_junk","init_platform_config","init_deploy_paths","init_path","processFilesForBrowser","browserFiles","options","getENV","filesArray","filePaths","file","deployFiles","optimizeDeployPaths","initialFileInfos","i","deployPath","allRelativePaths","info","nonJunkRelativePathsArray","filterJunk","nonJunkRelativePathsSet","result","fileInfo","md5","calculateMD5","import_types","init_browser_files","__esmMin","init_md5","init_junk","init_deploy_paths","prepare_input_exports","__export","convertBrowserInput","convertDeployInput","convertNodeInput","validateFiles","files","options","config","getCurrentConfig","totalSize","file","validateInputEarly","input","environment","item","postProcessFiles","validationFiles","f","staticFiles","processFilesForNode","fileArray","processFilesForBrowser","apiClient","getENV","import_types","init_prepare_input","__esmMin","init_env","init_node_files","init_browser_files","init_platform_config","import_commander","node_exports","__export","ApiHttp","JUNK_DIRECTORIES","Ship","__setTestEnvironment","calculateMD5","createAccountResource","createAliasResource","createDeploymentResource","createKeysResource","node_default","filterJunk","getCurrentConfig","getENV","loadConfig","mergeDeployOptions","optimizeDeployPaths","pluralize","processFilesForNode","resolveConfig","setConfig","_mime","import_types","init_env","DEPLOY_ENDPOINT","PING_ENDPOINT","ALIASES_ENDPOINT","CONFIG_ENDPOINT","ACCOUNT_ENDPOINT","SPA_CHECK_ENDPOINT","getBrowserContentType","file","collectAsyncIterable","iterable","result","x","ApiHttp","options","#getAuthHeaders","customHeaders","headers","#fetchWithAuth","url","operationName","fetchOptions","hasInstanceCredentials","hasAuthorizationHeader","error","#handleFetchError","#request","response","#handleResponseError","files","#validateFiles","apiUrl","signal","apiKey","deployToken","requestBody","requestHeaders","#prepareRequestPayload","authHeaders","getENV","#createBrowserBody","body","#createNodeBody","formData","checksums","fileContent","contentType","fileWithPath","FormDataNodeClass","FileNodeClass","FormDataEncoderClass","pathImport","formDataNodeInstance","i","fileNodeInstance","preservedPath","encoder","encodedChunks","chunk","errorData","message","id","name","deployment","indexFile","f","MAX_INDEX_SIZE","indexContent","requestData","import_types","init_env","loadConfig","configFile","env","getENV","nodeLoadConfig","resolveConfig","userOptions","loadedConfig","finalConfig","result","mergeDeployOptions","options","clientDefaults","import_types","init_md5","createSPAConfig","configString","content","md5","calculateMD5","detectAndConfigureSPA","files","apiClient","options","f","spaConfig","createDeploymentResource","getApi","clientDefaults","ensureInit","processInput","input","options","mergedOptions","mergeDeployOptions","apiClient","staticFiles","detectAndConfigureSPA","id","createAliasResource","aliasName","deployment","createAccountResource","createKeysResource","Ship","options","config","ApiHttp","initCallback","getApi","createDeploymentResource","input","createAliasResource","createAccountResource","createKeysResource","import_types","init_env","init_config","init_platform_config","shared_exports","__export","ApiHttp","JUNK_DIRECTORIES","Ship","__setTestEnvironment","calculateMD5","createAccountResource","createAliasResource","createDeploymentResource","createKeysResource","filterJunk","getENV","loadConfig","mergeDeployOptions","optimizeDeployPaths","pluralize","resolveConfig","types_exports","__reExport","__reExport","shared_exports","types_exports","import_types","init_md5","pluralize","count","singular","plural","includeCount","word","init_junk","init_deploy_paths","init_env","import_types","__reExport","node_exports","shared_exports","init_config","init_platform_config","init_node_files","init_env","Ship","options","getENV","resolveConfig","loadedConfig","loadConfig","finalConfig","ApiHttp","platformConfig","setConfig","error","input","#isValidNodeInput","convertDeployInput","item","node_default","import_types","import_fs","path","import_columnify","import_yoctocolors","applyColor","colorFn","text","noColor","success","msg","isJson","error","errorPrefix","errorMsg","warn","warnPrefix","warnMsg","info","infoPrefix","infoMsg","formatTimestamp","timestamp","context","isoString","formatValue","key","value","mb","formatTable","data","columns","firstItem","columnOrder","transformedData","item","transformed","col","columnify","config","heading","line","formatDetails","obj","entries","import_yoctocolors","fs","os","packageJson","packageJsonPath","developmentPath","program","err","globalOptions","message","error","displayHelp","str","noColor","applyBold","text","applyDim","output","processOptions","command","options","validationError","handleError","context","opts","resourceType","originalMessage","match","resourceId","withErrorHandling","handler","args","client","createClient","result","outputContext","errorContext","shipOptions","Ship","formatters","isJson","listColumns","formatTable","operation","success","warn","formatDetails","performDeploy","path","cmdOptions","commandContext","stats","deployOptions","abortController","spinner","yoctoSpinner","sigintHandler","key","formatter","thisCommand","actionCommand","deploymentsCmd","commandObj","unknownArg","arg","deployment","aliasesCmd","name","accountCmd","completionCmd","shell","homeDir","installPath","profileFile","sourceLine","bashScriptPath","zshScriptPath","fishScriptPath","fishCompletionsDir","info","profileContent","prefix","e","lines","filteredLines","i","removedSomething","line","originalEndsWithNewline","newContent","handleCompletion","isBash","isZsh","isFish"]}
1
+ {"version":3,"sources":["../src/shared/lib/env.ts","../src/node/core/config.ts","../src/shared/lib/md5.ts","../src/node/core/platform-config.ts","../src/shared/lib/junk.ts","../src/shared/lib/path.ts","../src/shared/lib/deploy-paths.ts","../src/node/core/node-files.ts","../src/browser/lib/browser-files.ts","../src/node/core/prepare-input.ts","../src/node/cli/index.ts","../src/node/index.ts","../src/shared/api/http.ts","../src/shared/core/config.ts","../src/shared/lib/prepare-input.ts","../src/shared/resources.ts","../src/shared/base-ship.ts","../src/shared/index.ts","../src/shared/types.ts","../src/shared/core/constants.ts","../src/shared/lib/text.ts","../src/node/cli/utils.ts"],"sourcesContent":["/**\n * @file Environment detection utilities for the Ship SDK.\n * Helps in determining whether the SDK is running in a Node.js, browser, or unknown environment.\n */\n\n/**\n * Represents the detected or simulated JavaScript execution environment.\n */\nexport type ExecutionEnvironment = 'browser' | 'node' | 'unknown';\n\n/** @internal Environment override for testing. */\nlet _testEnvironment: ExecutionEnvironment | null = null;\n\n/**\n * **FOR TESTING PURPOSES ONLY.**\n *\n * Allows tests to override the detected environment, forcing the SDK to behave\n * as if it's running in the specified environment.\n *\n * @param env - The environment to simulate ('node', 'browser', 'unknown'),\n * or `null` to clear the override and revert to actual environment detection.\n * @internal\n */\nexport function __setTestEnvironment(env: ExecutionEnvironment | null): void {\n _testEnvironment = env;\n}\n\n/**\n * Detects the actual JavaScript execution environment (Node.js, browser, or unknown)\n * by checking for characteristic global objects.\n * @returns The detected environment as {@link ExecutionEnvironment}.\n * @internal\n */\nfunction detectEnvironment(): ExecutionEnvironment {\n // Check for Node.js environment\n if (typeof process !== 'undefined' && process.versions && process.versions.node) {\n return 'node';\n }\n\n // Check for Browser environment (including Web Workers)\n if (typeof window !== 'undefined' || typeof self !== 'undefined') {\n return 'browser';\n }\n\n return 'unknown';\n}\n\n/**\n * Gets the current effective execution environment.\n *\n * This function first checks if a test environment override is active via {@link __setTestEnvironment}.\n * If not, it detects the actual environment (Node.js, browser, or unknown).\n *\n * @returns The current execution environment: 'browser', 'node', or 'unknown'.\n * @public\n */\nexport function getENV(): ExecutionEnvironment {\n // Return test override if set\n if (_testEnvironment) {\n return _testEnvironment;\n }\n \n // Detect actual environment\n return detectEnvironment();\n}\n","/**\n * @file Manages loading and validation of client configuration.\n * This module uses `cosmiconfig` to find and load configuration from various\n * file sources (e.g., `.shiprc`, `package.json`) and environment variables.\n * Configuration values are validated using Zod schemas.\n */\n\nimport { z } from 'zod';\nimport type { ShipClientOptions, DeploymentOptions } from '../../shared/types.js';\nimport { ShipError } from '@shipstatic/types';\nimport { getENV } from '../../shared/lib/env.js';\nimport { DEFAULT_API } from '../../shared/core/constants.js';\n\n\n\n/** @internal Name of the module, used by cosmiconfig for config file searching. */\nconst MODULE_NAME = 'ship';\n\n/**\n * Zod schema for validating ship configuration.\n * @internal\n */\nconst ConfigSchema = z.object({\n apiUrl: z.string().url().optional(),\n apiKey: z.string().optional(),\n deployToken: z.string().optional()\n}).strict();\n\n/**\n * Validates configuration using Zod schema.\n * @param config - Configuration object to validate\n * @returns Validated configuration or throws error\n * @internal\n */\nfunction validateConfig(config: any): Partial<ShipClientOptions> {\n try {\n return ConfigSchema.parse(config);\n } catch (error) {\n if (error instanceof z.ZodError) {\n const firstError = error.issues[0];\n const path = firstError.path.length > 0 ? ` at ${firstError.path.join('.')}` : '';\n throw ShipError.config(`Configuration validation failed${path}: ${firstError.message}`);\n }\n throw ShipError.config('Configuration validation failed');\n }\n}\n\n/**\n * Loads client configuration from files.\n * Searches for .shiprc and package.json with ship key.\n * First searches from the current directory, then from the home directory.\n * @param configFile - Optional specific config file path to load\n * @returns Configuration object or empty if not found/invalid\n * @internal\n */\nasync function loadConfigFromFile(configFile?: string): Promise<Partial<ShipClientOptions>> {\n try {\n // Only use cosmiconfig in Node.js environments\n if (getENV() !== 'node') {\n return {};\n }\n \n // Dynamically import cosmiconfig and os only in Node.js environments\n const { cosmiconfigSync } = await import('cosmiconfig');\n const os = await import('os');\n \n const explorer = cosmiconfigSync(MODULE_NAME, {\n searchPlaces: [\n `.${MODULE_NAME}rc`,\n 'package.json',\n `${os.homedir()}/.${MODULE_NAME}rc`, // Always include home directory as fallback\n ],\n stopDir: os.homedir(), // Stop searching at home directory\n });\n \n let result;\n \n // If a specific config file is provided, load it directly\n if (configFile) {\n result = explorer.load(configFile);\n } else {\n // cosmiconfig automatically searches up the directory tree\n // from current directory to stopDir (home directory)\n result = explorer.search();\n }\n \n if (result && result.config) {\n return validateConfig(result.config);\n }\n } catch (error) {\n if (error instanceof ShipError) throw error; // Re-throw all ShipError instances\n // Silently fail for file loading issues - this is optional config\n }\n return {};\n}\n\n/**\n * Simplified configuration loading prioritizing environment variables.\n * Only loads file config if environment variables are not set.\n * Only available in Node.js environments.\n *\n * @param configFile - Optional specific config file path to load\n * @returns Configuration object with loaded values\n * @throws {ShipInvalidConfigError} If the configuration is invalid.\n */\nexport async function loadConfig(configFile?: string): Promise<Partial<ShipClientOptions>> {\n if (getENV() !== 'node') return {};\n\n // Start with environment variables (highest priority)\n const envConfig = {\n apiUrl: process.env.SHIP_API_URL,\n apiKey: process.env.SHIP_API_KEY,\n deployToken: process.env.SHIP_DEPLOY_TOKEN,\n };\n\n // Always try to load file config for fallback values\n const fileConfig = await loadConfigFromFile(configFile);\n\n // Merge with environment variables taking precedence\n const mergedConfig = {\n apiUrl: envConfig.apiUrl ?? fileConfig.apiUrl,\n apiKey: envConfig.apiKey ?? fileConfig.apiKey,\n deployToken: envConfig.deployToken ?? fileConfig.deployToken,\n };\n\n // Validate final config\n return validateConfig(mergedConfig);\n}\n\n","/**\n * @file Simplified MD5 calculation utility with separate environment handlers.\n */\nimport { getENV } from './env.js';\nimport { ShipError } from '@shipstatic/types';\n\nexport interface MD5Result {\n md5: string;\n}\n\n/**\n * Browser-specific MD5 calculation for Blob/File objects\n */\nasync function calculateMD5Browser(blob: Blob): Promise<MD5Result> {\n const SparkMD5 = (await import('spark-md5')).default;\n \n return new Promise((resolve, reject) => {\n const chunkSize = 2097152; // 2MB chunks\n const chunks = Math.ceil(blob.size / chunkSize);\n let currentChunk = 0;\n const spark = new SparkMD5.ArrayBuffer();\n const fileReader = new FileReader();\n\n const loadNext = () => {\n const start = currentChunk * chunkSize;\n const end = Math.min(start + chunkSize, blob.size);\n fileReader.readAsArrayBuffer(blob.slice(start, end));\n };\n\n fileReader.onload = (e) => {\n const result = e.target?.result as ArrayBuffer;\n if (!result) {\n reject(ShipError.business('Failed to read file chunk'));\n return;\n }\n \n spark.append(result);\n currentChunk++;\n \n if (currentChunk < chunks) {\n loadNext();\n } else {\n resolve({ md5: spark.end() });\n }\n };\n\n fileReader.onerror = () => {\n reject(ShipError.business('Failed to calculate MD5: FileReader error'));\n };\n\n loadNext();\n });\n}\n\n/**\n * Node.js-specific MD5 calculation for Buffer or file path\n */\nasync function calculateMD5Node(input: Buffer | string): Promise<MD5Result> {\n const crypto = await import('crypto');\n \n if (Buffer.isBuffer(input)) {\n const hash = crypto.createHash('md5');\n hash.update(input);\n return { md5: hash.digest('hex') };\n }\n \n // Handle file path\n const fs = await import('fs');\n return new Promise((resolve, reject) => {\n const hash = crypto.createHash('md5');\n const stream = fs.createReadStream(input);\n \n stream.on('error', err => \n reject(ShipError.business(`Failed to read file for MD5: ${err.message}`))\n );\n stream.on('data', chunk => hash.update(chunk));\n stream.on('end', () => resolve({ md5: hash.digest('hex') }));\n });\n}\n\n/**\n * Unified MD5 calculation that delegates to environment-specific handlers\n */\nexport async function calculateMD5(input: Blob | Buffer | string): Promise<MD5Result> {\n const env = getENV();\n \n if (env === 'browser') {\n if (!(input instanceof Blob)) {\n throw ShipError.business('Invalid input for browser MD5 calculation: Expected Blob or File.');\n }\n return calculateMD5Browser(input);\n }\n \n if (env === 'node') {\n if (!(Buffer.isBuffer(input) || typeof input === 'string')) {\n throw ShipError.business('Invalid input for Node.js MD5 calculation: Expected Buffer or file path string.');\n }\n return calculateMD5Node(input);\n }\n \n throw ShipError.business('Unknown or unsupported execution environment for MD5 calculation.');\n}\n","/**\n * @file Platform configuration management for the Ship SDK.\n * Implements fail-fast dynamic configuration with mandatory API fetch.\n */\n\nimport type { ConfigResponse } from '@shipstatic/types';\nimport { ShipError } from '@shipstatic/types';\n\n// Dynamic config - must be fetched from API before operations\nlet _config: ConfigResponse | null = null;\n\n/**\n * Set the current config (called after fetching from API)\n */\nexport function setConfig(config: ConfigResponse): void {\n _config = config;\n}\n\n/**\n * Get current config - throws if not initialized (fail-fast approach)\n * @throws {ShipError.config} If configuration hasn't been fetched from API\n */\nexport function getCurrentConfig(): ConfigResponse {\n if (_config === null) {\n throw ShipError.config(\n 'Platform configuration not initialized. The SDK must fetch configuration from the API before performing operations.'\n );\n }\n return _config;\n}\n\n/**\n * Check if config has been initialized from API\n */\nexport function isConfigInitialized(): boolean {\n return _config !== null;\n}\n\n/**\n * Reset config state (primarily for testing)\n * @internal\n */\nexport function resetConfig(): void {\n _config = null;\n}","/**\n * @file Utility for filtering out junk files and directories from file paths\n * \n * This module provides functionality to filter out common system junk files and directories\n * from a list of file paths. It uses the 'junk' package to identify junk filenames and\n * a custom list to filter out common junk directories.\n */\nimport { isJunk } from 'junk';\n\n/**\n * List of directory names considered as junk\n * \n * Files within these directories (at any level in the path hierarchy) will be excluded.\n * The comparison is case-insensitive for cross-platform compatibility.\n * \n * @internal\n */\nexport const JUNK_DIRECTORIES = [\n '__MACOSX',\n '.Trashes',\n '.fseventsd',\n '.Spotlight-V100',\n] as const;\n\n/**\n * Filters an array of file paths, removing those considered junk\n * \n * A path is filtered out if either:\n * 1. The basename is identified as junk by the 'junk' package (e.g., .DS_Store, Thumbs.db)\n * 2. Any directory segment in the path matches an entry in JUNK_DIRECTORIES (case-insensitive)\n *\n * All path separators are normalized to forward slashes for consistent cross-platform behavior.\n * \n * @param filePaths - An array of file path strings to filter\n * @returns A new array containing only non-junk file paths\n */\nexport function filterJunk(filePaths: string[]): string[] {\n if (!filePaths || filePaths.length === 0) {\n return [];\n }\n\n return filePaths.filter(filePath => {\n if (!filePath) {\n return false; // Exclude null or undefined paths\n }\n\n // Normalize path separators to forward slashes and split into segments\n const parts = filePath.replace(/\\\\/g, '/').split('/').filter(Boolean);\n if (parts.length === 0) return true;\n \n // Check if the basename is a junk file (using junk package)\n const basename = parts[parts.length - 1];\n if (isJunk(basename)) {\n return false;\n }\n\n // Check if any directory segment is in our junk directories list\n const directorySegments = parts.slice(0, -1);\n for (const segment of directorySegments) {\n if (JUNK_DIRECTORIES.some(junkDir => \n segment.toLowerCase() === junkDir.toLowerCase())) {\n return false;\n }\n }\n\n return true;\n });\n}\n","/**\n * @file Path helper utilities that work in both browser and Node.js environments.\n * Provides environment-agnostic path manipulation functions.\n */\n\n/**\n * Finds the common parent directory from an array of directory paths.\n * Simple, unified implementation for flattenDirs functionality.\n * \n * @param dirPaths - Array of directory paths (not file paths - directories containing the files)\n * @returns The common parent directory path, or empty string if none found\n */\nexport function findCommonParent(dirPaths: string[]): string {\n if (!dirPaths || dirPaths.length === 0) return '';\n \n // Normalize all paths to use forward slashes\n const normalizedPaths = dirPaths\n .filter(p => p && typeof p === 'string')\n .map(p => p.replace(/\\\\/g, '/'));\n \n if (normalizedPaths.length === 0) return '';\n if (normalizedPaths.length === 1) return normalizedPaths[0];\n \n // Split into segments and find common prefix\n const pathSegments = normalizedPaths.map(p => p.split('/').filter(Boolean));\n const commonSegments = [];\n const minLength = Math.min(...pathSegments.map(p => p.length));\n \n for (let i = 0; i < minLength; i++) {\n const segment = pathSegments[0][i];\n if (pathSegments.every(segments => segments[i] === segment)) {\n commonSegments.push(segment);\n } else {\n break;\n }\n }\n \n return commonSegments.join('/');\n}\n\n\n\n/**\n * Converts backslashes to forward slashes for cross-platform compatibility.\n * Does not remove leading slashes (preserves absolute paths).\n * @param path - The path to normalize\n * @returns Path with forward slashes\n */\nexport function normalizeSlashes(path: string): string {\n return path.replace(/\\\\/g, '/');\n}\n\n/**\n * Normalizes a path for web usage by converting backslashes to forward slashes\n * and removing leading slashes.\n * @param path - The path to normalize\n * @returns Normalized path suitable for web deployment\n */\nexport function normalizeWebPath(path: string): string {\n return path.replace(/\\\\/g, '/').replace(/\\/+/g, '/').replace(/^\\/+/, '');\n}\n\n","/**\n * @file Deploy path optimization - the core logic that makes Ship deployments clean and intuitive.\n * Automatically strips common parent directories to create clean deployment URLs.\n */\n\nimport { normalizeWebPath } from './path.js';\n\n/**\n * Represents a file ready for deployment with its optimized path\n */\nexport interface DeployFile {\n /** The clean deployment path (e.g., \"assets/style.css\") */\n path: string;\n /** Original filename */\n name: string;\n}\n\n/**\n * Core path optimization logic.\n * Transforms messy local paths into clean deployment paths.\n * \n * @example\n * Input: [\"dist/index.html\", \"dist/assets/app.js\"]\n * Output: [\"index.html\", \"assets/app.js\"]\n * \n * @param filePaths - Raw file paths from the local filesystem\n * @param options - Path processing options\n */\nexport function optimizeDeployPaths(\n filePaths: string[], \n options: { flatten?: boolean } = {}\n): DeployFile[] {\n // When flattening is disabled, keep original structure\n if (options.flatten === false) {\n return filePaths.map(path => ({\n path: normalizeWebPath(path),\n name: extractFileName(path)\n }));\n }\n\n // Find the common directory prefix to strip\n const commonPrefix = findCommonDirectory(filePaths);\n \n return filePaths.map(filePath => {\n let deployPath = normalizeWebPath(filePath);\n \n // Strip the common prefix to create clean deployment paths\n if (commonPrefix) {\n const prefixToRemove = commonPrefix.endsWith('/') ? commonPrefix : `${commonPrefix}/`;\n if (deployPath.startsWith(prefixToRemove)) {\n deployPath = deployPath.substring(prefixToRemove.length);\n }\n }\n \n // Fallback to filename if path becomes empty\n if (!deployPath) {\n deployPath = extractFileName(filePath);\n }\n \n return {\n path: deployPath,\n name: extractFileName(filePath)\n };\n });\n}\n\n/**\n * Finds the common directory shared by all file paths.\n * This is what gets stripped to create clean deployment URLs.\n * \n * @example\n * [\"dist/index.html\", \"dist/assets/app.js\"] → \"dist\"\n * [\"src/components/A.tsx\", \"src/utils/B.ts\"] → \"src\"\n * [\"file1.txt\", \"file2.txt\", \"subdir/file3.txt\"] → \"\" (no common directory)\n */\nfunction findCommonDirectory(filePaths: string[]): string {\n if (!filePaths.length) return '';\n \n // Normalize all paths first\n const normalizedPaths = filePaths.map(path => normalizeWebPath(path));\n \n // Find the common prefix among all file paths (not just directories)\n const pathSegments = normalizedPaths.map(path => path.split('/'));\n const commonSegments: string[] = [];\n const minLength = Math.min(...pathSegments.map(segments => segments.length));\n \n // Check each segment level to find the longest common prefix\n for (let i = 0; i < minLength - 1; i++) { // -1 because we don't want to include the filename\n const segment = pathSegments[0][i];\n if (pathSegments.every(segments => segments[i] === segment)) {\n commonSegments.push(segment);\n } else {\n break;\n }\n }\n \n return commonSegments.join('/');\n}\n\n/**\n * Extracts just the filename from a file path\n */\nfunction extractFileName(path: string): string {\n return path.split(/[/\\\\]/).pop() || path;\n}","/**\n * @file Node.js-specific file utilities for the Ship SDK.\n * Provides helpers for recursively discovering, filtering, and preparing files for deploy in Node.js.\n */\nimport { getENV } from '../../shared/lib/env.js';\nimport type { StaticFile, DeploymentOptions } from '../../shared/types.js';\nimport { calculateMD5 } from '../../shared/lib/md5.js';\nimport { filterJunk } from '../../shared/lib/junk.js';\nimport { ShipError } from '@shipstatic/types';\nimport { getCurrentConfig } from './platform-config.js';\nimport { optimizeDeployPaths } from '../../shared/lib/deploy-paths.js';\nimport { findCommonParent } from '../../shared/lib/path.js';\n\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n\n/**\n * Simple recursive function to walk directory and return all file paths.\n * More declarative and focused than the previous implementation.\n * @param dirPath - Directory path to traverse\n * @returns Array of absolute file paths in the directory\n */\nfunction findAllFilePaths(dirPath: string): string[] {\n const results: string[] = [];\n \n try {\n const entries = fs.readdirSync(dirPath);\n \n for (const entry of entries) {\n const fullPath = path.join(dirPath, entry);\n const stats = fs.statSync(fullPath);\n \n if (stats.isDirectory()) {\n const subFiles = findAllFilePaths(fullPath);\n results.push(...subFiles);\n } else if (stats.isFile()) {\n results.push(fullPath);\n }\n }\n } catch (error) {\n console.error(`Error reading directory ${dirPath}:`, error);\n }\n \n return results;\n}\n\n/**\n * Processes Node.js file and directory paths into an array of StaticFile objects ready for deploy.\n * Uses corrected logic to properly handle common parent directory stripping.\n * \n * @param paths - File or directory paths to scan and process.\n * @param options - Processing options (pathDetect, etc.).\n * @returns Promise resolving to an array of StaticFile objects.\n * @throws {ShipClientError} If called outside Node.js or if fs/path modules fail.\n */\nexport async function processFilesForNode(\n paths: string[],\n options: DeploymentOptions = {}\n): Promise<StaticFile[]> {\n if (getENV() !== 'node') {\n throw ShipError.business('processFilesForNode can only be called in Node.js environment.');\n }\n\n // 1. Discover all unique, absolute file paths from the input list\n const absolutePaths = paths.flatMap(p => {\n const absPath = path.resolve(p);\n try {\n const stats = fs.statSync(absPath);\n return stats.isDirectory() ? findAllFilePaths(absPath) : [absPath];\n } catch (error) {\n throw ShipError.file(`Path does not exist: ${p}`, p);\n }\n });\n const uniquePaths = [...new Set(absolutePaths)];\n \n // 2. Filter out junk files from the final list\n const validPaths = filterJunk(uniquePaths);\n if (validPaths.length === 0) {\n return [];\n }\n\n // 3. Determine the base path for calculating relative paths\n // Find the common parent of the INPUT paths (not the discovered file paths)\n const inputAbsolutePaths = paths.map(p => path.resolve(p));\n const inputBasePath = findCommonParent(inputAbsolutePaths.map(p => {\n try {\n const stats = fs.statSync(p);\n return stats.isDirectory() ? p : path.dirname(p);\n } catch {\n return path.dirname(p);\n }\n }));\n\n // 4. Create raw relative paths for optimization\n const relativePaths = validPaths.map(filePath => {\n // If we have a meaningful common base path from inputs, use it\n if (inputBasePath && inputBasePath.length > 0) {\n const rel = path.relative(inputBasePath, filePath);\n if (rel && typeof rel === 'string' && !rel.startsWith('..')) {\n return rel.replace(/\\\\/g, '/');\n }\n }\n \n // Fallback: if no good common parent or relative path goes up, just use basename\n return path.basename(filePath);\n });\n\n // 5. Optimize paths for deployment (flattening)\n const deployFiles = optimizeDeployPaths(relativePaths, {\n flatten: options.pathDetect !== false\n });\n\n // 6. Process files into StaticFile objects\n const results: StaticFile[] = [];\n let totalSize = 0;\n const platformLimits = getCurrentConfig();\n\n for (let i = 0; i < validPaths.length; i++) {\n const filePath = validPaths[i];\n const deployPath = deployFiles[i].path;\n \n try {\n const stats = fs.statSync(filePath);\n if (stats.size === 0) {\n console.warn(`Skipping empty file: ${filePath}`);\n continue; // Skip empty files\n }\n\n // Validate file sizes\n if (stats.size > platformLimits.maxFileSize) {\n throw ShipError.business(`File ${filePath} is too large. Maximum allowed size is ${platformLimits.maxFileSize / (1024 * 1024)}MB.`);\n }\n totalSize += stats.size;\n if (totalSize > platformLimits.maxTotalSize) {\n throw ShipError.business(`Total deploy size is too large. Maximum allowed is ${platformLimits.maxTotalSize / (1024 * 1024)}MB.`);\n }\n\n const content = fs.readFileSync(filePath);\n const { md5 } = await calculateMD5(content);\n \n // Security validation: Ensure no dangerous characters in paths\n if (deployPath.includes('\\0') || deployPath.includes('/../') || deployPath.startsWith('../') || deployPath.endsWith('/..')) {\n throw ShipError.business(`Security error: Unsafe file path \"${deployPath}\" for file: ${filePath}`);\n }\n \n results.push({\n path: deployPath,\n content,\n size: content.length,\n md5,\n });\n } catch (error) {\n if (error instanceof ShipError && error.isClientError && error.isClientError()) {\n throw error;\n }\n console.error(`Could not process file ${filePath}:`, error);\n }\n }\n\n // Final validation\n if (results.length > platformLimits.maxFilesCount) {\n throw ShipError.business(`Too many files to deploy. Maximum allowed is ${platformLimits.maxFilesCount} files.`);\n }\n \n return results;\n}","/**\n * @file Browser-specific file utilities for the Ship SDK.\n * Provides helpers for processing browser files into deploy-ready objects and extracting common directory info.\n */\nimport type { StaticFile, DeploymentOptions } from '../../shared/types.js';\nimport { calculateMD5 } from '../../shared/lib/md5.js';\nimport { ShipError } from '@shipstatic/types';\nimport { filterJunk } from '../../shared/lib/junk.js';\nimport { optimizeDeployPaths } from '../../shared/lib/deploy-paths.js';\n\n\n/**\n * Internal structure representing a browser file to be processed for deploy.\n * @internal\n */\ninterface BrowserFileProcessItem {\n file: File;\n relativePath: string;\n}\n\n/**\n * Processes browser files (FileList or File[]) into an array of StaticFile objects ready for deploy.\n * Calculates MD5, filters junk files, and applies automatic path optimization.\n *\n * @param browserFiles - FileList or File[] to process for deploy.\n * @param options - Processing options including pathDetect for automatic path optimization.\n * @returns Promise resolving to an array of StaticFile objects.\n * @throws {ShipClientError} If called outside a browser or with invalid input.\n */\nexport async function processFilesForBrowser(\n browserFiles: FileList | File[],\n options: DeploymentOptions = {}\n): Promise<StaticFile[]> {\n // Check environment using getENV\n const { getENV } = await import('../../shared/lib/env.js');\n if (getENV() !== 'browser') {\n throw ShipError.business('processFilesForBrowser can only be called in a browser environment.');\n }\n\n const filesArray = Array.isArray(browserFiles) ? browserFiles : Array.from(browserFiles);\n \n // Extract file paths from browser files, preferring webkitRelativePath for directory structure\n const filePaths = filesArray.map(file => (file as any).webkitRelativePath || file.name);\n \n // Optimize paths for clean deployment URLs\n const deployFiles = optimizeDeployPaths(filePaths, { \n flatten: options.pathDetect !== false \n });\n \n // Prepare file information with security validation\n const initialFileInfos: BrowserFileProcessItem[] = [];\n for (let i = 0; i < filesArray.length; i++) {\n const file = filesArray[i];\n const deployPath = deployFiles[i].path;\n \n // Security validation: Ensure no dangerous characters in paths\n if (deployPath.includes('..') || deployPath.includes('\\0')) {\n throw ShipError.business(`Security error: Unsafe file path \"${deployPath}\" for file: ${file.name}`);\n }\n \n initialFileInfos.push({ file, relativePath: deployPath });\n }\n\n // Filter out junk files\n const allRelativePaths = initialFileInfos.map(info => info.relativePath);\n const nonJunkRelativePathsArray = filterJunk(allRelativePaths);\n const nonJunkRelativePathsSet = new Set(nonJunkRelativePathsArray);\n\n // Create StaticFile objects for each valid file\n const result: StaticFile[] = [];\n for (const fileInfo of initialFileInfos) {\n // Skip junk files but NOT empty files (tests expect empty files to be processed)\n if (!nonJunkRelativePathsSet.has(fileInfo.relativePath)) {\n continue;\n }\n \n // Calculate MD5 hash\n const { md5 } = await calculateMD5(fileInfo.file);\n \n // Create and add the StaticFile - keep File as File (impossible simplicity!)\n result.push({\n content: fileInfo.file,\n path: fileInfo.relativePath,\n size: fileInfo.file.size,\n md5,\n });\n }\n \n return result;\n}\n\n","/**\n * @file Input conversion utilities for deployment\n * Converts various input types to StaticFile[] for unified processing\n */\n\nimport type { StaticFile, DeploymentOptions, DeployInput } from '../../shared/types.js';\nimport { ShipError, DEPLOYMENT_CONFIG_FILENAME } from '@shipstatic/types';\nimport { getENV } from '../../shared/lib/env.js';\nimport { processFilesForNode } from './node-files.js';\nimport { processFilesForBrowser } from '../../browser/lib/browser-files.js';\nimport { getCurrentConfig } from './platform-config.js';\nimport { calculateMD5 } from '../../shared/lib/md5.js';\n\n\n/**\n * Fail-fast file validation for both Node.js and browser environments\n * Validates immediately without collecting all files first for better performance\n * @param files - Array of files to validate (can be File[] or file metadata)\n * @param options - Validation options\n * @throws {ShipError} If validation fails\n * @internal\n */\nfunction validateFiles(files: Array<{ name: string; size: number }>, options: { skipEmptyCheck?: boolean } = {}): void {\n const config = getCurrentConfig();\n \n // Check for empty file array - fail fast\n if (!options.skipEmptyCheck && files.length === 0) {\n throw ShipError.business('No files to deploy.');\n }\n \n // Check file count limit - fail fast\n if (files.length > config.maxFilesCount) {\n throw ShipError.business(`Too many files to deploy. Maximum allowed is ${config.maxFilesCount}.`);\n }\n \n // Validate individual files and calculate total size - fail on first violation\n let totalSize = 0;\n for (const file of files) {\n // Individual file size validation - fail immediately\n if (file.size > config.maxFileSize) {\n throw ShipError.business(`File ${file.name} is too large. Maximum allowed size is ${config.maxFileSize / (1024 * 1024)}MB.`);\n }\n \n // Accumulate total size and check incrementally for early failure\n totalSize += file.size;\n if (totalSize > config.maxTotalSize) {\n throw ShipError.business(`Total deploy size is too large. Maximum allowed is ${config.maxTotalSize / (1024 * 1024)}MB.`);\n }\n }\n}\n\n/**\n * Early validation for file count and basic input\n * Used before file processing to fail fast on obvious issues\n * @param input - Input to validate\n * @param environment - Current environment (node/browser)\n * @throws {ShipError} If validation fails\n * @internal\n */\nfunction validateInputEarly(input: any, environment: string): void {\n if (environment === 'node') {\n if (!Array.isArray(input)) {\n throw ShipError.business('Invalid input type for Node.js environment. Expected string[] file paths.');\n }\n if (input.length === 0) {\n throw ShipError.business('No files to deploy.');\n }\n if (!input.every(item => typeof item === 'string')) {\n throw ShipError.business('Invalid input type for Node.js environment. Expected string[] file paths.');\n }\n } else if (environment === 'browser') {\n if (input instanceof HTMLInputElement && !input.files) {\n throw ShipError.business('No files selected in HTMLInputElement');\n }\n }\n}\n\n/**\n * Shared post-processing logic for StaticFile arrays\n * @param files - Array of StaticFile objects to process\n * @returns Processed StaticFile array\n * @internal\n */\nfunction postProcessFiles(files: StaticFile[]): StaticFile[] {\n // Validate processed files - convert StaticFile[] to the expected format\n const validationFiles = files.map(f => ({ name: f.path, size: f.size }));\n validateFiles(validationFiles, { skipEmptyCheck: true });\n \n // Normalize paths to forward slashes\n files.forEach(f => {\n if (f.path) f.path = f.path.replace(/\\\\/g, '/');\n });\n \n return files;\n}\n\n/**\n * Converts Node.js string[] paths to StaticFile[]\n */\nexport async function convertNodeInput(\n input: string[], \n options: DeploymentOptions = {}\n): Promise<StaticFile[]> {\n // Early validation - fail fast before processing\n validateInputEarly(input, 'node');\n\n // Pass options directly to node processor - no conflicting logic here\n const staticFiles: StaticFile[] = await processFilesForNode(input, options);\n \n // Apply shared validation and post-processing\n return postProcessFiles(staticFiles);\n}\n\n/**\n * Converts browser FileList/File[]/HTMLInputElement to StaticFile[]\n */\nexport async function convertBrowserInput(\n input: FileList | File[] | HTMLInputElement,\n options: DeploymentOptions = {}\n): Promise<StaticFile[]> {\n // Early validation - fail fast before processing\n validateInputEarly(input, 'browser');\n\n let fileArray: File[];\n \n if (input instanceof HTMLInputElement) {\n fileArray = Array.from(input.files!);\n } else if (\n typeof input === 'object' &&\n input !== null &&\n typeof (input as any).length === 'number' &&\n typeof (input as any).item === 'function'\n ) {\n fileArray = Array.from(input as FileList);\n } else if (Array.isArray(input)) {\n if (input.length > 0 && typeof input[0] === 'string') {\n throw ShipError.business('Invalid input type for browser environment. Expected File[], FileList, or HTMLInputElement.');\n }\n fileArray = input as File[];\n } else {\n throw ShipError.business('Invalid input type for browser environment. Expected File[], FileList, or HTMLInputElement.');\n }\n\n // Filter out empty files first\n fileArray = fileArray.filter(file => {\n if (file.size === 0) {\n console.warn(`Skipping empty file: ${file.name}`);\n return false;\n }\n return true;\n });\n\n // Early validation using shared logic - fail fast before heavy processing\n validateFiles(fileArray);\n\n // Pass options directly to browser processor - no conflicting logic here\n const staticFiles: StaticFile[] = await processFilesForBrowser(fileArray as File[], options);\n \n // Apply shared validation and post-processing\n return postProcessFiles(staticFiles);\n}\n\n/**\n * Unified input conversion function with automatic SPA detection\n * Converts any DeployInput to StaticFile[] and auto-generates ship.json for SPAs\n */\nexport async function convertDeployInput(\n input: DeployInput,\n options: DeploymentOptions = {},\n apiClient?: any\n): Promise<StaticFile[]> {\n const environment = getENV();\n \n // Early validation at the unified level - fail immediately on environment issues\n if (environment !== 'node' && environment !== 'browser') {\n throw ShipError.business('Unsupported execution environment.');\n }\n \n // Convert input to StaticFile[] based on environment\n let files: StaticFile[];\n if (environment === 'node') {\n // Normalize string to string[] for Node.js processing\n if (typeof input === 'string') {\n files = await convertNodeInput([input], options);\n } else if (Array.isArray(input) && input.every(item => typeof item === 'string')) {\n files = await convertNodeInput(input as string[], options);\n } else {\n throw ShipError.business('Invalid input type for Node.js environment. Expected string[] file paths.');\n }\n } else {\n files = await convertBrowserInput(input as FileList | File[] | HTMLInputElement, options);\n }\n \n return files;\n}\n\n","/**\n * @file Main entry point for the Ship CLI.\n * Ultra-simple CLI with explicit commands and deploy shortcut.\n */\nimport { Command } from 'commander';\nimport { Ship, ShipError } from '../index.js';\nimport { validateApiKey, validateDeployToken, validateApiUrl } from '@shipstatic/types';\nimport { readFileSync, existsSync, statSync } from 'fs';\nimport * as path from 'path';\nimport { formatTable, formatDetails, success, error, info, warn } from './utils.js';\nimport { bold, dim } from 'yoctocolors';\n// Removed tabtab dependency - now using custom completion script\nimport * as fs from 'fs';\nimport * as os from 'os';\n\n// Get package.json data for version information using robust path resolution\nlet packageJson: any = { version: '0.0.0' };\n\ntry {\n // For the built CLI, package.json is always one level up from the dist directory\n // This is more reliable than hardcoded multiple fallback paths\n const packageJsonPath = path.resolve(__dirname, '../package.json');\n packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n} catch (error) {\n // Fallback for development/testing scenarios where the structure might differ\n const developmentPath = path.resolve(__dirname, '../../package.json');\n try {\n packageJson = JSON.parse(readFileSync(developmentPath, 'utf-8'));\n } catch (fallbackError) {\n // Final fallback - use default version\n // This is better than silent failure as it gives visibility into the issue\n }\n}\n\n\n\nconst program = new Command();\n\n// Override Commander.js error handling while preserving help/version behavior\nprogram\n .exitOverride((err) => {\n // Only override actual errors, not help/version exits\n if (err.code === 'commander.help' || err.code === 'commander.version' || err.exitCode === 0) {\n process.exit(err.exitCode || 0);\n }\n \n const globalOptions = program.opts();\n \n // Extract the actual error message from Commander.js error\n let message = err.message || 'unknown command error';\n \n // Clean up common Commander.js error messages\n message = message\n .replace(/^error: /, '') // Remove Commander's error prefix\n .replace(/\\n.*/, '') // Keep only the first line\n .replace(/\\.$/, '') // Remove trailing period\n .toLowerCase(); // Make lowercase\n \n // Route through our error function for consistent formatting\n error(message, globalOptions.json, globalOptions.noColor);\n \n // Show help after error (unless in JSON mode)\n if (!globalOptions.json) {\n displayHelp(globalOptions.noColor);\n }\n \n process.exit(err.exitCode || 1);\n })\n .configureOutput({\n // Suppress Commander's default error output - we handle it in exitOverride\n writeErr: (str) => {\n // Only suppress error output, allow help/version to go through\n if (!str.startsWith('error:')) {\n process.stderr.write(str);\n }\n },\n writeOut: (str) => process.stdout.write(str)\n });\n\n// CLI formatting helpers are imported from utils.js\n\n\n/**\n * Display comprehensive help information for all commands\n */\nfunction displayHelp(noColor?: boolean) {\n const applyBold = (text: string) => noColor ? text : bold(text);\n const applyDim = (text: string) => noColor ? text : dim(text);\n \n const output = `${applyBold('USAGE')}\n ship <path> 🚀 Deploy static sites with simplicity\n\n${applyBold('COMMANDS')}\n 📦 ${applyBold('Deployments')}\n ship deployments list List all deployments\n ship deployments create <path> Create deployment from file or directory\n ship deployments get <deployment> Show deployment information\n ship deployments remove <deployment> Delete deployment permanently\n\n 🌎 ${applyBold('Aliases')}\n ship aliases list List all aliases\n ship aliases set <name> <deployment> Create or update alias pointing to deployment\n ship aliases get <name> Show alias information\n ship aliases check <name> Manually trigger DNS check for external alias\n ship aliases remove <name> Delete alias permanently\n\n 🦸 ${applyBold('Account')}\n ship whoami Get current account information\n\n 🛠️ ${applyBold('Completion')}\n ship completion install Install shell completion script\n ship completion uninstall Uninstall shell completion script\n\n${applyBold('FLAGS')}\n --api-key <key> API key for authenticated deployments\n --deploy-token <token> Deploy token for single-use deployments\n --config <file> Custom config file path\n --no-path-detect Disable automatic path optimization and flattening\n --no-spa-detect Disable automatic SPA detection and configuration\n --no-color Disable colored output\n --json Output results in JSON format\n --version Show version information\n\n${applyDim('Please report any issues to https://github.com/shipstatic/ship/issues')}\n`;\n\n console.log(output);\n}\n\n/**\n * Process CLI options using Commander's built-in option merging.\n * Applies CLI-specific transformations and validations.\n */\nfunction processOptions(command: any): any {\n // Use Commander's built-in option merging - much simpler!\n const options = command.opts();\n \n // Convert Commander.js --no-color flag (color: false) to our convention (noColor: true)\n if (options.color === false) {\n options.noColor = true;\n }\n \n // Validate options early\n try {\n if (options.apiKey && typeof options.apiKey === 'string') {\n validateApiKey(options.apiKey);\n }\n \n if (options.deployToken && typeof options.deployToken === 'string') {\n validateDeployToken(options.deployToken);\n }\n \n if (options.apiUrl && typeof options.apiUrl === 'string') {\n validateApiUrl(options.apiUrl);\n }\n } catch (validationError) {\n if (validationError instanceof ShipError) {\n error(validationError.message, options.json, options.noColor);\n process.exit(1);\n }\n throw validationError;\n }\n \n return options;\n}\n\n/**\n * Error handler using ShipError type guards - all errors should be ShipError instances\n */\nfunction handleError(err: any, context?: { operation?: string; resourceType?: string; resourceId?: string }, options?: any) {\n // Always get options from the root program object to ensure global flags are included.\n const opts = program.opts();\n // All errors in this codebase should be ShipError instances\n if (!(err instanceof ShipError)) {\n const message = err.message || err;\n \n if (opts.json) {\n console.error(JSON.stringify({ \n error: message,\n details: { originalError: message }\n }, null, 2));\n console.error();\n } else {\n error(message, opts.json, opts.noColor);\n // Show help after error (unless in JSON mode)\n displayHelp(opts.noColor);\n }\n process.exit(1);\n }\n\n let message = err.message;\n \n // Handle specific error types based on error details\n if (err.details?.data?.error === 'not_found') {\n if (context?.operation === 'remove') {\n const resourceType = context.resourceType || 'resource';\n const resourceId = context.resourceId || '';\n message = `${resourceId} ${resourceType.toLowerCase()} not found`;\n } else {\n // For other operations (like aliases set), use consistent format\n const originalMessage = err.details.data.message || 'Resource not found';\n // Convert \"Deployment X not found\" to \"Deployment not found: X\" format\n const match = originalMessage.match(/^(.*?)\\s+(.+?)\\s+not found$/);\n if (match) {\n const [, resourceType, resourceId] = match;\n message = `${resourceId} ${resourceType.toLowerCase()} not found`;\n } else {\n message = originalMessage;\n }\n }\n }\n // Handle business logic errors with detailed messages\n else if (err.details?.data?.error === 'business_logic_error') {\n message = err.details.data.message || 'Business logic error occurred';\n }\n // User-friendly messages for common error types \n else if (err.isAuthError()) {\n message = 'authentication failed';\n }\n else if (err.isNetworkError()) {\n message = 'network error';\n }\n // For file, validation, and client errors, trust the original message\n // For server errors, provide generic fallback\n else if (!err.isFileError() && !err.isValidationError() && !err.isClientError()) {\n message = 'server error';\n }\n \n if (opts.json) {\n console.error(JSON.stringify({ \n error: message,\n ...(err.details ? { details: err.details } : {})\n }, null, 2));\n console.error();\n } else {\n error(message, opts.json, opts.noColor);\n // Show help for validation errors related to unknown commands\n if (err.isValidationError() && message.includes('unknown command')) {\n displayHelp(opts.noColor);\n }\n // Don't show help for other ShipError instances - these are API/system errors, not user CLI mistakes\n }\n process.exit(1);\n}\n\n/**\n * Wrapper for CLI actions that handles errors and client creation consistently\n * Reduces boilerplate while preserving context for error handling\n */\nfunction withErrorHandling<T extends any[], R>(\n handler: (client: Ship, ...args: T) => Promise<R>,\n context?: { operation?: string; resourceType?: string; getResourceId?: (...args: T) => string }\n) {\n return async function(this: any, ...args: T) {\n try {\n // Get processed options using Commander's built-in merging (including validation!)\n const globalOptions = processOptions(this);\n \n const client = createClient();\n const result = await handler(client, ...args);\n \n // Build context for output if provided\n const outputContext = context ? {\n operation: context.operation,\n resourceType: context.resourceType,\n resourceId: context.getResourceId ? context.getResourceId(...args) : undefined\n } : undefined;\n \n output(result, outputContext, globalOptions);\n } catch (error: any) {\n const errorContext = context ? {\n operation: context.operation,\n resourceType: context.resourceType,\n resourceId: context.getResourceId ? context.getResourceId(...args) : undefined\n } : undefined;\n \n // Get processed options using Commander's built-in merging\n const globalOptions = processOptions(this);\n \n handleError(error, errorContext, globalOptions);\n }\n };\n}\n\n/**\n * Create Ship client with synchronous constructor\n */\nfunction createClient(): Ship {\n const options = program.opts();\n const shipOptions: any = {};\n \n // Only include options that are actually set (not undefined)\n if (options.config !== undefined) {\n shipOptions.configFile = options.config;\n }\n if (options.apiUrl !== undefined) {\n shipOptions.apiUrl = options.apiUrl;\n }\n if (options.apiKey !== undefined) {\n shipOptions.apiKey = options.apiKey;\n }\n if (options.deployToken !== undefined) {\n shipOptions.deployToken = options.deployToken;\n }\n \n // Use synchronous constructor - initialization happens lazily\n return new Ship(shipOptions);\n}\n\n/**\n * Human-readable formatters for different result types\n */\nconst formatters = {\n deployments: (result: any, context?: { operation?: string }, isJson?: boolean, noColor?: boolean) => {\n if (!result.deployments || result.deployments.length === 0) {\n if (isJson) {\n console.log(JSON.stringify({ deployments: [] }, null, 2));\n } else {\n console.log('no deployments found');\n console.log();\n }\n return;\n }\n \n // For deployments list: hide files, size, status, expires for cleaner output\n const listColumns = ['deployment', 'url', 'created'];\n console.log(formatTable(result.deployments, listColumns, noColor));\n },\n aliases: (result: any, context?: { operation?: string }, isJson?: boolean, noColor?: boolean) => {\n if (!result.aliases || result.aliases.length === 0) {\n if (isJson) {\n console.log(JSON.stringify({ aliases: [] }, null, 2));\n } else {\n console.log('no aliases found');\n console.log();\n }\n return;\n }\n \n // For aliases list: hide status, confirmed for cleaner output\n const listColumns = ['alias', 'deployment', 'url', 'created'];\n console.log(formatTable(result.aliases, listColumns, noColor));\n },\n alias: (result: any, context?: { operation?: string }, isJson?: boolean, noColor?: boolean) => {\n // Always show success message for alias operations, particularly 'set'\n if (result.alias) {\n const operation = result.isCreate ? 'created' : 'updated';\n success(`${result.alias} alias ${operation}`, isJson, noColor);\n }\n \n // Show DNS CNAME warning for external aliases that are not confirmed\n if (!isJson && result.alias && result.alias.includes('.') && !result.confirmed) {\n warn(`To complete setup, create a DNS CNAME record pointing ${result.alias} to cname.statichost.com`, isJson, noColor);\n }\n \n console.log(formatDetails(result, noColor));\n },\n deployment: (result: any, context?: { operation?: string }, isJson?: boolean, noColor?: boolean) => {\n // Show success message for create operations only\n if (result.status && context?.operation === 'create') {\n success(`${result.deployment} deployment created ✨`, isJson, noColor);\n }\n console.log(formatDetails(result, noColor));\n },\n email: (result: any, context?: { operation?: string }, isJson?: boolean, noColor?: boolean) => {\n console.log(formatDetails(result, noColor));\n },\n message: (result: any, context?: { operation?: string }, isJson?: boolean, noColor?: boolean) => {\n // Handle messages from operations like DNS check\n if (result.message) {\n success(result.message, isJson, noColor);\n }\n }\n};\n\n/**\n * Common deploy logic used by both shortcut and explicit commands\n */\nasync function performDeploy(client: Ship, path: string, cmdOptions: any, commandContext?: any): Promise<any> {\n // Validate path exists before proceeding\n if (!existsSync(path)) {\n throw ShipError.file(`${path} path does not exist`, path);\n }\n \n // Check if path is a file or directory\n const stats = statSync(path);\n if (!stats.isDirectory() && !stats.isFile()) {\n throw ShipError.file(`${path} path must be a file or directory`, path);\n }\n \n const deployOptions: any = {};\n \n // Handle path detection flag\n if (cmdOptions?.noPathDetect !== undefined) {\n deployOptions.pathDetect = !cmdOptions.noPathDetect;\n }\n \n // Handle SPA detection flag\n if (cmdOptions?.noSpaDetect !== undefined) {\n deployOptions.spaDetect = !cmdOptions.noSpaDetect;\n }\n \n // Set up cancellation support using SDK's built-in AbortController\n const abortController = new AbortController();\n deployOptions.signal = abortController.signal;\n \n // Display upload pending message\n let spinner: any = null;\n \n // Show spinner only in TTY (not piped), not in JSON mode, and not with --no-color (script parsing)\n const globalOptions = commandContext ? processOptions(commandContext) : {};\n if (process.stdout.isTTY && !globalOptions.json && !globalOptions.noColor) {\n const { default: yoctoSpinner } = await import('yocto-spinner');\n spinner = yoctoSpinner({ text: 'uploading…' }).start();\n }\n \n // Handle Ctrl+C by aborting the request\n const sigintHandler = () => {\n abortController.abort();\n if (spinner) spinner.stop();\n process.exit(130);\n };\n process.on('SIGINT', sigintHandler);\n \n try {\n const result = await client.deployments.create(path, deployOptions);\n \n // Cleanup\n process.removeListener('SIGINT', sigintHandler);\n if (spinner) spinner.stop();\n \n return result;\n } catch (error) {\n // Cleanup on error\n process.removeListener('SIGINT', sigintHandler);\n if (spinner) spinner.stop();\n throw error;\n }\n}\n\n/**\n * Format output based on --json flag\n */\nfunction output(result: any, context?: { operation?: string; resourceType?: string; resourceId?: string }, options?: any) {\n const opts = options || program.opts();\n \n // Handle void/undefined results (removal operations)\n if (result === undefined) {\n if (context?.operation === 'remove' && context.resourceType && context.resourceId) {\n success(`${context.resourceId} ${context.resourceType.toLowerCase()} removed`, opts.json, opts.noColor);\n } else {\n success('removed successfully', opts.json, opts.noColor);\n }\n return;\n }\n \n // Handle ping result (boolean or object with success property)\n if (result === true || (result && typeof result === 'object' && result.hasOwnProperty('success'))) {\n const isSuccess = result === true || result.success;\n if (isSuccess) {\n success('api reachable', opts.json, opts.noColor);\n } else {\n error('api unreachable', opts.json, opts.noColor);\n }\n return;\n }\n \n // For regular results in JSON mode, output the raw JSON\n if (opts.json) {\n console.log(JSON.stringify(result, null, 2));\n console.log();\n return;\n }\n \n // Find appropriate formatter based on result properties (non-JSON mode)\n for (const [key, formatter] of Object.entries(formatters)) {\n if (result[key]) {\n formatter(result, context, opts.json, opts.noColor);\n return;\n }\n }\n \n // Default fallback\n success('success', opts.json, opts.noColor);\n}\n\n\n\nprogram\n .name('ship')\n .description('🚀 Deploy static sites with simplicity')\n .version(packageJson.version, '--version', 'Show version information')\n .option('--api-key <key>', 'API key for authenticated deployments')\n .option('--deploy-token <token>', 'Deploy token for single-use deployments')\n .option('--config <file>', 'Custom config file path')\n .option('--api-url <url>', 'API URL (for development)')\n .option('--json', 'Output results in JSON format')\n .option('--no-color', 'Disable colored output')\n .option('--help', 'Display help for command')\n .helpOption(false); // Disable default help\n\n// Handle --help flag manually to show custom help\nprogram.hook('preAction', (thisCommand, actionCommand) => {\n const options = thisCommand.opts();\n if (options.help) {\n const noColor = options.color === false || options.noColor;\n displayHelp(noColor);\n process.exit(0);\n }\n});\n\n// Validate options early - before any action is executed\nprogram.hook('preAction', (thisCommand, actionCommand) => {\n const options = thisCommand.opts();\n \n try {\n if (options.apiKey && typeof options.apiKey === 'string') {\n validateApiKey(options.apiKey);\n }\n \n if (options.deployToken && typeof options.deployToken === 'string') {\n validateDeployToken(options.deployToken);\n }\n \n if (options.apiUrl && typeof options.apiUrl === 'string') {\n validateApiUrl(options.apiUrl);\n }\n } catch (validationError) {\n if (validationError instanceof ShipError) {\n const noColor = options.color === false || options.noColor;\n error(validationError.message, options.json, noColor);\n process.exit(1);\n }\n throw validationError;\n }\n});\n\n// Ping command\nprogram\n .command('ping')\n .description('Check API connectivity')\n .action(withErrorHandling((client) => client.ping()));\n\n// Whoami shortcut - alias for account get\nprogram\n .command('whoami')\n .description('Get current account information')\n .action(withErrorHandling(\n (client) => client.whoami(),\n { operation: 'get', resourceType: 'Account' }\n ));\n\n// Deployments commands\nconst deploymentsCmd = program\n .command('deployments')\n .description('Manage deployments')\n .action((...args) => {\n const globalOptions = processOptions(program);\n \n // Get the command object (last argument)\n const commandObj = args[args.length - 1];\n \n // Check if an unknown subcommand was provided\n if (commandObj && commandObj.args && commandObj.args.length > 0) {\n const unknownArg = commandObj.args.find((arg: string) => !['list', 'create', 'get', 'remove'].includes(arg));\n if (unknownArg) {\n error(`unknown command '${unknownArg}'`, globalOptions.json, globalOptions.noColor);\n }\n }\n \n displayHelp(globalOptions.noColor);\n process.exit(1);\n });\n\ndeploymentsCmd\n .command('list')\n .description('List all deployments')\n .action(withErrorHandling((client) => client.deployments.list()));\n\ndeploymentsCmd\n .command('create <path>')\n .description('Create deployment from file or directory')\n .option('--no-path-detect', 'Disable automatic path optimization and flattening')\n .option('--no-spa-detect', 'Disable automatic SPA detection and configuration')\n .action(withErrorHandling(\n function(this: any, client: Ship, path: string, cmdOptions: any) { \n return performDeploy(client, path, cmdOptions, this);\n },\n { operation: 'create' }\n ));\n\ndeploymentsCmd\n .command('get <deployment>')\n .description('Show deployment information')\n .action(withErrorHandling(\n (client, deployment: string) => client.deployments.get(deployment),\n { operation: 'get', resourceType: 'Deployment', getResourceId: (deployment: string) => deployment }\n ));\n\ndeploymentsCmd\n .command('remove <deployment>')\n .description('Delete deployment permanently')\n .action(withErrorHandling(\n (client, deployment: string) => client.deployments.remove(deployment),\n { operation: 'remove', resourceType: 'Deployment', getResourceId: (deployment: string) => deployment }\n ));\n\n// Aliases commands\nconst aliasesCmd = program\n .command('aliases')\n .description('Manage aliases')\n .action((...args) => {\n const globalOptions = processOptions(program);\n \n // Get the command object (last argument)\n const commandObj = args[args.length - 1];\n \n // Check if an unknown subcommand was provided\n if (commandObj && commandObj.args && commandObj.args.length > 0) {\n const unknownArg = commandObj.args.find((arg: string) => !['list', 'get', 'set', 'remove'].includes(arg));\n if (unknownArg) {\n error(`unknown command '${unknownArg}'`, globalOptions.json, globalOptions.noColor);\n }\n }\n \n displayHelp(globalOptions.noColor);\n process.exit(1);\n });\n\naliasesCmd\n .command('list')\n .description('List all aliases')\n .action(withErrorHandling((client) => client.aliases.list()));\n\naliasesCmd\n .command('get <name>')\n .description('Show alias information')\n .action(withErrorHandling(\n (client, name: string) => client.aliases.get(name),\n { operation: 'get', resourceType: 'Alias', getResourceId: (name: string) => name }\n ));\n\naliasesCmd\n .command('check <name>')\n .description('Manually trigger DNS check for external alias')\n .action(withErrorHandling(\n (client, name: string) => client.aliases.check(name),\n { operation: 'check', resourceType: 'Alias', getResourceId: (name: string) => name }\n ));\n\naliasesCmd\n .command('set <name> <deployment>')\n .description('Create or update alias pointing to deployment')\n .action(withErrorHandling(\n (client: Ship, name: string, deployment: string) => client.aliases.set(name, deployment),\n { operation: 'set', resourceType: 'Alias', getResourceId: (name: string) => name }\n ));\n\naliasesCmd\n .command('remove <name>')\n .description('Delete alias permanently')\n .action(withErrorHandling(\n (client, name: string) => client.aliases.remove(name),\n { operation: 'remove', resourceType: 'Alias', getResourceId: (name: string) => name }\n ));\n\n// Account commands\nconst accountCmd = program\n .command('account')\n .description('Manage account')\n .action((...args) => {\n const globalOptions = processOptions(program);\n \n // Get the command object (last argument)\n const commandObj = args[args.length - 1];\n \n // Check if an unknown subcommand was provided\n if (commandObj && commandObj.args && commandObj.args.length > 0) {\n const unknownArg = commandObj.args.find((arg: string) => !['get'].includes(arg));\n if (unknownArg) {\n error(`unknown command '${unknownArg}'`, globalOptions.json, globalOptions.noColor);\n }\n }\n \n displayHelp(globalOptions.noColor);\n process.exit(1);\n });\n\naccountCmd\n .command('get')\n .description('Show account information')\n .action(withErrorHandling(\n (client) => client.whoami(),\n { operation: 'get', resourceType: 'Account' }\n ));\n\n// Completion commands\nconst completionCmd = program\n .command('completion')\n .description('Setup shell completion')\n .action((...args) => {\n const globalOptions = processOptions(program);\n \n // Get the command object (last argument)\n const commandObj = args[args.length - 1];\n \n // Check if an unknown subcommand was provided\n if (commandObj && commandObj.args && commandObj.args.length > 0) {\n const unknownArg = commandObj.args.find((arg: string) => !['install', 'uninstall'].includes(arg));\n if (unknownArg) {\n error(`unknown command '${unknownArg}'`, globalOptions.json, globalOptions.noColor);\n }\n }\n \n displayHelp(globalOptions.noColor);\n process.exit(1);\n });\n\ncompletionCmd\n .command('install')\n .description('Install shell completion script')\n .action(async () => {\n const shell = process.env.SHELL || '';\n const homeDir = os.homedir();\n let installPath: string;\n let profileFile: string;\n let sourceLine: string = '';\n\n // Resolve the path to the bundled completion scripts\n const bashScriptPath = path.resolve(__dirname, 'completions/ship.bash');\n const zshScriptPath = path.resolve(__dirname, 'completions/ship.zsh');\n const fishScriptPath = path.resolve(__dirname, 'completions/ship.fish');\n\n try {\n if (shell.includes('bash')) {\n installPath = path.join(homeDir, '.ship_completion.bash');\n profileFile = path.join(homeDir, '.bash_profile');\n sourceLine = `# ship\\nsource '${installPath}'\\n# ship end`;\n fs.copyFileSync(bashScriptPath, installPath);\n } else if (shell.includes('zsh')) {\n installPath = path.join(homeDir, '.ship_completion.zsh');\n profileFile = path.join(homeDir, '.zshrc');\n sourceLine = `# ship\\nsource '${installPath}'\\n# ship end`;\n fs.copyFileSync(zshScriptPath, installPath);\n } else if (shell.includes('fish')) {\n const fishCompletionsDir = path.join(homeDir, '.config/fish/completions');\n if (!fs.existsSync(fishCompletionsDir)) {\n fs.mkdirSync(fishCompletionsDir, { recursive: true });\n }\n installPath = path.join(fishCompletionsDir, 'ship.fish');\n fs.copyFileSync(fishScriptPath, installPath);\n const options = program.opts();\n success('fish completion installed successfully', options.json, options.noColor);\n info('please restart your shell to apply the changes', options.json, options.noColor);\n return;\n } else {\n const options = program.opts();\n error(`unsupported shell: ${shell}. could not install completion script`, options.json, options.noColor);\n return;\n }\n\n // For bash and zsh, we need to add sourcing to profile\n const profileExists = fs.existsSync(profileFile);\n if (profileExists) {\n const profileContent = fs.readFileSync(profileFile, 'utf-8');\n if (!profileContent.includes('# ship') || !profileContent.includes('# ship end')) {\n // Ensure there's a newline before our block if file doesn't end with one\n const needsNewline = profileContent.length > 0 && !profileContent.endsWith('\\n');\n const prefix = needsNewline ? '\\n' : '';\n fs.appendFileSync(profileFile, prefix + sourceLine);\n }\n } else {\n fs.writeFileSync(profileFile, sourceLine);\n }\n\n const options = program.opts();\n success(`completion script installed for ${shell.split('/').pop()}`, options.json, options.noColor);\n warn(`run \"source ${profileFile}\" or restart your shell`, options.json, options.noColor);\n } catch (e: any) {\n const options = program.opts();\n error(`could not install completion script: ${e.message}`, options.json, options.noColor);\n if (shell.includes('bash') || shell.includes('zsh')) {\n warn(`add the following line to your profile file manually\\n${sourceLine}`, options.json, options.noColor);\n }\n }\n });\n\ncompletionCmd\n .command('uninstall')\n .description('Uninstall shell completion script')\n .action(async () => {\n const shell = process.env.SHELL || '';\n const homeDir = os.homedir();\n let installPath: string;\n let profileFile: string;\n\n try {\n if (shell.includes('bash')) {\n installPath = path.join(homeDir, '.ship_completion.bash');\n profileFile = path.join(homeDir, '.bash_profile');\n } else if (shell.includes('zsh')) {\n installPath = path.join(homeDir, '.ship_completion.zsh');\n profileFile = path.join(homeDir, '.zshrc');\n } else if (shell.includes('fish')) {\n const fishCompletionsDir = path.join(homeDir, '.config/fish/completions');\n installPath = path.join(fishCompletionsDir, 'ship.fish');\n \n // Remove fish completion file\n const options = program.opts();\n if (fs.existsSync(installPath)) {\n fs.unlinkSync(installPath);\n success('fish completion uninstalled successfully', options.json, options.noColor);\n } else {\n warn('fish completion was not installed', options.json, options.noColor);\n }\n info('please restart your shell to apply the changes', options.json, options.noColor);\n return;\n } else {\n const options = program.opts();\n error(`unsupported shell: ${shell}. could not uninstall completion script`, options.json, options.noColor);\n return;\n }\n\n // Remove completion script file\n if (fs.existsSync(installPath)) {\n fs.unlinkSync(installPath);\n }\n\n // Remove sourcing line from profile\n if (fs.existsSync(profileFile)) {\n const profileContent = fs.readFileSync(profileFile, 'utf-8');\n const lines = profileContent.split('\\n');\n \n // Find and remove the ship block using start/end markers\n const filteredLines: string[] = [];\n let i = 0;\n let removedSomething = false;\n \n while (i < lines.length) {\n const line = lines[i];\n \n // Check if this is the start of a ship block\n if (line.trim() === '# ship') {\n removedSomething = true;\n // Skip all lines until we find the end marker\n i++;\n while (i < lines.length && lines[i].trim() !== '# ship end') {\n i++;\n }\n // Skip the end marker too\n if (i < lines.length && lines[i].trim() === '# ship end') {\n i++;\n }\n } else {\n // Keep this line\n filteredLines.push(line);\n i++;\n }\n }\n \n const options = program.opts();\n if (removedSomething) {\n // Preserve the original file's ending format (with or without final newline)\n const originalEndsWithNewline = profileContent.endsWith('\\n');\n let newContent;\n if (filteredLines.length === 0) {\n newContent = '';\n } else if (originalEndsWithNewline) {\n newContent = filteredLines.join('\\n') + '\\n';\n } else {\n newContent = filteredLines.join('\\n');\n }\n fs.writeFileSync(profileFile, newContent);\n success(`completion script uninstalled for ${shell.split('/').pop()}`, options.json, options.noColor);\n warn(`run \"source ${profileFile}\" or restart your shell`, options.json, options.noColor);\n } else {\n error('completion was not found in profile', options.json, options.noColor);\n }\n } else {\n const options = program.opts();\n error('profile file not found', options.json, options.noColor);\n }\n } catch (e: any) {\n const options = program.opts();\n error(`could not uninstall completion script: ${e.message}`, options.json, options.noColor);\n }\n });\n\n\n// Deploy shortcut as default action\nprogram\n .argument('[path]', 'Path to deploy')\n .option('--no-path-detect', 'Disable automatic path optimization and flattening')\n .option('--no-spa-detect', 'Disable automatic SPA detection and configuration')\n .action(withErrorHandling(\n async function(this: any, client: Ship, path?: string, cmdOptions?: any) {\n if (!path) {\n const globalOptions = program.opts();\n // Convert Commander.js --no-color flag (color: false) to our convention (noColor: true)\n const noColor = globalOptions.color === false || globalOptions.noColor;\n displayHelp(noColor);\n process.exit(0);\n }\n \n // Check if the argument looks like a path (not a command)\n if (!path.includes('/') && !path.startsWith('.') && !path.startsWith('~')) {\n // This looks like an unknown command, not a path\n throw ShipError.validation(`unknown command '${path}'`);\n }\n \n return performDeploy(client, path, cmdOptions, this);\n },\n { operation: 'create' }\n ));\n\n\n\n/**\n * Simple completion handler - no self-invocation, just static completions\n */\nfunction handleCompletion() {\n const args = process.argv;\n const isBash = args.includes('--compbash');\n const isZsh = args.includes('--compzsh');\n const isFish = args.includes('--compfish');\n \n if (!isBash && !isZsh && !isFish) return;\n\n const completions = ['ping', 'whoami', 'deployments', 'aliases', 'account', 'completion'];\n console.log(completions.join(isFish ? '\\n' : ' '));\n process.exit(0);\n}\n\n// Handle completion requests (before any other processing)\nif (process.env.NODE_ENV !== 'test' && (process.argv.includes('--compbash') || process.argv.includes('--compzsh') || process.argv.includes('--compfish'))) {\n handleCompletion();\n}\n\n// Handle main CLI parsing\nif (process.env.NODE_ENV !== 'test') {\n try {\n program.parse(process.argv);\n } catch (err: any) {\n // Commander.js errors are already handled by exitOverride above\n // This catch is just for safety - exitOverride should handle all Commander errors\n if (err.code && err.code.startsWith('commander.')) {\n process.exit(err.exitCode || 1);\n }\n throw err;\n }\n}","/**\n * @file Ship SDK for Node.js environments with full file system support.\n */\n\nimport { Ship as BaseShip } from '../shared/base-ship.js';\nimport { ShipError } from '@shipstatic/types';\nimport { getENV } from '../shared/lib/env.js';\nimport { loadConfig } from './core/config.js';\nimport { resolveConfig } from '../shared/core/config.js';\nimport { setConfig } from './core/platform-config.js';\nimport { ApiHttp } from '../shared/api/http.js';\nimport type { ShipClientOptions, DeployInput, DeploymentOptions, StaticFile } from '../shared/types.js';\n\n// Export all shared functionality\nexport * from '../shared/index.js';\n\n/**\n * Ship SDK Client for Node.js environments.\n * \n * Provides full file system access, configuration file loading,\n * and environment variable support.\n * \n * @example\n * ```typescript\n * // Authenticated deployments with API key\n * const ship = new Ship({ apiKey: \"ship-xxxx\" });\n * \n * // Single-use deployments with deploy token\n * const ship = new Ship({ deployToken: \"token-xxxx\" });\n * \n * // Deploy a directory\n * await ship.deploy('./dist');\n * ```\n */\nexport class Ship extends BaseShip {\n constructor(options: ShipClientOptions = {}) {\n const environment = getENV();\n \n if (environment !== 'node') {\n throw ShipError.business('Node.js Ship class can only be used in Node.js environment.');\n }\n \n super(options);\n }\n\n protected resolveInitialConfig(options: ShipClientOptions): any {\n return resolveConfig(options, {});\n }\n\n protected async loadFullConfig(): Promise<void> {\n try {\n // Load config from file/env\n const loadedConfig = await loadConfig(this.clientOptions.configFile);\n // Re-resolve and re-create the http client with the full config\n const finalConfig = resolveConfig(this.clientOptions, loadedConfig);\n this.http = new ApiHttp({ ...this.clientOptions, ...finalConfig });\n \n const platformConfig = await this.http.getConfig();\n setConfig(platformConfig);\n } catch (error) {\n // Reset initialization promise so it can be retried\n this.initPromise = null;\n throw error;\n }\n }\n\n protected async processInput(input: DeployInput, options: DeploymentOptions): Promise<StaticFile[]> {\n // Validate input type for Node.js environment\n if (!this.#isValidNodeInput(input)) {\n throw ShipError.business('Invalid input type for Node.js environment. Expected string[] file paths.');\n }\n \n // Check for empty array specifically\n if (Array.isArray(input) && input.length === 0) {\n throw ShipError.business('No files to deploy.');\n }\n \n const { convertDeployInput } = await import('./core/prepare-input.js');\n return convertDeployInput(input, options, this.http);\n }\n\n /**\n * Validates that input is appropriate for Node.js environment\n * @private\n */\n #isValidNodeInput(input: DeployInput): boolean {\n // Check for string or string array (file paths)\n if (typeof input === 'string') {\n return true;\n }\n \n if (Array.isArray(input)) {\n // Allow empty arrays (will be handled as \"No files to deploy\") \n // and arrays of strings only\n return input.every(item => typeof item === 'string');\n }\n \n return false;\n }\n}\n\n// Default export (for import Ship from 'ship')\nexport default Ship;\n\n// Node.js specific exports\nexport { loadConfig } from './core/config.js';\nexport { setConfig, getCurrentConfig } from './core/platform-config.js';\n\n// Node.js utilities\nexport { processFilesForNode } from './core/node-files.js';\nexport { __setTestEnvironment, getENV } from '../shared/lib/env.js';","/**\n * @file Manages HTTP requests to the Ship API using native fetch.\n */\nimport * as _mime from 'mime-types';\nimport type { \n Deployment, \n DeploymentListResponse, \n PingResponse, \n ConfigResponse, \n DeploymentRemoveResponse, \n Alias, \n AliasListResponse, \n Account, \n SPACheckRequest, \n SPACheckResponse,\n StaticFile\n} from '@shipstatic/types';\nimport type { ApiDeployOptions, ShipClientOptions } from '../types.js';\nimport { ShipError, DEFAULT_API } from '@shipstatic/types';\n\nimport { getENV } from '../lib/env.js';\n\n// FormData and File types for Node.js environment\n/**\n * Internal type alias for Node.js FormData implementation used during file deploys.\n * @internal\n */\ntype FormDataNode = any;\n/**\n * Internal type alias for Node.js File implementation used during file deploys.\n * @internal\n */\ntype FileNode = any;\n\n/** Default API host URL if not otherwise configured. */\n/** @internal */\nconst DEPLOY_ENDPOINT = '/deployments';\n/** @internal */\nconst PING_ENDPOINT = '/ping';\n/** @internal */\nconst ALIASES_ENDPOINT = '/aliases';\n/** @internal */\nconst CONFIG_ENDPOINT = '/config';\n/** @internal */\nconst ACCOUNT_ENDPOINT = '/account';\n/** @internal */\nconst SPA_CHECK_ENDPOINT = '/spa-check';\n\n/**\n * Determines the MIME type for a given file (File object or path string) in browser environments.\n * Falls back to 'application/octet-stream' if type cannot be determined.\n * @internal\n * @param file - File object or file path string.\n * @returns The MIME type as a string.\n */\nfunction getBrowserContentType(file: File | string): string {\n if (typeof file === 'string') {\n return _mime.lookup(file) || 'application/octet-stream';\n } else {\n return _mime.lookup(file.name) || file.type || 'application/octet-stream';\n }\n}\n\n/**\n * Collects all items from an AsyncIterable into an array.\n * Useful for converting streaming multipart encoders to Buffer arrays.\n * @internal\n * @template T - The item type yielded by the iterable.\n * @param iterable - The async iterable to collect.\n * @returns A promise resolving to an array of all items.\n */\nasync function collectAsyncIterable<T>(iterable: AsyncIterable<T>): Promise<T[]> {\n const result: T[] = [];\n for await (const x of iterable) {\n result.push(x);\n }\n return result;\n}\n\n/**\n * Handles direct HTTP communication with the Ship API, including deploys and health checks.\n * Responsible for constructing requests, managing authentication, and error translation.\n * @internal\n */\nexport class ApiHttp {\n private readonly apiUrl: string;\n private readonly apiKey: string;\n private readonly deployToken: string;\n\n /**\n * Constructs a new ApiHttp instance with the provided client options.\n * @param options - Client options including API host, authentication credentials, and timeout settings.\n */\n constructor(options: ShipClientOptions) {\n this.apiUrl = options.apiUrl || DEFAULT_API;\n this.apiKey = options.apiKey ?? \"\";\n this.deployToken = options.deployToken ?? \"\";\n }\n\n /**\n * Generates common headers for API requests, including authentication credentials if present.\n * Deploy tokens take precedence over API keys for single-use deployments.\n * @param customHeaders - Optional additional headers to include.\n * @returns Object containing merged headers.\n * @private\n */\n #getAuthHeaders(customHeaders: Record<string, string> = {}): Record<string, string> {\n const headers = { ...customHeaders };\n \n // Deploy tokens take precedence for single-use deployments\n if (this.deployToken) {\n headers['Authorization'] = `Bearer ${this.deployToken}`;\n } else if (this.apiKey) {\n headers['Authorization'] = `Bearer ${this.apiKey}`;\n }\n \n return headers;\n }\n\n /**\n * Low-level fetch wrapper with authentication - used only by #request method.\n * This method only handles the raw fetch request with auth headers.\n * @param url - Request URL\n * @param options - Fetch options\n * @param operationName - Name of operation for error messages\n * @returns Promise resolving to Response object\n * @private\n */\n async #fetchWithAuth(url: string, options: RequestInit = {}, operationName: string): Promise<Response> {\n const headers = this.#getAuthHeaders(options.headers as Record<string, string>);\n \n const fetchOptions: RequestInit = {\n ...options,\n headers,\n };\n\n // If no apiKey, deployToken, or Authorization header is provided, attempt to use cookie-based authentication\n const hasInstanceCredentials = !!(this.apiKey || this.deployToken);\n const hasAuthorizationHeader = !!(headers as any)?.Authorization;\n \n if (!hasInstanceCredentials && !hasAuthorizationHeader) {\n fetchOptions.credentials = 'include';\n }\n\n try {\n const response = await fetch(url, fetchOptions);\n return response;\n } catch (error: any) {\n this.#handleFetchError(error, operationName);\n // This line is unreachable because #handleFetchError always throws\n throw error;\n }\n }\n\n /**\n * Unified HTTP request helper that handles the complete request lifecycle.\n * Makes authenticated requests, checks response status, and handles all errors.\n * Automatically determines whether to parse JSON based on response headers.\n * @param url - Request URL\n * @param options - Fetch options \n * @param operationName - Name of operation for error messages\n * @returns Promise resolving to parsed JSON response or undefined for empty responses\n * @throws {ShipError} Various ShipError types based on the failure mode\n * @private\n */\n async #request<T>(url: string, options: RequestInit = {}, operationName: string): Promise<T> {\n try {\n const response = await this.#fetchWithAuth(url, options, operationName);\n \n if (!response.ok) {\n await this.#handleResponseError(response, operationName);\n }\n \n // Check if response has content to parse\n const contentLength = response.headers.get('Content-Length');\n if (contentLength === '0' || response.status === 204) {\n return undefined as T; // Return undefined for empty responses\n }\n \n return await response.json() as T;\n } catch (error: any) {\n if (error instanceof ShipError) {\n throw error;\n }\n this.#handleFetchError(error, operationName);\n // This line is unreachable because #handleFetchError always throws\n throw error;\n }\n }\n \n /**\n * Sends a ping request to the Ship API server to verify connectivity and authentication.\n * @returns Promise resolving to `true` if the ping is successful, `false` otherwise.\n * @throws {ShipApiError} If the API returns an error response (4xx, 5xx).\n * @throws {ShipNetworkError} If a network error occurs (e.g., DNS failure, connection refused).\n */\n public async ping(): Promise<boolean> {\n const data = await this.#request<PingResponse>(`${this.apiUrl}${PING_ENDPOINT}`, { method: 'GET' }, 'Ping');\n return data?.success || false;\n }\n\n /**\n * Get full ping response from the API server\n * @returns Promise resolving to the full PingResponse object.\n */\n public async getPingResponse(): Promise<PingResponse> {\n return await this.#request<PingResponse>(`${this.apiUrl}${PING_ENDPOINT}`, { method: 'GET' }, 'Ping');\n }\n\n /**\n * Fetches platform configuration from the API.\n * @returns Promise resolving to the config response.\n * @throws {ShipError} If the config request fails.\n */\n public async getConfig(): Promise<ConfigResponse> {\n return await this.#request<ConfigResponse>(`${this.apiUrl}${CONFIG_ENDPOINT}`, { method: 'GET' }, 'Config');\n }\n\n /**\n * Deploys an array of StaticFile objects to the Ship API.\n * Constructs and sends a multipart/form-data POST request, handling both browser and Node.js environments.\n * Validates files and manages deploy progress and error translation.\n * @param files - Array of StaticFile objects to deploy (must include MD5 checksums).\n * @param options - Optional per-deploy configuration (overrides instance defaults).\n * @returns Promise resolving to a full Deployment object on success.\n * @throws {ShipFileError} If a file is missing an MD5 checksum or content type is unsupported.\n * @throws {ShipClientError} If no files are provided or if environment is unknown.\n * @throws {ShipNetworkError} If a network error occurs during deploy.\n * @throws {ShipApiError} If the API returns an error response.\n * @throws {ShipCancelledError} If the deploy is cancelled via an AbortSignal.\n */\n public async deploy(\n files: StaticFile[],\n options: ApiDeployOptions = {}\n ): Promise<Deployment> {\n this.#validateFiles(files);\n\n const {\n apiUrl = this.apiUrl,\n signal,\n apiKey,\n deployToken\n } = options;\n\n const { requestBody, requestHeaders } = await this.#prepareRequestPayload(files);\n \n // Override auth headers if per-deploy credentials are provided\n // Deploy tokens take precedence over API keys\n let authHeaders = {};\n if (deployToken) {\n authHeaders = { 'Authorization': `Bearer ${deployToken}` };\n } else if (apiKey) {\n authHeaders = { 'Authorization': `Bearer ${apiKey}` };\n }\n \n const fetchOptions: RequestInit = {\n method: 'POST',\n body: requestBody,\n headers: { ...requestHeaders, ...authHeaders },\n signal: signal || null\n };\n\n // Use unified request method to eliminate duplication\n return await this.#request<Deployment>(`${apiUrl}${DEPLOY_ENDPOINT}`, fetchOptions, 'Deploy');\n }\n \n /**\n * Validates the files array for deploy requirements.\n * Ensures all files have MD5 checksums and at least one file is present.\n * @param files - Files to validate.\n * @throws {ShipFileError} If a file is missing an MD5 checksum.\n * @throws {ShipClientError} If no files are provided.\n * @private\n */\n #validateFiles(files: StaticFile[]): void {\n if (!files.length) {\n throw ShipError.business('No files to deploy.');\n }\n \n for (const file of files) {\n if (!file.md5) {\n throw ShipError.file(`MD5 checksum missing for file: ${file.path}`, file.path);\n }\n }\n }\n\n\n /**\n * Prepares the request payload (body and headers) for deploy based on execution environment.\n * Selects browser or Node.js multipart construction as needed.\n * @param files - Files to deploy.\n * @returns Promise resolving to request body and headers.\n * @private\n */\n async #prepareRequestPayload(files: StaticFile[]): Promise<{\n requestBody: FormData | ArrayBuffer;\n requestHeaders: Record<string, string>;\n }> {\n let requestBody: FormData | ArrayBuffer;\n let requestHeaders: Record<string, string> = {};\n \n if (getENV() === 'browser') {\n requestBody = this.#createBrowserBody(files);\n } else if (getENV() === 'node') {\n const { body, headers } = await this.#createNodeBody(files);\n requestBody = body.buffer.slice(body.byteOffset, body.byteOffset + body.byteLength) as ArrayBuffer;\n requestHeaders = headers;\n } else {\n throw ShipError.business('Unknown or unsupported execution environment');\n }\n \n return { requestBody, requestHeaders };\n }\n\n /**\n * Creates a FormData object for browser environments, populating it with files and checksums.\n * @param files - Array of StaticFile objects to include in the FormData.\n * @returns FormData object ready for transmission.\n * @throws {ShipFileError} If file content is of an unsupported type for browser FormData.\n * @private\n */\n #createBrowserBody(files: StaticFile[]): FormData {\n const formData = new FormData();\n const checksums: string[] = [];\n \n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n let fileContent: File | Blob;\n \n if (file.content instanceof File || file.content instanceof Blob) {\n fileContent = file.content;\n } else {\n throw ShipError.file(`Unsupported file.content type for browser FormData: ${file.path}`, file.path);\n }\n \n const contentType = getBrowserContentType(fileContent instanceof File ? fileContent : file.path);\n const fileWithPath = new File([fileContent], file.path, { type: contentType });\n formData.append('files[]', fileWithPath);\n checksums.push(file.md5!);\n }\n \n // Add checksums as JSON array\n formData.append('checksums', JSON.stringify(checksums));\n return formData;\n }\n\n /**\n * Creates the multipart request body (Buffer) and headers for Node.js environments using formdata-node and form-data-encoder.\n * @param files - Array of StaticFile objects to include in the multipart body.\n * @returns Promise resolving to an object with the body Buffer and headers.\n * @throws {ShipFileError} If file content is of an unsupported type for Node.js FormData.\n * @private\n */\n async #createNodeBody(files: StaticFile[]): Promise<{body: Buffer, headers: Record<string, string>}> {\n const { FormData: FormDataNodeClass, File: FileNodeClass } = await import('formdata-node');\n const { FormDataEncoder: FormDataEncoderClass } = await import('form-data-encoder');\n const pathImport = await import('path');\n const formDataNodeInstance: FormDataNode = new FormDataNodeClass();\n const checksums: string[] = [];\n\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n const contentType = _mime.lookup(file.path) || 'application/octet-stream';\n let fileNodeInstance: FileNode;\n\n if (Buffer.isBuffer(file.content)) {\n fileNodeInstance = new FileNodeClass([file.content], file.path, { type: contentType });\n } else if (typeof Blob !== \"undefined\" && file.content instanceof Blob) {\n fileNodeInstance = new FileNodeClass([file.content], file.path, { type: contentType });\n } else {\n throw ShipError.file(`Unsupported file.content type for Node.js FormData: ${file.path}`, file.path);\n }\n const preservedPath = file.path.startsWith('/') ? file.path : '/' + file.path;\n formDataNodeInstance.append('files[]', fileNodeInstance, preservedPath);\n checksums.push(file.md5!);\n }\n\n // Add checksums as JSON array\n formDataNodeInstance.append('checksums', JSON.stringify(checksums));\n\n const encoder = new FormDataEncoderClass(formDataNodeInstance);\n const encodedChunks = await collectAsyncIterable(encoder.encode());\n const body = Buffer.concat(encodedChunks.map(chunk => Buffer.from(chunk as Uint8Array)));\n\n const headers = {\n 'Content-Type': encoder.contentType,\n 'Content-Length': Buffer.byteLength(body).toString()\n };\n return { body, headers };\n }\n\n /**\n * Handles fetch response errors and throws appropriate ShipError types.\n * @param response - Fetch Response object with error status\n * @param operationName - Name of the failed operation\n * @throws {ShipApiError} Always throws with API error details\n * @private\n */\n async #handleResponseError(response: Response, operationName: string): Promise<never> {\n let errorData: any = {};\n try {\n const contentType = response.headers.get('content-type');\n if (contentType && contentType.includes('application/json')) {\n errorData = await response.json();\n } else {\n errorData = { message: await response.text() };\n }\n } catch {\n errorData = { message: 'Failed to parse error response' };\n }\n\n // Handle structured error responses (with error field, code, or message)\n if (errorData.error || errorData.code || errorData.message) {\n // Use message if available, otherwise use the error field as the message, or fallback\n const message = errorData.message || errorData.error || `${operationName} failed due to API error`;\n \n // Handle authentication errors specifically\n if (response.status === 401) {\n throw ShipError.authentication(message);\n }\n \n throw ShipError.api(\n message,\n response.status,\n errorData.code,\n errorData\n );\n }\n\n // Fallback for completely unstructured errors\n // Handle authentication errors specifically for unstructured responses too\n if (response.status === 401) {\n throw ShipError.authentication(`Authentication failed for ${operationName}`);\n }\n \n throw ShipError.api(\n `${operationName} failed due to API error`,\n response.status,\n undefined,\n errorData\n );\n }\n\n /**\n * Translates fetch errors into appropriate ShipError types and always throws.\n * Intended for use in catch blocks of API requests; never returns.\n * @param error - The error object caught from fetch.\n * @param operationName - Name of the failed operation (e.g., 'Deploy', 'Ping').\n * @throws {ShipCancelledError} If the request was cancelled.\n * @throws {ShipNetworkError} If a network error occurred (DNS failure, connection refused).\n * @throws {ShipClientError} For other unexpected errors.\n * @private\n */\n #handleFetchError(error: any, operationName: string): never {\n if (error.name === 'AbortError') {\n throw ShipError.cancelled(`${operationName} operation was cancelled.`);\n }\n if (error instanceof TypeError && error.message.includes('fetch')) {\n throw ShipError.network(`${operationName} failed due to network error: ${error.message}`, error);\n }\n if (error instanceof ShipError) {\n throw error;\n }\n throw ShipError.business(`An unexpected error occurred during ${operationName}: ${error.message || 'Unknown error'}`);\n }\n\n /**\n * Lists all deployments for the authenticated account\n * @returns Promise resolving to deployment list response\n */\n public async listDeployments(): Promise<DeploymentListResponse> {\n return await this.#request<DeploymentListResponse>(`${this.apiUrl}${DEPLOY_ENDPOINT}`, { method: 'GET' }, 'List Deployments');\n }\n\n /**\n * Gets a specific deployment by ID\n * @param id - Deployment ID to retrieve\n * @returns Promise resolving to deployment details\n */\n public async getDeployment(id: string): Promise<Deployment> {\n return await this.#request<Deployment>(`${this.apiUrl}${DEPLOY_ENDPOINT}/${id}`, { method: 'GET' }, 'Get Deployment');\n }\n\n /**\n * Removes a deployment by ID\n * @param id - Deployment ID to remove\n * @returns Promise resolving when removal is complete\n */\n public async removeDeployment(id: string): Promise<void> {\n await this.#request<DeploymentRemoveResponse>(`${this.apiUrl}${DEPLOY_ENDPOINT}/${id}`, { method: 'DELETE' }, 'Remove Deployment');\n }\n\n /**\n * Sets an alias (create or update)\n * @param name - Alias name\n * @param deployment - Deployment name to point to\n * @returns Promise resolving to the created/updated alias with operation context\n */\n public async setAlias(name: string, deployment: string): Promise<import('@shipstatic/types').Alias> {\n try {\n const response = await this.#fetchWithAuth(`${this.apiUrl}${ALIASES_ENDPOINT}/${encodeURIComponent(name)}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ deployment: deployment })\n }, 'Set Alias');\n \n if (!response.ok) {\n await this.#handleResponseError(response, 'Set Alias');\n }\n \n const alias = await response.json() as import('@shipstatic/types').Alias;\n \n // 201 = created, 200 = updated\n return {\n ...alias,\n isCreate: response.status === 201\n };\n } catch (error: any) {\n this.#handleFetchError(error, 'Set Alias');\n }\n }\n\n /**\n * Gets a specific alias by name\n * @param name - Alias name to retrieve\n * @returns Promise resolving to alias details\n */\n public async getAlias(name: string): Promise<Alias> {\n return await this.#request<Alias>(`${this.apiUrl}${ALIASES_ENDPOINT}/${encodeURIComponent(name)}`, { method: 'GET' }, 'Get Alias');\n }\n\n /**\n * Lists all aliases for the authenticated account\n * @returns Promise resolving to alias list response\n */\n public async listAliases(): Promise<AliasListResponse> {\n return await this.#request<AliasListResponse>(`${this.apiUrl}${ALIASES_ENDPOINT}`, { method: 'GET' }, 'List Aliases');\n }\n\n /**\n * Removes an alias by name\n * @param name - Alias name to remove\n * @returns Promise resolving to removal confirmation\n */\n public async removeAlias(name: string): Promise<void> {\n await this.#request<void>(`${this.apiUrl}${ALIASES_ENDPOINT}/${encodeURIComponent(name)}`, { method: 'DELETE' }, 'Remove Alias');\n }\n\n /**\n * Triggers a manual DNS check for an external alias\n * @param name - Alias name to check DNS for\n * @returns Promise resolving to confirmation message\n */\n public async checkAlias(name: string): Promise<{ message: string }> {\n return await this.#request<{ message: string }>(`${this.apiUrl}${ALIASES_ENDPOINT}/${encodeURIComponent(name)}/dns-check`, { method: 'POST' }, 'Check Alias');\n }\n\n /**\n * Gets account details for the authenticated user\n * @returns Promise resolving to account details\n */\n public async getAccount(): Promise<Account> {\n return await this.#request<Account>(`${this.apiUrl}${ACCOUNT_ENDPOINT}`, { method: 'GET' }, 'Get Account');\n }\n\n /**\n * Checks if files represent a SPA structure using AI analysis\n * @param files - Array of StaticFile objects to analyze\n * @returns Promise resolving to boolean indicating if it's a SPA\n */\n public async checkSPA(files: StaticFile[]): Promise<boolean> {\n // Find index.html and extract its content - required for SPA detection\n const indexFile = files.find(f => f.path === 'index.html' || f.path === '/index.html');\n if (!indexFile) {\n return false; // No index.html = not a SPA\n }\n \n // Skip if index.html is too large (unlikely to be a SPA)\n const MAX_INDEX_SIZE = 100 * 1024; // 100KB\n if (indexFile.size > MAX_INDEX_SIZE) {\n return false; // Very large index.html = likely not a SPA\n }\n \n let indexContent: string;\n // Check for Buffer in Node.js environment first (Buffer is not available in browser)\n if (typeof Buffer !== 'undefined' && Buffer.isBuffer(indexFile.content)) {\n indexContent = indexFile.content.toString('utf-8');\n } else if (typeof Blob !== 'undefined' && indexFile.content instanceof Blob) {\n indexContent = await indexFile.content.text();\n } else if (typeof File !== 'undefined' && indexFile.content instanceof File) {\n indexContent = await indexFile.content.text();\n } else {\n return false; // Unsupported content type\n }\n \n // Build file paths list\n const filePaths = files.map(file => file.path);\n \n const requestData: SPACheckRequest = {\n files: filePaths,\n index: indexContent\n };\n \n const response = await this.#request<SPACheckResponse>(\n `${this.apiUrl}${SPA_CHECK_ENDPOINT}`, \n { \n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(requestData)\n }, \n 'SPA Check'\n );\n return response.isSPA;\n }\n}\n","/**\n * @file Shared configuration logic for both environments.\n */\n\nimport { DEFAULT_API, type PlatformConfig } from '@shipstatic/types';\nimport type { ShipClientOptions, DeploymentOptions } from '../types.js';\nimport { getENV } from '../lib/env.js';\n\n// Re-export for backward compatibility\nexport type Config = PlatformConfig;\n\n/**\n * Cross-environment config loader that dispatches to appropriate implementation.\n */\nexport async function loadConfig(configFile?: string): Promise<Config> {\n const env = getENV();\n \n if (env === 'browser') {\n // In browser, return empty config (no file system access)\n return {};\n } else if (env === 'node') {\n // In Node.js, load from environment and files\n const { loadConfig: nodeLoadConfig } = await import('../../node/core/config.js');\n return nodeLoadConfig(configFile);\n } else {\n // Fallback to empty config for unknown environments\n return {};\n }\n}\n\n/**\n * Universal configuration resolver for all environments.\n * This is the single source of truth for config resolution.\n */\nexport function resolveConfig(\n userOptions: ShipClientOptions = {}, \n loadedConfig: Partial<ShipClientOptions> = {}\n): { apiUrl: string; apiKey?: string; deployToken?: string } {\n const finalConfig = {\n apiUrl: userOptions.apiUrl || loadedConfig.apiUrl || DEFAULT_API,\n apiKey: userOptions.apiKey !== undefined ? userOptions.apiKey : loadedConfig.apiKey,\n deployToken: userOptions.deployToken !== undefined ? userOptions.deployToken : loadedConfig.deployToken,\n };\n\n const result: { apiUrl: string; apiKey?: string; deployToken?: string } = {\n apiUrl: finalConfig.apiUrl\n };\n \n if (finalConfig.apiKey !== undefined) result.apiKey = finalConfig.apiKey;\n if (finalConfig.deployToken !== undefined) result.deployToken = finalConfig.deployToken;\n \n return result;\n}\n\n/**\n * Merge deployment options with client defaults.\n * This is shared logic used by both environments.\n */\nexport function mergeDeployOptions(\n options: DeploymentOptions, \n clientDefaults: ShipClientOptions\n): DeploymentOptions {\n const result: DeploymentOptions = { ...options };\n \n // Only add defined values from client defaults\n if (result.apiUrl === undefined && clientDefaults.apiUrl !== undefined) {\n result.apiUrl = clientDefaults.apiUrl;\n }\n if (result.apiKey === undefined && clientDefaults.apiKey !== undefined) {\n result.apiKey = clientDefaults.apiKey;\n }\n if (result.deployToken === undefined && clientDefaults.deployToken !== undefined) {\n result.deployToken = clientDefaults.deployToken;\n }\n if (result.timeout === undefined && clientDefaults.timeout !== undefined) {\n result.timeout = clientDefaults.timeout;\n }\n if (result.maxConcurrency === undefined && clientDefaults.maxConcurrency !== undefined) {\n result.maxConcurrency = clientDefaults.maxConcurrency;\n }\n if (result.onProgress === undefined && clientDefaults.onProgress !== undefined) {\n result.onProgress = clientDefaults.onProgress;\n }\n if (result.onProgressStats === undefined && clientDefaults.onProgressStats !== undefined) {\n result.onProgressStats = clientDefaults.onProgressStats;\n }\n \n return result;\n}","/**\n * @file Shared SPA detection utilities for both environments.\n * \n * Provides SPA detection and auto-configuration functionality\n * that can be used by both Node.js and browser environments.\n */\n\nimport { DEPLOYMENT_CONFIG_FILENAME } from '@shipstatic/types';\nimport { calculateMD5 } from './md5.js';\nimport type { StaticFile, DeploymentOptions } from '../types.js';\nimport type { ApiHttp } from '../api/http.js';\n\n/**\n * Creates ship.json configuration for SPA projects.\n * @returns Promise resolving to StaticFile with SPA configuration\n */\nexport async function createSPAConfig(): Promise<StaticFile> {\n const config = {\n \"rewrites\": [{\n \"source\": \"/(.*)\",\n \"destination\": \"/index.html\"\n }]\n };\n \n const configString = JSON.stringify(config, null, 2);\n \n // Create content that works in both browser and Node.js environments\n let content: Buffer | Blob;\n if (typeof Buffer !== 'undefined') {\n // Node.js environment\n content = Buffer.from(configString, 'utf-8');\n } else {\n // Browser environment\n content = new Blob([configString], { type: 'application/json' });\n }\n \n const { md5 } = await calculateMD5(content);\n \n return {\n path: DEPLOYMENT_CONFIG_FILENAME,\n content,\n size: configString.length,\n md5\n };\n}\n\n/**\n * Detects SPA projects and auto-generates configuration.\n * This function can be used by both Node.js and browser environments.\n * \n * @param files - Array of StaticFiles to analyze\n * @param apiClient - HTTP client for API communication\n * @param options - Deployment options containing SPA detection settings\n * @returns Promise resolving to files array with optional SPA config added\n */\nexport async function detectAndConfigureSPA(\n files: StaticFile[], \n apiClient: ApiHttp, \n options: DeploymentOptions\n): Promise<StaticFile[]> {\n // Skip if disabled or config already exists\n if (options.spaDetect === false || files.some(f => f.path === DEPLOYMENT_CONFIG_FILENAME)) {\n return files;\n }\n \n try {\n const isSPA = await apiClient.checkSPA(files);\n \n if (isSPA) {\n const spaConfig = await createSPAConfig();\n return [...files, spaConfig];\n }\n } catch (error) {\n // SPA detection failed, continue silently without auto-config\n }\n \n return files;\n}","/**\n * @file All Ship SDK resources in one place - impossibly simple.\n */\nimport type { \n Deployment, \n DeploymentListResponse, \n Alias, \n AliasListResponse, \n Account,\n StaticFile,\n DeployInput,\n DeploymentResource,\n AliasResource,\n AccountResource\n} from '@shipstatic/types';\nimport type { ApiHttp } from './api/http.js';\nimport type { ShipClientOptions, DeploymentOptions } from './types.js';\nimport { mergeDeployOptions } from './core/config.js';\nimport { detectAndConfigureSPA } from './lib/prepare-input.js';\n\n// Re-export DeployInput for external use\nexport type { DeployInput };\n\nexport function createDeploymentResource(\n getApi: () => ApiHttp, \n clientDefaults?: ShipClientOptions,\n ensureInit?: () => Promise<void>,\n processInput?: (input: DeployInput, options: DeploymentOptions) => Promise<StaticFile[]>\n): DeploymentResource {\n return {\n create: async (input: DeployInput, options: DeploymentOptions = {}) => {\n // Ensure full initialization before proceeding\n if (ensureInit) await ensureInit();\n \n // Merge user options with client defaults\n const mergedOptions = clientDefaults \n ? mergeDeployOptions(options, clientDefaults)\n : options;\n \n // Get API client AFTER initialization is complete to avoid race conditions\n const apiClient = getApi();\n \n // Use environment-specific input processing\n if (!processInput) {\n throw new Error('processInput function is not provided.');\n }\n \n // 1. Process input from the specific environment\n let staticFiles: StaticFile[] = await processInput(input, mergedOptions);\n \n // 2. 🆕 Apply SPA detection universally here (works for both Node.js and Browser!)\n staticFiles = await detectAndConfigureSPA(staticFiles, apiClient, mergedOptions);\n \n // 3. Deploy using the API - now returns the full Deployment object directly\n return await apiClient.deploy(staticFiles, mergedOptions);\n },\n\n list: async () => {\n if (ensureInit) await ensureInit();\n return getApi().listDeployments();\n },\n\n remove: async (id: string) => {\n if (ensureInit) await ensureInit();\n await getApi().removeDeployment(id);\n // Return void for deletion operations\n },\n\n get: async (id: string) => {\n if (ensureInit) await ensureInit();\n return getApi().getDeployment(id);\n }\n };\n}\n\n// =============================================================================\n// ALIAS RESOURCE\n// =============================================================================\n\nexport function createAliasResource(getApi: () => ApiHttp, ensureInit?: () => Promise<void>): AliasResource {\n return {\n set: async (aliasName: string, deployment: string) => {\n if (ensureInit) await ensureInit();\n // Set alias and return the created/updated alias directly\n return getApi().setAlias(aliasName, deployment);\n },\n\n get: async (aliasName: string) => {\n if (ensureInit) await ensureInit();\n return getApi().getAlias(aliasName);\n },\n\n list: async () => {\n if (ensureInit) await ensureInit();\n return getApi().listAliases();\n },\n\n remove: async (aliasName: string) => {\n if (ensureInit) await ensureInit();\n await getApi().removeAlias(aliasName);\n // Return void for deletion operations\n },\n\n check: async (aliasName: string) => {\n if (ensureInit) await ensureInit();\n return getApi().checkAlias(aliasName);\n }\n };\n}\n\n// =============================================================================\n// ACCOUNT RESOURCE\n// =============================================================================\n\nexport function createAccountResource(getApi: () => ApiHttp, ensureInit?: () => Promise<void>): AccountResource {\n return {\n get: async () => {\n if (ensureInit) await ensureInit();\n return getApi().getAccount();\n }\n };\n}\n\n","/**\n * @file Base Ship SDK class - provides shared functionality across environments.\n */\n\nimport { ApiHttp } from './api/http.js';\nimport { ShipError } from '@shipstatic/types';\nimport type { ShipClientOptions } from './types.js';\nimport type { Deployment } from '@shipstatic/types';\n\n// Resource imports\nimport { \n createDeploymentResource, \n createAliasResource, \n createAccountResource,\n type DeployInput\n} from './resources.js';\nimport type { \n DeploymentResource, \n AliasResource, \n AccountResource\n} from '@shipstatic/types';\n\nimport type { StaticFile } from '@shipstatic/types';\nimport type { DeploymentOptions } from './types.js';\n\n/**\n * Abstract base class for Ship SDK implementations.\n * \n * Provides shared functionality while allowing environment-specific\n * implementations to handle configuration loading and deployment processing.\n */\nexport abstract class Ship {\n protected http: ApiHttp;\n protected readonly clientOptions: ShipClientOptions;\n protected initPromise: Promise<void> | null = null;\n \n // Resource instances (initialized during creation)\n protected _deployments: DeploymentResource;\n protected _aliases: AliasResource;\n protected _account: AccountResource;\n\n constructor(options: ShipClientOptions = {}) {\n this.clientOptions = options;\n \n // Initialize HTTP client with constructor options for immediate use\n const config = this.resolveInitialConfig(options);\n this.http = new ApiHttp({ ...options, ...config });\n \n // Initialize resources with lazy loading support\n const initCallback = () => this.ensureInitialized();\n const getApi = () => this.http;\n \n // Pass the processInput method to deployment resource\n this._deployments = createDeploymentResource(\n getApi, \n this.clientOptions, \n initCallback,\n (input, options) => this.processInput(input, options)\n );\n this._aliases = createAliasResource(getApi, initCallback);\n this._account = createAccountResource(getApi, initCallback);\n }\n\n // Abstract methods that environments must implement\n protected abstract resolveInitialConfig(options: ShipClientOptions): any;\n protected abstract loadFullConfig(): Promise<void>;\n protected abstract processInput(input: DeployInput, options: DeploymentOptions): Promise<StaticFile[]>;\n\n /**\n * Ensure full initialization is complete - called lazily by resources\n */\n protected async ensureInitialized(): Promise<void> {\n if (!this.initPromise) {\n this.initPromise = this.loadFullConfig();\n }\n return this.initPromise;\n }\n\n /**\n * Ping the API server to check connectivity\n */\n async ping(): Promise<boolean> {\n await this.ensureInitialized();\n return this.http.ping();\n }\n\n /**\n * Deploy project (convenience shortcut to ship.deployments.create())\n */\n async deploy(input: DeployInput, options?: DeploymentOptions): Promise<Deployment> {\n return this.deployments.create(input, options);\n }\n\n /**\n * Get current account information (convenience shortcut to ship.account.get())\n */\n async whoami() {\n return this.account.get();\n }\n\n /**\n * Get deployments resource (environment-specific)\n */\n get deployments(): DeploymentResource {\n return this._deployments;\n }\n \n /**\n * Get aliases resource\n */\n get aliases(): AliasResource {\n return this._aliases;\n }\n \n /**\n * Get account resource\n */\n get account(): AccountResource {\n return this._account;\n }\n \n}","/**\n * @file Shared SDK exports - environment agnostic.\n */\n\n// Core functionality\nexport * from './resources.js';\nexport * from './types.js';\nexport * from './api/http.js';\nexport * from './core/constants.js';\nexport * from './core/config.js';\nexport { Ship } from './base-ship.js';\n\n// Shared utilities\nexport * from './lib/md5.js';\nexport * from './lib/text.js';\nexport * from './lib/junk.js';\nexport * from './lib/deploy-paths.js';\nexport * from './lib/env.js';\n\n// Re-export types from @shipstatic/types\nexport { ShipError, ShipErrorType } from '@shipstatic/types';\nexport type { PingResponse, Deployment, Alias, Account } from '@shipstatic/types';","/**\n * @file SDK-specific type definitions\n * Consolidates all Ship SDK types into a single file for clarity.\n * Core types come from @shipstatic/types, while SDK-specific types are defined here.\n */\n\n// Re-export all types from @shipstatic/types for convenience\nexport * from '@shipstatic/types';\n\n// =============================================================================\n// DEPLOYMENT OPTIONS\n// =============================================================================\n\n/**\n * Universal deploy options for both Node.js and Browser environments\n */\nexport interface DeploymentOptions {\n /** The API URL to use for this specific deploy. Overrides client's default. */\n apiUrl?: string;\n /** An AbortSignal to allow cancellation of the deploy operation. */\n signal?: AbortSignal;\n /** An optional subdomain to suggest for the deployment. Availability is subject to the API. */\n subdomain?: string;\n /** Callback invoked if the deploy is cancelled via the AbortSignal. */\n onCancel?: () => void;\n /** Maximum number of concurrent operations. */\n maxConcurrency?: number;\n /** Timeout in milliseconds for the deploy request. */\n timeout?: number;\n /** API key for this specific deploy. Overrides client's default. */\n apiKey?: string;\n /** Deploy token for this specific deploy. Overrides client's default. */\n deployToken?: string;\n /** Whether to auto-detect and optimize file paths by flattening common directories. Defaults to true. */\n pathDetect?: boolean;\n /** Whether to auto-detect SPAs and generate ship.json configuration. Defaults to true. */\n spaDetect?: boolean;\n /** Callback for overall deploy progress (0-100). */\n onProgress?: (progress: number) => void;\n /** Callback for detailed progress statistics. */\n onProgressStats?: (progressStats: ProgressStats) => void;\n}\n\n/**\n * Options for configuring an deploy operation via `apiClient.deployFiles`.\n * Derived from DeploymentOptions but excludes client-side only options.\n */\nexport type ApiDeployOptions = Omit<DeploymentOptions, 'pathDetect'>;\n\n// =============================================================================\n// PROGRESS TRACKING\n// =============================================================================\n\n/**\n * Detailed statistics about the progress of an deploy operation.\n */\nexport interface ProgressStats {\n /** The number of bytes loaded so far. */\n loaded: number;\n /** The total number of bytes to be loaded. May be 0 if unknown initially. */\n total: number;\n /** The progress as a fraction (loaded/total). Value is between 0 and 1. */\n progress: number;\n /** Optional identifier for the file this progress pertains to, if applicable. */\n file?: string;\n}\n\n// =============================================================================\n// CLIENT CONFIGURATION\n// =============================================================================\n\n/**\n * Options for configuring a `Ship` instance.\n * Sets default API host, authentication credentials, progress callbacks, concurrency, and timeouts for the client.\n */\nexport interface ShipClientOptions {\n /** Default API URL for the client instance. */\n apiUrl?: string | undefined;\n /** API key for authenticated deployments. */\n apiKey?: string | undefined;\n /** Deploy token for single-use deployments. */\n deployToken?: string | undefined;\n /** Path to custom config file. */\n configFile?: string | undefined;\n /**\n * Default callback for overall deploy progress for deploys made with this client.\n * @param progress - A number between 0 and 100.\n */\n onProgress?: ((progress: number) => void) | undefined;\n /**\n * Default callback for detailed progress statistics for deploys made with this client.\n * @param progressStats - Progress statistics object.\n */\n onProgressStats?: ((progressStats: ProgressStats) => void) | undefined;\n /**\n * Default for maximum concurrent deploys.\n * Used if an deploy operation doesn't specify its own `maxConcurrency`.\n * Defaults to 4 if not set here or in the specific deploy call.\n */\n maxConcurrency?: number | undefined;\n /**\n * Default timeout in milliseconds for API requests made by this client instance.\n * Used if an deploy operation doesn't specify its own timeout.\n */\n timeout?: number | undefined;\n}\n\n// StaticFile is now imported from @shipstatic/types\n\n// =============================================================================\n// API RESPONSES\n// =============================================================================\n\n// PingResponse is imported from @shipstatic/types (single source of truth)","/**\n * @file SDK-specific constants.\n * Platform constants are now in @shipstatic/types.\n */\n\n// Re-export platform constants for convenience\nexport { DEFAULT_API } from '@shipstatic/types';","/**\n * Utility functions for string manipulation.\n */\n\n/**\n * Simple utility to pluralize a word based on a count.\n * @param count The number to determine pluralization.\n * @param singular The singular form of the word.\n * @param plural The plural form of the word.\n * @param includeCount Whether to include the count in the returned string. Defaults to true.\n * @returns A string with the count and the correctly pluralized word.\n */\nexport function pluralize(\n count: number,\n singular: string,\n plural: string,\n includeCount: boolean = true\n): string {\n const word = count === 1 ? singular : plural;\n return includeCount ? `${count} ${word}` : word;\n}\n","/**\n * Simple CLI utilities following \"impossible simplicity\" mantra\n */\nimport columnify from 'columnify';\nimport { bold, dim, green, red, yellow, blue, inverse, hidden } from 'yoctocolors';\n\n/**\n * Helper to conditionally apply colors based on noColor flag\n */\nconst applyColor = (colorFn: (text: string) => string, text: string, noColor?: boolean): string => {\n return noColor ? text : colorFn(text);\n};\n\n/**\n * Message helper functions for consistent CLI output\n */\nexport const success = (msg: string, isJson?: boolean, noColor?: boolean) => {\n if (isJson) {\n console.log(JSON.stringify({ success: msg }, null, 2) + '\\n');\n } else {\n console.log(`${applyColor(green, msg.toLowerCase().replace(/\\.$/, ''), noColor)}\\n`);\n }\n};\n\nexport const error = (msg: string, isJson?: boolean, noColor?: boolean) => {\n if (isJson) {\n console.error(JSON.stringify({ error: msg }, null, 2) + '\\n');\n } else {\n const errorPrefix = applyColor((text) => inverse(red(text)), `${applyColor(hidden, '[', noColor)}error${applyColor(hidden, ']', noColor)}`, noColor);\n const errorMsg = applyColor(red, msg.toLowerCase().replace(/\\.$/, ''), noColor);\n console.error(`${errorPrefix} ${errorMsg}\\n`);\n }\n};\n\nexport const warn = (msg: string, isJson?: boolean, noColor?: boolean) => {\n if (isJson) {\n console.log(JSON.stringify({ warning: msg }, null, 2) + '\\n');\n } else {\n const warnPrefix = applyColor((text) => inverse(yellow(text)), `${applyColor(hidden, '[', noColor)}warning${applyColor(hidden, ']', noColor)}`, noColor);\n const warnMsg = applyColor(yellow, msg.toLowerCase().replace(/\\.$/, ''), noColor);\n console.log(`${warnPrefix} ${warnMsg}\\n`);\n }\n};\n\nexport const info = (msg: string, isJson?: boolean, noColor?: boolean) => {\n if (isJson) {\n console.log(JSON.stringify({ info: msg }, null, 2) + '\\n');\n } else {\n const infoPrefix = applyColor((text) => inverse(blue(text)), `${applyColor(hidden, '[', noColor)}info${applyColor(hidden, ']', noColor)}`, noColor);\n const infoMsg = applyColor(blue, msg.toLowerCase().replace(/\\.$/, ''), noColor);\n console.log(`${infoPrefix} ${infoMsg}\\n`);\n }\n};\n\n\n/**\n * Format unix timestamp to ISO 8601 string without milliseconds, or return '-' if not provided\n */\nexport const formatTimestamp = (timestamp?: number, context: 'table' | 'details' = 'details', noColor?: boolean): string => {\n if (timestamp === undefined || timestamp === null || timestamp === 0) {\n return '-';\n }\n \n const isoString = new Date(timestamp * 1000).toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n \n // Hide the T and Z characters only in table/list views for cleaner appearance\n if (context === 'table') {\n return isoString.replace(/T/, applyColor(hidden, 'T', noColor)).replace(/Z$/, applyColor(hidden, 'Z', noColor));\n }\n \n return isoString;\n};\n\n/**\n * Format value for display\n */\nconst formatValue = (key: string, value: any, context: 'table' | 'details' = 'details', noColor?: boolean): string => {\n if (typeof value === 'number' && (key === 'created' || key === 'expires' || key === 'confirmed')) {\n return formatTimestamp(value, context, noColor);\n }\n if (key === 'size' && typeof value === 'number') {\n const mb = value / (1024 * 1024);\n return mb >= 1 ? `${mb.toFixed(1)}Mb` : `${(value / 1024).toFixed(1)}Kb`;\n }\n if (key === 'config') {\n // Handle both boolean and number (0/1) values\n if (typeof value === 'boolean') {\n return value ? 'yes' : 'no';\n }\n if (typeof value === 'number') {\n return value === 1 ? 'yes' : 'no';\n }\n }\n return String(value);\n};\n\n/**\n * Format data as table with specified columns for easy parsing\n */\nexport const formatTable = (data: any[], columns?: string[], noColor?: boolean): string => {\n if (!data || data.length === 0) return '';\n \n // Get column order from first item (preserves API order) or use provided columns\n const firstItem = data[0] || {};\n const columnOrder = columns || Object.keys(firstItem).filter(key => \n firstItem[key] !== undefined && key !== 'verified' && key !== 'isCreate'\n );\n \n // Transform data preserving column order\n const transformedData = data.map(item => {\n const transformed: any = {};\n columnOrder.forEach(col => {\n if (col in item && item[col] !== undefined) {\n transformed[col] = formatValue(col, item[col], 'table', noColor);\n }\n });\n return transformed;\n });\n \n const output = columnify(transformedData, {\n columnSplitter: ' ', // Use 3 spaces for visual alignment\n columns: columnOrder, // Explicitly preserve order\n config: columnOrder.reduce((config, col) => {\n config[col] = { headingTransform: (heading: string) => applyColor(dim, heading, noColor) };\n return config;\n }, {} as any)\n });\n \n // Clean output: remove null bytes and ensure clean spacing\n return output\n .split('\\n')\n .map((line: string) => line\n .replace(/\\0/g, '') // Remove any null bytes\n .replace(/\\s+$/, '') // Remove trailing spaces\n )\n .join('\\n') + '\\n';\n};\n\n/**\n * Format object properties as key-value pairs with space separation for readability\n */\nexport const formatDetails = (obj: any, noColor?: boolean): string => {\n const entries = Object.entries(obj).filter(([key, value]) => {\n // Filter out internal properties only\n if (key === 'verified' || key === 'isCreate') return false;\n return value !== undefined;\n });\n \n if (entries.length === 0) return '';\n \n // Transform to columnify format while preserving order\n const data = entries.map(([key, value]) => ({\n property: key + ':',\n value: formatValue(key, value, 'details', noColor)\n }));\n \n const output = columnify(data, {\n columnSplitter: ' ',\n showHeaders: false,\n config: {\n property: { \n dataTransform: (value: string) => applyColor(dim, value, noColor)\n }\n }\n });\n \n // Clean output: remove null bytes and ensure clean spacing\n return output\n .split('\\n')\n .map((line: string) => line.replace(/\\0/g, '')) // Remove any null bytes\n .join('\\n') + '\\n';\n};\n\n"],"mappings":"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","names":["env_exports","__export","__setTestEnvironment","getENV","env","_testEnvironment","detectEnvironment","init_env","__esmMin","config_exports","__export","loadConfig","validateConfig","config","ConfigSchema","error","firstError","path","loadConfigFromFile","configFile","getENV","cosmiconfigSync","os","explorer","MODULE_NAME","result","envConfig","fileConfig","mergedConfig","import_zod","import_types","init_config","__esmMin","init_env","calculateMD5Browser","blob","SparkMD5","resolve","reject","chunks","currentChunk","spark","fileReader","loadNext","start","end","e","result","calculateMD5Node","input","crypto","hash","fs","stream","err","chunk","calculateMD5","env","getENV","import_types","init_md5","__esmMin","init_env","setConfig","config","_config","getCurrentConfig","import_types","init_platform_config","__esmMin","filterJunk","filePaths","filePath","parts","basename","directorySegments","segment","JUNK_DIRECTORIES","junkDir","import_junk","init_junk","__esmMin","findCommonParent","dirPaths","normalizedPaths","p","pathSegments","commonSegments","minLength","i","segment","segments","normalizeWebPath","path","init_path","__esmMin","optimizeDeployPaths","filePaths","options","path","normalizeWebPath","extractFileName","commonPrefix","findCommonDirectory","filePath","deployPath","prefixToRemove","pathSegments","commonSegments","minLength","segments","i","segment","init_deploy_paths","__esmMin","init_path","findAllFilePaths","dirPath","results","entries","entry","fullPath","stats","subFiles","error","processFilesForNode","paths","options","getENV","absolutePaths","p","absPath","uniquePaths","validPaths","filterJunk","inputAbsolutePaths","inputBasePath","findCommonParent","relativePaths","filePath","rel","deployFiles","optimizeDeployPaths","totalSize","platformLimits","getCurrentConfig","i","deployPath","content","md5","calculateMD5","import_types","fs","path","init_node_files","__esmMin","init_env","init_md5","init_junk","init_platform_config","init_deploy_paths","init_path","processFilesForBrowser","browserFiles","options","getENV","filesArray","filePaths","file","deployFiles","optimizeDeployPaths","initialFileInfos","i","deployPath","allRelativePaths","info","nonJunkRelativePathsArray","filterJunk","nonJunkRelativePathsSet","result","fileInfo","md5","calculateMD5","import_types","init_browser_files","__esmMin","init_md5","init_junk","init_deploy_paths","prepare_input_exports","__export","convertBrowserInput","convertDeployInput","convertNodeInput","validateFiles","files","options","config","getCurrentConfig","totalSize","file","validateInputEarly","input","environment","item","postProcessFiles","validationFiles","f","staticFiles","processFilesForNode","fileArray","processFilesForBrowser","apiClient","getENV","import_types","init_prepare_input","__esmMin","init_env","init_node_files","init_browser_files","init_platform_config","import_commander","node_exports","__export","ApiHttp","JUNK_DIRECTORIES","Ship","__setTestEnvironment","calculateMD5","createAccountResource","createAliasResource","createDeploymentResource","node_default","filterJunk","getCurrentConfig","getENV","loadConfig","mergeDeployOptions","optimizeDeployPaths","pluralize","processFilesForNode","resolveConfig","setConfig","_mime","import_types","init_env","DEPLOY_ENDPOINT","PING_ENDPOINT","ALIASES_ENDPOINT","CONFIG_ENDPOINT","ACCOUNT_ENDPOINT","SPA_CHECK_ENDPOINT","getBrowserContentType","file","collectAsyncIterable","iterable","result","x","ApiHttp","options","#getAuthHeaders","customHeaders","headers","#fetchWithAuth","url","operationName","fetchOptions","hasInstanceCredentials","hasAuthorizationHeader","error","#handleFetchError","#request","response","#handleResponseError","files","#validateFiles","apiUrl","signal","apiKey","deployToken","requestBody","requestHeaders","#prepareRequestPayload","authHeaders","getENV","#createBrowserBody","body","#createNodeBody","formData","checksums","fileContent","contentType","fileWithPath","FormDataNodeClass","FileNodeClass","FormDataEncoderClass","pathImport","formDataNodeInstance","i","fileNodeInstance","preservedPath","encoder","encodedChunks","chunk","errorData","message","id","name","deployment","indexFile","f","MAX_INDEX_SIZE","indexContent","requestData","import_types","init_env","loadConfig","configFile","env","getENV","nodeLoadConfig","resolveConfig","userOptions","loadedConfig","finalConfig","result","mergeDeployOptions","options","clientDefaults","import_types","init_md5","createSPAConfig","configString","content","md5","calculateMD5","detectAndConfigureSPA","files","apiClient","options","f","spaConfig","createDeploymentResource","getApi","clientDefaults","ensureInit","processInput","input","options","mergedOptions","mergeDeployOptions","apiClient","staticFiles","detectAndConfigureSPA","id","createAliasResource","aliasName","deployment","createAccountResource","Ship","options","config","ApiHttp","initCallback","getApi","createDeploymentResource","input","createAliasResource","createAccountResource","import_types","init_env","init_config","init_platform_config","shared_exports","__export","ApiHttp","JUNK_DIRECTORIES","Ship","__setTestEnvironment","calculateMD5","createAccountResource","createAliasResource","createDeploymentResource","filterJunk","getENV","loadConfig","mergeDeployOptions","optimizeDeployPaths","pluralize","resolveConfig","types_exports","__reExport","__reExport","shared_exports","types_exports","import_types","init_md5","pluralize","count","singular","plural","includeCount","word","init_junk","init_deploy_paths","init_env","import_types","__reExport","node_exports","shared_exports","init_config","init_platform_config","init_node_files","init_env","Ship","options","getENV","resolveConfig","loadedConfig","loadConfig","finalConfig","ApiHttp","platformConfig","setConfig","error","input","#isValidNodeInput","convertDeployInput","item","node_default","import_types","import_fs","path","import_columnify","import_yoctocolors","applyColor","colorFn","text","noColor","success","msg","isJson","error","errorPrefix","errorMsg","warn","warnPrefix","warnMsg","info","infoPrefix","infoMsg","formatTimestamp","timestamp","context","isoString","formatValue","key","value","mb","formatTable","data","columns","firstItem","columnOrder","transformedData","item","transformed","col","columnify","config","heading","line","formatDetails","obj","entries","import_yoctocolors","fs","os","packageJson","packageJsonPath","developmentPath","program","err","globalOptions","message","error","displayHelp","str","noColor","applyBold","text","applyDim","output","processOptions","command","options","validationError","handleError","context","opts","resourceType","originalMessage","match","resourceId","withErrorHandling","handler","args","client","createClient","result","outputContext","errorContext","shipOptions","Ship","formatters","isJson","listColumns","formatTable","operation","success","warn","formatDetails","performDeploy","path","cmdOptions","commandContext","stats","deployOptions","abortController","spinner","yoctoSpinner","sigintHandler","key","formatter","thisCommand","actionCommand","deploymentsCmd","commandObj","unknownArg","arg","deployment","aliasesCmd","name","accountCmd","completionCmd","shell","homeDir","installPath","profileFile","sourceLine","bashScriptPath","zshScriptPath","fishScriptPath","fishCompletionsDir","info","profileContent","prefix","e","lines","filteredLines","i","removedSomething","line","originalEndsWithNewline","newContent","handleCompletion","isBash","isZsh","isFish"]}