@nmakarov/cli-toolkit 0.18.0 → 0.23.0

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.
Files changed (69) hide show
  1. package/README.md +9 -0
  2. package/dist/args.cjs +1 -4
  3. package/dist/args.cjs.map +1 -1
  4. package/dist/args.js +1 -1
  5. package/dist/args.js.map +1 -1
  6. package/dist/cli-runner.cjs +1493 -516
  7. package/dist/cli-runner.cjs.map +1 -1
  8. package/dist/cli-runner.js +1509 -531
  9. package/dist/cli-runner.js.map +1 -1
  10. package/dist/db.cjs +85 -157
  11. package/dist/db.cjs.map +1 -1
  12. package/dist/db.js +84 -150
  13. package/dist/db.js.map +1 -1
  14. package/dist/errors.cjs +2 -2
  15. package/dist/errors.cjs.map +1 -1
  16. package/dist/errors.js +2 -1
  17. package/dist/errors.js.map +1 -1
  18. package/dist/filedatabase.cjs +19 -19
  19. package/dist/filedatabase.cjs.map +1 -1
  20. package/dist/filedatabase.js +19 -16
  21. package/dist/filedatabase.js.map +1 -1
  22. package/dist/http-client.cjs +9 -11
  23. package/dist/http-client.cjs.map +1 -1
  24. package/dist/http-client.js +10 -9
  25. package/dist/http-client.js.map +1 -1
  26. package/dist/http-client2.cjs +34 -33
  27. package/dist/http-client2.cjs.map +1 -1
  28. package/dist/http-client2.js +34 -30
  29. package/dist/http-client2.js.map +1 -1
  30. package/dist/index.cjs +2063 -658
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.js +2063 -663
  33. package/dist/index.js.map +1 -1
  34. package/dist/init.cjs +97 -69
  35. package/dist/init.cjs.map +1 -1
  36. package/dist/init.js +112 -83
  37. package/dist/init.js.map +1 -1
  38. package/dist/logger.cjs +5 -5
  39. package/dist/logger.cjs.map +1 -1
  40. package/dist/logger.js +5 -4
  41. package/dist/logger.js.map +1 -1
  42. package/dist/mock-server.cjs +21 -33
  43. package/dist/mock-server.cjs.map +1 -1
  44. package/dist/mock-server.js +21 -28
  45. package/dist/mock-server.js.map +1 -1
  46. package/dist/params.cjs +22 -10
  47. package/dist/params.cjs.map +1 -1
  48. package/dist/params.js +22 -7
  49. package/dist/params.js.map +1 -1
  50. package/dist/s3.cjs +286 -0
  51. package/dist/s3.cjs.map +1 -0
  52. package/dist/s3.js +273 -0
  53. package/dist/s3.js.map +1 -0
  54. package/dist/screen.cjs +34 -39
  55. package/dist/screen.cjs.map +1 -1
  56. package/dist/screen.js +48 -46
  57. package/dist/screen.js.map +1 -1
  58. package/dist/tasks.cjs +1640 -416
  59. package/dist/tasks.cjs.map +1 -1
  60. package/dist/tasks.js +1614 -412
  61. package/dist/tasks.js.map +1 -1
  62. package/dist/utils.cjs +7 -8
  63. package/dist/utils.cjs.map +1 -1
  64. package/dist/utils.js +6 -6
  65. package/dist/utils.js.map +1 -1
  66. package/package.json +36 -44
  67. package/scripts/ssm/parse-cli.js +35 -0
  68. package/scripts/ssm/ssm-admin.js +151 -0
  69. package/scripts/ssm/ssm-pull.js +147 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/http-client.ts","../src/http-client/index.ts","../src/errors.ts","../src/http-client/errors.ts","../src/http-client/retry.ts"],"sourcesContent":["// HttpClient module exports\nexport { HttpClient, HttpClientError } from './http-client/index.js';\nexport type {\n HttpClientConfig,\n RequestOptions,\n HttpClientResponse,\n HttpMethod,\n HttpClientErrorType,\n HttpClientStatus\n} from './http-client/types.js';\n","/**\n * HttpClient - Resilient HTTP Client with Retry Logic\n *\n * A production-ready HTTP client that:\n * - Wraps axios with enhanced error handling and retry logic\n * - Never throws exceptions - always returns unified response format\n * - Uses exponential backoff with jitter for retries\n * - Provides human-readable error classifications\n * - Supports comprehensive logging\n * - Handles all HTTP methods consistently\n */\n\nimport axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';\nimport type {\n HttpClientConfig,\n RequestOptions,\n HttpClientResponse,\n HttpMethod,\n HttpClientStatus,\n RetryContext\n} from './types.js';\nimport { HttpClientError } from '../errors.js';\nimport { classifyError, getErrorDescription } from './errors.js';\nimport { calculateRetryDelay, sleep, shouldRetryError, createRetryContext, updateRetryContext } from './retry.js';\n\nexport { HttpClientError };\n\n/**\n * Resilient HTTP Client with automatic retry logic.\n * Use HttpClient.init(context, options) when running with init/context; constructor(config) for standalone.\n */\nexport class HttpClient {\n private axiosInstance: AxiosInstance;\n private config: HttpClientConfig;\n private logger: any;\n\n constructor(contextOrConfig: any = {}, config?: HttpClientConfig) {\n const hasContext = config !== undefined;\n const options: HttpClientConfig = hasContext ? config! : (contextOrConfig || {});\n const context = hasContext ? contextOrConfig : undefined;\n\n this.config = {\n ...options,\n logger: context?.logger ?? options.logger ?? console,\n };\n this.logger = this.config.logger;\n\n this.axiosInstance = axios.create({\n timeout: this.config.timeout,\n validateStatus: () => true,\n maxRedirects: this.config.maxRedirects,\n headers: { 'User-Agent': this.config.userAgent },\n httpsAgent: this.config.validateSSL ? undefined : { rejectUnauthorized: false } as any,\n });\n\n // Add response interceptor for logging (optional - only if debug enabled)\n this.axiosInstance.interceptors.response.use(\n (response) => response,\n (error) => {\n // Log network-level errors here if needed\n // (HTTP errors are handled in the request method)\n return Promise.reject(error);\n }\n );\n }\n\n /**\n * Static init - discovers params via getAllForModule(defs). Whatever is in options goes.\n */\n static init(context: any, options: HttpClientConfig = {}): HttpClient {\n const defs: Record<string, string> = {\n timeout: 'number default 30000',\n retryCount: 'number default 3',\n retryDelay: 'number default 1000',\n maxRetryDelay: 'number default 30000',\n retryJitter: 'number default 0.1',\n userAgent: 'string default HttpClient/v1.0',\n validateSSL: 'boolean default true',\n maxRedirects: 'number default 5',\n };\n const discovered = context?.params?.getAllForModule?.(defs) ?? {};\n const merged: HttpClientConfig = { ...discovered, ...options, logger: options.logger ?? context?.logger };\n return new HttpClient(context, merged);\n }\n\n /**\n * Make an HTTP request with automatic retry logic\n * Never throws - always returns HttpClientResponse\n */\n async request(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {}\n ): Promise<HttpClientResponse> {\n const startTime = Date.now();\n\n // Merge request options with defaults\n const requestConfig: AxiosRequestConfig = {\n method,\n url,\n timeout: options.timeout ?? this.config.timeout,\n headers: {\n 'User-Agent': options.userAgent ?? this.config.userAgent,\n ...options.headers\n },\n params: options.params,\n data: options.data\n };\n\n const retryCount = options.retryCount ?? this.config.retryCount;\n const retryDelay = options.retryDelay ?? this.config.retryDelay;\n\n // Initialize retry context\n let retryContext: RetryContext | null = null;\n let lastError: any = null;\n\n // Attempt the request with retries\n for (let attempt = 1; attempt <= retryCount + 1; attempt++) {\n try {\n if (options.debug) {\n this.logger.debug?.(`[HttpClient] ${method} ${url} (attempt ${attempt}/${retryCount + 1})`);\n }\n\n const response: AxiosResponse = await this.axiosInstance.request(requestConfig);\n const duration = Date.now() - startTime;\n\n // Success! Return unified response format\n const customStatus = this.mapHttpStatusToCustomStatus(response.status);\n\n if (options.debug) {\n this.logger.debug?.(`[HttpClient] ${method} ${url} → ${response.status} ${customStatus} (${duration}ms)`);\n }\n\n return {\n status: customStatus,\n code: response.status,\n headers: response.headers as Record<string, string>,\n data: response.data,\n duration,\n retryCount: attempt - 1,\n finalUrl: response.request?.res?.responseUrl || url\n };\n\n } catch (error: any) {\n lastError = error;\n const duration = Date.now() - startTime;\n\n // Classify the error\n const classification = classifyError(error);\n const errorDescription = getErrorDescription(classification.type);\n\n // Log the error\n if (classification.retryable && attempt <= retryCount) {\n this.logger.warn?.(`[HttpClient] ${method} ${url} failed (${classification.type}): ${errorDescription}. Retrying in ${retryDelay}ms...`);\n } else if (!classification.retryable || attempt > retryCount) {\n this.logger.error?.(`[HttpClient] ${method} ${url} failed (${classification.type}): ${errorDescription}`);\n }\n\n // Check if we should retry\n if (attempt <= retryCount && shouldRetryError(classification)) {\n // Calculate delay and wait\n const delay = calculateRetryDelay(\n attempt,\n retryDelay,\n this.config.maxRetryDelay,\n this.config.retryJitter\n );\n\n if (options.debug) {\n this.logger.debug?.(`[HttpClient] Waiting ${delay}ms before retry ${attempt + 1}`);\n }\n\n await sleep(delay);\n continue;\n }\n\n // No more retries or not retryable - return error response\n return {\n status: classification.status,\n code: error.response?.status || null,\n error: classification.type,\n headers: error.response?.headers || null,\n data: error.response?.data || null,\n duration,\n retryCount: attempt - 1,\n finalUrl: url\n };\n }\n }\n\n // This should never be reached, but just in case\n return {\n status: 'unknown',\n code: null,\n error: 'unknown',\n headers: null,\n data: null,\n duration: Date.now() - startTime,\n retryCount: retryCount,\n finalUrl: url\n };\n }\n\n /**\n * GET request\n */\n async get(url: string, options: RequestOptions = {}): Promise<HttpClientResponse> {\n return this.request('GET', url, options);\n }\n\n /**\n * POST request\n */\n async post(url: string, options: RequestOptions = {}): Promise<HttpClientResponse> {\n return this.request('POST', url, options);\n }\n\n /**\n * PUT request\n */\n async put(url: string, options: RequestOptions = {}): Promise<HttpClientResponse> {\n return this.request('PUT', url, options);\n }\n\n /**\n * DELETE request\n */\n async delete(url: string, options: RequestOptions = {}): Promise<HttpClientResponse> {\n return this.request('DELETE', url, options);\n }\n\n /**\n * PATCH request\n */\n async patch(url: string, options: RequestOptions = {}): Promise<HttpClientResponse> {\n return this.request('PATCH', url, options);\n }\n\n /**\n * HEAD request\n */\n async head(url: string, options: RequestOptions = {}): Promise<HttpClientResponse> {\n return this.request('HEAD', url, options);\n }\n\n /**\n * OPTIONS request\n */\n async options(url: string, options: RequestOptions = {}): Promise<HttpClientResponse> {\n return this.request('OPTIONS', url, options);\n }\n\n /**\n * Map HTTP status code to custom status\n */\n private mapHttpStatusToCustomStatus(httpStatus: number): HttpClientStatus {\n if (httpStatus >= 200 && httpStatus < 300) {\n return 'success';\n } else if (httpStatus === 401) {\n return 'authRequired';\n } else if (httpStatus === 403) {\n return 'authFailed';\n } else if (httpStatus >= 400 && httpStatus < 500) {\n return 'clientError';\n } else if (httpStatus >= 500) {\n return 'serverError';\n }\n return 'unknown';\n }\n\n /**\n * Get current configuration (for debugging)\n */\n getConfig(): Readonly<HttpClientConfig> {\n return { ...this.config };\n }\n}\n","/**\n * Error classes for the CLI toolkit\n */\n\nexport class FrameworkError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"FrameworkError\";\n }\n}\n\nexport class ParamError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"ParamError\";\n }\n}\n\nexport class InitError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"InitError\";\n }\n}\n\nexport class CriticalRequestError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"CriticalRequestError\";\n }\n}\n\nexport class ControlFlowError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ControlFlowError\";\n }\n}\n\nexport class HttpClientError extends FrameworkError {\n constructor(message: string, public readonly cause?: Error) {\n super(message);\n this.name = \"HttpClientError\";\n }\n}\n\nexport class FileDatabaseError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"FileDatabaseError\";\n }\n}\n\n","/**\n * HttpClient Error Classification\n *\n * Maps technical errors to human-readable, use-case oriented error types\n */\n\nimport type { HttpClientErrorType, HttpClientStatus, ErrorClassification } from './types.js';\n\n/**\n * Classify an error and determine retry behavior\n */\nexport function classifyError(error: any): ErrorClassification {\n // Handle axios response errors (HTTP errors)\n if (error.response) {\n const { status } = error.response;\n\n switch (status) {\n case 400:\n return { type: 'badRequest', retryable: false, isAuth: false, status: 'clientError' };\n case 401:\n return { type: 'unauthorized', retryable: false, isAuth: true, status: 'authRequired' };\n case 403:\n return { type: 'forbidden', retryable: false, isAuth: true, status: 'authFailed' };\n case 404:\n return { type: 'notFound', retryable: false, isAuth: false, status: 'clientError' };\n case 405:\n return { type: 'methodNotAllowed', retryable: false, isAuth: false, status: 'clientError' };\n case 409:\n return { type: 'conflict', retryable: false, isAuth: false, status: 'clientError' };\n case 422:\n return { type: 'unprocessableEntity', retryable: false, isAuth: false, status: 'clientError' };\n case 429:\n return { type: 'tooManyRequests', retryable: true, isAuth: false, status: 'clientError' };\n case 500:\n return { type: 'internalServerError', retryable: true, isAuth: false, status: 'serverError' };\n case 502:\n return { type: 'badGateway', retryable: true, isAuth: false, status: 'serverError' };\n case 503:\n return { type: 'serviceUnavailable', retryable: true, isAuth: false, status: 'serverError' };\n case 504:\n return { type: 'gatewayTimeout', retryable: true, isAuth: false, status: 'serverError' };\n default:\n if (status >= 400 && status < 500) {\n return { type: 'clientError' as HttpClientErrorType, retryable: false, isAuth: false, status: 'clientError' };\n } else if (status >= 500) {\n return { type: 'serverError' as HttpClientErrorType, retryable: true, isAuth: false, status: 'serverError' };\n }\n break;\n }\n }\n\n // Handle network/connection errors (no response)\n if (error.code) {\n switch (error.code) {\n case 'ECONNREFUSED':\n case 'ECONNRESET':\n case 'EPIPE':\n case 'ENOTFOUND':\n case 'EHOSTUNREACH':\n case 'ENETUNREACH':\n return { type: 'connectionFailed', retryable: true, isAuth: false, status: 'networkError' };\n\n case 'ETIMEDOUT':\n case 'ECONNABORTED':\n case 'ESOCKETTIMEDOUT':\n return { type: 'timeout', retryable: true, isAuth: false, status: 'timeout' };\n\n case 'EAUTH':\n case 'EACCES':\n return { type: 'unauthorized', retryable: false, isAuth: true, status: 'authRequired' };\n\n default:\n return { type: 'networkError', retryable: true, isAuth: false, status: 'networkError' };\n }\n }\n\n // Handle timeout errors\n if (error.message && (\n error.message.includes('timeout') ||\n error.message.includes('TIMEOUT') ||\n error.message.includes('aborted')\n )) {\n return { type: 'timeout', retryable: true, isAuth: false, status: 'timeout' };\n }\n\n // Handle cancellation\n if (error.name === 'AbortError' || error.message?.includes('cancelled')) {\n return { type: 'requestCancelled', retryable: false, isAuth: false, status: 'unknown' };\n }\n\n // Default fallback\n return { type: 'unknown', retryable: false, isAuth: false, status: 'unknown' };\n}\n\n/**\n * Get a human-readable description for an error type\n */\nexport function getErrorDescription(errorType: HttpClientErrorType): string {\n const descriptions: Record<HttpClientErrorType, string> = {\n connectionFailed: 'Failed to establish a connection to the server',\n timeout: 'Request timed out before completing',\n networkError: 'Network connection issue occurred',\n badRequest: 'Request was malformed or invalid',\n unauthorized: 'Authentication credentials are required',\n forbidden: 'Access to the requested resource is forbidden',\n notFound: 'The requested resource was not found',\n methodNotAllowed: 'HTTP method not allowed for this resource',\n conflict: 'Request conflicts with current server state',\n unprocessableEntity: 'Request data could not be processed',\n tooManyRequests: 'Too many requests sent in a short time',\n internalServerError: 'Server encountered an internal error',\n badGateway: 'Invalid response from upstream server',\n serviceUnavailable: 'Server is temporarily unavailable',\n gatewayTimeout: 'Upstream server timed out',\n unknown: 'An unknown error occurred',\n requestCancelled: 'Request was cancelled before completion'\n };\n\n return descriptions[errorType] || 'An unknown error occurred';\n}\n","/**\n * HttpClient Retry Logic\n *\n * Implements exponential backoff with jitter to prevent thundering herd problems\n */\n\nimport type { RetryContext } from './types.js';\n\n/**\n * Calculate the next retry delay using exponential backoff with jitter\n *\n * Formula: delay = baseDelay * (2 ^ (attempt - 1)) + randomJitter\n *\n * Jitter prevents the \"thundering herd\" problem where multiple failed requests\n * all retry at the exact same time, overwhelming the server.\n */\nexport function calculateRetryDelay(\n attempt: number,\n baseDelay: number,\n maxDelay: number,\n jitterFactor: number = 0.1\n): number {\n // Exponential backoff: baseDelay * (2 ^ (attempt - 1))\n const exponentialDelay = baseDelay * Math.pow(2, attempt - 1);\n\n // Cap at maximum delay\n const cappedDelay = Math.min(exponentialDelay, maxDelay);\n\n // Add jitter: random variation up to jitterFactor of the delay\n const jitter = cappedDelay * jitterFactor * Math.random();\n\n return Math.floor(cappedDelay + jitter);\n}\n\n/**\n * Sleep for the specified number of milliseconds\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Determine if an error should be retried based on classification\n */\nexport function shouldRetryError(classification: { retryable: boolean; isAuth: boolean }): boolean {\n // Never retry auth errors (they won't succeed with the same credentials)\n if (classification.isAuth) {\n return false;\n }\n\n // Retry if the error is classified as retryable\n return classification.retryable;\n}\n\n/**\n * Create a retry context for tracking retry attempts\n */\nexport function createRetryContext(\n maxAttempts: number,\n baseDelay: number,\n maxDelay: number,\n jitterFactor: number\n): RetryContext {\n return {\n attempt: 1,\n maxAttempts,\n lastError: new Error('Initial attempt'),\n totalDelay: 0,\n nextDelay: calculateRetryDelay(1, baseDelay, maxDelay, jitterFactor)\n };\n}\n\n/**\n * Update retry context for the next attempt\n */\nexport function updateRetryContext(\n context: RetryContext,\n lastError: Error,\n baseDelay: number,\n maxDelay: number,\n jitterFactor: number\n): RetryContext {\n const nextAttempt = context.attempt + 1;\n const nextDelay = calculateRetryDelay(nextAttempt, baseDelay, maxDelay, jitterFactor);\n\n return {\n attempt: nextAttempt,\n maxAttempts: context.maxAttempts,\n lastError,\n totalDelay: context.totalDelay + context.nextDelay,\n nextDelay\n };\n}\n"],"mappings":"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","names":["axios"]}
1
+ {"version":3,"sources":["../src/http-client/index.js","../src/errors.js","../src/http-client/errors.js","../src/http-client/retry.js"],"sourcesContent":["/**\n * HttpClient - Resilient HTTP Client with Retry Logic\n *\n * A production-ready HTTP client that:\n * - Wraps axios with enhanced error handling and retry logic\n * - Never throws exceptions - always returns unified response format\n * - Uses exponential backoff with jitter for retries\n * - Provides human-readable error classifications\n * - Supports comprehensive logging\n * - Handles all HTTP methods consistently\n */\n\nimport axios, { } from \"axios\";\n\n\n\n\n\n\n\n\nimport { HttpClientError } from \"../errors.js\";\nimport { classifyError, getErrorDescription } from \"./errors.js\";\nimport { calculateRetryDelay, sleep, shouldRetryError, } from \"./retry.js\";\n\nexport { HttpClientError };\n\n/**\n * Resilient HTTP Client with automatic retry logic.\n * Use HttpClient.init(context, options) when running with init/context; constructor(config) for standalone.\n */\nexport class HttpClient {\n axiosInstance;\n config;\n logger;\n\n constructor(contextOrConfig = {}, config) {\n const hasContext = config !== undefined;\n const options = hasContext ? config : (contextOrConfig || {});\n const context = hasContext ? contextOrConfig : undefined;\n\n this.config = {\n ...options,\n logger: context?.logger ?? options.logger ?? console,\n };\n this.logger = this.config.logger;\n\n this.axiosInstance = axios.create({\n timeout: this.config.timeout,\n validateStatus: () => true,\n maxRedirects: this.config.maxRedirects,\n headers: { \"User-Agent\": this.config.userAgent },\n httpsAgent: this.config.validateSSL ? undefined : { rejectUnauthorized: false } ,\n });\n\n // Add response interceptor for logging (optional - only if debug enabled)\n this.axiosInstance.interceptors.response.use(\n (response) => response,\n (error) => {\n // Log network-level errors here if needed\n // (HTTP errors are handled in the request method)\n return Promise.reject(error);\n }\n );\n }\n\n /**\n * Static init - discovers params via getAllForModule(defs). Whatever is in options goes.\n */\n static init(context, options = {}) {\n const defs = {\n timeout: \"number default 30000\",\n retryCount: \"number default 3\",\n retryDelay: \"number default 1000\",\n maxRetryDelay: \"number default 30000\",\n retryJitter: \"number default 0.1\",\n userAgent: \"string default HttpClient/v1.0\",\n validateSSL: \"boolean default true\",\n maxRedirects: \"number default 5\",\n };\n const discovered = context?.params?.getAllForModule?.(defs) ?? {};\n const merged = { ...discovered, ...options, logger: options.logger ?? context?.logger };\n return new HttpClient(context, merged);\n }\n\n /**\n * Make an HTTP request with automatic retry logic\n * Never throws - always returns HttpClientResponse\n */\n async request(\n method,\n url,\n options = {}\n ) {\n const startTime = Date.now();\n\n // Merge request options with defaults\n const requestConfig = {\n method,\n url,\n timeout: options.timeout ?? this.config.timeout,\n headers: {\n \"User-Agent\": options.userAgent ?? this.config.userAgent,\n ...options.headers\n },\n params: options.params,\n data: options.data\n };\n\n const retryCount = options.retryCount ?? this.config.retryCount;\n const retryDelay = options.retryDelay ?? this.config.retryDelay;\n\n // Initialize retry context\n const _retryContext = null;\n let _lastError = null;\n\n // Attempt the request with retries\n for (let attempt = 1; attempt <= retryCount + 1; attempt++) {\n try {\n if (options.debug) {\n this.logger.debug?.(`[HttpClient] ${method} ${url} (attempt ${attempt}/${retryCount + 1})`);\n }\n\n const response = await this.axiosInstance.request(requestConfig);\n const duration = Date.now() - startTime;\n\n // Success! Return unified response format\n const customStatus = this.mapHttpStatusToCustomStatus(response.status);\n\n if (options.debug) {\n this.logger.debug?.(`[HttpClient] ${method} ${url} → ${response.status} ${customStatus} (${duration}ms)`);\n }\n\n return {\n status: customStatus,\n code: response.status,\n headers: response.headers ,\n data: response.data,\n duration,\n retryCount: attempt - 1,\n finalUrl: response.request?.res?.responseUrl || url\n };\n\n } catch (error) {\n _lastError = error;\n const duration = Date.now() - startTime;\n\n // Classify the error\n const classification = classifyError(error);\n const errorDescription = getErrorDescription(classification.type);\n\n // Log the error\n if (classification.retryable && attempt <= retryCount) {\n this.logger.warn?.(`[HttpClient] ${method} ${url} failed (${classification.type}): ${errorDescription}. Retrying in ${retryDelay}ms...`);\n } else if (!classification.retryable || attempt > retryCount) {\n this.logger.error?.(`[HttpClient] ${method} ${url} failed (${classification.type}): ${errorDescription}`);\n }\n\n // Check if we should retry\n if (attempt <= retryCount && shouldRetryError(classification)) {\n // Calculate delay and wait\n const delay = calculateRetryDelay(\n attempt,\n retryDelay,\n this.config.maxRetryDelay,\n this.config.retryJitter\n );\n\n if (options.debug) {\n this.logger.debug?.(`[HttpClient] Waiting ${delay}ms before retry ${attempt + 1}`);\n }\n\n await sleep(delay);\n continue;\n }\n\n // No more retries or not retryable - return error response\n return {\n status: classification.status,\n code: error.response?.status || null,\n error: classification.type,\n headers: error.response?.headers || null,\n data: error.response?.data || null,\n duration,\n retryCount: attempt - 1,\n finalUrl: url\n };\n }\n }\n\n // This should never be reached, but just in case\n return {\n status: \"unknown\",\n code: null,\n error: \"unknown\",\n headers: null,\n data: null,\n duration: Date.now() - startTime,\n retryCount: retryCount,\n finalUrl: url\n };\n }\n\n /**\n * GET request\n */\n async get(url, options = {}) {\n return this.request(\"GET\", url, options);\n }\n\n /**\n * POST request\n */\n async post(url, options = {}) {\n return this.request(\"POST\", url, options);\n }\n\n /**\n * PUT request\n */\n async put(url, options = {}) {\n return this.request(\"PUT\", url, options);\n }\n\n /**\n * DELETE request\n */\n async delete(url, options = {}) {\n return this.request(\"DELETE\", url, options);\n }\n\n /**\n * PATCH request\n */\n async patch(url, options = {}) {\n return this.request(\"PATCH\", url, options);\n }\n\n /**\n * HEAD request\n */\n async head(url, options = {}) {\n return this.request(\"HEAD\", url, options);\n }\n\n /**\n * OPTIONS request\n */\n async options(url, options = {}) {\n return this.request(\"OPTIONS\", url, options);\n }\n\n /**\n * Map HTTP status code to custom status\n */\n mapHttpStatusToCustomStatus(httpStatus) {\n if (httpStatus >= 200 && httpStatus < 300) {\n return \"success\";\n } else if (httpStatus === 401) {\n return \"authRequired\";\n } else if (httpStatus === 403) {\n return \"authFailed\";\n } else if (httpStatus >= 400 && httpStatus < 500) {\n return \"clientError\";\n } else if (httpStatus >= 500) {\n return \"serverError\";\n }\n return \"unknown\";\n }\n\n /**\n * Get current configuration (for debugging)\n */\n getConfig() {\n return { ...this.config };\n }\n}\n","/**\n * Error classes for the CLI toolkit\n */\n\nexport class FrameworkError extends Error {\n constructor(message) {\n super(message);\n this.name = \"FrameworkError\";\n }\n}\n\nexport class ParamError extends FrameworkError {\n constructor(message) {\n super(message);\n this.name = \"ParamError\";\n }\n}\n\nexport class InitError extends FrameworkError {\n constructor(message) {\n super(message);\n this.name = \"InitError\";\n }\n}\n\nexport class CriticalRequestError extends FrameworkError {\n constructor(message) {\n super(message);\n this.name = \"CriticalRequestError\";\n }\n}\n\nexport class ControlFlowError extends Error {\n constructor(message) {\n super(message);\n this.name = \"ControlFlowError\";\n }\n}\n\nexport class HttpClientError extends FrameworkError {\n constructor(message, cause) {\n super(message);this.cause = cause;;\n this.name = \"HttpClientError\";\n }\n}\n\nexport class FileDatabaseError extends FrameworkError {\n constructor(message) {\n super(message);\n this.name = \"FileDatabaseError\";\n }\n}\n\n","\n\n\n\n\n\n\n\n/**\n * Classify an error and determine retry behavior\n */\nexport function classifyError(error) {\n // Handle axios response errors (HTTP errors)\n if (error.response) {\n const { status } = error.response;\n\n switch (status) {\n case 400:\n return { type: \"badRequest\", retryable: false, isAuth: false, status: \"clientError\" };\n case 401:\n return { type: \"unauthorized\", retryable: false, isAuth: true, status: \"authRequired\" };\n case 403:\n return { type: \"forbidden\", retryable: false, isAuth: true, status: \"authFailed\" };\n case 404:\n return { type: \"notFound\", retryable: false, isAuth: false, status: \"clientError\" };\n case 405:\n return { type: \"methodNotAllowed\", retryable: false, isAuth: false, status: \"clientError\" };\n case 409:\n return { type: \"conflict\", retryable: false, isAuth: false, status: \"clientError\" };\n case 422:\n return { type: \"unprocessableEntity\", retryable: false, isAuth: false, status: \"clientError\" };\n case 429:\n return { type: \"tooManyRequests\", retryable: true, isAuth: false, status: \"clientError\" };\n case 500:\n return { type: \"internalServerError\", retryable: true, isAuth: false, status: \"serverError\" };\n case 502:\n return { type: \"badGateway\", retryable: true, isAuth: false, status: \"serverError\" };\n case 503:\n return { type: \"serviceUnavailable\", retryable: true, isAuth: false, status: \"serverError\" };\n case 504:\n return { type: \"gatewayTimeout\", retryable: true, isAuth: false, status: \"serverError\" };\n default:\n if (status >= 400 && status < 500) {\n return { type: \"clientError\" , retryable: false, isAuth: false, status: \"clientError\" };\n } else if (status >= 500) {\n return { type: \"serverError\" , retryable: true, isAuth: false, status: \"serverError\" };\n }\n break;\n }\n }\n\n // Handle network/connection errors (no response)\n if (error.code) {\n switch (error.code) {\n case \"ECONNREFUSED\":\n case \"ECONNRESET\":\n case \"EPIPE\":\n case \"ENOTFOUND\":\n case \"EHOSTUNREACH\":\n case \"ENETUNREACH\":\n return { type: \"connectionFailed\", retryable: true, isAuth: false, status: \"networkError\" };\n\n case \"ETIMEDOUT\":\n case \"ECONNABORTED\":\n case \"ESOCKETTIMEDOUT\":\n return { type: \"timeout\", retryable: true, isAuth: false, status: \"timeout\" };\n\n case \"EAUTH\":\n case \"EACCES\":\n return { type: \"unauthorized\", retryable: false, isAuth: true, status: \"authRequired\" };\n\n default:\n return { type: \"networkError\", retryable: true, isAuth: false, status: \"networkError\" };\n }\n }\n\n // Handle timeout errors\n if (error.message && (\n error.message.includes(\"timeout\") ||\n error.message.includes(\"TIMEOUT\") ||\n error.message.includes(\"aborted\")\n )) {\n return { type: \"timeout\", retryable: true, isAuth: false, status: \"timeout\" };\n }\n\n // Handle cancellation\n if (error.name === \"AbortError\" || error.message?.includes(\"cancelled\")) {\n return { type: \"requestCancelled\", retryable: false, isAuth: false, status: \"unknown\" };\n }\n\n // Default fallback\n return { type: \"unknown\", retryable: false, isAuth: false, status: \"unknown\" };\n}\n\n/**\n * Get a human-readable description for an error type\n */\nexport function getErrorDescription(errorType) {\n const descriptions = {\n connectionFailed: \"Failed to establish a connection to the server\",\n timeout: \"Request timed out before completing\",\n networkError: \"Network connection issue occurred\",\n badRequest: \"Request was malformed or invalid\",\n unauthorized: \"Authentication credentials are required\",\n forbidden: \"Access to the requested resource is forbidden\",\n notFound: \"The requested resource was not found\",\n methodNotAllowed: \"HTTP method not allowed for this resource\",\n conflict: \"Request conflicts with current server state\",\n unprocessableEntity: \"Request data could not be processed\",\n tooManyRequests: \"Too many requests sent in a short time\",\n internalServerError: \"Server encountered an internal error\",\n badGateway: \"Invalid response from upstream server\",\n serviceUnavailable: \"Server is temporarily unavailable\",\n gatewayTimeout: \"Upstream server timed out\",\n unknown: \"An unknown error occurred\",\n requestCancelled: \"Request was cancelled before completion\"\n };\n\n return descriptions[errorType] || \"An unknown error occurred\";\n}\n","\n\n\n\n\n\n\n\n/**\n * Calculate the next retry delay using exponential backoff with jitter\n *\n * Formula: delay = baseDelay * (2 ^ (attempt - 1)) + randomJitter\n *\n * Jitter prevents the \"thundering herd\" problem where multiple failed requests\n * all retry at the exact same time, overwhelming the server.\n */\nexport function calculateRetryDelay(\n attempt,\n baseDelay,\n maxDelay,\n jitterFactor = 0.1\n) {\n // Exponential backoff: baseDelay * (2 ^ (attempt - 1))\n const exponentialDelay = baseDelay * Math.pow(2, attempt - 1);\n\n // Cap at maximum delay\n const cappedDelay = Math.min(exponentialDelay, maxDelay);\n\n // Add jitter: random variation up to jitterFactor of the delay\n const jitter = cappedDelay * jitterFactor * Math.random();\n\n return Math.floor(cappedDelay + jitter);\n}\n\n/**\n * Sleep for the specified number of milliseconds\n */\nexport function sleep(ms) {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Determine if an error should be retried based on classification\n */\nexport function shouldRetryError(classification) {\n // Never retry auth errors (they won't succeed with the same credentials)\n if (classification.isAuth) {\n return false;\n }\n\n // Retry if the error is classified as retryable\n return classification.retryable;\n}\n\n/**\n * Create a retry context for tracking retry attempts\n */\nexport function createRetryContext(\n maxAttempts,\n baseDelay,\n maxDelay,\n jitterFactor\n) {\n return {\n attempt: 1,\n maxAttempts,\n lastError: new Error(\"Initial attempt\"),\n totalDelay: 0,\n nextDelay: calculateRetryDelay(1, baseDelay, maxDelay, jitterFactor)\n };\n}\n\n/**\n * Update retry context for the next attempt\n */\nexport function updateRetryContext(\n context,\n lastError,\n baseDelay,\n maxDelay,\n jitterFactor\n) {\n const nextAttempt = context.attempt + 1;\n const nextDelay = calculateRetryDelay(nextAttempt, baseDelay, maxDelay, jitterFactor);\n\n return {\n attempt: nextAttempt,\n maxAttempts: context.maxAttempts,\n lastError,\n totalDelay: context.totalDelay + context.nextDelay,\n nextDelay\n };\n}\n"],"mappings":"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","names":["axios"]}
@@ -1,7 +1,7 @@
1
- // src/http-client/index.ts
2
- import axios from "axios";
1
+ // src/http-client/index.js
2
+ import axios, {} from "axios";
3
3
 
4
- // src/errors.ts
4
+ // src/errors.js
5
5
  var FrameworkError = class extends Error {
6
6
  constructor(message) {
7
7
  super(message);
@@ -12,11 +12,12 @@ var HttpClientError = class extends FrameworkError {
12
12
  constructor(message, cause) {
13
13
  super(message);
14
14
  this.cause = cause;
15
+ ;
15
16
  this.name = "HttpClientError";
16
17
  }
17
18
  };
18
19
 
19
- // src/http-client/errors.ts
20
+ // src/http-client/errors.js
20
21
  function classifyError(error) {
21
22
  if (error.response) {
22
23
  const { status } = error.response;
@@ -105,7 +106,7 @@ function getErrorDescription(errorType) {
105
106
  return descriptions[errorType] || "An unknown error occurred";
106
107
  }
107
108
 
108
- // src/http-client/retry.ts
109
+ // src/http-client/retry.js
109
110
  function calculateRetryDelay(attempt, baseDelay, maxDelay, jitterFactor = 0.1) {
110
111
  const exponentialDelay = baseDelay * Math.pow(2, attempt - 1);
111
112
  const cappedDelay = Math.min(exponentialDelay, maxDelay);
@@ -122,7 +123,7 @@ function shouldRetryError(classification) {
122
123
  return classification.retryable;
123
124
  }
124
125
 
125
- // src/http-client/index.ts
126
+ // src/http-client/index.js
126
127
  var HttpClient = class _HttpClient {
127
128
  axiosInstance;
128
129
  config;
@@ -187,8 +188,8 @@ var HttpClient = class _HttpClient {
187
188
  };
188
189
  const retryCount = options.retryCount ?? this.config.retryCount;
189
190
  const retryDelay = options.retryDelay ?? this.config.retryDelay;
190
- let retryContext = null;
191
- let lastError = null;
191
+ const _retryContext = null;
192
+ let _lastError = null;
192
193
  for (let attempt = 1; attempt <= retryCount + 1; attempt++) {
193
194
  try {
194
195
  if (options.debug) {
@@ -210,7 +211,7 @@ var HttpClient = class _HttpClient {
210
211
  finalUrl: response.request?.res?.responseUrl || url
211
212
  };
212
213
  } catch (error) {
213
- lastError = error;
214
+ _lastError = error;
214
215
  const duration = Date.now() - startTime;
215
216
  const classification = classifyError(error);
216
217
  const errorDescription = getErrorDescription(classification.type);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/http-client/index.ts","../src/errors.ts","../src/http-client/errors.ts","../src/http-client/retry.ts"],"sourcesContent":["/**\n * HttpClient - Resilient HTTP Client with Retry Logic\n *\n * A production-ready HTTP client that:\n * - Wraps axios with enhanced error handling and retry logic\n * - Never throws exceptions - always returns unified response format\n * - Uses exponential backoff with jitter for retries\n * - Provides human-readable error classifications\n * - Supports comprehensive logging\n * - Handles all HTTP methods consistently\n */\n\nimport axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';\nimport type {\n HttpClientConfig,\n RequestOptions,\n HttpClientResponse,\n HttpMethod,\n HttpClientStatus,\n RetryContext\n} from './types.js';\nimport { HttpClientError } from '../errors.js';\nimport { classifyError, getErrorDescription } from './errors.js';\nimport { calculateRetryDelay, sleep, shouldRetryError, createRetryContext, updateRetryContext } from './retry.js';\n\nexport { HttpClientError };\n\n/**\n * Resilient HTTP Client with automatic retry logic.\n * Use HttpClient.init(context, options) when running with init/context; constructor(config) for standalone.\n */\nexport class HttpClient {\n private axiosInstance: AxiosInstance;\n private config: HttpClientConfig;\n private logger: any;\n\n constructor(contextOrConfig: any = {}, config?: HttpClientConfig) {\n const hasContext = config !== undefined;\n const options: HttpClientConfig = hasContext ? config! : (contextOrConfig || {});\n const context = hasContext ? contextOrConfig : undefined;\n\n this.config = {\n ...options,\n logger: context?.logger ?? options.logger ?? console,\n };\n this.logger = this.config.logger;\n\n this.axiosInstance = axios.create({\n timeout: this.config.timeout,\n validateStatus: () => true,\n maxRedirects: this.config.maxRedirects,\n headers: { 'User-Agent': this.config.userAgent },\n httpsAgent: this.config.validateSSL ? undefined : { rejectUnauthorized: false } as any,\n });\n\n // Add response interceptor for logging (optional - only if debug enabled)\n this.axiosInstance.interceptors.response.use(\n (response) => response,\n (error) => {\n // Log network-level errors here if needed\n // (HTTP errors are handled in the request method)\n return Promise.reject(error);\n }\n );\n }\n\n /**\n * Static init - discovers params via getAllForModule(defs). Whatever is in options goes.\n */\n static init(context: any, options: HttpClientConfig = {}): HttpClient {\n const defs: Record<string, string> = {\n timeout: 'number default 30000',\n retryCount: 'number default 3',\n retryDelay: 'number default 1000',\n maxRetryDelay: 'number default 30000',\n retryJitter: 'number default 0.1',\n userAgent: 'string default HttpClient/v1.0',\n validateSSL: 'boolean default true',\n maxRedirects: 'number default 5',\n };\n const discovered = context?.params?.getAllForModule?.(defs) ?? {};\n const merged: HttpClientConfig = { ...discovered, ...options, logger: options.logger ?? context?.logger };\n return new HttpClient(context, merged);\n }\n\n /**\n * Make an HTTP request with automatic retry logic\n * Never throws - always returns HttpClientResponse\n */\n async request(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {}\n ): Promise<HttpClientResponse> {\n const startTime = Date.now();\n\n // Merge request options with defaults\n const requestConfig: AxiosRequestConfig = {\n method,\n url,\n timeout: options.timeout ?? this.config.timeout,\n headers: {\n 'User-Agent': options.userAgent ?? this.config.userAgent,\n ...options.headers\n },\n params: options.params,\n data: options.data\n };\n\n const retryCount = options.retryCount ?? this.config.retryCount;\n const retryDelay = options.retryDelay ?? this.config.retryDelay;\n\n // Initialize retry context\n let retryContext: RetryContext | null = null;\n let lastError: any = null;\n\n // Attempt the request with retries\n for (let attempt = 1; attempt <= retryCount + 1; attempt++) {\n try {\n if (options.debug) {\n this.logger.debug?.(`[HttpClient] ${method} ${url} (attempt ${attempt}/${retryCount + 1})`);\n }\n\n const response: AxiosResponse = await this.axiosInstance.request(requestConfig);\n const duration = Date.now() - startTime;\n\n // Success! Return unified response format\n const customStatus = this.mapHttpStatusToCustomStatus(response.status);\n\n if (options.debug) {\n this.logger.debug?.(`[HttpClient] ${method} ${url} → ${response.status} ${customStatus} (${duration}ms)`);\n }\n\n return {\n status: customStatus,\n code: response.status,\n headers: response.headers as Record<string, string>,\n data: response.data,\n duration,\n retryCount: attempt - 1,\n finalUrl: response.request?.res?.responseUrl || url\n };\n\n } catch (error: any) {\n lastError = error;\n const duration = Date.now() - startTime;\n\n // Classify the error\n const classification = classifyError(error);\n const errorDescription = getErrorDescription(classification.type);\n\n // Log the error\n if (classification.retryable && attempt <= retryCount) {\n this.logger.warn?.(`[HttpClient] ${method} ${url} failed (${classification.type}): ${errorDescription}. Retrying in ${retryDelay}ms...`);\n } else if (!classification.retryable || attempt > retryCount) {\n this.logger.error?.(`[HttpClient] ${method} ${url} failed (${classification.type}): ${errorDescription}`);\n }\n\n // Check if we should retry\n if (attempt <= retryCount && shouldRetryError(classification)) {\n // Calculate delay and wait\n const delay = calculateRetryDelay(\n attempt,\n retryDelay,\n this.config.maxRetryDelay,\n this.config.retryJitter\n );\n\n if (options.debug) {\n this.logger.debug?.(`[HttpClient] Waiting ${delay}ms before retry ${attempt + 1}`);\n }\n\n await sleep(delay);\n continue;\n }\n\n // No more retries or not retryable - return error response\n return {\n status: classification.status,\n code: error.response?.status || null,\n error: classification.type,\n headers: error.response?.headers || null,\n data: error.response?.data || null,\n duration,\n retryCount: attempt - 1,\n finalUrl: url\n };\n }\n }\n\n // This should never be reached, but just in case\n return {\n status: 'unknown',\n code: null,\n error: 'unknown',\n headers: null,\n data: null,\n duration: Date.now() - startTime,\n retryCount: retryCount,\n finalUrl: url\n };\n }\n\n /**\n * GET request\n */\n async get(url: string, options: RequestOptions = {}): Promise<HttpClientResponse> {\n return this.request('GET', url, options);\n }\n\n /**\n * POST request\n */\n async post(url: string, options: RequestOptions = {}): Promise<HttpClientResponse> {\n return this.request('POST', url, options);\n }\n\n /**\n * PUT request\n */\n async put(url: string, options: RequestOptions = {}): Promise<HttpClientResponse> {\n return this.request('PUT', url, options);\n }\n\n /**\n * DELETE request\n */\n async delete(url: string, options: RequestOptions = {}): Promise<HttpClientResponse> {\n return this.request('DELETE', url, options);\n }\n\n /**\n * PATCH request\n */\n async patch(url: string, options: RequestOptions = {}): Promise<HttpClientResponse> {\n return this.request('PATCH', url, options);\n }\n\n /**\n * HEAD request\n */\n async head(url: string, options: RequestOptions = {}): Promise<HttpClientResponse> {\n return this.request('HEAD', url, options);\n }\n\n /**\n * OPTIONS request\n */\n async options(url: string, options: RequestOptions = {}): Promise<HttpClientResponse> {\n return this.request('OPTIONS', url, options);\n }\n\n /**\n * Map HTTP status code to custom status\n */\n private mapHttpStatusToCustomStatus(httpStatus: number): HttpClientStatus {\n if (httpStatus >= 200 && httpStatus < 300) {\n return 'success';\n } else if (httpStatus === 401) {\n return 'authRequired';\n } else if (httpStatus === 403) {\n return 'authFailed';\n } else if (httpStatus >= 400 && httpStatus < 500) {\n return 'clientError';\n } else if (httpStatus >= 500) {\n return 'serverError';\n }\n return 'unknown';\n }\n\n /**\n * Get current configuration (for debugging)\n */\n getConfig(): Readonly<HttpClientConfig> {\n return { ...this.config };\n }\n}\n","/**\n * Error classes for the CLI toolkit\n */\n\nexport class FrameworkError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"FrameworkError\";\n }\n}\n\nexport class ParamError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"ParamError\";\n }\n}\n\nexport class InitError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"InitError\";\n }\n}\n\nexport class CriticalRequestError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"CriticalRequestError\";\n }\n}\n\nexport class ControlFlowError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ControlFlowError\";\n }\n}\n\nexport class HttpClientError extends FrameworkError {\n constructor(message: string, public readonly cause?: Error) {\n super(message);\n this.name = \"HttpClientError\";\n }\n}\n\nexport class FileDatabaseError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"FileDatabaseError\";\n }\n}\n\n","/**\n * HttpClient Error Classification\n *\n * Maps technical errors to human-readable, use-case oriented error types\n */\n\nimport type { HttpClientErrorType, HttpClientStatus, ErrorClassification } from './types.js';\n\n/**\n * Classify an error and determine retry behavior\n */\nexport function classifyError(error: any): ErrorClassification {\n // Handle axios response errors (HTTP errors)\n if (error.response) {\n const { status } = error.response;\n\n switch (status) {\n case 400:\n return { type: 'badRequest', retryable: false, isAuth: false, status: 'clientError' };\n case 401:\n return { type: 'unauthorized', retryable: false, isAuth: true, status: 'authRequired' };\n case 403:\n return { type: 'forbidden', retryable: false, isAuth: true, status: 'authFailed' };\n case 404:\n return { type: 'notFound', retryable: false, isAuth: false, status: 'clientError' };\n case 405:\n return { type: 'methodNotAllowed', retryable: false, isAuth: false, status: 'clientError' };\n case 409:\n return { type: 'conflict', retryable: false, isAuth: false, status: 'clientError' };\n case 422:\n return { type: 'unprocessableEntity', retryable: false, isAuth: false, status: 'clientError' };\n case 429:\n return { type: 'tooManyRequests', retryable: true, isAuth: false, status: 'clientError' };\n case 500:\n return { type: 'internalServerError', retryable: true, isAuth: false, status: 'serverError' };\n case 502:\n return { type: 'badGateway', retryable: true, isAuth: false, status: 'serverError' };\n case 503:\n return { type: 'serviceUnavailable', retryable: true, isAuth: false, status: 'serverError' };\n case 504:\n return { type: 'gatewayTimeout', retryable: true, isAuth: false, status: 'serverError' };\n default:\n if (status >= 400 && status < 500) {\n return { type: 'clientError' as HttpClientErrorType, retryable: false, isAuth: false, status: 'clientError' };\n } else if (status >= 500) {\n return { type: 'serverError' as HttpClientErrorType, retryable: true, isAuth: false, status: 'serverError' };\n }\n break;\n }\n }\n\n // Handle network/connection errors (no response)\n if (error.code) {\n switch (error.code) {\n case 'ECONNREFUSED':\n case 'ECONNRESET':\n case 'EPIPE':\n case 'ENOTFOUND':\n case 'EHOSTUNREACH':\n case 'ENETUNREACH':\n return { type: 'connectionFailed', retryable: true, isAuth: false, status: 'networkError' };\n\n case 'ETIMEDOUT':\n case 'ECONNABORTED':\n case 'ESOCKETTIMEDOUT':\n return { type: 'timeout', retryable: true, isAuth: false, status: 'timeout' };\n\n case 'EAUTH':\n case 'EACCES':\n return { type: 'unauthorized', retryable: false, isAuth: true, status: 'authRequired' };\n\n default:\n return { type: 'networkError', retryable: true, isAuth: false, status: 'networkError' };\n }\n }\n\n // Handle timeout errors\n if (error.message && (\n error.message.includes('timeout') ||\n error.message.includes('TIMEOUT') ||\n error.message.includes('aborted')\n )) {\n return { type: 'timeout', retryable: true, isAuth: false, status: 'timeout' };\n }\n\n // Handle cancellation\n if (error.name === 'AbortError' || error.message?.includes('cancelled')) {\n return { type: 'requestCancelled', retryable: false, isAuth: false, status: 'unknown' };\n }\n\n // Default fallback\n return { type: 'unknown', retryable: false, isAuth: false, status: 'unknown' };\n}\n\n/**\n * Get a human-readable description for an error type\n */\nexport function getErrorDescription(errorType: HttpClientErrorType): string {\n const descriptions: Record<HttpClientErrorType, string> = {\n connectionFailed: 'Failed to establish a connection to the server',\n timeout: 'Request timed out before completing',\n networkError: 'Network connection issue occurred',\n badRequest: 'Request was malformed or invalid',\n unauthorized: 'Authentication credentials are required',\n forbidden: 'Access to the requested resource is forbidden',\n notFound: 'The requested resource was not found',\n methodNotAllowed: 'HTTP method not allowed for this resource',\n conflict: 'Request conflicts with current server state',\n unprocessableEntity: 'Request data could not be processed',\n tooManyRequests: 'Too many requests sent in a short time',\n internalServerError: 'Server encountered an internal error',\n badGateway: 'Invalid response from upstream server',\n serviceUnavailable: 'Server is temporarily unavailable',\n gatewayTimeout: 'Upstream server timed out',\n unknown: 'An unknown error occurred',\n requestCancelled: 'Request was cancelled before completion'\n };\n\n return descriptions[errorType] || 'An unknown error occurred';\n}\n","/**\n * HttpClient Retry Logic\n *\n * Implements exponential backoff with jitter to prevent thundering herd problems\n */\n\nimport type { RetryContext } from './types.js';\n\n/**\n * Calculate the next retry delay using exponential backoff with jitter\n *\n * Formula: delay = baseDelay * (2 ^ (attempt - 1)) + randomJitter\n *\n * Jitter prevents the \"thundering herd\" problem where multiple failed requests\n * all retry at the exact same time, overwhelming the server.\n */\nexport function calculateRetryDelay(\n attempt: number,\n baseDelay: number,\n maxDelay: number,\n jitterFactor: number = 0.1\n): number {\n // Exponential backoff: baseDelay * (2 ^ (attempt - 1))\n const exponentialDelay = baseDelay * Math.pow(2, attempt - 1);\n\n // Cap at maximum delay\n const cappedDelay = Math.min(exponentialDelay, maxDelay);\n\n // Add jitter: random variation up to jitterFactor of the delay\n const jitter = cappedDelay * jitterFactor * Math.random();\n\n return Math.floor(cappedDelay + jitter);\n}\n\n/**\n * Sleep for the specified number of milliseconds\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Determine if an error should be retried based on classification\n */\nexport function shouldRetryError(classification: { retryable: boolean; isAuth: boolean }): boolean {\n // Never retry auth errors (they won't succeed with the same credentials)\n if (classification.isAuth) {\n return false;\n }\n\n // Retry if the error is classified as retryable\n return classification.retryable;\n}\n\n/**\n * Create a retry context for tracking retry attempts\n */\nexport function createRetryContext(\n maxAttempts: number,\n baseDelay: number,\n maxDelay: number,\n jitterFactor: number\n): RetryContext {\n return {\n attempt: 1,\n maxAttempts,\n lastError: new Error('Initial attempt'),\n totalDelay: 0,\n nextDelay: calculateRetryDelay(1, baseDelay, maxDelay, jitterFactor)\n };\n}\n\n/**\n * Update retry context for the next attempt\n */\nexport function updateRetryContext(\n context: RetryContext,\n lastError: Error,\n baseDelay: number,\n maxDelay: number,\n jitterFactor: number\n): RetryContext {\n const nextAttempt = context.attempt + 1;\n const nextDelay = calculateRetryDelay(nextAttempt, baseDelay, maxDelay, jitterFactor);\n\n return {\n attempt: nextAttempt,\n maxAttempts: context.maxAttempts,\n lastError,\n totalDelay: context.totalDelay + context.nextDelay,\n nextDelay\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/http-client/index.js","../src/errors.js","../src/http-client/errors.js","../src/http-client/retry.js"],"sourcesContent":["/**\n * HttpClient - Resilient HTTP Client with Retry Logic\n *\n * A production-ready HTTP client that:\n * - Wraps axios with enhanced error handling and retry logic\n * - Never throws exceptions - always returns unified response format\n * - Uses exponential backoff with jitter for retries\n * - Provides human-readable error classifications\n * - Supports comprehensive logging\n * - Handles all HTTP methods consistently\n */\n\nimport axios, { } from \"axios\";\n\n\n\n\n\n\n\n\nimport { HttpClientError } from \"../errors.js\";\nimport { classifyError, getErrorDescription } from \"./errors.js\";\nimport { calculateRetryDelay, sleep, shouldRetryError, } from \"./retry.js\";\n\nexport { HttpClientError };\n\n/**\n * Resilient HTTP Client with automatic retry logic.\n * Use HttpClient.init(context, options) when running with init/context; constructor(config) for standalone.\n */\nexport class HttpClient {\n axiosInstance;\n config;\n logger;\n\n constructor(contextOrConfig = {}, config) {\n const hasContext = config !== undefined;\n const options = hasContext ? config : (contextOrConfig || {});\n const context = hasContext ? contextOrConfig : undefined;\n\n this.config = {\n ...options,\n logger: context?.logger ?? options.logger ?? console,\n };\n this.logger = this.config.logger;\n\n this.axiosInstance = axios.create({\n timeout: this.config.timeout,\n validateStatus: () => true,\n maxRedirects: this.config.maxRedirects,\n headers: { \"User-Agent\": this.config.userAgent },\n httpsAgent: this.config.validateSSL ? undefined : { rejectUnauthorized: false } ,\n });\n\n // Add response interceptor for logging (optional - only if debug enabled)\n this.axiosInstance.interceptors.response.use(\n (response) => response,\n (error) => {\n // Log network-level errors here if needed\n // (HTTP errors are handled in the request method)\n return Promise.reject(error);\n }\n );\n }\n\n /**\n * Static init - discovers params via getAllForModule(defs). Whatever is in options goes.\n */\n static init(context, options = {}) {\n const defs = {\n timeout: \"number default 30000\",\n retryCount: \"number default 3\",\n retryDelay: \"number default 1000\",\n maxRetryDelay: \"number default 30000\",\n retryJitter: \"number default 0.1\",\n userAgent: \"string default HttpClient/v1.0\",\n validateSSL: \"boolean default true\",\n maxRedirects: \"number default 5\",\n };\n const discovered = context?.params?.getAllForModule?.(defs) ?? {};\n const merged = { ...discovered, ...options, logger: options.logger ?? context?.logger };\n return new HttpClient(context, merged);\n }\n\n /**\n * Make an HTTP request with automatic retry logic\n * Never throws - always returns HttpClientResponse\n */\n async request(\n method,\n url,\n options = {}\n ) {\n const startTime = Date.now();\n\n // Merge request options with defaults\n const requestConfig = {\n method,\n url,\n timeout: options.timeout ?? this.config.timeout,\n headers: {\n \"User-Agent\": options.userAgent ?? this.config.userAgent,\n ...options.headers\n },\n params: options.params,\n data: options.data\n };\n\n const retryCount = options.retryCount ?? this.config.retryCount;\n const retryDelay = options.retryDelay ?? this.config.retryDelay;\n\n // Initialize retry context\n const _retryContext = null;\n let _lastError = null;\n\n // Attempt the request with retries\n for (let attempt = 1; attempt <= retryCount + 1; attempt++) {\n try {\n if (options.debug) {\n this.logger.debug?.(`[HttpClient] ${method} ${url} (attempt ${attempt}/${retryCount + 1})`);\n }\n\n const response = await this.axiosInstance.request(requestConfig);\n const duration = Date.now() - startTime;\n\n // Success! Return unified response format\n const customStatus = this.mapHttpStatusToCustomStatus(response.status);\n\n if (options.debug) {\n this.logger.debug?.(`[HttpClient] ${method} ${url} → ${response.status} ${customStatus} (${duration}ms)`);\n }\n\n return {\n status: customStatus,\n code: response.status,\n headers: response.headers ,\n data: response.data,\n duration,\n retryCount: attempt - 1,\n finalUrl: response.request?.res?.responseUrl || url\n };\n\n } catch (error) {\n _lastError = error;\n const duration = Date.now() - startTime;\n\n // Classify the error\n const classification = classifyError(error);\n const errorDescription = getErrorDescription(classification.type);\n\n // Log the error\n if (classification.retryable && attempt <= retryCount) {\n this.logger.warn?.(`[HttpClient] ${method} ${url} failed (${classification.type}): ${errorDescription}. Retrying in ${retryDelay}ms...`);\n } else if (!classification.retryable || attempt > retryCount) {\n this.logger.error?.(`[HttpClient] ${method} ${url} failed (${classification.type}): ${errorDescription}`);\n }\n\n // Check if we should retry\n if (attempt <= retryCount && shouldRetryError(classification)) {\n // Calculate delay and wait\n const delay = calculateRetryDelay(\n attempt,\n retryDelay,\n this.config.maxRetryDelay,\n this.config.retryJitter\n );\n\n if (options.debug) {\n this.logger.debug?.(`[HttpClient] Waiting ${delay}ms before retry ${attempt + 1}`);\n }\n\n await sleep(delay);\n continue;\n }\n\n // No more retries or not retryable - return error response\n return {\n status: classification.status,\n code: error.response?.status || null,\n error: classification.type,\n headers: error.response?.headers || null,\n data: error.response?.data || null,\n duration,\n retryCount: attempt - 1,\n finalUrl: url\n };\n }\n }\n\n // This should never be reached, but just in case\n return {\n status: \"unknown\",\n code: null,\n error: \"unknown\",\n headers: null,\n data: null,\n duration: Date.now() - startTime,\n retryCount: retryCount,\n finalUrl: url\n };\n }\n\n /**\n * GET request\n */\n async get(url, options = {}) {\n return this.request(\"GET\", url, options);\n }\n\n /**\n * POST request\n */\n async post(url, options = {}) {\n return this.request(\"POST\", url, options);\n }\n\n /**\n * PUT request\n */\n async put(url, options = {}) {\n return this.request(\"PUT\", url, options);\n }\n\n /**\n * DELETE request\n */\n async delete(url, options = {}) {\n return this.request(\"DELETE\", url, options);\n }\n\n /**\n * PATCH request\n */\n async patch(url, options = {}) {\n return this.request(\"PATCH\", url, options);\n }\n\n /**\n * HEAD request\n */\n async head(url, options = {}) {\n return this.request(\"HEAD\", url, options);\n }\n\n /**\n * OPTIONS request\n */\n async options(url, options = {}) {\n return this.request(\"OPTIONS\", url, options);\n }\n\n /**\n * Map HTTP status code to custom status\n */\n mapHttpStatusToCustomStatus(httpStatus) {\n if (httpStatus >= 200 && httpStatus < 300) {\n return \"success\";\n } else if (httpStatus === 401) {\n return \"authRequired\";\n } else if (httpStatus === 403) {\n return \"authFailed\";\n } else if (httpStatus >= 400 && httpStatus < 500) {\n return \"clientError\";\n } else if (httpStatus >= 500) {\n return \"serverError\";\n }\n return \"unknown\";\n }\n\n /**\n * Get current configuration (for debugging)\n */\n getConfig() {\n return { ...this.config };\n }\n}\n","/**\n * Error classes for the CLI toolkit\n */\n\nexport class FrameworkError extends Error {\n constructor(message) {\n super(message);\n this.name = \"FrameworkError\";\n }\n}\n\nexport class ParamError extends FrameworkError {\n constructor(message) {\n super(message);\n this.name = \"ParamError\";\n }\n}\n\nexport class InitError extends FrameworkError {\n constructor(message) {\n super(message);\n this.name = \"InitError\";\n }\n}\n\nexport class CriticalRequestError extends FrameworkError {\n constructor(message) {\n super(message);\n this.name = \"CriticalRequestError\";\n }\n}\n\nexport class ControlFlowError extends Error {\n constructor(message) {\n super(message);\n this.name = \"ControlFlowError\";\n }\n}\n\nexport class HttpClientError extends FrameworkError {\n constructor(message, cause) {\n super(message);this.cause = cause;;\n this.name = \"HttpClientError\";\n }\n}\n\nexport class FileDatabaseError extends FrameworkError {\n constructor(message) {\n super(message);\n this.name = \"FileDatabaseError\";\n }\n}\n\n","\n\n\n\n\n\n\n\n/**\n * Classify an error and determine retry behavior\n */\nexport function classifyError(error) {\n // Handle axios response errors (HTTP errors)\n if (error.response) {\n const { status } = error.response;\n\n switch (status) {\n case 400:\n return { type: \"badRequest\", retryable: false, isAuth: false, status: \"clientError\" };\n case 401:\n return { type: \"unauthorized\", retryable: false, isAuth: true, status: \"authRequired\" };\n case 403:\n return { type: \"forbidden\", retryable: false, isAuth: true, status: \"authFailed\" };\n case 404:\n return { type: \"notFound\", retryable: false, isAuth: false, status: \"clientError\" };\n case 405:\n return { type: \"methodNotAllowed\", retryable: false, isAuth: false, status: \"clientError\" };\n case 409:\n return { type: \"conflict\", retryable: false, isAuth: false, status: \"clientError\" };\n case 422:\n return { type: \"unprocessableEntity\", retryable: false, isAuth: false, status: \"clientError\" };\n case 429:\n return { type: \"tooManyRequests\", retryable: true, isAuth: false, status: \"clientError\" };\n case 500:\n return { type: \"internalServerError\", retryable: true, isAuth: false, status: \"serverError\" };\n case 502:\n return { type: \"badGateway\", retryable: true, isAuth: false, status: \"serverError\" };\n case 503:\n return { type: \"serviceUnavailable\", retryable: true, isAuth: false, status: \"serverError\" };\n case 504:\n return { type: \"gatewayTimeout\", retryable: true, isAuth: false, status: \"serverError\" };\n default:\n if (status >= 400 && status < 500) {\n return { type: \"clientError\" , retryable: false, isAuth: false, status: \"clientError\" };\n } else if (status >= 500) {\n return { type: \"serverError\" , retryable: true, isAuth: false, status: \"serverError\" };\n }\n break;\n }\n }\n\n // Handle network/connection errors (no response)\n if (error.code) {\n switch (error.code) {\n case \"ECONNREFUSED\":\n case \"ECONNRESET\":\n case \"EPIPE\":\n case \"ENOTFOUND\":\n case \"EHOSTUNREACH\":\n case \"ENETUNREACH\":\n return { type: \"connectionFailed\", retryable: true, isAuth: false, status: \"networkError\" };\n\n case \"ETIMEDOUT\":\n case \"ECONNABORTED\":\n case \"ESOCKETTIMEDOUT\":\n return { type: \"timeout\", retryable: true, isAuth: false, status: \"timeout\" };\n\n case \"EAUTH\":\n case \"EACCES\":\n return { type: \"unauthorized\", retryable: false, isAuth: true, status: \"authRequired\" };\n\n default:\n return { type: \"networkError\", retryable: true, isAuth: false, status: \"networkError\" };\n }\n }\n\n // Handle timeout errors\n if (error.message && (\n error.message.includes(\"timeout\") ||\n error.message.includes(\"TIMEOUT\") ||\n error.message.includes(\"aborted\")\n )) {\n return { type: \"timeout\", retryable: true, isAuth: false, status: \"timeout\" };\n }\n\n // Handle cancellation\n if (error.name === \"AbortError\" || error.message?.includes(\"cancelled\")) {\n return { type: \"requestCancelled\", retryable: false, isAuth: false, status: \"unknown\" };\n }\n\n // Default fallback\n return { type: \"unknown\", retryable: false, isAuth: false, status: \"unknown\" };\n}\n\n/**\n * Get a human-readable description for an error type\n */\nexport function getErrorDescription(errorType) {\n const descriptions = {\n connectionFailed: \"Failed to establish a connection to the server\",\n timeout: \"Request timed out before completing\",\n networkError: \"Network connection issue occurred\",\n badRequest: \"Request was malformed or invalid\",\n unauthorized: \"Authentication credentials are required\",\n forbidden: \"Access to the requested resource is forbidden\",\n notFound: \"The requested resource was not found\",\n methodNotAllowed: \"HTTP method not allowed for this resource\",\n conflict: \"Request conflicts with current server state\",\n unprocessableEntity: \"Request data could not be processed\",\n tooManyRequests: \"Too many requests sent in a short time\",\n internalServerError: \"Server encountered an internal error\",\n badGateway: \"Invalid response from upstream server\",\n serviceUnavailable: \"Server is temporarily unavailable\",\n gatewayTimeout: \"Upstream server timed out\",\n unknown: \"An unknown error occurred\",\n requestCancelled: \"Request was cancelled before completion\"\n };\n\n return descriptions[errorType] || \"An unknown error occurred\";\n}\n","\n\n\n\n\n\n\n\n/**\n * Calculate the next retry delay using exponential backoff with jitter\n *\n * Formula: delay = baseDelay * (2 ^ (attempt - 1)) + randomJitter\n *\n * Jitter prevents the \"thundering herd\" problem where multiple failed requests\n * all retry at the exact same time, overwhelming the server.\n */\nexport function calculateRetryDelay(\n attempt,\n baseDelay,\n maxDelay,\n jitterFactor = 0.1\n) {\n // Exponential backoff: baseDelay * (2 ^ (attempt - 1))\n const exponentialDelay = baseDelay * Math.pow(2, attempt - 1);\n\n // Cap at maximum delay\n const cappedDelay = Math.min(exponentialDelay, maxDelay);\n\n // Add jitter: random variation up to jitterFactor of the delay\n const jitter = cappedDelay * jitterFactor * Math.random();\n\n return Math.floor(cappedDelay + jitter);\n}\n\n/**\n * Sleep for the specified number of milliseconds\n */\nexport function sleep(ms) {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Determine if an error should be retried based on classification\n */\nexport function shouldRetryError(classification) {\n // Never retry auth errors (they won't succeed with the same credentials)\n if (classification.isAuth) {\n return false;\n }\n\n // Retry if the error is classified as retryable\n return classification.retryable;\n}\n\n/**\n * Create a retry context for tracking retry attempts\n */\nexport function createRetryContext(\n maxAttempts,\n baseDelay,\n maxDelay,\n jitterFactor\n) {\n return {\n attempt: 1,\n maxAttempts,\n lastError: new Error(\"Initial attempt\"),\n totalDelay: 0,\n nextDelay: calculateRetryDelay(1, baseDelay, maxDelay, jitterFactor)\n };\n}\n\n/**\n * Update retry context for the next attempt\n */\nexport function updateRetryContext(\n context,\n lastError,\n baseDelay,\n maxDelay,\n jitterFactor\n) {\n const nextAttempt = context.attempt + 1;\n const nextDelay = calculateRetryDelay(nextAttempt, baseDelay, maxDelay, jitterFactor);\n\n return {\n attempt: nextAttempt,\n maxAttempts: context.maxAttempts,\n lastError,\n totalDelay: context.totalDelay + context.nextDelay,\n nextDelay\n };\n}\n"],"mappings":"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","names":[]}
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -27,18 +26,16 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
26
  ));
28
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
28
 
30
- // src/http-client2.ts
29
+ // src/http-client2/index.js
31
30
  var http_client2_exports = {};
32
31
  __export(http_client2_exports, {
33
32
  HttpClient: () => HttpClient,
34
33
  HttpClientError: () => HttpClientError
35
34
  });
36
35
  module.exports = __toCommonJS(http_client2_exports);
37
-
38
- // src/http-client2/index.ts
39
36
  var import_path4 = __toESM(require("path"), 1);
40
37
 
41
- // src/errors.ts
38
+ // src/errors.js
42
39
  var FrameworkError = class extends Error {
43
40
  constructor(message) {
44
41
  super(message);
@@ -55,6 +52,7 @@ var HttpClientError = class extends FrameworkError {
55
52
  constructor(message, cause) {
56
53
  super(message);
57
54
  this.cause = cause;
55
+ ;
58
56
  this.name = "HttpClientError";
59
57
  }
60
58
  };
@@ -65,7 +63,7 @@ var FileDatabaseError = class extends FrameworkError {
65
63
  }
66
64
  };
67
65
 
68
- // src/http-client2/errors.ts
66
+ // src/http-client2/errors.js
69
67
  function classifyError(error) {
70
68
  if (error.response) {
71
69
  const { status } = error.response;
@@ -150,7 +148,7 @@ function getErrorDescription(errorType) {
150
148
  return descriptions[errorType] || "An unknown error occurred";
151
149
  }
152
150
 
153
- // src/http-client2/retry.ts
151
+ // src/http-client2/retry.js
154
152
  function calculateRetryDelay(attempt, baseDelay, maxDelay, jitterFactor = 0.1) {
155
153
  const exponentialDelay = baseDelay * Math.pow(2, attempt - 1);
156
154
  const cappedDelay = Math.min(exponentialDelay, maxDelay);
@@ -165,11 +163,11 @@ function shouldRetryError(classification) {
165
163
  return classification.retryable;
166
164
  }
167
165
 
168
- // src/filedatabase/index.ts
166
+ // src/filedatabase/index.js
169
167
  var import_fs3 = __toESM(require("fs"), 1);
170
168
  var import_path3 = __toESM(require("path"), 1);
171
169
 
172
- // src/utils/os-utils.ts
170
+ // src/utils/os-utils.js
173
171
  var import_fs = __toESM(require("fs"), 1);
174
172
  var import_path = __toESM(require("path"), 1);
175
173
  var import_child_process = require("child_process");
@@ -198,7 +196,7 @@ function getFreeDiskSpace(targetPath) {
198
196
  }
199
197
  }
200
198
 
201
- // src/utils/fs-utils.ts
199
+ // src/utils/fs-utils.js
202
200
  var import_fs2 = __toESM(require("fs"), 1);
203
201
  var import_path2 = __toESM(require("path"), 1);
204
202
  async function ensurePath(...pathParts) {
@@ -222,7 +220,7 @@ function getFileExtension(dataType) {
222
220
  }
223
221
  }
224
222
 
225
- // src/utils/format-utils.ts
223
+ // src/utils/format-utils.js
226
224
  function bytesToHumanReadable(bytes) {
227
225
  if (bytes === 0) return "0 B";
228
226
  const k = 1024;
@@ -231,7 +229,7 @@ function bytesToHumanReadable(bytes) {
231
229
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
232
230
  }
233
231
 
234
- // src/utils/date-utils.ts
232
+ // src/utils/date-utils.js
235
233
  function isTimestampFolder(folderName) {
236
234
  const isoRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(Z|\.\d{3}Z)$/;
237
235
  if (!isoRegex.test(folderName)) {
@@ -241,7 +239,7 @@ function isTimestampFolder(folderName) {
241
239
  return !isNaN(date.getTime()) && date.getTime() > 0;
242
240
  }
243
241
 
244
- // src/filedatabase/serializers.ts
242
+ // src/filedatabase/serializers.js
245
243
  function detectDataType(data) {
246
244
  if (Array.isArray(data)) {
247
245
  return "json-array";
@@ -273,7 +271,7 @@ function deserializeData(rawData, dataType) {
273
271
  }
274
272
  }
275
273
 
276
- // src/filedatabase/index.ts
274
+ // src/filedatabase/index.js
277
275
  var FileDatabase = class _FileDatabase {
278
276
  basePath;
279
277
  namespace;
@@ -359,7 +357,7 @@ var FileDatabase = class _FileDatabase {
359
357
  if (errors.length) {
360
358
  throw new FileDatabaseError(`[FileDatabase] ${errors.join("; ")}`);
361
359
  }
362
- let parts = [this.basePath, this.namespace];
360
+ const parts = [this.basePath, this.namespace];
363
361
  if (this.tableName) {
364
362
  parts.push(...this.tableName.split("/"));
365
363
  }
@@ -852,14 +850,17 @@ var FileDatabase = class _FileDatabase {
852
850
  * Prepare the instance for read or write operations
853
851
  * This discovers state and sets up internal members based on mode and current data
854
852
  */
855
- async prepare({ write, read, version }) {
853
+ async prepare(options) {
854
+ const { write, read, version, deferInitialVersion } = options;
856
855
  if (write) {
857
856
  if (this.versioned) {
858
857
  if (this.currentVersion === null) {
859
- await this.makeNewVersion();
860
- this.metadata = this.getDefaultMetadata();
861
- this.metadata.version = this.currentVersion;
862
- this.makeNewFile();
858
+ if (!deferInitialVersion) {
859
+ await this.makeNewVersion();
860
+ this.metadata = this.getDefaultMetadata();
861
+ this.metadata.version = this.currentVersion;
862
+ this.makeNewFile();
863
+ }
863
864
  } else {
864
865
  if (!this.metadata.files.length) {
865
866
  this.metadata = await this.figureMetadata(this.currentVersion);
@@ -969,7 +970,7 @@ var FileDatabase = class _FileDatabase {
969
970
  if (options.forceNewVersion && !this.versioned) {
970
971
  throw new FileDatabaseError("Cannot use forceNewVersion in non-versioned mode");
971
972
  }
972
- await this.prepare({ write: true });
973
+ await this.prepare({ write: true, deferInitialVersion: !!(options.forceNewVersion && this.versioned) });
973
974
  const incomingDataType = detectDataType(data);
974
975
  this.metadata.dataType = incomingDataType;
975
976
  if (options.forceNewVersion) {
@@ -1263,7 +1264,7 @@ var FileDatabase = class _FileDatabase {
1263
1264
  }
1264
1265
  };
1265
1266
 
1266
- // src/mock-server/mock-storage.ts
1267
+ // src/mock-server/mock-storage.js
1267
1268
  function stableStringify(obj) {
1268
1269
  if (obj === null) return "null";
1269
1270
  if (obj === void 0) return "undefined";
@@ -1360,7 +1361,7 @@ var MockStorage = class {
1360
1361
  }
1361
1362
  };
1362
1363
 
1363
- // src/http-client2/index.ts
1364
+ // src/http-client2/index.js
1364
1365
  function buildUrl(baseURL, url, params) {
1365
1366
  let full = url;
1366
1367
  if (baseURL) {
@@ -1458,7 +1459,8 @@ var HttpClient = class _HttpClient {
1458
1459
  }
1459
1460
  }
1460
1461
  /**
1461
- * Static init - discovers params via context.params.getAllForModule("http-client2", defs). Whatever is in options goes.
1462
+ * Static init - discovers params via context.params.getAllForModule("http-client2", defs).
1463
+ * Whatever is in options wins. Params are grouped under `http-client2` for --showUsedParams.
1462
1464
  */
1463
1465
  static init(context, options = {}) {
1464
1466
  const defs = {
@@ -1481,7 +1483,7 @@ var HttpClient = class _HttpClient {
1481
1483
  showMaxArrayItems: "number default 5",
1482
1484
  showMaxChars: "number default 300"
1483
1485
  };
1484
- const discovered = context?.params?.getAllForModule?.(defs) ?? {};
1486
+ const discovered = context?.params?.getAllForModule?.("http-client2", defs) ?? {};
1485
1487
  const merged = { ...discovered, ...options };
1486
1488
  if ((merged.saveMock || merged.useMock) && !merged.mocksPath) {
1487
1489
  throw new ParamError("[http-client2] mocksPath is required when saveMock or useMock is set");
@@ -1496,7 +1498,7 @@ var HttpClient = class _HttpClient {
1496
1498
  const timeout = options.timeout ?? this.config.timeout;
1497
1499
  const retryCount = options.retryCount ?? this.config.retryCount ?? 3;
1498
1500
  const retryDelay = options.retryDelay ?? this.config.retryDelay ?? 1e3;
1499
- let fullUrl = buildUrl(this.config.baseURL, url, options.params);
1501
+ const fullUrl = buildUrl(this.config.baseURL, url, options.params);
1500
1502
  if (this.config.useMock && this.mockStorage) {
1501
1503
  try {
1502
1504
  const urlObj = new URL(fullUrl);
@@ -1677,21 +1679,20 @@ var HttpClient = class _HttpClient {
1677
1679
  const maxKeys = this.config.showMaxKeys ?? 20;
1678
1680
  const maxArray = this.config.showMaxArrayItems ?? 5;
1679
1681
  const maxChars = this.config.showMaxChars ?? 300;
1680
- const log = this.logger.info ?? this.logger.log ?? console.log;
1681
- log(`[HttpClient] ${method} ${url}`);
1682
+ this.logger.info(`[HttpClient] ${method} ${url}`);
1682
1683
  if (this.config.showRequestHeaders && reqHeaders && Object.keys(reqHeaders).length > 0) {
1683
- log(` Request headers: ${formatForDisplay(reqHeaders, maxKeys, maxArray, maxChars)}`);
1684
+ this.logger.info(` Request headers: ${formatForDisplay(reqHeaders, maxKeys, maxArray, maxChars)}`);
1684
1685
  }
1685
1686
  if (options.data != null) {
1686
- log(` Request body: ${formatForDisplay(options.data, maxKeys, maxArray, maxChars)}`);
1687
+ this.logger.info(` Request body: ${formatForDisplay(options.data, maxKeys, maxArray, maxChars)}`);
1687
1688
  }
1688
1689
  if (res) {
1689
- log(` \u2192 ${res.status}${fromMock ? " (from mock)" : ""} ${durationMs}ms`);
1690
+ this.logger.info(` \u2192 ${res.status}${fromMock ? " (from mock)" : ""} ${durationMs}ms`);
1690
1691
  if (this.config.showResponseHeaders && res.headers && Object.keys(res.headers).length > 0) {
1691
- log(` Response headers: ${formatForDisplay(res.headers, maxKeys, maxArray, maxChars)}`);
1692
+ this.logger.info(` Response headers: ${formatForDisplay(res.headers, maxKeys, maxArray, maxChars)}`);
1692
1693
  }
1693
1694
  if (res.data != null) {
1694
- log(` Response body: ${formatForDisplay(res.data, maxKeys, maxArray, maxChars)}`);
1695
+ this.logger.info(` Response body: ${formatForDisplay(res.data, maxKeys, maxArray, maxChars)}`);
1695
1696
  }
1696
1697
  }
1697
1698
  }