@socketsecurity/lib 1.3.4 → 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 (287) hide show
  1. package/CHANGELOG.md +103 -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/env.d.ts +67 -0
  79. package/dist/env.js +1 -1
  80. package/dist/env.js.map +3 -3
  81. package/dist/fs.d.ts +7 -0
  82. package/dist/fs.js +3 -3
  83. package/dist/fs.js.map +3 -3
  84. package/dist/github.js +1 -1
  85. package/dist/github.js.map +3 -3
  86. package/dist/globs.js +1 -1
  87. package/dist/globs.js.map +2 -2
  88. package/dist/ipc.d.ts +1 -1
  89. package/dist/ipc.js +1 -1
  90. package/dist/ipc.js.map +3 -3
  91. package/dist/logger.d.ts +2 -1
  92. package/dist/logger.js +1 -1
  93. package/dist/logger.js.map +3 -3
  94. package/dist/packages/isolation.js +1 -1
  95. package/dist/packages/isolation.js.map +3 -3
  96. package/dist/packages/normalize.js +1 -1
  97. package/dist/packages/normalize.js.map +3 -3
  98. package/dist/packages/operations.js +1 -1
  99. package/dist/packages/operations.js.map +3 -3
  100. package/dist/path.d.ts +2 -2
  101. package/dist/path.js +1 -1
  102. package/dist/path.js.map +3 -3
  103. package/dist/paths/rewire.d.ts +71 -0
  104. package/dist/paths/rewire.js +3 -0
  105. package/dist/paths/rewire.js.map +7 -0
  106. package/dist/paths.d.ts +26 -0
  107. package/dist/paths.js +1 -1
  108. package/dist/paths.js.map +3 -3
  109. package/dist/spawn.js +1 -1
  110. package/dist/spawn.js.map +3 -3
  111. package/dist/spinner.js +1 -1
  112. package/dist/spinner.js.map +2 -2
  113. package/package.json +39 -226
  114. package/dist/env/appdata.d.ts +0 -1
  115. package/dist/env/appdata.js +0 -3
  116. package/dist/env/appdata.js.map +0 -7
  117. package/dist/env/comspec.d.ts +0 -1
  118. package/dist/env/comspec.js +0 -3
  119. package/dist/env/comspec.js.map +0 -7
  120. package/dist/env/getters.d.ts +0 -40
  121. package/dist/env/getters.js +0 -3
  122. package/dist/env/getters.js.map +0 -7
  123. package/dist/env/github-api-url.d.ts +0 -1
  124. package/dist/env/github-api-url.js +0 -3
  125. package/dist/env/github-api-url.js.map +0 -7
  126. package/dist/env/github-base-ref.d.ts +0 -1
  127. package/dist/env/github-base-ref.js +0 -3
  128. package/dist/env/github-base-ref.js.map +0 -7
  129. package/dist/env/github-ref-name.d.ts +0 -1
  130. package/dist/env/github-ref-name.js +0 -3
  131. package/dist/env/github-ref-name.js.map +0 -7
  132. package/dist/env/github-ref-type.d.ts +0 -1
  133. package/dist/env/github-ref-type.js +0 -3
  134. package/dist/env/github-ref-type.js.map +0 -7
  135. package/dist/env/github-repository.d.ts +0 -1
  136. package/dist/env/github-repository.js +0 -3
  137. package/dist/env/github-repository.js.map +0 -7
  138. package/dist/env/github-server-url.d.ts +0 -1
  139. package/dist/env/github-server-url.js +0 -3
  140. package/dist/env/github-server-url.js.map +0 -7
  141. package/dist/env/github-token.d.ts +0 -1
  142. package/dist/env/github-token.js +0 -3
  143. package/dist/env/github-token.js.map +0 -7
  144. package/dist/env/jest-worker-id.d.ts +0 -1
  145. package/dist/env/jest-worker-id.js +0 -3
  146. package/dist/env/jest-worker-id.js.map +0 -7
  147. package/dist/env/lang.d.ts +0 -1
  148. package/dist/env/lang.js +0 -3
  149. package/dist/env/lang.js.map +0 -7
  150. package/dist/env/lc-all.d.ts +0 -1
  151. package/dist/env/lc-all.js +0 -3
  152. package/dist/env/lc-all.js.map +0 -7
  153. package/dist/env/lc-messages.d.ts +0 -1
  154. package/dist/env/lc-messages.js +0 -3
  155. package/dist/env/lc-messages.js.map +0 -7
  156. package/dist/env/localappdata.d.ts +0 -1
  157. package/dist/env/localappdata.js +0 -3
  158. package/dist/env/localappdata.js.map +0 -7
  159. package/dist/env/npm-config-registry.d.ts +0 -1
  160. package/dist/env/npm-config-registry.js +0 -3
  161. package/dist/env/npm-config-registry.js.map +0 -7
  162. package/dist/env/npm-config-user-agent.d.ts +0 -1
  163. package/dist/env/npm-config-user-agent.js +0 -3
  164. package/dist/env/npm-config-user-agent.js.map +0 -7
  165. package/dist/env/npm-lifecycle-event.d.ts +0 -1
  166. package/dist/env/npm-lifecycle-event.js +0 -3
  167. package/dist/env/npm-lifecycle-event.js.map +0 -7
  168. package/dist/env/npm-registry.d.ts +0 -1
  169. package/dist/env/npm-registry.js +0 -3
  170. package/dist/env/npm-registry.js.map +0 -7
  171. package/dist/env/npm-token.d.ts +0 -1
  172. package/dist/env/npm-token.js +0 -3
  173. package/dist/env/npm-token.js.map +0 -7
  174. package/dist/env/socket-accept-risks.d.ts +0 -1
  175. package/dist/env/socket-accept-risks.js +0 -3
  176. package/dist/env/socket-accept-risks.js.map +0 -7
  177. package/dist/env/socket-api-base-url.d.ts +0 -1
  178. package/dist/env/socket-api-base-url.js +0 -3
  179. package/dist/env/socket-api-base-url.js.map +0 -7
  180. package/dist/env/socket-api-proxy.d.ts +0 -1
  181. package/dist/env/socket-api-proxy.js +0 -3
  182. package/dist/env/socket-api-proxy.js.map +0 -7
  183. package/dist/env/socket-api-timeout.d.ts +0 -1
  184. package/dist/env/socket-api-timeout.js +0 -3
  185. package/dist/env/socket-api-timeout.js.map +0 -7
  186. package/dist/env/socket-api-token.d.ts +0 -1
  187. package/dist/env/socket-api-token.js +0 -3
  188. package/dist/env/socket-api-token.js.map +0 -7
  189. package/dist/env/socket-cacache-dir.d.ts +0 -1
  190. package/dist/env/socket-cacache-dir.js +0 -3
  191. package/dist/env/socket-cacache-dir.js.map +0 -7
  192. package/dist/env/socket-cli-accept-risks.d.ts +0 -1
  193. package/dist/env/socket-cli-accept-risks.js +0 -3
  194. package/dist/env/socket-cli-accept-risks.js.map +0 -7
  195. package/dist/env/socket-cli-api-base-url.d.ts +0 -1
  196. package/dist/env/socket-cli-api-base-url.js +0 -3
  197. package/dist/env/socket-cli-api-base-url.js.map +0 -7
  198. package/dist/env/socket-cli-api-proxy.d.ts +0 -1
  199. package/dist/env/socket-cli-api-proxy.js +0 -3
  200. package/dist/env/socket-cli-api-proxy.js.map +0 -7
  201. package/dist/env/socket-cli-api-timeout.d.ts +0 -1
  202. package/dist/env/socket-cli-api-timeout.js +0 -3
  203. package/dist/env/socket-cli-api-timeout.js.map +0 -7
  204. package/dist/env/socket-cli-api-token.d.ts +0 -1
  205. package/dist/env/socket-cli-api-token.js +0 -3
  206. package/dist/env/socket-cli-api-token.js.map +0 -7
  207. package/dist/env/socket-cli-config.d.ts +0 -1
  208. package/dist/env/socket-cli-config.js +0 -3
  209. package/dist/env/socket-cli-config.js.map +0 -7
  210. package/dist/env/socket-cli-fix.d.ts +0 -1
  211. package/dist/env/socket-cli-fix.js +0 -3
  212. package/dist/env/socket-cli-fix.js.map +0 -7
  213. package/dist/env/socket-cli-no-api-token.d.ts +0 -1
  214. package/dist/env/socket-cli-no-api-token.js +0 -3
  215. package/dist/env/socket-cli-no-api-token.js.map +0 -7
  216. package/dist/env/socket-cli-optimize.d.ts +0 -1
  217. package/dist/env/socket-cli-optimize.js +0 -3
  218. package/dist/env/socket-cli-optimize.js.map +0 -7
  219. package/dist/env/socket-cli-org-slug.d.ts +0 -1
  220. package/dist/env/socket-cli-org-slug.js +0 -3
  221. package/dist/env/socket-cli-org-slug.js.map +0 -7
  222. package/dist/env/socket-cli-shadow-accept-risks.d.ts +0 -1
  223. package/dist/env/socket-cli-shadow-accept-risks.js +0 -3
  224. package/dist/env/socket-cli-shadow-accept-risks.js.map +0 -7
  225. package/dist/env/socket-cli-shadow-api-token.d.ts +0 -1
  226. package/dist/env/socket-cli-shadow-api-token.js +0 -3
  227. package/dist/env/socket-cli-shadow-api-token.js.map +0 -7
  228. package/dist/env/socket-cli-shadow-bin.d.ts +0 -1
  229. package/dist/env/socket-cli-shadow-bin.js +0 -3
  230. package/dist/env/socket-cli-shadow-bin.js.map +0 -7
  231. package/dist/env/socket-cli-shadow-progress.d.ts +0 -1
  232. package/dist/env/socket-cli-shadow-progress.js +0 -3
  233. package/dist/env/socket-cli-shadow-progress.js.map +0 -7
  234. package/dist/env/socket-cli-shadow-silent.d.ts +0 -1
  235. package/dist/env/socket-cli-shadow-silent.js +0 -3
  236. package/dist/env/socket-cli-shadow-silent.js.map +0 -7
  237. package/dist/env/socket-cli-view-all-risks.d.ts +0 -1
  238. package/dist/env/socket-cli-view-all-risks.js +0 -3
  239. package/dist/env/socket-cli-view-all-risks.js.map +0 -7
  240. package/dist/env/socket-config.d.ts +0 -1
  241. package/dist/env/socket-config.js +0 -3
  242. package/dist/env/socket-config.js.map +0 -7
  243. package/dist/env/socket-debug.d.ts +0 -1
  244. package/dist/env/socket-debug.js +0 -3
  245. package/dist/env/socket-debug.js.map +0 -7
  246. package/dist/env/socket-home.d.ts +0 -1
  247. package/dist/env/socket-home.js +0 -3
  248. package/dist/env/socket-home.js.map +0 -7
  249. package/dist/env/socket-no-api-token.d.ts +0 -1
  250. package/dist/env/socket-no-api-token.js +0 -3
  251. package/dist/env/socket-no-api-token.js.map +0 -7
  252. package/dist/env/socket-npm-registry.d.ts +0 -1
  253. package/dist/env/socket-npm-registry.js +0 -3
  254. package/dist/env/socket-npm-registry.js.map +0 -7
  255. package/dist/env/socket-org-slug.d.ts +0 -1
  256. package/dist/env/socket-org-slug.js +0 -3
  257. package/dist/env/socket-org-slug.js.map +0 -7
  258. package/dist/env/socket-registry-url.d.ts +0 -1
  259. package/dist/env/socket-registry-url.js +0 -3
  260. package/dist/env/socket-registry-url.js.map +0 -7
  261. package/dist/env/socket-view-all-risks.d.ts +0 -1
  262. package/dist/env/socket-view-all-risks.js +0 -3
  263. package/dist/env/socket-view-all-risks.js.map +0 -7
  264. package/dist/env/temp.d.ts +0 -1
  265. package/dist/env/temp.js +0 -3
  266. package/dist/env/temp.js.map +0 -7
  267. package/dist/env/tmp.d.ts +0 -1
  268. package/dist/env/tmp.js +0 -3
  269. package/dist/env/tmp.js.map +0 -7
  270. package/dist/env/tmpdir.d.ts +0 -1
  271. package/dist/env/tmpdir.js +0 -3
  272. package/dist/env/tmpdir.js.map +0 -7
  273. package/dist/env/userprofile.d.ts +0 -1
  274. package/dist/env/userprofile.js +0 -3
  275. package/dist/env/userprofile.js.map +0 -7
  276. package/dist/env/vitest.d.ts +0 -1
  277. package/dist/env/vitest.js +0 -3
  278. package/dist/env/vitest.js.map +0 -7
  279. package/dist/env/xdg-cache-home.d.ts +0 -1
  280. package/dist/env/xdg-cache-home.js +0 -3
  281. package/dist/env/xdg-cache-home.js.map +0 -7
  282. package/dist/env/xdg-config-home.d.ts +0 -1
  283. package/dist/env/xdg-config-home.js +0 -3
  284. package/dist/env/xdg-config-home.js.map +0 -7
  285. package/dist/env/xdg-data-home.d.ts +0 -1
  286. package/dist/env/xdg-data-home.js +0 -3
  287. package/dist/env/xdg-data-home.js.map +0 -7
package/dist/spawn.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/spawn.ts"],
4
- "sourcesContent": ["/**\n * @fileoverview Child process spawning utilities with cross-platform support.\n * Provides enhanced spawn functionality with stdio handling and error management.\n *\n * SECURITY: Array-Based Arguments Prevent Command Injection\n *\n * This module uses array-based arguments for all command execution, which is the\n * PRIMARY DEFENSE against command injection attacks. When you pass arguments as\n * an array to spawn():\n *\n * spawn('npx', ['sfw', tool, ...args], { shell: true })\n *\n * Node.js handles escaping automatically. Each argument is passed directly to the\n * OS without shell interpretation. Shell metacharacters like ; | & $ ( ) ` are\n * treated as LITERAL STRINGS, not as commands. This approach is secure even when\n * shell: true is used on Windows for .cmd/.bat file resolution.\n *\n * UNSAFE ALTERNATIVE (not used in this codebase):\n * spawn(`npx sfw ${tool} ${args.join(' ')}`, { shell: true }) // \u2716 VULNERABLE\n *\n * String concatenation allows injection. For example, if tool = \"foo; rm -rf /\",\n * the shell would execute both commands. Array-based arguments prevent this.\n *\n * References:\n * - https://nodejs.org/api/child_process.html#child_processspawncommand-args-options\n * - https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html\n */\n\nimport { getAbortSignal, getSpinner } from '#constants/process'\n\nimport { isArray } from './arrays'\n\nconst abortSignal = getAbortSignal()\nconst spinner = getSpinner()\n\nimport { getOwn, hasOwn } from './objects'\nimport { stripAnsi } from './strings'\n\n// Define BufferEncoding type for TypeScript compatibility.\ntype BufferEncoding = globalThis.BufferEncoding\n\nconst windowsScriptExtRegExp = /\\.(?:cmd|bat|ps1)$/i\n\nlet _child_process: typeof import('node:child_process') | undefined\n/**\n * Lazily load the `child_process` module to avoid Webpack bundling issues.\n *\n * @returns The Node.js `child_process` module\n *\n * @example\n * const childProcess = getChildProcess()\n * childProcess.spawnSync('ls', ['-la'])\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getChildProcess() {\n if (_child_process === undefined) {\n // Use non-'node:' prefixed require to avoid Webpack errors.\n\n _child_process = /*@__PURE__*/ require('node:child_process')\n }\n return _child_process as typeof import('node:child_process')\n}\n\n/**\n * Options for spawning a child process with promise-based completion.\n *\n * @property {string | undefined} cwd - Current working directory for the process\n * @property {boolean | undefined} stdioString - Convert stdio output to strings (default: `true`)\n * @property {StdioType | undefined} stdio - Stdio configuration (`'pipe'`, `'ignore'`, `'inherit'`, or array)\n * @property {NodeJS.ProcessEnv | undefined} env - Environment variables for the process\n * @property {boolean | string | undefined} shell - Whether to run command in shell, or path to shell\n * @property {AbortSignal | undefined} signal - Signal to abort the process\n * @property {number | undefined} timeout - Maximum time in milliseconds before killing the process\n * @property {number | undefined} uid - User identity of the process (POSIX only)\n * @property {number | undefined} gid - Group identity of the process (POSIX only)\n */\nexport type PromiseSpawnOptions = {\n cwd?: string | undefined\n stdioString?: boolean | undefined\n stdio?: StdioType | undefined\n env?: NodeJS.ProcessEnv | undefined\n shell?: boolean | string | undefined\n signal?: AbortSignal | undefined\n timeout?: number | undefined\n uid?: number | undefined\n gid?: number | undefined\n}\n\n/**\n * Result returned by {@link spawn} when the child process completes.\n * This is a Promise that resolves with process exit information and output,\n * with additional properties for accessing the running process and stdin stream.\n *\n * @property {ChildProcessType} process - The running child process instance\n * @property {WritableStreamType | null} stdin - Writable stream for process stdin, or `null` if not piped\n *\n * @example\n * const result = spawn('echo', ['hello'])\n * result.stdin?.write('additional input\\n')\n * const { code, stdout } = await result\n * console.log(stdout) // 'hello'\n */\nexport type PromiseSpawnResult = Promise<{\n cmd: string\n args: string[] | readonly string[]\n code: number\n signal: NodeJS.Signals | null\n stdout: string | Buffer\n stderr: string | Buffer\n}> & {\n process: ChildProcessType\n stdin: WritableStreamType | null\n}\n\nlet _npmCliPromiseSpawn:\n | ((\n cmd: string,\n args: string[],\n options?: PromiseSpawnOptions | undefined,\n extra?: SpawnExtra | undefined,\n ) => PromiseSpawnResult)\n | undefined\n/**\n * Lazily load the `@npmcli/promise-spawn` module for async process spawning.\n *\n * @returns The promise-spawn module that provides Promise-based spawn functionality\n *\n * @example\n * const promiseSpawn = getNpmcliPromiseSpawn()\n * await promiseSpawn('git', ['status'])\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getNpmcliPromiseSpawn() {\n if (_npmCliPromiseSpawn === undefined) {\n _npmCliPromiseSpawn = /*@__PURE__*/ require('./external/@npmcli/promise-spawn')\n }\n return _npmCliPromiseSpawn as unknown as typeof import('@npmcli/promise-spawn')\n}\n\nlet _path: typeof import('node:path') | undefined\n/**\n * Lazily load the `path` module to avoid Webpack bundling issues.\n *\n * @returns The Node.js `path` module\n *\n * @example\n * const path = getPath()\n * const basename = path.basename('/foo/bar.txt')\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getPath() {\n if (_path === undefined) {\n // Use non-'node:' prefixed require to avoid Webpack errors.\n\n _path = /*@__PURE__*/ require('node:path')\n }\n return _path as typeof import('node:path')\n}\n\n/**\n * Error object thrown when a spawned process fails.\n * Extends the standard Error with process-specific information including exit code,\n * signal, command details, and captured output.\n *\n * @property {string[]} args - Arguments passed to the command\n * @property {string} cmd - Command that was executed\n * @property {number} code - Process exit code\n * @property {string} name - Error name (typically `'Error'`)\n * @property {string} message - Error message describing the failure\n * @property {NodeJS.Signals | null} signal - Signal that terminated the process, if any\n * @property {string} stack - Stack trace of the error\n * @property {string | Buffer} stderr - Standard error output from the process\n * @property {string | Buffer} stdout - Standard output from the process\n *\n * @example\n * try {\n * await spawn('exit', ['1'])\n * } catch (error) {\n * if (isSpawnError(error)) {\n * console.error(`Command failed with code ${error.code}`)\n * console.error(`stderr: ${error.stderr}`)\n * }\n * }\n */\nexport type SpawnError = {\n args: string[]\n cmd: string\n code: number\n name: string\n message: string\n signal: NodeJS.Signals | null\n stack: string\n stderr: string | Buffer\n stdout: string | Buffer\n}\n\n/**\n * Spawn error variant where stdout and stderr are guaranteed to be strings.\n * This type is used when `stdioString: true` is set in spawn options.\n *\n * @property {string} stdout - Standard output as a string\n * @property {string} stderr - Standard error as a string\n */\nexport type SpawnErrorWithOutputString = SpawnError & {\n stdout: string\n stderr: string\n}\n\n/**\n * Spawn error variant where stdout and stderr are guaranteed to be Buffers.\n * This type is used when `stdioString: false` is set in spawn options.\n *\n * @property {Buffer} stdout - Standard output as a Buffer\n * @property {Buffer} stderr - Standard error as a Buffer\n */\nexport type SpawnErrorWithOutputBuffer = SpawnError & {\n stdout: Buffer\n stderr: Buffer\n}\n\n/**\n * Extra options passed to the underlying promise-spawn implementation.\n * This is an open-ended object for passing additional metadata or configuration.\n */\nexport type SpawnExtra = Record<string, unknown>\n\n/**\n * Valid values for individual stdio streams.\n * - `'pipe'` - Creates a pipe between child and parent (default)\n * - `'ignore'` - Ignores the stream\n * - `'inherit'` - Uses parent's stream\n * - `'overlapped'` - Windows-specific overlapped I/O\n */\nexport type IOType = 'pipe' | 'ignore' | 'inherit' | 'overlapped'\n\n/**\n * Configuration for process stdio (stdin, stdout, stderr) streams.\n * Can be a single value applied to all streams, or an array specifying each stream individually.\n * - `'ipc'` - Creates an IPC channel for communication with the parent\n *\n * @example\n * // All streams piped\n * stdio: 'pipe'\n *\n * @example\n * // Custom configuration per stream: [stdin, stdout, stderr]\n * stdio: ['ignore', 'pipe', 'pipe']\n */\nexport type StdioType = IOType | 'ipc' | Array<IOType | 'ipc'>\n\n/**\n * Result object returned by {@link spawnSync} when the child process completes synchronously.\n *\n * @template T - Type of stdout/stderr (string or Buffer)\n * @property {number} pid - Process ID of the spawned child\n * @property {Array<T | null>} output - Array containing stdout/stderr values\n * @property {T} stdout - Standard output from the process\n * @property {T} stderr - Standard error from the process\n * @property {number | null} status - Exit code, or `null` if killed by signal\n * @property {NodeJS.Signals | null} signal - Signal that terminated the process, or `null`\n * @property {Error | undefined} error - Error object if the spawn failed\n */\nexport interface SpawnSyncReturns<T> {\n pid: number\n output: Array<T | null>\n stdout: T\n stderr: T\n status: number | null\n signal: NodeJS.Signals | null\n error?: Error | undefined\n}\n\n/**\n * Check if a value is a spawn error with expected error properties.\n * Tests for common error properties from child process failures.\n *\n * @param {unknown} value - Value to check\n * @returns {boolean} `true` if the value has spawn error properties\n *\n * @example\n * try {\n * await spawn('nonexistent-command')\n * } catch (error) {\n * if (isSpawnError(error)) {\n * console.error(`Spawn failed: ${error.code}`)\n * }\n * }\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function isSpawnError(value: unknown): value is SpawnError {\n if (value === null || typeof value !== 'object') {\n return false\n }\n // Check for spawn-specific error properties.\n const err = value as Record<string, unknown>\n return (\n (hasOwn(err, 'code') && typeof err['code'] !== 'undefined') ||\n (hasOwn(err, 'errno') && typeof err['errno'] !== 'undefined') ||\n (hasOwn(err, 'syscall') && typeof err['syscall'] === 'string')\n )\n}\n\n/**\n * Check if stdio configuration matches a specific type.\n * When called with one argument, validates if it's a valid stdio type.\n * When called with two arguments, checks if the stdio config matches the specified type.\n *\n * @param {string | string[]} stdio - Stdio configuration to check\n * @param {StdioType | undefined} type - Expected stdio type (optional)\n * @returns {boolean} `true` if stdio matches the type or is valid\n *\n * @example\n * // Check if valid stdio type\n * isStdioType('pipe') // true\n * isStdioType('invalid') // false\n *\n * @example\n * // Check if stdio matches specific type\n * isStdioType('pipe', 'pipe') // true\n * isStdioType(['pipe', 'pipe', 'pipe'], 'pipe') // true\n * isStdioType('ignore', 'pipe') // false\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function isStdioType(\n stdio: string | string[],\n type?: StdioType | undefined,\n): boolean {\n // If called with one argument, check if it's a valid stdio type.\n // biome-ignore lint/complexity/noArguments: Function overload detection for single vs two-arg calls.\n if (arguments.length === 1) {\n const validTypes = ['pipe', 'ignore', 'inherit', 'overlapped']\n return typeof stdio === 'string' && validTypes.includes(stdio)\n }\n // Original two-argument behavior.\n return (\n stdio === type ||\n ((stdio === null || stdio === undefined) && type === 'pipe') ||\n (isArray(stdio) &&\n stdio.length > 2 &&\n stdio[0] === type &&\n stdio[1] === type &&\n stdio[2] === type)\n )\n}\n\n/**\n * Strip ANSI escape codes from spawn result stdout and stderr.\n * Modifies the result object in place to remove color codes and formatting.\n *\n * @param {unknown} result - Spawn result object with stdout/stderr properties\n * @returns {unknown} The modified result object\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction stripAnsiFromSpawnResult(result: unknown): unknown {\n const res = result as {\n stdout?: string | Buffer\n stderr?: string | Buffer\n }\n const { stderr, stdout } = res\n if (typeof stdout === 'string') {\n res.stdout = stripAnsi(stdout)\n }\n if (typeof stderr === 'string') {\n res.stderr = stripAnsi(stderr)\n }\n return res\n}\n\n/*@__NO_SIDE_EFFECTS__*/\n// Duplicated from Node.js child_process.SpawnOptions\n// These are the options passed to child_process.spawn()\ninterface NodeSpawnOptions {\n cwd?: string | URL | undefined\n env?: NodeJS.ProcessEnv | undefined\n argv0?: string | undefined\n stdio?: any\n detached?: boolean | undefined\n uid?: number | undefined\n gid?: number | undefined\n serialization?: 'json' | 'advanced' | undefined\n shell?: boolean | string | undefined\n windowsVerbatimArguments?: boolean | undefined\n windowsHide?: boolean | undefined\n signal?: AbortSignal | undefined\n timeout?: number | undefined\n killSignal?: NodeJS.Signals | number | undefined\n}\n\n// Duplicated from Node.js child_process.ChildProcess\n// This represents a spawned child process\ninterface ChildProcessType {\n stdin: NodeJS.WritableStream | null\n stdout: NodeJS.ReadableStream | null\n stderr: NodeJS.ReadableStream | null\n readonly channel?: any\n readonly stdio: [\n NodeJS.WritableStream | null,\n NodeJS.ReadableStream | null,\n NodeJS.ReadableStream | null,\n NodeJS.ReadableStream | NodeJS.WritableStream | null | undefined,\n NodeJS.ReadableStream | NodeJS.WritableStream | null | undefined,\n ]\n readonly killed: boolean\n readonly pid?: number | undefined\n readonly connected: boolean\n readonly exitCode: number | null\n readonly signalCode: NodeJS.Signals | null\n readonly spawnargs: string[]\n readonly spawnfile: string\n kill(signal?: NodeJS.Signals | number): boolean\n send(message: any, callback?: (error: Error | null) => void): boolean\n send(\n message: any,\n sendHandle?: any | undefined,\n callback?: (error: Error | null) => void,\n ): boolean\n send(\n message: any,\n sendHandle?: any | undefined,\n options?: any | undefined,\n callback?: (error: Error | null) => void,\n ): boolean\n disconnect(): void\n unref(): void\n ref(): void\n}\n\n// Duplicated from Node.js stream.Writable\ninterface WritableStreamType {\n writable: boolean\n writableEnded: boolean\n writableFinished: boolean\n writableHighWaterMark: number\n writableLength: number\n writableObjectMode: boolean\n writableCorked: number\n destroyed: boolean\n write(\n chunk: any,\n encoding?: BufferEncoding | undefined,\n callback?: (error?: Error | null) => void,\n ): boolean\n write(chunk: any, callback?: (error?: Error | null) => void): boolean\n end(cb?: () => void): this\n end(chunk: any, cb?: () => void): this\n end(chunk: any, encoding?: BufferEncoding | undefined, cb?: () => void): this\n cork(): void\n uncork(): void\n destroy(error?: Error | undefined): this\n}\n\n/**\n * Options for spawning a child process with {@link spawn}.\n * Extends Node.js spawn options with additional Socket-specific functionality.\n *\n * @property {import('./spinner').Spinner | undefined} spinner - Spinner instance to pause during execution\n * @property {boolean | undefined} stdioString - Convert output to strings (default: `true`)\n * @property {boolean | undefined} stripAnsi - Remove ANSI codes from output (default: `true`)\n * @property {string | URL | undefined} cwd - Current working directory\n * @property {NodeJS.ProcessEnv | undefined} env - Environment variables\n * @property {StdioType | undefined} stdio - Stdio configuration\n * @property {boolean | string | undefined} shell - Run command in shell\n * @property {number | undefined} timeout - Timeout in milliseconds\n * @property {AbortSignal | undefined} signal - Abort signal\n * @property {number | undefined} uid - User identity (POSIX)\n * @property {number | undefined} gid - Group identity (POSIX)\n */\nexport type SpawnOptions = import('./objects').Remap<\n NodeSpawnOptions & {\n spinner?: import('./spinner').Spinner | undefined\n stdioString?: boolean\n stripAnsi?: boolean\n }\n>\nexport type SpawnResult = PromiseSpawnResult\n/**\n * Result object returned when a spawned process completes.\n *\n * @property {string} cmd - Command that was executed\n * @property {string[] | readonly string[]} args - Arguments passed to the command\n * @property {number} code - Process exit code\n * @property {NodeJS.Signals | null} signal - Signal that terminated the process, if any\n * @property {string | Buffer} stdout - Standard output (string if `stdioString: true`, Buffer otherwise)\n * @property {string | Buffer} stderr - Standard error (string if `stdioString: true`, Buffer otherwise)\n */\nexport type SpawnStdioResult = {\n cmd: string\n args: string[] | readonly string[]\n code: number\n signal: NodeJS.Signals | null\n stdout: string | Buffer\n stderr: string | Buffer\n}\n\n/**\n * Spawn a child process and return a promise that resolves when it completes.\n * Provides enhanced error handling, output capture, and cross-platform support.\n *\n * SECURITY: This function uses array-based arguments which prevent command injection.\n * Arguments in the `args` array are passed directly to the OS without shell\n * interpretation. Shell metacharacters (;|&$()`) are treated as literal strings,\n * not as commands or operators. This is the PRIMARY SECURITY DEFENSE.\n *\n * Even when shell: true is used (on Windows for .cmd/.bat execution), the array-based\n * approach remains secure because Node.js properly escapes each argument before passing\n * to the shell.\n *\n * @param {string} cmd - Command to execute (not user-controlled)\n * @param {string[] | readonly string[] | undefined} args - Array of arguments (safe even with user input)\n * @param {SpawnOptions | undefined} options - Spawn options for process configuration\n * @param {SpawnExtra | undefined} extra - Extra options for promise-spawn\n * @returns {SpawnResult} Promise that resolves with process exit information\n *\n * @throws {SpawnError} When the process exits with non-zero code or is terminated by signal\n *\n * @example\n * // Basic usage - spawn and wait for completion\n * const result = await spawn('git', ['status'])\n * console.log(result.stdout)\n *\n * @example\n * // With options - set working directory and environment\n * const result = await spawn('npm', ['install'], {\n * cwd: '/path/to/project',\n * env: { NODE_ENV: 'production' }\n * })\n *\n * @example\n * // \u2714 DO THIS - Array-based arguments (safe)\n * spawn('git', ['commit', '-m', userMessage])\n * // Each argument is properly escaped, even if userMessage = \"foo; rm -rf /\"\n *\n * @example\n * // \u2716 NEVER DO THIS - String concatenation (vulnerable)\n * spawn(`git commit -m \"${userMessage}\"`, { shell: true })\n * // Vulnerable to injection if userMessage = '\"; rm -rf / #'\n *\n * @example\n * // Access stdin for interactive processes\n * const result = spawn('cat', [])\n * result.stdin?.write('Hello\\n')\n * result.stdin?.end()\n * const { stdout } = await result\n * console.log(stdout) // 'Hello'\n *\n * @example\n * // Handle errors with exit codes\n * try {\n * await spawn('exit', ['1'])\n * } catch (error) {\n * if (isSpawnError(error)) {\n * console.error(`Failed with code ${error.code}`)\n * console.error(error.stderr)\n * }\n * }\n */\nexport function spawn(\n cmd: string,\n args?: string[] | readonly string[],\n options?: SpawnOptions | undefined,\n extra?: SpawnExtra | undefined,\n): SpawnResult {\n // Windows cmd.exe command resolution for .cmd/.bat/.ps1 files:\n //\n // When shell: true is used on Windows with script files (.cmd, .bat, .ps1),\n // cmd.exe can have issues executing full paths. The solution is to use just\n // the command basename without extension and let cmd.exe find it via PATH.\n //\n // How cmd.exe resolves commands:\n // 1. Searches current directory first\n // 2. Then searches each directory in PATH environment variable\n // 3. For each directory, tries extensions from PATHEXT (.COM, .EXE, .BAT, .CMD, etc.)\n // 4. Executes the first match found\n //\n // Example: Given 'C:\\pnpm\\pnpm.cmd' with shell: true\n // 1. Extract basename without extension: 'pnpm'\n // 2. cmd.exe searches PATH directories for 'pnpm'\n // 3. PATHEXT causes it to try 'pnpm.com', 'pnpm.exe', 'pnpm.bat', 'pnpm.cmd', etc.\n // 4. Finds and executes 'C:\\pnpm\\pnpm.cmd'\n //\n // This approach is consistent with how other tools handle Windows execution:\n // - npm's promise-spawn: uses which.sync() to find commands in PATH\n // - cross-spawn: spawns cmd.exe with escaped arguments\n // - execa: uses cross-spawn under the hood for Windows support\n //\n // See: https://github.com/nodejs/node/issues/3675\n const shell = getOwn(options, 'shell')\n // Inline WIN32 constant for coverage mode compatibility\n const WIN32 = process.platform === 'win32'\n let actualCmd = cmd\n if (WIN32 && shell && windowsScriptExtRegExp.test(actualCmd)) {\n const path = getPath()\n // Extract just the command name without path and extension.\n actualCmd = path.basename(actualCmd, path.extname(actualCmd))\n }\n const {\n spinner: optionsSpinner = spinner,\n stripAnsi: shouldStripAnsi = true,\n ...spawnOptions\n } = { __proto__: null, ...options } as SpawnOptions\n const spinnerInstance = optionsSpinner\n const { env, stdio, stdioString = true } = spawnOptions\n // The stdio option can be a string or an array.\n // https://nodejs.org/api/child_process.html#optionsstdio\n const wasSpinning = !!spinnerInstance?.isSpinning\n const shouldStopSpinner =\n wasSpinning && !isStdioType(stdio, 'ignore') && !isStdioType(stdio, 'pipe')\n const shouldRestartSpinner = shouldStopSpinner\n if (shouldStopSpinner) {\n spinnerInstance.stop()\n }\n const npmCliPromiseSpawn = getNpmcliPromiseSpawn()\n // Use __proto__: null to prevent prototype pollution when passing to\n // third-party code, Node.js built-ins, or JavaScript built-in methods.\n // https://github.com/npm/promise-spawn\n // https://github.com/nodejs/node/blob/v24.0.1/lib/child_process.js#L674-L678\n const promiseSpawnOpts = {\n __proto__: null,\n cwd: typeof spawnOptions.cwd === 'string' ? spawnOptions.cwd : undefined,\n env: {\n __proto__: null,\n ...process.env,\n ...env,\n } as unknown as NodeJS.ProcessEnv,\n signal: abortSignal,\n stdio: spawnOptions.stdio,\n stdioString,\n shell: spawnOptions.shell,\n timeout: spawnOptions.timeout,\n uid: spawnOptions.uid,\n gid: spawnOptions.gid,\n } as unknown as PromiseSpawnOptions\n const spawnPromise = npmCliPromiseSpawn(\n actualCmd,\n args ? [...args] : [],\n promiseSpawnOpts as Parameters<typeof npmCliPromiseSpawn>[2],\n extra,\n )\n const oldSpawnPromise = spawnPromise\n let newSpawnPromise: PromiseSpawnResult\n if (shouldStripAnsi && stdioString) {\n newSpawnPromise = spawnPromise\n .then(result => {\n const strippedResult = stripAnsiFromSpawnResult(result)\n // Add exitCode as an alias for code.\n if ('code' in (strippedResult as { code?: number })) {\n ;(strippedResult as { code: number; exitCode: number }).exitCode = (\n strippedResult as { code: number }\n ).code\n }\n return strippedResult\n })\n .catch(error => {\n throw stripAnsiFromSpawnResult(error)\n }) as PromiseSpawnResult\n } else {\n newSpawnPromise = spawnPromise.then(result => {\n // Add exitCode as an alias for code.\n if ('code' in result) {\n const res = result as typeof result & { exitCode: number }\n res.exitCode = result.code\n return res\n }\n return result\n }) as PromiseSpawnResult\n }\n if (shouldRestartSpinner) {\n newSpawnPromise = newSpawnPromise.finally(() => {\n spinnerInstance.start()\n }) as PromiseSpawnResult\n }\n // Copy process and stdin properties from original promise\n ;(newSpawnPromise as unknown as PromiseSpawnResult).process =\n oldSpawnPromise.process\n ;(newSpawnPromise as unknown as PromiseSpawnResult).stdin = (\n oldSpawnPromise as unknown as PromiseSpawnResult\n ).stdin\n return newSpawnPromise as SpawnResult\n}\n\n/*@__NO_SIDE_EFFECTS__*/\n/**\n * Options for synchronously spawning a child process with {@link spawnSync}.\n * Same as {@link SpawnOptions} but excludes the `spinner` property (not applicable for synchronous execution).\n */\nexport type SpawnSyncOptions = Omit<SpawnOptions, 'spinner'>\n\n/**\n * Synchronously spawn a child process and wait for it to complete.\n * Blocks execution until the process exits, returning all output and exit information.\n *\n * WARNING: This function blocks the event loop. Use {@link spawn} for async operations.\n *\n * @param {string} cmd - Command to execute\n * @param {string[] | readonly string[] | undefined} args - Array of arguments\n * @param {SpawnSyncOptions | undefined} options - Spawn options for process configuration\n * @returns {SpawnSyncReturns<string | Buffer>} Process result with exit code and captured output\n *\n * @example\n * // Basic synchronous spawn\n * const result = spawnSync('git', ['status'])\n * console.log(result.stdout)\n * console.log(result.status) // exit code\n *\n * @example\n * // With options\n * const result = spawnSync('npm', ['install'], {\n * cwd: '/path/to/project',\n * stdioString: true\n * })\n * if (result.status !== 0) {\n * console.error(result.stderr)\n * }\n *\n * @example\n * // Get raw buffer output\n * const result = spawnSync('cat', ['binary-file'], {\n * stdioString: false\n * })\n * console.log(result.stdout) // Buffer\n *\n * @example\n * // Handle process errors\n * const result = spawnSync('nonexistent-command')\n * if (result.error) {\n * console.error('Failed to spawn:', result.error)\n * }\n */\nexport function spawnSync(\n cmd: string,\n args?: string[] | readonly string[],\n options?: SpawnSyncOptions | undefined,\n): SpawnSyncReturns<string | Buffer> {\n // Windows cmd.exe command resolution for .cmd/.bat/.ps1 files:\n // See spawn() function above for detailed explanation of this approach.\n const shell = getOwn(options, 'shell')\n // Inline WIN32 constant for coverage mode compatibility\n const WIN32 = process.platform === 'win32'\n let actualCmd = cmd\n if (WIN32 && shell && windowsScriptExtRegExp.test(actualCmd)) {\n const path = getPath()\n // Extract just the command name without path and extension.\n actualCmd = path.basename(actualCmd, path.extname(actualCmd))\n }\n const { stripAnsi: shouldStripAnsi = true, ...rawSpawnOptions } = {\n __proto__: null,\n ...options,\n } as SpawnSyncOptions\n const { stdioString: rawStdioString = true } = rawSpawnOptions\n const rawEncoding = rawStdioString ? 'utf8' : 'buffer'\n const spawnOptions = {\n encoding: rawEncoding,\n ...rawSpawnOptions,\n } as NodeSpawnOptions & { encoding: BufferEncoding | 'buffer' }\n const stdioString = spawnOptions.encoding !== 'buffer'\n const result = getChildProcess().spawnSync(actualCmd, args, spawnOptions)\n if (stdioString) {\n const { stderr, stdout } = result\n if (stdout) {\n result.stdout = stdout.toString().trim()\n }\n if (stderr) {\n result.stderr = stderr.toString().trim()\n }\n }\n return (\n shouldStripAnsi && stdioString ? stripAnsiFromSpawnResult(result) : result\n ) as SpawnSyncReturns<string | Buffer>\n}\n"],
5
- "mappings": "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",
6
- "names": ["spawn_exports", "__export", "isSpawnError", "isStdioType", "spawn", "spawnSync", "__toCommonJS", "import_process", "import_arrays", "import_objects", "import_strings", "abortSignal", "spinner", "windowsScriptExtRegExp", "_child_process", "getChildProcess", "_npmCliPromiseSpawn", "getNpmcliPromiseSpawn", "_path", "getPath", "value", "err", "stdio", "type", "stripAnsiFromSpawnResult", "result", "res", "stderr", "stdout", "cmd", "args", "options", "extra", "shell", "WIN32", "actualCmd", "path", "optionsSpinner", "shouldStripAnsi", "spawnOptions", "spinnerInstance", "env", "stdioString", "shouldStopSpinner", "shouldRestartSpinner", "npmCliPromiseSpawn", "promiseSpawnOpts", "spawnPromise", "oldSpawnPromise", "newSpawnPromise", "strippedResult", "error", "rawSpawnOptions", "rawStdioString"]
4
+ "sourcesContent": ["/**\n * @fileoverview Child process spawning utilities with cross-platform support.\n * Provides enhanced spawn functionality with stdio handling and error management.\n *\n * SECURITY: Array-Based Arguments Prevent Command Injection\n *\n * This module uses array-based arguments for all command execution, which is the\n * PRIMARY DEFENSE against command injection attacks. When you pass arguments as\n * an array to spawn():\n *\n * spawn('npx', ['sfw', tool, ...args], { shell: true })\n *\n * Node.js handles escaping automatically. Each argument is passed directly to the\n * OS without shell interpretation. Shell metacharacters like ; | & $ ( ) ` are\n * treated as LITERAL STRINGS, not as commands. This approach is secure even when\n * shell: true is used on Windows for .cmd/.bat file resolution.\n *\n * UNSAFE ALTERNATIVE (not used in this codebase):\n * spawn(`npx sfw ${tool} ${args.join(' ')}`, { shell: true }) // \u2716 VULNERABLE\n *\n * String concatenation allows injection. For example, if tool = \"foo; rm -rf /\",\n * the shell would execute both commands. Array-based arguments prevent this.\n *\n * References:\n * - https://nodejs.org/api/child_process.html#child_processspawncommand-args-options\n * - https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html\n */\n\nimport { getAbortSignal, getSpinner } from '#constants/process'\n\nimport { isArray } from './arrays'\n\nconst abortSignal = getAbortSignal()\nconst spinner = getSpinner()\n\nimport { getOwn, hasOwn } from './objects'\nimport { stripAnsi } from './strings'\n\n// Define BufferEncoding type for TypeScript compatibility.\ntype BufferEncoding = globalThis.BufferEncoding\n\nconst windowsScriptExtRegExp = /\\.(?:cmd|bat|ps1)$/i\n\nlet _child_process: typeof import('node:child_process') | undefined\n/**\n * Lazily load the `child_process` module to avoid Webpack bundling issues.\n *\n * @returns The Node.js `child_process` module\n *\n * @example\n * const childProcess = getChildProcess()\n * childProcess.spawnSync('ls', ['-la'])\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getChildProcess() {\n if (_child_process === undefined) {\n // Use non-'node:' prefixed require to avoid Webpack errors.\n\n _child_process = /*@__PURE__*/ require('node:child_process')\n }\n return _child_process as typeof import('node:child_process')\n}\n\n/**\n * Options for spawning a child process with promise-based completion.\n *\n * @property {string | undefined} cwd - Current working directory for the process\n * @property {boolean | undefined} stdioString - Convert stdio output to strings (default: `true`)\n * @property {StdioType | undefined} stdio - Stdio configuration (`'pipe'`, `'ignore'`, `'inherit'`, or array)\n * @property {NodeJS.ProcessEnv | undefined} env - Environment variables for the process\n * @property {boolean | string | undefined} shell - Whether to run command in shell, or path to shell\n * @property {AbortSignal | undefined} signal - Signal to abort the process\n * @property {number | undefined} timeout - Maximum time in milliseconds before killing the process\n * @property {number | undefined} uid - User identity of the process (POSIX only)\n * @property {number | undefined} gid - Group identity of the process (POSIX only)\n */\nexport type PromiseSpawnOptions = {\n cwd?: string | undefined\n stdioString?: boolean | undefined\n stdio?: StdioType | undefined\n env?: NodeJS.ProcessEnv | undefined\n shell?: boolean | string | undefined\n signal?: AbortSignal | undefined\n timeout?: number | undefined\n uid?: number | undefined\n gid?: number | undefined\n}\n\n/**\n * Result returned by {@link spawn} when the child process completes.\n * This is a Promise that resolves with process exit information and output,\n * with additional properties for accessing the running process and stdin stream.\n *\n * @property {ChildProcessType} process - The running child process instance\n * @property {WritableStreamType | null} stdin - Writable stream for process stdin, or `null` if not piped\n *\n * @example\n * const result = spawn('echo', ['hello'])\n * result.stdin?.write('additional input\\n')\n * const { code, stdout } = await result\n * console.log(stdout) // 'hello'\n */\nexport type PromiseSpawnResult = Promise<{\n cmd: string\n args: string[] | readonly string[]\n code: number\n signal: NodeJS.Signals | null\n stdout: string | Buffer\n stderr: string | Buffer\n}> & {\n process: ChildProcessType\n stdin: WritableStreamType | null\n}\n\nlet _npmCliPromiseSpawn:\n | ((\n cmd: string,\n args: string[],\n options?: PromiseSpawnOptions | undefined,\n extra?: SpawnExtra | undefined,\n ) => PromiseSpawnResult)\n | undefined\n/**\n * Lazily load the `@npmcli/promise-spawn` module for async process spawning.\n *\n * @returns The promise-spawn module that provides Promise-based spawn functionality\n *\n * @example\n * const promiseSpawn = getNpmcliPromiseSpawn()\n * await promiseSpawn('git', ['status'])\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getNpmcliPromiseSpawn() {\n if (_npmCliPromiseSpawn === undefined) {\n _npmCliPromiseSpawn = /*@__PURE__*/ require('./external/@npmcli/promise-spawn')\n }\n return _npmCliPromiseSpawn as unknown as typeof import('@npmcli/promise-spawn')\n}\n\nlet _path: typeof import('node:path') | undefined\n/**\n * Lazily load the `path` module to avoid Webpack bundling issues.\n *\n * @returns The Node.js `path` module\n *\n * @example\n * const path = getPath()\n * const basename = path.basename('/foo/bar.txt')\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getPath() {\n if (_path === undefined) {\n // Use non-'node:' prefixed require to avoid Webpack errors.\n\n _path = /*@__PURE__*/ require('node:path')\n }\n return _path as typeof import('node:path')\n}\n\n/**\n * Error object thrown when a spawned process fails.\n * Extends the standard Error with process-specific information including exit code,\n * signal, command details, and captured output.\n *\n * @property {string[]} args - Arguments passed to the command\n * @property {string} cmd - Command that was executed\n * @property {number} code - Process exit code\n * @property {string} name - Error name (typically `'Error'`)\n * @property {string} message - Error message describing the failure\n * @property {NodeJS.Signals | null} signal - Signal that terminated the process, if any\n * @property {string} stack - Stack trace of the error\n * @property {string | Buffer} stderr - Standard error output from the process\n * @property {string | Buffer} stdout - Standard output from the process\n *\n * @example\n * try {\n * await spawn('exit', ['1'])\n * } catch (error) {\n * if (isSpawnError(error)) {\n * console.error(`Command failed with code ${error.code}`)\n * console.error(`stderr: ${error.stderr}`)\n * }\n * }\n */\nexport type SpawnError = {\n args: string[]\n cmd: string\n code: number\n name: string\n message: string\n signal: NodeJS.Signals | null\n stack: string\n stderr: string | Buffer\n stdout: string | Buffer\n}\n\n/**\n * Spawn error variant where stdout and stderr are guaranteed to be strings.\n * This type is used when `stdioString: true` is set in spawn options.\n *\n * @property {string} stdout - Standard output as a string\n * @property {string} stderr - Standard error as a string\n */\nexport type SpawnErrorWithOutputString = SpawnError & {\n stdout: string\n stderr: string\n}\n\n/**\n * Spawn error variant where stdout and stderr are guaranteed to be Buffers.\n * This type is used when `stdioString: false` is set in spawn options.\n *\n * @property {Buffer} stdout - Standard output as a Buffer\n * @property {Buffer} stderr - Standard error as a Buffer\n */\nexport type SpawnErrorWithOutputBuffer = SpawnError & {\n stdout: Buffer\n stderr: Buffer\n}\n\n/**\n * Extra options passed to the underlying promise-spawn implementation.\n * This is an open-ended object for passing additional metadata or configuration.\n */\nexport type SpawnExtra = Record<string, unknown>\n\n/**\n * Valid values for individual stdio streams.\n * - `'pipe'` - Creates a pipe between child and parent (default)\n * - `'ignore'` - Ignores the stream\n * - `'inherit'` - Uses parent's stream\n * - `'overlapped'` - Windows-specific overlapped I/O\n */\nexport type IOType = 'pipe' | 'ignore' | 'inherit' | 'overlapped'\n\n/**\n * Configuration for process stdio (stdin, stdout, stderr) streams.\n * Can be a single value applied to all streams, or an array specifying each stream individually.\n * - `'ipc'` - Creates an IPC channel for communication with the parent\n *\n * @example\n * // All streams piped\n * stdio: 'pipe'\n *\n * @example\n * // Custom configuration per stream: [stdin, stdout, stderr]\n * stdio: ['ignore', 'pipe', 'pipe']\n */\nexport type StdioType = IOType | 'ipc' | Array<IOType | 'ipc'>\n\n/**\n * Result object returned by {@link spawnSync} when the child process completes synchronously.\n *\n * @template T - Type of stdout/stderr (string or Buffer)\n * @property {number} pid - Process ID of the spawned child\n * @property {Array<T | null>} output - Array containing stdout/stderr values\n * @property {T} stdout - Standard output from the process\n * @property {T} stderr - Standard error from the process\n * @property {number | null} status - Exit code, or `null` if killed by signal\n * @property {NodeJS.Signals | null} signal - Signal that terminated the process, or `null`\n * @property {Error | undefined} error - Error object if the spawn failed\n */\nexport interface SpawnSyncReturns<T> {\n pid: number\n output: Array<T | null>\n stdout: T\n stderr: T\n status: number | null\n signal: NodeJS.Signals | null\n error?: Error | undefined\n}\n\n/**\n * Check if a value is a spawn error with expected error properties.\n * Tests for common error properties from child process failures.\n *\n * @param {unknown} value - Value to check\n * @returns {boolean} `true` if the value has spawn error properties\n *\n * @example\n * try {\n * await spawn('nonexistent-command')\n * } catch (error) {\n * if (isSpawnError(error)) {\n * console.error(`Spawn failed: ${error.code}`)\n * }\n * }\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function isSpawnError(value: unknown): value is SpawnError {\n if (value === null || typeof value !== 'object') {\n return false\n }\n // Check for spawn-specific error properties.\n const err = value as Record<string, unknown>\n return (\n (hasOwn(err, 'code') && typeof err['code'] !== 'undefined') ||\n (hasOwn(err, 'errno') && typeof err['errno'] !== 'undefined') ||\n (hasOwn(err, 'syscall') && typeof err['syscall'] === 'string')\n )\n}\n\n/**\n * Check if stdio configuration matches a specific type.\n * When called with one argument, validates if it's a valid stdio type.\n * When called with two arguments, checks if the stdio config matches the specified type.\n *\n * @param {string | string[]} stdio - Stdio configuration to check\n * @param {StdioType | undefined} type - Expected stdio type (optional)\n * @returns {boolean} `true` if stdio matches the type or is valid\n *\n * @example\n * // Check if valid stdio type\n * isStdioType('pipe') // true\n * isStdioType('invalid') // false\n *\n * @example\n * // Check if stdio matches specific type\n * isStdioType('pipe', 'pipe') // true\n * isStdioType(['pipe', 'pipe', 'pipe'], 'pipe') // true\n * isStdioType('ignore', 'pipe') // false\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function isStdioType(\n stdio: string | string[],\n type?: StdioType | undefined,\n): boolean {\n // If called with one argument, check if it's a valid stdio type.\n // biome-ignore lint/complexity/noArguments: Function overload detection for single vs two-arg calls.\n if (arguments.length === 1) {\n const validTypes = ['pipe', 'ignore', 'inherit', 'overlapped']\n return typeof stdio === 'string' && validTypes.includes(stdio)\n }\n // Original two-argument behavior.\n return (\n stdio === type ||\n ((stdio === null || stdio === undefined) && type === 'pipe') ||\n (isArray(stdio) &&\n stdio.length > 2 &&\n stdio[0] === type &&\n stdio[1] === type &&\n stdio[2] === type)\n )\n}\n\n/**\n * Strip ANSI escape codes from spawn result stdout and stderr.\n * Modifies the result object in place to remove color codes and formatting.\n *\n * @param {unknown} result - Spawn result object with stdout/stderr properties\n * @returns {unknown} The modified result object\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction stripAnsiFromSpawnResult(result: unknown): unknown {\n const res = result as {\n stdout?: string | Buffer\n stderr?: string | Buffer\n }\n const { stderr, stdout } = res\n if (typeof stdout === 'string') {\n res.stdout = stripAnsi(stdout)\n }\n if (typeof stderr === 'string') {\n res.stderr = stripAnsi(stderr)\n }\n return res\n}\n\n/*@__NO_SIDE_EFFECTS__*/\n// Duplicated from Node.js child_process.SpawnOptions\n// These are the options passed to child_process.spawn()\ninterface NodeSpawnOptions {\n cwd?: string | URL | undefined\n env?: NodeJS.ProcessEnv | undefined\n argv0?: string | undefined\n stdio?: any\n detached?: boolean | undefined\n uid?: number | undefined\n gid?: number | undefined\n serialization?: 'json' | 'advanced' | undefined\n shell?: boolean | string | undefined\n windowsVerbatimArguments?: boolean | undefined\n windowsHide?: boolean | undefined\n signal?: AbortSignal | undefined\n timeout?: number | undefined\n killSignal?: NodeJS.Signals | number | undefined\n}\n\n// Duplicated from Node.js child_process.ChildProcess\n// This represents a spawned child process\ninterface ChildProcessType {\n stdin: NodeJS.WritableStream | null\n stdout: NodeJS.ReadableStream | null\n stderr: NodeJS.ReadableStream | null\n readonly channel?: any\n readonly stdio: [\n NodeJS.WritableStream | null,\n NodeJS.ReadableStream | null,\n NodeJS.ReadableStream | null,\n NodeJS.ReadableStream | NodeJS.WritableStream | null | undefined,\n NodeJS.ReadableStream | NodeJS.WritableStream | null | undefined,\n ]\n readonly killed: boolean\n readonly pid?: number | undefined\n readonly connected: boolean\n readonly exitCode: number | null\n readonly signalCode: NodeJS.Signals | null\n readonly spawnargs: string[]\n readonly spawnfile: string\n kill(signal?: NodeJS.Signals | number): boolean\n send(message: any, callback?: (error: Error | null) => void): boolean\n send(\n message: any,\n sendHandle?: any | undefined,\n callback?: (error: Error | null) => void,\n ): boolean\n send(\n message: any,\n sendHandle?: any | undefined,\n options?: any | undefined,\n callback?: (error: Error | null) => void,\n ): boolean\n disconnect(): void\n unref(): void\n ref(): void\n}\n\n// Duplicated from Node.js stream.Writable\ninterface WritableStreamType {\n writable: boolean\n writableEnded: boolean\n writableFinished: boolean\n writableHighWaterMark: number\n writableLength: number\n writableObjectMode: boolean\n writableCorked: number\n destroyed: boolean\n write(\n chunk: any,\n encoding?: BufferEncoding | undefined,\n callback?: (error?: Error | null) => void,\n ): boolean\n write(chunk: any, callback?: (error?: Error | null) => void): boolean\n end(cb?: () => void): this\n end(chunk: any, cb?: () => void): this\n end(chunk: any, encoding?: BufferEncoding | undefined, cb?: () => void): this\n cork(): void\n uncork(): void\n destroy(error?: Error | undefined): this\n}\n\n/**\n * Options for spawning a child process with {@link spawn}.\n * Extends Node.js spawn options with additional Socket-specific functionality.\n *\n * @property {import('./spinner').Spinner | undefined} spinner - Spinner instance to pause during execution\n * @property {boolean | undefined} stdioString - Convert output to strings (default: `true`)\n * @property {boolean | undefined} stripAnsi - Remove ANSI codes from output (default: `true`)\n * @property {string | URL | undefined} cwd - Current working directory\n * @property {NodeJS.ProcessEnv | undefined} env - Environment variables\n * @property {StdioType | undefined} stdio - Stdio configuration\n * @property {boolean | string | undefined} shell - Run command in shell\n * @property {number | undefined} timeout - Timeout in milliseconds\n * @property {AbortSignal | undefined} signal - Abort signal\n * @property {number | undefined} uid - User identity (POSIX)\n * @property {number | undefined} gid - Group identity (POSIX)\n */\nexport type SpawnOptions = import('./objects').Remap<\n NodeSpawnOptions & {\n spinner?: import('./spinner').Spinner | undefined\n stdioString?: boolean\n stripAnsi?: boolean\n }\n>\nexport type SpawnResult = PromiseSpawnResult\n/**\n * Result object returned when a spawned process completes.\n *\n * @property {string} cmd - Command that was executed\n * @property {string[] | readonly string[]} args - Arguments passed to the command\n * @property {number} code - Process exit code\n * @property {NodeJS.Signals | null} signal - Signal that terminated the process, if any\n * @property {string | Buffer} stdout - Standard output (string if `stdioString: true`, Buffer otherwise)\n * @property {string | Buffer} stderr - Standard error (string if `stdioString: true`, Buffer otherwise)\n */\nexport type SpawnStdioResult = {\n cmd: string\n args: string[] | readonly string[]\n code: number\n signal: NodeJS.Signals | null\n stdout: string | Buffer\n stderr: string | Buffer\n}\n\n/**\n * Spawn a child process and return a promise that resolves when it completes.\n * Provides enhanced error handling, output capture, and cross-platform support.\n *\n * SECURITY: This function uses array-based arguments which prevent command injection.\n * Arguments in the `args` array are passed directly to the OS without shell\n * interpretation. Shell metacharacters (;|&$()`) are treated as literal strings,\n * not as commands or operators. This is the PRIMARY SECURITY DEFENSE.\n *\n * Even when shell: true is used (on Windows for .cmd/.bat execution), the array-based\n * approach remains secure because Node.js properly escapes each argument before passing\n * to the shell.\n *\n * @param {string} cmd - Command to execute (not user-controlled)\n * @param {string[] | readonly string[] | undefined} args - Array of arguments (safe even with user input)\n * @param {SpawnOptions | undefined} options - Spawn options for process configuration\n * @param {SpawnExtra | undefined} extra - Extra options for promise-spawn\n * @returns {SpawnResult} Promise that resolves with process exit information\n *\n * @throws {SpawnError} When the process exits with non-zero code or is terminated by signal\n *\n * @example\n * // Basic usage - spawn and wait for completion\n * const result = await spawn('git', ['status'])\n * console.log(result.stdout)\n *\n * @example\n * // With options - set working directory and environment\n * const result = await spawn('npm', ['install'], {\n * cwd: '/path/to/project',\n * env: { NODE_ENV: 'production' }\n * })\n *\n * @example\n * // \u2714 DO THIS - Array-based arguments (safe)\n * spawn('git', ['commit', '-m', userMessage])\n * // Each argument is properly escaped, even if userMessage = \"foo; rm -rf /\"\n *\n * @example\n * // \u2716 NEVER DO THIS - String concatenation (vulnerable)\n * spawn(`git commit -m \"${userMessage}\"`, { shell: true })\n * // Vulnerable to injection if userMessage = '\"; rm -rf / #'\n *\n * @example\n * // Access stdin for interactive processes\n * const result = spawn('cat', [])\n * result.stdin?.write('Hello\\n')\n * result.stdin?.end()\n * const { stdout } = await result\n * console.log(stdout) // 'Hello'\n *\n * @example\n * // Handle errors with exit codes\n * try {\n * await spawn('exit', ['1'])\n * } catch (error) {\n * if (isSpawnError(error)) {\n * console.error(`Failed with code ${error.code}`)\n * console.error(error.stderr)\n * }\n * }\n */\nexport function spawn(\n cmd: string,\n args?: string[] | readonly string[],\n options?: SpawnOptions | undefined,\n extra?: SpawnExtra | undefined,\n): SpawnResult {\n // Windows cmd.exe command resolution for .cmd/.bat/.ps1 files:\n //\n // When shell: true is used on Windows with script files (.cmd, .bat, .ps1),\n // cmd.exe can have issues executing full paths. The solution is to use just\n // the command basename without extension and let cmd.exe find it via PATH.\n //\n // How cmd.exe resolves commands:\n // 1. Searches current directory first\n // 2. Then searches each directory in PATH environment variable\n // 3. For each directory, tries extensions from PATHEXT (.COM, .EXE, .BAT, .CMD, etc.)\n // 4. Executes the first match found\n //\n // Example: Given 'C:\\pnpm\\pnpm.cmd' with shell: true\n // 1. Extract basename without extension: 'pnpm'\n // 2. cmd.exe searches PATH directories for 'pnpm'\n // 3. PATHEXT causes it to try 'pnpm.com', 'pnpm.exe', 'pnpm.bat', 'pnpm.cmd', etc.\n // 4. Finds and executes 'C:\\pnpm\\pnpm.cmd'\n //\n // This approach is consistent with how other tools handle Windows execution:\n // - npm's promise-spawn: uses which.sync() to find commands in PATH\n // - cross-spawn: spawns cmd.exe with escaped arguments\n // - execa: uses cross-spawn under the hood for Windows support\n //\n // See: https://github.com/nodejs/node/issues/3675\n const shell = getOwn(options, 'shell')\n // Inline WIN32 constant for coverage mode compatibility\n const WIN32 = process.platform === 'win32'\n let actualCmd = cmd\n if (WIN32 && shell && windowsScriptExtRegExp.test(actualCmd)) {\n const path = getPath()\n // Extract just the command name without path and extension.\n actualCmd = path.basename(actualCmd, path.extname(actualCmd))\n }\n const {\n spinner: optionsSpinner = spinner,\n stripAnsi: shouldStripAnsi = true,\n ...spawnOptions\n } = { __proto__: null, ...options } as SpawnOptions\n const spinnerInstance = optionsSpinner\n const { env, stdio, stdioString = true } = spawnOptions\n // The stdio option can be a string or an array.\n // https://nodejs.org/api/child_process.html#optionsstdio\n const wasSpinning = !!spinnerInstance?.isSpinning\n const shouldStopSpinner =\n wasSpinning && !isStdioType(stdio, 'ignore') && !isStdioType(stdio, 'pipe')\n const shouldRestartSpinner = shouldStopSpinner\n if (shouldStopSpinner) {\n spinnerInstance.stop()\n }\n const npmCliPromiseSpawn = getNpmcliPromiseSpawn()\n // Use __proto__: null to prevent prototype pollution when passing to\n // third-party code, Node.js built-ins, or JavaScript built-in methods.\n // https://github.com/npm/promise-spawn\n // https://github.com/nodejs/node/blob/v24.0.1/lib/child_process.js#L674-L678\n // Preserve Windows process.env Proxy behavior when no custom env is provided.\n // On Windows, process.env is a Proxy that provides case-insensitive access\n // (PATH vs Path vs path). Spreading creates a plain object that loses this.\n // Only spread when we have custom environment variables to merge.\n const envToUse = env\n ? ({\n __proto__: null,\n ...process.env,\n ...env,\n } as unknown as NodeJS.ProcessEnv)\n : process.env\n\n const promiseSpawnOpts = {\n __proto__: null,\n cwd: typeof spawnOptions.cwd === 'string' ? spawnOptions.cwd : undefined,\n env: envToUse,\n signal: abortSignal,\n stdio: spawnOptions.stdio,\n stdioString,\n shell: spawnOptions.shell,\n timeout: spawnOptions.timeout,\n uid: spawnOptions.uid,\n gid: spawnOptions.gid,\n } as unknown as PromiseSpawnOptions\n const spawnPromise = npmCliPromiseSpawn(\n actualCmd,\n args ? [...args] : [],\n promiseSpawnOpts as Parameters<typeof npmCliPromiseSpawn>[2],\n extra,\n )\n const oldSpawnPromise = spawnPromise\n let newSpawnPromise: PromiseSpawnResult\n if (shouldStripAnsi && stdioString) {\n newSpawnPromise = spawnPromise\n .then(result => {\n const strippedResult = stripAnsiFromSpawnResult(result)\n // Add exitCode as an alias for code.\n if ('code' in (strippedResult as { code?: number })) {\n ;(strippedResult as { code: number; exitCode: number }).exitCode = (\n strippedResult as { code: number }\n ).code\n }\n return strippedResult\n })\n .catch(error => {\n throw stripAnsiFromSpawnResult(error)\n }) as PromiseSpawnResult\n } else {\n newSpawnPromise = spawnPromise.then(result => {\n // Add exitCode as an alias for code.\n if ('code' in result) {\n const res = result as typeof result & { exitCode: number }\n res.exitCode = result.code\n return res\n }\n return result\n }) as PromiseSpawnResult\n }\n if (shouldRestartSpinner) {\n newSpawnPromise = newSpawnPromise.finally(() => {\n spinnerInstance.start()\n }) as PromiseSpawnResult\n }\n // Copy process and stdin properties from original promise\n ;(newSpawnPromise as unknown as PromiseSpawnResult).process =\n oldSpawnPromise.process\n ;(newSpawnPromise as unknown as PromiseSpawnResult).stdin = (\n oldSpawnPromise as unknown as PromiseSpawnResult\n ).stdin\n return newSpawnPromise as SpawnResult\n}\n\n/*@__NO_SIDE_EFFECTS__*/\n/**\n * Options for synchronously spawning a child process with {@link spawnSync}.\n * Same as {@link SpawnOptions} but excludes the `spinner` property (not applicable for synchronous execution).\n */\nexport type SpawnSyncOptions = Omit<SpawnOptions, 'spinner'>\n\n/**\n * Synchronously spawn a child process and wait for it to complete.\n * Blocks execution until the process exits, returning all output and exit information.\n *\n * WARNING: This function blocks the event loop. Use {@link spawn} for async operations.\n *\n * @param {string} cmd - Command to execute\n * @param {string[] | readonly string[] | undefined} args - Array of arguments\n * @param {SpawnSyncOptions | undefined} options - Spawn options for process configuration\n * @returns {SpawnSyncReturns<string | Buffer>} Process result with exit code and captured output\n *\n * @example\n * // Basic synchronous spawn\n * const result = spawnSync('git', ['status'])\n * console.log(result.stdout)\n * console.log(result.status) // exit code\n *\n * @example\n * // With options\n * const result = spawnSync('npm', ['install'], {\n * cwd: '/path/to/project',\n * stdioString: true\n * })\n * if (result.status !== 0) {\n * console.error(result.stderr)\n * }\n *\n * @example\n * // Get raw buffer output\n * const result = spawnSync('cat', ['binary-file'], {\n * stdioString: false\n * })\n * console.log(result.stdout) // Buffer\n *\n * @example\n * // Handle process errors\n * const result = spawnSync('nonexistent-command')\n * if (result.error) {\n * console.error('Failed to spawn:', result.error)\n * }\n */\nexport function spawnSync(\n cmd: string,\n args?: string[] | readonly string[],\n options?: SpawnSyncOptions | undefined,\n): SpawnSyncReturns<string | Buffer> {\n // Windows cmd.exe command resolution for .cmd/.bat/.ps1 files:\n // See spawn() function above for detailed explanation of this approach.\n const shell = getOwn(options, 'shell')\n // Inline WIN32 constant for coverage mode compatibility\n const WIN32 = process.platform === 'win32'\n let actualCmd = cmd\n if (WIN32 && shell && windowsScriptExtRegExp.test(actualCmd)) {\n const path = getPath()\n // Extract just the command name without path and extension.\n actualCmd = path.basename(actualCmd, path.extname(actualCmd))\n }\n const { stripAnsi: shouldStripAnsi = true, ...rawSpawnOptions } = {\n __proto__: null,\n ...options,\n } as SpawnSyncOptions\n const { stdioString: rawStdioString = true } = rawSpawnOptions\n const rawEncoding = rawStdioString ? 'utf8' : 'buffer'\n const spawnOptions = {\n encoding: rawEncoding,\n ...rawSpawnOptions,\n } as NodeSpawnOptions & { encoding: BufferEncoding | 'buffer' }\n const stdioString = spawnOptions.encoding !== 'buffer'\n const result = getChildProcess().spawnSync(actualCmd, args, spawnOptions)\n if (stdioString) {\n const { stderr, stdout } = result\n if (stdout) {\n result.stdout = stdout.toString().trim()\n }\n if (stderr) {\n result.stderr = stderr.toString().trim()\n }\n }\n return (\n shouldStripAnsi && stdioString ? stripAnsiFromSpawnResult(result) : result\n ) as SpawnSyncReturns<string | Buffer>\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["spawn_exports", "__export", "isSpawnError", "isStdioType", "spawn", "spawnSync", "__toCommonJS", "import_process", "import_arrays", "import_objects", "import_strings", "abortSignal", "spinner", "windowsScriptExtRegExp", "_child_process", "getChildProcess", "_npmCliPromiseSpawn", "getNpmcliPromiseSpawn", "_path", "getPath", "value", "err", "stdio", "type", "stripAnsiFromSpawnResult", "result", "res", "stderr", "stdout", "cmd", "args", "options", "extra", "shell", "WIN32", "actualCmd", "path", "optionsSpinner", "shouldStripAnsi", "spawnOptions", "spinnerInstance", "env", "stdioString", "shouldStopSpinner", "shouldRestartSpinner", "npmCliPromiseSpawn", "envToUse", "promiseSpawnOpts", "spawnPromise", "oldSpawnPromise", "newSpawnPromise", "strippedResult", "error", "rawSpawnOptions", "rawStdioString"]
7
7
  }
package/dist/spinner.js CHANGED
@@ -1,3 +1,3 @@
1
1
  /* Socket Lib - Built with esbuild */
2
- var W=Object.create;var S=Object.defineProperty;var q=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var Y=Object.getPrototypeOf,G=Object.prototype.hasOwnProperty;var v=(t,o)=>{for(var i in o)S(t,i,{get:o[i],enumerable:!0})},T=(t,o,i,s)=>{if(o&&typeof o=="object"||typeof o=="function")for(let d of V(o))!G.call(t,d)&&d!==i&&S(t,d,{get:()=>o[d],enumerable:!(s=q(o,d))||s.enumerable});return t};var L=(t,o,i)=>(i=t!=null?W(Y(t)):{},T(o||!t||!t.__esModule?S(i,"default",{value:t,enumerable:!0}):i,t)),M=t=>T(S({},"__esModule",{value:!0}),t);var J={};v(J,{Spinner:()=>C,ciSpinner:()=>D,getCliSpinners:()=>$,getDefaultSpinner:()=>E,spinner:()=>N,withSpinner:()=>H,withSpinnerRestore:()=>K,withSpinnerSync:()=>U});module.exports=M(J);var I=require("#env/ci"),B=require("./effects/pulse-frames"),u=require("./effects/text-shimmer"),k=L(require("./external/@socketregistry/yocto-spinner")),P=require("./objects"),b=require("./strings");const z={__proto__:null,black:[0,0,0],blue:[0,0,255],blueBright:[100,149,237],cyan:[0,255,255],cyanBright:[0,255,255],gray:[128,128,128],green:[0,128,0],greenBright:[0,255,0],magenta:[255,0,255],magentaBright:[255,105,180],red:[255,0,0],redBright:[255,69,0],white:[255,255,255],whiteBright:[255,255,255],yellow:[255,255,0],yellowBright:[255,255,153]};function x(t){return Array.isArray(t)}function y(t){return x(t)?t:z[t]}const D={frames:[""],interval:2147483647};function w(t){return{__proto__:null,configurable:!0,value:t,writable:!0}}function R(t){return typeof t=="string"?t.trimStart():""}function F(t){const{current:o,total:i,unit:s}=t,d=Math.round(o/i*100),n=j(d),e=s?`${o}/${i} ${s}`:`${o}/${i}`;return`${n} ${d}% (${e})`}function j(t,o=20){const i=Math.round(t/100*o),s=o-i,d="\u2588".repeat(i)+"\u2591".repeat(s);return require("./external/yoctocolors-cjs").cyan(d)}let m;function $(t){return m===void 0&&(m={__proto__:null,...(0,k.default)({}).constructor.spinners,socket:(0,B.generateSocketSpinnerFrames)()}),typeof t=="string"&&m?(0,P.hasOwn)(m,t)?m[t]:void 0:m}let g,A;function C(t){if(g===void 0){const s=(0,k.default)({}).constructor;g=class extends s{#o="";#i="";#t;#n;#e;constructor(n){const e={__proto__:null,...n},r=e.color??[140,82,255];if(x(r)&&(r.length!==3||!r.every(p=>typeof p=="number"&&p>=0&&p<=255)))throw new TypeError("RGB color must be an array of 3 numbers between 0 and 255");const a=y(r);let h;if(e.shimmer){let p,f,c=.3333333333333333;if(typeof e.shimmer=="string")p=e.shimmer;else{const l={__proto__:null,...e.shimmer};p=l.dir??u.DIR_LTR,f=l.color??u.COLOR_INHERIT,c=l.speed??1/3}h={__proto__:null,color:f===void 0?u.COLOR_INHERIT:f,currentDir:u.DIR_LTR,mode:p,speed:c,step:0}}super({signal:require("#constants/process").getAbortSignal(),...e,color:a,onRenderFrame:(p,f,c)=>{const O=(0,b.stringWidth)(p)===1?" ":" ";return p?`${c(p)}${O}${f}`:f},onFrameUpdate:h?()=>{this.#o&&(super.text=this.#p())}:void 0}),this.#n=h,this.#e=h}get color(){const n=super.color;return x(n)?n:y(n)}set color(n){super.color=x(n)?n:y(n)}#r(n,e){let r,a=e.at(0);typeof a=="string"?r=e.slice(1):(r=e,a="");const h=this.isSpinning,p=R(a);super[n](p);const{incLogCallCountSymbol:f,lastWasBlankSymbol:c,logger:l}=require("./logger.js");return n==="stop"?h&&p&&(l[c]((0,b.isBlankString)(p)),l[f]()):(l[c](!1),l[f]()),r.length&&(l.log(...r),l[c](!1)),this}#p(){let n=this.#o;if(this.#t){const e=F(this.#t);n=n?`${n} ${e}`:e}if(n&&this.#n){let e;this.#n.color===u.COLOR_INHERIT?e=this.color:Array.isArray(this.#n.color[0])?e=this.#n.color:e=y(this.#n.color),n=(0,u.applyShimmer)(n,this.#n,{color:e,direction:this.#n.mode})}return this.#i&&n&&(n=this.#i+n),n}#u(n,e){let r=e.at(0),a;typeof r=="string"?a=e.slice(1):(a=e,r="");const{LOG_SYMBOLS:h,logger:p}=require("./logger.js");return p.error(`${h[n]} ${r}`,...a),this}#s(){super.text=this.#p()}debug(n,...e){const{isDebug:r}=require("./debug.js");return r()?this.#u("info",[n,...e]):this}debugAndStop(n,...e){const{isDebug:r}=require("./debug.js");return r()?this.#r("info",[n,...e]):this}dedent(n){if(n===0)this.#i="";else{const e=n??2,r=Math.max(0,this.#i.length-e);this.#i=this.#i.slice(0,r)}return this.#s(),this}done(n,...e){return this.#u("success",[n,...e])}doneAndStop(n,...e){return this.#r("success",[n,...e])}fail(n,...e){return this.#u("fail",[n,...e])}failAndStop(n,...e){return this.#r("error",[n,...e])}indent(n){if(n===0)this.#i="";else{const e=n??2;this.#i+=" ".repeat(e)}return this.#s(),this}info(n,...e){return this.#u("info",[n,...e])}infoAndStop(n,...e){return this.#r("info",[n,...e])}log(...n){const{logger:e}=require("./logger.js");return e.log(...n),this}logAndStop(n,...e){return this.#r("stop",[n,...e])}progress=(n,e,r)=>(this.#t={__proto__:null,current:n,total:e,...r?{unit:r}:{}},this.#s(),this);progressStep(n=1){if(this.#t){const e=this.#t.current+n;this.#t={__proto__:null,current:Math.max(0,Math.min(e,this.#t.total)),total:this.#t.total,...this.#t.unit?{unit:this.#t.unit}:{}},this.#s()}return this}start(...n){if(n.length){const e=n.at(0),r=R(e);r?this.#o=r:(this.#o="",super.text="")}return this.#s(),this.#r("start",n)}step(n,...e){const{logger:r}=require("./logger.js");return typeof n=="string"&&(r.error(""),r.error(n,...e)),this}substep(n,...e){if(typeof n=="string"){const{logger:r}=require("./logger.js");r.error(` ${n}`,...e)}return this}stop(...n){this.#o="",this.#t=void 0,this.#n&&(this.#n.currentDir=u.DIR_LTR,this.#n.step=0);const e=this.#r("stop",n);return super.text="",e}success(n,...e){return this.#u("success",[n,...e])}successAndStop(n,...e){return this.#r("success",[n,...e])}text(n){return arguments.length===0?this.#o:(this.#o=n??"",this.#s(),this)}warn(n,...e){return this.#u("warn",[n,...e])}warnAndStop(n,...e){return this.#r("warning",[n,...e])}shimmer(n){if(n===!1)this.#n=void 0;else if(n===!0)this.#e?this.#n={...this.#e}:(this.#n={color:u.COLOR_INHERIT,currentDir:u.DIR_LTR,mode:u.DIR_LTR,speed:1/3,step:0},this.#e=this.#n);else if(typeof n=="string")this.#n?(this.#n={...this.#n,mode:n},this.#e=this.#n):this.#e?(this.#n={...this.#e,mode:n},this.#e=this.#n):(this.#n={color:u.COLOR_INHERIT,currentDir:u.DIR_LTR,mode:n,speed:1/3,step:0},this.#e=this.#n);else if(n&&typeof n=="object"){const e={__proto__:null,...n};this.#n?(this.#n={...this.#n,...e.color!==void 0?{color:e.color}:{},...e.dir!==void 0?{mode:e.dir}:{},...e.speed!==void 0?{speed:e.speed}:{}},this.#e=this.#n):this.#e?(this.#n={...this.#e,...e.color!==void 0?{color:e.color}:{},...e.dir!==void 0?{mode:e.dir}:{},...e.speed!==void 0?{speed:e.speed}:{}},this.#e=this.#n):(this.#n={color:e.color??u.COLOR_INHERIT,currentDir:u.DIR_LTR,mode:e.dir??u.DIR_LTR,speed:e.speed??1/3,step:0},this.#e=this.#n)}return this.#s(),this}},Object.defineProperties(g.prototype,{error:w(g.prototype.fail),errorAndStop:w(g.prototype.failAndStop),warning:w(g.prototype.warn),warningAndStop:w(g.prototype.warnAndStop)}),A=I.CI?D:$("socket")}return new g({spinner:A,...t})}let _;function E(){return _===void 0&&(_=C()),_}const N=(()=>{let t;return new Proxy({},{get(o,i){t===void 0&&(t=C());const s=t[i];return typeof s=="function"?s.bind(t):s}})})();async function H(t){const{message:o,operation:i,spinner:s}={__proto__:null,...t};if(!s)return await i();s.start(o);try{return await i()}finally{s.stop()}}async function K(t){const{operation:o,spinner:i,wasSpinning:s}={__proto__:null,...t};try{return await o()}finally{i&&s&&i.start()}}function U(t){const{message:o,operation:i,spinner:s}={__proto__:null,...t};if(!s)return i();s.start(o);try{return i()}finally{s.stop()}}0&&(module.exports={Spinner,ciSpinner,getCliSpinners,getDefaultSpinner,spinner,withSpinner,withSpinnerRestore,withSpinnerSync});
2
+ var W=Object.create;var S=Object.defineProperty;var q=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var Y=Object.getPrototypeOf,G=Object.prototype.hasOwnProperty;var v=(t,o)=>{for(var i in o)S(t,i,{get:o[i],enumerable:!0})},T=(t,o,i,s)=>{if(o&&typeof o=="object"||typeof o=="function")for(let d of V(o))!G.call(t,d)&&d!==i&&S(t,d,{get:()=>o[d],enumerable:!(s=q(o,d))||s.enumerable});return t};var L=(t,o,i)=>(i=t!=null?W(Y(t)):{},T(o||!t||!t.__esModule?S(i,"default",{value:t,enumerable:!0}):i,t)),M=t=>T(S({},"__esModule",{value:!0}),t);var J={};v(J,{Spinner:()=>C,ciSpinner:()=>D,getCliSpinners:()=>$,getDefaultSpinner:()=>E,spinner:()=>N,withSpinner:()=>H,withSpinnerRestore:()=>K,withSpinnerSync:()=>U});module.exports=M(J);var I=require("#env/ci"),B=require("./effects/pulse-frames"),u=require("./effects/text-shimmer"),k=L(require("./external/@socketregistry/yocto-spinner")),P=require("./objects"),b=require("./strings");const z={__proto__:null,black:[0,0,0],blue:[0,0,255],blueBright:[100,149,237],cyan:[0,255,255],cyanBright:[0,255,255],gray:[128,128,128],green:[0,128,0],greenBright:[0,255,0],magenta:[255,0,255],magentaBright:[255,105,180],red:[255,0,0],redBright:[255,69,0],white:[255,255,255],whiteBright:[255,255,255],yellow:[255,255,0],yellowBright:[255,255,153]};function x(t){return Array.isArray(t)}function y(t){return x(t)?t:z[t]}const D={frames:[""],interval:2147483647};function w(t){return{__proto__:null,configurable:!0,value:t,writable:!0}}function R(t){return typeof t=="string"?t.trimStart():""}function F(t){const{current:o,total:i,unit:s}=t,d=Math.round(o/i*100),n=j(d),e=s?`${o}/${i} ${s}`:`${o}/${i}`;return`${n} ${d}% (${e})`}function j(t,o=20){const i=Math.round(t/100*o),s=o-i,d="\u2588".repeat(i)+"\u2591".repeat(s);return require("./external/yoctocolors-cjs").cyan(d)}let m;function $(t){return m===void 0&&(m={__proto__:null,...(0,k.default)({}).constructor.spinners,socket:(0,B.generateSocketSpinnerFrames)()}),typeof t=="string"&&m?(0,P.hasOwn)(m,t)?m[t]:void 0:m}let g,A;function C(t){if(g===void 0){const s=(0,k.default)({}).constructor;g=class extends s{#o="";#i="";#t;#n;#e;constructor(n){const e={__proto__:null,...n},r=e.color??[140,82,255];if(x(r)&&(r.length!==3||!r.every(p=>typeof p=="number"&&p>=0&&p<=255)))throw new TypeError("RGB color must be an array of 3 numbers between 0 and 255");const a=y(r);let h;if(e.shimmer){let p,f,c=.3333333333333333;if(typeof e.shimmer=="string")p=e.shimmer;else{const l={__proto__:null,...e.shimmer};p=l.dir??u.DIR_LTR,f=l.color??u.COLOR_INHERIT,c=l.speed??1/3}h={__proto__:null,color:f===void 0?u.COLOR_INHERIT:f,currentDir:u.DIR_LTR,mode:p,speed:c,step:0}}super({signal:require("#constants/process").getAbortSignal(),...e,color:a,onRenderFrame:(p,f,c)=>{const O=(0,b.stringWidth)(p)===1?" ":" ";return p?`${c(p)}${O}${f}`:f},onFrameUpdate:h?()=>{this.#o&&(super.text=this.#p())}:void 0}),this.#n=h,this.#e=h}get color(){const n=super.color;return x(n)?n:y(n)}set color(n){super.color=x(n)?n:y(n)}#r(n,e){let r,a=e.at(0);typeof a=="string"?r=e.slice(1):(r=e,a="");const h=this.isSpinning,p=R(a);super[n](p);const{incLogCallCountSymbol:f,lastWasBlankSymbol:c,logger:l}=require("./logger.js");return n==="stop"?h&&p&&(l[c]((0,b.isBlankString)(p)),l[f]()):(l[c](!1),l[f]()),r.length&&(l.log(...r),l[c](!1)),this}#p(){let n=this.#o;if(this.#t){const e=F(this.#t);n=n?`${n} ${e}`:e}if(n&&this.#n){let e;this.#n.color===u.COLOR_INHERIT?e=this.color:Array.isArray(this.#n.color[0])?e=this.#n.color:e=y(this.#n.color),n=(0,u.applyShimmer)(n,this.#n,{color:e,direction:this.#n.mode})}return this.#i&&n&&(n=this.#i+n),n}#u(n,e){let r=e.at(0),a;typeof r=="string"?a=e.slice(1):(a=e,r="");const{LOG_SYMBOLS:h,logger:p}=require("./logger.js");return p.error(`${h[n]} ${r}`,...a),this}#s(){super.text=this.#p()}debug(n,...e){const{isDebug:r}=require("./debug.js");return r()?this.#u("info",[n,...e]):this}debugAndStop(n,...e){const{isDebug:r}=require("./debug.js");return r()?this.#r("info",[n,...e]):this}dedent(n){if(n===0)this.#i="";else{const e=n??2,r=Math.max(0,this.#i.length-e);this.#i=this.#i.slice(0,r)}return this.#s(),this}done(n,...e){return this.#u("success",[n,...e])}doneAndStop(n,...e){return this.#r("success",[n,...e])}fail(n,...e){return this.#u("fail",[n,...e])}failAndStop(n,...e){return this.#r("error",[n,...e])}indent(n){if(n===0)this.#i="";else{const e=n??2;this.#i+=" ".repeat(e)}return this.#s(),this}info(n,...e){return this.#u("info",[n,...e])}infoAndStop(n,...e){return this.#r("info",[n,...e])}log(...n){const{logger:e}=require("./logger.js");return e.log(...n),this}logAndStop(n,...e){return this.#r("stop",[n,...e])}progress=(n,e,r)=>(this.#t={__proto__:null,current:n,total:e,...r?{unit:r}:{}},this.#s(),this);progressStep(n=1){if(this.#t){const e=this.#t.current+n;this.#t={__proto__:null,current:Math.max(0,Math.min(e,this.#t.total)),total:this.#t.total,...this.#t.unit?{unit:this.#t.unit}:{}},this.#s()}return this}start(...n){if(n.length){const e=n.at(0),r=R(e);r?this.#o=r:(this.#o="",super.text="")}return this.#s(),this.#r("start",n)}step(n,...e){const{logger:r}=require("./logger.js");return typeof n=="string"&&(r.error(""),r.error(n,...e)),this}substep(n,...e){if(typeof n=="string"){const{logger:r}=require("./logger.js");r.error(` ${n}`,...e)}return this}stop(...n){this.#o="",this.#t=void 0,this.#n&&(this.#n.currentDir=u.DIR_LTR,this.#n.step=0);const e=this.#r("stop",n);return super.text="",e}success(n,...e){return this.#u("success",[n,...e])}successAndStop(n,...e){return this.#r("success",[n,...e])}text(n){return arguments.length===0?this.#o:(this.#o=n??"",this.#s(),this)}warn(n,...e){return this.#u("warn",[n,...e])}warnAndStop(n,...e){return this.#r("warning",[n,...e])}shimmer(n){if(n===!1)this.#n=void 0;else if(n===!0)this.#e?this.#n={...this.#e}:(this.#n={color:u.COLOR_INHERIT,currentDir:u.DIR_LTR,mode:u.DIR_LTR,speed:1/3,step:0},this.#e=this.#n);else if(typeof n=="string")this.#n?(this.#n={...this.#n,mode:n},this.#e=this.#n):this.#e?(this.#n={...this.#e,mode:n},this.#e=this.#n):(this.#n={color:u.COLOR_INHERIT,currentDir:u.DIR_LTR,mode:n,speed:1/3,step:0},this.#e=this.#n);else if(n&&typeof n=="object"){const e={__proto__:null,...n};this.#n?(this.#n={...this.#n,...e.color!==void 0?{color:e.color}:{},...e.dir!==void 0?{mode:e.dir}:{},...e.speed!==void 0?{speed:e.speed}:{}},this.#e=this.#n):this.#e?(this.#n={...this.#e,...e.color!==void 0?{color:e.color}:{},...e.dir!==void 0?{mode:e.dir}:{},...e.speed!==void 0?{speed:e.speed}:{}},this.#e=this.#n):(this.#n={color:e.color??u.COLOR_INHERIT,currentDir:u.DIR_LTR,mode:e.dir??u.DIR_LTR,speed:e.speed??1/3,step:0},this.#e=this.#n)}return this.#s(),this}},Object.defineProperties(g.prototype,{error:w(g.prototype.fail),errorAndStop:w(g.prototype.failAndStop),warning:w(g.prototype.warn),warningAndStop:w(g.prototype.warnAndStop)}),A=(0,I.getCI)()?D:$("socket")}return new g({spinner:A,...t})}let _;function E(){return _===void 0&&(_=C()),_}const N=(()=>{let t;return new Proxy({},{get(o,i){t===void 0&&(t=C());const s=t[i];return typeof s=="function"?s.bind(t):s}})})();async function H(t){const{message:o,operation:i,spinner:s}={__proto__:null,...t};if(!s)return await i();s.start(o);try{return await i()}finally{s.stop()}}async function K(t){const{operation:o,spinner:i,wasSpinning:s}={__proto__:null,...t};try{return await o()}finally{i&&s&&i.start()}}function U(t){const{message:o,operation:i,spinner:s}={__proto__:null,...t};if(!s)return i();s.start(o);try{return i()}finally{s.stop()}}0&&(module.exports={Spinner,ciSpinner,getCliSpinners,getDefaultSpinner,spinner,withSpinner,withSpinnerRestore,withSpinnerSync});
3
3
  //# sourceMappingURL=spinner.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/spinner.ts"],
4
- "sourcesContent": ["/**\n * @fileoverview CLI spinner utilities for long-running operations.\n * Provides animated progress indicators with CI environment detection.\n */\n\nimport type { Writable } from 'node:stream'\n\n// Note: getAbortSignal is imported lazily to avoid circular dependencies.\nimport { CI } from '#env/ci'\nimport { generateSocketSpinnerFrames } from './effects/pulse-frames'\nimport type {\n ShimmerColorGradient,\n ShimmerConfig,\n ShimmerDirection,\n ShimmerState,\n} from './effects/text-shimmer'\nimport { applyShimmer, COLOR_INHERIT, DIR_LTR } from './effects/text-shimmer'\nimport yoctoSpinner from './external/@socketregistry/yocto-spinner'\nimport { hasOwn } from './objects'\nimport { isBlankString, stringWidth } from './strings'\n\n/**\n * Named color values supported by the spinner.\n * Maps to standard terminal colors with bright variants.\n */\nexport type ColorName =\n | 'black'\n | 'blue'\n | 'blueBright'\n | 'cyan'\n | 'cyanBright'\n | 'gray'\n | 'green'\n | 'greenBright'\n | 'magenta'\n | 'magentaBright'\n | 'red'\n | 'redBright'\n | 'white'\n | 'whiteBright'\n | 'yellow'\n | 'yellowBright'\n\n/**\n * Special 'inherit' color value that uses the spinner's current color.\n * Used with shimmer effects to dynamically inherit the spinner color.\n */\nexport type ColorInherit = 'inherit'\n\n/**\n * RGB color tuple with values 0-255 for red, green, and blue channels.\n * @example [140, 82, 255] // Socket purple\n * @example [255, 0, 0] // Red\n */\nexport type ColorRgb = readonly [number, number, number]\n\n/**\n * Union of all supported color types: named colors or RGB tuples.\n */\nexport type ColorValue = ColorName | ColorRgb\n\n/**\n * Symbol types for status messages.\n * Maps to log symbols: success (\u2713), fail (\u2717), info (\u2139), warn (\u26A0).\n */\nexport type SymbolType = 'fail' | 'info' | 'success' | 'warn'\n\n// Map color names to RGB values.\nconst colorToRgb: Record<ColorName, ColorRgb> = {\n __proto__: null,\n black: [0, 0, 0],\n blue: [0, 0, 255],\n blueBright: [100, 149, 237],\n cyan: [0, 255, 255],\n cyanBright: [0, 255, 255],\n gray: [128, 128, 128],\n green: [0, 128, 0],\n greenBright: [0, 255, 0],\n magenta: [255, 0, 255],\n magentaBright: [255, 105, 180],\n red: [255, 0, 0],\n redBright: [255, 69, 0],\n white: [255, 255, 255],\n whiteBright: [255, 255, 255],\n yellow: [255, 255, 0],\n yellowBright: [255, 255, 153],\n} as Record<ColorName, ColorRgb>\n\n/**\n * Type guard to check if a color value is an RGB tuple.\n * @param value - Color value to check\n * @returns `true` if value is an RGB tuple, `false` if it's a color name\n */\nfunction isRgbTuple(value: ColorValue): value is ColorRgb {\n return Array.isArray(value)\n}\n\n/**\n * Convert a color value to RGB tuple format.\n * Named colors are looked up in the `colorToRgb` map, RGB tuples are returned as-is.\n * @param color - Color name or RGB tuple\n * @returns RGB tuple with values 0-255\n */\nfunction toRgb(color: ColorValue): ColorRgb {\n if (isRgbTuple(color)) {\n return color\n }\n return colorToRgb[color]\n}\n\n/**\n * Progress tracking information for display in spinner.\n * Used by `progress()` and `progressStep()` methods to show animated progress bars.\n */\nexport type ProgressInfo = {\n /** Current progress value */\n current: number\n /** Total/maximum progress value */\n total: number\n /** Optional unit label displayed after the progress count (e.g., 'files', 'items') */\n unit?: string | undefined\n}\n\n/**\n * Internal shimmer state with color configuration.\n * Extends `ShimmerState` with additional color property that can be inherited from spinner.\n */\nexport type ShimmerInfo = ShimmerState & {\n /** Color for shimmer effect - can inherit from spinner, use explicit color, or gradient */\n color: ColorInherit | ColorValue | ShimmerColorGradient\n}\n\n/**\n * Spinner instance for displaying animated loading indicators.\n * Provides methods for status updates, progress tracking, and text shimmer effects.\n *\n * KEY BEHAVIORS:\n * - Methods WITHOUT \"AndStop\" keep the spinner running (e.g., `success()`, `fail()`)\n * - Methods WITH \"AndStop\" auto-clear the spinner line (e.g., `successAndStop()`, `failAndStop()`)\n * - Status messages (done, success, fail, info, warn, step, substep) go to stderr\n * - Data messages (`log()`) go to stdout\n *\n * @example\n * ```ts\n * import { Spinner } from '@socketsecurity/registry/lib/spinner'\n *\n * const spinner = Spinner({ text: 'Loading\u2026' })\n * spinner.start()\n *\n * // Show success while continuing to spin\n * spinner.success('Step 1 complete')\n *\n * // Stop the spinner with success message\n * spinner.successAndStop('All done!')\n * ```\n */\nexport type Spinner = {\n /** Current spinner color as RGB tuple */\n color: ColorRgb\n /** Current spinner animation style */\n spinner: SpinnerStyle\n\n /** Whether spinner is currently animating */\n get isSpinning(): boolean\n\n /** Clear the current line without stopping the spinner */\n clear(): Spinner\n\n /** Show debug message without stopping (only if debug mode enabled) */\n debug(text?: string | undefined, ...extras: unknown[]): Spinner\n /** Show debug message and stop the spinner (only if debug mode enabled) */\n debugAndStop(text?: string | undefined, ...extras: unknown[]): Spinner\n\n /** Alias for `fail()` - show error without stopping */\n error(text?: string | undefined, ...extras: unknown[]): Spinner\n /** Alias for `failAndStop()` - show error and stop */\n errorAndStop(text?: string | undefined, ...extras: unknown[]): Spinner\n\n /** Show failure (\u2717) without stopping the spinner */\n fail(text?: string | undefined, ...extras: unknown[]): Spinner\n /** Show failure (\u2717) and stop the spinner, auto-clearing the line */\n failAndStop(text?: string | undefined, ...extras: unknown[]): Spinner\n\n /** Get current spinner text (getter) or set new text (setter) */\n text(value: string): Spinner\n text(): string\n\n /** Increase indentation by specified spaces (default: 2) */\n indent(spaces?: number | undefined): Spinner\n /** Decrease indentation by specified spaces (default: 2) */\n dedent(spaces?: number | undefined): Spinner\n\n /** Show info (\u2139) message without stopping the spinner */\n info(text?: string | undefined, ...extras: unknown[]): Spinner\n /** Show info (\u2139) message and stop the spinner, auto-clearing the line */\n infoAndStop(text?: string | undefined, ...extras: unknown[]): Spinner\n\n /** Log to stdout without stopping the spinner */\n log(text?: string | undefined, ...extras: unknown[]): Spinner\n /** Log and stop the spinner, auto-clearing the line */\n logAndStop(text?: string | undefined, ...extras: unknown[]): Spinner\n\n /** Start spinning with optional text */\n start(text?: string | undefined): Spinner\n /** Stop spinning and clear internal state, auto-clearing the line */\n stop(text?: string | undefined): Spinner\n /** Stop and show final text without clearing the line */\n stopAndPersist(text?: string | undefined): Spinner\n\n /** Show main step message to stderr without stopping */\n step(text?: string | undefined, ...extras: unknown[]): Spinner\n /** Show indented substep message to stderr without stopping */\n substep(text?: string | undefined, ...extras: unknown[]): Spinner\n\n /** Show success (\u2713) without stopping the spinner */\n success(text?: string | undefined, ...extras: unknown[]): Spinner\n /** Show success (\u2713) and stop the spinner, auto-clearing the line */\n successAndStop(text?: string | undefined, ...extras: unknown[]): Spinner\n\n /** Alias for `success()` - show success without stopping */\n done(text?: string | undefined, ...extras: unknown[]): Spinner\n /** Alias for `successAndStop()` - show success and stop */\n doneAndStop(text?: string | undefined, ...extras: unknown[]): Spinner\n\n /** Update progress bar with current/total values and optional unit */\n progress(current: number, total: number, unit?: string | undefined): Spinner\n /** Increment progress by specified amount (default: 1) */\n progressStep(amount?: number): Spinner\n\n /** Toggle shimmer effect on/off */\n shimmer(enabled: boolean): Spinner\n /** Update shimmer configuration or set direction */\n shimmer(config: Partial<ShimmerConfig> | ShimmerDirection): Spinner\n\n /** Show warning (\u26A0) without stopping the spinner */\n warn(text?: string | undefined, ...extras: unknown[]): Spinner\n /** Show warning (\u26A0) and stop the spinner, auto-clearing the line */\n warnAndStop(text?: string | undefined, ...extras: unknown[]): Spinner\n}\n\n/**\n * Configuration options for creating a spinner instance.\n */\nexport type SpinnerOptions = {\n /**\n * Spinner color as RGB tuple or color name.\n * @default [140, 82, 255] Socket purple\n */\n readonly color?: ColorValue | undefined\n /**\n * Shimmer effect configuration or direction string.\n * When enabled, text will have an animated shimmer effect.\n * @default undefined No shimmer effect\n */\n readonly shimmer?: ShimmerConfig | ShimmerDirection | undefined\n /**\n * Animation style with frames and timing.\n * @default 'socket' Custom Socket animation in CLI, minimal in CI\n */\n readonly spinner?: SpinnerStyle | undefined\n /**\n * Abort signal for cancelling the spinner.\n * @default getAbortSignal() from process constants\n */\n readonly signal?: AbortSignal | undefined\n /**\n * Output stream for spinner rendering.\n * @default process.stderr\n */\n readonly stream?: Writable | undefined\n /**\n * Initial text to display with the spinner.\n * @default undefined No initial text\n */\n readonly text?: string | undefined\n}\n\n/**\n * Animation style definition for spinner frames.\n * Defines the visual appearance and timing of the spinner animation.\n */\nexport type SpinnerStyle = {\n /** Array of animation frames (strings to display sequentially) */\n readonly frames: string[]\n /**\n * Milliseconds between frame changes.\n * @default 80 Standard frame rate\n */\n readonly interval?: number | undefined\n}\n\n/**\n * Minimal spinner style for CI environments.\n * Uses empty frame and max interval to effectively disable animation in CI.\n */\nexport const ciSpinner: SpinnerStyle = {\n frames: [''],\n interval: 2_147_483_647,\n}\n\n/**\n * Create a property descriptor for defining non-enumerable properties.\n * Used for adding aliased methods to the Spinner prototype.\n * @param value - Value for the property\n * @returns Property descriptor object\n * @private\n */\nfunction desc(value: unknown) {\n return {\n __proto__: null,\n configurable: true,\n value,\n writable: true,\n }\n}\n\n/**\n * Normalize text input by trimming leading whitespace.\n * Non-string values are converted to empty string.\n * @param value - Text to normalize\n * @returns Normalized string with leading whitespace removed\n * @private\n */\nfunction normalizeText(value: unknown) {\n return typeof value === 'string' ? value.trimStart() : ''\n}\n\n/**\n * Format progress information as a visual progress bar with percentage and count.\n * @param progress - Progress tracking information\n * @returns Formatted string with colored progress bar, percentage, and count\n * @private\n * @example \"\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591 35% (7/20 files)\"\n */\nfunction formatProgress(progress: ProgressInfo): string {\n const { current, total, unit } = progress\n const percentage = Math.round((current / total) * 100)\n const bar = renderProgressBar(percentage)\n const count = unit ? `${current}/${total} ${unit}` : `${current}/${total}`\n return `${bar} ${percentage}% (${count})`\n}\n\n/**\n * Render a progress bar using block characters (\u2588 for filled, \u2591 for empty).\n * @param percentage - Progress percentage (0-100)\n * @param width - Total width of progress bar in characters\n * @returns Colored progress bar string\n * @default width=20\n * @private\n */\nfunction renderProgressBar(percentage: number, width: number = 20): string {\n const filled = Math.round((percentage / 100) * width)\n const empty = width - filled\n const bar = '\u2588'.repeat(filled) + '\u2591'.repeat(empty)\n // Use cyan color for the progress bar\n const colors = /*@__PURE__*/ require('./external/yoctocolors-cjs')\n return colors.cyan(bar)\n}\n\nlet _cliSpinners: Record<string, SpinnerStyle> | undefined\n\n/**\n * Get available CLI spinner styles or a specific style by name.\n * Extends the standard cli-spinners collection with Socket custom spinners.\n *\n * Custom spinners:\n * - `socket` (default): Socket pulse animation with sparkles and lightning\n *\n * @param styleName - Optional name of specific spinner style to retrieve\n * @returns Specific spinner style if name provided, all styles if omitted, `undefined` if style not found\n * @see https://github.com/sindresorhus/cli-spinners/blob/main/spinners.json\n *\n * @example\n * ```ts\n * // Get all available spinner styles\n * const allSpinners = getCliSpinners()\n *\n * // Get specific style\n * const socketStyle = getCliSpinners('socket')\n * const dotsStyle = getCliSpinners('dots')\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function getCliSpinners(\n styleName?: string | undefined,\n): SpinnerStyle | Record<string, SpinnerStyle> | undefined {\n if (_cliSpinners === undefined) {\n const YoctoCtor = yoctoSpinner as any\n // Get the YoctoSpinner class to access static properties.\n const tempInstance = YoctoCtor({})\n const YoctoSpinnerClass = tempInstance.constructor as any\n // Extend the standard cli-spinners collection with Socket custom spinners.\n _cliSpinners = {\n __proto__: null,\n ...YoctoSpinnerClass.spinners,\n socket: generateSocketSpinnerFrames(),\n }\n }\n if (typeof styleName === 'string' && _cliSpinners) {\n return hasOwn(_cliSpinners, styleName) ? _cliSpinners[styleName] : undefined\n }\n return _cliSpinners\n}\n\nlet _Spinner: {\n new (options?: SpinnerOptions | undefined): Spinner\n}\nlet _defaultSpinner: SpinnerStyle | undefined\n\n/**\n * Create a spinner instance for displaying loading indicators.\n * Provides an animated CLI spinner with status messages, progress tracking, and shimmer effects.\n *\n * AUTO-CLEAR BEHAVIOR:\n * - All *AndStop() methods AUTO-CLEAR the spinner line via yocto-spinner.stop()\n * Examples: `doneAndStop()`, `successAndStop()`, `failAndStop()`, etc.\n *\n * - Methods WITHOUT \"AndStop\" do NOT clear (spinner keeps spinning)\n * Examples: `done()`, `success()`, `fail()`, etc.\n *\n * STREAM USAGE:\n * - Spinner animation: stderr (yocto-spinner default)\n * - Status methods (done, success, fail, info, warn, step, substep): stderr\n * - Data methods (`log()`): stdout\n *\n * COMPARISON WITH LOGGER:\n * - `logger.done()` does NOT auto-clear (requires manual `logger.clearLine()`)\n * - `spinner.doneAndStop()` DOES auto-clear (built into yocto-spinner.stop())\n * - Pattern: `logger.clearLine().done()` vs `spinner.doneAndStop()`\n *\n * @param options - Configuration options for the spinner\n * @returns New spinner instance\n *\n * @example\n * ```ts\n * import { Spinner } from '@socketsecurity/registry/lib/spinner'\n *\n * // Basic usage\n * const spinner = Spinner({ text: 'Loading data\u2026' })\n * spinner.start()\n * await fetchData()\n * spinner.successAndStop('Data loaded!')\n *\n * // With custom color\n * const spinner = Spinner({\n * text: 'Processing\u2026',\n * color: [255, 0, 0] // Red\n * })\n *\n * // With shimmer effect\n * const spinner = Spinner({\n * text: 'Building\u2026',\n * shimmer: { dir: 'ltr', speed: 0.5 }\n * })\n *\n * // Show progress\n * spinner.progress(5, 10, 'files')\n * spinner.progressStep() // Increment by 1\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function Spinner(options?: SpinnerOptions | undefined): Spinner {\n if (_Spinner === undefined) {\n const YoctoCtor = yoctoSpinner as any\n // Get the actual YoctoSpinner class from an instance\n const tempInstance = YoctoCtor({})\n const YoctoSpinnerClass = tempInstance.constructor\n\n /*@__PURE__*/\n _Spinner = class SpinnerClass extends (YoctoSpinnerClass as any) {\n declare isSpinning: boolean\n #baseText: string = ''\n #indentation: string = ''\n #progress?: ProgressInfo | undefined\n #shimmer?: ShimmerInfo | undefined\n #shimmerSavedConfig?: ShimmerInfo | undefined\n\n constructor(options?: SpinnerOptions | undefined) {\n const opts = { __proto__: null, ...options } as SpinnerOptions\n\n // Convert color option to RGB (default to Socket purple).\n const spinnerColor = opts.color ?? ([140, 82, 255] as const)\n\n // Validate RGB tuple if provided.\n if (\n isRgbTuple(spinnerColor) &&\n (spinnerColor.length !== 3 ||\n !spinnerColor.every(\n n => typeof n === 'number' && n >= 0 && n <= 255,\n ))\n ) {\n throw new TypeError(\n 'RGB color must be an array of 3 numbers between 0 and 255',\n )\n }\n\n const spinnerColorRgb = toRgb(spinnerColor)\n\n // Parse shimmer config - can be object or direction string.\n let shimmerInfo: ShimmerInfo | undefined\n if (opts.shimmer) {\n let shimmerDir: ShimmerDirection\n let shimmerColor:\n | ColorInherit\n | ColorValue\n | ShimmerColorGradient\n | undefined\n // Default: 0.33 steps per frame (~150ms per step).\n let shimmerSpeed: number = 1 / 3\n\n if (typeof opts.shimmer === 'string') {\n shimmerDir = opts.shimmer\n } else {\n const shimmerConfig = {\n __proto__: null,\n ...opts.shimmer,\n } as ShimmerConfig\n shimmerDir = shimmerConfig.dir ?? DIR_LTR\n shimmerColor = shimmerConfig.color ?? COLOR_INHERIT\n shimmerSpeed = shimmerConfig.speed ?? 1 / 3\n }\n\n // Create shimmer info with initial animation state:\n // - COLOR_INHERIT means use spinner color dynamically\n // - ColorValue (name or RGB tuple) is an explicit override color\n // - undefined color defaults to COLOR_INHERIT\n // - speed controls steps per frame (lower = slower, e.g., 0.33 = ~150ms per step)\n shimmerInfo = {\n __proto__: null,\n color: shimmerColor === undefined ? COLOR_INHERIT : shimmerColor,\n currentDir: DIR_LTR,\n mode: shimmerDir,\n speed: shimmerSpeed,\n step: 0,\n } as ShimmerInfo\n }\n\n // eslint-disable-next-line constructor-super\n super({\n signal: require('#constants/process').getAbortSignal(),\n ...opts,\n // Pass RGB color directly to yocto-spinner (it now supports RGB).\n color: spinnerColorRgb,\n // onRenderFrame callback provides full control over frame + text layout.\n // Calculates spacing based on frame width to prevent text jumping.\n onRenderFrame: (\n frame: string,\n text: string,\n applyColor: (text: string) => string,\n ) => {\n const width = stringWidth(frame)\n // Narrow frames (width 1) get 2 spaces, wide frames (width 2) get 1 space.\n // Total width is consistent: 3 characters (frame + spacing) before text.\n const spacing = width === 1 ? ' ' : ' '\n return frame ? `${applyColor(frame)}${spacing}${text}` : text\n },\n // onFrameUpdate callback is called by yocto-spinner whenever a frame advances.\n // This ensures shimmer updates are perfectly synchronized with animation beats.\n onFrameUpdate: shimmerInfo\n ? () => {\n // Update parent's text without triggering render.\n // Parent's #skipRender flag prevents nested render calls.\n // Only update if we have base text to avoid blank frames.\n if (this.#baseText) {\n super.text = this.#buildDisplayText()\n }\n }\n : undefined,\n })\n\n this.#shimmer = shimmerInfo\n this.#shimmerSavedConfig = shimmerInfo\n }\n\n // Override color getter to ensure it's always RGB.\n get color(): ColorRgb {\n const value = super.color\n return isRgbTuple(value) ? value : toRgb(value)\n }\n\n // Override color setter to always convert to RGB before passing to yocto-spinner.\n set color(value: ColorValue | ColorRgb) {\n super.color = isRgbTuple(value) ? value : toRgb(value)\n }\n\n /**\n * Apply a yocto-spinner method and update logger state.\n * Handles text normalization, extra arguments, and logger tracking.\n * @private\n */\n #apply(methodName: string, args: unknown[]) {\n let extras: unknown[]\n let text = args.at(0)\n if (typeof text === 'string') {\n extras = args.slice(1)\n } else {\n extras = args\n text = ''\n }\n const wasSpinning = this.isSpinning\n const normalized = normalizeText(text)\n super[methodName](normalized)\n const {\n incLogCallCountSymbol,\n lastWasBlankSymbol,\n logger,\n } = /*@__PURE__*/ require('./logger.js')\n if (methodName === 'stop') {\n if (wasSpinning && normalized) {\n logger[lastWasBlankSymbol](isBlankString(normalized))\n logger[incLogCallCountSymbol]()\n }\n } else {\n logger[lastWasBlankSymbol](false)\n logger[incLogCallCountSymbol]()\n }\n if (extras.length) {\n logger.log(...extras)\n logger[lastWasBlankSymbol](false)\n }\n return this\n }\n\n /**\n * Build the complete display text with progress, shimmer, and indentation.\n * Combines base text, progress bar, shimmer effects, and indentation.\n * @private\n */\n #buildDisplayText() {\n let displayText = this.#baseText\n\n if (this.#progress) {\n const progressText = formatProgress(this.#progress)\n displayText = displayText\n ? `${displayText} ${progressText}`\n : progressText\n }\n\n // Apply shimmer effect if enabled.\n if (displayText && this.#shimmer) {\n // If shimmer color is 'inherit', use current spinner color (getter ensures RGB).\n // Otherwise, check if it's a gradient (array of arrays) or single color.\n let shimmerColor: ColorRgb | ShimmerColorGradient\n if (this.#shimmer.color === COLOR_INHERIT) {\n shimmerColor = this.color\n } else if (Array.isArray(this.#shimmer.color[0])) {\n // It's a gradient - use as is.\n shimmerColor = this.#shimmer.color as ShimmerColorGradient\n } else {\n // It's a single color - convert to RGB.\n shimmerColor = toRgb(this.#shimmer.color as ColorValue)\n }\n\n displayText = applyShimmer(displayText, this.#shimmer, {\n color: shimmerColor,\n direction: this.#shimmer.mode,\n })\n }\n\n // Apply indentation\n if (this.#indentation && displayText) {\n displayText = this.#indentation + displayText\n }\n\n return displayText\n }\n\n /**\n * Show a status message without stopping the spinner.\n * Outputs the symbol and message to stderr, then continues spinning.\n */\n #showStatusAndKeepSpinning(symbolType: SymbolType, args: unknown[]) {\n let text = args.at(0)\n let extras: unknown[]\n if (typeof text === 'string') {\n extras = args.slice(1)\n } else {\n extras = args\n text = ''\n }\n\n const { LOG_SYMBOLS, logger } = /*@__PURE__*/ require('./logger.js')\n // Note: Status messages always go to stderr.\n logger.error(`${LOG_SYMBOLS[symbolType]} ${text}`, ...extras)\n return this\n }\n\n /**\n * Update the spinner's displayed text.\n * Rebuilds display text and triggers render.\n * @private\n */\n #updateSpinnerText() {\n // Call the parent class's text setter, which triggers render.\n super.text = this.#buildDisplayText()\n }\n\n /**\n * Show a debug message (\u2139) without stopping the spinner.\n * Only displays if debug mode is enabled via environment variable.\n * Outputs to stderr and continues spinning.\n *\n * @param text - Debug message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n debug(text?: string | undefined, ...extras: unknown[]) {\n const { isDebug } = /*@__PURE__*/ require('./debug.js')\n if (isDebug()) {\n return this.#showStatusAndKeepSpinning('info', [text, ...extras])\n }\n return this\n }\n\n /**\n * Show a debug message (\u2139) and stop the spinner.\n * Only displays if debug mode is enabled via environment variable.\n * Auto-clears the spinner line before displaying the message.\n *\n * @param text - Debug message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n debugAndStop(text?: string | undefined, ...extras: unknown[]) {\n const { isDebug } = /*@__PURE__*/ require('./debug.js')\n if (isDebug()) {\n return this.#apply('info', [text, ...extras])\n }\n return this\n }\n\n /**\n * Decrease indentation level by removing spaces from the left.\n * Pass 0 to reset indentation to zero completely.\n *\n * @param spaces - Number of spaces to remove\n * @returns This spinner for chaining\n * @default spaces=2\n *\n * @example\n * ```ts\n * spinner.dedent() // Remove 2 spaces\n * spinner.dedent(4) // Remove 4 spaces\n * spinner.dedent(0) // Reset to zero indentation\n * ```\n */\n dedent(spaces?: number | undefined) {\n // Pass 0 to reset indentation\n if (spaces === 0) {\n this.#indentation = ''\n } else {\n const amount = spaces ?? 2\n const newLength = Math.max(0, this.#indentation.length - amount)\n this.#indentation = this.#indentation.slice(0, newLength)\n }\n this.#updateSpinnerText()\n return this\n }\n\n /**\n * Show a done/success message (\u2713) without stopping the spinner.\n * Alias for `success()` with a shorter name.\n *\n * DESIGN DECISION: Unlike yocto-spinner, our `done()` does NOT stop the spinner.\n * Use `doneAndStop()` if you want to stop the spinner.\n *\n * @param text - Message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n done(text?: string | undefined, ...extras: unknown[]) {\n return this.#showStatusAndKeepSpinning('success', [text, ...extras])\n }\n\n /**\n * Show a done/success message (\u2713) and stop the spinner.\n * Auto-clears the spinner line before displaying the success message.\n *\n * @param text - Message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n doneAndStop(text?: string | undefined, ...extras: unknown[]) {\n return this.#apply('success', [text, ...extras])\n }\n\n /**\n * Show a failure message (\u2717) without stopping the spinner.\n * DESIGN DECISION: Unlike yocto-spinner, our `fail()` does NOT stop the spinner.\n * This allows displaying errors while continuing to spin.\n * Use `failAndStop()` if you want to stop the spinner.\n *\n * @param text - Error message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n fail(text?: string | undefined, ...extras: unknown[]) {\n return this.#showStatusAndKeepSpinning('fail', [text, ...extras])\n }\n\n /**\n * Show a failure message (\u2717) and stop the spinner.\n * Auto-clears the spinner line before displaying the error message.\n *\n * @param text - Error message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n failAndStop(text?: string | undefined, ...extras: unknown[]) {\n return this.#apply('error', [text, ...extras])\n }\n\n /**\n * Increase indentation level by adding spaces to the left.\n * Pass 0 to reset indentation to zero completely.\n *\n * @param spaces - Number of spaces to add\n * @returns This spinner for chaining\n * @default spaces=2\n *\n * @example\n * ```ts\n * spinner.indent() // Add 2 spaces\n * spinner.indent(4) // Add 4 spaces\n * spinner.indent(0) // Reset to zero indentation\n * ```\n */\n indent(spaces?: number | undefined) {\n // Pass 0 to reset indentation\n if (spaces === 0) {\n this.#indentation = ''\n } else {\n const amount = spaces ?? 2\n this.#indentation += ' '.repeat(amount)\n }\n this.#updateSpinnerText()\n return this\n }\n\n /**\n * Show an info message (\u2139) without stopping the spinner.\n * Outputs to stderr and continues spinning.\n *\n * @param text - Info message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n info(text?: string | undefined, ...extras: unknown[]) {\n return this.#showStatusAndKeepSpinning('info', [text, ...extras])\n }\n\n /**\n * Show an info message (\u2139) and stop the spinner.\n * Auto-clears the spinner line before displaying the message.\n *\n * @param text - Info message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n infoAndStop(text?: string | undefined, ...extras: unknown[]) {\n return this.#apply('info', [text, ...extras])\n }\n\n /**\n * Log a message to stdout without stopping the spinner.\n * Unlike other status methods, this outputs to stdout for data logging.\n *\n * @param args - Values to log to stdout\n * @returns This spinner for chaining\n */\n log(...args: unknown[]) {\n const { logger } = /*@__PURE__*/ require('./logger.js')\n logger.log(...args)\n return this\n }\n\n /**\n * Log a message to stdout and stop the spinner.\n * Auto-clears the spinner line before displaying the message.\n *\n * @param text - Message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n logAndStop(text?: string | undefined, ...extras: unknown[]) {\n return this.#apply('stop', [text, ...extras])\n }\n\n /**\n * Update progress information displayed with the spinner.\n * Shows a progress bar with percentage and optional unit label.\n *\n * @param current - Current progress value\n * @param total - Total/maximum progress value\n * @param unit - Optional unit label (e.g., 'files', 'items')\n * @returns This spinner for chaining\n *\n * @example\n * ```ts\n * spinner.progress(5, 10) // \"\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591 50% (5/10)\"\n * spinner.progress(7, 20, 'files') // \"\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591 35% (7/20 files)\"\n * ```\n */\n progress = (\n current: number,\n total: number,\n unit?: string | undefined,\n ) => {\n this.#progress = {\n __proto__: null,\n current,\n total,\n ...(unit ? { unit } : {}),\n } as ProgressInfo\n this.#updateSpinnerText()\n return this\n }\n\n /**\n * Increment progress by a specified amount.\n * Updates the progress bar displayed with the spinner.\n * Clamps the result between 0 and the total value.\n *\n * @param amount - Amount to increment by\n * @returns This spinner for chaining\n * @default amount=1\n *\n * @example\n * ```ts\n * spinner.progress(0, 10, 'files')\n * spinner.progressStep() // Progress: 1/10\n * spinner.progressStep(3) // Progress: 4/10\n * ```\n */\n progressStep(amount: number = 1) {\n if (this.#progress) {\n const newCurrent = this.#progress.current + amount\n this.#progress = {\n __proto__: null,\n current: Math.max(0, Math.min(newCurrent, this.#progress.total)),\n total: this.#progress.total,\n ...(this.#progress.unit ? { unit: this.#progress.unit } : {}),\n } as ProgressInfo\n this.#updateSpinnerText()\n }\n return this\n }\n\n /**\n * Start the spinner animation with optional text.\n * Begins displaying the animated spinner on stderr.\n *\n * @param text - Optional text to display with the spinner\n * @returns This spinner for chaining\n *\n * @example\n * ```ts\n * spinner.start('Loading\u2026')\n * // Later:\n * spinner.successAndStop('Done!')\n * ```\n */\n start(...args: unknown[]) {\n if (args.length) {\n const text = args.at(0)\n const normalized = normalizeText(text)\n // We clear this.text on start when `text` is falsy because yocto-spinner\n // will not clear it otherwise.\n if (!normalized) {\n this.#baseText = ''\n super.text = ''\n } else {\n this.#baseText = normalized\n }\n }\n\n this.#updateSpinnerText()\n return this.#apply('start', args)\n }\n\n /**\n * Log a main step message to stderr without stopping the spinner.\n * Adds a blank line before the message for visual separation.\n * Aligns with `logger.step()` to use stderr for status messages.\n *\n * @param text - Step message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n *\n * @example\n * ```ts\n * spinner.step('Building application')\n * spinner.substep('Compiling TypeScript')\n * spinner.substep('Bundling assets')\n * ```\n */\n step(text?: string | undefined, ...extras: unknown[]) {\n const { logger } = /*@__PURE__*/ require('./logger.js')\n if (typeof text === 'string') {\n // Add blank line before step for visual separation.\n logger.error('')\n // Use error (stderr) to align with logger.step() default stream.\n logger.error(text, ...extras)\n }\n return this\n }\n\n /**\n * Log an indented substep message to stderr without stopping the spinner.\n * Adds 2-space indentation to the message.\n * Aligns with `logger.substep()` to use stderr for status messages.\n *\n * @param text - Substep message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n *\n * @example\n * ```ts\n * spinner.step('Building application')\n * spinner.substep('Compiling TypeScript')\n * spinner.substep('Bundling assets')\n * ```\n */\n substep(text?: string | undefined, ...extras: unknown[]) {\n if (typeof text === 'string') {\n // Add 2-space indent for substep.\n const { logger } = /*@__PURE__*/ require('./logger.js')\n // Use error (stderr) to align with logger.substep() default stream.\n logger.error(` ${text}`, ...extras)\n }\n return this\n }\n\n /**\n * Stop the spinner animation and clear internal state.\n * Auto-clears the spinner line via yocto-spinner.stop().\n * Resets progress, shimmer, and text state.\n *\n * @param text - Optional final text to display after stopping\n * @returns This spinner for chaining\n *\n * @example\n * ```ts\n * spinner.start('Processing\u2026')\n * // Do work\n * spinner.stop() // Just stop, no message\n * // or\n * spinner.stop('Finished processing')\n * ```\n */\n stop(...args: unknown[]) {\n // Clear internal state.\n this.#baseText = ''\n this.#progress = undefined\n // Reset shimmer animation state if shimmer is enabled.\n if (this.#shimmer) {\n this.#shimmer.currentDir = DIR_LTR\n this.#shimmer.step = 0\n }\n // Call parent stop first (clears screen, sets isSpinning = false).\n const result = this.#apply('stop', args)\n // Then clear text to avoid blank frame render.\n // This is safe now because isSpinning is false.\n super.text = ''\n return result\n }\n\n /**\n * Show a success message (\u2713) without stopping the spinner.\n * DESIGN DECISION: Unlike yocto-spinner, our `success()` does NOT stop the spinner.\n * This allows displaying success messages while continuing to spin for multi-step operations.\n * Use `successAndStop()` if you want to stop the spinner.\n *\n * @param text - Success message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n success(text?: string | undefined, ...extras: unknown[]) {\n return this.#showStatusAndKeepSpinning('success', [text, ...extras])\n }\n\n /**\n * Show a success message (\u2713) and stop the spinner.\n * Auto-clears the spinner line before displaying the success message.\n *\n * @param text - Success message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n successAndStop(text?: string | undefined, ...extras: unknown[]) {\n return this.#apply('success', [text, ...extras])\n }\n\n /**\n * Get or set the spinner text.\n * When called with no arguments, returns the current base text.\n * When called with text, updates the display and returns the spinner for chaining.\n *\n * @param value - Text to display (omit to get current text)\n * @returns Current text (getter) or this spinner (setter)\n *\n * @example\n * ```ts\n * // Setter\n * spinner.text('Loading data\u2026')\n * spinner.text('Processing\u2026')\n *\n * // Getter\n * const current = spinner.text()\n * console.log(current) // \"Processing\u2026\"\n * ```\n */\n text(): string\n text(value: string): Spinner\n text(value?: string): string | Spinner {\n // biome-ignore lint/complexity/noArguments: Function overload for getter/setter pattern.\n if (arguments.length === 0) {\n // Getter: return current base text\n return this.#baseText\n }\n // Setter: update base text and refresh display\n this.#baseText = value ?? ''\n this.#updateSpinnerText()\n return this as unknown as Spinner\n }\n\n /**\n * Show a warning message (\u26A0) without stopping the spinner.\n * Outputs to stderr and continues spinning.\n *\n * @param text - Warning message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n warn(text?: string | undefined, ...extras: unknown[]) {\n return this.#showStatusAndKeepSpinning('warn', [text, ...extras])\n }\n\n /**\n * Show a warning message (\u26A0) and stop the spinner.\n * Auto-clears the spinner line before displaying the warning message.\n *\n * @param text - Warning message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n warnAndStop(text?: string | undefined, ...extras: unknown[]) {\n return this.#apply('warning', [text, ...extras])\n }\n\n /**\n * Toggle shimmer effect or update shimmer configuration.\n * Preserves shimmer config when toggling off, allowing easy re-enable.\n * Supports partial config updates to tweak specific properties.\n *\n * @param enabledOrConfig - Boolean to toggle, partial config to update, or direction string\n * @returns This spinner for chaining\n *\n * @example\n * // Toggle off (preserves config for later re-enable)\n * spinner.shimmer(false)\n *\n * // Toggle on (restores saved config or uses defaults)\n * spinner.shimmer(true)\n *\n * // Update specific properties\n * spinner.shimmer({ speed: 0.5 })\n * spinner.shimmer({ color: [255, 0, 0] })\n *\n * // Set direction\n * spinner.shimmer('rtl')\n */\n shimmer(\n enabledOrConfig:\n | boolean\n | Partial<ShimmerConfig>\n | ShimmerDirection\n | undefined,\n ): Spinner {\n if (enabledOrConfig === false) {\n // Disable shimmer but preserve config.\n this.#shimmer = undefined\n } else if (enabledOrConfig === true) {\n // Re-enable with saved config or defaults.\n if (this.#shimmerSavedConfig) {\n // Restore saved config.\n this.#shimmer = { ...this.#shimmerSavedConfig }\n } else {\n // Create default config.\n this.#shimmer = {\n color: COLOR_INHERIT,\n currentDir: DIR_LTR,\n mode: DIR_LTR,\n speed: 1 / 3,\n step: 0,\n } as ShimmerInfo\n this.#shimmerSavedConfig = this.#shimmer\n }\n } else if (typeof enabledOrConfig === 'string') {\n // Direction string - update existing or create new.\n if (this.#shimmer) {\n // Update existing shimmer direction.\n this.#shimmer = {\n ...this.#shimmer,\n mode: enabledOrConfig,\n }\n this.#shimmerSavedConfig = this.#shimmer\n } else if (this.#shimmerSavedConfig) {\n // Restore and update.\n this.#shimmer = {\n ...this.#shimmerSavedConfig,\n mode: enabledOrConfig,\n }\n this.#shimmerSavedConfig = this.#shimmer\n } else {\n // Create new with direction.\n this.#shimmer = {\n color: COLOR_INHERIT,\n currentDir: DIR_LTR,\n mode: enabledOrConfig,\n speed: 1 / 3,\n step: 0,\n } as ShimmerInfo\n this.#shimmerSavedConfig = this.#shimmer\n }\n } else if (enabledOrConfig && typeof enabledOrConfig === 'object') {\n // Partial config update - merge with existing or saved config.\n const partialConfig = {\n __proto__: null,\n ...enabledOrConfig,\n } as Partial<ShimmerConfig>\n\n if (this.#shimmer) {\n // Update existing shimmer.\n this.#shimmer = {\n ...this.#shimmer,\n ...(partialConfig.color !== undefined\n ? { color: partialConfig.color }\n : {}),\n ...(partialConfig.dir !== undefined\n ? { mode: partialConfig.dir }\n : {}),\n ...(partialConfig.speed !== undefined\n ? { speed: partialConfig.speed }\n : {}),\n } as ShimmerInfo\n this.#shimmerSavedConfig = this.#shimmer\n } else if (this.#shimmerSavedConfig) {\n // Restore and update.\n this.#shimmer = {\n ...this.#shimmerSavedConfig,\n ...(partialConfig.color !== undefined\n ? { color: partialConfig.color }\n : {}),\n ...(partialConfig.dir !== undefined\n ? { mode: partialConfig.dir }\n : {}),\n ...(partialConfig.speed !== undefined\n ? { speed: partialConfig.speed }\n : {}),\n } as ShimmerInfo\n this.#shimmerSavedConfig = this.#shimmer\n } else {\n // Create new with partial config.\n this.#shimmer = {\n color: partialConfig.color ?? COLOR_INHERIT,\n currentDir: DIR_LTR,\n mode: partialConfig.dir ?? DIR_LTR,\n speed: partialConfig.speed ?? 1 / 3,\n step: 0,\n } as ShimmerInfo\n this.#shimmerSavedConfig = this.#shimmer\n }\n }\n\n this.#updateSpinnerText()\n return this as unknown as Spinner\n }\n } as unknown as {\n new (options?: SpinnerOptions | undefined): Spinner\n }\n // Add aliases.\n Object.defineProperties(_Spinner.prototype, {\n error: desc(_Spinner.prototype.fail),\n errorAndStop: desc(_Spinner.prototype.failAndStop),\n warning: desc(_Spinner.prototype.warn),\n warningAndStop: desc(_Spinner.prototype.warnAndStop),\n })\n _defaultSpinner = CI\n ? ciSpinner\n : (getCliSpinners('socket') as SpinnerStyle)\n }\n return new _Spinner({\n spinner: _defaultSpinner,\n ...options,\n })\n}\n\nlet _spinner: ReturnType<typeof Spinner> | undefined\n\n/**\n * Get the default spinner instance.\n * Lazily creates the spinner to avoid circular dependencies during module initialization.\n * Reuses the same instance across calls.\n *\n * @returns Shared default spinner instance\n *\n * @example\n * ```ts\n * import { getDefaultSpinner } from '@socketsecurity/registry/lib/spinner'\n *\n * const spinner = getDefaultSpinner()\n * spinner.start('Loading\u2026')\n * ```\n */\nexport function getDefaultSpinner(): ReturnType<typeof Spinner> {\n if (_spinner === undefined) {\n _spinner = Spinner()\n }\n return _spinner\n}\n\n/**\n * Default shared spinner instance (lazily initialized).\n *\n * @deprecated Use `getDefaultSpinner()` function instead for better tree-shaking and to avoid circular dependencies.\n *\n * @example\n * ```ts\n * // Old (deprecated):\n * import { spinner } from '@socketsecurity/registry/lib/spinner'\n * spinner.start('Loading\u2026')\n *\n * // New (recommended):\n * import { getDefaultSpinner } from '@socketsecurity/registry/lib/spinner'\n * const spinner = getDefaultSpinner()\n * spinner.start('Loading\u2026')\n * ```\n */\nexport const spinner = /* @__PURE__ */ (() => {\n // Lazy initialization to prevent circular dependency issues during module loading.\n let _lazySpinner: ReturnType<typeof Spinner> | undefined\n return new Proxy({} as ReturnType<typeof Spinner>, {\n get(_target, prop) {\n if (_lazySpinner === undefined) {\n _lazySpinner = Spinner()\n }\n const value = _lazySpinner[prop as keyof ReturnType<typeof Spinner>]\n return typeof value === 'function' ? value.bind(_lazySpinner) : value\n },\n })\n})()\n\n/**\n * Configuration options for `withSpinner()` helper.\n * @template T - Return type of the async operation\n */\nexport type WithSpinnerOptions<T> = {\n /** Message to display while the spinner is running */\n message: string\n /** Async function to execute while spinner is active */\n operation: () => Promise<T>\n /**\n * Optional spinner instance to use.\n * If not provided, operation runs without spinner.\n */\n spinner?: Spinner | undefined\n}\n\n/**\n * Execute an async operation with spinner lifecycle management.\n * Ensures `spinner.stop()` is always called via try/finally, even if the operation throws.\n * Provides safe cleanup and consistent spinner behavior.\n *\n * @template T - Return type of the operation\n * @param options - Configuration object\n * @param options.message - Message to display while spinner is running\n * @param options.operation - Async function to execute\n * @param options.spinner - Optional spinner instance (if not provided, no spinner is used)\n * @returns Result of the operation\n * @throws Re-throws any error from operation after stopping spinner\n *\n * @example\n * ```ts\n * import { Spinner, withSpinner } from '@socketsecurity/registry/lib/spinner'\n *\n * const spinner = Spinner()\n *\n * // With spinner instance\n * const result = await withSpinner({\n * message: 'Processing\u2026',\n * operation: async () => {\n * return await processData()\n * },\n * spinner\n * })\n *\n * // Without spinner instance (no-op, just runs operation)\n * const result = await withSpinner({\n * message: 'Processing\u2026',\n * operation: async () => {\n * return await processData()\n * }\n * })\n * ```\n */\nexport async function withSpinner<T>(\n options: WithSpinnerOptions<T>,\n): Promise<T> {\n const { message, operation, spinner } = {\n __proto__: null,\n ...options,\n } as WithSpinnerOptions<T>\n\n if (!spinner) {\n return await operation()\n }\n\n spinner.start(message)\n try {\n return await operation()\n } finally {\n spinner.stop()\n }\n}\n\n/**\n * Configuration options for `withSpinnerRestore()` helper.\n * @template T - Return type of the async operation\n */\nexport type WithSpinnerRestoreOptions<T> = {\n /** Async function to execute while spinner is stopped */\n operation: () => Promise<T>\n /** Optional spinner instance to restore after operation */\n spinner?: Spinner | undefined\n /** Whether spinner was spinning before the operation (used to conditionally restart) */\n wasSpinning: boolean\n}\n\n/**\n * Execute an async operation with conditional spinner restart.\n * Useful when you need to temporarily stop a spinner for an operation,\n * then restore it to its previous state (if it was spinning).\n *\n * @template T - Return type of the operation\n * @param options - Configuration object\n * @param options.operation - Async function to execute\n * @param options.spinner - Optional spinner instance to manage\n * @param options.wasSpinning - Whether spinner was spinning before the operation\n * @returns Result of the operation\n * @throws Re-throws any error from operation after restoring spinner state\n *\n * @example\n * ```ts\n * import { getDefaultSpinner, withSpinnerRestore } from '@socketsecurity/registry/lib/spinner'\n *\n * const spinner = getDefaultSpinner()\n * const wasSpinning = spinner.isSpinning\n * spinner.stop()\n *\n * const result = await withSpinnerRestore({\n * operation: async () => {\n * // Do work without spinner\n * return await someOperation()\n * },\n * spinner,\n * wasSpinning\n * })\n * // Spinner is automatically restarted if wasSpinning was true\n * ```\n */\nexport async function withSpinnerRestore<T>(\n options: WithSpinnerRestoreOptions<T>,\n): Promise<T> {\n const { operation, spinner, wasSpinning } = {\n __proto__: null,\n ...options,\n } as WithSpinnerRestoreOptions<T>\n\n try {\n return await operation()\n } finally {\n if (spinner && wasSpinning) {\n spinner.start()\n }\n }\n}\n\n/**\n * Configuration options for `withSpinnerSync()` helper.\n * @template T - Return type of the sync operation\n */\nexport type WithSpinnerSyncOptions<T> = {\n /** Message to display while the spinner is running */\n message: string\n /** Synchronous function to execute while spinner is active */\n operation: () => T\n /**\n * Optional spinner instance to use.\n * If not provided, operation runs without spinner.\n */\n spinner?: Spinner | undefined\n}\n\n/**\n * Execute a synchronous operation with spinner lifecycle management.\n * Ensures `spinner.stop()` is always called via try/finally, even if the operation throws.\n * Provides safe cleanup and consistent spinner behavior for sync operations.\n *\n * @template T - Return type of the operation\n * @param options - Configuration object\n * @param options.message - Message to display while spinner is running\n * @param options.operation - Synchronous function to execute\n * @param options.spinner - Optional spinner instance (if not provided, no spinner is used)\n * @returns Result of the operation\n * @throws Re-throws any error from operation after stopping spinner\n *\n * @example\n * ```ts\n * import { Spinner, withSpinnerSync } from '@socketsecurity/registry/lib/spinner'\n *\n * const spinner = Spinner()\n *\n * const result = withSpinnerSync({\n * message: 'Processing\u2026',\n * operation: () => {\n * return processDataSync()\n * },\n * spinner\n * })\n * ```\n */\nexport function withSpinnerSync<T>(options: WithSpinnerSyncOptions<T>): T {\n const { message, operation, spinner } = {\n __proto__: null,\n ...options,\n } as WithSpinnerSyncOptions<T>\n\n if (!spinner) {\n return operation()\n }\n\n spinner.start(message)\n try {\n return operation()\n } finally {\n spinner.stop()\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * @fileoverview CLI spinner utilities for long-running operations.\n * Provides animated progress indicators with CI environment detection.\n */\n\nimport type { Writable } from 'node:stream'\n\n// Note: getAbortSignal is imported lazily to avoid circular dependencies.\nimport { getCI } from '#env/ci'\nimport { generateSocketSpinnerFrames } from './effects/pulse-frames'\nimport type {\n ShimmerColorGradient,\n ShimmerConfig,\n ShimmerDirection,\n ShimmerState,\n} from './effects/text-shimmer'\nimport { applyShimmer, COLOR_INHERIT, DIR_LTR } from './effects/text-shimmer'\nimport yoctoSpinner from './external/@socketregistry/yocto-spinner'\nimport { hasOwn } from './objects'\nimport { isBlankString, stringWidth } from './strings'\n\n/**\n * Named color values supported by the spinner.\n * Maps to standard terminal colors with bright variants.\n */\nexport type ColorName =\n | 'black'\n | 'blue'\n | 'blueBright'\n | 'cyan'\n | 'cyanBright'\n | 'gray'\n | 'green'\n | 'greenBright'\n | 'magenta'\n | 'magentaBright'\n | 'red'\n | 'redBright'\n | 'white'\n | 'whiteBright'\n | 'yellow'\n | 'yellowBright'\n\n/**\n * Special 'inherit' color value that uses the spinner's current color.\n * Used with shimmer effects to dynamically inherit the spinner color.\n */\nexport type ColorInherit = 'inherit'\n\n/**\n * RGB color tuple with values 0-255 for red, green, and blue channels.\n * @example [140, 82, 255] // Socket purple\n * @example [255, 0, 0] // Red\n */\nexport type ColorRgb = readonly [number, number, number]\n\n/**\n * Union of all supported color types: named colors or RGB tuples.\n */\nexport type ColorValue = ColorName | ColorRgb\n\n/**\n * Symbol types for status messages.\n * Maps to log symbols: success (\u2713), fail (\u2717), info (\u2139), warn (\u26A0).\n */\nexport type SymbolType = 'fail' | 'info' | 'success' | 'warn'\n\n// Map color names to RGB values.\nconst colorToRgb: Record<ColorName, ColorRgb> = {\n __proto__: null,\n black: [0, 0, 0],\n blue: [0, 0, 255],\n blueBright: [100, 149, 237],\n cyan: [0, 255, 255],\n cyanBright: [0, 255, 255],\n gray: [128, 128, 128],\n green: [0, 128, 0],\n greenBright: [0, 255, 0],\n magenta: [255, 0, 255],\n magentaBright: [255, 105, 180],\n red: [255, 0, 0],\n redBright: [255, 69, 0],\n white: [255, 255, 255],\n whiteBright: [255, 255, 255],\n yellow: [255, 255, 0],\n yellowBright: [255, 255, 153],\n} as Record<ColorName, ColorRgb>\n\n/**\n * Type guard to check if a color value is an RGB tuple.\n * @param value - Color value to check\n * @returns `true` if value is an RGB tuple, `false` if it's a color name\n */\nfunction isRgbTuple(value: ColorValue): value is ColorRgb {\n return Array.isArray(value)\n}\n\n/**\n * Convert a color value to RGB tuple format.\n * Named colors are looked up in the `colorToRgb` map, RGB tuples are returned as-is.\n * @param color - Color name or RGB tuple\n * @returns RGB tuple with values 0-255\n */\nfunction toRgb(color: ColorValue): ColorRgb {\n if (isRgbTuple(color)) {\n return color\n }\n return colorToRgb[color]\n}\n\n/**\n * Progress tracking information for display in spinner.\n * Used by `progress()` and `progressStep()` methods to show animated progress bars.\n */\nexport type ProgressInfo = {\n /** Current progress value */\n current: number\n /** Total/maximum progress value */\n total: number\n /** Optional unit label displayed after the progress count (e.g., 'files', 'items') */\n unit?: string | undefined\n}\n\n/**\n * Internal shimmer state with color configuration.\n * Extends `ShimmerState` with additional color property that can be inherited from spinner.\n */\nexport type ShimmerInfo = ShimmerState & {\n /** Color for shimmer effect - can inherit from spinner, use explicit color, or gradient */\n color: ColorInherit | ColorValue | ShimmerColorGradient\n}\n\n/**\n * Spinner instance for displaying animated loading indicators.\n * Provides methods for status updates, progress tracking, and text shimmer effects.\n *\n * KEY BEHAVIORS:\n * - Methods WITHOUT \"AndStop\" keep the spinner running (e.g., `success()`, `fail()`)\n * - Methods WITH \"AndStop\" auto-clear the spinner line (e.g., `successAndStop()`, `failAndStop()`)\n * - Status messages (done, success, fail, info, warn, step, substep) go to stderr\n * - Data messages (`log()`) go to stdout\n *\n * @example\n * ```ts\n * import { Spinner } from '@socketsecurity/registry/lib/spinner'\n *\n * const spinner = Spinner({ text: 'Loading\u2026' })\n * spinner.start()\n *\n * // Show success while continuing to spin\n * spinner.success('Step 1 complete')\n *\n * // Stop the spinner with success message\n * spinner.successAndStop('All done!')\n * ```\n */\nexport type Spinner = {\n /** Current spinner color as RGB tuple */\n color: ColorRgb\n /** Current spinner animation style */\n spinner: SpinnerStyle\n\n /** Whether spinner is currently animating */\n get isSpinning(): boolean\n\n /** Clear the current line without stopping the spinner */\n clear(): Spinner\n\n /** Show debug message without stopping (only if debug mode enabled) */\n debug(text?: string | undefined, ...extras: unknown[]): Spinner\n /** Show debug message and stop the spinner (only if debug mode enabled) */\n debugAndStop(text?: string | undefined, ...extras: unknown[]): Spinner\n\n /** Alias for `fail()` - show error without stopping */\n error(text?: string | undefined, ...extras: unknown[]): Spinner\n /** Alias for `failAndStop()` - show error and stop */\n errorAndStop(text?: string | undefined, ...extras: unknown[]): Spinner\n\n /** Show failure (\u2717) without stopping the spinner */\n fail(text?: string | undefined, ...extras: unknown[]): Spinner\n /** Show failure (\u2717) and stop the spinner, auto-clearing the line */\n failAndStop(text?: string | undefined, ...extras: unknown[]): Spinner\n\n /** Get current spinner text (getter) or set new text (setter) */\n text(value: string): Spinner\n text(): string\n\n /** Increase indentation by specified spaces (default: 2) */\n indent(spaces?: number | undefined): Spinner\n /** Decrease indentation by specified spaces (default: 2) */\n dedent(spaces?: number | undefined): Spinner\n\n /** Show info (\u2139) message without stopping the spinner */\n info(text?: string | undefined, ...extras: unknown[]): Spinner\n /** Show info (\u2139) message and stop the spinner, auto-clearing the line */\n infoAndStop(text?: string | undefined, ...extras: unknown[]): Spinner\n\n /** Log to stdout without stopping the spinner */\n log(text?: string | undefined, ...extras: unknown[]): Spinner\n /** Log and stop the spinner, auto-clearing the line */\n logAndStop(text?: string | undefined, ...extras: unknown[]): Spinner\n\n /** Start spinning with optional text */\n start(text?: string | undefined): Spinner\n /** Stop spinning and clear internal state, auto-clearing the line */\n stop(text?: string | undefined): Spinner\n /** Stop and show final text without clearing the line */\n stopAndPersist(text?: string | undefined): Spinner\n\n /** Show main step message to stderr without stopping */\n step(text?: string | undefined, ...extras: unknown[]): Spinner\n /** Show indented substep message to stderr without stopping */\n substep(text?: string | undefined, ...extras: unknown[]): Spinner\n\n /** Show success (\u2713) without stopping the spinner */\n success(text?: string | undefined, ...extras: unknown[]): Spinner\n /** Show success (\u2713) and stop the spinner, auto-clearing the line */\n successAndStop(text?: string | undefined, ...extras: unknown[]): Spinner\n\n /** Alias for `success()` - show success without stopping */\n done(text?: string | undefined, ...extras: unknown[]): Spinner\n /** Alias for `successAndStop()` - show success and stop */\n doneAndStop(text?: string | undefined, ...extras: unknown[]): Spinner\n\n /** Update progress bar with current/total values and optional unit */\n progress(current: number, total: number, unit?: string | undefined): Spinner\n /** Increment progress by specified amount (default: 1) */\n progressStep(amount?: number): Spinner\n\n /** Toggle shimmer effect on/off */\n shimmer(enabled: boolean): Spinner\n /** Update shimmer configuration or set direction */\n shimmer(config: Partial<ShimmerConfig> | ShimmerDirection): Spinner\n\n /** Show warning (\u26A0) without stopping the spinner */\n warn(text?: string | undefined, ...extras: unknown[]): Spinner\n /** Show warning (\u26A0) and stop the spinner, auto-clearing the line */\n warnAndStop(text?: string | undefined, ...extras: unknown[]): Spinner\n}\n\n/**\n * Configuration options for creating a spinner instance.\n */\nexport type SpinnerOptions = {\n /**\n * Spinner color as RGB tuple or color name.\n * @default [140, 82, 255] Socket purple\n */\n readonly color?: ColorValue | undefined\n /**\n * Shimmer effect configuration or direction string.\n * When enabled, text will have an animated shimmer effect.\n * @default undefined No shimmer effect\n */\n readonly shimmer?: ShimmerConfig | ShimmerDirection | undefined\n /**\n * Animation style with frames and timing.\n * @default 'socket' Custom Socket animation in CLI, minimal in CI\n */\n readonly spinner?: SpinnerStyle | undefined\n /**\n * Abort signal for cancelling the spinner.\n * @default getAbortSignal() from process constants\n */\n readonly signal?: AbortSignal | undefined\n /**\n * Output stream for spinner rendering.\n * @default process.stderr\n */\n readonly stream?: Writable | undefined\n /**\n * Initial text to display with the spinner.\n * @default undefined No initial text\n */\n readonly text?: string | undefined\n}\n\n/**\n * Animation style definition for spinner frames.\n * Defines the visual appearance and timing of the spinner animation.\n */\nexport type SpinnerStyle = {\n /** Array of animation frames (strings to display sequentially) */\n readonly frames: string[]\n /**\n * Milliseconds between frame changes.\n * @default 80 Standard frame rate\n */\n readonly interval?: number | undefined\n}\n\n/**\n * Minimal spinner style for CI environments.\n * Uses empty frame and max interval to effectively disable animation in CI.\n */\nexport const ciSpinner: SpinnerStyle = {\n frames: [''],\n interval: 2_147_483_647,\n}\n\n/**\n * Create a property descriptor for defining non-enumerable properties.\n * Used for adding aliased methods to the Spinner prototype.\n * @param value - Value for the property\n * @returns Property descriptor object\n * @private\n */\nfunction desc(value: unknown) {\n return {\n __proto__: null,\n configurable: true,\n value,\n writable: true,\n }\n}\n\n/**\n * Normalize text input by trimming leading whitespace.\n * Non-string values are converted to empty string.\n * @param value - Text to normalize\n * @returns Normalized string with leading whitespace removed\n * @private\n */\nfunction normalizeText(value: unknown) {\n return typeof value === 'string' ? value.trimStart() : ''\n}\n\n/**\n * Format progress information as a visual progress bar with percentage and count.\n * @param progress - Progress tracking information\n * @returns Formatted string with colored progress bar, percentage, and count\n * @private\n * @example \"\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591 35% (7/20 files)\"\n */\nfunction formatProgress(progress: ProgressInfo): string {\n const { current, total, unit } = progress\n const percentage = Math.round((current / total) * 100)\n const bar = renderProgressBar(percentage)\n const count = unit ? `${current}/${total} ${unit}` : `${current}/${total}`\n return `${bar} ${percentage}% (${count})`\n}\n\n/**\n * Render a progress bar using block characters (\u2588 for filled, \u2591 for empty).\n * @param percentage - Progress percentage (0-100)\n * @param width - Total width of progress bar in characters\n * @returns Colored progress bar string\n * @default width=20\n * @private\n */\nfunction renderProgressBar(percentage: number, width: number = 20): string {\n const filled = Math.round((percentage / 100) * width)\n const empty = width - filled\n const bar = '\u2588'.repeat(filled) + '\u2591'.repeat(empty)\n // Use cyan color for the progress bar\n const colors = /*@__PURE__*/ require('./external/yoctocolors-cjs')\n return colors.cyan(bar)\n}\n\nlet _cliSpinners: Record<string, SpinnerStyle> | undefined\n\n/**\n * Get available CLI spinner styles or a specific style by name.\n * Extends the standard cli-spinners collection with Socket custom spinners.\n *\n * Custom spinners:\n * - `socket` (default): Socket pulse animation with sparkles and lightning\n *\n * @param styleName - Optional name of specific spinner style to retrieve\n * @returns Specific spinner style if name provided, all styles if omitted, `undefined` if style not found\n * @see https://github.com/sindresorhus/cli-spinners/blob/main/spinners.json\n *\n * @example\n * ```ts\n * // Get all available spinner styles\n * const allSpinners = getCliSpinners()\n *\n * // Get specific style\n * const socketStyle = getCliSpinners('socket')\n * const dotsStyle = getCliSpinners('dots')\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function getCliSpinners(\n styleName?: string | undefined,\n): SpinnerStyle | Record<string, SpinnerStyle> | undefined {\n if (_cliSpinners === undefined) {\n const YoctoCtor = yoctoSpinner as any\n // Get the YoctoSpinner class to access static properties.\n const tempInstance = YoctoCtor({})\n const YoctoSpinnerClass = tempInstance.constructor as any\n // Extend the standard cli-spinners collection with Socket custom spinners.\n _cliSpinners = {\n __proto__: null,\n ...YoctoSpinnerClass.spinners,\n socket: generateSocketSpinnerFrames(),\n }\n }\n if (typeof styleName === 'string' && _cliSpinners) {\n return hasOwn(_cliSpinners, styleName) ? _cliSpinners[styleName] : undefined\n }\n return _cliSpinners\n}\n\nlet _Spinner: {\n new (options?: SpinnerOptions | undefined): Spinner\n}\nlet _defaultSpinner: SpinnerStyle | undefined\n\n/**\n * Create a spinner instance for displaying loading indicators.\n * Provides an animated CLI spinner with status messages, progress tracking, and shimmer effects.\n *\n * AUTO-CLEAR BEHAVIOR:\n * - All *AndStop() methods AUTO-CLEAR the spinner line via yocto-spinner.stop()\n * Examples: `doneAndStop()`, `successAndStop()`, `failAndStop()`, etc.\n *\n * - Methods WITHOUT \"AndStop\" do NOT clear (spinner keeps spinning)\n * Examples: `done()`, `success()`, `fail()`, etc.\n *\n * STREAM USAGE:\n * - Spinner animation: stderr (yocto-spinner default)\n * - Status methods (done, success, fail, info, warn, step, substep): stderr\n * - Data methods (`log()`): stdout\n *\n * COMPARISON WITH LOGGER:\n * - `logger.done()` does NOT auto-clear (requires manual `logger.clearLine()`)\n * - `spinner.doneAndStop()` DOES auto-clear (built into yocto-spinner.stop())\n * - Pattern: `logger.clearLine().done()` vs `spinner.doneAndStop()`\n *\n * @param options - Configuration options for the spinner\n * @returns New spinner instance\n *\n * @example\n * ```ts\n * import { Spinner } from '@socketsecurity/registry/lib/spinner'\n *\n * // Basic usage\n * const spinner = Spinner({ text: 'Loading data\u2026' })\n * spinner.start()\n * await fetchData()\n * spinner.successAndStop('Data loaded!')\n *\n * // With custom color\n * const spinner = Spinner({\n * text: 'Processing\u2026',\n * color: [255, 0, 0] // Red\n * })\n *\n * // With shimmer effect\n * const spinner = Spinner({\n * text: 'Building\u2026',\n * shimmer: { dir: 'ltr', speed: 0.5 }\n * })\n *\n * // Show progress\n * spinner.progress(5, 10, 'files')\n * spinner.progressStep() // Increment by 1\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function Spinner(options?: SpinnerOptions | undefined): Spinner {\n if (_Spinner === undefined) {\n const YoctoCtor = yoctoSpinner as any\n // Get the actual YoctoSpinner class from an instance\n const tempInstance = YoctoCtor({})\n const YoctoSpinnerClass = tempInstance.constructor\n\n /*@__PURE__*/\n _Spinner = class SpinnerClass extends (YoctoSpinnerClass as any) {\n declare isSpinning: boolean\n #baseText: string = ''\n #indentation: string = ''\n #progress?: ProgressInfo | undefined\n #shimmer?: ShimmerInfo | undefined\n #shimmerSavedConfig?: ShimmerInfo | undefined\n\n constructor(options?: SpinnerOptions | undefined) {\n const opts = { __proto__: null, ...options } as SpinnerOptions\n\n // Convert color option to RGB (default to Socket purple).\n const spinnerColor = opts.color ?? ([140, 82, 255] as const)\n\n // Validate RGB tuple if provided.\n if (\n isRgbTuple(spinnerColor) &&\n (spinnerColor.length !== 3 ||\n !spinnerColor.every(\n n => typeof n === 'number' && n >= 0 && n <= 255,\n ))\n ) {\n throw new TypeError(\n 'RGB color must be an array of 3 numbers between 0 and 255',\n )\n }\n\n const spinnerColorRgb = toRgb(spinnerColor)\n\n // Parse shimmer config - can be object or direction string.\n let shimmerInfo: ShimmerInfo | undefined\n if (opts.shimmer) {\n let shimmerDir: ShimmerDirection\n let shimmerColor:\n | ColorInherit\n | ColorValue\n | ShimmerColorGradient\n | undefined\n // Default: 0.33 steps per frame (~150ms per step).\n let shimmerSpeed: number = 1 / 3\n\n if (typeof opts.shimmer === 'string') {\n shimmerDir = opts.shimmer\n } else {\n const shimmerConfig = {\n __proto__: null,\n ...opts.shimmer,\n } as ShimmerConfig\n shimmerDir = shimmerConfig.dir ?? DIR_LTR\n shimmerColor = shimmerConfig.color ?? COLOR_INHERIT\n shimmerSpeed = shimmerConfig.speed ?? 1 / 3\n }\n\n // Create shimmer info with initial animation state:\n // - COLOR_INHERIT means use spinner color dynamically\n // - ColorValue (name or RGB tuple) is an explicit override color\n // - undefined color defaults to COLOR_INHERIT\n // - speed controls steps per frame (lower = slower, e.g., 0.33 = ~150ms per step)\n shimmerInfo = {\n __proto__: null,\n color: shimmerColor === undefined ? COLOR_INHERIT : shimmerColor,\n currentDir: DIR_LTR,\n mode: shimmerDir,\n speed: shimmerSpeed,\n step: 0,\n } as ShimmerInfo\n }\n\n // eslint-disable-next-line constructor-super\n super({\n signal: require('#constants/process').getAbortSignal(),\n ...opts,\n // Pass RGB color directly to yocto-spinner (it now supports RGB).\n color: spinnerColorRgb,\n // onRenderFrame callback provides full control over frame + text layout.\n // Calculates spacing based on frame width to prevent text jumping.\n onRenderFrame: (\n frame: string,\n text: string,\n applyColor: (text: string) => string,\n ) => {\n const width = stringWidth(frame)\n // Narrow frames (width 1) get 2 spaces, wide frames (width 2) get 1 space.\n // Total width is consistent: 3 characters (frame + spacing) before text.\n const spacing = width === 1 ? ' ' : ' '\n return frame ? `${applyColor(frame)}${spacing}${text}` : text\n },\n // onFrameUpdate callback is called by yocto-spinner whenever a frame advances.\n // This ensures shimmer updates are perfectly synchronized with animation beats.\n onFrameUpdate: shimmerInfo\n ? () => {\n // Update parent's text without triggering render.\n // Parent's #skipRender flag prevents nested render calls.\n // Only update if we have base text to avoid blank frames.\n if (this.#baseText) {\n super.text = this.#buildDisplayText()\n }\n }\n : undefined,\n })\n\n this.#shimmer = shimmerInfo\n this.#shimmerSavedConfig = shimmerInfo\n }\n\n // Override color getter to ensure it's always RGB.\n get color(): ColorRgb {\n const value = super.color\n return isRgbTuple(value) ? value : toRgb(value)\n }\n\n // Override color setter to always convert to RGB before passing to yocto-spinner.\n set color(value: ColorValue | ColorRgb) {\n super.color = isRgbTuple(value) ? value : toRgb(value)\n }\n\n /**\n * Apply a yocto-spinner method and update logger state.\n * Handles text normalization, extra arguments, and logger tracking.\n * @private\n */\n #apply(methodName: string, args: unknown[]) {\n let extras: unknown[]\n let text = args.at(0)\n if (typeof text === 'string') {\n extras = args.slice(1)\n } else {\n extras = args\n text = ''\n }\n const wasSpinning = this.isSpinning\n const normalized = normalizeText(text)\n super[methodName](normalized)\n const {\n incLogCallCountSymbol,\n lastWasBlankSymbol,\n logger,\n } = /*@__PURE__*/ require('./logger.js')\n if (methodName === 'stop') {\n if (wasSpinning && normalized) {\n logger[lastWasBlankSymbol](isBlankString(normalized))\n logger[incLogCallCountSymbol]()\n }\n } else {\n logger[lastWasBlankSymbol](false)\n logger[incLogCallCountSymbol]()\n }\n if (extras.length) {\n logger.log(...extras)\n logger[lastWasBlankSymbol](false)\n }\n return this\n }\n\n /**\n * Build the complete display text with progress, shimmer, and indentation.\n * Combines base text, progress bar, shimmer effects, and indentation.\n * @private\n */\n #buildDisplayText() {\n let displayText = this.#baseText\n\n if (this.#progress) {\n const progressText = formatProgress(this.#progress)\n displayText = displayText\n ? `${displayText} ${progressText}`\n : progressText\n }\n\n // Apply shimmer effect if enabled.\n if (displayText && this.#shimmer) {\n // If shimmer color is 'inherit', use current spinner color (getter ensures RGB).\n // Otherwise, check if it's a gradient (array of arrays) or single color.\n let shimmerColor: ColorRgb | ShimmerColorGradient\n if (this.#shimmer.color === COLOR_INHERIT) {\n shimmerColor = this.color\n } else if (Array.isArray(this.#shimmer.color[0])) {\n // It's a gradient - use as is.\n shimmerColor = this.#shimmer.color as ShimmerColorGradient\n } else {\n // It's a single color - convert to RGB.\n shimmerColor = toRgb(this.#shimmer.color as ColorValue)\n }\n\n displayText = applyShimmer(displayText, this.#shimmer, {\n color: shimmerColor,\n direction: this.#shimmer.mode,\n })\n }\n\n // Apply indentation\n if (this.#indentation && displayText) {\n displayText = this.#indentation + displayText\n }\n\n return displayText\n }\n\n /**\n * Show a status message without stopping the spinner.\n * Outputs the symbol and message to stderr, then continues spinning.\n */\n #showStatusAndKeepSpinning(symbolType: SymbolType, args: unknown[]) {\n let text = args.at(0)\n let extras: unknown[]\n if (typeof text === 'string') {\n extras = args.slice(1)\n } else {\n extras = args\n text = ''\n }\n\n const { LOG_SYMBOLS, logger } = /*@__PURE__*/ require('./logger.js')\n // Note: Status messages always go to stderr.\n logger.error(`${LOG_SYMBOLS[symbolType]} ${text}`, ...extras)\n return this\n }\n\n /**\n * Update the spinner's displayed text.\n * Rebuilds display text and triggers render.\n * @private\n */\n #updateSpinnerText() {\n // Call the parent class's text setter, which triggers render.\n super.text = this.#buildDisplayText()\n }\n\n /**\n * Show a debug message (\u2139) without stopping the spinner.\n * Only displays if debug mode is enabled via environment variable.\n * Outputs to stderr and continues spinning.\n *\n * @param text - Debug message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n debug(text?: string | undefined, ...extras: unknown[]) {\n const { isDebug } = /*@__PURE__*/ require('./debug.js')\n if (isDebug()) {\n return this.#showStatusAndKeepSpinning('info', [text, ...extras])\n }\n return this\n }\n\n /**\n * Show a debug message (\u2139) and stop the spinner.\n * Only displays if debug mode is enabled via environment variable.\n * Auto-clears the spinner line before displaying the message.\n *\n * @param text - Debug message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n debugAndStop(text?: string | undefined, ...extras: unknown[]) {\n const { isDebug } = /*@__PURE__*/ require('./debug.js')\n if (isDebug()) {\n return this.#apply('info', [text, ...extras])\n }\n return this\n }\n\n /**\n * Decrease indentation level by removing spaces from the left.\n * Pass 0 to reset indentation to zero completely.\n *\n * @param spaces - Number of spaces to remove\n * @returns This spinner for chaining\n * @default spaces=2\n *\n * @example\n * ```ts\n * spinner.dedent() // Remove 2 spaces\n * spinner.dedent(4) // Remove 4 spaces\n * spinner.dedent(0) // Reset to zero indentation\n * ```\n */\n dedent(spaces?: number | undefined) {\n // Pass 0 to reset indentation\n if (spaces === 0) {\n this.#indentation = ''\n } else {\n const amount = spaces ?? 2\n const newLength = Math.max(0, this.#indentation.length - amount)\n this.#indentation = this.#indentation.slice(0, newLength)\n }\n this.#updateSpinnerText()\n return this\n }\n\n /**\n * Show a done/success message (\u2713) without stopping the spinner.\n * Alias for `success()` with a shorter name.\n *\n * DESIGN DECISION: Unlike yocto-spinner, our `done()` does NOT stop the spinner.\n * Use `doneAndStop()` if you want to stop the spinner.\n *\n * @param text - Message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n done(text?: string | undefined, ...extras: unknown[]) {\n return this.#showStatusAndKeepSpinning('success', [text, ...extras])\n }\n\n /**\n * Show a done/success message (\u2713) and stop the spinner.\n * Auto-clears the spinner line before displaying the success message.\n *\n * @param text - Message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n doneAndStop(text?: string | undefined, ...extras: unknown[]) {\n return this.#apply('success', [text, ...extras])\n }\n\n /**\n * Show a failure message (\u2717) without stopping the spinner.\n * DESIGN DECISION: Unlike yocto-spinner, our `fail()` does NOT stop the spinner.\n * This allows displaying errors while continuing to spin.\n * Use `failAndStop()` if you want to stop the spinner.\n *\n * @param text - Error message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n fail(text?: string | undefined, ...extras: unknown[]) {\n return this.#showStatusAndKeepSpinning('fail', [text, ...extras])\n }\n\n /**\n * Show a failure message (\u2717) and stop the spinner.\n * Auto-clears the spinner line before displaying the error message.\n *\n * @param text - Error message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n failAndStop(text?: string | undefined, ...extras: unknown[]) {\n return this.#apply('error', [text, ...extras])\n }\n\n /**\n * Increase indentation level by adding spaces to the left.\n * Pass 0 to reset indentation to zero completely.\n *\n * @param spaces - Number of spaces to add\n * @returns This spinner for chaining\n * @default spaces=2\n *\n * @example\n * ```ts\n * spinner.indent() // Add 2 spaces\n * spinner.indent(4) // Add 4 spaces\n * spinner.indent(0) // Reset to zero indentation\n * ```\n */\n indent(spaces?: number | undefined) {\n // Pass 0 to reset indentation\n if (spaces === 0) {\n this.#indentation = ''\n } else {\n const amount = spaces ?? 2\n this.#indentation += ' '.repeat(amount)\n }\n this.#updateSpinnerText()\n return this\n }\n\n /**\n * Show an info message (\u2139) without stopping the spinner.\n * Outputs to stderr and continues spinning.\n *\n * @param text - Info message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n info(text?: string | undefined, ...extras: unknown[]) {\n return this.#showStatusAndKeepSpinning('info', [text, ...extras])\n }\n\n /**\n * Show an info message (\u2139) and stop the spinner.\n * Auto-clears the spinner line before displaying the message.\n *\n * @param text - Info message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n infoAndStop(text?: string | undefined, ...extras: unknown[]) {\n return this.#apply('info', [text, ...extras])\n }\n\n /**\n * Log a message to stdout without stopping the spinner.\n * Unlike other status methods, this outputs to stdout for data logging.\n *\n * @param args - Values to log to stdout\n * @returns This spinner for chaining\n */\n log(...args: unknown[]) {\n const { logger } = /*@__PURE__*/ require('./logger.js')\n logger.log(...args)\n return this\n }\n\n /**\n * Log a message to stdout and stop the spinner.\n * Auto-clears the spinner line before displaying the message.\n *\n * @param text - Message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n logAndStop(text?: string | undefined, ...extras: unknown[]) {\n return this.#apply('stop', [text, ...extras])\n }\n\n /**\n * Update progress information displayed with the spinner.\n * Shows a progress bar with percentage and optional unit label.\n *\n * @param current - Current progress value\n * @param total - Total/maximum progress value\n * @param unit - Optional unit label (e.g., 'files', 'items')\n * @returns This spinner for chaining\n *\n * @example\n * ```ts\n * spinner.progress(5, 10) // \"\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591 50% (5/10)\"\n * spinner.progress(7, 20, 'files') // \"\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591 35% (7/20 files)\"\n * ```\n */\n progress = (\n current: number,\n total: number,\n unit?: string | undefined,\n ) => {\n this.#progress = {\n __proto__: null,\n current,\n total,\n ...(unit ? { unit } : {}),\n } as ProgressInfo\n this.#updateSpinnerText()\n return this\n }\n\n /**\n * Increment progress by a specified amount.\n * Updates the progress bar displayed with the spinner.\n * Clamps the result between 0 and the total value.\n *\n * @param amount - Amount to increment by\n * @returns This spinner for chaining\n * @default amount=1\n *\n * @example\n * ```ts\n * spinner.progress(0, 10, 'files')\n * spinner.progressStep() // Progress: 1/10\n * spinner.progressStep(3) // Progress: 4/10\n * ```\n */\n progressStep(amount: number = 1) {\n if (this.#progress) {\n const newCurrent = this.#progress.current + amount\n this.#progress = {\n __proto__: null,\n current: Math.max(0, Math.min(newCurrent, this.#progress.total)),\n total: this.#progress.total,\n ...(this.#progress.unit ? { unit: this.#progress.unit } : {}),\n } as ProgressInfo\n this.#updateSpinnerText()\n }\n return this\n }\n\n /**\n * Start the spinner animation with optional text.\n * Begins displaying the animated spinner on stderr.\n *\n * @param text - Optional text to display with the spinner\n * @returns This spinner for chaining\n *\n * @example\n * ```ts\n * spinner.start('Loading\u2026')\n * // Later:\n * spinner.successAndStop('Done!')\n * ```\n */\n start(...args: unknown[]) {\n if (args.length) {\n const text = args.at(0)\n const normalized = normalizeText(text)\n // We clear this.text on start when `text` is falsy because yocto-spinner\n // will not clear it otherwise.\n if (!normalized) {\n this.#baseText = ''\n super.text = ''\n } else {\n this.#baseText = normalized\n }\n }\n\n this.#updateSpinnerText()\n return this.#apply('start', args)\n }\n\n /**\n * Log a main step message to stderr without stopping the spinner.\n * Adds a blank line before the message for visual separation.\n * Aligns with `logger.step()` to use stderr for status messages.\n *\n * @param text - Step message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n *\n * @example\n * ```ts\n * spinner.step('Building application')\n * spinner.substep('Compiling TypeScript')\n * spinner.substep('Bundling assets')\n * ```\n */\n step(text?: string | undefined, ...extras: unknown[]) {\n const { logger } = /*@__PURE__*/ require('./logger.js')\n if (typeof text === 'string') {\n // Add blank line before step for visual separation.\n logger.error('')\n // Use error (stderr) to align with logger.step() default stream.\n logger.error(text, ...extras)\n }\n return this\n }\n\n /**\n * Log an indented substep message to stderr without stopping the spinner.\n * Adds 2-space indentation to the message.\n * Aligns with `logger.substep()` to use stderr for status messages.\n *\n * @param text - Substep message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n *\n * @example\n * ```ts\n * spinner.step('Building application')\n * spinner.substep('Compiling TypeScript')\n * spinner.substep('Bundling assets')\n * ```\n */\n substep(text?: string | undefined, ...extras: unknown[]) {\n if (typeof text === 'string') {\n // Add 2-space indent for substep.\n const { logger } = /*@__PURE__*/ require('./logger.js')\n // Use error (stderr) to align with logger.substep() default stream.\n logger.error(` ${text}`, ...extras)\n }\n return this\n }\n\n /**\n * Stop the spinner animation and clear internal state.\n * Auto-clears the spinner line via yocto-spinner.stop().\n * Resets progress, shimmer, and text state.\n *\n * @param text - Optional final text to display after stopping\n * @returns This spinner for chaining\n *\n * @example\n * ```ts\n * spinner.start('Processing\u2026')\n * // Do work\n * spinner.stop() // Just stop, no message\n * // or\n * spinner.stop('Finished processing')\n * ```\n */\n stop(...args: unknown[]) {\n // Clear internal state.\n this.#baseText = ''\n this.#progress = undefined\n // Reset shimmer animation state if shimmer is enabled.\n if (this.#shimmer) {\n this.#shimmer.currentDir = DIR_LTR\n this.#shimmer.step = 0\n }\n // Call parent stop first (clears screen, sets isSpinning = false).\n const result = this.#apply('stop', args)\n // Then clear text to avoid blank frame render.\n // This is safe now because isSpinning is false.\n super.text = ''\n return result\n }\n\n /**\n * Show a success message (\u2713) without stopping the spinner.\n * DESIGN DECISION: Unlike yocto-spinner, our `success()` does NOT stop the spinner.\n * This allows displaying success messages while continuing to spin for multi-step operations.\n * Use `successAndStop()` if you want to stop the spinner.\n *\n * @param text - Success message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n success(text?: string | undefined, ...extras: unknown[]) {\n return this.#showStatusAndKeepSpinning('success', [text, ...extras])\n }\n\n /**\n * Show a success message (\u2713) and stop the spinner.\n * Auto-clears the spinner line before displaying the success message.\n *\n * @param text - Success message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n successAndStop(text?: string | undefined, ...extras: unknown[]) {\n return this.#apply('success', [text, ...extras])\n }\n\n /**\n * Get or set the spinner text.\n * When called with no arguments, returns the current base text.\n * When called with text, updates the display and returns the spinner for chaining.\n *\n * @param value - Text to display (omit to get current text)\n * @returns Current text (getter) or this spinner (setter)\n *\n * @example\n * ```ts\n * // Setter\n * spinner.text('Loading data\u2026')\n * spinner.text('Processing\u2026')\n *\n * // Getter\n * const current = spinner.text()\n * console.log(current) // \"Processing\u2026\"\n * ```\n */\n text(): string\n text(value: string): Spinner\n text(value?: string): string | Spinner {\n // biome-ignore lint/complexity/noArguments: Function overload for getter/setter pattern.\n if (arguments.length === 0) {\n // Getter: return current base text\n return this.#baseText\n }\n // Setter: update base text and refresh display\n this.#baseText = value ?? ''\n this.#updateSpinnerText()\n return this as unknown as Spinner\n }\n\n /**\n * Show a warning message (\u26A0) without stopping the spinner.\n * Outputs to stderr and continues spinning.\n *\n * @param text - Warning message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n warn(text?: string | undefined, ...extras: unknown[]) {\n return this.#showStatusAndKeepSpinning('warn', [text, ...extras])\n }\n\n /**\n * Show a warning message (\u26A0) and stop the spinner.\n * Auto-clears the spinner line before displaying the warning message.\n *\n * @param text - Warning message to display\n * @param extras - Additional values to log\n * @returns This spinner for chaining\n */\n warnAndStop(text?: string | undefined, ...extras: unknown[]) {\n return this.#apply('warning', [text, ...extras])\n }\n\n /**\n * Toggle shimmer effect or update shimmer configuration.\n * Preserves shimmer config when toggling off, allowing easy re-enable.\n * Supports partial config updates to tweak specific properties.\n *\n * @param enabledOrConfig - Boolean to toggle, partial config to update, or direction string\n * @returns This spinner for chaining\n *\n * @example\n * // Toggle off (preserves config for later re-enable)\n * spinner.shimmer(false)\n *\n * // Toggle on (restores saved config or uses defaults)\n * spinner.shimmer(true)\n *\n * // Update specific properties\n * spinner.shimmer({ speed: 0.5 })\n * spinner.shimmer({ color: [255, 0, 0] })\n *\n * // Set direction\n * spinner.shimmer('rtl')\n */\n shimmer(\n enabledOrConfig:\n | boolean\n | Partial<ShimmerConfig>\n | ShimmerDirection\n | undefined,\n ): Spinner {\n if (enabledOrConfig === false) {\n // Disable shimmer but preserve config.\n this.#shimmer = undefined\n } else if (enabledOrConfig === true) {\n // Re-enable with saved config or defaults.\n if (this.#shimmerSavedConfig) {\n // Restore saved config.\n this.#shimmer = { ...this.#shimmerSavedConfig }\n } else {\n // Create default config.\n this.#shimmer = {\n color: COLOR_INHERIT,\n currentDir: DIR_LTR,\n mode: DIR_LTR,\n speed: 1 / 3,\n step: 0,\n } as ShimmerInfo\n this.#shimmerSavedConfig = this.#shimmer\n }\n } else if (typeof enabledOrConfig === 'string') {\n // Direction string - update existing or create new.\n if (this.#shimmer) {\n // Update existing shimmer direction.\n this.#shimmer = {\n ...this.#shimmer,\n mode: enabledOrConfig,\n }\n this.#shimmerSavedConfig = this.#shimmer\n } else if (this.#shimmerSavedConfig) {\n // Restore and update.\n this.#shimmer = {\n ...this.#shimmerSavedConfig,\n mode: enabledOrConfig,\n }\n this.#shimmerSavedConfig = this.#shimmer\n } else {\n // Create new with direction.\n this.#shimmer = {\n color: COLOR_INHERIT,\n currentDir: DIR_LTR,\n mode: enabledOrConfig,\n speed: 1 / 3,\n step: 0,\n } as ShimmerInfo\n this.#shimmerSavedConfig = this.#shimmer\n }\n } else if (enabledOrConfig && typeof enabledOrConfig === 'object') {\n // Partial config update - merge with existing or saved config.\n const partialConfig = {\n __proto__: null,\n ...enabledOrConfig,\n } as Partial<ShimmerConfig>\n\n if (this.#shimmer) {\n // Update existing shimmer.\n this.#shimmer = {\n ...this.#shimmer,\n ...(partialConfig.color !== undefined\n ? { color: partialConfig.color }\n : {}),\n ...(partialConfig.dir !== undefined\n ? { mode: partialConfig.dir }\n : {}),\n ...(partialConfig.speed !== undefined\n ? { speed: partialConfig.speed }\n : {}),\n } as ShimmerInfo\n this.#shimmerSavedConfig = this.#shimmer\n } else if (this.#shimmerSavedConfig) {\n // Restore and update.\n this.#shimmer = {\n ...this.#shimmerSavedConfig,\n ...(partialConfig.color !== undefined\n ? { color: partialConfig.color }\n : {}),\n ...(partialConfig.dir !== undefined\n ? { mode: partialConfig.dir }\n : {}),\n ...(partialConfig.speed !== undefined\n ? { speed: partialConfig.speed }\n : {}),\n } as ShimmerInfo\n this.#shimmerSavedConfig = this.#shimmer\n } else {\n // Create new with partial config.\n this.#shimmer = {\n color: partialConfig.color ?? COLOR_INHERIT,\n currentDir: DIR_LTR,\n mode: partialConfig.dir ?? DIR_LTR,\n speed: partialConfig.speed ?? 1 / 3,\n step: 0,\n } as ShimmerInfo\n this.#shimmerSavedConfig = this.#shimmer\n }\n }\n\n this.#updateSpinnerText()\n return this as unknown as Spinner\n }\n } as unknown as {\n new (options?: SpinnerOptions | undefined): Spinner\n }\n // Add aliases.\n Object.defineProperties(_Spinner.prototype, {\n error: desc(_Spinner.prototype.fail),\n errorAndStop: desc(_Spinner.prototype.failAndStop),\n warning: desc(_Spinner.prototype.warn),\n warningAndStop: desc(_Spinner.prototype.warnAndStop),\n })\n _defaultSpinner = getCI()\n ? ciSpinner\n : (getCliSpinners('socket') as SpinnerStyle)\n }\n return new _Spinner({\n spinner: _defaultSpinner,\n ...options,\n })\n}\n\nlet _spinner: ReturnType<typeof Spinner> | undefined\n\n/**\n * Get the default spinner instance.\n * Lazily creates the spinner to avoid circular dependencies during module initialization.\n * Reuses the same instance across calls.\n *\n * @returns Shared default spinner instance\n *\n * @example\n * ```ts\n * import { getDefaultSpinner } from '@socketsecurity/registry/lib/spinner'\n *\n * const spinner = getDefaultSpinner()\n * spinner.start('Loading\u2026')\n * ```\n */\nexport function getDefaultSpinner(): ReturnType<typeof Spinner> {\n if (_spinner === undefined) {\n _spinner = Spinner()\n }\n return _spinner\n}\n\n/**\n * Default shared spinner instance (lazily initialized).\n *\n * @deprecated Use `getDefaultSpinner()` function instead for better tree-shaking and to avoid circular dependencies.\n *\n * @example\n * ```ts\n * // Old (deprecated):\n * import { spinner } from '@socketsecurity/registry/lib/spinner'\n * spinner.start('Loading\u2026')\n *\n * // New (recommended):\n * import { getDefaultSpinner } from '@socketsecurity/registry/lib/spinner'\n * const spinner = getDefaultSpinner()\n * spinner.start('Loading\u2026')\n * ```\n */\nexport const spinner = /* @__PURE__ */ (() => {\n // Lazy initialization to prevent circular dependency issues during module loading.\n let _lazySpinner: ReturnType<typeof Spinner> | undefined\n return new Proxy({} as ReturnType<typeof Spinner>, {\n get(_target, prop) {\n if (_lazySpinner === undefined) {\n _lazySpinner = Spinner()\n }\n const value = _lazySpinner[prop as keyof ReturnType<typeof Spinner>]\n return typeof value === 'function' ? value.bind(_lazySpinner) : value\n },\n })\n})()\n\n/**\n * Configuration options for `withSpinner()` helper.\n * @template T - Return type of the async operation\n */\nexport type WithSpinnerOptions<T> = {\n /** Message to display while the spinner is running */\n message: string\n /** Async function to execute while spinner is active */\n operation: () => Promise<T>\n /**\n * Optional spinner instance to use.\n * If not provided, operation runs without spinner.\n */\n spinner?: Spinner | undefined\n}\n\n/**\n * Execute an async operation with spinner lifecycle management.\n * Ensures `spinner.stop()` is always called via try/finally, even if the operation throws.\n * Provides safe cleanup and consistent spinner behavior.\n *\n * @template T - Return type of the operation\n * @param options - Configuration object\n * @param options.message - Message to display while spinner is running\n * @param options.operation - Async function to execute\n * @param options.spinner - Optional spinner instance (if not provided, no spinner is used)\n * @returns Result of the operation\n * @throws Re-throws any error from operation after stopping spinner\n *\n * @example\n * ```ts\n * import { Spinner, withSpinner } from '@socketsecurity/registry/lib/spinner'\n *\n * const spinner = Spinner()\n *\n * // With spinner instance\n * const result = await withSpinner({\n * message: 'Processing\u2026',\n * operation: async () => {\n * return await processData()\n * },\n * spinner\n * })\n *\n * // Without spinner instance (no-op, just runs operation)\n * const result = await withSpinner({\n * message: 'Processing\u2026',\n * operation: async () => {\n * return await processData()\n * }\n * })\n * ```\n */\nexport async function withSpinner<T>(\n options: WithSpinnerOptions<T>,\n): Promise<T> {\n const { message, operation, spinner } = {\n __proto__: null,\n ...options,\n } as WithSpinnerOptions<T>\n\n if (!spinner) {\n return await operation()\n }\n\n spinner.start(message)\n try {\n return await operation()\n } finally {\n spinner.stop()\n }\n}\n\n/**\n * Configuration options for `withSpinnerRestore()` helper.\n * @template T - Return type of the async operation\n */\nexport type WithSpinnerRestoreOptions<T> = {\n /** Async function to execute while spinner is stopped */\n operation: () => Promise<T>\n /** Optional spinner instance to restore after operation */\n spinner?: Spinner | undefined\n /** Whether spinner was spinning before the operation (used to conditionally restart) */\n wasSpinning: boolean\n}\n\n/**\n * Execute an async operation with conditional spinner restart.\n * Useful when you need to temporarily stop a spinner for an operation,\n * then restore it to its previous state (if it was spinning).\n *\n * @template T - Return type of the operation\n * @param options - Configuration object\n * @param options.operation - Async function to execute\n * @param options.spinner - Optional spinner instance to manage\n * @param options.wasSpinning - Whether spinner was spinning before the operation\n * @returns Result of the operation\n * @throws Re-throws any error from operation after restoring spinner state\n *\n * @example\n * ```ts\n * import { getDefaultSpinner, withSpinnerRestore } from '@socketsecurity/registry/lib/spinner'\n *\n * const spinner = getDefaultSpinner()\n * const wasSpinning = spinner.isSpinning\n * spinner.stop()\n *\n * const result = await withSpinnerRestore({\n * operation: async () => {\n * // Do work without spinner\n * return await someOperation()\n * },\n * spinner,\n * wasSpinning\n * })\n * // Spinner is automatically restarted if wasSpinning was true\n * ```\n */\nexport async function withSpinnerRestore<T>(\n options: WithSpinnerRestoreOptions<T>,\n): Promise<T> {\n const { operation, spinner, wasSpinning } = {\n __proto__: null,\n ...options,\n } as WithSpinnerRestoreOptions<T>\n\n try {\n return await operation()\n } finally {\n if (spinner && wasSpinning) {\n spinner.start()\n }\n }\n}\n\n/**\n * Configuration options for `withSpinnerSync()` helper.\n * @template T - Return type of the sync operation\n */\nexport type WithSpinnerSyncOptions<T> = {\n /** Message to display while the spinner is running */\n message: string\n /** Synchronous function to execute while spinner is active */\n operation: () => T\n /**\n * Optional spinner instance to use.\n * If not provided, operation runs without spinner.\n */\n spinner?: Spinner | undefined\n}\n\n/**\n * Execute a synchronous operation with spinner lifecycle management.\n * Ensures `spinner.stop()` is always called via try/finally, even if the operation throws.\n * Provides safe cleanup and consistent spinner behavior for sync operations.\n *\n * @template T - Return type of the operation\n * @param options - Configuration object\n * @param options.message - Message to display while spinner is running\n * @param options.operation - Synchronous function to execute\n * @param options.spinner - Optional spinner instance (if not provided, no spinner is used)\n * @returns Result of the operation\n * @throws Re-throws any error from operation after stopping spinner\n *\n * @example\n * ```ts\n * import { Spinner, withSpinnerSync } from '@socketsecurity/registry/lib/spinner'\n *\n * const spinner = Spinner()\n *\n * const result = withSpinnerSync({\n * message: 'Processing\u2026',\n * operation: () => {\n * return processDataSync()\n * },\n * spinner\n * })\n * ```\n */\nexport function withSpinnerSync<T>(options: WithSpinnerSyncOptions<T>): T {\n const { message, operation, spinner } = {\n __proto__: null,\n ...options,\n } as WithSpinnerSyncOptions<T>\n\n if (!spinner) {\n return operation()\n }\n\n spinner.start(message)\n try {\n return operation()\n } finally {\n spinner.stop()\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["spinner_exports", "__export", "Spinner", "ciSpinner", "getCliSpinners", "getDefaultSpinner", "spinner", "withSpinner", "withSpinnerRestore", "withSpinnerSync", "__toCommonJS", "import_ci", "import_pulse_frames", "import_text_shimmer", "import_yocto_spinner", "import_objects", "import_strings", "colorToRgb", "isRgbTuple", "value", "toRgb", "color", "desc", "normalizeText", "formatProgress", "progress", "current", "total", "unit", "percentage", "bar", "renderProgressBar", "count", "width", "filled", "empty", "_cliSpinners", "styleName", "yoctoSpinner", "_Spinner", "_defaultSpinner", "options", "YoctoSpinnerClass", "#baseText", "#indentation", "#progress", "#shimmer", "#shimmerSavedConfig", "opts", "spinnerColor", "n", "spinnerColorRgb", "shimmerInfo", "shimmerDir", "shimmerColor", "shimmerSpeed", "shimmerConfig", "frame", "text", "applyColor", "spacing", "#buildDisplayText", "#apply", "methodName", "args", "extras", "wasSpinning", "normalized", "incLogCallCountSymbol", "lastWasBlankSymbol", "logger", "displayText", "progressText", "#showStatusAndKeepSpinning", "symbolType", "LOG_SYMBOLS", "#updateSpinnerText", "isDebug", "spaces", "amount", "newLength", "newCurrent", "result", "enabledOrConfig", "partialConfig", "_spinner", "_lazySpinner", "_target", "prop", "message", "operation"]
7
7
  }