@socketsecurity/lib 1.3.5 → 2.0.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 (282) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/dist/agent.js +1 -1
  3. package/dist/agent.js.map +2 -2
  4. package/dist/bin.js +1 -1
  5. package/dist/bin.js.map +3 -3
  6. package/dist/cacache.d.ts +4 -0
  7. package/dist/cacache.js +1 -1
  8. package/dist/cacache.js.map +3 -3
  9. package/dist/constants/packages.js +1 -1
  10. package/dist/constants/packages.js.map +3 -3
  11. package/dist/debug.d.ts +0 -7
  12. package/dist/debug.js +2 -2
  13. package/dist/debug.js.map +3 -3
  14. package/dist/dlx-binary.js +1 -1
  15. package/dist/dlx-binary.js.map +3 -3
  16. package/dist/effects/text-shimmer.js +1 -1
  17. package/dist/effects/text-shimmer.js.map +2 -2
  18. package/dist/env/ci.d.ts +1 -1
  19. package/dist/env/ci.js +1 -1
  20. package/dist/env/ci.js.map +3 -3
  21. package/dist/env/debug.d.ts +1 -1
  22. package/dist/env/debug.js +1 -1
  23. package/dist/env/debug.js.map +3 -3
  24. package/dist/env/github.d.ts +40 -0
  25. package/dist/env/github.js +3 -0
  26. package/dist/env/github.js.map +7 -0
  27. package/dist/env/home.d.ts +1 -1
  28. package/dist/env/home.js +1 -1
  29. package/dist/env/home.js.map +3 -3
  30. package/dist/env/locale.d.ts +15 -0
  31. package/dist/env/locale.js +3 -0
  32. package/dist/env/locale.js.map +7 -0
  33. package/dist/env/node-auth-token.d.ts +1 -1
  34. package/dist/env/node-auth-token.js +1 -1
  35. package/dist/env/node-auth-token.js.map +3 -3
  36. package/dist/env/node-env.d.ts +1 -1
  37. package/dist/env/node-env.js +1 -1
  38. package/dist/env/node-env.js.map +3 -3
  39. package/dist/env/npm.d.ts +25 -0
  40. package/dist/env/npm.js +3 -0
  41. package/dist/env/npm.js.map +7 -0
  42. package/dist/env/path.d.ts +1 -1
  43. package/dist/env/path.js +1 -1
  44. package/dist/env/path.js.map +3 -3
  45. package/dist/env/pre-commit.d.ts +1 -1
  46. package/dist/env/pre-commit.js +1 -1
  47. package/dist/env/pre-commit.js.map +3 -3
  48. package/dist/env/rewire.d.ts +106 -0
  49. package/dist/env/rewire.js +3 -0
  50. package/dist/env/rewire.js.map +7 -0
  51. package/dist/env/shell.d.ts +1 -1
  52. package/dist/env/shell.js +1 -1
  53. package/dist/env/shell.js.map +3 -3
  54. package/dist/env/socket-cli-shadow.d.ts +30 -0
  55. package/dist/env/socket-cli-shadow.js +3 -0
  56. package/dist/env/socket-cli-shadow.js.map +7 -0
  57. package/dist/env/socket-cli.d.ts +72 -0
  58. package/dist/env/socket-cli.js +3 -0
  59. package/dist/env/socket-cli.js.map +7 -0
  60. package/dist/env/socket.d.ts +75 -0
  61. package/dist/env/socket.js +3 -0
  62. package/dist/env/socket.js.map +7 -0
  63. package/dist/env/temp-dir.d.ts +15 -0
  64. package/dist/env/temp-dir.js +3 -0
  65. package/dist/env/temp-dir.js.map +7 -0
  66. package/dist/env/term.d.ts +1 -1
  67. package/dist/env/term.js +1 -1
  68. package/dist/env/term.js.map +3 -3
  69. package/dist/env/test.d.ts +15 -0
  70. package/dist/env/test.js +3 -0
  71. package/dist/env/test.js.map +7 -0
  72. package/dist/env/windows.d.ts +20 -0
  73. package/dist/env/windows.js +3 -0
  74. package/dist/env/windows.js.map +7 -0
  75. package/dist/env/xdg.d.ts +15 -0
  76. package/dist/env/xdg.js +3 -0
  77. package/dist/env/xdg.js.map +7 -0
  78. package/dist/fs.d.ts +7 -0
  79. package/dist/fs.js +3 -3
  80. package/dist/fs.js.map +3 -3
  81. package/dist/github.js +1 -1
  82. package/dist/github.js.map +3 -3
  83. package/dist/globs.js +1 -1
  84. package/dist/globs.js.map +2 -2
  85. package/dist/ipc.d.ts +1 -1
  86. package/dist/ipc.js +1 -1
  87. package/dist/ipc.js.map +3 -3
  88. package/dist/logger.d.ts +2 -1
  89. package/dist/logger.js +1 -1
  90. package/dist/logger.js.map +3 -3
  91. package/dist/packages/isolation.js +1 -1
  92. package/dist/packages/isolation.js.map +3 -3
  93. package/dist/packages/normalize.js +1 -1
  94. package/dist/packages/normalize.js.map +3 -3
  95. package/dist/packages/operations.js +1 -1
  96. package/dist/packages/operations.js.map +3 -3
  97. package/dist/path.d.ts +2 -2
  98. package/dist/path.js +1 -1
  99. package/dist/path.js.map +3 -3
  100. package/dist/paths/rewire.d.ts +71 -0
  101. package/dist/paths/rewire.js +3 -0
  102. package/dist/paths/rewire.js.map +7 -0
  103. package/dist/paths.d.ts +26 -0
  104. package/dist/paths.js +1 -1
  105. package/dist/paths.js.map +3 -3
  106. package/dist/spinner.js +1 -1
  107. package/dist/spinner.js.map +2 -2
  108. package/package.json +39 -226
  109. package/dist/env/appdata.d.ts +0 -1
  110. package/dist/env/appdata.js +0 -3
  111. package/dist/env/appdata.js.map +0 -7
  112. package/dist/env/comspec.d.ts +0 -1
  113. package/dist/env/comspec.js +0 -3
  114. package/dist/env/comspec.js.map +0 -7
  115. package/dist/env/getters.d.ts +0 -40
  116. package/dist/env/getters.js +0 -3
  117. package/dist/env/getters.js.map +0 -7
  118. package/dist/env/github-api-url.d.ts +0 -1
  119. package/dist/env/github-api-url.js +0 -3
  120. package/dist/env/github-api-url.js.map +0 -7
  121. package/dist/env/github-base-ref.d.ts +0 -1
  122. package/dist/env/github-base-ref.js +0 -3
  123. package/dist/env/github-base-ref.js.map +0 -7
  124. package/dist/env/github-ref-name.d.ts +0 -1
  125. package/dist/env/github-ref-name.js +0 -3
  126. package/dist/env/github-ref-name.js.map +0 -7
  127. package/dist/env/github-ref-type.d.ts +0 -1
  128. package/dist/env/github-ref-type.js +0 -3
  129. package/dist/env/github-ref-type.js.map +0 -7
  130. package/dist/env/github-repository.d.ts +0 -1
  131. package/dist/env/github-repository.js +0 -3
  132. package/dist/env/github-repository.js.map +0 -7
  133. package/dist/env/github-server-url.d.ts +0 -1
  134. package/dist/env/github-server-url.js +0 -3
  135. package/dist/env/github-server-url.js.map +0 -7
  136. package/dist/env/github-token.d.ts +0 -1
  137. package/dist/env/github-token.js +0 -3
  138. package/dist/env/github-token.js.map +0 -7
  139. package/dist/env/jest-worker-id.d.ts +0 -1
  140. package/dist/env/jest-worker-id.js +0 -3
  141. package/dist/env/jest-worker-id.js.map +0 -7
  142. package/dist/env/lang.d.ts +0 -1
  143. package/dist/env/lang.js +0 -3
  144. package/dist/env/lang.js.map +0 -7
  145. package/dist/env/lc-all.d.ts +0 -1
  146. package/dist/env/lc-all.js +0 -3
  147. package/dist/env/lc-all.js.map +0 -7
  148. package/dist/env/lc-messages.d.ts +0 -1
  149. package/dist/env/lc-messages.js +0 -3
  150. package/dist/env/lc-messages.js.map +0 -7
  151. package/dist/env/localappdata.d.ts +0 -1
  152. package/dist/env/localappdata.js +0 -3
  153. package/dist/env/localappdata.js.map +0 -7
  154. package/dist/env/npm-config-registry.d.ts +0 -1
  155. package/dist/env/npm-config-registry.js +0 -3
  156. package/dist/env/npm-config-registry.js.map +0 -7
  157. package/dist/env/npm-config-user-agent.d.ts +0 -1
  158. package/dist/env/npm-config-user-agent.js +0 -3
  159. package/dist/env/npm-config-user-agent.js.map +0 -7
  160. package/dist/env/npm-lifecycle-event.d.ts +0 -1
  161. package/dist/env/npm-lifecycle-event.js +0 -3
  162. package/dist/env/npm-lifecycle-event.js.map +0 -7
  163. package/dist/env/npm-registry.d.ts +0 -1
  164. package/dist/env/npm-registry.js +0 -3
  165. package/dist/env/npm-registry.js.map +0 -7
  166. package/dist/env/npm-token.d.ts +0 -1
  167. package/dist/env/npm-token.js +0 -3
  168. package/dist/env/npm-token.js.map +0 -7
  169. package/dist/env/socket-accept-risks.d.ts +0 -1
  170. package/dist/env/socket-accept-risks.js +0 -3
  171. package/dist/env/socket-accept-risks.js.map +0 -7
  172. package/dist/env/socket-api-base-url.d.ts +0 -1
  173. package/dist/env/socket-api-base-url.js +0 -3
  174. package/dist/env/socket-api-base-url.js.map +0 -7
  175. package/dist/env/socket-api-proxy.d.ts +0 -1
  176. package/dist/env/socket-api-proxy.js +0 -3
  177. package/dist/env/socket-api-proxy.js.map +0 -7
  178. package/dist/env/socket-api-timeout.d.ts +0 -1
  179. package/dist/env/socket-api-timeout.js +0 -3
  180. package/dist/env/socket-api-timeout.js.map +0 -7
  181. package/dist/env/socket-api-token.d.ts +0 -1
  182. package/dist/env/socket-api-token.js +0 -3
  183. package/dist/env/socket-api-token.js.map +0 -7
  184. package/dist/env/socket-cacache-dir.d.ts +0 -1
  185. package/dist/env/socket-cacache-dir.js +0 -3
  186. package/dist/env/socket-cacache-dir.js.map +0 -7
  187. package/dist/env/socket-cli-accept-risks.d.ts +0 -1
  188. package/dist/env/socket-cli-accept-risks.js +0 -3
  189. package/dist/env/socket-cli-accept-risks.js.map +0 -7
  190. package/dist/env/socket-cli-api-base-url.d.ts +0 -1
  191. package/dist/env/socket-cli-api-base-url.js +0 -3
  192. package/dist/env/socket-cli-api-base-url.js.map +0 -7
  193. package/dist/env/socket-cli-api-proxy.d.ts +0 -1
  194. package/dist/env/socket-cli-api-proxy.js +0 -3
  195. package/dist/env/socket-cli-api-proxy.js.map +0 -7
  196. package/dist/env/socket-cli-api-timeout.d.ts +0 -1
  197. package/dist/env/socket-cli-api-timeout.js +0 -3
  198. package/dist/env/socket-cli-api-timeout.js.map +0 -7
  199. package/dist/env/socket-cli-api-token.d.ts +0 -1
  200. package/dist/env/socket-cli-api-token.js +0 -3
  201. package/dist/env/socket-cli-api-token.js.map +0 -7
  202. package/dist/env/socket-cli-config.d.ts +0 -1
  203. package/dist/env/socket-cli-config.js +0 -3
  204. package/dist/env/socket-cli-config.js.map +0 -7
  205. package/dist/env/socket-cli-fix.d.ts +0 -1
  206. package/dist/env/socket-cli-fix.js +0 -3
  207. package/dist/env/socket-cli-fix.js.map +0 -7
  208. package/dist/env/socket-cli-no-api-token.d.ts +0 -1
  209. package/dist/env/socket-cli-no-api-token.js +0 -3
  210. package/dist/env/socket-cli-no-api-token.js.map +0 -7
  211. package/dist/env/socket-cli-optimize.d.ts +0 -1
  212. package/dist/env/socket-cli-optimize.js +0 -3
  213. package/dist/env/socket-cli-optimize.js.map +0 -7
  214. package/dist/env/socket-cli-org-slug.d.ts +0 -1
  215. package/dist/env/socket-cli-org-slug.js +0 -3
  216. package/dist/env/socket-cli-org-slug.js.map +0 -7
  217. package/dist/env/socket-cli-shadow-accept-risks.d.ts +0 -1
  218. package/dist/env/socket-cli-shadow-accept-risks.js +0 -3
  219. package/dist/env/socket-cli-shadow-accept-risks.js.map +0 -7
  220. package/dist/env/socket-cli-shadow-api-token.d.ts +0 -1
  221. package/dist/env/socket-cli-shadow-api-token.js +0 -3
  222. package/dist/env/socket-cli-shadow-api-token.js.map +0 -7
  223. package/dist/env/socket-cli-shadow-bin.d.ts +0 -1
  224. package/dist/env/socket-cli-shadow-bin.js +0 -3
  225. package/dist/env/socket-cli-shadow-bin.js.map +0 -7
  226. package/dist/env/socket-cli-shadow-progress.d.ts +0 -1
  227. package/dist/env/socket-cli-shadow-progress.js +0 -3
  228. package/dist/env/socket-cli-shadow-progress.js.map +0 -7
  229. package/dist/env/socket-cli-shadow-silent.d.ts +0 -1
  230. package/dist/env/socket-cli-shadow-silent.js +0 -3
  231. package/dist/env/socket-cli-shadow-silent.js.map +0 -7
  232. package/dist/env/socket-cli-view-all-risks.d.ts +0 -1
  233. package/dist/env/socket-cli-view-all-risks.js +0 -3
  234. package/dist/env/socket-cli-view-all-risks.js.map +0 -7
  235. package/dist/env/socket-config.d.ts +0 -1
  236. package/dist/env/socket-config.js +0 -3
  237. package/dist/env/socket-config.js.map +0 -7
  238. package/dist/env/socket-debug.d.ts +0 -1
  239. package/dist/env/socket-debug.js +0 -3
  240. package/dist/env/socket-debug.js.map +0 -7
  241. package/dist/env/socket-home.d.ts +0 -1
  242. package/dist/env/socket-home.js +0 -3
  243. package/dist/env/socket-home.js.map +0 -7
  244. package/dist/env/socket-no-api-token.d.ts +0 -1
  245. package/dist/env/socket-no-api-token.js +0 -3
  246. package/dist/env/socket-no-api-token.js.map +0 -7
  247. package/dist/env/socket-npm-registry.d.ts +0 -1
  248. package/dist/env/socket-npm-registry.js +0 -3
  249. package/dist/env/socket-npm-registry.js.map +0 -7
  250. package/dist/env/socket-org-slug.d.ts +0 -1
  251. package/dist/env/socket-org-slug.js +0 -3
  252. package/dist/env/socket-org-slug.js.map +0 -7
  253. package/dist/env/socket-registry-url.d.ts +0 -1
  254. package/dist/env/socket-registry-url.js +0 -3
  255. package/dist/env/socket-registry-url.js.map +0 -7
  256. package/dist/env/socket-view-all-risks.d.ts +0 -1
  257. package/dist/env/socket-view-all-risks.js +0 -3
  258. package/dist/env/socket-view-all-risks.js.map +0 -7
  259. package/dist/env/temp.d.ts +0 -1
  260. package/dist/env/temp.js +0 -3
  261. package/dist/env/temp.js.map +0 -7
  262. package/dist/env/tmp.d.ts +0 -1
  263. package/dist/env/tmp.js +0 -3
  264. package/dist/env/tmp.js.map +0 -7
  265. package/dist/env/tmpdir.d.ts +0 -1
  266. package/dist/env/tmpdir.js +0 -3
  267. package/dist/env/tmpdir.js.map +0 -7
  268. package/dist/env/userprofile.d.ts +0 -1
  269. package/dist/env/userprofile.js +0 -3
  270. package/dist/env/userprofile.js.map +0 -7
  271. package/dist/env/vitest.d.ts +0 -1
  272. package/dist/env/vitest.js +0 -3
  273. package/dist/env/vitest.js.map +0 -7
  274. package/dist/env/xdg-cache-home.d.ts +0 -1
  275. package/dist/env/xdg-cache-home.js +0 -3
  276. package/dist/env/xdg-cache-home.js.map +0 -7
  277. package/dist/env/xdg-config-home.d.ts +0 -1
  278. package/dist/env/xdg-config-home.js +0 -3
  279. package/dist/env/xdg-config-home.js.map +0 -7
  280. package/dist/env/xdg-data-home.d.ts +0 -1
  281. package/dist/env/xdg-data-home.js +0 -3
  282. package/dist/env/xdg-data-home.js.map +0 -7
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/github.ts"],
4
- "sourcesContent": ["/**\n * @fileoverview GitHub utilities for Socket projects.\n * Provides GitHub API integration for repository operations.\n *\n * Authentication:\n * - getGitHubToken: Retrieve GitHub token from environment variables\n * - fetchGitHub: Authenticated GitHub API requests with rate limit handling\n *\n * Ref Resolution:\n * - resolveRefToSha: Convert tags/branches to commit SHAs (with memoization and persistent cache)\n * - clearRefCache: Clear the in-memory memoization cache\n *\n * Caching:\n * - Uses cacache for persistent storage with in-memory memoization\n * - Two-tier caching: in-memory (Map) for hot data, persistent (cacache) for durability\n * - Default TTL: 5 minutes\n * - Disable with DISABLE_GITHUB_CACHE env var\n *\n * Rate Limiting:\n * - Automatic rate limit detection and error messages\n * - Cache to minimize API calls\n */\n\nimport type { TtlCache } from './cache-with-ttl'\nimport { createTtlCache } from './cache-with-ttl'\nimport { httpRequest } from './http-request'\nimport type { SpawnOptions } from './spawn'\nimport { spawn } from './spawn'\n\n// GitHub API base URL constant (inlined for coverage mode compatibility).\nconst GITHUB_API_BASE_URL = 'https://api.github.com'\n\n// 5 minutes.\nconst DEFAULT_CACHE_TTL_MS = 5 * 60 * 1000\n\n// Create TTL cache instance for GitHub ref resolution.\n// Uses cacache for persistent storage with in-memory memoization.\nlet _githubCache: TtlCache | undefined\n\n/**\n * Get or create the GitHub cache instance.\n * Lazy initializes the cache with default TTL and memoization enabled.\n * Used internally for caching GitHub API responses.\n *\n * @returns The singleton cache instance\n */\nfunction getGithubCache(): TtlCache {\n if (_githubCache === undefined) {\n _githubCache = createTtlCache({\n memoize: true,\n prefix: 'github-refs',\n ttl: DEFAULT_CACHE_TTL_MS,\n })\n }\n return _githubCache\n}\n\n/**\n * Options for GitHub API fetch requests.\n */\nexport interface GitHubFetchOptions {\n /**\n * GitHub authentication token.\n * If not provided, will attempt to use token from environment variables.\n */\n token?: string | undefined\n /**\n * Additional HTTP headers to include in the request.\n * Will be merged with default headers (Accept, User-Agent, Authorization).\n */\n headers?: Record<string, string> | undefined\n}\n\n/**\n * Error thrown when GitHub API rate limit is exceeded.\n * Extends the standard Error with additional rate limit information.\n */\nexport interface GitHubRateLimitError extends Error {\n /** HTTP status code (always 403 for rate limit errors) */\n status: number\n /**\n * Date when the rate limit will reset.\n * Undefined if reset time is not available in response headers.\n */\n resetTime?: Date | undefined\n}\n\n/**\n * Get GitHub authentication token from environment variables.\n * Checks multiple environment variable names in priority order.\n *\n * Environment variables checked (in order):\n * 1. `GITHUB_TOKEN` - Standard GitHub token variable\n * 2. `GH_TOKEN` - Alternative GitHub CLI token variable\n * 3. `SOCKET_CLI_GITHUB_TOKEN` - Socket-specific token variable\n *\n * @returns The first available GitHub token, or `undefined` if none found\n *\n * @example\n * ```ts\n * const token = getGitHubToken()\n * if (!token) {\n * console.warn('No GitHub token found')\n * }\n * ```\n */\nexport function getGitHubToken(): string | undefined {\n const { env } = process\n return (\n env['GITHUB_TOKEN'] ||\n env['GH_TOKEN'] ||\n env['SOCKET_CLI_GITHUB_TOKEN'] ||\n undefined\n )\n}\n\n/**\n * Fetch data from GitHub API with automatic authentication and rate limit handling.\n * Makes authenticated requests to the GitHub REST API with proper error handling.\n *\n * Features:\n * - Automatic token injection from environment if not provided\n * - Rate limit detection with helpful error messages\n * - Standard GitHub API headers (Accept, User-Agent)\n * - JSON response parsing\n *\n * @template T - Expected response type (defaults to `unknown`)\n * @param url - Full GitHub API URL (e.g., 'https://api.github.com/repos/owner/repo')\n * @param options - Fetch options including token and custom headers\n * @returns Parsed JSON response of type `T`\n *\n * @throws {GitHubRateLimitError} When API rate limit is exceeded (status 403)\n * @throws {Error} For other API errors with status code and message\n *\n * @example\n * ```ts\n * // Fetch repository information\n * interface Repo {\n * name: string\n * full_name: string\n * default_branch: string\n * }\n * const repo = await fetchGitHub<Repo>(\n * 'https://api.github.com/repos/owner/repo'\n * )\n * console.log(`Default branch: ${repo.default_branch}`)\n * ```\n *\n * @example\n * ```ts\n * // With custom token and headers\n * const data = await fetchGitHub(\n * 'https://api.github.com/user',\n * {\n * token: 'ghp_customtoken',\n * headers: { 'X-Custom-Header': 'value' }\n * }\n * )\n * ```\n *\n * @example\n * ```ts\n * // Handle rate limit errors\n * try {\n * await fetchGitHub('https://api.github.com/repos/owner/repo')\n * } catch (error) {\n * if (error.status === 403 && error.resetTime) {\n * console.error(`Rate limited until ${error.resetTime}`)\n * }\n * }\n * ```\n */\nexport async function fetchGitHub<T = unknown>(\n url: string,\n options?: GitHubFetchOptions | undefined,\n): Promise<T> {\n const opts = { __proto__: null, ...options } as GitHubFetchOptions\n const token = opts.token || getGitHubToken()\n\n const headers: Record<string, string> = {\n Accept: 'application/vnd.github.v3+json',\n 'User-Agent': 'socket-registry-github-client',\n ...opts.headers,\n }\n\n if (token) {\n headers['Authorization'] = `Bearer ${token}`\n }\n\n const response = await httpRequest(url, { headers })\n\n if (!response.ok) {\n if (response.status === 403) {\n const rateLimit = response.headers['x-ratelimit-remaining']\n const rateLimitStr =\n typeof rateLimit === 'string' ? rateLimit : rateLimit?.[0]\n if (rateLimitStr === '0') {\n const resetTime = response.headers['x-ratelimit-reset']\n const resetTimeStr =\n typeof resetTime === 'string' ? resetTime : resetTime?.[0]\n const resetDate = resetTimeStr\n ? new Date(Number(resetTimeStr) * 1000)\n : undefined\n const error = new Error(\n `GitHub API rate limit exceeded${resetDate ? `. Resets at ${resetDate.toLocaleString()}` : ''}. Use GITHUB_TOKEN environment variable to increase rate limit.`,\n ) as GitHubRateLimitError\n error.status = 403\n error.resetTime = resetDate\n throw error\n }\n }\n throw new Error(\n `GitHub API error ${response.status}: ${response.statusText}`,\n )\n }\n\n return JSON.parse(response.body.toString('utf8')) as T\n}\n\n/**\n * GitHub ref object returned by the API.\n * Represents a git reference (tag or branch).\n */\nexport interface GitHubRef {\n /** The object this ref points to */\n object: {\n /** SHA of the commit or tag object */\n sha: string\n /** Type of object ('commit' or 'tag') */\n type: string\n /** API URL to fetch the full object details */\n url: string\n }\n /** Full ref path (e.g., 'refs/tags/v1.0.0' or 'refs/heads/main') */\n ref: string\n /** API URL for this ref */\n url: string\n}\n\n/**\n * GitHub annotated tag object returned by the API.\n * Represents a git tag with metadata.\n */\nexport interface GitHubTag {\n /** Tag annotation message */\n message: string\n /** The commit this tag points to */\n object: {\n /** SHA of the commit */\n sha: string\n /** Type of object (usually 'commit') */\n type: string\n /** API URL to fetch the commit details */\n url: string\n }\n /** SHA of this tag object itself */\n sha: string\n /** Tag name (e.g., 'v1.0.0') */\n tag: string\n /**\n * Information about who created the tag.\n * Undefined for lightweight tags.\n */\n tagger?: {\n /** Tag creation date in ISO 8601 format */\n date: string\n /** Tagger's email address */\n email: string\n /** Tagger's name */\n name: string\n }\n /** API URL for this tag object */\n url: string\n}\n\n/**\n * GitHub commit object returned by the API.\n * Represents a git commit with metadata.\n */\nexport interface GitHubCommit {\n /** Full commit SHA */\n sha: string\n /** API URL for this commit */\n url: string\n /** Commit details */\n commit: {\n /** Commit message */\n message: string\n /** Author information */\n author: {\n /** Commit author date in ISO 8601 format */\n date: string\n /** Author's email address */\n email: string\n /** Author's name */\n name: string\n }\n }\n}\n\n/**\n * Options for resolving git refs to commit SHAs.\n */\nexport interface ResolveRefOptions {\n /**\n * GitHub authentication token.\n * If not provided, will attempt to use token from environment variables.\n */\n token?: string | undefined\n}\n\n/**\n * Resolve a git ref (tag, branch, or commit SHA) to its full commit SHA.\n * Handles tags (annotated and lightweight), branches, and commit SHAs.\n * Results are cached in-memory and on disk (with TTL) to minimize API calls.\n *\n * Resolution strategy:\n * 1. Try as a tag (refs/tags/{ref})\n * 2. If tag is annotated, dereference to get the commit SHA\n * 3. If not a tag, try as a branch (refs/heads/{ref})\n * 4. If not a branch, try as a commit SHA directly\n *\n * Caching behavior:\n * - In-memory cache (Map) for immediate lookups\n * - Persistent disk cache (cacache) for durability across runs\n * - Default TTL: 5 minutes\n * - Disable caching with `DISABLE_GITHUB_CACHE` env var\n *\n * @param owner - Repository owner (user or organization name)\n * @param repo - Repository name\n * @param ref - Git reference to resolve (tag name, branch name, or commit SHA)\n * @param options - Resolution options including authentication token\n * @returns The full commit SHA (40-character hex string)\n *\n * @throws {Error} When ref cannot be resolved after trying all strategies\n * @throws {GitHubRateLimitError} When API rate limit is exceeded\n *\n * @example\n * ```ts\n * // Resolve a tag to commit SHA\n * const sha = await resolveRefToSha('owner', 'repo', 'v1.0.0')\n * console.log(sha) // 'a1b2c3d4e5f6...'\n * ```\n *\n * @example\n * ```ts\n * // Resolve a branch to latest commit SHA\n * const sha = await resolveRefToSha('owner', 'repo', 'main')\n * console.log(sha) // Latest commit on main branch\n * ```\n *\n * @example\n * ```ts\n * // Resolve with custom token\n * const sha = await resolveRefToSha(\n * 'owner',\n * 'repo',\n * 'develop',\n * { token: 'ghp_customtoken' }\n * )\n * ```\n *\n * @example\n * ```ts\n * // Commit SHA passes through unchanged (but validates it exists)\n * const sha = await resolveRefToSha('owner', 'repo', 'a1b2c3d4')\n * console.log(sha) // Full 40-char SHA\n * ```\n */\nexport async function resolveRefToSha(\n owner: string,\n repo: string,\n ref: string,\n options?: ResolveRefOptions | undefined,\n): Promise<string> {\n const opts = {\n __proto__: null,\n ...options,\n } as ResolveRefOptions\n\n const cacheKey = `${owner}/${repo}@${ref}`\n\n // Optionally disable cache.\n if (process.env['DISABLE_GITHUB_CACHE']) {\n return await fetchRefSha(owner, repo, ref, opts)\n }\n\n // Use TTL cache for persistent storage and in-memory memoization.\n const cache = getGithubCache()\n return await cache.getOrFetch(cacheKey, async () => {\n return await fetchRefSha(owner, repo, ref, opts)\n })\n}\n\n/**\n * Fetch the SHA for a git ref from GitHub API.\n * Internal helper that implements the multi-strategy ref resolution logic.\n * Tries tags, branches, and direct commit lookups in sequence.\n *\n * @param owner - Repository owner\n * @param repo - Repository name\n * @param ref - Git reference to resolve\n * @param options - Resolution options with authentication token\n * @returns The full commit SHA\n *\n * @throws {Error} When ref cannot be resolved after all strategies fail\n */\nasync function fetchRefSha(\n owner: string,\n repo: string,\n ref: string,\n options: ResolveRefOptions,\n): Promise<string> {\n const fetchOptions: GitHubFetchOptions = {\n token: options.token,\n }\n\n try {\n // Try as a tag first.\n const tagUrl = `${GITHUB_API_BASE_URL}/repos/${owner}/${repo}/git/refs/tags/${ref}`\n const tagData = await fetchGitHub<GitHubRef>(tagUrl, fetchOptions)\n\n // Tag might point to a tag object or directly to a commit.\n if (tagData.object.type === 'tag') {\n // Dereference the tag object to get the commit.\n const tagObject = await fetchGitHub<GitHubTag>(\n tagData.object.url,\n fetchOptions,\n )\n return tagObject.object.sha\n }\n return tagData.object.sha\n } catch {\n // Not a tag, try as a branch.\n try {\n const branchUrl = `${GITHUB_API_BASE_URL}/repos/${owner}/${repo}/git/refs/heads/${ref}`\n const branchData = await fetchGitHub<GitHubRef>(branchUrl, fetchOptions)\n return branchData.object.sha\n } catch {\n // Try without refs/ prefix (for commit SHAs or other refs).\n try {\n const commitUrl = `${GITHUB_API_BASE_URL}/repos/${owner}/${repo}/commits/${ref}`\n const commitData = await fetchGitHub<GitHubCommit>(\n commitUrl,\n fetchOptions,\n )\n return commitData.sha\n } catch (e) {\n throw new Error(\n `failed to resolve ref \"${ref}\" for ${owner}/${repo}: ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n }\n }\n}\n\n/**\n * Clear the ref resolution cache (in-memory only).\n * Clears the in-memory memoization cache without affecting the persistent disk cache.\n * Useful for testing or when you need fresh data from the API.\n *\n * Note: This only clears the in-memory cache. The persistent cacache storage\n * remains intact and will be used to rebuild the in-memory cache on next access.\n *\n * @returns Promise that resolves when cache is cleared\n *\n * @example\n * ```ts\n * // Clear cache to force fresh API calls\n * await clearRefCache()\n * const sha = await resolveRefToSha('owner', 'repo', 'main')\n * // This will hit the persistent cache or API, not in-memory cache\n * ```\n */\nexport async function clearRefCache(): Promise<void> {\n if (_githubCache) {\n await _githubCache.clear({ memoOnly: true })\n }\n}\n\n/**\n * Get GitHub authentication token from git config.\n * Reads the `github.token` configuration value from git config.\n * This is a fallback method when environment variables don't contain a token.\n *\n * @param options - Spawn options for git command execution\n * @returns GitHub token from git config, or `undefined` if not configured\n *\n * @example\n * ```ts\n * const token = await getGitHubTokenFromGitConfig()\n * if (token) {\n * console.log('Found token in git config')\n * }\n * ```\n *\n * @example\n * ```ts\n * // With custom working directory\n * const token = await getGitHubTokenFromGitConfig({\n * cwd: '/path/to/repo'\n * })\n * ```\n */\nexport async function getGitHubTokenFromGitConfig(\n options?: SpawnOptions | undefined,\n): Promise<string | undefined> {\n try {\n const result = await spawn('git', ['config', 'github.token'], {\n ...options,\n stdio: 'pipe',\n })\n if (result.code === 0 && result.stdout) {\n return result.stdout.toString().trim()\n }\n } catch {\n // Ignore errors - git config may not have token.\n }\n return undefined\n}\n\n/**\n * Get GitHub authentication token from all available sources.\n * Checks environment variables first, then falls back to git config.\n * This is the recommended way to get a GitHub token with maximum compatibility.\n *\n * Priority order:\n * 1. Environment variables (GITHUB_TOKEN, GH_TOKEN, SOCKET_CLI_GITHUB_TOKEN)\n * 2. Git config (github.token)\n *\n * @returns GitHub token from first available source, or `undefined` if none found\n *\n * @example\n * ```ts\n * const token = await getGitHubTokenWithFallback()\n * if (!token) {\n * throw new Error('GitHub token required')\n * }\n * ```\n */\nexport async function getGitHubTokenWithFallback(): Promise<\n string | undefined\n> {\n return getGitHubToken() || (await getGitHubTokenFromGitConfig())\n}\n\n/**\n * GitHub Security Advisory (GHSA) details.\n * Represents a complete security advisory from GitHub's database.\n */\nexport interface GhsaDetails {\n /** GHSA identifier (e.g., 'GHSA-xxxx-yyyy-zzzz') */\n ghsaId: string\n /** Short summary of the vulnerability */\n summary: string\n /** Detailed description of the vulnerability */\n details: string\n /** Severity level ('low', 'moderate', 'high', 'critical') */\n severity: string\n /** Alternative identifiers (CVE IDs, etc.) */\n aliases: string[]\n /** ISO 8601 timestamp when advisory was published */\n publishedAt: string\n /** ISO 8601 timestamp when advisory was last updated */\n updatedAt: string\n /**\n * ISO 8601 timestamp when advisory was withdrawn.\n * `null` if advisory is still active.\n */\n withdrawnAt: string | null\n /** External reference URLs for more information */\n references: Array<{ url: string }>\n /** Affected packages and version ranges */\n vulnerabilities: Array<{\n /** Package information */\n package: {\n /** Ecosystem (e.g., 'npm', 'pip', 'maven') */\n ecosystem: string\n /** Package name */\n name: string\n }\n /** Version range expression for vulnerable versions */\n vulnerableVersionRange: string\n /**\n * First patched version that fixes the vulnerability.\n * `null` if no patched version exists yet.\n */\n firstPatchedVersion: { identifier: string } | null\n }>\n /**\n * CVSS (Common Vulnerability Scoring System) information.\n * `null` if CVSS score is not available.\n */\n cvss: {\n /** CVSS score (0.0-10.0) */\n score: number\n /** CVSS vector string describing the vulnerability characteristics */\n vectorString: string\n } | null\n /** CWE (Common Weakness Enumeration) categories */\n cwes: Array<{\n /** CWE identifier (e.g., 'CWE-79') */\n cweId: string\n /** Human-readable CWE name */\n name: string\n /** Description of the weakness category */\n description: string\n }>\n}\n\n/**\n * Generate GitHub Security Advisory URL from GHSA ID.\n * Constructs the public advisory URL for a given GHSA identifier.\n *\n * @param ghsaId - GHSA identifier (e.g., 'GHSA-xxxx-yyyy-zzzz')\n * @returns Full URL to the advisory page\n *\n * @example\n * ```ts\n * const url = getGhsaUrl('GHSA-1234-5678-90ab')\n * console.log(url) // 'https://github.com/advisories/GHSA-1234-5678-90ab'\n * ```\n */\nexport function getGhsaUrl(ghsaId: string): string {\n return `https://github.com/advisories/${ghsaId}`\n}\n\n/**\n * Fetch GitHub Security Advisory details from the API.\n * Retrieves complete advisory information including severity, affected packages,\n * CVSS scores, and CWE classifications.\n *\n * @param ghsaId - GHSA identifier to fetch (e.g., 'GHSA-xxxx-yyyy-zzzz')\n * @param options - Fetch options including authentication token\n * @returns Complete advisory details with normalized field names\n *\n * @throws {Error} If advisory cannot be found or API request fails\n * @throws {GitHubRateLimitError} When API rate limit is exceeded\n *\n * @example\n * ```ts\n * const advisory = await fetchGhsaDetails('GHSA-1234-5678-90ab')\n * console.log(`Severity: ${advisory.severity}`)\n * console.log(`Affects: ${advisory.vulnerabilities.length} packages`)\n * if (advisory.cvss) {\n * console.log(`CVSS Score: ${advisory.cvss.score}`)\n * }\n * ```\n *\n * @example\n * ```ts\n * // Check if vulnerability is patched\n * const advisory = await fetchGhsaDetails('GHSA-xxxx-yyyy-zzzz')\n * for (const vuln of advisory.vulnerabilities) {\n * if (vuln.firstPatchedVersion) {\n * console.log(\n * `Patched in ${vuln.package.name}@${vuln.firstPatchedVersion.identifier}`\n * )\n * }\n * }\n * ```\n */\nexport async function fetchGhsaDetails(\n ghsaId: string,\n options?: GitHubFetchOptions | undefined,\n): Promise<GhsaDetails> {\n const url = `https://api.github.com/advisories/${ghsaId}`\n const data = await fetchGitHub<{\n aliases?: string[]\n cvss: unknown\n cwes?: Array<{ cweId: string; name: string; description: string }>\n details: string\n ghsa_id: string\n published_at: string\n references?: Array<{ url: string }>\n severity: string\n summary: string\n updated_at: string\n vulnerabilities?: Array<{\n package: { ecosystem: string; name: string }\n vulnerableVersionRange: string\n firstPatchedVersion: { identifier: string } | null\n }>\n withdrawn_at: string\n }>(url, options)\n\n return {\n ghsaId: data.ghsa_id,\n summary: data.summary,\n details: data.details,\n severity: data.severity,\n aliases: data.aliases || [],\n publishedAt: data.published_at,\n updatedAt: data.updated_at,\n withdrawnAt: data.withdrawn_at,\n references: data.references || [],\n vulnerabilities: data.vulnerabilities || [],\n cvss: data.cvss as { score: number; vectorString: string } | null,\n cwes: data.cwes || [],\n }\n}\n\n/**\n * Fetch GitHub Security Advisory details with caching.\n * Retrieves advisory information with two-tier caching (in-memory + persistent).\n * Cached results are stored with the default TTL (5 minutes).\n *\n * Caching behavior:\n * - Checks in-memory cache first for immediate response\n * - Falls back to persistent disk cache if not in memory\n * - Fetches from API only if not cached\n * - Stores result in both cache tiers\n * - Respects `DISABLE_GITHUB_CACHE` env var\n *\n * @param ghsaId - GHSA identifier to fetch\n * @param options - Fetch options including authentication token\n * @returns Complete advisory details\n *\n * @throws {Error} If advisory cannot be found or API request fails\n * @throws {GitHubRateLimitError} When API rate limit is exceeded\n *\n * @example\n * ```ts\n * // First call hits API\n * const advisory = await cacheFetchGhsa('GHSA-1234-5678-90ab')\n *\n * // Second call within 5 minutes returns cached data\n * const cached = await cacheFetchGhsa('GHSA-1234-5678-90ab')\n * ```\n *\n * @example\n * ```ts\n * // Disable caching for fresh data\n * process.env.DISABLE_GITHUB_CACHE = '1'\n * const advisory = await cacheFetchGhsa('GHSA-xxxx-yyyy-zzzz')\n * ```\n */\nexport async function cacheFetchGhsa(\n ghsaId: string,\n options?: GitHubFetchOptions | undefined,\n): Promise<GhsaDetails> {\n const cache = getGithubCache()\n const key = `ghsa:${ghsaId}`\n\n // Check cache first.\n if (!process.env['DISABLE_GITHUB_CACHE']) {\n const cached = await cache.get(key)\n if (cached) {\n return JSON.parse(cached as string) as GhsaDetails\n }\n }\n\n // Fetch and cache.\n const data = await fetchGhsaDetails(ghsaId, options)\n await cache.set(key, JSON.stringify(data))\n return data\n}\n"],
5
- "mappings": "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",
6
- "names": ["github_exports", "__export", "cacheFetchGhsa", "clearRefCache", "fetchGhsaDetails", "fetchGitHub", "getGhsaUrl", "getGitHubToken", "getGitHubTokenFromGitConfig", "getGitHubTokenWithFallback", "resolveRefToSha", "__toCommonJS", "import_cache_with_ttl", "import_http_request", "import_spawn", "GITHUB_API_BASE_URL", "DEFAULT_CACHE_TTL_MS", "_githubCache", "getGithubCache", "env", "url", "options", "opts", "token", "headers", "response", "rateLimit", "resetTime", "resetTimeStr", "resetDate", "error", "owner", "repo", "ref", "cacheKey", "fetchRefSha", "fetchOptions", "tagUrl", "tagData", "branchUrl", "commitUrl", "e", "result", "ghsaId", "data", "cache", "key", "cached"]
4
+ "sourcesContent": ["/**\n * @fileoverview GitHub utilities for Socket projects.\n * Provides GitHub API integration for repository operations.\n *\n * Authentication:\n * - getGitHubToken: Retrieve GitHub token from environment variables\n * - fetchGitHub: Authenticated GitHub API requests with rate limit handling\n *\n * Ref Resolution:\n * - resolveRefToSha: Convert tags/branches to commit SHAs (with memoization and persistent cache)\n * - clearRefCache: Clear the in-memory memoization cache\n *\n * Caching:\n * - Uses cacache for persistent storage with in-memory memoization\n * - Two-tier caching: in-memory (Map) for hot data, persistent (cacache) for durability\n * - Default TTL: 5 minutes\n * - Disable with DISABLE_GITHUB_CACHE env var\n *\n * Rate Limiting:\n * - Automatic rate limit detection and error messages\n * - Cache to minimize API calls\n */\n\nimport type { TtlCache } from './cache-with-ttl'\nimport { createTtlCache } from './cache-with-ttl'\nimport { getGhToken, getGithubToken } from '#env/github'\nimport { getSocketCliGithubToken } from '#env/socket-cli'\nimport { httpRequest } from './http-request'\nimport type { SpawnOptions } from './spawn'\nimport { spawn } from './spawn'\n\n// GitHub API base URL constant (inlined for coverage mode compatibility).\nconst GITHUB_API_BASE_URL = 'https://api.github.com'\n\n// 5 minutes.\nconst DEFAULT_CACHE_TTL_MS = 5 * 60 * 1000\n\n// Create TTL cache instance for GitHub ref resolution.\n// Uses cacache for persistent storage with in-memory memoization.\nlet _githubCache: TtlCache | undefined\n\n/**\n * Get or create the GitHub cache instance.\n * Lazy initializes the cache with default TTL and memoization enabled.\n * Used internally for caching GitHub API responses.\n *\n * @returns The singleton cache instance\n */\nfunction getGithubCache(): TtlCache {\n if (_githubCache === undefined) {\n _githubCache = createTtlCache({\n memoize: true,\n prefix: 'github-refs',\n ttl: DEFAULT_CACHE_TTL_MS,\n })\n }\n return _githubCache\n}\n\n/**\n * Options for GitHub API fetch requests.\n */\nexport interface GitHubFetchOptions {\n /**\n * GitHub authentication token.\n * If not provided, will attempt to use token from environment variables.\n */\n token?: string | undefined\n /**\n * Additional HTTP headers to include in the request.\n * Will be merged with default headers (Accept, User-Agent, Authorization).\n */\n headers?: Record<string, string> | undefined\n}\n\n/**\n * Error thrown when GitHub API rate limit is exceeded.\n * Extends the standard Error with additional rate limit information.\n */\nexport interface GitHubRateLimitError extends Error {\n /** HTTP status code (always 403 for rate limit errors) */\n status: number\n /**\n * Date when the rate limit will reset.\n * Undefined if reset time is not available in response headers.\n */\n resetTime?: Date | undefined\n}\n\n/**\n * Get GitHub authentication token from environment variables.\n * Checks multiple environment variable names in priority order.\n *\n * Environment variables checked (in order):\n * 1. `GITHUB_TOKEN` - Standard GitHub token variable\n * 2. `GH_TOKEN` - Alternative GitHub CLI token variable\n * 3. `SOCKET_CLI_GITHUB_TOKEN` - Socket-specific token variable\n *\n * @returns The first available GitHub token, or `undefined` if none found\n *\n * @example\n * ```ts\n * const token = getGitHubToken()\n * if (!token) {\n * console.warn('No GitHub token found')\n * }\n * ```\n */\nexport function getGitHubToken(): string | undefined {\n return (\n getGithubToken() || getGhToken() || getSocketCliGithubToken() || undefined\n )\n}\n\n/**\n * Fetch data from GitHub API with automatic authentication and rate limit handling.\n * Makes authenticated requests to the GitHub REST API with proper error handling.\n *\n * Features:\n * - Automatic token injection from environment if not provided\n * - Rate limit detection with helpful error messages\n * - Standard GitHub API headers (Accept, User-Agent)\n * - JSON response parsing\n *\n * @template T - Expected response type (defaults to `unknown`)\n * @param url - Full GitHub API URL (e.g., 'https://api.github.com/repos/owner/repo')\n * @param options - Fetch options including token and custom headers\n * @returns Parsed JSON response of type `T`\n *\n * @throws {GitHubRateLimitError} When API rate limit is exceeded (status 403)\n * @throws {Error} For other API errors with status code and message\n *\n * @example\n * ```ts\n * // Fetch repository information\n * interface Repo {\n * name: string\n * full_name: string\n * default_branch: string\n * }\n * const repo = await fetchGitHub<Repo>(\n * 'https://api.github.com/repos/owner/repo'\n * )\n * console.log(`Default branch: ${repo.default_branch}`)\n * ```\n *\n * @example\n * ```ts\n * // With custom token and headers\n * const data = await fetchGitHub(\n * 'https://api.github.com/user',\n * {\n * token: 'ghp_customtoken',\n * headers: { 'X-Custom-Header': 'value' }\n * }\n * )\n * ```\n *\n * @example\n * ```ts\n * // Handle rate limit errors\n * try {\n * await fetchGitHub('https://api.github.com/repos/owner/repo')\n * } catch (error) {\n * if (error.status === 403 && error.resetTime) {\n * console.error(`Rate limited until ${error.resetTime}`)\n * }\n * }\n * ```\n */\nexport async function fetchGitHub<T = unknown>(\n url: string,\n options?: GitHubFetchOptions | undefined,\n): Promise<T> {\n const opts = { __proto__: null, ...options } as GitHubFetchOptions\n const token = opts.token || getGitHubToken()\n\n const headers: Record<string, string> = {\n Accept: 'application/vnd.github.v3+json',\n 'User-Agent': 'socket-registry-github-client',\n ...opts.headers,\n }\n\n if (token) {\n headers['Authorization'] = `Bearer ${token}`\n }\n\n const response = await httpRequest(url, { headers })\n\n if (!response.ok) {\n if (response.status === 403) {\n const rateLimit = response.headers['x-ratelimit-remaining']\n const rateLimitStr =\n typeof rateLimit === 'string' ? rateLimit : rateLimit?.[0]\n if (rateLimitStr === '0') {\n const resetTime = response.headers['x-ratelimit-reset']\n const resetTimeStr =\n typeof resetTime === 'string' ? resetTime : resetTime?.[0]\n const resetDate = resetTimeStr\n ? new Date(Number(resetTimeStr) * 1000)\n : undefined\n const error = new Error(\n `GitHub API rate limit exceeded${resetDate ? `. Resets at ${resetDate.toLocaleString()}` : ''}. Use GITHUB_TOKEN environment variable to increase rate limit.`,\n ) as GitHubRateLimitError\n error.status = 403\n error.resetTime = resetDate\n throw error\n }\n }\n throw new Error(\n `GitHub API error ${response.status}: ${response.statusText}`,\n )\n }\n\n return JSON.parse(response.body.toString('utf8')) as T\n}\n\n/**\n * GitHub ref object returned by the API.\n * Represents a git reference (tag or branch).\n */\nexport interface GitHubRef {\n /** The object this ref points to */\n object: {\n /** SHA of the commit or tag object */\n sha: string\n /** Type of object ('commit' or 'tag') */\n type: string\n /** API URL to fetch the full object details */\n url: string\n }\n /** Full ref path (e.g., 'refs/tags/v1.0.0' or 'refs/heads/main') */\n ref: string\n /** API URL for this ref */\n url: string\n}\n\n/**\n * GitHub annotated tag object returned by the API.\n * Represents a git tag with metadata.\n */\nexport interface GitHubTag {\n /** Tag annotation message */\n message: string\n /** The commit this tag points to */\n object: {\n /** SHA of the commit */\n sha: string\n /** Type of object (usually 'commit') */\n type: string\n /** API URL to fetch the commit details */\n url: string\n }\n /** SHA of this tag object itself */\n sha: string\n /** Tag name (e.g., 'v1.0.0') */\n tag: string\n /**\n * Information about who created the tag.\n * Undefined for lightweight tags.\n */\n tagger?: {\n /** Tag creation date in ISO 8601 format */\n date: string\n /** Tagger's email address */\n email: string\n /** Tagger's name */\n name: string\n }\n /** API URL for this tag object */\n url: string\n}\n\n/**\n * GitHub commit object returned by the API.\n * Represents a git commit with metadata.\n */\nexport interface GitHubCommit {\n /** Full commit SHA */\n sha: string\n /** API URL for this commit */\n url: string\n /** Commit details */\n commit: {\n /** Commit message */\n message: string\n /** Author information */\n author: {\n /** Commit author date in ISO 8601 format */\n date: string\n /** Author's email address */\n email: string\n /** Author's name */\n name: string\n }\n }\n}\n\n/**\n * Options for resolving git refs to commit SHAs.\n */\nexport interface ResolveRefOptions {\n /**\n * GitHub authentication token.\n * If not provided, will attempt to use token from environment variables.\n */\n token?: string | undefined\n}\n\n/**\n * Resolve a git ref (tag, branch, or commit SHA) to its full commit SHA.\n * Handles tags (annotated and lightweight), branches, and commit SHAs.\n * Results are cached in-memory and on disk (with TTL) to minimize API calls.\n *\n * Resolution strategy:\n * 1. Try as a tag (refs/tags/{ref})\n * 2. If tag is annotated, dereference to get the commit SHA\n * 3. If not a tag, try as a branch (refs/heads/{ref})\n * 4. If not a branch, try as a commit SHA directly\n *\n * Caching behavior:\n * - In-memory cache (Map) for immediate lookups\n * - Persistent disk cache (cacache) for durability across runs\n * - Default TTL: 5 minutes\n * - Disable caching with `DISABLE_GITHUB_CACHE` env var\n *\n * @param owner - Repository owner (user or organization name)\n * @param repo - Repository name\n * @param ref - Git reference to resolve (tag name, branch name, or commit SHA)\n * @param options - Resolution options including authentication token\n * @returns The full commit SHA (40-character hex string)\n *\n * @throws {Error} When ref cannot be resolved after trying all strategies\n * @throws {GitHubRateLimitError} When API rate limit is exceeded\n *\n * @example\n * ```ts\n * // Resolve a tag to commit SHA\n * const sha = await resolveRefToSha('owner', 'repo', 'v1.0.0')\n * console.log(sha) // 'a1b2c3d4e5f6...'\n * ```\n *\n * @example\n * ```ts\n * // Resolve a branch to latest commit SHA\n * const sha = await resolveRefToSha('owner', 'repo', 'main')\n * console.log(sha) // Latest commit on main branch\n * ```\n *\n * @example\n * ```ts\n * // Resolve with custom token\n * const sha = await resolveRefToSha(\n * 'owner',\n * 'repo',\n * 'develop',\n * { token: 'ghp_customtoken' }\n * )\n * ```\n *\n * @example\n * ```ts\n * // Commit SHA passes through unchanged (but validates it exists)\n * const sha = await resolveRefToSha('owner', 'repo', 'a1b2c3d4')\n * console.log(sha) // Full 40-char SHA\n * ```\n */\nexport async function resolveRefToSha(\n owner: string,\n repo: string,\n ref: string,\n options?: ResolveRefOptions | undefined,\n): Promise<string> {\n const opts = {\n __proto__: null,\n ...options,\n } as ResolveRefOptions\n\n const cacheKey = `${owner}/${repo}@${ref}`\n\n // Optionally disable cache.\n if (process.env['DISABLE_GITHUB_CACHE']) {\n return await fetchRefSha(owner, repo, ref, opts)\n }\n\n // Use TTL cache for persistent storage and in-memory memoization.\n const cache = getGithubCache()\n return await cache.getOrFetch(cacheKey, async () => {\n return await fetchRefSha(owner, repo, ref, opts)\n })\n}\n\n/**\n * Fetch the SHA for a git ref from GitHub API.\n * Internal helper that implements the multi-strategy ref resolution logic.\n * Tries tags, branches, and direct commit lookups in sequence.\n *\n * @param owner - Repository owner\n * @param repo - Repository name\n * @param ref - Git reference to resolve\n * @param options - Resolution options with authentication token\n * @returns The full commit SHA\n *\n * @throws {Error} When ref cannot be resolved after all strategies fail\n */\nasync function fetchRefSha(\n owner: string,\n repo: string,\n ref: string,\n options: ResolveRefOptions,\n): Promise<string> {\n const fetchOptions: GitHubFetchOptions = {\n token: options.token,\n }\n\n try {\n // Try as a tag first.\n const tagUrl = `${GITHUB_API_BASE_URL}/repos/${owner}/${repo}/git/refs/tags/${ref}`\n const tagData = await fetchGitHub<GitHubRef>(tagUrl, fetchOptions)\n\n // Tag might point to a tag object or directly to a commit.\n if (tagData.object.type === 'tag') {\n // Dereference the tag object to get the commit.\n const tagObject = await fetchGitHub<GitHubTag>(\n tagData.object.url,\n fetchOptions,\n )\n return tagObject.object.sha\n }\n return tagData.object.sha\n } catch {\n // Not a tag, try as a branch.\n try {\n const branchUrl = `${GITHUB_API_BASE_URL}/repos/${owner}/${repo}/git/refs/heads/${ref}`\n const branchData = await fetchGitHub<GitHubRef>(branchUrl, fetchOptions)\n return branchData.object.sha\n } catch {\n // Try without refs/ prefix (for commit SHAs or other refs).\n try {\n const commitUrl = `${GITHUB_API_BASE_URL}/repos/${owner}/${repo}/commits/${ref}`\n const commitData = await fetchGitHub<GitHubCommit>(\n commitUrl,\n fetchOptions,\n )\n return commitData.sha\n } catch (e) {\n throw new Error(\n `failed to resolve ref \"${ref}\" for ${owner}/${repo}: ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n }\n }\n}\n\n/**\n * Clear the ref resolution cache (in-memory only).\n * Clears the in-memory memoization cache without affecting the persistent disk cache.\n * Useful for testing or when you need fresh data from the API.\n *\n * Note: This only clears the in-memory cache. The persistent cacache storage\n * remains intact and will be used to rebuild the in-memory cache on next access.\n *\n * @returns Promise that resolves when cache is cleared\n *\n * @example\n * ```ts\n * // Clear cache to force fresh API calls\n * await clearRefCache()\n * const sha = await resolveRefToSha('owner', 'repo', 'main')\n * // This will hit the persistent cache or API, not in-memory cache\n * ```\n */\nexport async function clearRefCache(): Promise<void> {\n if (_githubCache) {\n await _githubCache.clear({ memoOnly: true })\n }\n}\n\n/**\n * Get GitHub authentication token from git config.\n * Reads the `github.token` configuration value from git config.\n * This is a fallback method when environment variables don't contain a token.\n *\n * @param options - Spawn options for git command execution\n * @returns GitHub token from git config, or `undefined` if not configured\n *\n * @example\n * ```ts\n * const token = await getGitHubTokenFromGitConfig()\n * if (token) {\n * console.log('Found token in git config')\n * }\n * ```\n *\n * @example\n * ```ts\n * // With custom working directory\n * const token = await getGitHubTokenFromGitConfig({\n * cwd: '/path/to/repo'\n * })\n * ```\n */\nexport async function getGitHubTokenFromGitConfig(\n options?: SpawnOptions | undefined,\n): Promise<string | undefined> {\n try {\n const result = await spawn('git', ['config', 'github.token'], {\n ...options,\n stdio: 'pipe',\n })\n if (result.code === 0 && result.stdout) {\n return result.stdout.toString().trim()\n }\n } catch {\n // Ignore errors - git config may not have token.\n }\n return undefined\n}\n\n/**\n * Get GitHub authentication token from all available sources.\n * Checks environment variables first, then falls back to git config.\n * This is the recommended way to get a GitHub token with maximum compatibility.\n *\n * Priority order:\n * 1. Environment variables (GITHUB_TOKEN, GH_TOKEN, SOCKET_CLI_GITHUB_TOKEN)\n * 2. Git config (github.token)\n *\n * @returns GitHub token from first available source, or `undefined` if none found\n *\n * @example\n * ```ts\n * const token = await getGitHubTokenWithFallback()\n * if (!token) {\n * throw new Error('GitHub token required')\n * }\n * ```\n */\nexport async function getGitHubTokenWithFallback(): Promise<\n string | undefined\n> {\n return getGitHubToken() || (await getGitHubTokenFromGitConfig())\n}\n\n/**\n * GitHub Security Advisory (GHSA) details.\n * Represents a complete security advisory from GitHub's database.\n */\nexport interface GhsaDetails {\n /** GHSA identifier (e.g., 'GHSA-xxxx-yyyy-zzzz') */\n ghsaId: string\n /** Short summary of the vulnerability */\n summary: string\n /** Detailed description of the vulnerability */\n details: string\n /** Severity level ('low', 'moderate', 'high', 'critical') */\n severity: string\n /** Alternative identifiers (CVE IDs, etc.) */\n aliases: string[]\n /** ISO 8601 timestamp when advisory was published */\n publishedAt: string\n /** ISO 8601 timestamp when advisory was last updated */\n updatedAt: string\n /**\n * ISO 8601 timestamp when advisory was withdrawn.\n * `null` if advisory is still active.\n */\n withdrawnAt: string | null\n /** External reference URLs for more information */\n references: Array<{ url: string }>\n /** Affected packages and version ranges */\n vulnerabilities: Array<{\n /** Package information */\n package: {\n /** Ecosystem (e.g., 'npm', 'pip', 'maven') */\n ecosystem: string\n /** Package name */\n name: string\n }\n /** Version range expression for vulnerable versions */\n vulnerableVersionRange: string\n /**\n * First patched version that fixes the vulnerability.\n * `null` if no patched version exists yet.\n */\n firstPatchedVersion: { identifier: string } | null\n }>\n /**\n * CVSS (Common Vulnerability Scoring System) information.\n * `null` if CVSS score is not available.\n */\n cvss: {\n /** CVSS score (0.0-10.0) */\n score: number\n /** CVSS vector string describing the vulnerability characteristics */\n vectorString: string\n } | null\n /** CWE (Common Weakness Enumeration) categories */\n cwes: Array<{\n /** CWE identifier (e.g., 'CWE-79') */\n cweId: string\n /** Human-readable CWE name */\n name: string\n /** Description of the weakness category */\n description: string\n }>\n}\n\n/**\n * Generate GitHub Security Advisory URL from GHSA ID.\n * Constructs the public advisory URL for a given GHSA identifier.\n *\n * @param ghsaId - GHSA identifier (e.g., 'GHSA-xxxx-yyyy-zzzz')\n * @returns Full URL to the advisory page\n *\n * @example\n * ```ts\n * const url = getGhsaUrl('GHSA-1234-5678-90ab')\n * console.log(url) // 'https://github.com/advisories/GHSA-1234-5678-90ab'\n * ```\n */\nexport function getGhsaUrl(ghsaId: string): string {\n return `https://github.com/advisories/${ghsaId}`\n}\n\n/**\n * Fetch GitHub Security Advisory details from the API.\n * Retrieves complete advisory information including severity, affected packages,\n * CVSS scores, and CWE classifications.\n *\n * @param ghsaId - GHSA identifier to fetch (e.g., 'GHSA-xxxx-yyyy-zzzz')\n * @param options - Fetch options including authentication token\n * @returns Complete advisory details with normalized field names\n *\n * @throws {Error} If advisory cannot be found or API request fails\n * @throws {GitHubRateLimitError} When API rate limit is exceeded\n *\n * @example\n * ```ts\n * const advisory = await fetchGhsaDetails('GHSA-1234-5678-90ab')\n * console.log(`Severity: ${advisory.severity}`)\n * console.log(`Affects: ${advisory.vulnerabilities.length} packages`)\n * if (advisory.cvss) {\n * console.log(`CVSS Score: ${advisory.cvss.score}`)\n * }\n * ```\n *\n * @example\n * ```ts\n * // Check if vulnerability is patched\n * const advisory = await fetchGhsaDetails('GHSA-xxxx-yyyy-zzzz')\n * for (const vuln of advisory.vulnerabilities) {\n * if (vuln.firstPatchedVersion) {\n * console.log(\n * `Patched in ${vuln.package.name}@${vuln.firstPatchedVersion.identifier}`\n * )\n * }\n * }\n * ```\n */\nexport async function fetchGhsaDetails(\n ghsaId: string,\n options?: GitHubFetchOptions | undefined,\n): Promise<GhsaDetails> {\n const url = `https://api.github.com/advisories/${ghsaId}`\n const data = await fetchGitHub<{\n aliases?: string[]\n cvss: unknown\n cwes?: Array<{ cweId: string; name: string; description: string }>\n details: string\n ghsa_id: string\n published_at: string\n references?: Array<{ url: string }>\n severity: string\n summary: string\n updated_at: string\n vulnerabilities?: Array<{\n package: { ecosystem: string; name: string }\n vulnerableVersionRange: string\n firstPatchedVersion: { identifier: string } | null\n }>\n withdrawn_at: string\n }>(url, options)\n\n return {\n ghsaId: data.ghsa_id,\n summary: data.summary,\n details: data.details,\n severity: data.severity,\n aliases: data.aliases || [],\n publishedAt: data.published_at,\n updatedAt: data.updated_at,\n withdrawnAt: data.withdrawn_at,\n references: data.references || [],\n vulnerabilities: data.vulnerabilities || [],\n cvss: data.cvss as { score: number; vectorString: string } | null,\n cwes: data.cwes || [],\n }\n}\n\n/**\n * Fetch GitHub Security Advisory details with caching.\n * Retrieves advisory information with two-tier caching (in-memory + persistent).\n * Cached results are stored with the default TTL (5 minutes).\n *\n * Caching behavior:\n * - Checks in-memory cache first for immediate response\n * - Falls back to persistent disk cache if not in memory\n * - Fetches from API only if not cached\n * - Stores result in both cache tiers\n * - Respects `DISABLE_GITHUB_CACHE` env var\n *\n * @param ghsaId - GHSA identifier to fetch\n * @param options - Fetch options including authentication token\n * @returns Complete advisory details\n *\n * @throws {Error} If advisory cannot be found or API request fails\n * @throws {GitHubRateLimitError} When API rate limit is exceeded\n *\n * @example\n * ```ts\n * // First call hits API\n * const advisory = await cacheFetchGhsa('GHSA-1234-5678-90ab')\n *\n * // Second call within 5 minutes returns cached data\n * const cached = await cacheFetchGhsa('GHSA-1234-5678-90ab')\n * ```\n *\n * @example\n * ```ts\n * // Disable caching for fresh data\n * process.env.DISABLE_GITHUB_CACHE = '1'\n * const advisory = await cacheFetchGhsa('GHSA-xxxx-yyyy-zzzz')\n * ```\n */\nexport async function cacheFetchGhsa(\n ghsaId: string,\n options?: GitHubFetchOptions | undefined,\n): Promise<GhsaDetails> {\n const cache = getGithubCache()\n const key = `ghsa:${ghsaId}`\n\n // Check cache first.\n if (!process.env['DISABLE_GITHUB_CACHE']) {\n const cached = await cache.get(key)\n if (cached) {\n return JSON.parse(cached as string) as GhsaDetails\n }\n }\n\n // Fetch and cache.\n const data = await fetchGhsaDetails(ghsaId, options)\n await cache.set(key, JSON.stringify(data))\n return data\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["github_exports", "__export", "cacheFetchGhsa", "clearRefCache", "fetchGhsaDetails", "fetchGitHub", "getGhsaUrl", "getGitHubToken", "getGitHubTokenFromGitConfig", "getGitHubTokenWithFallback", "resolveRefToSha", "__toCommonJS", "import_cache_with_ttl", "import_github", "import_socket_cli", "import_http_request", "import_spawn", "GITHUB_API_BASE_URL", "DEFAULT_CACHE_TTL_MS", "_githubCache", "getGithubCache", "url", "options", "opts", "token", "headers", "response", "rateLimit", "resetTime", "resetTimeStr", "resetDate", "error", "owner", "repo", "ref", "cacheKey", "fetchRefSha", "fetchOptions", "tagUrl", "tagData", "branchUrl", "commitUrl", "e", "result", "ghsaId", "data", "cache", "key", "cached"]
7
7
  }
package/dist/globs.js CHANGED
@@ -1,3 +1,3 @@
1
1
  /* Socket Lib - Built with esbuild */
2
- var l=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var _=Object.prototype.hasOwnProperty;var O=(e,o)=>{for(var n in o)l(e,n,{get:o[n],enumerable:!0})},y=(e,o,n,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let t of h(o))!_.call(e,t)&&t!==n&&l(e,t,{get:()=>o[t],enumerable:!(r=d(o,t))||r.enumerable});return e};var S=e=>y(l({},"__esModule",{value:!0}),e);var L={};O(L,{defaultIgnore:()=>f,getGlobMatcher:()=>w,globStreamLicenses:()=>v});module.exports=S(L);var u=require("./objects");const f=(0,u.objectFreeze)(["**/.git","**/.npmrc","**/node_modules","**/.DS_Store","**/.gitignore","**/.hg","**/.lock-wscript","**/.npmignore","**/.svn","**/.wafpickle-*","**/.*.swp","**/._*/**","**/archived-packages/**","**/build/config.gypi","**/CVS","**/npm-debug.log","**/*.orig","**/.env","**/.eslintcache","**/.nvm","**/.tap","**/.vscode","**/*.tsbuildinfo","**/Thumbs.db","**/bower_components"]);let c;function G(){return c===void 0&&(c=require("./external/picomatch")),c}let b;function E(){if(b===void 0){const e=require("./external/fast-glob");b=e.default||e}return b}function v(e,o){const{ignore:n,ignoreOriginals:r,recursive:t,...a}={__proto__:null,...o},s=[...Array.isArray(n)?n:f,"**/*.{cjs,cts,js,json,mjs,mts,ts}"];return r&&s.push(require("./constants/paths").LICENSE_ORIGINAL_GLOB_RECURSIVE),E().globStream([t?require("./constants/paths").LICENSE_GLOB_RECURSIVE:require("./constants/paths").LICENSE_GLOB],{__proto__:null,absolute:!0,caseSensitiveMatch:!1,cwd:e,...a,...s?{ignore:s}:{}})}const g=new Map;function w(e,o){const n=Array.isArray(e)?e:[e],r=JSON.stringify({patterns:n,options:o});let t=g.get(r);if(t)return t;const a=n.filter(i=>!i.startsWith("!")),s=n.filter(i=>i.startsWith("!")).map(i=>i.slice(1)),p=G(),m={dot:!0,nocase:!0,...o,...s.length>0?{ignore:s}:{}};return t=p(a.length>0?a:n,m),g.set(r,t),t}0&&(module.exports={defaultIgnore,getGlobMatcher,globStreamLicenses});
2
+ var l=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var _=Object.prototype.hasOwnProperty;var O=(e,o)=>{for(var n in o)l(e,n,{get:o[n],enumerable:!0})},y=(e,o,n,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let t of h(o))!_.call(e,t)&&t!==n&&l(e,t,{get:()=>o[t],enumerable:!(r=d(o,t))||r.enumerable});return e};var S=e=>y(l({},"__esModule",{value:!0}),e);var L={};O(L,{defaultIgnore:()=>f,getGlobMatcher:()=>w,globStreamLicenses:()=>v});module.exports=S(L);var u=require("./objects");const f=(0,u.objectFreeze)(["**/.git","**/.npmrc","**/node_modules","**/.DS_Store","**/.gitignore","**/.hg","**/.lock-wscript","**/.npmignore","**/.svn","**/.wafpickle-*","**/.*.swp","**/._*/**","**/archived-packages/**","**/build/config.gypi","**/CVS","**/npm-debug.log","**/*.orig","**/.env","**/.eslintcache","**/.nvm","**/.tap","**/.vscode","**/*.tsbuildinfo","**/Thumbs.db","**/bower_components"]);let c;function G(){return c===void 0&&(c=require("./external/picomatch")),c}let b;function E(){if(b===void 0){const e=require("./external/fast-glob");b=e.default||e}return b}function v(e,o){const{ignore:n,ignoreOriginals:r,recursive:t,...a}={__proto__:null,...o},s=[...Array.isArray(n)?n:f,"**/*.{cjs,cts,js,json,mjs,mts,ts}"];return r&&s.push(require("#constants/paths").LICENSE_ORIGINAL_GLOB_RECURSIVE),E().globStream([t?require("#constants/paths").LICENSE_GLOB_RECURSIVE:require("#constants/paths").LICENSE_GLOB],{__proto__:null,absolute:!0,caseSensitiveMatch:!1,cwd:e,...a,...s?{ignore:s}:{}})}const g=new Map;function w(e,o){const n=Array.isArray(e)?e:[e],r=JSON.stringify({patterns:n,options:o});let t=g.get(r);if(t)return t;const a=n.filter(i=>!i.startsWith("!")),s=n.filter(i=>i.startsWith("!")).map(i=>i.slice(1)),p=G(),m={dot:!0,nocase:!0,...o,...s.length>0?{ignore:s}:{}};return t=p(a.length>0?a:n,m),g.set(r,t),t}0&&(module.exports={defaultIgnore,getGlobMatcher,globStreamLicenses});
3
3
  //# sourceMappingURL=globs.js.map
package/dist/globs.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/globs.ts"],
4
- "sourcesContent": ["/**\n * @fileoverview Glob pattern matching utilities with default ignore patterns.\n * Provides file filtering and glob matcher functions for npm-like behavior.\n */\n\n// IMPORTANT: Do not use destructuring here - use direct assignment instead.\nimport { objectFreeze as ObjectFreeze } from './objects'\n\n// Type definitions\ntype Pattern = string\n\ninterface FastGlobOptions {\n absolute?: boolean\n baseNameMatch?: boolean\n braceExpansion?: boolean\n caseSensitiveMatch?: boolean\n concurrency?: number\n cwd?: string\n deep?: number\n dot?: boolean\n extglob?: boolean\n followSymbolicLinks?: boolean\n fs?: unknown\n globstar?: boolean\n ignore?: string[]\n ignoreFiles?: string[]\n markDirectories?: boolean\n objectMode?: boolean\n onlyDirectories?: boolean\n onlyFiles?: boolean\n stats?: boolean\n suppressErrors?: boolean\n throwErrorOnBrokenSymbolicLink?: boolean\n unique?: boolean\n}\n\nexport interface GlobOptions extends FastGlobOptions {\n ignoreOriginals?: boolean\n recursive?: boolean\n}\n\nexport type { Pattern, FastGlobOptions }\n\nexport const defaultIgnore = ObjectFreeze([\n // Most of these ignored files can be included specifically if included in the\n // files globs. Exceptions to this are:\n // https://docs.npmjs.com/cli/v10/configuring-npm/package-json#files\n // These can NOT be included.\n // https://github.com/npm/npm-packlist/blob/v10.0.0/lib/index.js#L280\n '**/.git',\n '**/.npmrc',\n // '**/bun.lockb?',\n '**/node_modules',\n // '**/package-lock.json',\n // '**/pnpm-lock.ya?ml',\n // '**/yarn.lock',\n // Include npm-packlist defaults:\n // https://github.com/npm/npm-packlist/blob/v10.0.0/lib/index.js#L15-L38\n '**/.DS_Store',\n '**/.gitignore',\n '**/.hg',\n '**/.lock-wscript',\n '**/.npmignore',\n '**/.svn',\n '**/.wafpickle-*',\n '**/.*.swp',\n '**/._*/**',\n '**/archived-packages/**',\n '**/build/config.gypi',\n '**/CVS',\n '**/npm-debug.log',\n '**/*.orig',\n // Inline generic socket-registry .gitignore entries.\n '**/.env',\n '**/.eslintcache',\n '**/.nvm',\n '**/.tap',\n '**/.vscode',\n '**/*.tsbuildinfo',\n '**/Thumbs.db',\n // Inline additional ignores.\n '**/bower_components',\n])\n\nlet _picomatch: typeof import('picomatch') | undefined\n/**\n * Lazily load the picomatch module.\n * @private\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getPicomatch() {\n if (_picomatch === undefined) {\n // The 'picomatch' package is browser safe.\n _picomatch = /*@__PURE__*/ require('./external/picomatch')\n }\n return _picomatch as typeof import('picomatch')\n}\n\nlet _fastGlob: typeof import('fast-glob') | undefined\n/**\n * Lazily load the fast-glob module.\n * @private\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getFastGlob() {\n if (_fastGlob === undefined) {\n const globExport = /*@__PURE__*/ require('./external/fast-glob')\n _fastGlob = globExport.default || globExport\n }\n return _fastGlob as typeof import('fast-glob')\n}\n\n/**\n * Create a stream of license file paths matching glob patterns.\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function globStreamLicenses(\n dirname: string,\n options?: GlobOptions,\n): NodeJS.ReadableStream {\n const {\n ignore: ignoreOpt,\n ignoreOriginals,\n recursive,\n ...globOptions\n } = { __proto__: null, ...options } as GlobOptions\n const ignore = [\n ...(Array.isArray(ignoreOpt) ? ignoreOpt : defaultIgnore),\n '**/*.{cjs,cts,js,json,mjs,mts,ts}',\n ]\n if (ignoreOriginals) {\n ignore.push(\n /*@__INLINE__*/ require('../constants/paths')\n .LICENSE_ORIGINAL_GLOB_RECURSIVE,\n )\n }\n const fastGlob = getFastGlob()\n return fastGlob.globStream(\n [\n recursive\n ? /*@__INLINE__*/ require('../constants/paths').LICENSE_GLOB_RECURSIVE\n : /*@__INLINE__*/ require('../constants/paths').LICENSE_GLOB,\n ],\n {\n __proto__: null,\n absolute: true,\n caseSensitiveMatch: false,\n cwd: dirname,\n ...globOptions,\n ...(ignore ? { ignore } : {}),\n } as import('fast-glob').Options,\n )\n}\n\nconst matcherCache = new Map()\n/**\n * Get a cached glob matcher function.\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function getGlobMatcher(\n glob: Pattern | Pattern[],\n options?: { dot?: boolean; nocase?: boolean; ignore?: string[] },\n): (path: string) => boolean {\n const patterns = Array.isArray(glob) ? glob : [glob]\n const key = JSON.stringify({ patterns, options })\n let matcher = matcherCache.get(key)\n if (matcher) {\n return matcher\n }\n\n // Separate positive and negative patterns.\n const positivePatterns = patterns.filter(p => !p.startsWith('!'))\n const negativePatterns = patterns\n .filter(p => p.startsWith('!'))\n .map(p => p.slice(1))\n\n const picomatch = getPicomatch()\n\n // Use ignore option for negation patterns.\n const matchOptions = {\n dot: true,\n nocase: true,\n ...options,\n ...(negativePatterns.length > 0 ? { ignore: negativePatterns } : {}),\n }\n\n matcher = picomatch(\n positivePatterns.length > 0 ? positivePatterns : patterns,\n matchOptions,\n )\n\n matcherCache.set(key, matcher)\n return matcher\n}\n"],
5
- "mappings": ";4ZAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,mBAAAE,EAAA,mBAAAC,EAAA,uBAAAC,IAAA,eAAAC,EAAAL,GAMA,IAAAM,EAA6C,qBAqCtC,MAAMJ,KAAgB,EAAAK,cAAa,CAMxC,UACA,YAEA,kBAMA,eACA,gBACA,SACA,mBACA,gBACA,UACA,kBACA,YACA,YACA,0BACA,uBACA,SACA,mBACA,YAEA,UACA,kBACA,UACA,UACA,aACA,mBACA,eAEA,qBACF,CAAC,EAED,IAAIC,EAMJ,SAASC,GAAe,CACtB,OAAID,IAAe,SAEjBA,EAA2B,QAAQ,sBAAsB,GAEpDA,CACT,CAEA,IAAIE,EAMJ,SAASC,GAAc,CACrB,GAAID,IAAc,OAAW,CAC3B,MAAME,EAA2B,QAAQ,sBAAsB,EAC/DF,EAAYE,EAAW,SAAWA,CACpC,CACA,OAAOF,CACT,CAMO,SAASN,EACdS,EACAC,EACuB,CACvB,KAAM,CACJ,OAAQC,EACR,gBAAAC,EACA,UAAAC,EACA,GAAGC,CACL,EAAI,CAAE,UAAW,KAAM,GAAGJ,CAAQ,EAC5BK,EAAS,CACb,GAAI,MAAM,QAAQJ,CAAS,EAAIA,EAAYb,EAC3C,mCACF,EACA,OAAIc,GACFG,EAAO,KACW,QAAQ,oBAAoB,EACzC,+BACL,EAEeR,EAAY,EACb,WACd,CACEM,EACoB,QAAQ,oBAAoB,EAAE,uBAC9B,QAAQ,oBAAoB,EAAE,YACpD,EACA,CACE,UAAW,KACX,SAAU,GACV,mBAAoB,GACpB,IAAKJ,EACL,GAAGK,EACH,GAAIC,EAAS,CAAE,OAAAA,CAAO,EAAI,CAAC,CAC7B,CACF,CACF,CAEA,MAAMC,EAAe,IAAI,IAKlB,SAASjB,EACdkB,EACAP,EAC2B,CAC3B,MAAMQ,EAAW,MAAM,QAAQD,CAAI,EAAIA,EAAO,CAACA,CAAI,EAC7CE,EAAM,KAAK,UAAU,CAAE,SAAAD,EAAU,QAAAR,CAAQ,CAAC,EAChD,IAAIU,EAAUJ,EAAa,IAAIG,CAAG,EAClC,GAAIC,EACF,OAAOA,EAIT,MAAMC,EAAmBH,EAAS,OAAOI,GAAK,CAACA,EAAE,WAAW,GAAG,CAAC,EAC1DC,EAAmBL,EACtB,OAAOI,GAAKA,EAAE,WAAW,GAAG,CAAC,EAC7B,IAAIA,GAAKA,EAAE,MAAM,CAAC,CAAC,EAEhBE,EAAYnB,EAAa,EAGzBoB,EAAe,CACnB,IAAK,GACL,OAAQ,GACR,GAAGf,EACH,GAAIa,EAAiB,OAAS,EAAI,CAAE,OAAQA,CAAiB,EAAI,CAAC,CACpE,EAEA,OAAAH,EAAUI,EACRH,EAAiB,OAAS,EAAIA,EAAmBH,EACjDO,CACF,EAEAT,EAAa,IAAIG,EAAKC,CAAO,EACtBA,CACT",
4
+ "sourcesContent": ["/**\n * @fileoverview Glob pattern matching utilities with default ignore patterns.\n * Provides file filtering and glob matcher functions for npm-like behavior.\n */\n\n// IMPORTANT: Do not use destructuring here - use direct assignment instead.\nimport { objectFreeze as ObjectFreeze } from './objects'\n\n// Type definitions\ntype Pattern = string\n\ninterface FastGlobOptions {\n absolute?: boolean\n baseNameMatch?: boolean\n braceExpansion?: boolean\n caseSensitiveMatch?: boolean\n concurrency?: number\n cwd?: string\n deep?: number\n dot?: boolean\n extglob?: boolean\n followSymbolicLinks?: boolean\n fs?: unknown\n globstar?: boolean\n ignore?: string[]\n ignoreFiles?: string[]\n markDirectories?: boolean\n objectMode?: boolean\n onlyDirectories?: boolean\n onlyFiles?: boolean\n stats?: boolean\n suppressErrors?: boolean\n throwErrorOnBrokenSymbolicLink?: boolean\n unique?: boolean\n}\n\nexport interface GlobOptions extends FastGlobOptions {\n ignoreOriginals?: boolean\n recursive?: boolean\n}\n\nexport type { Pattern, FastGlobOptions }\n\nexport const defaultIgnore = ObjectFreeze([\n // Most of these ignored files can be included specifically if included in the\n // files globs. Exceptions to this are:\n // https://docs.npmjs.com/cli/v10/configuring-npm/package-json#files\n // These can NOT be included.\n // https://github.com/npm/npm-packlist/blob/v10.0.0/lib/index.js#L280\n '**/.git',\n '**/.npmrc',\n // '**/bun.lockb?',\n '**/node_modules',\n // '**/package-lock.json',\n // '**/pnpm-lock.ya?ml',\n // '**/yarn.lock',\n // Include npm-packlist defaults:\n // https://github.com/npm/npm-packlist/blob/v10.0.0/lib/index.js#L15-L38\n '**/.DS_Store',\n '**/.gitignore',\n '**/.hg',\n '**/.lock-wscript',\n '**/.npmignore',\n '**/.svn',\n '**/.wafpickle-*',\n '**/.*.swp',\n '**/._*/**',\n '**/archived-packages/**',\n '**/build/config.gypi',\n '**/CVS',\n '**/npm-debug.log',\n '**/*.orig',\n // Inline generic socket-registry .gitignore entries.\n '**/.env',\n '**/.eslintcache',\n '**/.nvm',\n '**/.tap',\n '**/.vscode',\n '**/*.tsbuildinfo',\n '**/Thumbs.db',\n // Inline additional ignores.\n '**/bower_components',\n])\n\nlet _picomatch: typeof import('picomatch') | undefined\n/**\n * Lazily load the picomatch module.\n * @private\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getPicomatch() {\n if (_picomatch === undefined) {\n // The 'picomatch' package is browser safe.\n _picomatch = /*@__PURE__*/ require('./external/picomatch')\n }\n return _picomatch as typeof import('picomatch')\n}\n\nlet _fastGlob: typeof import('fast-glob') | undefined\n/**\n * Lazily load the fast-glob module.\n * @private\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getFastGlob() {\n if (_fastGlob === undefined) {\n const globExport = /*@__PURE__*/ require('./external/fast-glob')\n _fastGlob = globExport.default || globExport\n }\n return _fastGlob as typeof import('fast-glob')\n}\n\n/**\n * Create a stream of license file paths matching glob patterns.\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function globStreamLicenses(\n dirname: string,\n options?: GlobOptions,\n): NodeJS.ReadableStream {\n const {\n ignore: ignoreOpt,\n ignoreOriginals,\n recursive,\n ...globOptions\n } = { __proto__: null, ...options } as GlobOptions\n const ignore = [\n ...(Array.isArray(ignoreOpt) ? ignoreOpt : defaultIgnore),\n '**/*.{cjs,cts,js,json,mjs,mts,ts}',\n ]\n if (ignoreOriginals) {\n ignore.push(\n /*@__INLINE__*/ require('#constants/paths')\n .LICENSE_ORIGINAL_GLOB_RECURSIVE,\n )\n }\n const fastGlob = getFastGlob()\n return fastGlob.globStream(\n [\n recursive\n ? /*@__INLINE__*/ require('#constants/paths').LICENSE_GLOB_RECURSIVE\n : /*@__INLINE__*/ require('#constants/paths').LICENSE_GLOB,\n ],\n {\n __proto__: null,\n absolute: true,\n caseSensitiveMatch: false,\n cwd: dirname,\n ...globOptions,\n ...(ignore ? { ignore } : {}),\n } as import('fast-glob').Options,\n )\n}\n\nconst matcherCache = new Map()\n/**\n * Get a cached glob matcher function.\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function getGlobMatcher(\n glob: Pattern | Pattern[],\n options?: { dot?: boolean; nocase?: boolean; ignore?: string[] },\n): (path: string) => boolean {\n const patterns = Array.isArray(glob) ? glob : [glob]\n const key = JSON.stringify({ patterns, options })\n let matcher = matcherCache.get(key)\n if (matcher) {\n return matcher\n }\n\n // Separate positive and negative patterns.\n const positivePatterns = patterns.filter(p => !p.startsWith('!'))\n const negativePatterns = patterns\n .filter(p => p.startsWith('!'))\n .map(p => p.slice(1))\n\n const picomatch = getPicomatch()\n\n // Use ignore option for negation patterns.\n const matchOptions = {\n dot: true,\n nocase: true,\n ...options,\n ...(negativePatterns.length > 0 ? { ignore: negativePatterns } : {}),\n }\n\n matcher = picomatch(\n positivePatterns.length > 0 ? positivePatterns : patterns,\n matchOptions,\n )\n\n matcherCache.set(key, matcher)\n return matcher\n}\n"],
5
+ "mappings": ";4ZAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,mBAAAE,EAAA,mBAAAC,EAAA,uBAAAC,IAAA,eAAAC,EAAAL,GAMA,IAAAM,EAA6C,qBAqCtC,MAAMJ,KAAgB,EAAAK,cAAa,CAMxC,UACA,YAEA,kBAMA,eACA,gBACA,SACA,mBACA,gBACA,UACA,kBACA,YACA,YACA,0BACA,uBACA,SACA,mBACA,YAEA,UACA,kBACA,UACA,UACA,aACA,mBACA,eAEA,qBACF,CAAC,EAED,IAAIC,EAMJ,SAASC,GAAe,CACtB,OAAID,IAAe,SAEjBA,EAA2B,QAAQ,sBAAsB,GAEpDA,CACT,CAEA,IAAIE,EAMJ,SAASC,GAAc,CACrB,GAAID,IAAc,OAAW,CAC3B,MAAME,EAA2B,QAAQ,sBAAsB,EAC/DF,EAAYE,EAAW,SAAWA,CACpC,CACA,OAAOF,CACT,CAMO,SAASN,EACdS,EACAC,EACuB,CACvB,KAAM,CACJ,OAAQC,EACR,gBAAAC,EACA,UAAAC,EACA,GAAGC,CACL,EAAI,CAAE,UAAW,KAAM,GAAGJ,CAAQ,EAC5BK,EAAS,CACb,GAAI,MAAM,QAAQJ,CAAS,EAAIA,EAAYb,EAC3C,mCACF,EACA,OAAIc,GACFG,EAAO,KACW,QAAQ,kBAAkB,EACvC,+BACL,EAEeR,EAAY,EACb,WACd,CACEM,EACoB,QAAQ,kBAAkB,EAAE,uBAC5B,QAAQ,kBAAkB,EAAE,YAClD,EACA,CACE,UAAW,KACX,SAAU,GACV,mBAAoB,GACpB,IAAKJ,EACL,GAAGK,EACH,GAAIC,EAAS,CAAE,OAAAA,CAAO,EAAI,CAAC,CAC7B,CACF,CACF,CAEA,MAAMC,EAAe,IAAI,IAKlB,SAASjB,EACdkB,EACAP,EAC2B,CAC3B,MAAMQ,EAAW,MAAM,QAAQD,CAAI,EAAIA,EAAO,CAACA,CAAI,EAC7CE,EAAM,KAAK,UAAU,CAAE,SAAAD,EAAU,QAAAR,CAAQ,CAAC,EAChD,IAAIU,EAAUJ,EAAa,IAAIG,CAAG,EAClC,GAAIC,EACF,OAAOA,EAIT,MAAMC,EAAmBH,EAAS,OAAOI,GAAK,CAACA,EAAE,WAAW,GAAG,CAAC,EAC1DC,EAAmBL,EACtB,OAAOI,GAAKA,EAAE,WAAW,GAAG,CAAC,EAC7B,IAAIA,GAAKA,EAAE,MAAM,CAAC,CAAC,EAEhBE,EAAYnB,EAAa,EAGzBoB,EAAe,CACnB,IAAK,GACL,OAAQ,GACR,GAAGf,EACH,GAAIa,EAAiB,OAAS,EAAI,CAAE,OAAQA,CAAiB,EAAI,CAAC,CACpE,EAEA,OAAAH,EAAUI,EACRH,EAAiB,OAAS,EAAIA,EAAmBH,EACjDO,CACF,EAEAT,EAAa,IAAIG,EAAKC,CAAO,EACtBA,CACT",
6
6
  "names": ["globs_exports", "__export", "defaultIgnore", "getGlobMatcher", "globStreamLicenses", "__toCommonJS", "import_objects", "ObjectFreeze", "_picomatch", "getPicomatch", "_fastGlob", "getFastGlob", "globExport", "dirname", "options", "ignoreOpt", "ignoreOriginals", "recursive", "globOptions", "ignore", "matcherCache", "glob", "patterns", "key", "matcher", "positivePatterns", "p", "negativePatterns", "picomatch", "matchOptions"]
7
7
  }
package/dist/ipc.d.ts CHANGED
@@ -191,7 +191,7 @@ export declare function readIpcStub(stubPath: string): Promise<unknown>;
191
191
  * periodically or on application startup.
192
192
  *
193
193
  * ## Cleanup Rules:
194
- * - Files older than 5 minutes are removed
194
+ * - Files older than 5 minutes are removed (checked via both filesystem mtime and JSON timestamp)
195
195
  * - Only stub files (stub-*.json) are processed
196
196
  * - Errors are silently ignored (best-effort cleanup)
197
197
  *
package/dist/ipc.js CHANGED
@@ -1,3 +1,3 @@
1
1
  /* Socket Lib - Built with esbuild */
2
- var M=Object.create;var d=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var T=Object.getPrototypeOf,j=Object.prototype.hasOwnProperty;var P=(t,n)=>{for(var e in n)d(t,e,{get:n[e],enumerable:!0})},I=(t,n,e,o)=>{if(n&&typeof n=="object"||typeof n=="function")for(let s of S(n))!j.call(t,s)&&s!==e&&d(t,s,{get:()=>n[s],enumerable:!(o=v(n,s))||o.enumerable});return t};var f=(t,n,e)=>(e=t!=null?M(T(t)):{},I(n||!t||!t.__esModule?d(e,"default",{value:t,enumerable:!0}):e,t)),D=t=>I(d({},"__esModule",{value:!0}),t);var W={};P(W,{IpcHandshakeSchema:()=>B,cleanupIpcStubs:()=>O,createIpcChannelId:()=>N,createIpcMessage:()=>A,getIpcStubPath:()=>y,hasIpcChannel:()=>H,onIpc:()=>k,parseIpcMessage:()=>x,readIpcStub:()=>J,sendIpc:()=>C,waitForIpc:()=>F,writeIpcStub:()=>E});module.exports=D(W);var l=f(require("node:crypto")),r=require("node:fs"),g=f(require("node:os")),p=f(require("node:path")),i=require("./zod");const w=i.z.object({id:i.z.string().min(1),timestamp:i.z.number().positive(),type:i.z.string().min(1),data:i.z.unknown()}),B=w.extend({type:i.z.literal("handshake"),data:i.z.object({version:i.z.string(),pid:i.z.number().int().positive(),apiToken:i.z.string().optional(),appName:i.z.string()})}),b=i.z.object({pid:i.z.number().int().positive(),timestamp:i.z.number().positive(),data:i.z.unknown()});function N(t="socket"){return`${t}-${process.pid}-${l.default.randomBytes(8).toString("hex")}`}function y(t){const n=g.default.tmpdir(),e=p.default.join(n,".socket-ipc",t);return p.default.join(e,`stub-${process.pid}.json`)}async function $(t){const n=p.default.dirname(t);await r.promises.mkdir(n,{recursive:!0})}async function E(t,n){const e=y(t);await $(e);const o={data:n,pid:process.pid,timestamp:Date.now()},s=b.parse(o);return await r.promises.writeFile(e,JSON.stringify(s,null,2),"utf8"),e}async function J(t){try{const n=await r.promises.readFile(t,"utf8"),e=JSON.parse(n),o=b.parse(e),s=Date.now()-o.timestamp,a=300*1e3;return s>a?(await r.promises.unlink(t).catch(()=>{}),null):o.data}catch{return null}}async function O(t){const n=g.default.tmpdir(),e=p.default.join(n,".socket-ipc",t);try{const o=await r.promises.readdir(e),s=Date.now(),a=300*1e3;await Promise.all(o.map(async c=>{if(c.startsWith("stub-")&&c.endsWith(".json")){const u=p.default.join(e,c);try{const h=await r.promises.stat(u);s-h.mtimeMs>a&&await r.promises.unlink(u)}catch{}}}))}catch{}}function C(t,n){if(t&&typeof t=="object"&&"send"in t&&typeof t.send=="function")try{const e=w.parse(n);return t.send(e)}catch{return!1}return!1}function k(t){const n=e=>{const o=x(e);o&&t(o)};return process.on("message",n),()=>{process.off("message",n)}}function F(t,n={}){const{timeout:e=3e4}=n;return new Promise((o,s)=>{let a=null,c=null;const u=()=>{a&&a(),s(new Error(`IPC timeout waiting for message type: ${t}`))};a=k(m=>{m.type===t&&(c&&clearTimeout(c),a&&a(),o(m.data))}),e>0&&(c=setTimeout(u,e))})}function A(t,n){return{id:l.default.randomBytes(16).toString("hex"),timestamp:Date.now(),type:t,data:n}}function H(t){return!!(t&&typeof t=="object"&&"send"in t&&typeof t.send=="function"&&"channel"in t&&t.channel!==void 0)}function x(t){try{return w.parse(t)}catch{return null}}0&&(module.exports={IpcHandshakeSchema,cleanupIpcStubs,createIpcChannelId,createIpcMessage,getIpcStubPath,hasIpcChannel,onIpc,parseIpcMessage,readIpcStub,sendIpc,waitForIpc,writeIpcStub});
2
+ var P=Object.create;var m=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var O=Object.getPrototypeOf,A=Object.prototype.hasOwnProperty;var J=(t,e)=>{for(var n in e)m(t,n,{get:e[n],enumerable:!0})},y=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of B(e))!A.call(t,s)&&s!==n&&m(t,s,{get:()=>e[s],enumerable:!(o=N(e,s))||o.enumerable});return t};var k=(t,e,n)=>(n=t!=null?P(O(t)):{},y(e||!t||!t.__esModule?m(n,"default",{value:t,enumerable:!0}):n,t)),$=t=>y(m({},"__esModule",{value:!0}),t);var L={};J(L,{IpcHandshakeSchema:()=>E,cleanupIpcStubs:()=>z,createIpcChannelId:()=>F,createIpcMessage:()=>G,getIpcStubPath:()=>x,hasIpcChannel:()=>K,onIpc:()=>S,parseIpcMessage:()=>v,readIpcStub:()=>W,sendIpc:()=>_,waitForIpc:()=>q,writeIpcStub:()=>H});module.exports=$(L);var l=k(require("node:crypto")),c=require("node:fs"),p=k(require("node:path")),g=require("./fs"),h=require("./paths"),i=require("./zod");const w=i.z.object({id:i.z.string().min(1),timestamp:i.z.number().positive(),type:i.z.string().min(1),data:i.z.unknown()}),E=w.extend({type:i.z.literal("handshake"),data:i.z.object({version:i.z.string(),pid:i.z.number().int().positive(),apiToken:i.z.string().optional(),appName:i.z.string()})}),I=i.z.object({pid:i.z.number().int().positive(),timestamp:i.z.number().positive(),data:i.z.unknown()});function F(t="socket"){return`${t}-${process.pid}-${l.default.randomBytes(8).toString("hex")}`}function x(t){const e=(0,h.getOsTmpDir)(),n=p.default.join(e,".socket-ipc",t);return p.default.join(n,`stub-${process.pid}.json`)}async function C(t){const e=p.default.dirname(t);await c.promises.mkdir(e,{recursive:!0})}async function H(t,e){const n=x(t);await C(n);const o={data:e,pid:process.pid,timestamp:Date.now()},s=I.parse(o);return await c.promises.writeFile(n,JSON.stringify(s,null,2),"utf8"),n}async function W(t){try{const e=await c.promises.readFile(t,"utf8"),n=JSON.parse(e),o=I.parse(n),s=Date.now()-o.timestamp,a=300*1e3;if(s>a){try{(0,g.safeDeleteSync)(t,{force:!0})}catch{}return null}return o.data}catch{return null}}async function z(t){const e=(0,h.getOsTmpDir)(),n=p.default.join(e,".socket-ipc",t);try{const o=await c.promises.readdir(n),s=Date.now(),a=300*1e3;await Promise.all(o.map(async r=>{if(r.startsWith("stub-")&&r.endsWith(".json")){const u=p.default.join(n,r);try{const b=await c.promises.stat(u);let f=s-b.mtimeMs>a;try{const M=await c.promises.readFile(u,"utf8"),T=JSON.parse(M),D=I.parse(T),j=s-D.timestamp;f=f||j>a}catch{}f&&(0,g.safeDeleteSync)(u,{force:!0})}catch{}}}))}catch{}}function _(t,e){if(t&&typeof t=="object"&&"send"in t&&typeof t.send=="function")try{const n=w.parse(e);return t.send(n)}catch{return!1}return!1}function S(t){const e=n=>{const o=v(n);o&&t(o)};return process.on("message",e),()=>{process.off("message",e)}}function q(t,e={}){const{timeout:n=3e4}=e;return new Promise((o,s)=>{let a=null,r=null;const u=()=>{a&&a(),s(new Error(`IPC timeout waiting for message type: ${t}`))};a=S(d=>{d.type===t&&(r&&clearTimeout(r),a&&a(),o(d.data))}),n>0&&(r=setTimeout(u,n))})}function G(t,e){return{id:l.default.randomBytes(16).toString("hex"),timestamp:Date.now(),type:t,data:e}}function K(t){return!!(t&&typeof t=="object"&&"send"in t&&typeof t.send=="function"&&"channel"in t&&t.channel!==void 0)}function v(t){try{return w.parse(t)}catch{return null}}0&&(module.exports={IpcHandshakeSchema,cleanupIpcStubs,createIpcChannelId,createIpcMessage,getIpcStubPath,hasIpcChannel,onIpc,parseIpcMessage,readIpcStub,sendIpc,waitForIpc,writeIpcStub});
3
3
  //# sourceMappingURL=ipc.js.map
package/dist/ipc.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/ipc.ts"],
4
- "sourcesContent": ["/**\n * IPC (Inter-Process Communication) Module\n * ==========================================\n *\n * This module provides secure inter-process communication utilities for Socket CLI\n * and related tools. It replaces environment variable passing with more secure and\n * scalable alternatives.\n *\n * ## Key Features:\n * - File-based stub communication for initial data handoff\n * - Node.js IPC channel support for real-time bidirectional messaging\n * - Automatic cleanup of temporary files\n * - Type-safe message validation with Zod schemas\n * - Timeout handling for reliability\n *\n * ## Use Cases:\n * 1. Passing API tokens between processes without exposing them in env vars\n * 2. Transferring large configuration objects that exceed env var size limits\n * 3. Bidirectional communication between parent and child processes\n * 4. Secure handshake protocols between Socket CLI components\n *\n * ## Security Considerations:\n * - Stub files are created with restricted permissions in OS temp directory\n * - Messages include timestamps for freshness validation\n * - Automatic cleanup prevents sensitive data persistence\n * - Unique IDs prevent message replay attacks\n *\n * @module ipc\n */\n\nimport crypto from 'node:crypto'\nimport { promises as fs } from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\n\nimport { z } from './zod'\n\n// Define BufferEncoding type for TypeScript compatibility.\ntype BufferEncoding = globalThis.BufferEncoding\n\n/**\n * Zod Schemas for Runtime Validation\n * ====================================\n * These schemas provide runtime type safety for IPC messages,\n * ensuring data integrity across process boundaries.\n */\n\n/**\n * Base IPC message schema - validates the core message structure.\n * All IPC messages must conform to this schema.\n */\nconst IpcMessageSchema = z.object({\n /** Unique identifier for message tracking and response correlation. */\n id: z.string().min(1),\n /** Unix timestamp for freshness validation and replay prevention. */\n timestamp: z.number().positive(),\n /** Message type identifier for routing and handling. */\n type: z.string().min(1),\n /** Payload data - can be any JSON-serializable value. */\n data: z.unknown(),\n})\n\n/**\n * IPC handshake schema - used for initial connection establishment.\n * The handshake includes version info and authentication tokens.\n * @internal Exported for testing purposes.\n */\nexport const IpcHandshakeSchema = IpcMessageSchema.extend({\n type: z.literal('handshake'),\n data: z.object({\n /** Protocol version for compatibility checking. */\n version: z.string(),\n /** Process ID for identification. */\n pid: z.number().int().positive(),\n /** Optional API token for authentication. */\n apiToken: z.string().optional(),\n /** Application name for multi-app support. */\n appName: z.string(),\n }),\n})\n\n/**\n * IPC stub file schema - validates the structure of stub files.\n * Stub files are used for passing data between processes via filesystem.\n */\nconst IpcStubSchema = z.object({\n /** Process ID that created the stub. */\n pid: z.number().int().positive(),\n /** Creation timestamp for age validation. */\n timestamp: z.number().positive(),\n /** The actual data payload. */\n data: z.unknown(),\n})\n\n/**\n * TypeScript interfaces for IPC communication.\n * These types ensure type consistency across the IPC module.\n */\n\n/**\n * Base IPC message interface.\n * All IPC messages must conform to this structure.\n */\nexport interface IpcMessage<T = unknown> {\n /** Unique identifier for message tracking and response correlation. */\n id: string\n /** Unix timestamp for freshness validation and replay prevention. */\n timestamp: number\n /** Message type identifier for routing and handling. */\n type: string\n /** Payload data - can be any JSON-serializable value. */\n data: T\n}\n\n/**\n * IPC handshake message interface.\n * Used for initial connection establishment.\n */\nexport interface IpcHandshake\n extends IpcMessage<{\n /** Protocol version for compatibility checking. */\n version: string\n /** Process ID for identification. */\n pid: number\n /** Optional API token for authentication. */\n apiToken?: string\n /** Application name for multi-app support. */\n appName: string\n }> {\n type: 'handshake'\n}\n\n/**\n * IPC stub file interface.\n * Represents the structure of stub files used for filesystem-based IPC.\n */\nexport interface IpcStub {\n /** Process ID that created the stub. */\n pid: number\n /** Creation timestamp for age validation. */\n timestamp: number\n /** The actual data payload. */\n data: unknown\n}\n\n/**\n * Options for IPC communication\n */\nexport interface IpcOptions {\n /** Timeout in milliseconds for async operations. */\n timeout?: number\n /** Text encoding for message serialization. */\n encoding?: BufferEncoding\n}\n\n/**\n * Create a unique IPC channel identifier for message correlation.\n *\n * Generates a unique identifier that combines:\n * - A prefix for namespacing (defaults to 'socket')\n * - The current process ID for process identification\n * - A random hex string for uniqueness\n *\n * @param prefix - Optional prefix to namespace the channel ID\n * @returns A unique channel identifier string\n *\n * @example\n * ```typescript\n * const channelId = createIpcChannelId('socket-cli')\n * // Returns: 'socket-cli-12345-a1b2c3d4e5f6g7h8'\n * ```\n */\nexport function createIpcChannelId(prefix = 'socket'): string {\n return `${prefix}-${process.pid}-${crypto.randomBytes(8).toString('hex')}`\n}\n\n/**\n * Get the IPC stub path for a given application.\n *\n * This function generates a unique file path for IPC stub files that are used\n * to pass data between processes. The stub files are stored in a hidden directory\n * within the system's temporary folder.\n *\n * ## Path Structure:\n * - Base: System temp directory (e.g., /tmp on Unix, %TEMP% on Windows)\n * - Directory: `.socket-ipc/{appName}/`\n * - Filename: `stub-{pid}.json`\n *\n * ## Security Features:\n * - Files are isolated per application via appName parameter\n * - Process ID in filename prevents collisions between concurrent processes\n * - Temporary directory location ensures automatic cleanup on system restart\n *\n * @param appName - The application identifier (e.g., 'socket-cli', 'socket-dlx')\n * @returns Full path to the IPC stub file\n *\n * @example\n * ```typescript\n * const stubPath = getIpcStubPath('socket-cli')\n * // Returns: '/tmp/.socket-ipc/socket-cli/stub-12345.json' (Unix)\n * // Returns: 'C:\\\\Users\\\\Name\\\\AppData\\\\Local\\\\Temp\\\\.socket-ipc\\\\socket-cli\\\\stub-12345.json' (Windows)\n * ```\n *\n * @used Currently used by socket-cli for self-update and inter-process communication\n */\nexport function getIpcStubPath(appName: string): string {\n // Get the system's temporary directory - this is platform-specific.\n const tempDir = os.tmpdir()\n\n // Create a hidden directory structure for Socket IPC files.\n // The dot prefix makes it hidden on Unix-like systems.\n const stubDir = path.join(tempDir, '.socket-ipc', appName)\n\n // Generate filename with process ID to ensure uniqueness.\n // The PID prevents conflicts when multiple processes run simultaneously.\n return path.join(stubDir, `stub-${process.pid}.json`)\n}\n\n/**\n * Ensure IPC directory exists for stub file creation.\n *\n * This helper function creates the directory structure needed for IPC stub files.\n * It's called before writing stub files to ensure the parent directories exist.\n *\n * @param filePath - Full path to the file that needs its directory created\n * @returns Promise that resolves when directory is created\n *\n * @internal Helper function used by writeIpcStub\n */\nasync function ensureIpcDirectory(filePath: string): Promise<void> {\n const dir = path.dirname(filePath)\n // Create directory recursively if it doesn't exist.\n await fs.mkdir(dir, { recursive: true })\n}\n\n/**\n * Write IPC data to a stub file for inter-process data transfer.\n *\n * This function creates a stub file containing data that needs to be passed\n * between processes. The stub file includes metadata like process ID and\n * timestamp for validation.\n *\n * ## File Structure:\n * ```json\n * {\n * \"pid\": 12345,\n * \"timestamp\": 1699564234567,\n * \"data\": { ... }\n * }\n * ```\n *\n * ## Use Cases:\n * - Passing API tokens to child processes\n * - Transferring configuration between Socket CLI components\n * - Sharing large data that exceeds environment variable limits\n *\n * @param appName - The application identifier\n * @param data - The data to write to the stub file\n * @returns Promise resolving to the stub file path\n *\n * @example\n * ```typescript\n * const stubPath = await writeIpcStub('socket-cli', {\n * apiToken: 'secret-token',\n * config: { ... }\n * })\n * // Pass stubPath to child process for reading\n * ```\n */\nexport async function writeIpcStub(\n appName: string,\n data: unknown,\n): Promise<string> {\n const stubPath = getIpcStubPath(appName)\n await ensureIpcDirectory(stubPath)\n\n // Create stub data with validation metadata.\n const ipcData: IpcStub = {\n data,\n pid: process.pid,\n timestamp: Date.now(),\n }\n\n // Validate data structure with Zod schema.\n const validated = IpcStubSchema.parse(ipcData)\n\n // Write with pretty printing for debugging.\n await fs.writeFile(stubPath, JSON.stringify(validated, null, 2), 'utf8')\n return stubPath\n}\n\n/**\n * Read IPC data from a stub file with automatic cleanup.\n *\n * This function reads data from an IPC stub file and validates its freshness.\n * Stale files (older than 5 minutes) are automatically cleaned up to prevent\n * accumulation of temporary files.\n *\n * ## Validation Steps:\n * 1. Read and parse JSON file\n * 2. Validate structure with Zod schema\n * 3. Check timestamp freshness\n * 4. Clean up if stale\n * 5. Return data if valid\n *\n * @param stubPath - Path to the stub file to read\n * @returns Promise resolving to the data or null if invalid/stale\n *\n * @example\n * ```typescript\n * const data = await readIpcStub('/tmp/.socket-ipc/socket-cli/stub-12345.json')\n * if (data) {\n * console.log('Received:', data)\n * }\n * ```\n *\n * @unused Reserved for future implementation\n */\nexport async function readIpcStub(stubPath: string): Promise<unknown> {\n try {\n const content = await fs.readFile(stubPath, 'utf8')\n const parsed = JSON.parse(content)\n // Validate structure with Zod schema.\n const validated = IpcStubSchema.parse(parsed)\n // Check age for freshness validation.\n const ageMs = Date.now() - validated.timestamp\n // 5 minutes.\n const maxAgeMs = 5 * 60 * 1000\n if (ageMs > maxAgeMs) {\n // Clean up stale file.\n await fs.unlink(stubPath).catch(() => {})\n return null\n }\n return validated.data\n } catch {\n // Return null for any errors (file not found, invalid JSON, validation failure).\n return null\n }\n}\n\n/**\n * Clean up IPC stub files for an application.\n *\n * This maintenance function removes stale IPC stub files to prevent\n * accumulation in the temporary directory. It's designed to be called\n * periodically or on application startup.\n *\n * ## Cleanup Rules:\n * - Files older than 5 minutes are removed\n * - Only stub files (stub-*.json) are processed\n * - Errors are silently ignored (best-effort cleanup)\n *\n * @param appName - The application identifier\n * @returns Promise that resolves when cleanup is complete\n *\n * @example\n * ```typescript\n * // Clean up on application startup\n * await cleanupIpcStubs('socket-cli')\n * ```\n *\n * @unused Reserved for future implementation\n */\nexport async function cleanupIpcStubs(appName: string): Promise<void> {\n const tempDir = os.tmpdir()\n const stubDir = path.join(tempDir, '.socket-ipc', appName)\n try {\n const files = await fs.readdir(stubDir)\n const now = Date.now()\n // 5 minutes.\n const maxAgeMs = 5 * 60 * 1000\n // Process each file in parallel for efficiency.\n await Promise.all(\n files.map(async file => {\n if (file.startsWith('stub-') && file.endsWith('.json')) {\n const filePath = path.join(stubDir, file)\n try {\n const stats = await fs.stat(filePath)\n const ageMs = now - stats.mtimeMs\n if (ageMs > maxAgeMs) {\n await fs.unlink(filePath)\n }\n } catch {\n // Ignore errors for individual files.\n }\n }\n }),\n )\n } catch {\n // Directory might not exist, that's ok.\n }\n}\n\n/**\n * Send data through Node.js IPC channel.\n *\n * This function sends structured messages through the Node.js IPC channel\n * when available. The IPC channel must be established with stdio: ['pipe', 'pipe', 'pipe', 'ipc'].\n *\n * ## Requirements:\n * - Process must have been spawned with IPC channel enabled\n * - Message must be serializable to JSON\n * - Process.send() must be available\n *\n * @param process - The process object with IPC channel\n * @param message - The IPC message to send\n * @returns true if message was sent, false otherwise\n *\n * @example\n * ```typescript\n * const message = createIpcMessage('handshake', { version: '1.0.0' })\n * const sent = sendIpc(childProcess, message)\n * ```\n *\n * @unused Reserved for bidirectional communication implementation\n */\nexport function sendIpc(\n process: NodeJS.Process | unknown,\n message: IpcMessage,\n): boolean {\n if (\n process &&\n typeof process === 'object' &&\n 'send' in process &&\n typeof process.send === 'function'\n ) {\n try {\n // Validate message structure before sending.\n const validated = IpcMessageSchema.parse(message)\n return process.send(validated)\n } catch {\n return false\n }\n }\n return false\n}\n\n/**\n * Receive data through Node.js IPC channel.\n *\n * Sets up a listener for IPC messages with automatic validation and parsing.\n * Returns a cleanup function to remove the listener when no longer needed.\n *\n * ## Message Flow:\n * 1. Receive raw message from IPC channel\n * 2. Validate with parseIpcMessage\n * 3. Call handler if valid\n * 4. Ignore invalid messages\n *\n * @param handler - Function to call with valid IPC messages\n * @returns Cleanup function to remove the listener\n *\n * @example\n * ```typescript\n * const cleanup = onIpc((message) => {\n * console.log('Received:', message.type, message.data)\n * })\n * // Later...\n * cleanup() // Remove listener\n * ```\n *\n * @unused Reserved for bidirectional communication\n */\nexport function onIpc(handler: (message: IpcMessage) => void): () => void {\n const listener = (message: unknown) => {\n const parsed = parseIpcMessage(message)\n if (parsed) {\n handler(parsed)\n }\n }\n process.on('message', listener)\n // Return cleanup function for proper resource management.\n return () => {\n process.off('message', listener)\n }\n}\n\n/**\n * Create a promise that resolves when a specific IPC message is received.\n *\n * This utility function provides async/await support for IPC communication,\n * allowing you to wait for specific message types with timeout support.\n *\n * ## Features:\n * - Automatic timeout handling\n * - Type-safe message data\n * - Resource cleanup on completion\n * - Promise-based API\n *\n * @param messageType - The message type to wait for\n * @param options - Options including timeout configuration\n * @returns Promise resolving to the message data\n *\n * @example\n * ```typescript\n * try {\n * const response = await waitForIpc<ConfigData>('config-response', {\n * timeout: 5000 // 5 seconds\n * })\n * console.log('Config received:', response)\n * } catch (error) {\n * console.error('Timeout waiting for config')\n * }\n * ```\n *\n * @unused Reserved for request-response pattern implementation\n */\nexport function waitForIpc<T = unknown>(\n messageType: string,\n options: IpcOptions = {},\n): Promise<T> {\n const { timeout = 30_000 } = options\n return new Promise((resolve, reject) => {\n let cleanup: (() => void) | null = null\n let timeoutId: NodeJS.Timeout | null = null\n const handleTimeout = () => {\n if (cleanup) {\n cleanup()\n }\n reject(new Error(`IPC timeout waiting for message type: ${messageType}`))\n }\n const handleMessage = (message: IpcMessage) => {\n if (message.type === messageType) {\n if (timeoutId) {\n clearTimeout(timeoutId)\n }\n if (cleanup) {\n cleanup()\n }\n resolve(message.data as T)\n }\n }\n cleanup = onIpc(handleMessage)\n if (timeout > 0) {\n timeoutId = setTimeout(handleTimeout, timeout)\n }\n })\n}\n\n/**\n * Create an IPC message with proper structure and metadata.\n *\n * This factory function creates properly structured IPC messages with:\n * - Unique ID for tracking\n * - Timestamp for freshness\n * - Type for routing\n * - Data payload\n *\n * @param type - The message type identifier\n * @param data - The message payload\n * @returns A properly structured IPC message\n *\n * @example\n * ```typescript\n * const handshake = createIpcMessage('handshake', {\n * version: '1.0.0',\n * pid: process.pid,\n * appName: 'socket-cli'\n * })\n * ```\n *\n * @unused Reserved for future message creation needs\n */\nexport function createIpcMessage<T = unknown>(\n type: string,\n data: T,\n): IpcMessage<T> {\n return {\n id: crypto.randomBytes(16).toString('hex'),\n timestamp: Date.now(),\n type,\n data,\n }\n}\n\n/**\n * Check if process has IPC channel available.\n *\n * This utility checks whether a process object has the necessary\n * properties for IPC communication. Used to determine if IPC\n * messaging is possible before attempting to send.\n *\n * @param process - The process object to check\n * @returns true if IPC is available, false otherwise\n *\n * @example\n * ```typescript\n * if (hasIpcChannel(childProcess)) {\n * sendIpc(childProcess, message)\n * } else {\n * // Fall back to alternative communication method\n * }\n * ```\n *\n * @unused Reserved for IPC availability detection\n */\nexport function hasIpcChannel(process: unknown): boolean {\n return Boolean(\n process &&\n typeof process === 'object' &&\n 'send' in process &&\n typeof process.send === 'function' &&\n 'channel' in process &&\n process.channel !== undefined,\n )\n}\n\n/**\n * Safely parse and validate IPC messages.\n *\n * This function performs runtime validation of incoming messages\n * to ensure they conform to the IPC message structure. It uses\n * Zod schemas for robust validation.\n *\n * ## Validation Steps:\n * 1. Check if message is an object\n * 2. Validate required fields exist\n * 3. Validate field types\n * 4. Return typed message or null\n *\n * @param message - The raw message to parse\n * @returns Parsed IPC message or null if invalid\n *\n * @example\n * ```typescript\n * const parsed = parseIpcMessage(rawMessage)\n * if (parsed) {\n * handleMessage(parsed)\n * }\n * ```\n *\n * @unused Reserved for message validation needs\n */\nexport function parseIpcMessage(message: unknown): IpcMessage | null {\n try {\n // Use Zod schema for comprehensive validation.\n const validated = IpcMessageSchema.parse(message)\n return validated as IpcMessage\n } catch {\n // Return null for any validation failure.\n return null\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["ipc_exports", "__export", "IpcHandshakeSchema", "cleanupIpcStubs", "createIpcChannelId", "createIpcMessage", "getIpcStubPath", "hasIpcChannel", "onIpc", "parseIpcMessage", "readIpcStub", "sendIpc", "waitForIpc", "writeIpcStub", "__toCommonJS", "import_node_crypto", "import_node_fs", "import_node_os", "import_node_path", "import_zod", "IpcMessageSchema", "IpcStubSchema", "prefix", "crypto", "appName", "tempDir", "os", "stubDir", "path", "ensureIpcDirectory", "filePath", "dir", "fs", "data", "stubPath", "ipcData", "validated", "content", "parsed", "ageMs", "maxAgeMs", "files", "now", "file", "stats", "process", "message", "handler", "listener", "messageType", "options", "timeout", "resolve", "reject", "cleanup", "timeoutId", "handleTimeout", "type"]
4
+ "sourcesContent": ["/**\n * IPC (Inter-Process Communication) Module\n * ==========================================\n *\n * This module provides secure inter-process communication utilities for Socket CLI\n * and related tools. It replaces environment variable passing with more secure and\n * scalable alternatives.\n *\n * ## Key Features:\n * - File-based stub communication for initial data handoff\n * - Node.js IPC channel support for real-time bidirectional messaging\n * - Automatic cleanup of temporary files\n * - Type-safe message validation with Zod schemas\n * - Timeout handling for reliability\n *\n * ## Use Cases:\n * 1. Passing API tokens between processes without exposing them in env vars\n * 2. Transferring large configuration objects that exceed env var size limits\n * 3. Bidirectional communication between parent and child processes\n * 4. Secure handshake protocols between Socket CLI components\n *\n * ## Security Considerations:\n * - Stub files are created with restricted permissions in OS temp directory\n * - Messages include timestamps for freshness validation\n * - Automatic cleanup prevents sensitive data persistence\n * - Unique IDs prevent message replay attacks\n *\n * @module ipc\n */\n\nimport crypto from 'node:crypto'\nimport { promises as fs } from 'node:fs'\nimport path from 'node:path'\n\nimport { safeDeleteSync } from './fs'\nimport { getOsTmpDir } from './paths'\nimport { z } from './zod'\n\n// Define BufferEncoding type for TypeScript compatibility.\ntype BufferEncoding = globalThis.BufferEncoding\n\n/**\n * Zod Schemas for Runtime Validation\n * ====================================\n * These schemas provide runtime type safety for IPC messages,\n * ensuring data integrity across process boundaries.\n */\n\n/**\n * Base IPC message schema - validates the core message structure.\n * All IPC messages must conform to this schema.\n */\nconst IpcMessageSchema = z.object({\n /** Unique identifier for message tracking and response correlation. */\n id: z.string().min(1),\n /** Unix timestamp for freshness validation and replay prevention. */\n timestamp: z.number().positive(),\n /** Message type identifier for routing and handling. */\n type: z.string().min(1),\n /** Payload data - can be any JSON-serializable value. */\n data: z.unknown(),\n})\n\n/**\n * IPC handshake schema - used for initial connection establishment.\n * The handshake includes version info and authentication tokens.\n * @internal Exported for testing purposes.\n */\nexport const IpcHandshakeSchema = IpcMessageSchema.extend({\n type: z.literal('handshake'),\n data: z.object({\n /** Protocol version for compatibility checking. */\n version: z.string(),\n /** Process ID for identification. */\n pid: z.number().int().positive(),\n /** Optional API token for authentication. */\n apiToken: z.string().optional(),\n /** Application name for multi-app support. */\n appName: z.string(),\n }),\n})\n\n/**\n * IPC stub file schema - validates the structure of stub files.\n * Stub files are used for passing data between processes via filesystem.\n */\nconst IpcStubSchema = z.object({\n /** Process ID that created the stub. */\n pid: z.number().int().positive(),\n /** Creation timestamp for age validation. */\n timestamp: z.number().positive(),\n /** The actual data payload. */\n data: z.unknown(),\n})\n\n/**\n * TypeScript interfaces for IPC communication.\n * These types ensure type consistency across the IPC module.\n */\n\n/**\n * Base IPC message interface.\n * All IPC messages must conform to this structure.\n */\nexport interface IpcMessage<T = unknown> {\n /** Unique identifier for message tracking and response correlation. */\n id: string\n /** Unix timestamp for freshness validation and replay prevention. */\n timestamp: number\n /** Message type identifier for routing and handling. */\n type: string\n /** Payload data - can be any JSON-serializable value. */\n data: T\n}\n\n/**\n * IPC handshake message interface.\n * Used for initial connection establishment.\n */\nexport interface IpcHandshake\n extends IpcMessage<{\n /** Protocol version for compatibility checking. */\n version: string\n /** Process ID for identification. */\n pid: number\n /** Optional API token for authentication. */\n apiToken?: string\n /** Application name for multi-app support. */\n appName: string\n }> {\n type: 'handshake'\n}\n\n/**\n * IPC stub file interface.\n * Represents the structure of stub files used for filesystem-based IPC.\n */\nexport interface IpcStub {\n /** Process ID that created the stub. */\n pid: number\n /** Creation timestamp for age validation. */\n timestamp: number\n /** The actual data payload. */\n data: unknown\n}\n\n/**\n * Options for IPC communication\n */\nexport interface IpcOptions {\n /** Timeout in milliseconds for async operations. */\n timeout?: number\n /** Text encoding for message serialization. */\n encoding?: BufferEncoding\n}\n\n/**\n * Create a unique IPC channel identifier for message correlation.\n *\n * Generates a unique identifier that combines:\n * - A prefix for namespacing (defaults to 'socket')\n * - The current process ID for process identification\n * - A random hex string for uniqueness\n *\n * @param prefix - Optional prefix to namespace the channel ID\n * @returns A unique channel identifier string\n *\n * @example\n * ```typescript\n * const channelId = createIpcChannelId('socket-cli')\n * // Returns: 'socket-cli-12345-a1b2c3d4e5f6g7h8'\n * ```\n */\nexport function createIpcChannelId(prefix = 'socket'): string {\n return `${prefix}-${process.pid}-${crypto.randomBytes(8).toString('hex')}`\n}\n\n/**\n * Get the IPC stub path for a given application.\n *\n * This function generates a unique file path for IPC stub files that are used\n * to pass data between processes. The stub files are stored in a hidden directory\n * within the system's temporary folder.\n *\n * ## Path Structure:\n * - Base: System temp directory (e.g., /tmp on Unix, %TEMP% on Windows)\n * - Directory: `.socket-ipc/{appName}/`\n * - Filename: `stub-{pid}.json`\n *\n * ## Security Features:\n * - Files are isolated per application via appName parameter\n * - Process ID in filename prevents collisions between concurrent processes\n * - Temporary directory location ensures automatic cleanup on system restart\n *\n * @param appName - The application identifier (e.g., 'socket-cli', 'socket-dlx')\n * @returns Full path to the IPC stub file\n *\n * @example\n * ```typescript\n * const stubPath = getIpcStubPath('socket-cli')\n * // Returns: '/tmp/.socket-ipc/socket-cli/stub-12345.json' (Unix)\n * // Returns: 'C:\\\\Users\\\\Name\\\\AppData\\\\Local\\\\Temp\\\\.socket-ipc\\\\socket-cli\\\\stub-12345.json' (Windows)\n * ```\n *\n * @used Currently used by socket-cli for self-update and inter-process communication\n */\nexport function getIpcStubPath(appName: string): string {\n // Get the system's temporary directory - this is platform-specific.\n const tempDir = getOsTmpDir()\n\n // Create a hidden directory structure for Socket IPC files.\n // The dot prefix makes it hidden on Unix-like systems.\n const stubDir = path.join(tempDir, '.socket-ipc', appName)\n\n // Generate filename with process ID to ensure uniqueness.\n // The PID prevents conflicts when multiple processes run simultaneously.\n return path.join(stubDir, `stub-${process.pid}.json`)\n}\n\n/**\n * Ensure IPC directory exists for stub file creation.\n *\n * This helper function creates the directory structure needed for IPC stub files.\n * It's called before writing stub files to ensure the parent directories exist.\n *\n * @param filePath - Full path to the file that needs its directory created\n * @returns Promise that resolves when directory is created\n *\n * @internal Helper function used by writeIpcStub\n */\nasync function ensureIpcDirectory(filePath: string): Promise<void> {\n const dir = path.dirname(filePath)\n // Create directory recursively if it doesn't exist.\n await fs.mkdir(dir, { recursive: true })\n}\n\n/**\n * Write IPC data to a stub file for inter-process data transfer.\n *\n * This function creates a stub file containing data that needs to be passed\n * between processes. The stub file includes metadata like process ID and\n * timestamp for validation.\n *\n * ## File Structure:\n * ```json\n * {\n * \"pid\": 12345,\n * \"timestamp\": 1699564234567,\n * \"data\": { ... }\n * }\n * ```\n *\n * ## Use Cases:\n * - Passing API tokens to child processes\n * - Transferring configuration between Socket CLI components\n * - Sharing large data that exceeds environment variable limits\n *\n * @param appName - The application identifier\n * @param data - The data to write to the stub file\n * @returns Promise resolving to the stub file path\n *\n * @example\n * ```typescript\n * const stubPath = await writeIpcStub('socket-cli', {\n * apiToken: 'secret-token',\n * config: { ... }\n * })\n * // Pass stubPath to child process for reading\n * ```\n */\nexport async function writeIpcStub(\n appName: string,\n data: unknown,\n): Promise<string> {\n const stubPath = getIpcStubPath(appName)\n await ensureIpcDirectory(stubPath)\n\n // Create stub data with validation metadata.\n const ipcData: IpcStub = {\n data,\n pid: process.pid,\n timestamp: Date.now(),\n }\n\n // Validate data structure with Zod schema.\n const validated = IpcStubSchema.parse(ipcData)\n\n // Write with pretty printing for debugging.\n await fs.writeFile(stubPath, JSON.stringify(validated, null, 2), 'utf8')\n return stubPath\n}\n\n/**\n * Read IPC data from a stub file with automatic cleanup.\n *\n * This function reads data from an IPC stub file and validates its freshness.\n * Stale files (older than 5 minutes) are automatically cleaned up to prevent\n * accumulation of temporary files.\n *\n * ## Validation Steps:\n * 1. Read and parse JSON file\n * 2. Validate structure with Zod schema\n * 3. Check timestamp freshness\n * 4. Clean up if stale\n * 5. Return data if valid\n *\n * @param stubPath - Path to the stub file to read\n * @returns Promise resolving to the data or null if invalid/stale\n *\n * @example\n * ```typescript\n * const data = await readIpcStub('/tmp/.socket-ipc/socket-cli/stub-12345.json')\n * if (data) {\n * console.log('Received:', data)\n * }\n * ```\n *\n * @unused Reserved for future implementation\n */\nexport async function readIpcStub(stubPath: string): Promise<unknown> {\n try {\n const content = await fs.readFile(stubPath, 'utf8')\n const parsed = JSON.parse(content)\n // Validate structure with Zod schema.\n const validated = IpcStubSchema.parse(parsed)\n // Check age for freshness validation.\n const ageMs = Date.now() - validated.timestamp\n // 5 minutes.\n const maxAgeMs = 5 * 60 * 1000\n if (ageMs > maxAgeMs) {\n // Clean up stale file. IPC stubs are always in tmpdir, so use force: true.\n try {\n safeDeleteSync(stubPath, { force: true })\n } catch {\n // Ignore deletion errors\n }\n return null\n }\n return validated.data\n } catch {\n // Return null for any errors (file not found, invalid JSON, validation failure).\n return null\n }\n}\n\n/**\n * Clean up IPC stub files for an application.\n *\n * This maintenance function removes stale IPC stub files to prevent\n * accumulation in the temporary directory. It's designed to be called\n * periodically or on application startup.\n *\n * ## Cleanup Rules:\n * - Files older than 5 minutes are removed (checked via both filesystem mtime and JSON timestamp)\n * - Only stub files (stub-*.json) are processed\n * - Errors are silently ignored (best-effort cleanup)\n *\n * @param appName - The application identifier\n * @returns Promise that resolves when cleanup is complete\n *\n * @example\n * ```typescript\n * // Clean up on application startup\n * await cleanupIpcStubs('socket-cli')\n * ```\n *\n * @unused Reserved for future implementation\n */\nexport async function cleanupIpcStubs(appName: string): Promise<void> {\n const tempDir = getOsTmpDir()\n const stubDir = path.join(tempDir, '.socket-ipc', appName)\n try {\n const files = await fs.readdir(stubDir)\n const now = Date.now()\n // 5 minutes.\n const maxAgeMs = 5 * 60 * 1000\n // Process each file in parallel for efficiency.\n await Promise.all(\n files.map(async file => {\n if (file.startsWith('stub-') && file.endsWith('.json')) {\n const filePath = path.join(stubDir, file)\n try {\n // Check both filesystem mtime and JSON timestamp for more reliable detection\n const stats = await fs.stat(filePath)\n const mtimeAge = now - stats.mtimeMs\n let isStale = mtimeAge > maxAgeMs\n\n // Always check the timestamp inside the JSON file for accuracy\n // This is more reliable than filesystem mtime in some environments\n try {\n const content = await fs.readFile(filePath, 'utf8')\n const parsed = JSON.parse(content)\n const validated = IpcStubSchema.parse(parsed)\n const contentAge = now - validated.timestamp\n // File is stale if EITHER check indicates staleness\n isStale = isStale || contentAge > maxAgeMs\n } catch {\n // If we can't read/parse the file, rely on mtime check\n }\n\n if (isStale) {\n // IPC stubs are always in tmpdir, so we can use force: true to skip path checks\n safeDeleteSync(filePath, { force: true })\n }\n } catch {\n // Ignore errors for individual files.\n }\n }\n }),\n )\n } catch {\n // Directory might not exist, that's ok.\n }\n}\n\n/**\n * Send data through Node.js IPC channel.\n *\n * This function sends structured messages through the Node.js IPC channel\n * when available. The IPC channel must be established with stdio: ['pipe', 'pipe', 'pipe', 'ipc'].\n *\n * ## Requirements:\n * - Process must have been spawned with IPC channel enabled\n * - Message must be serializable to JSON\n * - Process.send() must be available\n *\n * @param process - The process object with IPC channel\n * @param message - The IPC message to send\n * @returns true if message was sent, false otherwise\n *\n * @example\n * ```typescript\n * const message = createIpcMessage('handshake', { version: '1.0.0' })\n * const sent = sendIpc(childProcess, message)\n * ```\n *\n * @unused Reserved for bidirectional communication implementation\n */\nexport function sendIpc(\n process: NodeJS.Process | unknown,\n message: IpcMessage,\n): boolean {\n if (\n process &&\n typeof process === 'object' &&\n 'send' in process &&\n typeof process.send === 'function'\n ) {\n try {\n // Validate message structure before sending.\n const validated = IpcMessageSchema.parse(message)\n return process.send(validated)\n } catch {\n return false\n }\n }\n return false\n}\n\n/**\n * Receive data through Node.js IPC channel.\n *\n * Sets up a listener for IPC messages with automatic validation and parsing.\n * Returns a cleanup function to remove the listener when no longer needed.\n *\n * ## Message Flow:\n * 1. Receive raw message from IPC channel\n * 2. Validate with parseIpcMessage\n * 3. Call handler if valid\n * 4. Ignore invalid messages\n *\n * @param handler - Function to call with valid IPC messages\n * @returns Cleanup function to remove the listener\n *\n * @example\n * ```typescript\n * const cleanup = onIpc((message) => {\n * console.log('Received:', message.type, message.data)\n * })\n * // Later...\n * cleanup() // Remove listener\n * ```\n *\n * @unused Reserved for bidirectional communication\n */\nexport function onIpc(handler: (message: IpcMessage) => void): () => void {\n const listener = (message: unknown) => {\n const parsed = parseIpcMessage(message)\n if (parsed) {\n handler(parsed)\n }\n }\n process.on('message', listener)\n // Return cleanup function for proper resource management.\n return () => {\n process.off('message', listener)\n }\n}\n\n/**\n * Create a promise that resolves when a specific IPC message is received.\n *\n * This utility function provides async/await support for IPC communication,\n * allowing you to wait for specific message types with timeout support.\n *\n * ## Features:\n * - Automatic timeout handling\n * - Type-safe message data\n * - Resource cleanup on completion\n * - Promise-based API\n *\n * @param messageType - The message type to wait for\n * @param options - Options including timeout configuration\n * @returns Promise resolving to the message data\n *\n * @example\n * ```typescript\n * try {\n * const response = await waitForIpc<ConfigData>('config-response', {\n * timeout: 5000 // 5 seconds\n * })\n * console.log('Config received:', response)\n * } catch (error) {\n * console.error('Timeout waiting for config')\n * }\n * ```\n *\n * @unused Reserved for request-response pattern implementation\n */\nexport function waitForIpc<T = unknown>(\n messageType: string,\n options: IpcOptions = {},\n): Promise<T> {\n const { timeout = 30_000 } = options\n return new Promise((resolve, reject) => {\n let cleanup: (() => void) | null = null\n let timeoutId: NodeJS.Timeout | null = null\n const handleTimeout = () => {\n if (cleanup) {\n cleanup()\n }\n reject(new Error(`IPC timeout waiting for message type: ${messageType}`))\n }\n const handleMessage = (message: IpcMessage) => {\n if (message.type === messageType) {\n if (timeoutId) {\n clearTimeout(timeoutId)\n }\n if (cleanup) {\n cleanup()\n }\n resolve(message.data as T)\n }\n }\n cleanup = onIpc(handleMessage)\n if (timeout > 0) {\n timeoutId = setTimeout(handleTimeout, timeout)\n }\n })\n}\n\n/**\n * Create an IPC message with proper structure and metadata.\n *\n * This factory function creates properly structured IPC messages with:\n * - Unique ID for tracking\n * - Timestamp for freshness\n * - Type for routing\n * - Data payload\n *\n * @param type - The message type identifier\n * @param data - The message payload\n * @returns A properly structured IPC message\n *\n * @example\n * ```typescript\n * const handshake = createIpcMessage('handshake', {\n * version: '1.0.0',\n * pid: process.pid,\n * appName: 'socket-cli'\n * })\n * ```\n *\n * @unused Reserved for future message creation needs\n */\nexport function createIpcMessage<T = unknown>(\n type: string,\n data: T,\n): IpcMessage<T> {\n return {\n id: crypto.randomBytes(16).toString('hex'),\n timestamp: Date.now(),\n type,\n data,\n }\n}\n\n/**\n * Check if process has IPC channel available.\n *\n * This utility checks whether a process object has the necessary\n * properties for IPC communication. Used to determine if IPC\n * messaging is possible before attempting to send.\n *\n * @param process - The process object to check\n * @returns true if IPC is available, false otherwise\n *\n * @example\n * ```typescript\n * if (hasIpcChannel(childProcess)) {\n * sendIpc(childProcess, message)\n * } else {\n * // Fall back to alternative communication method\n * }\n * ```\n *\n * @unused Reserved for IPC availability detection\n */\nexport function hasIpcChannel(process: unknown): boolean {\n return Boolean(\n process &&\n typeof process === 'object' &&\n 'send' in process &&\n typeof process.send === 'function' &&\n 'channel' in process &&\n process.channel !== undefined,\n )\n}\n\n/**\n * Safely parse and validate IPC messages.\n *\n * This function performs runtime validation of incoming messages\n * to ensure they conform to the IPC message structure. It uses\n * Zod schemas for robust validation.\n *\n * ## Validation Steps:\n * 1. Check if message is an object\n * 2. Validate required fields exist\n * 3. Validate field types\n * 4. Return typed message or null\n *\n * @param message - The raw message to parse\n * @returns Parsed IPC message or null if invalid\n *\n * @example\n * ```typescript\n * const parsed = parseIpcMessage(rawMessage)\n * if (parsed) {\n * handleMessage(parsed)\n * }\n * ```\n *\n * @unused Reserved for message validation needs\n */\nexport function parseIpcMessage(message: unknown): IpcMessage | null {\n try {\n // Use Zod schema for comprehensive validation.\n const validated = IpcMessageSchema.parse(message)\n return validated as IpcMessage\n } catch {\n // Return null for any validation failure.\n return null\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["ipc_exports", "__export", "IpcHandshakeSchema", "cleanupIpcStubs", "createIpcChannelId", "createIpcMessage", "getIpcStubPath", "hasIpcChannel", "onIpc", "parseIpcMessage", "readIpcStub", "sendIpc", "waitForIpc", "writeIpcStub", "__toCommonJS", "import_node_crypto", "import_node_fs", "import_node_path", "import_fs", "import_paths", "import_zod", "IpcMessageSchema", "IpcStubSchema", "prefix", "crypto", "appName", "tempDir", "stubDir", "path", "ensureIpcDirectory", "filePath", "dir", "fs", "data", "stubPath", "ipcData", "validated", "content", "parsed", "ageMs", "maxAgeMs", "files", "now", "file", "stats", "isStale", "contentAge", "process", "message", "handler", "listener", "messageType", "options", "timeout", "resolve", "reject", "cleanup", "timeoutId", "handleTimeout", "type"]
7
7
  }
package/dist/logger.d.ts CHANGED
@@ -259,9 +259,10 @@ export declare class Logger {
259
259
  * This is called automatically by logging methods.
260
260
  *
261
261
  * @param value - Whether the last line was blank
262
+ * @param stream - Optional stream to update (defaults to both streams if not bound, or target stream if bound)
262
263
  * @returns The logger instance for chaining
263
264
  */
264
- [lastWasBlankSymbol](value: unknown): this;
265
+ [lastWasBlankSymbol](value: unknown, stream?: 'stderr' | 'stdout'): this;
265
266
  /**
266
267
  * Logs an assertion failure message if the value is falsy.
267
268
  *
package/dist/logger.js CHANGED
@@ -1,3 +1,3 @@
1
1
  /* Socket Lib - Built with esbuild */
2
- var O=Object.create;var g=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var A=Object.getPrototypeOf,E=Object.prototype.hasOwnProperty;var I=(e,t)=>{for(var n in t)g(e,n,{get:t[n],enumerable:!0})},b=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of P(t))!E.call(e,o)&&o!==n&&g(e,o,{get:()=>t[o],enumerable:!(s=j(t,o))||s.enumerable});return e};var _=(e,t,n)=>(n=e!=null?O(A(e)):{},b(t||!e||!e.__esModule?g(n,"default",{value:e,enumerable:!0}):n,e)),M=e=>b(g({},"__esModule",{value:!0}),e);var H={};I(H,{LOG_SYMBOLS:()=>w,Logger:()=>h,incLogCallCountSymbol:()=>u,lastWasBlankSymbol:()=>c,logger:()=>G});module.exports=M(H);var L=_(require("./external/@socketregistry/is-unicode-supported")),S=_(require("./external/yoctocolors-cjs")),f=require("./objects"),d=require("./strings");const a=console,p=Reflect.apply,W=Reflect.construct;let y;function C(...e){return y===void 0&&(y=require("node:console").Console),W(y,e)}function B(){return S.default}const w=(()=>{const e={__proto__:null},t={__proto__:null},n=()=>{const s=(0,L.default)(),o=B();(0,f.objectAssign)(e,{fail:o.red(s?"\u2716":"\xD7"),info:o.blue(s?"\u2139":"i"),success:o.green(s?"\u2714":"\u221A"),warn:o.yellow(s?"\u26A0":"\u203C")}),(0,f.objectFreeze)(e);for(const i in t)delete t[i]};for(const s of Reflect.ownKeys(Reflect)){const o=Reflect[s];typeof o=="function"&&(t[s]=(...i)=>(n(),o(...i)))}return new Proxy(e,t)})(),K=["_stderrErrorHandler","_stdoutErrorHandler","assert","clear","count","countReset","createTask","debug","dir","dirxml","error","info","log","table","time","timeEnd","timeLog","trace","warn"].filter(e=>typeof a[e]=="function").map(e=>[e,a[e].bind(a)]),x={__proto__:null,writable:!0,enumerable:!1,configurable:!0},$=1e3,r=new WeakMap,v=Object.getOwnPropertySymbols(a),u=Symbol.for("logger.logCallCount++"),k=v.find(e=>e.label==="kGroupIndentWidth")??Symbol("kGroupIndentWidth"),c=Symbol.for("logger.lastWasBlank");class h{static LOG_SYMBOLS=w;#i;#t;#c;#u;#a="";#d="";#o=!1;#l=0;#h;#e;constructor(...t){this.#h=t;const n=t[0];if(typeof n=="object"&&n!==null?this.#e={__proto__:null,...n}:this.#e={__proto__:null},t.length)r.set(this,C(...t));else{const s=C({stdout:process.stdout,stderr:process.stderr});for(const{0:o,1:i}of K)s[o]=i;r.set(this,s)}}get stderr(){if(!this.#c){const t=new h(...this.#h);t.#i=this,t.#t="stderr",t.#e={__proto__:null,...this.#e},this.#c=t}return this.#c}get stdout(){if(!this.#u){const t=new h(...this.#h);t.#i=this,t.#t="stdout",t.#e={__proto__:null,...this.#e},this.#u=t}return this.#u}#g(){return this.#i||this}#s(t){const n=this.#g();return t==="stderr"?n.#a:n.#d}#n(t,n){const s=this.#g();t==="stderr"?s.#a=n:s.#d=n}#f(){return this.#t||"stderr"}#p(t,n,s){const o=r.get(this),i=n.at(0),l=typeof i=="string",T=s||(t==="log"?"stdout":"stderr"),R=this.#s(T),m=l?[(0,d.applyLinePrefix)(i,{prefix:R}),...n.slice(1)]:n;return p(o[t],o,m),this[c](l&&(0,d.isBlankString)(m[0])),this[u](),this}#y(t){return t.replace(/^[✖✗×⚠‼✔✓√ℹ]\uFE0F?\s*/u,"")}#r(t,n){const s=r.get(this);let o=n.at(0),i;typeof o=="string"?(o=this.#y(o),i=n.slice(1)):(i=n,o="");const l=this.#s("stderr");return s.error((0,d.applyLinePrefix)(`${w[t]} ${o}`,{prefix:l}),...i),this.#o=!1,this[u](),this}get logCallCount(){return this.#l}[u](){return this.#l+=1,this}[c](t){return this.#o=!!t,this}assert(t,...n){return r.get(this).assert(t,...n),this[c](!1),t?this:this[u]()}clearVisible(){if(this.#t)throw new Error("clearVisible() is only available on the main logger instance, not on stream-bound instances");const t=r.get(this);return t.clear(),t._stdout.isTTY&&(this[c](!0),this.#l=0),this}count(t){return r.get(this).count(t),this[c](!1),this[u]()}createTask(t){return{run:n=>{this.log(`Starting task: ${t}`);const s=n();return this.log(`Completed task: ${t}`),s}}}dedent(t=2){if(this.#t){const n=this.#s(this.#t);this.#n(this.#t,n.slice(0,-t))}else{const n=this.#s("stderr"),s=this.#s("stdout");this.#n("stderr",n.slice(0,-t)),this.#n("stdout",s.slice(0,-t))}return this}dir(t,n){return r.get(this).dir(t,n),this[c](!1),this[u]()}dirxml(...t){return r.get(this).dirxml(t),this[c](!1),this[u]()}error(...t){return this.#p("error",t)}errorNewline(){return this.#o?this:this.error("")}fail(...t){return this.#r("fail",t)}group(...t){const{length:n}=t;return n&&p(this.log,this,t),this.indent(this[k]),n&&(this[c](!1),this[u]()),this}groupCollapsed(...t){return p(this.group,this,t)}groupEnd(){return this.dedent(this[k]),this}indent(t=2){const n=" ".repeat(Math.min(t,$));if(this.#t){const s=this.#s(this.#t);this.#n(this.#t,s+n)}else{const s=this.#s("stderr"),o=this.#s("stdout");this.#n("stderr",s+n),this.#n("stdout",o+n)}return this}info(...t){return this.#r("info",t)}log(...t){return this.#p("log",t)}logNewline(){return this.#o?this:this.log("")}resetIndent(){return this.#t?this.#n(this.#t,""):(this.#n("stderr",""),this.#n("stdout","")),this}step(t,...n){return this.#o||this.log(""),this.log(t,...n)}substep(t,...n){const s=` ${t}`;return this.log(s,...n)}success(...t){return this.#r("success",t)}done(...t){return this.#r("success",t)}table(t,n){return r.get(this).table(t,n),this[c](!1),this[u]()}timeEnd(t){return r.get(this).timeEnd(t),this[c](!1),this[u]()}timeLog(t,...n){return r.get(this).timeLog(t,...n),this[c](!1),this[u]()}trace(t,...n){return r.get(this).trace(t,...n),this[c](!1),this[u]()}warn(...t){return this.#r("warn",t)}write(t){return r.get(this)._stdout.write(t),this[c](!1),this}progress(t){const n=r.get(this);return(this.#f()==="stderr"?n._stderr:n._stdout).write(`\u2234 ${t}`),this[c](!1),this}clearLine(){const t=r.get(this),s=this.#f()==="stderr"?t._stderr:t._stdout;return s.isTTY?(s.cursorTo(0),s.clearLine(0)):s.write("\r\x1B[K"),this}}Object.defineProperties(h.prototype,Object.fromEntries((()=>{const e=[[k,{...x,value:2}],[Symbol.toStringTag,{__proto__:null,configurable:!0,value:"logger"}]];for(const{0:t,1:n}of Object.entries(a))if(!h.prototype[t]&&typeof n=="function"){const{[t]:s}={[t](...o){const i=r.get(this),l=i[t](...o);return l===void 0||l===i?this:l}};e.push([t,{...x,value:s}])}return e})()));const G=new h;0&&(module.exports={LOG_SYMBOLS,Logger,incLogCallCountSymbol,lastWasBlankSymbol,logger});
2
+ var O=Object.create;var g=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var A=Object.getPrototypeOf,E=Object.prototype.hasOwnProperty;var W=(e,t)=>{for(var s in t)g(e,s,{get:t[s],enumerable:!0})},_=(e,t,s,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of P(t))!E.call(e,o)&&o!==s&&g(e,o,{get:()=>t[o],enumerable:!(n=j(t,o))||n.enumerable});return e};var L=(e,t,s)=>(s=e!=null?O(A(e)):{},_(t||!e||!e.__esModule?g(s,"default",{value:e,enumerable:!0}):s,e)),B=e=>_(g({},"__esModule",{value:!0}),e);var Y={};W(Y,{LOG_SYMBOLS:()=>w,Logger:()=>h,incLogCallCountSymbol:()=>u,lastWasBlankSymbol:()=>i,logger:()=>H});module.exports=B(Y);var S=L(require("./external/@socketregistry/is-unicode-supported")),T=L(require("./external/yoctocolors-cjs")),f=require("./objects"),d=require("./strings");const a=console,p=Reflect.apply,I=Reflect.construct;let y;function C(...e){return y===void 0&&(y=require("node:console").Console),I(y,e)}function M(){return T.default}const w=(()=>{const e={__proto__:null},t={__proto__:null},s=()=>{const n=(0,S.default)(),o=M();(0,f.objectAssign)(e,{fail:o.red(n?"\u2716":"\xD7"),info:o.blue(n?"\u2139":"i"),success:o.green(n?"\u2714":"\u221A"),warn:o.yellow(n?"\u26A0":"\u203C")}),(0,f.objectFreeze)(e);for(const c in t)delete t[c]};for(const n of Reflect.ownKeys(Reflect)){const o=Reflect[n];typeof o=="function"&&(t[n]=(...c)=>(s(),o(...c)))}return new Proxy(e,t)})(),K=["_stderrErrorHandler","_stdoutErrorHandler","assert","clear","count","countReset","createTask","debug","dir","dirxml","error","info","log","table","time","timeEnd","timeLog","trace","warn"].filter(e=>typeof a[e]=="function").map(e=>[e,a[e].bind(a)]),x={__proto__:null,writable:!0,enumerable:!1,configurable:!0},$=1e3,r=new WeakMap,G=Object.getOwnPropertySymbols(a),u=Symbol.for("logger.logCallCount++"),k=G.find(e=>e.label==="kGroupIndentWidth")??Symbol("kGroupIndentWidth"),i=Symbol.for("logger.lastWasBlank");class h{static LOG_SYMBOLS=w;#c;#t;#u;#l;#g="";#f="";#p=!1;#y=!1;#h=0;#a;#e;constructor(...t){this.#a=t;const s=t[0];if(typeof s=="object"&&s!==null?this.#e={__proto__:null,...s}:this.#e={__proto__:null},t.length)r.set(this,C(...t));else{const n=C({stdout:process.stdout,stderr:process.stderr});for(const{0:o,1:c}of K)n[o]=c;r.set(this,n)}}get stderr(){if(!this.#u){const t=new h(...this.#a);t.#c=this,t.#t="stderr",t.#e={__proto__:null,...this.#e},this.#u=t}return this.#u}get stdout(){if(!this.#l){const t=new h(...this.#a);t.#c=this,t.#t="stdout",t.#e={__proto__:null,...this.#e},this.#l=t}return this.#l}#o(){return this.#c||this}#n(t){const s=this.#o();return t==="stderr"?s.#g:s.#f}#s(t,s){const n=this.#o();t==="stderr"?n.#g=s:n.#f=s}#d(t){const s=this.#o();return t==="stderr"?s.#p:s.#y}#i(t,s){const n=this.#o();t==="stderr"?n.#p=s:n.#y=s}#w(){return this.#t||"stderr"}#k(t,s,n){const o=r.get(this),c=s.at(0),l=typeof c=="string",m=n||(t==="log"?"stdout":"stderr"),R=this.#n(m),b=l?[(0,d.applyLinePrefix)(c,{prefix:R}),...s.slice(1)]:s;return p(o[t],o,b),this[i](l&&(0,d.isBlankString)(b[0]),m),this[u](),this}#m(t){return t.replace(/^[✖✗×⚠‼✔✓√ℹ]\uFE0F?\s*/u,"")}#r(t,s){const n=r.get(this);let o=s.at(0),c;typeof o=="string"?(o=this.#m(o),c=s.slice(1)):(c=s,o="");const l=this.#n("stderr");return n.error((0,d.applyLinePrefix)(`${w[t]} ${o}`,{prefix:l}),...c),this[i](!1,"stderr"),this[u](),this}get logCallCount(){return this.#o().#h}[u](){const t=this.#o();return t.#h+=1,this}[i](t,s){return s?this.#i(s,!!t):this.#t?this.#i(this.#t,!!t):(this.#i("stderr",!!t),this.#i("stdout",!!t)),this}assert(t,...s){return r.get(this).assert(t,...s),this[i](!1),t?this:this[u]()}clearVisible(){if(this.#t)throw new Error("clearVisible() is only available on the main logger instance, not on stream-bound instances");const t=r.get(this);return t.clear(),t._stdout.isTTY&&(this[i](!0),this.#h=0),this}count(t){return r.get(this).count(t),this[i](!1),this[u]()}createTask(t){return{run:s=>{this.log(`Starting task: ${t}`);const n=s();return this.log(`Completed task: ${t}`),n}}}dedent(t=2){if(this.#t){const s=this.#n(this.#t);this.#s(this.#t,s.slice(0,-t))}else{const s=this.#n("stderr"),n=this.#n("stdout");this.#s("stderr",s.slice(0,-t)),this.#s("stdout",n.slice(0,-t))}return this}dir(t,s){return r.get(this).dir(t,s),this[i](!1),this[u]()}dirxml(...t){return r.get(this).dirxml(t),this[i](!1),this[u]()}error(...t){return this.#k("error",t)}errorNewline(){return this.#d("stderr")?this:this.error("")}fail(...t){return this.#r("fail",t)}group(...t){const{length:s}=t;return s&&p(this.log,this,t),this.indent(this[k]),s&&(this[i](!1),this[u]()),this}groupCollapsed(...t){return p(this.group,this,t)}groupEnd(){return this.dedent(this[k]),this}indent(t=2){const s=" ".repeat(Math.min(t,$));if(this.#t){const n=this.#n(this.#t);this.#s(this.#t,n+s)}else{const n=this.#n("stderr"),o=this.#n("stdout");this.#s("stderr",n+s),this.#s("stdout",o+s)}return this}info(...t){return this.#r("info",t)}log(...t){return this.#k("log",t)}logNewline(){return this.#d("stdout")?this:this.log("")}resetIndent(){return this.#t?this.#s(this.#t,""):(this.#s("stderr",""),this.#s("stdout","")),this}step(t,...s){return this.#d("stdout")||this.log(""),this.log(t,...s)}substep(t,...s){const n=` ${t}`;return this.log(n,...s)}success(...t){return this.#r("success",t)}done(...t){return this.#r("success",t)}table(t,s){return r.get(this).table(t,s),this[i](!1),this[u]()}timeEnd(t){return r.get(this).timeEnd(t),this[i](!1),this[u]()}timeLog(t,...s){return r.get(this).timeLog(t,...s),this[i](!1),this[u]()}trace(t,...s){return r.get(this).trace(t,...s),this[i](!1),this[u]()}warn(...t){return this.#r("warn",t)}write(t){return r.get(this)._stdout.write(t),this[i](!1),this}progress(t){const s=r.get(this);return(this.#w()==="stderr"?s._stderr:s._stdout).write(`\u2234 ${t}`),this[i](!1),this}clearLine(){const t=r.get(this),n=this.#w()==="stderr"?t._stderr:t._stdout;return n.isTTY?(n.cursorTo(0),n.clearLine(0)):n.write("\r\x1B[K"),this}}Object.defineProperties(h.prototype,Object.fromEntries((()=>{const e=[[k,{...x,value:2}],[Symbol.toStringTag,{__proto__:null,configurable:!0,value:"logger"}]];for(const{0:t,1:s}of Object.entries(a))if(!h.prototype[t]&&typeof s=="function"){const{[t]:n}={[t](...o){const c=r.get(this),l=c[t](...o);return l===void 0||l===c?this:l}};e.push([t,{...x,value:n}])}return e})()));const H=new h;0&&(module.exports={LOG_SYMBOLS,Logger,incLogCallCountSymbol,lastWasBlankSymbol,logger});
3
3
  //# sourceMappingURL=logger.js.map