@shipstatic/ship 0.1.5 → 0.1.6

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/lib/env.ts","../src/lib/md5.ts","../src/lib/junk.ts","../src/lib/path.ts","../src/lib/browser-files.ts","../src/cli/index.ts","../src/index.ts","../src/core/config.ts","../src/types.ts","../src/core/constants.ts","../src/api/http.ts","../src/core/platform-config.ts","../src/lib/prepare-input.ts","../src/lib/node-files.ts","../src/resources.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 Simplified MD5 calculation utility with separate environment handlers.\n */\nimport { getENV } from './env';\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 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 paths.\n * This function is the single shared implementation to be used by both browser and Node.js environments.\n * \n * @param paths - Array of paths to analyze for common parent directory.\n * @param separator - Path separator character (e.g., '/' for browser, path.sep for Node.js).\n * @returns The common parent directory path, or an empty string if none is found.\n */\nexport function findCommonParentDirectory(paths: string[], separator: string): string {\n // Validate input\n if (!paths || !Array.isArray(paths) || paths.length === 0) {\n return '';\n }\n \n // Filter out empty paths\n const validPaths = paths.filter(p => p && typeof p === 'string');\n \n if (validPaths.length === 0) {\n return '';\n }\n\n // Normalize paths to ensure consistent handling across environments\n // Convert all paths to use forward slashes regardless of input format\n const normalizedPaths = validPaths.map(p => {\n // Use the existing path normalization function to handle Windows and Unix paths\n const normalized = p.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n // Add trailing slash for consistent segment comparison\n return normalized.endsWith('/') ? normalized : normalized + '/';\n });\n \n // Special case for single path: return the directory itself\n // This ensures we strip the directory name for single directory inputs\n if (normalizedPaths.length === 1) {\n const path = normalizedPaths[0];\n // For a single path, return the path itself (without trailing slash)\n return path.slice(0, -1); // Remove trailing slash\n }\n\n // For multiple paths: find the common prefix across all paths using segments\n // Split all paths into segments for proper path component comparison\n const pathSegments = normalizedPaths.map(p => p.split('/').filter(Boolean));\n \n // Find the common path segments across all paths\n const commonSegments = [];\n const firstPathSegments = pathSegments[0];\n \n for (let i = 0; i < firstPathSegments.length; i++) {\n const segment = firstPathSegments[i];\n // Check if this segment is common across all paths\n const isCommonSegment = pathSegments.every(segments => \n segments.length > i && segments[i] === segment\n );\n \n if (isCommonSegment) {\n commonSegments.push(segment);\n } else {\n break; // Stop at first non-matching segment\n }\n }\n \n // Reconstruct the common path\n if (commonSegments.length === 0) {\n return ''; // No common segments\n }\n \n // Return the common path (using the correct separator for the environment)\n return commonSegments.join('/');\n}\n\n/**\n * Simple helper to find common parent of absolute paths using the system path separator.\n * More declarative wrapper around findCommonParentDirectory for Node.js usage.\n * @param absolutePaths - Array of absolute file paths\n * @returns Common parent directory path or empty string if none found\n */\nexport function findCommonParent(absolutePaths: string[]): string {\n if (typeof require === 'undefined') {\n // Browser environment - use forward slash\n return findCommonParentDirectory(absolutePaths, '/');\n }\n \n // Node.js environment - use system separator\n const path = require('path');\n return findCommonParentDirectory(absolutePaths, path.sep);\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(/^\\/+/, '');\n}\n\n/**\n * Ensures a path is relative by normalizing it and removing any leading slashes.\n * @param path - The path to make relative\n * @returns Relative path suitable for web deployment\n */\nexport function ensureRelativePath(path: string): string {\n return normalizeWebPath(path);\n}\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 { getENV } from './env.js';\nimport { StaticFile } from '../types.js';\nimport { calculateMD5 } from './md5.js';\nimport { ShipError } from '@shipstatic/types';\nimport { findCommonParentDirectory, normalizeWebPath } from './path.js';\nimport { filterJunk } from './junk.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 determines relative paths (stripping basePath if provided).\n *\n * @param browserFiles - FileList or File[] to process for deploy.\n * @param options - Optional processing options (basePath for path stripping, stripCommonPrefix).\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: { explicitBaseDirInput?: string; stripCommonPrefix?: boolean } = {}\n): Promise<StaticFile[]> {\n if (getENV() !== 'browser') {\n throw ShipError.business('processFilesForBrowser can only be called in a browser environment.');\n }\n\n const { explicitBaseDirInput, stripCommonPrefix } = options;\n const initialFileInfos: BrowserFileProcessItem[] = [];\n const filesArray = Array.isArray(browserFiles) ? browserFiles : Array.from(browserFiles);\n \n // If stripCommonPrefix is true and no explicit basePath is provided,\n // Determine the parent directory for path stripping if applicable\n let parentDir = '';\n if (stripCommonPrefix) {\n parentDir = findBrowserCommonParentDirectory(browserFiles);\n } else if (explicitBaseDirInput) {\n parentDir = explicitBaseDirInput;\n }\n\n // Prepare the initial file information with appropriate relative paths\n for (const file of filesArray) {\n let relativePath = (file as any).webkitRelativePath || file.name;\n if (parentDir) {\n // Normalize all paths to use forward slashes\n relativePath = normalizeWebPath(relativePath);\n const basePathWithSlash = parentDir.endsWith('/') ? parentDir : `${parentDir}/`;\n // Robustly strip deeply nested basePath prefix\n if (relativePath === parentDir || relativePath === basePathWithSlash || relativePath.startsWith(basePathWithSlash)) {\n relativePath = relativePath.substring(basePathWithSlash.length);\n }\n }\n // Always normalize output path to forward slashes\n relativePath = normalizeWebPath(relativePath);\n initialFileInfos.push({ file, relativePath });\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 and empty files\n if (!nonJunkRelativePathsSet.has(fileInfo.relativePath) || fileInfo.file.size === 0) {\n continue;\n }\n \n // Calculate MD5 hash\n const { md5 } = await calculateMD5(fileInfo.file);\n \n // Create and add the StaticFile\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 * Finds the common parent directory from a FileList or File[] using webkitRelativePath.\n * Useful for stripping a common prefix if files are selected from a single folder.\n *\n * @param files - FileList or File[] to analyze.\n * @returns Common parent directory string, or empty string if not consistent.\n * @throws {ShipClientError} If called outside a browser.\n */\nexport function findBrowserCommonParentDirectory(files: FileList | File[]): string {\n if (getENV() !== 'browser') {\n throw ShipError.business('findBrowserCommonParentDirectory can only be called in a browser environment.');\n }\n if (!files || files.length === 0) return '';\n \n const paths: (string | null | undefined)[] = Array.from(files)\n .map(file => (file as any).webkitRelativePath);\n\n // If any file is missing webkitRelativePath, we can't determine a common parent.\n if (paths.some(p => !p)) {\n return '';\n }\n\n return findCommonParentDirectory(paths as string[], '/');\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 } from '../index.js';\nimport { readFileSync } from 'fs';\nimport * as path from 'path';\n\n// Get package.json data for version information\nlet packageJson: any = { version: '0.0.0' };\nconst possiblePaths = [\n path.resolve(__dirname, '../package.json'),\n path.resolve(__dirname, '../../package.json'),\n path.resolve(__dirname, '../../../package.json')\n];\n\nfor (const packageJsonPath of possiblePaths) {\n try {\n packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n break;\n } catch (error) {\n // Continue to the next path\n }\n}\n\nconst program = new Command();\n\n/**\n * Simple error handler - just log and exit\n */\nfunction handleError(error: any) {\n console.error('Error:', error.message || error);\n process.exit(1);\n}\n\n/**\n * Create Ship client with CLI options\n */\nfunction createClient(): Ship {\n const options = program.opts();\n return new Ship({\n apiUrl: options.api,\n apiKey: options.apiKey\n });\n}\n\n/**\n * Human-readable formatters for different result types\n */\nconst formatters = {\n deployments: (result: any) => {\n result.deployments.forEach((d: any) => {\n console.log(`${d.deployment} (${d.status})`);\n });\n },\n aliases: (result: any) => {\n result.aliases.forEach((a: any) => {\n console.log(`${a.alias} -> ${a.deployment}`);\n });\n },\n deployment: (result: any) => {\n console.log(`${result.deployment} (${result.status})`);\n },\n alias: (result: any) => {\n console.log(`${result.alias} -> ${result.deployment}`);\n },\n email: (result: any) => {\n console.log(`${result.email} (${result.subscription})`);\n }\n};\n\n/**\n * Format output based on --json flag\n */\nfunction output(result: any) {\n const options = program.opts();\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n \n // Find appropriate formatter based on result properties\n for (const [key, formatter] of Object.entries(formatters)) {\n if (result[key]) {\n formatter(result);\n return;\n }\n }\n \n // Default fallback\n console.log('Success');\n}\n\nprogram\n .name('ship')\n .description('CLI for Shipstatic')\n .version(packageJson.version)\n .option('-u, --api <URL>', 'API URL')\n .option('-k, --apiKey <KEY>', 'API key')\n .option('--json', 'JSON output')\n .addHelpText('after', `\nExamples:\n ship ./path Deploy files (shortcut)\n ship ping Check API connectivity\n \n ship deployments list List all deployments\n ship deployments create ./app Deploy app directory\n ship deployments get abc123 Get deployment details\n ship deployments remove abc123 Remove deployment\n \n ship aliases list List all aliases\n ship aliases get staging Get alias details\n ship aliases set staging abc123 Set alias to deployment\n ship aliases remove staging Remove alias\n \n ship account get Get account details`);\n\n// Ping command\nprogram\n .command('ping')\n .description('Check API connectivity')\n .action(async () => {\n try {\n const client = createClient();\n const success = await client.ping();\n console.log(success ? 'Connected' : 'Failed');\n } catch (error: any) {\n handleError(error);\n }\n });\n\n// Deployments commands\nconst deploymentsCmd = program\n .command('deployments')\n .description('Manage deployments');\n\ndeploymentsCmd\n .command('list')\n .description('List all deployments')\n .action(async () => {\n try {\n const client = createClient();\n const result = await client.deployments.list();\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n });\n\ndeploymentsCmd\n .command('create <path>')\n .description('Deploy files from path')\n .action(async (path: string) => {\n try {\n const client = createClient();\n const result = await client.deployments.create([path]);\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n });\n\ndeploymentsCmd\n .command('get <id>')\n .description('Get deployment details')\n .action(async (id: string) => {\n try {\n const client = createClient();\n const result = await client.deployments.get(id);\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n });\n\ndeploymentsCmd\n .command('remove <id>')\n .description('Remove deployment')\n .action(async (id: string) => {\n try {\n const client = createClient();\n const result = await client.deployments.remove(id);\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n });\n\n// Aliases commands\nconst aliasesCmd = program\n .command('aliases')\n .description('Manage aliases');\n\naliasesCmd\n .command('list')\n .description('List all aliases')\n .action(async () => {\n try {\n const client = createClient();\n const result = await client.aliases.list();\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n });\n\naliasesCmd\n .command('get <name>')\n .description('Get alias details')\n .action(async (name: string) => {\n try {\n const client = createClient();\n const result = await client.aliases.get(name);\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n });\n\naliasesCmd\n .command('set <name> <deployment>')\n .description('Set alias to deployment')\n .action(async (name: string, deployment: string) => {\n try {\n const client = createClient();\n const result = await client.aliases.set(name, deployment);\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n });\n\naliasesCmd\n .command('remove <name>')\n .description('Remove alias')\n .action(async (name: string) => {\n try {\n const client = createClient();\n const result = await client.aliases.remove(name);\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n });\n\n// Account commands\nconst accountCmd = program\n .command('account')\n .description('Manage account');\n\naccountCmd\n .command('get')\n .description('Get account details')\n .action(async () => {\n try {\n const client = createClient();\n const result = await client.account.get();\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n });\n\n// Path shortcut - handle as fallback\nprogram\n .argument('[path]', 'Path to deploy (shortcut)')\n .action(async (path?: string) => {\n // If no path provided, show help\n if (!path) {\n program.help();\n return;\n }\n \n // Check if looks like a path (shortcut: ship ./path)\n if (path.startsWith('./') || path.startsWith('/') || path.startsWith('~') || path.includes('/')) {\n try {\n const client = createClient();\n const result = await client.deployments.create([path]);\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n } else {\n console.error('Unknown command:', path);\n console.error('Use \"ship --help\" for available commands');\n process.exit(1);\n }\n });\n\n\nif (process.env.NODE_ENV !== 'test') {\n program.parse(process.argv);\n}","/**\n * @file Main entry point for the Ship SDK.\n * This module provides a simplified class-based SDK interface similar to Vercel's approach.\n */\n\n// Core imports\nimport { getENV } from './lib/env.js';\nimport { loadConfig, resolveConfig } from './core/config.js';\nimport { ApiHttp } from './api/http.js';\nimport { ShipError } from '@shipstatic/types';\nimport { setConfig } from './core/platform-config.js';\nimport type { ShipClientOptions } from './types.js';\n\n// Resource imports\nimport { createDeploymentResource, createAliasResource, createAccountResource, createKeysResource } from './resources.js';\nimport type { DeploymentResource, AliasResource, AccountResource, KeysResource, DeployInput } from './resources.js';\nimport type { DeploymentOptions } from './types.js';\nimport type { Deployment } from '@shipstatic/types';\n\n\n\n// Re-export types from deploy types\nexport type { DeployInput, DeploymentOptions } from './types.js';\n\n\n/**\n * Ship SDK Client - Universal class-based interface for both Node.js and browser environments.\n * \n * Similar to Vercel's SDK approach:\n * ```\n * const ship = new Ship({ apiKey: \"your-api-key\" });\n * ```\n * \n * Automatically detects the environment and handles Node.js and browser deploys directly.\n * In Node.js environments, loads configuration from files and environment variables.\n * In browser environments, uses only the provided options.\n */\n/**\n * Ship SDK Client - Simplified single class supporting both Node.js and browser environments\n */\nexport class Ship {\n private http: ApiHttp;\n private environment: 'node' | 'browser';\n private configInitialized: boolean = false;\n private readonly clientOptions: ShipClientOptions;\n \n // Resource instances (lazy-loaded)\n private _deployments?: DeploymentResource;\n private _aliases?: AliasResource;\n private _account?: AccountResource;\n private _keys?: KeysResource;\n\n constructor(options: ShipClientOptions = {}) {\n this.clientOptions = options;\n this.environment = getENV() as 'node' | 'browser';\n \n if (this.environment !== 'node' && this.environment !== 'browser') {\n throw ShipError.business('Unsupported execution environment.');\n }\n \n // Load config synchronously and initialize HTTP client\n const loadedConfig = loadConfig();\n const config = resolveConfig(options, loadedConfig);\n this.http = new ApiHttp({ ...options, ...config });\n }\n\n /**\n * Initialize platform config from API (called automatically on first use)\n */\n private async initializeConfig(): Promise<void> {\n if (this.configInitialized) return;\n \n const config = await this.http.getConfig();\n setConfig(config);\n this.configInitialized = true;\n }\n\n /**\n * Ping the API server to check connectivity\n */\n async ping(): Promise<boolean> {\n return this.http.ping();\n }\n\n /**\n * Get deployments resource (environment-specific)\n */\n get deployments() {\n if (!this._deployments) {\n this._deployments = createDeploymentResource(this.http, () => this.initializeConfig(), this.clientOptions);\n }\n return this._deployments;\n }\n \n /**\n * Get aliases resource\n */\n get aliases(): AliasResource {\n if (!this._aliases) {\n this._aliases = createAliasResource(this.http);\n }\n return this._aliases;\n }\n \n /**\n * Get account resource\n */\n get account(): AccountResource {\n if (!this._account) {\n this._account = createAccountResource(this.http);\n }\n return this._account;\n }\n \n /**\n * Get keys resource\n */\n get keys(): KeysResource {\n if (!this._keys) {\n this._keys = createKeysResource(this.http);\n }\n return this._keys;\n }\n\n /**\n * Deploy files (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\n// Default export (for import Ship from 'ship')\nexport default Ship;\n\n// Export all public types\nexport type { StaticFile, ShipClientOptions, ApiDeployOptions, ProgressStats } from './types.js';\nexport type { PingResponse } from '@shipstatic/types';\n\n// Export resource types\nexport type { DeploymentResource, AliasResource, AccountResource, KeysResource } from './resources.js';\n\n// Export main error class and error type enum\nexport { ShipError, ShipErrorType } from '@shipstatic/types';\n\n// Advanced/utility exports (for tests and power users; subject to change)\nexport { processFilesForNode } from './lib/node-files.js';\nexport { processFilesForBrowser, findBrowserCommonParentDirectory } from './lib/browser-files.js';\n\n// Test utilities\n/**\n * @internal\n * Test utility to set the execution environment (e.g., 'node', 'browser').\n * This should not be used in production code.\n */\nexport { __setTestEnvironment } from './lib/env.js';\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 { cosmiconfigSync } from 'cosmiconfig';\nimport { ShipClientOptions, DeploymentOptions, ShipError } from '../types.js';\nimport { getENV } from '../lib/env.js';\nimport { DEFAULT_API } from './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}).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 * Synchronously loads client configuration from files.\n * Searches for .shiprc and package.json with ship key.\n * @returns Configuration object or empty if not found/invalid\n * @internal\n */\nfunction loadConfigFromFile(): Partial<ShipClientOptions> {\n try {\n const explorer = cosmiconfigSync(MODULE_NAME, {\n searchPlaces: [\n `.${MODULE_NAME}rc`,\n 'package.json',\n ],\n });\n \n const result = explorer.search();\n if (result && !result.isEmpty && 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 * @returns Configuration object with loaded values\n * @throws {ShipInvalidConfigError} If the configuration is invalid.\n */\nexport function loadConfig(): 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 };\n\n // Always try to load file config for fallback values\n const fileConfig = loadConfigFromFile();\n\n // Merge with environment variables taking precedence\n const mergedConfig = {\n apiUrl: envConfig.apiUrl ?? fileConfig.apiUrl,\n apiKey: envConfig.apiKey ?? fileConfig.apiKey,\n };\n\n // Validate final config\n return validateConfig(mergedConfig);\n}\n\n/**\n * Simplified configuration resolution with clear precedence.\n * Precedence: user options > environment variables > config files > defaults.\n * \n * @param userOptions - Options provided directly by the user\n * @param loadedConfig - Configuration loaded from environment/files\n * @returns Resolved configuration with api and apiKey\n */\nexport function resolveConfig(\n userOptions: ShipClientOptions = {}, \n loadedConfig: Partial<ShipClientOptions> = {}\n): { apiUrl: string; apiKey?: string } {\n // Build final config with clear precedence\n const finalConfig = {\n apiUrl: userOptions.apiUrl || loadedConfig.apiUrl || DEFAULT_API,\n apiKey: userOptions.apiKey !== undefined ? userOptions.apiKey : loadedConfig.apiKey,\n };\n\n // Return with optional apiKey\n return finalConfig.apiKey !== undefined \n ? { apiUrl: finalConfig.apiUrl, apiKey: finalConfig.apiKey }\n : { apiUrl: finalConfig.apiUrl };\n}\n\n\n// =============================================================================\n// CONFIGURATION MERGING\n// =============================================================================\n\n/**\n * Merge deployment options with client defaults.\n * Simple utility function that replaces the unnecessary ConfigMerger class.\n */\nexport function mergeDeployOptions(\n userOptions: DeploymentOptions = {},\n clientDefaults: ShipClientOptions\n): DeploymentOptions {\n const merged: DeploymentOptions = { ...userOptions };\n \n // Only set defaults if not already provided\n if (merged.onProgress === undefined && clientDefaults.onProgress !== undefined) {\n merged.onProgress = clientDefaults.onProgress;\n }\n if (merged.onProgressStats === undefined && clientDefaults.onProgressStats !== undefined) {\n merged.onProgressStats = clientDefaults.onProgressStats;\n }\n if (merged.maxConcurrency === undefined && clientDefaults.maxConcurrentDeploys !== undefined) {\n merged.maxConcurrency = clientDefaults.maxConcurrentDeploys;\n }\n if (merged.timeout === undefined && clientDefaults.timeout !== undefined) {\n merged.timeout = clientDefaults.timeout;\n }\n if (merged.apiKey === undefined && clientDefaults.apiKey !== undefined) {\n merged.apiKey = clientDefaults.apiKey;\n }\n if (merged.apiUrl === undefined && clientDefaults.apiUrl !== undefined) {\n merged.apiUrl = clientDefaults.apiUrl;\n }\n \n return merged;\n}\n","/**\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// ENVIRONMENT-SPECIFIC TYPES\n// =============================================================================\n\n/**\n * Consolidated input type for all environments\n */\nexport type DeployInput = FileList | File[] | HTMLInputElement | string[];\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 /** The API key to use for this specific deploy. Overrides client's default. */\n apiKey?: string;\n /** Whether to strip common prefix from file paths. */\n stripCommonPrefix?: 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, 'stripCommonPrefix'>;\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, key, 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 /** Default API key for the client instance. */\n apiKey?: 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 maxConcurrentDeploys?: 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// =============================================================================\n// FILE REPRESENTATION\n// =============================================================================\n\n/**\n * Represents a file that has been processed and is ready for deploy.\n * Used internally by the SDK and in advanced/manual deploy scenarios.\n */\nexport interface StaticFile {\n /**\n * The content of the file.\n * In Node.js, this is typically a `Buffer`.\n * In the browser, this is typically a `File` or `Blob` object.\n */\n content: File | Buffer | Blob;\n /**\n * The desired path for the file on the server, relative to the deployment root.\n * Should include the filename, e.g., `images/photo.jpg`.\n */\n path: string;\n /**\n * The original absolute file system path (primarily used in Node.js environments).\n * This helps in debugging or associating the server path back to its source.\n */\n filePath?: string;\n /**\n * The MD5 hash (checksum) of the file's content.\n * This is calculated by the SDK before deploy if not provided.\n */\n md5?: string;\n /** The size of the file in bytes. */\n size: number;\n}\n\n// =============================================================================\n// API RESPONSES\n// =============================================================================\n\n// PingResponse is imported from @shipstatic/types (single source of truth)","/**\n * @file Shared, environment-agnostic constants.\n */\n\n/** Default API URL if not otherwise configured. */\nexport const DEFAULT_API = 'https://api.shipstatic.com';\n\n/** API key prefix for validation and generation */\nexport const API_KEY_PREFIX = 'ship-';","/**\n * @file Manages HTTP requests to the Ship API using native fetch.\n */\nimport * as _mime from 'mime-types';\nimport type { Deployment, DeploymentListResponse, PingResponse, ConfigResponse, DeploymentRemoveResponse, Alias, AliasListResponse, Account } from '@shipstatic/types';\nimport { StaticFile, ApiDeployOptions, ShipClientOptions } from '../types.js';\nimport { ShipError } from '@shipstatic/types';\nimport { getENV } from '../lib/env.js';\nimport { DEFAULT_API } from '../core/constants.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\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\n /**\n * Constructs a new ApiHttp instance with the provided client options.\n * @param options - Client options including API host, apiKey, and timeout settings.\n */\n constructor(options: ShipClientOptions) {\n this.apiUrl = options.apiUrl || DEFAULT_API;\n this.apiKey = options.apiKey ?? \"\";\n }\n\n /**\n * Generates common headers for API requests, including the API key if present.\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 if (this.apiKey) {\n headers['Authorization'] = `Bearer ${this.apiKey}`;\n }\n return headers;\n }\n\n /**\n * Makes a fetch request with common error handling and authentication.\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 credentials: getENV() === 'browser' ? 'include' : 'same-origin',\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 * 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 } = options;\n\n try {\n const { requestBody, requestHeaders } = await this.#prepareRequestPayload(files);\n \n const fetchOptions: RequestInit = {\n method: 'POST',\n body: requestBody,\n headers: requestHeaders,\n signal: signal || null\n };\n\n const response = await this.#fetchWithAuth(`${apiUrl}${DEPLOY_ENDPOINT}`, fetchOptions, 'Deploy');\n \n if (!response.ok) {\n await this.#handleResponseError(response, 'Deploy');\n }\n \n return await response.json() as Deployment;\n } catch (error: any) {\n if (error instanceof ShipError) {\n throw error;\n }\n this.#handleFetchError(error, 'Deploy');\n // This line is unreachable because #handleFetchError always throws.\n // However, TypeScript requires a return statement here.\n throw ShipError.business('An unexpected error occurred and was not handled.');\n }\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 | Buffer;\n requestHeaders: Record<string, string>;\n }> {\n let requestBody: FormData | Buffer;\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;\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 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 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], pathImport.basename(file.path), { type: contentType });\n } else if (typeof Blob !== \"undefined\" && file.content instanceof Blob) {\n fileNodeInstance = new FileNodeClass([file.content], pathImport.basename(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 throw ShipError.api(\n message,\n response.status,\n errorData.code,\n errorData\n );\n }\n\n // Fallback for completely unstructured errors\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 deploymentName - Deployment name to point to\n * @returns Promise resolving to the created/updated alias\n */\n public async setAlias(name: string, deploymentName: string): Promise<Alias> {\n return await this.#request<Alias>(`${this.apiUrl}${ALIASES_ENDPOINT}/${encodeURIComponent(name)}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ deploymentId: deploymentName })\n }, 'Set Alias');\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 * 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 * @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 Input conversion utilities for deployment\n * Converts various input types to StaticFile[] for unified processing\n */\n\nimport type { StaticFile, DeploymentOptions, DeployInput } from '../types.js';\nimport { ShipError } from '@shipstatic/types';\nimport { getENV } from './env.js';\nimport { processFilesForNode } from './node-files.js';\nimport { processFilesForBrowser } from './browser-files.js';\nimport { getCurrentConfig } from '../core/platform-config.js';\n\n/**\n * Unified validation for file count and size limits\n * @param fileCount - Number of files \n * @param totalSize - Total size in bytes (optional, for size validation)\n * @throws {ShipError} If limits are exceeded\n * @internal\n */\nfunction validateLimits(fileCount: number, totalSize?: number): void {\n const config = getCurrentConfig();\n \n if (fileCount === 0) {\n throw ShipError.business('No files to deploy.');\n }\n \n if (fileCount > config.maxFilesCount) {\n throw ShipError.business(`Too many files to deploy. Maximum allowed is ${config.maxFilesCount}.`);\n }\n \n if (totalSize !== undefined && 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 * Validates individual file size against platform limits\n * @param fileName - Name of the file for error messages\n * @param fileSize - Size of the file in bytes\n * @throws {ShipError} If file is too large\n * @internal\n */\nfunction validateFileSize(fileName: string, fileSize: number): void {\n const config = getCurrentConfig();\n \n if (fileSize > config.maxFileSize) {\n throw ShipError.business(`File ${fileName} is too large. Maximum allowed size is ${config.maxFileSize / (1024 * 1024)}MB.`);\n }\n}\n\n/**\n * Comprehensive file validation for both Node.js and browser environments\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\n if (!options.skipEmptyCheck && files.length === 0) {\n throw ShipError.business('No files to deploy.');\n }\n \n // Check file count limit\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\n let totalSize = 0;\n for (const file of files) {\n // Individual file size validation\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 totalSize += file.size;\n }\n \n // Total size validation\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 * 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\n validateFiles(files, { 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 if (!Array.isArray(input) || !input.every(item => typeof item === 'string')) {\n throw ShipError.business('Invalid input type for Node.js environment. Expected string[] file paths.');\n }\n \n // Initial validation - just check input count\n if (input.length === 0) {\n throw ShipError.business('No files to deploy.');\n }\n\n // Process files for Node.js\n const processingOptions: { basePath?: string; stripCommonPrefix?: boolean } = {};\n \n if (options.stripCommonPrefix !== undefined) {\n processingOptions.stripCommonPrefix = options.stripCommonPrefix;\n if (options.stripCommonPrefix) {\n const path = require('path');\n const cwd = typeof process !== 'undefined' ? process.cwd() : '/';\n const resolvedPaths = input.map((inputPath: string) => path.resolve(cwd, inputPath));\n const { findCommonParent } = await import('./path.js');\n const commonParent = findCommonParent(resolvedPaths);\n if (commonParent) {\n processingOptions.basePath = commonParent;\n }\n }\n }\n\n const staticFiles: StaticFile[] = await processFilesForNode(input, processingOptions);\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 let fileArray: File[];\n \n if (input instanceof HTMLInputElement) {\n if (!input.files) throw ShipError.business('No files selected in 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\n validateFiles(fileArray);\n\n // Process files for browser\n const processingOptions: { stripCommonPrefix?: boolean; basePath?: string } = {};\n\n if (options.stripCommonPrefix !== undefined) {\n processingOptions.stripCommonPrefix = options.stripCommonPrefix;\n if (options.stripCommonPrefix) {\n const { findBrowserCommonParentDirectory } = await import('./browser-files.js');\n const commonParent = findBrowserCommonParentDirectory(\n input instanceof HTMLInputElement ? input.files! : input\n );\n if (commonParent) {\n processingOptions.basePath = commonParent;\n }\n }\n }\n\n const staticFiles: StaticFile[] = await processFilesForBrowser(fileArray as File[], processingOptions);\n \n // Apply shared validation and post-processing\n return postProcessFiles(staticFiles);\n}\n\n/**\n * Unified input conversion function\n * Converts any DeployInput to StaticFile[] based on environment\n */\nexport async function convertDeployInput(\n input: DeployInput,\n options: DeploymentOptions = {}\n): Promise<StaticFile[]> {\n const environment = getENV();\n \n if (environment === 'node') {\n if (!Array.isArray(input) || !input.every(item => typeof item === 'string')) {\n throw ShipError.business('Invalid input type for Node.js environment. Expected string[] file paths.');\n }\n return convertNodeInput(input as string[], options);\n } else if (environment === 'browser') {\n if (!(input instanceof HTMLInputElement || Array.isArray(input) || \n (typeof FileList !== 'undefined' && input instanceof FileList))) {\n throw ShipError.business('In browser, input must be FileList, File[], or HTMLInputElement.');\n }\n return convertBrowserInput(input as FileList | File[] | HTMLInputElement, options);\n } else {\n throw ShipError.business('Unsupported execution environment.');\n }\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 './env.js';\nimport { StaticFile } from '../types.js';\nimport { calculateMD5 } from './md5.js';\nimport { filterJunk } from './junk.js';\nimport { ShipError } from '@shipstatic/types';\nimport { getCurrentConfig } from '../core/platform-config.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 * Clean, declarative function to get files from a source path.\n * Follows the suggested architectural pattern from the feedback.\n * @param sourcePath - File or directory path to process\n * @param options - Options for processing (basePath, stripCommonPrefix)\n * @returns Promise resolving to array of StaticFile objects\n */\nexport async function getFilesFromPath(\n sourcePath: string, \n options: { basePath?: string; stripCommonPrefix?: boolean } = {}\n): Promise<StaticFile[]> {\n const absolutePath = path.resolve(sourcePath);\n \n // 1. Discover all files\n const allPaths = (() => {\n const stats = fs.statSync(absolutePath);\n if (stats.isFile()) {\n return [absolutePath];\n } else if (stats.isDirectory()) {\n return findAllFilePaths(absolutePath);\n } else {\n return [];\n }\n })();\n \n // 2. Filter out junk\n const validPaths = allPaths.filter(p => {\n const basename = path.basename(p);\n return filterJunk([basename]).length > 0; // Keep files that pass junk filter\n });\n \n // 3. Determine base for relative paths\n let commonParent: string;\n if (options.basePath) {\n commonParent = options.basePath;\n } else if (options.stripCommonPrefix) {\n // For stripCommonPrefix, we need to handle two cases:\n // 1. Single directory input: use the directory itself as the common parent\n // 2. Multiple files/dirs: use the parent of the input directory\n const stats = fs.statSync(absolutePath);\n if (stats.isDirectory()) {\n commonParent = absolutePath;\n } else {\n commonParent = path.dirname(absolutePath);\n }\n } else {\n // Default behavior: use the source directory\n const stats = fs.statSync(absolutePath);\n if (stats.isDirectory()) {\n commonParent = absolutePath;\n } else {\n commonParent = path.dirname(absolutePath);\n }\n }\n \n // 4. Process into StaticFile objects\n const results: StaticFile[] = [];\n let totalSize = 0;\n \n for (const filePath of validPaths) {\n try {\n // Validate file\n const stats = fs.statSync(filePath);\n \n if (stats.size === 0) {\n console.warn(`Skipping empty file: ${filePath}`);\n continue;\n }\n \n const platformLimits = getCurrentConfig();\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 \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 // Read content and calculate metadata\n const content = fs.readFileSync(filePath);\n const { md5 } = await calculateMD5(content);\n const relativePath = path.relative(commonParent, filePath).replace(/\\\\/g, '/');\n \n results.push({\n path: relativePath,\n content: 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 // Validate total file count\n const platformLimits = getCurrentConfig();\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\n\n/**\n * Processes Node.js file and directory paths into an array of StaticFile objects ready for deploy.\n * Now uses the simplified, declarative approach suggested in the feedback.\n * \n * @param paths - File or directory paths to scan and process.\n * @param options - Processing options (basePath, stripCommonPrefix).\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: { basePath?: string; stripCommonPrefix?: boolean } = {}\n): Promise<StaticFile[]> {\n if (getENV() !== 'node') {\n throw ShipError.business('processFilesForNode can only be called in a Node.js environment.');\n }\n\n // Handle multiple paths by processing each and combining results\n if (paths.length > 1) {\n const allResults: StaticFile[] = [];\n for (const singlePath of paths) {\n const results = await getFilesFromPath(singlePath, options);\n allResults.push(...results);\n }\n return allResults;\n }\n\n // Single path - use the simplified getFilesFromPath function\n return await getFilesFromPath(paths[0], options);\n}\n","/**\n * @file All Ship SDK resources in one place - impossibly simple.\n */\nimport type { Deployment, DeploymentListResponse, Alias, AliasListResponse, Account } from '@shipstatic/types';\nimport type { ApiHttp } from './api/http.js';\nimport type { StaticFile, ShipClientOptions } from './types.js';\nimport type { DeploymentOptions, DeployInput } from './types.js';\nimport { convertDeployInput } from './lib/prepare-input.js';\nimport { mergeDeployOptions } from './core/config.js';\n\n// Re-export DeployInput for external use\nexport type { DeployInput };\n\n// =============================================================================\n// DEPLOYMENT RESOURCE\n// =============================================================================\n\nexport interface DeploymentResource {\n create: (input: DeployInput, options?: DeploymentOptions) => Promise<Deployment>;\n list: () => Promise<DeploymentListResponse>;\n remove: (id: string) => Promise<void>;\n get: (id: string) => Promise<Deployment>;\n}\n\nexport function createDeploymentResource(\n api: ApiHttp, \n initConfig?: () => Promise<void>,\n clientDefaults?: ShipClientOptions\n): DeploymentResource {\n return {\n create: async (input: DeployInput, options: DeploymentOptions = {}) => {\n // Initialize config from API before validation\n if (initConfig) {\n await initConfig();\n }\n \n // Merge user options with client defaults\n const mergedOptions = clientDefaults \n ? mergeDeployOptions(options, clientDefaults)\n : options;\n \n // Convert input to StaticFile[] using unified utility\n const staticFiles: StaticFile[] = await convertDeployInput(input, mergedOptions);\n \n // Deploy using the API - now returns the full Deployment object directly\n return await api.deploy(staticFiles, mergedOptions);\n },\n\n list: async () => {\n return api.listDeployments();\n },\n\n remove: async (id: string) => {\n await api.removeDeployment(id);\n // Return void for deletion operations\n },\n\n get: async (id: string) => {\n return api.getDeployment(id);\n }\n };\n}\n\n// =============================================================================\n// ALIAS RESOURCE\n// =============================================================================\n\nexport interface AliasResource {\n set: (aliasName: string, deploymentName: string) => Promise<Alias>;\n get: (aliasName: string) => Promise<Alias>;\n list: () => Promise<AliasListResponse>;\n remove: (aliasName: string) => Promise<void>;\n}\n\nexport function createAliasResource(api: ApiHttp): AliasResource {\n return {\n set: async (aliasName: string, deploymentName: string) => {\n // Set alias and return the created/updated alias directly\n return api.setAlias(aliasName, deploymentName);\n },\n\n get: async (aliasName: string) => {\n return api.getAlias(aliasName);\n },\n\n list: async () => {\n return api.listAliases();\n },\n\n remove: async (aliasName: string) => {\n await api.removeAlias(aliasName);\n // Return void for deletion operations\n }\n };\n}\n\n// =============================================================================\n// ACCOUNT RESOURCE\n// =============================================================================\n\nexport interface AccountResource {\n get: () => Promise<Account>;\n}\n\nexport function createAccountResource(api: ApiHttp): AccountResource {\n return {\n get: async () => {\n return api.getAccount();\n }\n };\n}\n\n// =============================================================================\n// KEYS RESOURCE\n// =============================================================================\n\nexport interface KeysResource {\n create: () => Promise<{ apiKey: string }>;\n}\n\nexport function createKeysResource(api: ApiHttp): KeysResource {\n return {\n create: async () => {\n return api.createApiKey();\n }\n };\n}"],"mappings":"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","names":["detectEnvironment","getENV","_testEnvironment","init_env","__esmMin","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","filterJunk","filePaths","filePath","parts","basename","directorySegments","segment","JUNK_DIRECTORIES","junkDir","import_junk","init_junk","__esmMin","path_exports","__export","ensureRelativePath","findCommonParent","findCommonParentDirectory","normalizeSlashes","normalizeWebPath","paths","separator","validPaths","p","normalizedPaths","normalized","pathSegments","commonSegments","firstPathSegments","i","segment","segments","absolutePaths","path","init_path","__esmMin","browser_files_exports","__export","findBrowserCommonParentDirectory","processFilesForBrowser","browserFiles","options","getENV","explicitBaseDirInput","stripCommonPrefix","initialFileInfos","filesArray","parentDir","file","relativePath","normalizeWebPath","basePathWithSlash","allRelativePaths","info","nonJunkRelativePathsArray","filterJunk","nonJunkRelativePathsSet","result","fileInfo","md5","calculateMD5","files","paths","p","findCommonParentDirectory","import_types","init_browser_files","__esmMin","init_env","init_md5","init_path","init_junk","import_commander","init_env","import_zod","import_cosmiconfig","types_exports","__reExport","init_env","DEFAULT_API","MODULE_NAME","ConfigSchema","validateConfig","config","error","firstError","path","loadConfigFromFile","result","loadConfig","getENV","envConfig","fileConfig","mergedConfig","resolveConfig","userOptions","loadedConfig","finalConfig","DEFAULT_API","mergeDeployOptions","clientDefaults","merged","_mime","import_types","init_env","DEPLOY_ENDPOINT","PING_ENDPOINT","ALIASES_ENDPOINT","CONFIG_ENDPOINT","ACCOUNT_ENDPOINT","getBrowserContentType","file","collectAsyncIterable","iterable","result","x","_ApiHttp_instances","getAuthHeaders_fn","fetchWithAuth_fn","request_fn","validateFiles_fn","prepareRequestPayload_fn","createBrowserBody_fn","createNodeBody_fn","handleResponseError_fn","handleFetchError_fn","ApiHttp","options","__privateAdd","DEFAULT_API","__privateMethod","files","apiUrl","signal","requestBody","requestHeaders","fetchOptions","response","error","id","name","deploymentName","customHeaders","headers","url","operationName","getENV","body","formData","checksums","fileContent","contentType","fileWithPath","FormDataNodeClass","FileNodeClass","FormDataEncoderClass","pathImport","formDataNodeInstance","i","fileNodeInstance","preservedPath","encoder","encodedChunks","chunk","errorData","message","import_types","import_types","_config","setConfig","config","getCurrentConfig","import_types","init_env","init_env","init_md5","init_junk","import_types","fs","path","findAllFilePaths","dirPath","results","entries","entry","fullPath","stats","subFiles","error","getFilesFromPath","sourcePath","options","absolutePath","validPaths","p","basename","filterJunk","commonParent","totalSize","filePath","platformLimits","getCurrentConfig","content","md5","calculateMD5","relativePath","processFilesForNode","paths","getENV","allResults","singlePath","init_browser_files","validateFiles","files","options","config","getCurrentConfig","totalSize","file","postProcessFiles","f","convertNodeInput","input","item","processingOptions","path","cwd","resolvedPaths","inputPath","findCommonParent","commonParent","staticFiles","processFilesForNode","convertBrowserInput","fileArray","findBrowserCommonParentDirectory","processFilesForBrowser","convertDeployInput","environment","getENV","createDeploymentResource","api","initConfig","clientDefaults","input","options","mergedOptions","mergeDeployOptions","staticFiles","convertDeployInput","id","createAliasResource","aliasName","deploymentName","createAccountResource","createKeysResource","import_types","init_browser_files","init_env","Ship","options","getENV","loadedConfig","loadConfig","config","resolveConfig","ApiHttp","setConfig","createDeploymentResource","createAliasResource","createAccountResource","createKeysResource","input","import_fs","path","packageJson","possiblePaths","packageJsonPath","program","handleError","error","createClient","options","Ship","formatters","result","d","a","output","key","formatter","success","deploymentsCmd","id","aliasesCmd","name","deployment","accountCmd"]}
1
+ {"version":3,"sources":["../src/cli/index.ts","../src/lib/env.ts","../src/core/config.ts","../src/types.ts","../src/core/constants.ts","../src/api/http.ts","../src/index.ts","../src/core/platform-config.ts","../src/lib/prepare-input.ts","../src/lib/md5.ts","../src/lib/junk.ts","../src/lib/node-files.ts","../src/lib/path.ts","../src/lib/browser-files.ts","../src/resources.ts"],"sourcesContent":["/**\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 } from '../index.js';\nimport { readFileSync } from 'fs';\nimport * as path from 'path';\n\n// Get package.json data for version information\nlet packageJson: any = { version: '0.0.0' };\nconst possiblePaths = [\n path.resolve(__dirname, '../package.json'),\n path.resolve(__dirname, '../../package.json'),\n path.resolve(__dirname, '../../../package.json')\n];\n\nfor (const packageJsonPath of possiblePaths) {\n try {\n packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n break;\n } catch (error) {\n // Continue to the next path\n }\n}\n\nconst program = new Command();\n\n/**\n * Simple error handler - just log and exit\n */\nfunction handleError(error: any) {\n console.error('Error:', error.message || error);\n process.exit(1);\n}\n\n/**\n * Create Ship client with CLI options\n */\nfunction createClient(): Ship {\n const options = program.opts();\n return new Ship({\n apiUrl: options.api,\n apiKey: options.apiKey\n });\n}\n\n/**\n * Human-readable formatters for different result types\n */\nconst formatters = {\n deployments: (result: any) => {\n result.deployments.forEach((d: any) => {\n console.log(`${d.deployment} (${d.status})`);\n });\n },\n aliases: (result: any) => {\n result.aliases.forEach((a: any) => {\n console.log(`${a.alias} -> ${a.deployment}`);\n });\n },\n deployment: (result: any) => {\n console.log(`${result.deployment} (${result.status})`);\n },\n alias: (result: any) => {\n console.log(`${result.alias} -> ${result.deployment}`);\n },\n email: (result: any) => {\n console.log(`${result.email} (${result.subscription})`);\n }\n};\n\n/**\n * Format output based on --json flag\n */\nfunction output(result: any) {\n const options = program.opts();\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n \n // Find appropriate formatter based on result properties\n for (const [key, formatter] of Object.entries(formatters)) {\n if (result[key]) {\n formatter(result);\n return;\n }\n }\n \n // Default fallback\n console.log('Success');\n}\n\nprogram\n .name('ship')\n .description('CLI for Shipstatic')\n .version(packageJson.version)\n .option('-u, --api <URL>', 'API URL')\n .option('-k, --apiKey <KEY>', 'API key')\n .option('--json', 'JSON output')\n .addHelpText('after', `\nExamples:\n ship ./path Deploy files (shortcut, dirs flattened by default)\n ship ./dist --preserve-dirs Deploy preserving directory structure\n ship ping Check API connectivity\n \n ship deployments list List all deployments\n ship deployments create ./app Deploy app directory (dirs flattened by default)\n ship deployments create ./dist --preserve-dirs Deploy preserving dir structure\n ship deployments get abc123 Get deployment details\n ship deployments remove abc123 Remove deployment\n \n ship aliases list List all aliases\n ship aliases get staging Get alias details\n ship aliases set staging abc123 Set alias to deployment\n ship aliases remove staging Remove alias\n \n ship account get Get account details`);\n\n// Ping command\nprogram\n .command('ping')\n .description('Check API connectivity')\n .action(async () => {\n try {\n const client = createClient();\n const success = await client.ping();\n console.log(success ? 'Connected' : 'Failed');\n } catch (error: any) {\n handleError(error);\n }\n });\n\n// Deployments commands\nconst deploymentsCmd = program\n .command('deployments')\n .description('Manage deployments');\n\ndeploymentsCmd\n .command('list')\n .description('List all deployments')\n .action(async () => {\n try {\n const client = createClient();\n const result = await client.deployments.list();\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n });\n\ndeploymentsCmd\n .command('create <path>')\n .description('Deploy files from path')\n .option('--preserve-dirs', 'Preserve directory structure (by default, common parent directories are flattened)')\n .action(async (path: string, cmdOptions: any) => {\n try {\n const client = createClient();\n const deployOptions: any = {};\n \n if (cmdOptions.preserveDirs) {\n deployOptions.preserveDirs = true;\n }\n \n const result = await client.deployments.create([path], deployOptions);\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n });\n\ndeploymentsCmd\n .command('get <id>')\n .description('Get deployment details')\n .action(async (id: string) => {\n try {\n const client = createClient();\n const result = await client.deployments.get(id);\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n });\n\ndeploymentsCmd\n .command('remove <id>')\n .description('Remove deployment')\n .action(async (id: string) => {\n try {\n const client = createClient();\n const result = await client.deployments.remove(id);\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n });\n\n// Aliases commands\nconst aliasesCmd = program\n .command('aliases')\n .description('Manage aliases');\n\naliasesCmd\n .command('list')\n .description('List all aliases')\n .action(async () => {\n try {\n const client = createClient();\n const result = await client.aliases.list();\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n });\n\naliasesCmd\n .command('get <name>')\n .description('Get alias details')\n .action(async (name: string) => {\n try {\n const client = createClient();\n const result = await client.aliases.get(name);\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n });\n\naliasesCmd\n .command('set <name> <deployment>')\n .description('Set alias to deployment')\n .action(async (name: string, deployment: string) => {\n try {\n const client = createClient();\n const result = await client.aliases.set(name, deployment);\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n });\n\naliasesCmd\n .command('remove <name>')\n .description('Remove alias')\n .action(async (name: string) => {\n try {\n const client = createClient();\n const result = await client.aliases.remove(name);\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n });\n\n// Account commands\nconst accountCmd = program\n .command('account')\n .description('Manage account');\n\naccountCmd\n .command('get')\n .description('Get account details')\n .action(async () => {\n try {\n const client = createClient();\n const result = await client.account.get();\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n });\n\n// Path shortcut - handle as fallback\nprogram\n .argument('[path]', 'Path to deploy (shortcut)')\n .option('--preserve-dirs', 'Preserve directory structure (by default, common parent directories are flattened)')\n .action(async (path?: string, cmdOptions?: any) => {\n // If no path provided, show help\n if (!path) {\n program.help();\n return;\n }\n \n // Check if looks like a path (shortcut: ship ./path)\n if (path.startsWith('./') || path.startsWith('/') || path.startsWith('~') || path.includes('/')) {\n try {\n const client = createClient();\n const deployOptions: any = {};\n \n if (cmdOptions?.preserveDirs) {\n deployOptions.preserveDirs = true;\n }\n \n const result = await client.deployments.create([path], deployOptions);\n output(result);\n } catch (error: any) {\n handleError(error);\n }\n } else {\n console.error('Unknown command:', path);\n console.error('Use \"ship --help\" for available commands');\n process.exit(1);\n }\n });\n\n\nif (process.env.NODE_ENV !== 'test') {\n program.parse(process.argv);\n}","/**\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 { ShipClientOptions, DeploymentOptions, ShipError } from '../types.js';\nimport { getENV } from '../lib/env.js';\nimport { DEFAULT_API } from './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}).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 * @returns Configuration object or empty if not found/invalid\n * @internal\n */\nasync function loadConfigFromFile(): 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 only in Node.js environments\n const { cosmiconfigSync } = await import('cosmiconfig');\n \n const explorer = cosmiconfigSync(MODULE_NAME, {\n searchPlaces: [\n `.${MODULE_NAME}rc`,\n 'package.json',\n ],\n });\n \n const result = explorer.search();\n if (result && !result.isEmpty && 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 * @returns Configuration object with loaded values\n * @throws {ShipInvalidConfigError} If the configuration is invalid.\n */\nexport async function loadConfig(): 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 };\n\n // Always try to load file config for fallback values\n const fileConfig = await loadConfigFromFile();\n\n // Merge with environment variables taking precedence\n const mergedConfig = {\n apiUrl: envConfig.apiUrl ?? fileConfig.apiUrl,\n apiKey: envConfig.apiKey ?? fileConfig.apiKey,\n };\n\n // Validate final config\n return validateConfig(mergedConfig);\n}\n\n/**\n * Simplified configuration resolution with clear precedence.\n * Precedence: user options > environment variables > config files > defaults.\n * \n * @param userOptions - Options provided directly by the user\n * @param loadedConfig - Configuration loaded from environment/files\n * @returns Resolved configuration with api and apiKey\n */\nexport function resolveConfig(\n userOptions: ShipClientOptions = {}, \n loadedConfig: Partial<ShipClientOptions> = {}\n): { apiUrl: string; apiKey?: string } {\n // Build final config with clear precedence\n const finalConfig = {\n apiUrl: userOptions.apiUrl || loadedConfig.apiUrl || DEFAULT_API,\n apiKey: userOptions.apiKey !== undefined ? userOptions.apiKey : loadedConfig.apiKey,\n };\n\n // Return with optional apiKey\n return finalConfig.apiKey !== undefined \n ? { apiUrl: finalConfig.apiUrl, apiKey: finalConfig.apiKey }\n : { apiUrl: finalConfig.apiUrl };\n}\n\n\n// =============================================================================\n// CONFIGURATION MERGING\n// =============================================================================\n\n/**\n * Merge deployment options with client defaults.\n * Simple utility function that replaces the unnecessary ConfigMerger class.\n */\nexport function mergeDeployOptions(\n userOptions: DeploymentOptions = {},\n clientDefaults: ShipClientOptions\n): DeploymentOptions {\n const merged: DeploymentOptions = { ...userOptions };\n \n // Only set defaults if not already provided\n if (merged.onProgress === undefined && clientDefaults.onProgress !== undefined) {\n merged.onProgress = clientDefaults.onProgress;\n }\n if (merged.onProgressStats === undefined && clientDefaults.onProgressStats !== undefined) {\n merged.onProgressStats = clientDefaults.onProgressStats;\n }\n if (merged.maxConcurrency === undefined && clientDefaults.maxConcurrentDeploys !== undefined) {\n merged.maxConcurrency = clientDefaults.maxConcurrentDeploys;\n }\n if (merged.timeout === undefined && clientDefaults.timeout !== undefined) {\n merged.timeout = clientDefaults.timeout;\n }\n if (merged.apiKey === undefined && clientDefaults.apiKey !== undefined) {\n merged.apiKey = clientDefaults.apiKey;\n }\n if (merged.apiUrl === undefined && clientDefaults.apiUrl !== undefined) {\n merged.apiUrl = clientDefaults.apiUrl;\n }\n \n return merged;\n}\n","/**\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// ENVIRONMENT-SPECIFIC TYPES\n// =============================================================================\n\n/**\n * Consolidated input type for all environments\n */\nexport type DeployInput = FileList | File[] | HTMLInputElement | string[];\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 /** The API key to use for this specific deploy. Overrides client's default. */\n apiKey?: string;\n /** Whether to preserve directory structure. By default, common parent directories are flattened. */\n preserveDirs?: 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, 'preserveDirs'>;\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, key, 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 /** Default API key for the client instance. */\n apiKey?: 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 maxConcurrentDeploys?: 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// =============================================================================\n// FILE REPRESENTATION\n// =============================================================================\n\n/**\n * Represents a file that has been processed and is ready for deploy.\n * Used internally by the SDK and in advanced/manual deploy scenarios.\n */\nexport interface StaticFile {\n /**\n * The content of the file.\n * In Node.js, this is typically a `Buffer`.\n * In the browser, this is typically a `File` or `Blob` object.\n */\n content: File | Buffer | Blob;\n /**\n * The desired path for the file on the server, relative to the deployment root.\n * Should include the filename, e.g., `images/photo.jpg`.\n */\n path: string;\n /**\n * The original absolute file system path (primarily used in Node.js environments).\n * This helps in debugging or associating the server path back to its source.\n */\n filePath?: string;\n /**\n * The MD5 hash (checksum) of the file's content.\n * This is calculated by the SDK before deploy if not provided.\n */\n md5?: string;\n /** The size of the file in bytes. */\n size: number;\n}\n\n// =============================================================================\n// API RESPONSES\n// =============================================================================\n\n// PingResponse is imported from @shipstatic/types (single source of truth)","/**\n * @file Shared, environment-agnostic constants.\n */\n\n/** Default API URL if not otherwise configured. */\nexport const DEFAULT_API = 'https://api.shipstatic.com';\n\n/** API key prefix for validation and generation */\nexport const API_KEY_PREFIX = 'ship-';","/**\n * @file Manages HTTP requests to the Ship API using native fetch.\n */\nimport * as _mime from 'mime-types';\nimport type { Deployment, DeploymentListResponse, PingResponse, ConfigResponse, DeploymentRemoveResponse, Alias, AliasListResponse, Account } from '@shipstatic/types';\nimport { StaticFile, ApiDeployOptions, ShipClientOptions } from '../types.js';\nimport { ShipError } from '@shipstatic/types';\nimport { getENV } from '../lib/env.js';\nimport { DEFAULT_API } from '../core/constants.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\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\n /**\n * Constructs a new ApiHttp instance with the provided client options.\n * @param options - Client options including API host, apiKey, and timeout settings.\n */\n constructor(options: ShipClientOptions) {\n this.apiUrl = options.apiUrl || DEFAULT_API;\n this.apiKey = options.apiKey ?? \"\";\n }\n\n /**\n * Generates common headers for API requests, including the API key if present.\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 if (this.apiKey) {\n headers['Authorization'] = `Bearer ${this.apiKey}`;\n }\n return headers;\n }\n\n /**\n * Makes a fetch request with common error handling and authentication.\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 credentials: getENV() === 'browser' ? 'include' : 'same-origin',\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 * 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 } = options;\n\n try {\n const { requestBody, requestHeaders } = await this.#prepareRequestPayload(files);\n \n const fetchOptions: RequestInit = {\n method: 'POST',\n body: requestBody,\n headers: requestHeaders,\n signal: signal || null\n };\n\n const response = await this.#fetchWithAuth(`${apiUrl}${DEPLOY_ENDPOINT}`, fetchOptions, 'Deploy');\n \n if (!response.ok) {\n await this.#handleResponseError(response, 'Deploy');\n }\n \n return await response.json() as Deployment;\n } catch (error: any) {\n if (error instanceof ShipError) {\n throw error;\n }\n this.#handleFetchError(error, 'Deploy');\n // This line is unreachable because #handleFetchError always throws.\n // However, TypeScript requires a return statement here.\n throw ShipError.business('An unexpected error occurred and was not handled.');\n }\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 | Buffer;\n requestHeaders: Record<string, string>;\n }> {\n let requestBody: FormData | Buffer;\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;\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 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 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], pathImport.basename(file.path), { type: contentType });\n } else if (typeof Blob !== \"undefined\" && file.content instanceof Blob) {\n fileNodeInstance = new FileNodeClass([file.content], pathImport.basename(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 throw ShipError.api(\n message,\n response.status,\n errorData.code,\n errorData\n );\n }\n\n // Fallback for completely unstructured errors\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 deploymentName - Deployment name to point to\n * @returns Promise resolving to the created/updated alias\n */\n public async setAlias(name: string, deploymentName: string): Promise<Alias> {\n return await this.#request<Alias>(`${this.apiUrl}${ALIASES_ENDPOINT}/${encodeURIComponent(name)}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ deploymentId: deploymentName })\n }, 'Set Alias');\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 * 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 * @file Main entry point for the Ship SDK.\n * This module provides a simplified class-based SDK interface similar to Vercel's approach.\n */\n\n// Core imports\nimport { getENV } from './lib/env.js';\nimport { loadConfig, resolveConfig } from './core/config.js';\nimport { ApiHttp } from './api/http.js';\nimport { ShipError } from '@shipstatic/types';\nimport { setConfig } from './core/platform-config.js';\nimport type { ShipClientOptions } from './types.js';\n\n// Resource imports\nimport { createDeploymentResource, createAliasResource, createAccountResource, createKeysResource } from './resources.js';\nimport type { DeploymentResource, AliasResource, AccountResource, KeysResource, DeployInput } from './resources.js';\nimport type { DeploymentOptions } from './types.js';\nimport type { Deployment } from '@shipstatic/types';\n\n\n\n// Re-export types from deploy types\nexport type { DeployInput, DeploymentOptions } from './types.js';\n\n\n/**\n * Ship SDK Client - Universal class-based interface for both Node.js and browser environments.\n * \n * Similar to Vercel's SDK approach:\n * ```\n * const ship = new Ship({ apiKey: \"your-api-key\" });\n * ```\n * \n * Automatically detects the environment and handles Node.js and browser deploys directly.\n * In Node.js environments, loads configuration from files and environment variables.\n * In browser environments, uses only the provided options.\n */\n/**\n * Ship SDK Client - Simplified single class supporting both Node.js and browser environments\n */\nexport class Ship {\n private http: ApiHttp;\n private environment: 'node' | 'browser';\n private configInitialized: boolean = false;\n private configLoaded: boolean = false;\n private readonly clientOptions: ShipClientOptions;\n \n // Resource instances (lazy-loaded)\n private _deployments?: DeploymentResource;\n private _aliases?: AliasResource;\n private _account?: AccountResource;\n private _keys?: KeysResource;\n\n constructor(options: ShipClientOptions = {}) {\n this.clientOptions = options;\n this.environment = getENV() as 'node' | 'browser';\n \n if (this.environment !== 'node' && this.environment !== 'browser') {\n throw ShipError.business('Unsupported execution environment.');\n }\n \n // Initialize HTTP client with ONLY constructor options for now.\n // The full config will be loaded and applied lazily.\n const config = resolveConfig(options, {});\n this.http = new ApiHttp({ ...options, ...config });\n }\n\n /**\n * Initialize config from file/env and platform config from API (called automatically on first use)\n */\n private async initializeConfig(): Promise<void> {\n if (this.configInitialized) return;\n\n // Load config from file/env if not already done\n if (!this.configLoaded) {\n const loadedConfig = await loadConfig();\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 this.configLoaded = true;\n }\n \n const platformConfig = await this.http.getConfig();\n setConfig(platformConfig);\n this.configInitialized = true;\n }\n\n /**\n * Ping the API server to check connectivity\n */\n async ping(): Promise<boolean> {\n await this.initializeConfig();\n return this.http.ping();\n }\n\n /**\n * Get deployments resource (environment-specific)\n */\n get deployments() {\n if (!this._deployments) {\n this._deployments = createDeploymentResource(this.http, () => this.initializeConfig(), this.clientOptions);\n }\n return this._deployments;\n }\n \n /**\n * Get aliases resource\n */\n get aliases(): AliasResource {\n if (!this._aliases) {\n this._aliases = createAliasResource(this.http);\n }\n return this._aliases;\n }\n \n /**\n * Get account resource\n */\n get account(): AccountResource {\n if (!this._account) {\n this._account = createAccountResource(this.http);\n }\n return this._account;\n }\n \n /**\n * Get keys resource\n */\n get keys(): KeysResource {\n if (!this._keys) {\n this._keys = createKeysResource(this.http);\n }\n return this._keys;\n }\n\n /**\n * Deploy files (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\n// Default export (for import Ship from 'ship')\nexport default Ship;\n\n// Export all public types\nexport type { StaticFile, ShipClientOptions, ApiDeployOptions, ProgressStats } from './types.js';\nexport type { PingResponse } from '@shipstatic/types';\n\n// Export resource types\nexport type { DeploymentResource, AliasResource, AccountResource, KeysResource } from './resources.js';\n\n// Export main error class and error type enum\nexport { ShipError, ShipErrorType } from '@shipstatic/types';\n\n// Advanced/utility exports (for tests and power users; subject to change)\nexport { processFilesForNode } from './lib/node-files.js';\nexport { processFilesForBrowser } from './lib/browser-files.js';\n\n// Test utilities\n/**\n * @internal\n * Test utility to set the execution environment (e.g., 'node', 'browser').\n * This should not be used in production code.\n */\nexport { __setTestEnvironment } from './lib/env.js';\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 Input conversion utilities for deployment\n * Converts various input types to StaticFile[] for unified processing\n */\n\nimport type { StaticFile, DeploymentOptions, DeployInput } from '../types.js';\nimport { ShipError } from '@shipstatic/types';\nimport { getENV } from './env.js';\nimport { processFilesForNode } from './node-files.js';\nimport { processFilesForBrowser } from './browser-files.js';\nimport { getCurrentConfig } from '../core/platform-config.js';\n\n/**\n * Unified validation for file count and size limits\n * @param fileCount - Number of files \n * @param totalSize - Total size in bytes (optional, for size validation)\n * @throws {ShipError} If limits are exceeded\n * @internal\n */\nfunction validateLimits(fileCount: number, totalSize?: number): void {\n const config = getCurrentConfig();\n \n if (fileCount === 0) {\n throw ShipError.business('No files to deploy.');\n }\n \n if (fileCount > config.maxFilesCount) {\n throw ShipError.business(`Too many files to deploy. Maximum allowed is ${config.maxFilesCount}.`);\n }\n \n if (totalSize !== undefined && 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 * Validates individual file size against platform limits\n * @param fileName - Name of the file for error messages\n * @param fileSize - Size of the file in bytes\n * @throws {ShipError} If file is too large\n * @internal\n */\nfunction validateFileSize(fileName: string, fileSize: number): void {\n const config = getCurrentConfig();\n \n if (fileSize > config.maxFileSize) {\n throw ShipError.business(`File ${fileName} is too large. Maximum allowed size is ${config.maxFileSize / (1024 * 1024)}MB.`);\n }\n}\n\n/**\n * Comprehensive file validation for both Node.js and browser environments\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\n if (!options.skipEmptyCheck && files.length === 0) {\n throw ShipError.business('No files to deploy.');\n }\n \n // Check file count limit\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\n let totalSize = 0;\n for (const file of files) {\n // Individual file size validation\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 totalSize += file.size;\n }\n \n // Total size validation\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 * 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\n validateFiles(files, { 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 if (!Array.isArray(input) || !input.every(item => typeof item === 'string')) {\n throw ShipError.business('Invalid input type for Node.js environment. Expected string[] file paths.');\n }\n \n // Initial validation - just check input count\n if (input.length === 0) {\n throw ShipError.business('No files to deploy.');\n }\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 let fileArray: File[];\n \n if (input instanceof HTMLInputElement) {\n if (!input.files) throw ShipError.business('No files selected in 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\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\n * Converts any DeployInput to StaticFile[] based on environment\n */\nexport async function convertDeployInput(\n input: DeployInput,\n options: DeploymentOptions = {}\n): Promise<StaticFile[]> {\n const environment = getENV();\n \n if (environment === 'node') {\n if (!Array.isArray(input) || !input.every(item => typeof item === 'string')) {\n throw ShipError.business('Invalid input type for Node.js environment. Expected string[] file paths.');\n }\n return convertNodeInput(input as string[], options);\n } else if (environment === 'browser') {\n if (!(input instanceof HTMLInputElement || Array.isArray(input) || \n (typeof FileList !== 'undefined' && input instanceof FileList))) {\n throw ShipError.business('In browser, input must be FileList, File[], or HTMLInputElement.');\n }\n return convertBrowserInput(input as FileList | File[] | HTMLInputElement, options);\n } else {\n throw ShipError.business('Unsupported execution environment.');\n }\n}","/**\n * @file Simplified MD5 calculation utility with separate environment handlers.\n */\nimport { getENV } from './env';\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 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 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 './env.js';\nimport { StaticFile, DeploymentOptions } from '../types.js';\nimport { calculateMD5 } from './md5.js';\nimport { filterJunk } from './junk.js';\nimport { ShipError } from '@shipstatic/types';\nimport { getCurrentConfig } from '../core/platform-config.js';\nimport { findCommonParent } from './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 * Clean, declarative function to get files from a source path.\n * Follows the suggested architectural pattern from the feedback.\n * @param sourcePath - File or directory path to process\n * @param options - Options for processing (basePath, preserveDirs)\n * @returns Promise resolving to array of StaticFile objects\n */\nexport async function getFilesFromPath(\n sourcePath: string, \n options: DeploymentOptions = {}\n): Promise<StaticFile[]> {\n const absolutePath = path.resolve(sourcePath);\n \n // 1. Discover all files\n const allPaths = (() => {\n const stats = fs.statSync(absolutePath);\n if (stats.isFile()) {\n return [absolutePath];\n } else if (stats.isDirectory()) {\n return findAllFilePaths(absolutePath);\n } else {\n return [];\n }\n })();\n \n // 2. Filter out junk\n const validPaths = allPaths.filter(p => {\n const basename = path.basename(p);\n return filterJunk([basename]).length > 0; // Keep files that pass junk filter\n });\n \n // 3. Determine base for relative paths (simplified with unified logic)\n const stats = fs.statSync(absolutePath);\n let commonParent: string;\n \n if (options.preserveDirs) {\n // Preserve directory structure: use source directory\n commonParent = stats.isDirectory() ? absolutePath : path.dirname(absolutePath);\n } else {\n // Default: flatten by finding common parent of all file directories\n const fileDirs = validPaths.map(filePath => path.dirname(filePath));\n commonParent = findCommonParent(fileDirs);\n }\n \n // 4. Process into StaticFile objects\n const results: StaticFile[] = [];\n let totalSize = 0;\n \n for (const filePath of validPaths) {\n try {\n // Validate file\n const stats = fs.statSync(filePath);\n \n if (stats.size === 0) {\n console.warn(`Skipping empty file: ${filePath}`);\n continue;\n }\n \n const platformLimits = getCurrentConfig();\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 \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 // Read content and calculate metadata\n const content = fs.readFileSync(filePath);\n const { md5 } = await calculateMD5(content);\n let relativePath = path.relative(commonParent, filePath).replace(/\\\\/g, '/');\n \n // Security validation: Ensure no dangerous characters in paths\n if (relativePath.includes('..') || relativePath.includes('\\0')) {\n // Instead of throwing an error, let's normalize the path safely\n // This handles cases where path.relative might generate .. sequences\n relativePath = path.basename(filePath);\n }\n \n // Ensure path is not empty (this can happen if file equals commonParent)\n if (!relativePath) {\n relativePath = path.basename(filePath);\n }\n \n results.push({\n path: relativePath,\n content: 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 // Validate total file count\n const platformLimits = getCurrentConfig();\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\n\n/**\n * Processes Node.js file and directory paths into an array of StaticFile objects ready for deploy.\n * Now uses the simplified, declarative approach suggested in the feedback.\n * \n * @param paths - File or directory paths to scan and process.\n * @param options - Processing options (basePath, preserveDirs).\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 a Node.js environment.');\n }\n\n // Handle multiple paths\n if (paths.length > 1) {\n const allResults: StaticFile[] = [];\n for (const singlePath of paths) {\n const results = await getFilesFromPath(singlePath, options);\n allResults.push(...results);\n }\n return allResults;\n }\n\n // Single path - use the getFilesFromPath function\n return await getFilesFromPath(paths[0], options);\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(/^\\/+/, '');\n}\n\n/**\n * Ensures a path is relative by normalizing it and removing any leading slashes.\n * @param path - The path to make relative\n * @returns Relative path suitable for web deployment\n */\nexport function ensureRelativePath(path: string): string {\n return normalizeWebPath(path);\n}\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 { getENV } from './env.js';\nimport { StaticFile, DeploymentOptions } from '../types.js';\nimport { calculateMD5 } from './md5.js';\nimport { ShipError } from '@shipstatic/types';\nimport { findCommonParent, normalizeWebPath } from './path.js';\nimport { filterJunk } from './junk.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 determines relative paths (stripping basePath if provided).\n *\n * @param browserFiles - FileList or File[] to process for deploy.\n * @param options - Optional processing options (basePath for path stripping, preserveDirs).\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 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 // Determine common parent for flattening (unified logic) - now default behavior\n let commonParent = '';\n if (!options.preserveDirs) {\n // Default: flatten by finding common parent of all file directories\n const fileDirs = filesArray\n .map(file => (file as any).webkitRelativePath || file.name)\n .filter(path => path)\n .map(filePath => filePath.includes('/') ? filePath.substring(0, filePath.lastIndexOf('/')) : '');\n \n commonParent = findCommonParent(fileDirs);\n }\n\n // Prepare file information with appropriate relative paths\n const initialFileInfos: BrowserFileProcessItem[] = [];\n for (const file of filesArray) {\n let relativePath = (file as any).webkitRelativePath || file.name;\n \n // Apply flattening logic (default behavior unless preserveDirs is true)\n if (commonParent && !options.preserveDirs) {\n relativePath = normalizeWebPath(relativePath);\n const basePathWithSlash = commonParent.endsWith('/') ? commonParent : `${commonParent}/`;\n if (relativePath.startsWith(basePathWithSlash)) {\n relativePath = relativePath.substring(basePathWithSlash.length);\n } else if (relativePath === commonParent) {\n relativePath = '';\n }\n }\n \n // Always normalize to web paths (forward slashes, no leading slash)\n relativePath = normalizeWebPath(relativePath);\n \n // Security validation: Ensure no dangerous characters in paths\n if (relativePath.includes('..') || relativePath.includes('\\0')) {\n throw ShipError.business(`Security error: Unsafe file path \"${relativePath}\" for file: ${file.name}`);\n }\n \n // Ensure path is not empty\n if (!relativePath) {\n relativePath = file.name;\n }\n \n initialFileInfos.push({ file, relativePath });\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 and empty files\n if (!nonJunkRelativePathsSet.has(fileInfo.relativePath) || fileInfo.file.size === 0) {\n continue;\n }\n \n // Calculate MD5 hash\n const { md5 } = await calculateMD5(fileInfo.file);\n \n // Create and add the StaticFile\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 All Ship SDK resources in one place - impossibly simple.\n */\nimport type { Deployment, DeploymentListResponse, Alias, AliasListResponse, Account } from '@shipstatic/types';\nimport type { ApiHttp } from './api/http.js';\nimport type { StaticFile, ShipClientOptions } from './types.js';\nimport type { DeploymentOptions, DeployInput } from './types.js';\nimport { convertDeployInput } from './lib/prepare-input.js';\nimport { mergeDeployOptions } from './core/config.js';\n\n// Re-export DeployInput for external use\nexport type { DeployInput };\n\n// =============================================================================\n// DEPLOYMENT RESOURCE\n// =============================================================================\n\nexport interface DeploymentResource {\n create: (input: DeployInput, options?: DeploymentOptions) => Promise<Deployment>;\n list: () => Promise<DeploymentListResponse>;\n remove: (id: string) => Promise<void>;\n get: (id: string) => Promise<Deployment>;\n}\n\nexport function createDeploymentResource(\n api: ApiHttp, \n initConfig?: () => Promise<void>,\n clientDefaults?: ShipClientOptions\n): DeploymentResource {\n return {\n create: async (input: DeployInput, options: DeploymentOptions = {}) => {\n // Initialize config from API before validation\n if (initConfig) {\n await initConfig();\n }\n \n // Merge user options with client defaults\n const mergedOptions = clientDefaults \n ? mergeDeployOptions(options, clientDefaults)\n : options;\n \n // Convert input to StaticFile[] using unified utility\n const staticFiles: StaticFile[] = await convertDeployInput(input, mergedOptions);\n \n // Deploy using the API - now returns the full Deployment object directly\n return await api.deploy(staticFiles, mergedOptions);\n },\n\n list: async () => {\n return api.listDeployments();\n },\n\n remove: async (id: string) => {\n await api.removeDeployment(id);\n // Return void for deletion operations\n },\n\n get: async (id: string) => {\n return api.getDeployment(id);\n }\n };\n}\n\n// =============================================================================\n// ALIAS RESOURCE\n// =============================================================================\n\nexport interface AliasResource {\n set: (aliasName: string, deploymentName: string) => Promise<Alias>;\n get: (aliasName: string) => Promise<Alias>;\n list: () => Promise<AliasListResponse>;\n remove: (aliasName: string) => Promise<void>;\n}\n\nexport function createAliasResource(api: ApiHttp): AliasResource {\n return {\n set: async (aliasName: string, deploymentName: string) => {\n // Set alias and return the created/updated alias directly\n return api.setAlias(aliasName, deploymentName);\n },\n\n get: async (aliasName: string) => {\n return api.getAlias(aliasName);\n },\n\n list: async () => {\n return api.listAliases();\n },\n\n remove: async (aliasName: string) => {\n await api.removeAlias(aliasName);\n // Return void for deletion operations\n }\n };\n}\n\n// =============================================================================\n// ACCOUNT RESOURCE\n// =============================================================================\n\nexport interface AccountResource {\n get: () => Promise<Account>;\n}\n\nexport function createAccountResource(api: ApiHttp): AccountResource {\n return {\n get: async () => {\n return api.getAccount();\n }\n };\n}\n\n// =============================================================================\n// KEYS RESOURCE\n// =============================================================================\n\nexport interface KeysResource {\n create: () => Promise<{ apiKey: string }>;\n}\n\nexport function createKeysResource(api: ApiHttp): KeysResource {\n return {\n create: async () => {\n return api.createApiKey();\n }\n };\n}"],"mappings":"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","names":["import_commander","_testEnvironment","detectEnvironment","getENV","_testEnvironment","import_zod","types_exports","__reExport","DEFAULT_API","MODULE_NAME","ConfigSchema","validateConfig","config","error","firstError","path","loadConfigFromFile","getENV","cosmiconfigSync","result","loadConfig","envConfig","fileConfig","mergedConfig","resolveConfig","userOptions","loadedConfig","finalConfig","DEFAULT_API","mergeDeployOptions","clientDefaults","merged","_mime","import_types","DEPLOY_ENDPOINT","PING_ENDPOINT","ALIASES_ENDPOINT","CONFIG_ENDPOINT","ACCOUNT_ENDPOINT","getBrowserContentType","file","collectAsyncIterable","iterable","result","x","ApiHttp","options","DEFAULT_API","#getAuthHeaders","customHeaders","headers","#fetchWithAuth","url","operationName","fetchOptions","getENV","error","#handleFetchError","#request","response","#handleResponseError","files","#validateFiles","apiUrl","signal","requestBody","requestHeaders","#prepareRequestPayload","#createBrowserBody","body","#createNodeBody","formData","checksums","i","fileContent","contentType","fileWithPath","FormDataNodeClass","FileNodeClass","FormDataEncoderClass","pathImport","formDataNodeInstance","fileNodeInstance","preservedPath","encoder","encodedChunks","chunk","errorData","message","id","name","deploymentName","import_types","import_types","_config","setConfig","config","getCurrentConfig","import_types","import_types","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_junk","JUNK_DIRECTORIES","filterJunk","filePaths","filePath","parts","basename","directorySegments","segment","junkDir","import_types","findCommonParent","dirPaths","normalizedPaths","p","pathSegments","commonSegments","minLength","i","segment","segments","normalizeWebPath","path","fs","path","findAllFilePaths","dirPath","results","entries","entry","fullPath","stats","subFiles","error","getFilesFromPath","sourcePath","options","absolutePath","validPaths","p","basename","filterJunk","commonParent","fileDirs","filePath","findCommonParent","totalSize","platformLimits","getCurrentConfig","content","md5","calculateMD5","relativePath","processFilesForNode","paths","getENV","allResults","singlePath","import_types","processFilesForBrowser","browserFiles","options","getENV","filesArray","commonParent","fileDirs","file","path","filePath","findCommonParent","initialFileInfos","relativePath","normalizeWebPath","basePathWithSlash","allRelativePaths","info","nonJunkRelativePathsArray","filterJunk","nonJunkRelativePathsSet","result","fileInfo","md5","calculateMD5","validateFiles","files","options","config","getCurrentConfig","totalSize","file","postProcessFiles","f","convertNodeInput","input","item","staticFiles","processFilesForNode","convertBrowserInput","fileArray","processFilesForBrowser","convertDeployInput","environment","getENV","createDeploymentResource","api","initConfig","clientDefaults","input","options","mergedOptions","mergeDeployOptions","staticFiles","convertDeployInput","id","createAliasResource","aliasName","deploymentName","createAccountResource","createKeysResource","import_types","Ship","options","getENV","config","resolveConfig","ApiHttp","loadedConfig","loadConfig","finalConfig","platformConfig","setConfig","createDeploymentResource","createAliasResource","createAccountResource","createKeysResource","input","import_fs","path","packageJson","possiblePaths","packageJsonPath","program","handleError","error","createClient","options","Ship","formatters","result","d","a","output","key","formatter","success","deploymentsCmd","cmdOptions","client","deployOptions","id","aliasesCmd","name","deployment","accountCmd"]}