@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/fs.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/fs.ts"],
4
- "sourcesContent": ["/**\n * @fileoverview File system utilities with cross-platform path handling.\n * Provides enhanced fs operations, glob matching, and directory traversal functions.\n */\n\nimport type { Abortable } from 'node:events'\nimport type {\n Dirent,\n ObjectEncodingOptions,\n OpenMode,\n PathLike,\n StatSyncOptions,\n WriteFileOptions,\n} from 'node:fs'\n\nimport { getAbortSignal } from '#constants/process'\n\nimport { isArray } from './arrays'\n\nconst abortSignal = getAbortSignal()\n\nimport { defaultIgnore, getGlobMatcher } from './globs'\nimport type { JsonReviver } from './json'\nimport { jsonParse } from './json'\nimport { objectFreeze, type Remap } from './objects'\nimport { normalizePath, pathLikeToString } from './path'\nimport { naturalCompare } from './sorts'\n\n/**\n * Supported text encodings for Node.js Buffers.\n * Includes ASCII, UTF-8/16, base64, binary, and hexadecimal encodings.\n */\nexport type BufferEncoding =\n | 'ascii'\n | 'utf8'\n | 'utf-8'\n | 'utf16le'\n | 'ucs2'\n | 'ucs-2'\n | 'base64'\n | 'base64url'\n | 'latin1'\n | 'binary'\n | 'hex'\n\n/**\n * Represents any valid JSON content type.\n */\nexport type JsonContent = unknown\n\n/**\n * Options for asynchronous `findUp` operations.\n */\nexport interface FindUpOptions {\n /**\n * Starting directory for the search.\n * @default process.cwd()\n */\n cwd?: string | undefined\n /**\n * Only match directories, not files.\n * @default false\n */\n onlyDirectories?: boolean | undefined\n /**\n * Only match files, not directories.\n * @default true\n */\n onlyFiles?: boolean | undefined\n /**\n * Abort signal to cancel the search operation.\n */\n signal?: AbortSignal | undefined\n}\n\n/**\n * Options for synchronous `findUpSync` operations.\n */\nexport interface FindUpSyncOptions {\n /**\n * Starting directory for the search.\n * @default process.cwd()\n */\n cwd?: string | undefined\n /**\n * Directory to stop searching at (inclusive).\n * When provided, search will stop at this directory even if the root hasn't been reached.\n */\n stopAt?: string | undefined\n /**\n * Only match directories, not files.\n * @default false\n */\n onlyDirectories?: boolean | undefined\n /**\n * Only match files, not directories.\n * @default true\n */\n onlyFiles?: boolean | undefined\n}\n\n/**\n * Options for checking if a directory is empty.\n */\nexport interface IsDirEmptyOptions {\n /**\n * Glob patterns for files to ignore when checking emptiness.\n * Files matching these patterns are not counted.\n * @default defaultIgnore\n */\n ignore?: string[] | readonly string[] | undefined\n}\n\n/**\n * Options for read operations with abort support.\n */\nexport interface ReadOptions extends Abortable {\n /**\n * Character encoding to use for reading.\n * @default 'utf8'\n */\n encoding?: BufferEncoding | string | undefined\n /**\n * File system flag for reading behavior.\n * @default 'r'\n */\n flag?: string | undefined\n}\n\n/**\n * Options for reading directories with filtering and sorting.\n */\nexport interface ReadDirOptions {\n /**\n * Glob patterns for directories to ignore.\n * @default undefined\n */\n ignore?: string[] | readonly string[] | undefined\n /**\n * Include empty directories in results.\n * When `false`, empty directories are filtered out.\n * @default true\n */\n includeEmpty?: boolean | undefined\n /**\n * Sort directory names alphabetically using natural sort order.\n * @default true\n */\n sort?: boolean | undefined\n}\n\n/**\n * Options for reading files with encoding and abort support.\n * Can be either an options object, an encoding string, or null.\n */\nexport type ReadFileOptions =\n | Remap<\n ObjectEncodingOptions &\n Abortable & {\n flag?: OpenMode | undefined\n }\n >\n | BufferEncoding\n | null\n\n/**\n * Options for reading and parsing JSON files.\n */\nexport type ReadJsonOptions = Remap<\n ReadFileOptions & {\n /**\n * Whether to throw errors on parse failure.\n * When `false`, returns `undefined` on error instead of throwing.\n * @default true\n */\n throws?: boolean | undefined\n /**\n * JSON reviver function to transform parsed values.\n * Same as the second parameter to `JSON.parse()`.\n */\n reviver?: Parameters<typeof JSON.parse>[1] | undefined\n }\n>\n\n/**\n * Options for file/directory removal operations.\n */\nexport interface RemoveOptions {\n /**\n * Force deletion even outside normally safe directories.\n * When `false`, prevents deletion outside temp, cacache, and ~/.socket.\n * @default true for safe directories, false otherwise\n */\n force?: boolean | undefined\n /**\n * Maximum number of retry attempts on failure.\n * @default 3\n */\n maxRetries?: number | undefined\n /**\n * Recursively delete directories and contents.\n * @default true\n */\n recursive?: boolean | undefined\n /**\n * Delay in milliseconds between retry attempts.\n * @default 200\n */\n retryDelay?: number | undefined\n /**\n * Abort signal to cancel the operation.\n */\n signal?: AbortSignal | undefined\n}\n\n/**\n * Options for safe read operations that don't throw on errors.\n */\nexport interface SafeReadOptions extends ReadOptions {\n /**\n * Default value to return on read failure.\n * If not provided, `undefined` is returned on error.\n */\n defaultValue?: unknown | undefined\n}\n\n/**\n * Options for write operations with encoding and mode control.\n */\nexport interface WriteOptions extends Abortable {\n /**\n * Character encoding for writing.\n * @default 'utf8'\n */\n encoding?: BufferEncoding | string | undefined\n /**\n * File mode (permissions) to set.\n * Uses standard Unix permission bits (e.g., 0o644).\n * @default 0o666 (read/write for all, respecting umask)\n */\n mode?: number | undefined\n /**\n * File system flag for write behavior.\n * @default 'w' (create or truncate)\n */\n flag?: string | undefined\n}\n\n/**\n * Options for writing JSON files with formatting control.\n */\nexport interface WriteJsonOptions extends WriteOptions {\n /**\n * End-of-line sequence to use.\n * @default '\\n'\n * @example\n * ```ts\n * // Windows-style line endings\n * writeJson('data.json', data, { EOL: '\\r\\n' })\n * ```\n */\n EOL?: string | undefined\n /**\n * Whether to add a final newline at end of file.\n * @default true\n */\n finalEOL?: boolean | undefined\n /**\n * JSON replacer function to transform values during stringification.\n * Same as the second parameter to `JSON.stringify()`.\n */\n replacer?: JsonReviver | undefined\n /**\n * Number of spaces for indentation, or string to use for indentation.\n * @default 2\n * @example\n * ```ts\n * // Use tabs instead of spaces\n * writeJson('data.json', data, { spaces: '\\t' })\n *\n * // Use 4 spaces for indentation\n * writeJson('data.json', data, { spaces: 4 })\n * ```\n */\n spaces?: number | string | undefined\n}\n\nconst defaultRemoveOptions = objectFreeze({\n __proto__: null,\n force: true,\n maxRetries: 3,\n recursive: true,\n retryDelay: 200,\n})\n\nlet _fs: typeof import('fs') | undefined\n/**\n * Lazily load the fs module to avoid Webpack errors.\n * Uses non-'node:' prefixed require to prevent Webpack bundling issues.\n *\n * @returns The Node.js fs module\n * @private\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getFs() {\n if (_fs === undefined) {\n // Use non-'node:' prefixed require to avoid Webpack errors.\n\n _fs = /*@__PURE__*/ require('node:fs')\n }\n return _fs as typeof import('fs')\n}\n\nlet _path: typeof import('path') | undefined\n/**\n * Lazily load the path module to avoid Webpack errors.\n * Uses non-'node:' prefixed require to prevent Webpack bundling issues.\n *\n * @returns The Node.js path module\n * @private\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('path')\n}\n\nlet _os: typeof import('os') | undefined\n/**\n * Lazily load the os module to avoid Webpack errors.\n * Uses non-'node:' prefixed require to prevent Webpack bundling issues.\n *\n * @returns The Node.js os module\n * @private\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getOs() {\n if (_os === undefined) {\n // Use non-'node:' prefixed require to avoid Webpack errors.\n\n _os = /*@__PURE__*/ require('node:os')\n }\n return _os as typeof import('os')\n}\n\n/**\n * Process directory entries and filter for directories.\n * Filters entries to include only directories, optionally excluding empty ones.\n * Applies ignore patterns and natural sorting.\n *\n * @param dirents - Directory entries from readdir\n * @param dirname - Parent directory path\n * @param options - Filtering and sorting options\n * @returns Array of directory names, optionally sorted\n * @private\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction innerReadDirNames(\n dirents: Dirent[],\n dirname: string | undefined,\n options?: ReadDirOptions | undefined,\n): string[] {\n const {\n ignore,\n includeEmpty = true,\n sort = true,\n } = { __proto__: null, ...options } as ReadDirOptions\n const path = getPath()\n const names = dirents\n .filter(\n (d: Dirent) =>\n d.isDirectory() &&\n (includeEmpty ||\n !isDirEmptySync(path.join(dirname || d.parentPath, d.name), {\n ignore,\n })),\n )\n .map((d: Dirent) => d.name)\n return sort ? names.sort(naturalCompare) : names\n}\n\n/**\n * Stringify JSON with custom formatting options.\n * Formats JSON with configurable line endings and indentation.\n *\n * @param json - Value to stringify\n * @param EOL - End-of-line sequence\n * @param finalEOL - Whether to add final newline\n * @param replacer - JSON replacer function\n * @param spaces - Indentation spaces or string\n * @returns Formatted JSON string\n * @private\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction stringify(\n json: unknown,\n EOL: string,\n finalEOL: boolean,\n replacer: JsonReviver | undefined,\n spaces: number | string = 2,\n): string {\n const EOF = finalEOL ? EOL : ''\n const str = JSON.stringify(json, replacer, spaces)\n return `${str.replace(/\\n/g, EOL)}${EOF}`\n}\n\n/**\n * Find a file or directory by traversing up parent directories.\n * Searches from the starting directory upward to the filesystem root.\n * Useful for finding configuration files or project roots.\n *\n * @param name - Filename(s) to search for\n * @param options - Search options including cwd and type filters\n * @returns Normalized absolute path if found, undefined otherwise\n *\n * @example\n * ```ts\n * // Find package.json starting from current directory\n * const pkgPath = await findUp('package.json')\n *\n * // Find any of multiple config files\n * const configPath = await findUp(['.config.js', '.config.json'])\n *\n * // Find a directory instead of file\n * const nodeModules = await findUp('node_modules', { onlyDirectories: true })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function findUp(\n name: string | string[] | readonly string[],\n options?: FindUpOptions | undefined,\n): Promise<string | undefined> {\n const { cwd = process.cwd(), signal = abortSignal } = {\n __proto__: null,\n ...options,\n } as FindUpOptions\n let { onlyDirectories = false, onlyFiles = true } = {\n __proto__: null,\n ...options,\n } as FindUpOptions\n if (onlyDirectories) {\n onlyFiles = false\n }\n if (onlyFiles) {\n onlyDirectories = false\n }\n const fs = getFs()\n const path = getPath()\n let dir = path.resolve(cwd)\n const { root } = path.parse(dir)\n const names = isArray(name) ? name : [name as string]\n while (dir && dir !== root) {\n for (const n of names) {\n if (signal?.aborted) {\n return undefined\n }\n const thePath = path.join(dir, n)\n try {\n // eslint-disable-next-line no-await-in-loop\n const stats = await fs.promises.stat(thePath)\n if (!onlyDirectories && stats.isFile()) {\n return normalizePath(thePath)\n }\n if (!onlyFiles && stats.isDirectory()) {\n return normalizePath(thePath)\n }\n } catch {}\n }\n dir = path.dirname(dir)\n }\n return undefined\n}\n\n/**\n * Synchronously find a file or directory by traversing up parent directories.\n * Searches from the starting directory upward to the filesystem root or `stopAt` directory.\n * Useful for finding configuration files or project roots in synchronous contexts.\n *\n * @param name - Filename(s) to search for\n * @param options - Search options including cwd, stopAt, and type filters\n * @returns Normalized absolute path if found, undefined otherwise\n *\n * @example\n * ```ts\n * // Find package.json starting from current directory\n * const pkgPath = findUpSync('package.json')\n *\n * // Find .git directory but stop at home directory\n * const gitPath = findUpSync('.git', {\n * onlyDirectories: true,\n * stopAt: process.env.HOME\n * })\n *\n * // Find any of multiple config files\n * const configPath = findUpSync(['.eslintrc.js', '.eslintrc.json'])\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function findUpSync(\n name: string | string[] | readonly string[],\n options?: FindUpSyncOptions | undefined,\n) {\n const { cwd = process.cwd(), stopAt } = {\n __proto__: null,\n ...options,\n } as FindUpSyncOptions\n let { onlyDirectories = false, onlyFiles = true } = {\n __proto__: null,\n ...options,\n } as FindUpSyncOptions\n if (onlyDirectories) {\n onlyFiles = false\n }\n if (onlyFiles) {\n onlyDirectories = false\n }\n const fs = getFs()\n const path = getPath()\n let dir = path.resolve(cwd)\n const { root } = path.parse(dir)\n const stopDir = stopAt ? path.resolve(stopAt) : undefined\n const names = isArray(name) ? name : [name as string]\n while (dir && dir !== root) {\n // Check if we should stop at this directory.\n if (stopDir && dir === stopDir) {\n // Check current directory but don't go up.\n for (const n of names) {\n const thePath = path.join(dir, n)\n try {\n const stats = fs.statSync(thePath)\n if (!onlyDirectories && stats.isFile()) {\n return normalizePath(thePath)\n }\n if (!onlyFiles && stats.isDirectory()) {\n return normalizePath(thePath)\n }\n } catch {}\n }\n return undefined\n }\n for (const n of names) {\n const thePath = path.join(dir, n)\n try {\n const stats = fs.statSync(thePath)\n if (!onlyDirectories && stats.isFile()) {\n return normalizePath(thePath)\n }\n if (!onlyFiles && stats.isDirectory()) {\n return normalizePath(thePath)\n }\n } catch {}\n }\n dir = path.dirname(dir)\n }\n return undefined\n}\n\n/**\n * Check if a path is a directory asynchronously.\n * Returns `true` for directories, `false` for files or non-existent paths.\n *\n * @param filepath - Path to check\n * @returns `true` if path is a directory, `false` otherwise\n *\n * @example\n * ```ts\n * if (await isDir('./src')) {\n * console.log('src is a directory')\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function isDir(filepath: PathLike) {\n return !!(await safeStats(filepath))?.isDirectory()\n}\n\n/**\n * Check if a path is a directory synchronously.\n * Returns `true` for directories, `false` for files or non-existent paths.\n *\n * @param filepath - Path to check\n * @returns `true` if path is a directory, `false` otherwise\n *\n * @example\n * ```ts\n * if (isDirSync('./src')) {\n * console.log('src is a directory')\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function isDirSync(filepath: PathLike) {\n return !!safeStatsSync(filepath)?.isDirectory()\n}\n\n/**\n * Check if a directory is empty synchronously.\n * A directory is considered empty if it contains no files after applying ignore patterns.\n * Uses glob patterns to filter ignored files.\n *\n * @param dirname - Directory path to check\n * @param options - Options including ignore patterns\n * @returns `true` if directory is empty (or doesn't exist), `false` otherwise\n *\n * @example\n * ```ts\n * // Check if directory is completely empty\n * isDirEmptySync('./build')\n *\n * // Check if directory is empty, ignoring .DS_Store files\n * isDirEmptySync('./cache', { ignore: ['.DS_Store'] })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function isDirEmptySync(\n dirname: PathLike,\n options?: IsDirEmptyOptions | undefined,\n) {\n const { ignore = defaultIgnore } = {\n __proto__: null,\n ...options,\n } as IsDirEmptyOptions\n const fs = getFs()\n try {\n const files = fs.readdirSync(dirname)\n const { length } = files\n if (length === 0) {\n return true\n }\n const matcher = getGlobMatcher(\n ignore as string[],\n {\n cwd: pathLikeToString(dirname),\n } as { cwd?: string; dot?: boolean; ignore?: string[]; nocase?: boolean },\n )\n let ignoredCount = 0\n for (let i = 0; i < length; i += 1) {\n const file = files[i]\n if (file && matcher(file)) {\n ignoredCount += 1\n }\n }\n return ignoredCount === length\n } catch {\n // Return false for non-existent paths or other errors.\n return false\n }\n}\n\n/**\n * Check if a path is a symbolic link synchronously.\n * Uses `lstat` to check the link itself, not the target.\n *\n * @param filepath - Path to check\n * @returns `true` if path is a symbolic link, `false` otherwise\n *\n * @example\n * ```ts\n * if (isSymLinkSync('./my-link')) {\n * console.log('Path is a symbolic link')\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function isSymLinkSync(filepath: PathLike) {\n const fs = getFs()\n try {\n return fs.lstatSync(filepath).isSymbolicLink()\n } catch {}\n return false\n}\n\n/**\n * Result of file readability validation.\n * Contains lists of valid and invalid file paths.\n */\nexport interface ValidateFilesResult {\n /**\n * File paths that passed validation and are readable.\n */\n validPaths: string[]\n /**\n * File paths that failed validation (unreadable, permission denied, or non-existent).\n * Common with Yarn Berry PnP virtual filesystem, pnpm symlinks, or filesystem race conditions.\n */\n invalidPaths: string[]\n}\n\n/**\n * Validate that file paths are readable before processing.\n * Filters out files from glob results that cannot be accessed (common with\n * Yarn Berry PnP virtual filesystem, pnpm content-addressable store symlinks,\n * or filesystem race conditions in CI/CD environments).\n *\n * This defensive pattern prevents ENOENT errors when files exist in glob\n * results but are not accessible via standard filesystem operations.\n *\n * @param filepaths - Array of file paths to validate\n * @returns Object with `validPaths` (readable) and `invalidPaths` (unreadable)\n *\n * @example\n * ```ts\n * import { validateFiles } from '@socketsecurity/lib/fs'\n *\n * const files = ['package.json', '.pnp.cjs/virtual-file.json']\n * const { validPaths, invalidPaths } = validateFiles(files)\n *\n * console.log(`Valid: ${validPaths.length}`)\n * console.log(`Invalid: ${invalidPaths.length}`)\n * ```\n *\n * @example\n * ```ts\n * // Typical usage in Socket CLI commands\n * const packagePaths = await getPackageFilesForScan(targets)\n * const { validPaths } = validateFiles(packagePaths)\n * await sdk.uploadManifestFiles(orgSlug, validPaths)\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function validateFiles(\n filepaths: string[] | readonly string[],\n): ValidateFilesResult {\n const fs = getFs()\n const validPaths: string[] = []\n const invalidPaths: string[] = []\n const { R_OK } = fs.constants\n\n for (const filepath of filepaths) {\n try {\n fs.accessSync(filepath, R_OK)\n validPaths.push(filepath)\n } catch {\n invalidPaths.push(filepath)\n }\n }\n\n return { __proto__: null, validPaths, invalidPaths } as ValidateFilesResult\n}\n\n/**\n * Read directory names asynchronously with filtering and sorting.\n * Returns only directory names (not files), with optional filtering for empty directories\n * and glob-based ignore patterns. Results are naturally sorted by default.\n *\n * @param dirname - Directory path to read\n * @param options - Options for filtering and sorting\n * @returns Array of directory names, empty array on error\n *\n * @example\n * ```ts\n * // Get all subdirectories, sorted naturally\n * const dirs = await readDirNames('./packages')\n *\n * // Get non-empty directories only\n * const nonEmpty = await readDirNames('./cache', { includeEmpty: false })\n *\n * // Get directories without sorting\n * const unsorted = await readDirNames('./src', { sort: false })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function readDirNames(\n dirname: PathLike,\n options?: ReadDirOptions | undefined,\n) {\n const fs = getFs()\n try {\n return innerReadDirNames(\n await fs.promises.readdir(dirname, {\n __proto__: null,\n encoding: 'utf8',\n withFileTypes: true,\n } as ObjectEncodingOptions & { withFileTypes: true }),\n String(dirname),\n options,\n )\n } catch {}\n return []\n}\n\n/**\n * Read directory names synchronously with filtering and sorting.\n * Returns only directory names (not files), with optional filtering for empty directories\n * and glob-based ignore patterns. Results are naturally sorted by default.\n *\n * @param dirname - Directory path to read\n * @param options - Options for filtering and sorting\n * @returns Array of directory names, empty array on error\n *\n * @example\n * ```ts\n * // Get all subdirectories, sorted naturally\n * const dirs = readDirNamesSync('./packages')\n *\n * // Get non-empty directories only, ignoring node_modules\n * const nonEmpty = readDirNamesSync('./src', {\n * includeEmpty: false,\n * ignore: ['node_modules']\n * })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function readDirNamesSync(dirname: PathLike, options?: ReadDirOptions) {\n const fs = getFs()\n try {\n return innerReadDirNames(\n fs.readdirSync(dirname, {\n __proto__: null,\n encoding: 'utf8',\n withFileTypes: true,\n } as ObjectEncodingOptions & { withFileTypes: true }),\n String(dirname),\n options,\n )\n } catch {}\n return []\n}\n\n/**\n * Read a file as binary data asynchronously.\n * Returns a Buffer without encoding the contents.\n * Useful for reading images, archives, or other binary formats.\n *\n * @param filepath - Path to file\n * @param options - Read options (encoding is forced to null for binary)\n * @returns Promise resolving to Buffer containing file contents\n *\n * @example\n * ```ts\n * // Read an image file\n * const imageBuffer = await readFileBinary('./image.png')\n *\n * // Read with abort signal\n * const buffer = await readFileBinary('./data.bin', { signal: abortSignal })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function readFileBinary(\n filepath: PathLike,\n options?: ReadFileOptions | undefined,\n) {\n // Don't specify encoding to get a Buffer.\n const opts = typeof options === 'string' ? { encoding: options } : options\n const fs = getFs()\n return await fs.promises.readFile(filepath, {\n signal: abortSignal,\n ...opts,\n encoding: null,\n })\n}\n\n/**\n * Read a file as UTF-8 text asynchronously.\n * Returns a string with the file contents decoded as UTF-8.\n * This is the most common way to read text files.\n *\n * @param filepath - Path to file\n * @param options - Read options including encoding and abort signal\n * @returns Promise resolving to string containing file contents\n *\n * @example\n * ```ts\n * // Read a text file\n * const content = await readFileUtf8('./README.md')\n *\n * // Read with custom encoding\n * const content = await readFileUtf8('./data.txt', { encoding: 'utf-8' })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function readFileUtf8(\n filepath: PathLike,\n options?: ReadFileOptions | undefined,\n) {\n const opts = typeof options === 'string' ? { encoding: options } : options\n const fs = getFs()\n return await fs.promises.readFile(filepath, {\n signal: abortSignal,\n ...opts,\n encoding: 'utf8',\n })\n}\n\n/**\n * Read a file as binary data synchronously.\n * Returns a Buffer without encoding the contents.\n * Useful for reading images, archives, or other binary formats.\n *\n * @param filepath - Path to file\n * @param options - Read options (encoding is forced to null for binary)\n * @returns Buffer containing file contents\n *\n * @example\n * ```ts\n * // Read an image file\n * const imageBuffer = readFileBinarySync('./logo.png')\n *\n * // Read a compressed file\n * const gzipData = readFileBinarySync('./archive.gz')\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function readFileBinarySync(\n filepath: PathLike,\n options?: ReadFileOptions | undefined,\n) {\n // Don't specify encoding to get a Buffer\n const opts = typeof options === 'string' ? { encoding: options } : options\n const fs = getFs()\n return fs.readFileSync(filepath, {\n ...opts,\n encoding: null,\n } as ObjectEncodingOptions)\n}\n\n/**\n * Read a file as UTF-8 text synchronously.\n * Returns a string with the file contents decoded as UTF-8.\n * This is the most common way to read text files synchronously.\n *\n * @param filepath - Path to file\n * @param options - Read options including encoding\n * @returns String containing file contents\n *\n * @example\n * ```ts\n * // Read a configuration file\n * const config = readFileUtf8Sync('./config.txt')\n *\n * // Read with custom options\n * const data = readFileUtf8Sync('./data.txt', { encoding: 'utf8' })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function readFileUtf8Sync(\n filepath: PathLike,\n options?: ReadFileOptions | undefined,\n) {\n const opts = typeof options === 'string' ? { encoding: options } : options\n const fs = getFs()\n return fs.readFileSync(filepath, {\n ...opts,\n encoding: 'utf8',\n } as ObjectEncodingOptions)\n}\n\n/**\n * Read and parse a JSON file asynchronously.\n * Reads the file as UTF-8 text and parses it as JSON.\n * Optionally accepts a reviver function to transform parsed values.\n *\n * @param filepath - Path to JSON file\n * @param options - Read and parse options\n * @returns Promise resolving to parsed JSON value, or undefined if throws is false and an error occurs\n *\n * @example\n * ```ts\n * // Read and parse package.json\n * const pkg = await readJson('./package.json')\n *\n * // Read JSON with custom reviver\n * const data = await readJson('./data.json', {\n * reviver: (key, value) => {\n * if (key === 'date') return new Date(value)\n * return value\n * }\n * })\n *\n * // Don't throw on parse errors\n * const config = await readJson('./config.json', { throws: false })\n * if (config === undefined) {\n * console.log('Failed to parse config')\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function readJson(\n filepath: PathLike,\n options?: ReadJsonOptions | string | undefined,\n) {\n const opts = typeof options === 'string' ? { encoding: options } : options\n const { reviver, throws, ...fsOptions } = {\n __proto__: null,\n ...opts,\n } as unknown as ReadJsonOptions\n const shouldThrow = throws === undefined || !!throws\n const fs = getFs()\n let content = ''\n try {\n content = await fs.promises.readFile(filepath, {\n __proto__: null,\n encoding: 'utf8',\n ...fsOptions,\n } as unknown as Parameters<typeof fs.promises.readFile>[1] & {\n encoding: string\n })\n } catch (e) {\n if (shouldThrow) {\n throw e\n }\n return undefined\n }\n return jsonParse(content, {\n filepath: String(filepath),\n reviver,\n throws: shouldThrow,\n })\n}\n\n/**\n * Read and parse a JSON file synchronously.\n * Reads the file as UTF-8 text and parses it as JSON.\n * Optionally accepts a reviver function to transform parsed values.\n *\n * @param filepath - Path to JSON file\n * @param options - Read and parse options\n * @returns Parsed JSON value, or undefined if throws is false and an error occurs\n *\n * @example\n * ```ts\n * // Read and parse tsconfig.json\n * const tsconfig = readJsonSync('./tsconfig.json')\n *\n * // Read JSON with custom reviver\n * const data = readJsonSync('./data.json', {\n * reviver: (key, value) => {\n * if (typeof value === 'string' && /^\\d{4}-\\d{2}-\\d{2}/.test(value)) {\n * return new Date(value)\n * }\n * return value\n * }\n * })\n *\n * // Don't throw on parse errors\n * const config = readJsonSync('./config.json', { throws: false })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function readJsonSync(\n filepath: PathLike,\n options?: ReadJsonOptions | string | undefined,\n) {\n const opts = typeof options === 'string' ? { encoding: options } : options\n const { reviver, throws, ...fsOptions } = {\n __proto__: null,\n ...opts,\n } as unknown as ReadJsonOptions\n const shouldThrow = throws === undefined || !!throws\n const fs = getFs()\n let content = ''\n try {\n content = fs.readFileSync(filepath, {\n __proto__: null,\n encoding: 'utf8',\n ...fsOptions,\n } as unknown as Parameters<typeof fs.readFileSync>[1] & {\n encoding: string\n })\n } catch (e) {\n if (shouldThrow) {\n throw e\n }\n return undefined\n }\n return jsonParse(content, {\n filepath: String(filepath),\n reviver,\n throws: shouldThrow,\n })\n}\n\n/**\n * Safely delete a file or directory asynchronously with built-in protections.\n * Uses `del` for safer deletion that prevents removing cwd and above by default.\n * Automatically uses force: true for temp directory, cacache, and ~/.socket subdirectories.\n *\n * @param filepath - Path or array of paths to delete (supports glob patterns)\n * @param options - Deletion options including force, retries, and recursion\n * @throws {Error} When attempting to delete protected paths without force option\n *\n * @example\n * ```ts\n * // Delete a single file\n * await safeDelete('./temp-file.txt')\n *\n * // Delete a directory recursively\n * await safeDelete('./build', { recursive: true })\n *\n * // Delete multiple paths\n * await safeDelete(['./dist', './coverage'])\n *\n * // Delete with custom retry settings\n * await safeDelete('./flaky-dir', { maxRetries: 5, retryDelay: 500 })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function safeDelete(\n filepath: PathLike | PathLike[],\n options?: RemoveOptions | undefined,\n) {\n const del = /*@__PURE__*/ require('./external/del')\n const { deleteAsync } = del\n const opts = { __proto__: null, ...options } as RemoveOptions\n const patterns = isArray(filepath)\n ? filepath.map(pathLikeToString)\n : [pathLikeToString(filepath)]\n\n // Check if we're deleting within allowed directories.\n let shouldForce = opts.force !== false\n if (!shouldForce && patterns.length > 0) {\n const os = getOs()\n const path = getPath()\n const {\n getSocketCacacheDir,\n getSocketUserDir,\n } = /*@__PURE__*/ require('./paths')\n\n // Get allowed directories\n const tmpDir = os.tmpdir()\n const resolvedTmpDir = path.resolve(tmpDir)\n const cacacheDir = getSocketCacacheDir()\n const resolvedCacacheDir = path.resolve(cacacheDir)\n const socketUserDir = getSocketUserDir()\n const resolvedSocketUserDir = path.resolve(socketUserDir)\n\n // Check if all patterns are within allowed directories.\n const allInAllowedDirs = patterns.every(pattern => {\n const resolvedPath = path.resolve(pattern)\n\n // Check each allowed directory\n for (const allowedDir of [\n resolvedTmpDir,\n resolvedCacacheDir,\n resolvedSocketUserDir,\n ]) {\n const isInAllowedDir =\n resolvedPath.startsWith(allowedDir + path.sep) ||\n resolvedPath === allowedDir\n const relativePath = path.relative(allowedDir, resolvedPath)\n const isGoingBackward = relativePath.startsWith('..')\n\n if (isInAllowedDir && !isGoingBackward) {\n return true\n }\n }\n\n return false\n })\n\n if (allInAllowedDirs) {\n shouldForce = true\n }\n }\n\n await deleteAsync(patterns, {\n concurrency: opts.maxRetries || defaultRemoveOptions.maxRetries,\n dryRun: false,\n force: shouldForce,\n onlyFiles: false,\n })\n}\n\n/**\n * Safely delete a file or directory synchronously with built-in protections.\n * Uses `del` for safer deletion that prevents removing cwd and above by default.\n * Automatically uses force: true for temp directory, cacache, and ~/.socket subdirectories.\n *\n * @param filepath - Path or array of paths to delete (supports glob patterns)\n * @param options - Deletion options including force, retries, and recursion\n * @throws {Error} When attempting to delete protected paths without force option\n *\n * @example\n * ```ts\n * // Delete a single file\n * safeDeleteSync('./temp-file.txt')\n *\n * // Delete a directory recursively\n * safeDeleteSync('./build', { recursive: true })\n *\n * // Delete multiple paths with globs\n * safeDeleteSync(['./dist/**', './coverage/**'])\n *\n * // Force delete a protected path (use with caution)\n * safeDeleteSync('./important', { force: true })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function safeDeleteSync(\n filepath: PathLike | PathLike[],\n options?: RemoveOptions | undefined,\n) {\n const del = /*@__PURE__*/ require('./external/del')\n const { deleteSync } = del\n const opts = { __proto__: null, ...options } as RemoveOptions\n const patterns = isArray(filepath)\n ? filepath.map(pathLikeToString)\n : [pathLikeToString(filepath)]\n\n // Check if we're deleting within allowed directories.\n let shouldForce = opts.force !== false\n if (!shouldForce && patterns.length > 0) {\n const os = getOs()\n const path = getPath()\n const {\n getSocketCacacheDir,\n getSocketUserDir,\n } = /*@__PURE__*/ require('./paths')\n\n // Get allowed directories\n const tmpDir = os.tmpdir()\n const resolvedTmpDir = path.resolve(tmpDir)\n const cacacheDir = getSocketCacacheDir()\n const resolvedCacacheDir = path.resolve(cacacheDir)\n const socketUserDir = getSocketUserDir()\n const resolvedSocketUserDir = path.resolve(socketUserDir)\n\n // Check if all patterns are within allowed directories.\n const allInAllowedDirs = patterns.every(pattern => {\n const resolvedPath = path.resolve(pattern)\n\n // Check each allowed directory\n for (const allowedDir of [\n resolvedTmpDir,\n resolvedCacacheDir,\n resolvedSocketUserDir,\n ]) {\n const isInAllowedDir =\n resolvedPath.startsWith(allowedDir + path.sep) ||\n resolvedPath === allowedDir\n const relativePath = path.relative(allowedDir, resolvedPath)\n const isGoingBackward = relativePath.startsWith('..')\n\n if (isInAllowedDir && !isGoingBackward) {\n return true\n }\n }\n\n return false\n })\n\n if (allInAllowedDirs) {\n shouldForce = true\n }\n }\n\n deleteSync(patterns, {\n concurrency: opts.maxRetries || defaultRemoveOptions.maxRetries,\n dryRun: false,\n force: shouldForce,\n onlyFiles: false,\n })\n}\n\n/**\n * Safely read a file asynchronously, returning undefined on error.\n * Useful when you want to attempt reading a file without handling errors explicitly.\n * Returns undefined for any error (file not found, permission denied, etc.).\n *\n * @param filepath - Path to file\n * @param options - Read options including encoding and default value\n * @returns Promise resolving to file contents, or undefined on error\n *\n * @example\n * ```ts\n * // Try to read a file, get undefined if it doesn't exist\n * const content = await safeReadFile('./optional-config.txt')\n * if (content) {\n * console.log('Config found:', content)\n * }\n *\n * // Read with specific encoding\n * const data = await safeReadFile('./data.txt', { encoding: 'utf8' })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function safeReadFile(\n filepath: PathLike,\n options?: SafeReadOptions | undefined,\n) {\n const opts = typeof options === 'string' ? { encoding: options } : options\n const fs = getFs()\n try {\n return await fs.promises.readFile(filepath, {\n signal: abortSignal,\n ...opts,\n } as Abortable)\n } catch {}\n return undefined\n}\n\n/**\n * Safely get file stats asynchronously, returning undefined on error.\n * Useful for checking file existence and properties without error handling.\n * Returns undefined for any error (file not found, permission denied, etc.).\n *\n * @param filepath - Path to check\n * @returns Promise resolving to Stats object, or undefined on error\n *\n * @example\n * ```ts\n * // Check if file exists and get its stats\n * const stats = await safeStats('./file.txt')\n * if (stats) {\n * console.log('File size:', stats.size)\n * console.log('Modified:', stats.mtime)\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function safeStats(filepath: PathLike) {\n const fs = getFs()\n try {\n return await fs.promises.stat(filepath)\n } catch {}\n return undefined\n}\n\n/**\n * Safely get file stats synchronously, returning undefined on error.\n * Useful for checking file existence and properties without error handling.\n * Returns undefined for any error (file not found, permission denied, etc.).\n *\n * @param filepath - Path to check\n * @param options - Read options (currently unused but kept for API consistency)\n * @returns Stats object, or undefined on error\n *\n * @example\n * ```ts\n * // Check if file exists and get its size\n * const stats = safeStatsSync('./file.txt')\n * if (stats) {\n * console.log('File size:', stats.size)\n * console.log('Is directory:', stats.isDirectory())\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function safeStatsSync(\n filepath: PathLike,\n options?: ReadFileOptions | undefined,\n) {\n const opts = typeof options === 'string' ? { encoding: options } : options\n const fs = getFs()\n try {\n return fs.statSync(filepath, {\n __proto__: null,\n throwIfNoEntry: false,\n ...opts,\n } as StatSyncOptions)\n } catch {}\n return undefined\n}\n\n/**\n * Safely read a file synchronously, returning undefined on error.\n * Useful when you want to attempt reading a file without handling errors explicitly.\n * Returns undefined for any error (file not found, permission denied, etc.).\n *\n * @param filepath - Path to file\n * @param options - Read options including encoding and default value\n * @returns File contents, or undefined on error\n *\n * @example\n * ```ts\n * // Try to read a config file\n * const config = safeReadFileSync('./config.txt')\n * if (config) {\n * console.log('Config loaded successfully')\n * }\n *\n * // Read binary file safely\n * const buffer = safeReadFileSync('./image.png', { encoding: null })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function safeReadFileSync(\n filepath: PathLike,\n options?: SafeReadOptions | undefined,\n) {\n const opts = typeof options === 'string' ? { encoding: options } : options\n const fs = getFs()\n try {\n return fs.readFileSync(filepath, {\n __proto__: null,\n ...opts,\n } as ObjectEncodingOptions)\n } catch {}\n return undefined\n}\n\n/**\n * Generate a unique filepath by adding number suffix if the path exists.\n * Appends `-1`, `-2`, etc. before the file extension until a non-existent path is found.\n * Useful for creating files without overwriting existing ones.\n *\n * @param filepath - Desired file path\n * @returns Normalized unique filepath (original if it doesn't exist, or with number suffix)\n *\n * @example\n * ```ts\n * // If 'report.pdf' exists, returns 'report-1.pdf'\n * const uniquePath = uniqueSync('./report.pdf')\n *\n * // If 'data.json' and 'data-1.json' exist, returns 'data-2.json'\n * const path = uniqueSync('./data.json')\n *\n * // If 'backup' doesn't exist, returns 'backup' unchanged\n * const backupPath = uniqueSync('./backup')\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function uniqueSync(filepath: PathLike): string {\n const fs = getFs()\n const path = getPath()\n const filepathStr = String(filepath)\n\n // If the file doesn't exist, return as is\n if (!fs.existsSync(filepathStr)) {\n return normalizePath(filepathStr)\n }\n\n const dirname = path.dirname(filepathStr)\n const ext = path.extname(filepathStr)\n const basename = path.basename(filepathStr, ext)\n\n let counter = 1\n let uniquePath: string\n do {\n uniquePath = path.join(dirname, `${basename}-${counter}${ext}`)\n counter++\n } while (fs.existsSync(uniquePath))\n\n return normalizePath(uniquePath)\n}\n\n/**\n * Write JSON content to a file asynchronously with formatting.\n * Stringifies the value with configurable indentation and line endings.\n * Automatically adds a final newline by default for POSIX compliance.\n *\n * @param filepath - Path to write to\n * @param jsonContent - Value to stringify and write\n * @param options - Write options including formatting and encoding\n * @returns Promise that resolves when write completes\n *\n * @example\n * ```ts\n * // Write formatted JSON with default 2-space indentation\n * await writeJson('./data.json', { name: 'example', version: '1.0.0' })\n *\n * // Write with custom indentation\n * await writeJson('./config.json', config, { spaces: 4 })\n *\n * // Write with tabs instead of spaces\n * await writeJson('./data.json', data, { spaces: '\\t' })\n *\n * // Write without final newline\n * await writeJson('./inline.json', obj, { finalEOL: false })\n *\n * // Write with Windows line endings\n * await writeJson('./win.json', data, { EOL: '\\r\\n' })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function writeJson(\n filepath: PathLike,\n jsonContent: unknown,\n options?: WriteJsonOptions | string,\n): Promise<void> {\n const opts = typeof options === 'string' ? { encoding: options } : options\n const { EOL, finalEOL, replacer, spaces, ...fsOptions } = {\n __proto__: null,\n ...opts,\n } as WriteJsonOptions\n const fs = getFs()\n const jsonString = stringify(\n jsonContent,\n EOL || '\\n',\n finalEOL !== undefined ? finalEOL : true,\n replacer,\n spaces,\n )\n await fs.promises.writeFile(filepath, jsonString, {\n encoding: 'utf8',\n ...fsOptions,\n __proto__: null,\n } as ObjectEncodingOptions)\n}\n\n/**\n * Write JSON content to a file synchronously with formatting.\n * Stringifies the value with configurable indentation and line endings.\n * Automatically adds a final newline by default for POSIX compliance.\n *\n * @param filepath - Path to write to\n * @param jsonContent - Value to stringify and write\n * @param options - Write options including formatting and encoding\n *\n * @example\n * ```ts\n * // Write formatted JSON with default 2-space indentation\n * writeJsonSync('./package.json', pkg)\n *\n * // Write with custom indentation\n * writeJsonSync('./tsconfig.json', tsconfig, { spaces: 4 })\n *\n * // Write with tabs for indentation\n * writeJsonSync('./data.json', data, { spaces: '\\t' })\n *\n * // Write compacted (no indentation)\n * writeJsonSync('./compact.json', data, { spaces: 0 })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function writeJsonSync(\n filepath: PathLike,\n jsonContent: unknown,\n options?: WriteJsonOptions | string | undefined,\n): void {\n const opts = typeof options === 'string' ? { encoding: options } : options\n const { EOL, finalEOL, replacer, spaces, ...fsOptions } = {\n __proto__: null,\n ...opts,\n }\n const fs = getFs()\n const jsonString = stringify(\n jsonContent,\n EOL || '\\n',\n finalEOL !== undefined ? finalEOL : true,\n replacer,\n spaces,\n )\n fs.writeFileSync(filepath, jsonString, {\n encoding: 'utf8',\n ...fsOptions,\n __proto__: null,\n } as WriteFileOptions)\n}\n"],
5
- "mappings": "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",
6
- "names": ["fs_exports", "__export", "findUp", "findUpSync", "isDir", "isDirEmptySync", "isDirSync", "isSymLinkSync", "readDirNames", "readDirNamesSync", "readFileBinary", "readFileBinarySync", "readFileUtf8", "readFileUtf8Sync", "readJson", "readJsonSync", "safeDelete", "safeDeleteSync", "safeReadFile", "safeReadFileSync", "safeStats", "safeStatsSync", "uniqueSync", "validateFiles", "writeJson", "writeJsonSync", "__toCommonJS", "import_process", "import_arrays", "import_globs", "import_json", "import_objects", "import_path", "import_sorts", "abortSignal", "defaultRemoveOptions", "_fs", "getFs", "_path", "getPath", "_os", "getOs", "innerReadDirNames", "dirents", "dirname", "options", "ignore", "includeEmpty", "sort", "path", "names", "d", "stringify", "json", "EOL", "finalEOL", "replacer", "spaces", "EOF", "name", "cwd", "signal", "onlyDirectories", "onlyFiles", "fs", "dir", "root", "n", "thePath", "stats", "stopAt", "stopDir", "filepath", "files", "length", "matcher", "ignoredCount", "i", "file", "filepaths", "validPaths", "invalidPaths", "R_OK", "opts", "reviver", "throws", "fsOptions", "shouldThrow", "content", "e", "del", "deleteAsync", "patterns", "shouldForce", "os", "getSocketCacacheDir", "getSocketUserDir", "tmpDir", "resolvedTmpDir", "cacacheDir", "resolvedCacacheDir", "socketUserDir", "resolvedSocketUserDir", "pattern", "resolvedPath", "allowedDir", "isInAllowedDir", "isGoingBackward", "deleteSync", "filepathStr", "ext", "basename", "counter", "uniquePath", "jsonContent", "jsonString"]
4
+ "sourcesContent": ["/**\n * @fileoverview File system utilities with cross-platform path handling.\n * Provides enhanced fs operations, glob matching, and directory traversal functions.\n */\n\nimport type { Abortable } from 'node:events'\nimport type {\n Dirent,\n ObjectEncodingOptions,\n OpenMode,\n PathLike,\n StatSyncOptions,\n WriteFileOptions,\n} from 'node:fs'\n\nimport { getAbortSignal } from '#constants/process'\n\nimport { isArray } from './arrays'\n\nconst abortSignal = getAbortSignal()\n\nimport { defaultIgnore, getGlobMatcher } from './globs'\nimport type { JsonReviver } from './json'\nimport { jsonParse } from './json'\nimport { objectFreeze, type Remap } from './objects'\nimport { normalizePath, pathLikeToString } from './path'\nimport { registerCacheInvalidation } from './paths/rewire'\nimport { naturalCompare } from './sorts'\n\n/**\n * Supported text encodings for Node.js Buffers.\n * Includes ASCII, UTF-8/16, base64, binary, and hexadecimal encodings.\n */\nexport type BufferEncoding =\n | 'ascii'\n | 'utf8'\n | 'utf-8'\n | 'utf16le'\n | 'ucs2'\n | 'ucs-2'\n | 'base64'\n | 'base64url'\n | 'latin1'\n | 'binary'\n | 'hex'\n\n/**\n * Represents any valid JSON content type.\n */\nexport type JsonContent = unknown\n\n/**\n * Options for asynchronous `findUp` operations.\n */\nexport interface FindUpOptions {\n /**\n * Starting directory for the search.\n * @default process.cwd()\n */\n cwd?: string | undefined\n /**\n * Only match directories, not files.\n * @default false\n */\n onlyDirectories?: boolean | undefined\n /**\n * Only match files, not directories.\n * @default true\n */\n onlyFiles?: boolean | undefined\n /**\n * Abort signal to cancel the search operation.\n */\n signal?: AbortSignal | undefined\n}\n\n/**\n * Options for synchronous `findUpSync` operations.\n */\nexport interface FindUpSyncOptions {\n /**\n * Starting directory for the search.\n * @default process.cwd()\n */\n cwd?: string | undefined\n /**\n * Directory to stop searching at (inclusive).\n * When provided, search will stop at this directory even if the root hasn't been reached.\n */\n stopAt?: string | undefined\n /**\n * Only match directories, not files.\n * @default false\n */\n onlyDirectories?: boolean | undefined\n /**\n * Only match files, not directories.\n * @default true\n */\n onlyFiles?: boolean | undefined\n}\n\n/**\n * Options for checking if a directory is empty.\n */\nexport interface IsDirEmptyOptions {\n /**\n * Glob patterns for files to ignore when checking emptiness.\n * Files matching these patterns are not counted.\n * @default defaultIgnore\n */\n ignore?: string[] | readonly string[] | undefined\n}\n\n/**\n * Options for read operations with abort support.\n */\nexport interface ReadOptions extends Abortable {\n /**\n * Character encoding to use for reading.\n * @default 'utf8'\n */\n encoding?: BufferEncoding | string | undefined\n /**\n * File system flag for reading behavior.\n * @default 'r'\n */\n flag?: string | undefined\n}\n\n/**\n * Options for reading directories with filtering and sorting.\n */\nexport interface ReadDirOptions {\n /**\n * Glob patterns for directories to ignore.\n * @default undefined\n */\n ignore?: string[] | readonly string[] | undefined\n /**\n * Include empty directories in results.\n * When `false`, empty directories are filtered out.\n * @default true\n */\n includeEmpty?: boolean | undefined\n /**\n * Sort directory names alphabetically using natural sort order.\n * @default true\n */\n sort?: boolean | undefined\n}\n\n/**\n * Options for reading files with encoding and abort support.\n * Can be either an options object, an encoding string, or null.\n */\nexport type ReadFileOptions =\n | Remap<\n ObjectEncodingOptions &\n Abortable & {\n flag?: OpenMode | undefined\n }\n >\n | BufferEncoding\n | null\n\n/**\n * Options for reading and parsing JSON files.\n */\nexport type ReadJsonOptions = Remap<\n ReadFileOptions & {\n /**\n * Whether to throw errors on parse failure.\n * When `false`, returns `undefined` on error instead of throwing.\n * @default true\n */\n throws?: boolean | undefined\n /**\n * JSON reviver function to transform parsed values.\n * Same as the second parameter to `JSON.parse()`.\n */\n reviver?: Parameters<typeof JSON.parse>[1] | undefined\n }\n>\n\n/**\n * Options for file/directory removal operations.\n */\nexport interface RemoveOptions {\n /**\n * Force deletion even outside normally safe directories.\n * When `false`, prevents deletion outside temp, cacache, and ~/.socket.\n * @default true for safe directories, false otherwise\n */\n force?: boolean | undefined\n /**\n * Maximum number of retry attempts on failure.\n * @default 3\n */\n maxRetries?: number | undefined\n /**\n * Recursively delete directories and contents.\n * @default true\n */\n recursive?: boolean | undefined\n /**\n * Delay in milliseconds between retry attempts.\n * @default 200\n */\n retryDelay?: number | undefined\n /**\n * Abort signal to cancel the operation.\n */\n signal?: AbortSignal | undefined\n}\n\n/**\n * Options for safe read operations that don't throw on errors.\n */\nexport interface SafeReadOptions extends ReadOptions {\n /**\n * Default value to return on read failure.\n * If not provided, `undefined` is returned on error.\n */\n defaultValue?: unknown | undefined\n}\n\n/**\n * Options for write operations with encoding and mode control.\n */\nexport interface WriteOptions extends Abortable {\n /**\n * Character encoding for writing.\n * @default 'utf8'\n */\n encoding?: BufferEncoding | string | undefined\n /**\n * File mode (permissions) to set.\n * Uses standard Unix permission bits (e.g., 0o644).\n * @default 0o666 (read/write for all, respecting umask)\n */\n mode?: number | undefined\n /**\n * File system flag for write behavior.\n * @default 'w' (create or truncate)\n */\n flag?: string | undefined\n}\n\n/**\n * Options for writing JSON files with formatting control.\n */\nexport interface WriteJsonOptions extends WriteOptions {\n /**\n * End-of-line sequence to use.\n * @default '\\n'\n * @example\n * ```ts\n * // Windows-style line endings\n * writeJson('data.json', data, { EOL: '\\r\\n' })\n * ```\n */\n EOL?: string | undefined\n /**\n * Whether to add a final newline at end of file.\n * @default true\n */\n finalEOL?: boolean | undefined\n /**\n * JSON replacer function to transform values during stringification.\n * Same as the second parameter to `JSON.stringify()`.\n */\n replacer?: JsonReviver | undefined\n /**\n * Number of spaces for indentation, or string to use for indentation.\n * @default 2\n * @example\n * ```ts\n * // Use tabs instead of spaces\n * writeJson('data.json', data, { spaces: '\\t' })\n *\n * // Use 4 spaces for indentation\n * writeJson('data.json', data, { spaces: 4 })\n * ```\n */\n spaces?: number | string | undefined\n}\n\nconst defaultRemoveOptions = objectFreeze({\n __proto__: null,\n force: true,\n maxRetries: 3,\n recursive: true,\n retryDelay: 200,\n})\n\nlet _fs: typeof import('fs') | undefined\n/**\n * Lazily load the fs module to avoid Webpack errors.\n * Uses non-'node:' prefixed require to prevent Webpack bundling issues.\n *\n * @returns The Node.js fs module\n * @private\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getFs() {\n if (_fs === undefined) {\n // Use non-'node:' prefixed require to avoid Webpack errors.\n\n _fs = /*@__PURE__*/ require('node:fs')\n }\n return _fs as typeof import('fs')\n}\n\nlet _path: typeof import('path') | undefined\n/**\n * Lazily load the path module to avoid Webpack errors.\n * Uses non-'node:' prefixed require to prevent Webpack bundling issues.\n *\n * @returns The Node.js path module\n * @private\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('path')\n}\n\n/**\n * Process directory entries and filter for directories.\n * Filters entries to include only directories, optionally excluding empty ones.\n * Applies ignore patterns and natural sorting.\n *\n * @param dirents - Directory entries from readdir\n * @param dirname - Parent directory path\n * @param options - Filtering and sorting options\n * @returns Array of directory names, optionally sorted\n * @private\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction innerReadDirNames(\n dirents: Dirent[],\n dirname: string | undefined,\n options?: ReadDirOptions | undefined,\n): string[] {\n const {\n ignore,\n includeEmpty = true,\n sort = true,\n } = { __proto__: null, ...options } as ReadDirOptions\n const path = getPath()\n const names = dirents\n .filter(\n (d: Dirent) =>\n d.isDirectory() &&\n (includeEmpty ||\n !isDirEmptySync(path.join(dirname || d.parentPath, d.name), {\n ignore,\n })),\n )\n .map((d: Dirent) => d.name)\n return sort ? names.sort(naturalCompare) : names\n}\n\n/**\n * Stringify JSON with custom formatting options.\n * Formats JSON with configurable line endings and indentation.\n *\n * @param json - Value to stringify\n * @param EOL - End-of-line sequence\n * @param finalEOL - Whether to add final newline\n * @param replacer - JSON replacer function\n * @param spaces - Indentation spaces or string\n * @returns Formatted JSON string\n * @private\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction stringify(\n json: unknown,\n EOL: string,\n finalEOL: boolean,\n replacer: JsonReviver | undefined,\n spaces: number | string = 2,\n): string {\n const EOF = finalEOL ? EOL : ''\n const str = JSON.stringify(json, replacer, spaces)\n return `${str.replace(/\\n/g, EOL)}${EOF}`\n}\n\n/**\n * Find a file or directory by traversing up parent directories.\n * Searches from the starting directory upward to the filesystem root.\n * Useful for finding configuration files or project roots.\n *\n * @param name - Filename(s) to search for\n * @param options - Search options including cwd and type filters\n * @returns Normalized absolute path if found, undefined otherwise\n *\n * @example\n * ```ts\n * // Find package.json starting from current directory\n * const pkgPath = await findUp('package.json')\n *\n * // Find any of multiple config files\n * const configPath = await findUp(['.config.js', '.config.json'])\n *\n * // Find a directory instead of file\n * const nodeModules = await findUp('node_modules', { onlyDirectories: true })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function findUp(\n name: string | string[] | readonly string[],\n options?: FindUpOptions | undefined,\n): Promise<string | undefined> {\n const { cwd = process.cwd(), signal = abortSignal } = {\n __proto__: null,\n ...options,\n } as FindUpOptions\n let { onlyDirectories = false, onlyFiles = true } = {\n __proto__: null,\n ...options,\n } as FindUpOptions\n if (onlyDirectories) {\n onlyFiles = false\n }\n if (onlyFiles) {\n onlyDirectories = false\n }\n const fs = getFs()\n const path = getPath()\n let dir = path.resolve(cwd)\n const { root } = path.parse(dir)\n const names = isArray(name) ? name : [name as string]\n while (dir && dir !== root) {\n for (const n of names) {\n if (signal?.aborted) {\n return undefined\n }\n const thePath = path.join(dir, n)\n try {\n // eslint-disable-next-line no-await-in-loop\n const stats = await fs.promises.stat(thePath)\n if (!onlyDirectories && stats.isFile()) {\n return normalizePath(thePath)\n }\n if (!onlyFiles && stats.isDirectory()) {\n return normalizePath(thePath)\n }\n } catch {}\n }\n dir = path.dirname(dir)\n }\n return undefined\n}\n\n/**\n * Synchronously find a file or directory by traversing up parent directories.\n * Searches from the starting directory upward to the filesystem root or `stopAt` directory.\n * Useful for finding configuration files or project roots in synchronous contexts.\n *\n * @param name - Filename(s) to search for\n * @param options - Search options including cwd, stopAt, and type filters\n * @returns Normalized absolute path if found, undefined otherwise\n *\n * @example\n * ```ts\n * // Find package.json starting from current directory\n * const pkgPath = findUpSync('package.json')\n *\n * // Find .git directory but stop at home directory\n * const gitPath = findUpSync('.git', {\n * onlyDirectories: true,\n * stopAt: process.env.HOME\n * })\n *\n * // Find any of multiple config files\n * const configPath = findUpSync(['.eslintrc.js', '.eslintrc.json'])\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function findUpSync(\n name: string | string[] | readonly string[],\n options?: FindUpSyncOptions | undefined,\n) {\n const { cwd = process.cwd(), stopAt } = {\n __proto__: null,\n ...options,\n } as FindUpSyncOptions\n let { onlyDirectories = false, onlyFiles = true } = {\n __proto__: null,\n ...options,\n } as FindUpSyncOptions\n if (onlyDirectories) {\n onlyFiles = false\n }\n if (onlyFiles) {\n onlyDirectories = false\n }\n const fs = getFs()\n const path = getPath()\n let dir = path.resolve(cwd)\n const { root } = path.parse(dir)\n const stopDir = stopAt ? path.resolve(stopAt) : undefined\n const names = isArray(name) ? name : [name as string]\n while (dir && dir !== root) {\n // Check if we should stop at this directory.\n if (stopDir && dir === stopDir) {\n // Check current directory but don't go up.\n for (const n of names) {\n const thePath = path.join(dir, n)\n try {\n const stats = fs.statSync(thePath)\n if (!onlyDirectories && stats.isFile()) {\n return normalizePath(thePath)\n }\n if (!onlyFiles && stats.isDirectory()) {\n return normalizePath(thePath)\n }\n } catch {}\n }\n return undefined\n }\n for (const n of names) {\n const thePath = path.join(dir, n)\n try {\n const stats = fs.statSync(thePath)\n if (!onlyDirectories && stats.isFile()) {\n return normalizePath(thePath)\n }\n if (!onlyFiles && stats.isDirectory()) {\n return normalizePath(thePath)\n }\n } catch {}\n }\n dir = path.dirname(dir)\n }\n return undefined\n}\n\n/**\n * Check if a path is a directory asynchronously.\n * Returns `true` for directories, `false` for files or non-existent paths.\n *\n * @param filepath - Path to check\n * @returns `true` if path is a directory, `false` otherwise\n *\n * @example\n * ```ts\n * if (await isDir('./src')) {\n * console.log('src is a directory')\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function isDir(filepath: PathLike) {\n return !!(await safeStats(filepath))?.isDirectory()\n}\n\n/**\n * Check if a path is a directory synchronously.\n * Returns `true` for directories, `false` for files or non-existent paths.\n *\n * @param filepath - Path to check\n * @returns `true` if path is a directory, `false` otherwise\n *\n * @example\n * ```ts\n * if (isDirSync('./src')) {\n * console.log('src is a directory')\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function isDirSync(filepath: PathLike) {\n return !!safeStatsSync(filepath)?.isDirectory()\n}\n\n/**\n * Check if a directory is empty synchronously.\n * A directory is considered empty if it contains no files after applying ignore patterns.\n * Uses glob patterns to filter ignored files.\n *\n * @param dirname - Directory path to check\n * @param options - Options including ignore patterns\n * @returns `true` if directory is empty (or doesn't exist), `false` otherwise\n *\n * @example\n * ```ts\n * // Check if directory is completely empty\n * isDirEmptySync('./build')\n *\n * // Check if directory is empty, ignoring .DS_Store files\n * isDirEmptySync('./cache', { ignore: ['.DS_Store'] })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function isDirEmptySync(\n dirname: PathLike,\n options?: IsDirEmptyOptions | undefined,\n) {\n const { ignore = defaultIgnore } = {\n __proto__: null,\n ...options,\n } as IsDirEmptyOptions\n const fs = getFs()\n try {\n const files = fs.readdirSync(dirname)\n const { length } = files\n if (length === 0) {\n return true\n }\n const matcher = getGlobMatcher(\n ignore as string[],\n {\n cwd: pathLikeToString(dirname),\n } as { cwd?: string; dot?: boolean; ignore?: string[]; nocase?: boolean },\n )\n let ignoredCount = 0\n for (let i = 0; i < length; i += 1) {\n const file = files[i]\n if (file && matcher(file)) {\n ignoredCount += 1\n }\n }\n return ignoredCount === length\n } catch {\n // Return false for non-existent paths or other errors.\n return false\n }\n}\n\n/**\n * Check if a path is a symbolic link synchronously.\n * Uses `lstat` to check the link itself, not the target.\n *\n * @param filepath - Path to check\n * @returns `true` if path is a symbolic link, `false` otherwise\n *\n * @example\n * ```ts\n * if (isSymLinkSync('./my-link')) {\n * console.log('Path is a symbolic link')\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function isSymLinkSync(filepath: PathLike) {\n const fs = getFs()\n try {\n return fs.lstatSync(filepath).isSymbolicLink()\n } catch {}\n return false\n}\n\n/**\n * Result of file readability validation.\n * Contains lists of valid and invalid file paths.\n */\nexport interface ValidateFilesResult {\n /**\n * File paths that passed validation and are readable.\n */\n validPaths: string[]\n /**\n * File paths that failed validation (unreadable, permission denied, or non-existent).\n * Common with Yarn Berry PnP virtual filesystem, pnpm symlinks, or filesystem race conditions.\n */\n invalidPaths: string[]\n}\n\n/**\n * Validate that file paths are readable before processing.\n * Filters out files from glob results that cannot be accessed (common with\n * Yarn Berry PnP virtual filesystem, pnpm content-addressable store symlinks,\n * or filesystem race conditions in CI/CD environments).\n *\n * This defensive pattern prevents ENOENT errors when files exist in glob\n * results but are not accessible via standard filesystem operations.\n *\n * @param filepaths - Array of file paths to validate\n * @returns Object with `validPaths` (readable) and `invalidPaths` (unreadable)\n *\n * @example\n * ```ts\n * import { validateFiles } from '@socketsecurity/lib/fs'\n *\n * const files = ['package.json', '.pnp.cjs/virtual-file.json']\n * const { validPaths, invalidPaths } = validateFiles(files)\n *\n * console.log(`Valid: ${validPaths.length}`)\n * console.log(`Invalid: ${invalidPaths.length}`)\n * ```\n *\n * @example\n * ```ts\n * // Typical usage in Socket CLI commands\n * const packagePaths = await getPackageFilesForScan(targets)\n * const { validPaths } = validateFiles(packagePaths)\n * await sdk.uploadManifestFiles(orgSlug, validPaths)\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function validateFiles(\n filepaths: string[] | readonly string[],\n): ValidateFilesResult {\n const fs = getFs()\n const validPaths: string[] = []\n const invalidPaths: string[] = []\n const { R_OK } = fs.constants\n\n for (const filepath of filepaths) {\n try {\n fs.accessSync(filepath, R_OK)\n validPaths.push(filepath)\n } catch {\n invalidPaths.push(filepath)\n }\n }\n\n return { __proto__: null, validPaths, invalidPaths } as ValidateFilesResult\n}\n\n/**\n * Read directory names asynchronously with filtering and sorting.\n * Returns only directory names (not files), with optional filtering for empty directories\n * and glob-based ignore patterns. Results are naturally sorted by default.\n *\n * @param dirname - Directory path to read\n * @param options - Options for filtering and sorting\n * @returns Array of directory names, empty array on error\n *\n * @example\n * ```ts\n * // Get all subdirectories, sorted naturally\n * const dirs = await readDirNames('./packages')\n *\n * // Get non-empty directories only\n * const nonEmpty = await readDirNames('./cache', { includeEmpty: false })\n *\n * // Get directories without sorting\n * const unsorted = await readDirNames('./src', { sort: false })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function readDirNames(\n dirname: PathLike,\n options?: ReadDirOptions | undefined,\n) {\n const fs = getFs()\n try {\n return innerReadDirNames(\n await fs.promises.readdir(dirname, {\n __proto__: null,\n encoding: 'utf8',\n withFileTypes: true,\n } as ObjectEncodingOptions & { withFileTypes: true }),\n String(dirname),\n options,\n )\n } catch {}\n return []\n}\n\n/**\n * Read directory names synchronously with filtering and sorting.\n * Returns only directory names (not files), with optional filtering for empty directories\n * and glob-based ignore patterns. Results are naturally sorted by default.\n *\n * @param dirname - Directory path to read\n * @param options - Options for filtering and sorting\n * @returns Array of directory names, empty array on error\n *\n * @example\n * ```ts\n * // Get all subdirectories, sorted naturally\n * const dirs = readDirNamesSync('./packages')\n *\n * // Get non-empty directories only, ignoring node_modules\n * const nonEmpty = readDirNamesSync('./src', {\n * includeEmpty: false,\n * ignore: ['node_modules']\n * })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function readDirNamesSync(dirname: PathLike, options?: ReadDirOptions) {\n const fs = getFs()\n try {\n return innerReadDirNames(\n fs.readdirSync(dirname, {\n __proto__: null,\n encoding: 'utf8',\n withFileTypes: true,\n } as ObjectEncodingOptions & { withFileTypes: true }),\n String(dirname),\n options,\n )\n } catch {}\n return []\n}\n\n/**\n * Read a file as binary data asynchronously.\n * Returns a Buffer without encoding the contents.\n * Useful for reading images, archives, or other binary formats.\n *\n * @param filepath - Path to file\n * @param options - Read options (encoding is forced to null for binary)\n * @returns Promise resolving to Buffer containing file contents\n *\n * @example\n * ```ts\n * // Read an image file\n * const imageBuffer = await readFileBinary('./image.png')\n *\n * // Read with abort signal\n * const buffer = await readFileBinary('./data.bin', { signal: abortSignal })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function readFileBinary(\n filepath: PathLike,\n options?: ReadFileOptions | undefined,\n) {\n // Don't specify encoding to get a Buffer.\n const opts = typeof options === 'string' ? { encoding: options } : options\n const fs = getFs()\n return await fs.promises.readFile(filepath, {\n signal: abortSignal,\n ...opts,\n encoding: null,\n })\n}\n\n/**\n * Read a file as UTF-8 text asynchronously.\n * Returns a string with the file contents decoded as UTF-8.\n * This is the most common way to read text files.\n *\n * @param filepath - Path to file\n * @param options - Read options including encoding and abort signal\n * @returns Promise resolving to string containing file contents\n *\n * @example\n * ```ts\n * // Read a text file\n * const content = await readFileUtf8('./README.md')\n *\n * // Read with custom encoding\n * const content = await readFileUtf8('./data.txt', { encoding: 'utf-8' })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function readFileUtf8(\n filepath: PathLike,\n options?: ReadFileOptions | undefined,\n) {\n const opts = typeof options === 'string' ? { encoding: options } : options\n const fs = getFs()\n return await fs.promises.readFile(filepath, {\n signal: abortSignal,\n ...opts,\n encoding: 'utf8',\n })\n}\n\n/**\n * Read a file as binary data synchronously.\n * Returns a Buffer without encoding the contents.\n * Useful for reading images, archives, or other binary formats.\n *\n * @param filepath - Path to file\n * @param options - Read options (encoding is forced to null for binary)\n * @returns Buffer containing file contents\n *\n * @example\n * ```ts\n * // Read an image file\n * const imageBuffer = readFileBinarySync('./logo.png')\n *\n * // Read a compressed file\n * const gzipData = readFileBinarySync('./archive.gz')\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function readFileBinarySync(\n filepath: PathLike,\n options?: ReadFileOptions | undefined,\n) {\n // Don't specify encoding to get a Buffer\n const opts = typeof options === 'string' ? { encoding: options } : options\n const fs = getFs()\n return fs.readFileSync(filepath, {\n ...opts,\n encoding: null,\n } as ObjectEncodingOptions)\n}\n\n/**\n * Read a file as UTF-8 text synchronously.\n * Returns a string with the file contents decoded as UTF-8.\n * This is the most common way to read text files synchronously.\n *\n * @param filepath - Path to file\n * @param options - Read options including encoding\n * @returns String containing file contents\n *\n * @example\n * ```ts\n * // Read a configuration file\n * const config = readFileUtf8Sync('./config.txt')\n *\n * // Read with custom options\n * const data = readFileUtf8Sync('./data.txt', { encoding: 'utf8' })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function readFileUtf8Sync(\n filepath: PathLike,\n options?: ReadFileOptions | undefined,\n) {\n const opts = typeof options === 'string' ? { encoding: options } : options\n const fs = getFs()\n return fs.readFileSync(filepath, {\n ...opts,\n encoding: 'utf8',\n } as ObjectEncodingOptions)\n}\n\n/**\n * Read and parse a JSON file asynchronously.\n * Reads the file as UTF-8 text and parses it as JSON.\n * Optionally accepts a reviver function to transform parsed values.\n *\n * @param filepath - Path to JSON file\n * @param options - Read and parse options\n * @returns Promise resolving to parsed JSON value, or undefined if throws is false and an error occurs\n *\n * @example\n * ```ts\n * // Read and parse package.json\n * const pkg = await readJson('./package.json')\n *\n * // Read JSON with custom reviver\n * const data = await readJson('./data.json', {\n * reviver: (key, value) => {\n * if (key === 'date') return new Date(value)\n * return value\n * }\n * })\n *\n * // Don't throw on parse errors\n * const config = await readJson('./config.json', { throws: false })\n * if (config === undefined) {\n * console.log('Failed to parse config')\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function readJson(\n filepath: PathLike,\n options?: ReadJsonOptions | string | undefined,\n) {\n const opts = typeof options === 'string' ? { encoding: options } : options\n const { reviver, throws, ...fsOptions } = {\n __proto__: null,\n ...opts,\n } as unknown as ReadJsonOptions\n const shouldThrow = throws === undefined || !!throws\n const fs = getFs()\n let content = ''\n try {\n content = await fs.promises.readFile(filepath, {\n __proto__: null,\n encoding: 'utf8',\n ...fsOptions,\n } as unknown as Parameters<typeof fs.promises.readFile>[1] & {\n encoding: string\n })\n } catch (e) {\n if (shouldThrow) {\n throw e\n }\n return undefined\n }\n return jsonParse(content, {\n filepath: String(filepath),\n reviver,\n throws: shouldThrow,\n })\n}\n\n/**\n * Read and parse a JSON file synchronously.\n * Reads the file as UTF-8 text and parses it as JSON.\n * Optionally accepts a reviver function to transform parsed values.\n *\n * @param filepath - Path to JSON file\n * @param options - Read and parse options\n * @returns Parsed JSON value, or undefined if throws is false and an error occurs\n *\n * @example\n * ```ts\n * // Read and parse tsconfig.json\n * const tsconfig = readJsonSync('./tsconfig.json')\n *\n * // Read JSON with custom reviver\n * const data = readJsonSync('./data.json', {\n * reviver: (key, value) => {\n * if (typeof value === 'string' && /^\\d{4}-\\d{2}-\\d{2}/.test(value)) {\n * return new Date(value)\n * }\n * return value\n * }\n * })\n *\n * // Don't throw on parse errors\n * const config = readJsonSync('./config.json', { throws: false })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function readJsonSync(\n filepath: PathLike,\n options?: ReadJsonOptions | string | undefined,\n) {\n const opts = typeof options === 'string' ? { encoding: options } : options\n const { reviver, throws, ...fsOptions } = {\n __proto__: null,\n ...opts,\n } as unknown as ReadJsonOptions\n const shouldThrow = throws === undefined || !!throws\n const fs = getFs()\n let content = ''\n try {\n content = fs.readFileSync(filepath, {\n __proto__: null,\n encoding: 'utf8',\n ...fsOptions,\n } as unknown as Parameters<typeof fs.readFileSync>[1] & {\n encoding: string\n })\n } catch (e) {\n if (shouldThrow) {\n throw e\n }\n return undefined\n }\n return jsonParse(content, {\n filepath: String(filepath),\n reviver,\n throws: shouldThrow,\n })\n}\n\n// Cache for resolved allowed directories\nlet _cachedAllowedDirs: string[] | undefined\n\n/**\n * Get resolved allowed directories for safe deletion with lazy caching.\n * These directories are resolved once and cached for the process lifetime.\n */\nfunction getAllowedDirectories(): string[] {\n if (_cachedAllowedDirs === undefined) {\n const path = getPath()\n const {\n getOsTmpDir,\n getSocketCacacheDir,\n getSocketUserDir,\n } = /*@__PURE__*/ require('#lib/paths')\n\n _cachedAllowedDirs = [\n path.resolve(getOsTmpDir()),\n path.resolve(getSocketCacacheDir()),\n path.resolve(getSocketUserDir()),\n ]\n }\n return _cachedAllowedDirs\n}\n\n/**\n * Invalidate the cached allowed directories.\n * Called automatically by the paths/rewire module when paths are overridden in tests.\n *\n * @internal Used for test rewiring\n */\nexport function invalidatePathCache(): void {\n _cachedAllowedDirs = undefined\n}\n\n// Register cache invalidation with the rewire module\nregisterCacheInvalidation(invalidatePathCache)\n\n/**\n * Safely delete a file or directory asynchronously with built-in protections.\n * Uses `del` for safer deletion that prevents removing cwd and above by default.\n * Automatically uses force: true for temp directory, cacache, and ~/.socket subdirectories.\n *\n * @param filepath - Path or array of paths to delete (supports glob patterns)\n * @param options - Deletion options including force, retries, and recursion\n * @throws {Error} When attempting to delete protected paths without force option\n *\n * @example\n * ```ts\n * // Delete a single file\n * await safeDelete('./temp-file.txt')\n *\n * // Delete a directory recursively\n * await safeDelete('./build', { recursive: true })\n *\n * // Delete multiple paths\n * await safeDelete(['./dist', './coverage'])\n *\n * // Delete with custom retry settings\n * await safeDelete('./flaky-dir', { maxRetries: 5, retryDelay: 500 })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function safeDelete(\n filepath: PathLike | PathLike[],\n options?: RemoveOptions | undefined,\n) {\n const del = /*@__PURE__*/ require('./external/del')\n const { deleteAsync } = del\n const opts = { __proto__: null, ...options } as RemoveOptions\n const patterns = isArray(filepath)\n ? filepath.map(pathLikeToString)\n : [pathLikeToString(filepath)]\n\n // Check if we're deleting within allowed directories.\n let shouldForce = opts.force !== false\n if (!shouldForce && patterns.length > 0) {\n const path = getPath()\n const allowedDirs = getAllowedDirectories()\n\n // Check if all patterns are within allowed directories.\n const allInAllowedDirs = patterns.every(pattern => {\n const resolvedPath = path.resolve(pattern)\n\n // Check each allowed directory\n for (const allowedDir of allowedDirs) {\n const isInAllowedDir =\n resolvedPath.startsWith(allowedDir + path.sep) ||\n resolvedPath === allowedDir\n const relativePath = path.relative(allowedDir, resolvedPath)\n const isGoingBackward = relativePath.startsWith('..')\n\n if (isInAllowedDir && !isGoingBackward) {\n return true\n }\n }\n\n return false\n })\n\n if (allInAllowedDirs) {\n shouldForce = true\n }\n }\n\n await deleteAsync(patterns, {\n concurrency: opts.maxRetries || defaultRemoveOptions.maxRetries,\n dryRun: false,\n force: shouldForce,\n onlyFiles: false,\n })\n}\n\n/**\n * Safely delete a file or directory synchronously with built-in protections.\n * Uses `del` for safer deletion that prevents removing cwd and above by default.\n * Automatically uses force: true for temp directory, cacache, and ~/.socket subdirectories.\n *\n * @param filepath - Path or array of paths to delete (supports glob patterns)\n * @param options - Deletion options including force, retries, and recursion\n * @throws {Error} When attempting to delete protected paths without force option\n *\n * @example\n * ```ts\n * // Delete a single file\n * safeDeleteSync('./temp-file.txt')\n *\n * // Delete a directory recursively\n * safeDeleteSync('./build', { recursive: true })\n *\n * // Delete multiple paths with globs\n * safeDeleteSync(['./dist/**', './coverage/**'])\n *\n * // Force delete a protected path (use with caution)\n * safeDeleteSync('./important', { force: true })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function safeDeleteSync(\n filepath: PathLike | PathLike[],\n options?: RemoveOptions | undefined,\n) {\n const del = /*@__PURE__*/ require('./external/del')\n const { deleteSync } = del\n const opts = { __proto__: null, ...options } as RemoveOptions\n const patterns = isArray(filepath)\n ? filepath.map(pathLikeToString)\n : [pathLikeToString(filepath)]\n\n // Check if we're deleting within allowed directories.\n let shouldForce = opts.force !== false\n if (!shouldForce && patterns.length > 0) {\n const path = getPath()\n const allowedDirs = getAllowedDirectories()\n\n // Check if all patterns are within allowed directories.\n const allInAllowedDirs = patterns.every(pattern => {\n const resolvedPath = path.resolve(pattern)\n\n // Check each allowed directory\n for (const allowedDir of allowedDirs) {\n const isInAllowedDir =\n resolvedPath.startsWith(allowedDir + path.sep) ||\n resolvedPath === allowedDir\n const relativePath = path.relative(allowedDir, resolvedPath)\n const isGoingBackward = relativePath.startsWith('..')\n\n if (isInAllowedDir && !isGoingBackward) {\n return true\n }\n }\n\n return false\n })\n\n if (allInAllowedDirs) {\n shouldForce = true\n }\n }\n\n deleteSync(patterns, {\n concurrency: opts.maxRetries || defaultRemoveOptions.maxRetries,\n dryRun: false,\n force: shouldForce,\n onlyFiles: false,\n })\n}\n\n/**\n * Safely read a file asynchronously, returning undefined on error.\n * Useful when you want to attempt reading a file without handling errors explicitly.\n * Returns undefined for any error (file not found, permission denied, etc.).\n *\n * @param filepath - Path to file\n * @param options - Read options including encoding and default value\n * @returns Promise resolving to file contents, or undefined on error\n *\n * @example\n * ```ts\n * // Try to read a file, get undefined if it doesn't exist\n * const content = await safeReadFile('./optional-config.txt')\n * if (content) {\n * console.log('Config found:', content)\n * }\n *\n * // Read with specific encoding\n * const data = await safeReadFile('./data.txt', { encoding: 'utf8' })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function safeReadFile(\n filepath: PathLike,\n options?: SafeReadOptions | undefined,\n) {\n const opts = typeof options === 'string' ? { encoding: options } : options\n const fs = getFs()\n try {\n return await fs.promises.readFile(filepath, {\n signal: abortSignal,\n ...opts,\n } as Abortable)\n } catch {}\n return undefined\n}\n\n/**\n * Safely get file stats asynchronously, returning undefined on error.\n * Useful for checking file existence and properties without error handling.\n * Returns undefined for any error (file not found, permission denied, etc.).\n *\n * @param filepath - Path to check\n * @returns Promise resolving to Stats object, or undefined on error\n *\n * @example\n * ```ts\n * // Check if file exists and get its stats\n * const stats = await safeStats('./file.txt')\n * if (stats) {\n * console.log('File size:', stats.size)\n * console.log('Modified:', stats.mtime)\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function safeStats(filepath: PathLike) {\n const fs = getFs()\n try {\n return await fs.promises.stat(filepath)\n } catch {}\n return undefined\n}\n\n/**\n * Safely get file stats synchronously, returning undefined on error.\n * Useful for checking file existence and properties without error handling.\n * Returns undefined for any error (file not found, permission denied, etc.).\n *\n * @param filepath - Path to check\n * @param options - Read options (currently unused but kept for API consistency)\n * @returns Stats object, or undefined on error\n *\n * @example\n * ```ts\n * // Check if file exists and get its size\n * const stats = safeStatsSync('./file.txt')\n * if (stats) {\n * console.log('File size:', stats.size)\n * console.log('Is directory:', stats.isDirectory())\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function safeStatsSync(\n filepath: PathLike,\n options?: ReadFileOptions | undefined,\n) {\n const opts = typeof options === 'string' ? { encoding: options } : options\n const fs = getFs()\n try {\n return fs.statSync(filepath, {\n __proto__: null,\n throwIfNoEntry: false,\n ...opts,\n } as StatSyncOptions)\n } catch {}\n return undefined\n}\n\n/**\n * Safely read a file synchronously, returning undefined on error.\n * Useful when you want to attempt reading a file without handling errors explicitly.\n * Returns undefined for any error (file not found, permission denied, etc.).\n *\n * @param filepath - Path to file\n * @param options - Read options including encoding and default value\n * @returns File contents, or undefined on error\n *\n * @example\n * ```ts\n * // Try to read a config file\n * const config = safeReadFileSync('./config.txt')\n * if (config) {\n * console.log('Config loaded successfully')\n * }\n *\n * // Read binary file safely\n * const buffer = safeReadFileSync('./image.png', { encoding: null })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function safeReadFileSync(\n filepath: PathLike,\n options?: SafeReadOptions | undefined,\n) {\n const opts = typeof options === 'string' ? { encoding: options } : options\n const fs = getFs()\n try {\n return fs.readFileSync(filepath, {\n __proto__: null,\n ...opts,\n } as ObjectEncodingOptions)\n } catch {}\n return undefined\n}\n\n/**\n * Generate a unique filepath by adding number suffix if the path exists.\n * Appends `-1`, `-2`, etc. before the file extension until a non-existent path is found.\n * Useful for creating files without overwriting existing ones.\n *\n * @param filepath - Desired file path\n * @returns Normalized unique filepath (original if it doesn't exist, or with number suffix)\n *\n * @example\n * ```ts\n * // If 'report.pdf' exists, returns 'report-1.pdf'\n * const uniquePath = uniqueSync('./report.pdf')\n *\n * // If 'data.json' and 'data-1.json' exist, returns 'data-2.json'\n * const path = uniqueSync('./data.json')\n *\n * // If 'backup' doesn't exist, returns 'backup' unchanged\n * const backupPath = uniqueSync('./backup')\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function uniqueSync(filepath: PathLike): string {\n const fs = getFs()\n const path = getPath()\n const filepathStr = String(filepath)\n\n // If the file doesn't exist, return as is\n if (!fs.existsSync(filepathStr)) {\n return normalizePath(filepathStr)\n }\n\n const dirname = path.dirname(filepathStr)\n const ext = path.extname(filepathStr)\n const basename = path.basename(filepathStr, ext)\n\n let counter = 1\n let uniquePath: string\n do {\n uniquePath = path.join(dirname, `${basename}-${counter}${ext}`)\n counter++\n } while (fs.existsSync(uniquePath))\n\n return normalizePath(uniquePath)\n}\n\n/**\n * Write JSON content to a file asynchronously with formatting.\n * Stringifies the value with configurable indentation and line endings.\n * Automatically adds a final newline by default for POSIX compliance.\n *\n * @param filepath - Path to write to\n * @param jsonContent - Value to stringify and write\n * @param options - Write options including formatting and encoding\n * @returns Promise that resolves when write completes\n *\n * @example\n * ```ts\n * // Write formatted JSON with default 2-space indentation\n * await writeJson('./data.json', { name: 'example', version: '1.0.0' })\n *\n * // Write with custom indentation\n * await writeJson('./config.json', config, { spaces: 4 })\n *\n * // Write with tabs instead of spaces\n * await writeJson('./data.json', data, { spaces: '\\t' })\n *\n * // Write without final newline\n * await writeJson('./inline.json', obj, { finalEOL: false })\n *\n * // Write with Windows line endings\n * await writeJson('./win.json', data, { EOL: '\\r\\n' })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function writeJson(\n filepath: PathLike,\n jsonContent: unknown,\n options?: WriteJsonOptions | string,\n): Promise<void> {\n const opts = typeof options === 'string' ? { encoding: options } : options\n const { EOL, finalEOL, replacer, spaces, ...fsOptions } = {\n __proto__: null,\n ...opts,\n } as WriteJsonOptions\n const fs = getFs()\n const jsonString = stringify(\n jsonContent,\n EOL || '\\n',\n finalEOL !== undefined ? finalEOL : true,\n replacer,\n spaces,\n )\n await fs.promises.writeFile(filepath, jsonString, {\n encoding: 'utf8',\n ...fsOptions,\n __proto__: null,\n } as ObjectEncodingOptions)\n}\n\n/**\n * Write JSON content to a file synchronously with formatting.\n * Stringifies the value with configurable indentation and line endings.\n * Automatically adds a final newline by default for POSIX compliance.\n *\n * @param filepath - Path to write to\n * @param jsonContent - Value to stringify and write\n * @param options - Write options including formatting and encoding\n *\n * @example\n * ```ts\n * // Write formatted JSON with default 2-space indentation\n * writeJsonSync('./package.json', pkg)\n *\n * // Write with custom indentation\n * writeJsonSync('./tsconfig.json', tsconfig, { spaces: 4 })\n *\n * // Write with tabs for indentation\n * writeJsonSync('./data.json', data, { spaces: '\\t' })\n *\n * // Write compacted (no indentation)\n * writeJsonSync('./compact.json', data, { spaces: 0 })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function writeJsonSync(\n filepath: PathLike,\n jsonContent: unknown,\n options?: WriteJsonOptions | string | undefined,\n): void {\n const opts = typeof options === 'string' ? { encoding: options } : options\n const { EOL, finalEOL, replacer, spaces, ...fsOptions } = {\n __proto__: null,\n ...opts,\n }\n const fs = getFs()\n const jsonString = stringify(\n jsonContent,\n EOL || '\\n',\n finalEOL !== undefined ? finalEOL : true,\n replacer,\n spaces,\n )\n fs.writeFileSync(filepath, jsonString, {\n encoding: 'utf8',\n ...fsOptions,\n __proto__: null,\n } as WriteFileOptions)\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["fs_exports", "__export", "findUp", "findUpSync", "invalidatePathCache", "isDir", "isDirEmptySync", "isDirSync", "isSymLinkSync", "readDirNames", "readDirNamesSync", "readFileBinary", "readFileBinarySync", "readFileUtf8", "readFileUtf8Sync", "readJson", "readJsonSync", "safeDelete", "safeDeleteSync", "safeReadFile", "safeReadFileSync", "safeStats", "safeStatsSync", "uniqueSync", "validateFiles", "writeJson", "writeJsonSync", "__toCommonJS", "import_process", "import_arrays", "import_globs", "import_json", "import_objects", "import_path", "import_rewire", "import_sorts", "abortSignal", "defaultRemoveOptions", "_fs", "getFs", "_path", "getPath", "innerReadDirNames", "dirents", "dirname", "options", "ignore", "includeEmpty", "sort", "path", "names", "d", "stringify", "json", "EOL", "finalEOL", "replacer", "spaces", "EOF", "name", "cwd", "signal", "onlyDirectories", "onlyFiles", "fs", "dir", "root", "n", "thePath", "stats", "stopAt", "stopDir", "filepath", "files", "length", "matcher", "ignoredCount", "i", "file", "filepaths", "validPaths", "invalidPaths", "R_OK", "opts", "reviver", "throws", "fsOptions", "shouldThrow", "content", "e", "_cachedAllowedDirs", "getAllowedDirectories", "getOsTmpDir", "getSocketCacacheDir", "getSocketUserDir", "del", "deleteAsync", "patterns", "shouldForce", "allowedDirs", "pattern", "resolvedPath", "allowedDir", "isInAllowedDir", "isGoingBackward", "deleteSync", "filepathStr", "ext", "basename", "counter", "uniquePath", "jsonContent", "jsonString"]
7
7
  }
package/dist/github.js CHANGED
@@ -1,3 +1,3 @@
1
1
  /* Socket Lib - Built with esbuild */
2
- var h=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var $=Object.getOwnPropertyNames;var A=Object.prototype.hasOwnProperty;var O=(t,e)=>{for(var s in e)h(t,s,{get:e[s],enumerable:!0})},R=(t,e,s,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of $(e))!A.call(t,n)&&n!==s&&h(t,n,{get:()=>e[n],enumerable:!(i=H(e,n))||i.enumerable});return t};var x=t=>R(h({},"__esModule",{value:!0}),t);var U={};O(U,{cacheFetchGhsa:()=>I,clearRefCache:()=>k,fetchGhsaDetails:()=>v,fetchGitHub:()=>o,getGhsaUrl:()=>D,getGitHubToken:()=>f,getGitHubTokenFromGitConfig:()=>_,getGitHubTokenWithFallback:()=>C,resolveRefToSha:()=>E});module.exports=x(U);var b=require("./cache-with-ttl"),y=require("./http-request"),w=require("./spawn");const l="https://api.github.com",S=300*1e3;let c;function G(){return c===void 0&&(c=(0,b.createTtlCache)({memoize:!0,prefix:"github-refs",ttl:S})),c}function f(){const{env:t}=process;return t.GITHUB_TOKEN||t.GH_TOKEN||t.SOCKET_CLI_GITHUB_TOKEN||void 0}async function o(t,e){const s={__proto__:null,...e},i=s.token||f(),n={Accept:"application/vnd.github.v3+json","User-Agent":"socket-registry-github-client",...s.headers};i&&(n.Authorization=`Bearer ${i}`);const r=await(0,y.httpRequest)(t,{headers:n});if(!r.ok){if(r.status===403){const a=r.headers["x-ratelimit-remaining"];if((typeof a=="string"?a:a?.[0])==="0"){const g=r.headers["x-ratelimit-reset"],m=typeof g=="string"?g:g?.[0],u=m?new Date(Number(m)*1e3):void 0,d=new Error(`GitHub API rate limit exceeded${u?`. Resets at ${u.toLocaleString()}`:""}. Use GITHUB_TOKEN environment variable to increase rate limit.`);throw d.status=403,d.resetTime=u,d}}throw new Error(`GitHub API error ${r.status}: ${r.statusText}`)}return JSON.parse(r.body.toString("utf8"))}async function E(t,e,s,i){const n={__proto__:null,...i},r=`${t}/${e}@${s}`;return process.env.DISABLE_GITHUB_CACHE?await p(t,e,s,n):await G().getOrFetch(r,async()=>await p(t,e,s,n))}async function p(t,e,s,i){const n={token:i.token};try{const r=`${l}/repos/${t}/${e}/git/refs/tags/${s}`,a=await o(r,n);return a.object.type==="tag"?(await o(a.object.url,n)).object.sha:a.object.sha}catch{try{const r=`${l}/repos/${t}/${e}/git/refs/heads/${s}`;return(await o(r,n)).object.sha}catch{try{const r=`${l}/repos/${t}/${e}/commits/${s}`;return(await o(r,n)).sha}catch(r){throw new Error(`failed to resolve ref "${s}" for ${t}/${e}: ${r instanceof Error?r.message:String(r)}`)}}}}async function k(){c&&await c.clear({memoOnly:!0})}async function _(t){try{const e=await(0,w.spawn)("git",["config","github.token"],{...t,stdio:"pipe"});if(e.code===0&&e.stdout)return e.stdout.toString().trim()}catch{}}async function C(){return f()||await _()}function D(t){return`https://github.com/advisories/${t}`}async function v(t,e){const s=`https://api.github.com/advisories/${t}`,i=await o(s,e);return{ghsaId:i.ghsa_id,summary:i.summary,details:i.details,severity:i.severity,aliases:i.aliases||[],publishedAt:i.published_at,updatedAt:i.updated_at,withdrawnAt:i.withdrawn_at,references:i.references||[],vulnerabilities:i.vulnerabilities||[],cvss:i.cvss,cwes:i.cwes||[]}}async function I(t,e){const s=G(),i=`ghsa:${t}`;if(!process.env.DISABLE_GITHUB_CACHE){const r=await s.get(i);if(r)return JSON.parse(r)}const n=await v(t,e);return await s.set(i,JSON.stringify(n)),n}0&&(module.exports={cacheFetchGhsa,clearRefCache,fetchGhsaDetails,fetchGitHub,getGhsaUrl,getGitHubToken,getGitHubTokenFromGitConfig,getGitHubTokenWithFallback,resolveRefToSha});
2
+ var l=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var k=Object.prototype.hasOwnProperty;var x=(e,t)=>{for(var s in t)l(e,s,{get:t[s],enumerable:!0})},O=(e,t,s,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of R(t))!k.call(e,n)&&n!==s&&l(e,n,{get:()=>t[n],enumerable:!(i=A(t,n))||i.enumerable});return e};var S=e=>O(l({},"__esModule",{value:!0}),e);var F={};x(F,{cacheFetchGhsa:()=>U,clearRefCache:()=>E,fetchGhsaDetails:()=>_,fetchGitHub:()=>o,getGhsaUrl:()=>I,getGitHubToken:()=>m,getGitHubTokenFromGitConfig:()=>H,getGitHubTokenWithFallback:()=>P,resolveRefToSha:()=>D});module.exports=S(F);var y=require("./cache-with-ttl"),g=require("#env/github"),w=require("#env/socket-cli"),G=require("./http-request"),v=require("./spawn");const f="https://api.github.com",C=300*1e3;let c;function T(){return c===void 0&&(c=(0,y.createTtlCache)({memoize:!0,prefix:"github-refs",ttl:C})),c}function m(){return(0,g.getGithubToken)()||(0,g.getGhToken)()||(0,w.getSocketCliGithubToken)()||void 0}async function o(e,t){const s={__proto__:null,...t},i=s.token||m(),n={Accept:"application/vnd.github.v3+json","User-Agent":"socket-registry-github-client",...s.headers};i&&(n.Authorization=`Bearer ${i}`);const r=await(0,G.httpRequest)(e,{headers:n});if(!r.ok){if(r.status===403){const a=r.headers["x-ratelimit-remaining"];if((typeof a=="string"?a:a?.[0])==="0"){const u=r.headers["x-ratelimit-reset"],p=typeof u=="string"?u:u?.[0],h=p?new Date(Number(p)*1e3):void 0,d=new Error(`GitHub API rate limit exceeded${h?`. Resets at ${h.toLocaleString()}`:""}. Use GITHUB_TOKEN environment variable to increase rate limit.`);throw d.status=403,d.resetTime=h,d}}throw new Error(`GitHub API error ${r.status}: ${r.statusText}`)}return JSON.parse(r.body.toString("utf8"))}async function D(e,t,s,i){const n={__proto__:null,...i},r=`${e}/${t}@${s}`;return process.env.DISABLE_GITHUB_CACHE?await b(e,t,s,n):await T().getOrFetch(r,async()=>await b(e,t,s,n))}async function b(e,t,s,i){const n={token:i.token};try{const r=`${f}/repos/${e}/${t}/git/refs/tags/${s}`,a=await o(r,n);return a.object.type==="tag"?(await o(a.object.url,n)).object.sha:a.object.sha}catch{try{const r=`${f}/repos/${e}/${t}/git/refs/heads/${s}`;return(await o(r,n)).object.sha}catch{try{const r=`${f}/repos/${e}/${t}/commits/${s}`;return(await o(r,n)).sha}catch(r){throw new Error(`failed to resolve ref "${s}" for ${e}/${t}: ${r instanceof Error?r.message:String(r)}`)}}}}async function E(){c&&await c.clear({memoOnly:!0})}async function H(e){try{const t=await(0,v.spawn)("git",["config","github.token"],{...e,stdio:"pipe"});if(t.code===0&&t.stdout)return t.stdout.toString().trim()}catch{}}async function P(){return m()||await H()}function I(e){return`https://github.com/advisories/${e}`}async function _(e,t){const s=`https://api.github.com/advisories/${e}`,i=await o(s,t);return{ghsaId:i.ghsa_id,summary:i.summary,details:i.details,severity:i.severity,aliases:i.aliases||[],publishedAt:i.published_at,updatedAt:i.updated_at,withdrawnAt:i.withdrawn_at,references:i.references||[],vulnerabilities:i.vulnerabilities||[],cvss:i.cvss,cwes:i.cwes||[]}}async function U(e,t){const s=T(),i=`ghsa:${e}`;if(!process.env.DISABLE_GITHUB_CACHE){const r=await s.get(i);if(r)return JSON.parse(r)}const n=await _(e,t);return await s.set(i,JSON.stringify(n)),n}0&&(module.exports={cacheFetchGhsa,clearRefCache,fetchGhsaDetails,fetchGitHub,getGhsaUrl,getGitHubToken,getGitHubTokenFromGitConfig,getGitHubTokenWithFallback,resolveRefToSha});
3
3
  //# sourceMappingURL=github.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/github.ts"],
4
- "sourcesContent": ["/**\n * @fileoverview GitHub utilities for Socket projects.\n * Provides GitHub API integration for repository operations.\n *\n * Authentication:\n * - getGitHubToken: Retrieve GitHub token from environment variables\n * - fetchGitHub: Authenticated GitHub API requests with rate limit handling\n *\n * Ref Resolution:\n * - resolveRefToSha: Convert tags/branches to commit SHAs (with memoization and persistent cache)\n * - clearRefCache: Clear the in-memory memoization cache\n *\n * Caching:\n * - Uses cacache for persistent storage with in-memory memoization\n * - Two-tier caching: in-memory (Map) for hot data, persistent (cacache) for durability\n * - Default TTL: 5 minutes\n * - Disable with DISABLE_GITHUB_CACHE env var\n *\n * Rate Limiting:\n * - Automatic rate limit detection and error messages\n * - Cache to minimize API calls\n */\n\nimport type { TtlCache } from './cache-with-ttl'\nimport { createTtlCache } from './cache-with-ttl'\nimport { httpRequest } from './http-request'\nimport type { SpawnOptions } from './spawn'\nimport { spawn } from './spawn'\n\n// GitHub API base URL constant (inlined for coverage mode compatibility).\nconst GITHUB_API_BASE_URL = 'https://api.github.com'\n\n// 5 minutes.\nconst DEFAULT_CACHE_TTL_MS = 5 * 60 * 1000\n\n// Create TTL cache instance for GitHub ref resolution.\n// Uses cacache for persistent storage with in-memory memoization.\nlet _githubCache: TtlCache | undefined\n\n/**\n * Get or create the GitHub cache instance.\n * Lazy initializes the cache with default TTL and memoization enabled.\n * Used internally for caching GitHub API responses.\n *\n * @returns The singleton cache instance\n */\nfunction getGithubCache(): TtlCache {\n if (_githubCache === undefined) {\n _githubCache = createTtlCache({\n memoize: true,\n prefix: 'github-refs',\n ttl: DEFAULT_CACHE_TTL_MS,\n })\n }\n return _githubCache\n}\n\n/**\n * Options for GitHub API fetch requests.\n */\nexport interface GitHubFetchOptions {\n /**\n * GitHub authentication token.\n * If not provided, will attempt to use token from environment variables.\n */\n token?: string | undefined\n /**\n * Additional HTTP headers to include in the request.\n * Will be merged with default headers (Accept, User-Agent, Authorization).\n */\n headers?: Record<string, string> | undefined\n}\n\n/**\n * Error thrown when GitHub API rate limit is exceeded.\n * Extends the standard Error with additional rate limit information.\n */\nexport interface GitHubRateLimitError extends Error {\n /** HTTP status code (always 403 for rate limit errors) */\n status: number\n /**\n * Date when the rate limit will reset.\n * Undefined if reset time is not available in response headers.\n */\n resetTime?: Date | undefined\n}\n\n/**\n * Get GitHub authentication token from environment variables.\n * Checks multiple environment variable names in priority order.\n *\n * Environment variables checked (in order):\n * 1. `GITHUB_TOKEN` - Standard GitHub token variable\n * 2. `GH_TOKEN` - Alternative GitHub CLI token variable\n * 3. `SOCKET_CLI_GITHUB_TOKEN` - Socket-specific token variable\n *\n * @returns The first available GitHub token, or `undefined` if none found\n *\n * @example\n * ```ts\n * const token = getGitHubToken()\n * if (!token) {\n * console.warn('No GitHub token found')\n * }\n * ```\n */\nexport function getGitHubToken(): string | undefined {\n const { env } = process\n return (\n env['GITHUB_TOKEN'] ||\n env['GH_TOKEN'] ||\n env['SOCKET_CLI_GITHUB_TOKEN'] ||\n undefined\n )\n}\n\n/**\n * Fetch data from GitHub API with automatic authentication and rate limit handling.\n * Makes authenticated requests to the GitHub REST API with proper error handling.\n *\n * Features:\n * - Automatic token injection from environment if not provided\n * - Rate limit detection with helpful error messages\n * - Standard GitHub API headers (Accept, User-Agent)\n * - JSON response parsing\n *\n * @template T - Expected response type (defaults to `unknown`)\n * @param url - Full GitHub API URL (e.g., 'https://api.github.com/repos/owner/repo')\n * @param options - Fetch options including token and custom headers\n * @returns Parsed JSON response of type `T`\n *\n * @throws {GitHubRateLimitError} When API rate limit is exceeded (status 403)\n * @throws {Error} For other API errors with status code and message\n *\n * @example\n * ```ts\n * // Fetch repository information\n * interface Repo {\n * name: string\n * full_name: string\n * default_branch: string\n * }\n * const repo = await fetchGitHub<Repo>(\n * 'https://api.github.com/repos/owner/repo'\n * )\n * console.log(`Default branch: ${repo.default_branch}`)\n * ```\n *\n * @example\n * ```ts\n * // With custom token and headers\n * const data = await fetchGitHub(\n * 'https://api.github.com/user',\n * {\n * token: 'ghp_customtoken',\n * headers: { 'X-Custom-Header': 'value' }\n * }\n * )\n * ```\n *\n * @example\n * ```ts\n * // Handle rate limit errors\n * try {\n * await fetchGitHub('https://api.github.com/repos/owner/repo')\n * } catch (error) {\n * if (error.status === 403 && error.resetTime) {\n * console.error(`Rate limited until ${error.resetTime}`)\n * }\n * }\n * ```\n */\nexport async function fetchGitHub<T = unknown>(\n url: string,\n options?: GitHubFetchOptions | undefined,\n): Promise<T> {\n const opts = { __proto__: null, ...options } as GitHubFetchOptions\n const token = opts.token || getGitHubToken()\n\n const headers: Record<string, string> = {\n Accept: 'application/vnd.github.v3+json',\n 'User-Agent': 'socket-registry-github-client',\n ...opts.headers,\n }\n\n if (token) {\n headers['Authorization'] = `Bearer ${token}`\n }\n\n const response = await httpRequest(url, { headers })\n\n if (!response.ok) {\n if (response.status === 403) {\n const rateLimit = response.headers['x-ratelimit-remaining']\n const rateLimitStr =\n typeof rateLimit === 'string' ? rateLimit : rateLimit?.[0]\n if (rateLimitStr === '0') {\n const resetTime = response.headers['x-ratelimit-reset']\n const resetTimeStr =\n typeof resetTime === 'string' ? resetTime : resetTime?.[0]\n const resetDate = resetTimeStr\n ? new Date(Number(resetTimeStr) * 1000)\n : undefined\n const error = new Error(\n `GitHub API rate limit exceeded${resetDate ? `. Resets at ${resetDate.toLocaleString()}` : ''}. Use GITHUB_TOKEN environment variable to increase rate limit.`,\n ) as GitHubRateLimitError\n error.status = 403\n error.resetTime = resetDate\n throw error\n }\n }\n throw new Error(\n `GitHub API error ${response.status}: ${response.statusText}`,\n )\n }\n\n return JSON.parse(response.body.toString('utf8')) as T\n}\n\n/**\n * GitHub ref object returned by the API.\n * Represents a git reference (tag or branch).\n */\nexport interface GitHubRef {\n /** The object this ref points to */\n object: {\n /** SHA of the commit or tag object */\n sha: string\n /** Type of object ('commit' or 'tag') */\n type: string\n /** API URL to fetch the full object details */\n url: string\n }\n /** Full ref path (e.g., 'refs/tags/v1.0.0' or 'refs/heads/main') */\n ref: string\n /** API URL for this ref */\n url: string\n}\n\n/**\n * GitHub annotated tag object returned by the API.\n * Represents a git tag with metadata.\n */\nexport interface GitHubTag {\n /** Tag annotation message */\n message: string\n /** The commit this tag points to */\n object: {\n /** SHA of the commit */\n sha: string\n /** Type of object (usually 'commit') */\n type: string\n /** API URL to fetch the commit details */\n url: string\n }\n /** SHA of this tag object itself */\n sha: string\n /** Tag name (e.g., 'v1.0.0') */\n tag: string\n /**\n * Information about who created the tag.\n * Undefined for lightweight tags.\n */\n tagger?: {\n /** Tag creation date in ISO 8601 format */\n date: string\n /** Tagger's email address */\n email: string\n /** Tagger's name */\n name: string\n }\n /** API URL for this tag object */\n url: string\n}\n\n/**\n * GitHub commit object returned by the API.\n * Represents a git commit with metadata.\n */\nexport interface GitHubCommit {\n /** Full commit SHA */\n sha: string\n /** API URL for this commit */\n url: string\n /** Commit details */\n commit: {\n /** Commit message */\n message: string\n /** Author information */\n author: {\n /** Commit author date in ISO 8601 format */\n date: string\n /** Author's email address */\n email: string\n /** Author's name */\n name: string\n }\n }\n}\n\n/**\n * Options for resolving git refs to commit SHAs.\n */\nexport interface ResolveRefOptions {\n /**\n * GitHub authentication token.\n * If not provided, will attempt to use token from environment variables.\n */\n token?: string | undefined\n}\n\n/**\n * Resolve a git ref (tag, branch, or commit SHA) to its full commit SHA.\n * Handles tags (annotated and lightweight), branches, and commit SHAs.\n * Results are cached in-memory and on disk (with TTL) to minimize API calls.\n *\n * Resolution strategy:\n * 1. Try as a tag (refs/tags/{ref})\n * 2. If tag is annotated, dereference to get the commit SHA\n * 3. If not a tag, try as a branch (refs/heads/{ref})\n * 4. If not a branch, try as a commit SHA directly\n *\n * Caching behavior:\n * - In-memory cache (Map) for immediate lookups\n * - Persistent disk cache (cacache) for durability across runs\n * - Default TTL: 5 minutes\n * - Disable caching with `DISABLE_GITHUB_CACHE` env var\n *\n * @param owner - Repository owner (user or organization name)\n * @param repo - Repository name\n * @param ref - Git reference to resolve (tag name, branch name, or commit SHA)\n * @param options - Resolution options including authentication token\n * @returns The full commit SHA (40-character hex string)\n *\n * @throws {Error} When ref cannot be resolved after trying all strategies\n * @throws {GitHubRateLimitError} When API rate limit is exceeded\n *\n * @example\n * ```ts\n * // Resolve a tag to commit SHA\n * const sha = await resolveRefToSha('owner', 'repo', 'v1.0.0')\n * console.log(sha) // 'a1b2c3d4e5f6...'\n * ```\n *\n * @example\n * ```ts\n * // Resolve a branch to latest commit SHA\n * const sha = await resolveRefToSha('owner', 'repo', 'main')\n * console.log(sha) // Latest commit on main branch\n * ```\n *\n * @example\n * ```ts\n * // Resolve with custom token\n * const sha = await resolveRefToSha(\n * 'owner',\n * 'repo',\n * 'develop',\n * { token: 'ghp_customtoken' }\n * )\n * ```\n *\n * @example\n * ```ts\n * // Commit SHA passes through unchanged (but validates it exists)\n * const sha = await resolveRefToSha('owner', 'repo', 'a1b2c3d4')\n * console.log(sha) // Full 40-char SHA\n * ```\n */\nexport async function resolveRefToSha(\n owner: string,\n repo: string,\n ref: string,\n options?: ResolveRefOptions | undefined,\n): Promise<string> {\n const opts = {\n __proto__: null,\n ...options,\n } as ResolveRefOptions\n\n const cacheKey = `${owner}/${repo}@${ref}`\n\n // Optionally disable cache.\n if (process.env['DISABLE_GITHUB_CACHE']) {\n return await fetchRefSha(owner, repo, ref, opts)\n }\n\n // Use TTL cache for persistent storage and in-memory memoization.\n const cache = getGithubCache()\n return await cache.getOrFetch(cacheKey, async () => {\n return await fetchRefSha(owner, repo, ref, opts)\n })\n}\n\n/**\n * Fetch the SHA for a git ref from GitHub API.\n * Internal helper that implements the multi-strategy ref resolution logic.\n * Tries tags, branches, and direct commit lookups in sequence.\n *\n * @param owner - Repository owner\n * @param repo - Repository name\n * @param ref - Git reference to resolve\n * @param options - Resolution options with authentication token\n * @returns The full commit SHA\n *\n * @throws {Error} When ref cannot be resolved after all strategies fail\n */\nasync function fetchRefSha(\n owner: string,\n repo: string,\n ref: string,\n options: ResolveRefOptions,\n): Promise<string> {\n const fetchOptions: GitHubFetchOptions = {\n token: options.token,\n }\n\n try {\n // Try as a tag first.\n const tagUrl = `${GITHUB_API_BASE_URL}/repos/${owner}/${repo}/git/refs/tags/${ref}`\n const tagData = await fetchGitHub<GitHubRef>(tagUrl, fetchOptions)\n\n // Tag might point to a tag object or directly to a commit.\n if (tagData.object.type === 'tag') {\n // Dereference the tag object to get the commit.\n const tagObject = await fetchGitHub<GitHubTag>(\n tagData.object.url,\n fetchOptions,\n )\n return tagObject.object.sha\n }\n return tagData.object.sha\n } catch {\n // Not a tag, try as a branch.\n try {\n const branchUrl = `${GITHUB_API_BASE_URL}/repos/${owner}/${repo}/git/refs/heads/${ref}`\n const branchData = await fetchGitHub<GitHubRef>(branchUrl, fetchOptions)\n return branchData.object.sha\n } catch {\n // Try without refs/ prefix (for commit SHAs or other refs).\n try {\n const commitUrl = `${GITHUB_API_BASE_URL}/repos/${owner}/${repo}/commits/${ref}`\n const commitData = await fetchGitHub<GitHubCommit>(\n commitUrl,\n fetchOptions,\n )\n return commitData.sha\n } catch (e) {\n throw new Error(\n `failed to resolve ref \"${ref}\" for ${owner}/${repo}: ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n }\n }\n}\n\n/**\n * Clear the ref resolution cache (in-memory only).\n * Clears the in-memory memoization cache without affecting the persistent disk cache.\n * Useful for testing or when you need fresh data from the API.\n *\n * Note: This only clears the in-memory cache. The persistent cacache storage\n * remains intact and will be used to rebuild the in-memory cache on next access.\n *\n * @returns Promise that resolves when cache is cleared\n *\n * @example\n * ```ts\n * // Clear cache to force fresh API calls\n * await clearRefCache()\n * const sha = await resolveRefToSha('owner', 'repo', 'main')\n * // This will hit the persistent cache or API, not in-memory cache\n * ```\n */\nexport async function clearRefCache(): Promise<void> {\n if (_githubCache) {\n await _githubCache.clear({ memoOnly: true })\n }\n}\n\n/**\n * Get GitHub authentication token from git config.\n * Reads the `github.token` configuration value from git config.\n * This is a fallback method when environment variables don't contain a token.\n *\n * @param options - Spawn options for git command execution\n * @returns GitHub token from git config, or `undefined` if not configured\n *\n * @example\n * ```ts\n * const token = await getGitHubTokenFromGitConfig()\n * if (token) {\n * console.log('Found token in git config')\n * }\n * ```\n *\n * @example\n * ```ts\n * // With custom working directory\n * const token = await getGitHubTokenFromGitConfig({\n * cwd: '/path/to/repo'\n * })\n * ```\n */\nexport async function getGitHubTokenFromGitConfig(\n options?: SpawnOptions | undefined,\n): Promise<string | undefined> {\n try {\n const result = await spawn('git', ['config', 'github.token'], {\n ...options,\n stdio: 'pipe',\n })\n if (result.code === 0 && result.stdout) {\n return result.stdout.toString().trim()\n }\n } catch {\n // Ignore errors - git config may not have token.\n }\n return undefined\n}\n\n/**\n * Get GitHub authentication token from all available sources.\n * Checks environment variables first, then falls back to git config.\n * This is the recommended way to get a GitHub token with maximum compatibility.\n *\n * Priority order:\n * 1. Environment variables (GITHUB_TOKEN, GH_TOKEN, SOCKET_CLI_GITHUB_TOKEN)\n * 2. Git config (github.token)\n *\n * @returns GitHub token from first available source, or `undefined` if none found\n *\n * @example\n * ```ts\n * const token = await getGitHubTokenWithFallback()\n * if (!token) {\n * throw new Error('GitHub token required')\n * }\n * ```\n */\nexport async function getGitHubTokenWithFallback(): Promise<\n string | undefined\n> {\n return getGitHubToken() || (await getGitHubTokenFromGitConfig())\n}\n\n/**\n * GitHub Security Advisory (GHSA) details.\n * Represents a complete security advisory from GitHub's database.\n */\nexport interface GhsaDetails {\n /** GHSA identifier (e.g., 'GHSA-xxxx-yyyy-zzzz') */\n ghsaId: string\n /** Short summary of the vulnerability */\n summary: string\n /** Detailed description of the vulnerability */\n details: string\n /** Severity level ('low', 'moderate', 'high', 'critical') */\n severity: string\n /** Alternative identifiers (CVE IDs, etc.) */\n aliases: string[]\n /** ISO 8601 timestamp when advisory was published */\n publishedAt: string\n /** ISO 8601 timestamp when advisory was last updated */\n updatedAt: string\n /**\n * ISO 8601 timestamp when advisory was withdrawn.\n * `null` if advisory is still active.\n */\n withdrawnAt: string | null\n /** External reference URLs for more information */\n references: Array<{ url: string }>\n /** Affected packages and version ranges */\n vulnerabilities: Array<{\n /** Package information */\n package: {\n /** Ecosystem (e.g., 'npm', 'pip', 'maven') */\n ecosystem: string\n /** Package name */\n name: string\n }\n /** Version range expression for vulnerable versions */\n vulnerableVersionRange: string\n /**\n * First patched version that fixes the vulnerability.\n * `null` if no patched version exists yet.\n */\n firstPatchedVersion: { identifier: string } | null\n }>\n /**\n * CVSS (Common Vulnerability Scoring System) information.\n * `null` if CVSS score is not available.\n */\n cvss: {\n /** CVSS score (0.0-10.0) */\n score: number\n /** CVSS vector string describing the vulnerability characteristics */\n vectorString: string\n } | null\n /** CWE (Common Weakness Enumeration) categories */\n cwes: Array<{\n /** CWE identifier (e.g., 'CWE-79') */\n cweId: string\n /** Human-readable CWE name */\n name: string\n /** Description of the weakness category */\n description: string\n }>\n}\n\n/**\n * Generate GitHub Security Advisory URL from GHSA ID.\n * Constructs the public advisory URL for a given GHSA identifier.\n *\n * @param ghsaId - GHSA identifier (e.g., 'GHSA-xxxx-yyyy-zzzz')\n * @returns Full URL to the advisory page\n *\n * @example\n * ```ts\n * const url = getGhsaUrl('GHSA-1234-5678-90ab')\n * console.log(url) // 'https://github.com/advisories/GHSA-1234-5678-90ab'\n * ```\n */\nexport function getGhsaUrl(ghsaId: string): string {\n return `https://github.com/advisories/${ghsaId}`\n}\n\n/**\n * Fetch GitHub Security Advisory details from the API.\n * Retrieves complete advisory information including severity, affected packages,\n * CVSS scores, and CWE classifications.\n *\n * @param ghsaId - GHSA identifier to fetch (e.g., 'GHSA-xxxx-yyyy-zzzz')\n * @param options - Fetch options including authentication token\n * @returns Complete advisory details with normalized field names\n *\n * @throws {Error} If advisory cannot be found or API request fails\n * @throws {GitHubRateLimitError} When API rate limit is exceeded\n *\n * @example\n * ```ts\n * const advisory = await fetchGhsaDetails('GHSA-1234-5678-90ab')\n * console.log(`Severity: ${advisory.severity}`)\n * console.log(`Affects: ${advisory.vulnerabilities.length} packages`)\n * if (advisory.cvss) {\n * console.log(`CVSS Score: ${advisory.cvss.score}`)\n * }\n * ```\n *\n * @example\n * ```ts\n * // Check if vulnerability is patched\n * const advisory = await fetchGhsaDetails('GHSA-xxxx-yyyy-zzzz')\n * for (const vuln of advisory.vulnerabilities) {\n * if (vuln.firstPatchedVersion) {\n * console.log(\n * `Patched in ${vuln.package.name}@${vuln.firstPatchedVersion.identifier}`\n * )\n * }\n * }\n * ```\n */\nexport async function fetchGhsaDetails(\n ghsaId: string,\n options?: GitHubFetchOptions | undefined,\n): Promise<GhsaDetails> {\n const url = `https://api.github.com/advisories/${ghsaId}`\n const data = await fetchGitHub<{\n aliases?: string[]\n cvss: unknown\n cwes?: Array<{ cweId: string; name: string; description: string }>\n details: string\n ghsa_id: string\n published_at: string\n references?: Array<{ url: string }>\n severity: string\n summary: string\n updated_at: string\n vulnerabilities?: Array<{\n package: { ecosystem: string; name: string }\n vulnerableVersionRange: string\n firstPatchedVersion: { identifier: string } | null\n }>\n withdrawn_at: string\n }>(url, options)\n\n return {\n ghsaId: data.ghsa_id,\n summary: data.summary,\n details: data.details,\n severity: data.severity,\n aliases: data.aliases || [],\n publishedAt: data.published_at,\n updatedAt: data.updated_at,\n withdrawnAt: data.withdrawn_at,\n references: data.references || [],\n vulnerabilities: data.vulnerabilities || [],\n cvss: data.cvss as { score: number; vectorString: string } | null,\n cwes: data.cwes || [],\n }\n}\n\n/**\n * Fetch GitHub Security Advisory details with caching.\n * Retrieves advisory information with two-tier caching (in-memory + persistent).\n * Cached results are stored with the default TTL (5 minutes).\n *\n * Caching behavior:\n * - Checks in-memory cache first for immediate response\n * - Falls back to persistent disk cache if not in memory\n * - Fetches from API only if not cached\n * - Stores result in both cache tiers\n * - Respects `DISABLE_GITHUB_CACHE` env var\n *\n * @param ghsaId - GHSA identifier to fetch\n * @param options - Fetch options including authentication token\n * @returns Complete advisory details\n *\n * @throws {Error} If advisory cannot be found or API request fails\n * @throws {GitHubRateLimitError} When API rate limit is exceeded\n *\n * @example\n * ```ts\n * // First call hits API\n * const advisory = await cacheFetchGhsa('GHSA-1234-5678-90ab')\n *\n * // Second call within 5 minutes returns cached data\n * const cached = await cacheFetchGhsa('GHSA-1234-5678-90ab')\n * ```\n *\n * @example\n * ```ts\n * // Disable caching for fresh data\n * process.env.DISABLE_GITHUB_CACHE = '1'\n * const advisory = await cacheFetchGhsa('GHSA-xxxx-yyyy-zzzz')\n * ```\n */\nexport async function cacheFetchGhsa(\n ghsaId: string,\n options?: GitHubFetchOptions | undefined,\n): Promise<GhsaDetails> {\n const cache = getGithubCache()\n const key = `ghsa:${ghsaId}`\n\n // Check cache first.\n if (!process.env['DISABLE_GITHUB_CACHE']) {\n const cached = await cache.get(key)\n if (cached) {\n return JSON.parse(cached as string) as GhsaDetails\n }\n }\n\n // Fetch and cache.\n const data = await fetchGhsaDetails(ghsaId, options)\n await cache.set(key, JSON.stringify(data))\n return data\n}\n"],
5
- "mappings": "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",
6
- "names": ["github_exports", "__export", "cacheFetchGhsa", "clearRefCache", "fetchGhsaDetails", "fetchGitHub", "getGhsaUrl", "getGitHubToken", "getGitHubTokenFromGitConfig", "getGitHubTokenWithFallback", "resolveRefToSha", "__toCommonJS", "import_cache_with_ttl", "import_http_request", "import_spawn", "GITHUB_API_BASE_URL", "DEFAULT_CACHE_TTL_MS", "_githubCache", "getGithubCache", "env", "url", "options", "opts", "token", "headers", "response", "rateLimit", "resetTime", "resetTimeStr", "resetDate", "error", "owner", "repo", "ref", "cacheKey", "fetchRefSha", "fetchOptions", "tagUrl", "tagData", "branchUrl", "commitUrl", "e", "result", "ghsaId", "data", "cache", "key", "cached"]
4
+ "sourcesContent": ["/**\n * @fileoverview GitHub utilities for Socket projects.\n * Provides GitHub API integration for repository operations.\n *\n * Authentication:\n * - getGitHubToken: Retrieve GitHub token from environment variables\n * - fetchGitHub: Authenticated GitHub API requests with rate limit handling\n *\n * Ref Resolution:\n * - resolveRefToSha: Convert tags/branches to commit SHAs (with memoization and persistent cache)\n * - clearRefCache: Clear the in-memory memoization cache\n *\n * Caching:\n * - Uses cacache for persistent storage with in-memory memoization\n * - Two-tier caching: in-memory (Map) for hot data, persistent (cacache) for durability\n * - Default TTL: 5 minutes\n * - Disable with DISABLE_GITHUB_CACHE env var\n *\n * Rate Limiting:\n * - Automatic rate limit detection and error messages\n * - Cache to minimize API calls\n */\n\nimport type { TtlCache } from './cache-with-ttl'\nimport { createTtlCache } from './cache-with-ttl'\nimport { getGhToken, getGithubToken } from '#env/github'\nimport { getSocketCliGithubToken } from '#env/socket-cli'\nimport { httpRequest } from './http-request'\nimport type { SpawnOptions } from './spawn'\nimport { spawn } from './spawn'\n\n// GitHub API base URL constant (inlined for coverage mode compatibility).\nconst GITHUB_API_BASE_URL = 'https://api.github.com'\n\n// 5 minutes.\nconst DEFAULT_CACHE_TTL_MS = 5 * 60 * 1000\n\n// Create TTL cache instance for GitHub ref resolution.\n// Uses cacache for persistent storage with in-memory memoization.\nlet _githubCache: TtlCache | undefined\n\n/**\n * Get or create the GitHub cache instance.\n * Lazy initializes the cache with default TTL and memoization enabled.\n * Used internally for caching GitHub API responses.\n *\n * @returns The singleton cache instance\n */\nfunction getGithubCache(): TtlCache {\n if (_githubCache === undefined) {\n _githubCache = createTtlCache({\n memoize: true,\n prefix: 'github-refs',\n ttl: DEFAULT_CACHE_TTL_MS,\n })\n }\n return _githubCache\n}\n\n/**\n * Options for GitHub API fetch requests.\n */\nexport interface GitHubFetchOptions {\n /**\n * GitHub authentication token.\n * If not provided, will attempt to use token from environment variables.\n */\n token?: string | undefined\n /**\n * Additional HTTP headers to include in the request.\n * Will be merged with default headers (Accept, User-Agent, Authorization).\n */\n headers?: Record<string, string> | undefined\n}\n\n/**\n * Error thrown when GitHub API rate limit is exceeded.\n * Extends the standard Error with additional rate limit information.\n */\nexport interface GitHubRateLimitError extends Error {\n /** HTTP status code (always 403 for rate limit errors) */\n status: number\n /**\n * Date when the rate limit will reset.\n * Undefined if reset time is not available in response headers.\n */\n resetTime?: Date | undefined\n}\n\n/**\n * Get GitHub authentication token from environment variables.\n * Checks multiple environment variable names in priority order.\n *\n * Environment variables checked (in order):\n * 1. `GITHUB_TOKEN` - Standard GitHub token variable\n * 2. `GH_TOKEN` - Alternative GitHub CLI token variable\n * 3. `SOCKET_CLI_GITHUB_TOKEN` - Socket-specific token variable\n *\n * @returns The first available GitHub token, or `undefined` if none found\n *\n * @example\n * ```ts\n * const token = getGitHubToken()\n * if (!token) {\n * console.warn('No GitHub token found')\n * }\n * ```\n */\nexport function getGitHubToken(): string | undefined {\n return (\n getGithubToken() || getGhToken() || getSocketCliGithubToken() || undefined\n )\n}\n\n/**\n * Fetch data from GitHub API with automatic authentication and rate limit handling.\n * Makes authenticated requests to the GitHub REST API with proper error handling.\n *\n * Features:\n * - Automatic token injection from environment if not provided\n * - Rate limit detection with helpful error messages\n * - Standard GitHub API headers (Accept, User-Agent)\n * - JSON response parsing\n *\n * @template T - Expected response type (defaults to `unknown`)\n * @param url - Full GitHub API URL (e.g., 'https://api.github.com/repos/owner/repo')\n * @param options - Fetch options including token and custom headers\n * @returns Parsed JSON response of type `T`\n *\n * @throws {GitHubRateLimitError} When API rate limit is exceeded (status 403)\n * @throws {Error} For other API errors with status code and message\n *\n * @example\n * ```ts\n * // Fetch repository information\n * interface Repo {\n * name: string\n * full_name: string\n * default_branch: string\n * }\n * const repo = await fetchGitHub<Repo>(\n * 'https://api.github.com/repos/owner/repo'\n * )\n * console.log(`Default branch: ${repo.default_branch}`)\n * ```\n *\n * @example\n * ```ts\n * // With custom token and headers\n * const data = await fetchGitHub(\n * 'https://api.github.com/user',\n * {\n * token: 'ghp_customtoken',\n * headers: { 'X-Custom-Header': 'value' }\n * }\n * )\n * ```\n *\n * @example\n * ```ts\n * // Handle rate limit errors\n * try {\n * await fetchGitHub('https://api.github.com/repos/owner/repo')\n * } catch (error) {\n * if (error.status === 403 && error.resetTime) {\n * console.error(`Rate limited until ${error.resetTime}`)\n * }\n * }\n * ```\n */\nexport async function fetchGitHub<T = unknown>(\n url: string,\n options?: GitHubFetchOptions | undefined,\n): Promise<T> {\n const opts = { __proto__: null, ...options } as GitHubFetchOptions\n const token = opts.token || getGitHubToken()\n\n const headers: Record<string, string> = {\n Accept: 'application/vnd.github.v3+json',\n 'User-Agent': 'socket-registry-github-client',\n ...opts.headers,\n }\n\n if (token) {\n headers['Authorization'] = `Bearer ${token}`\n }\n\n const response = await httpRequest(url, { headers })\n\n if (!response.ok) {\n if (response.status === 403) {\n const rateLimit = response.headers['x-ratelimit-remaining']\n const rateLimitStr =\n typeof rateLimit === 'string' ? rateLimit : rateLimit?.[0]\n if (rateLimitStr === '0') {\n const resetTime = response.headers['x-ratelimit-reset']\n const resetTimeStr =\n typeof resetTime === 'string' ? resetTime : resetTime?.[0]\n const resetDate = resetTimeStr\n ? new Date(Number(resetTimeStr) * 1000)\n : undefined\n const error = new Error(\n `GitHub API rate limit exceeded${resetDate ? `. Resets at ${resetDate.toLocaleString()}` : ''}. Use GITHUB_TOKEN environment variable to increase rate limit.`,\n ) as GitHubRateLimitError\n error.status = 403\n error.resetTime = resetDate\n throw error\n }\n }\n throw new Error(\n `GitHub API error ${response.status}: ${response.statusText}`,\n )\n }\n\n return JSON.parse(response.body.toString('utf8')) as T\n}\n\n/**\n * GitHub ref object returned by the API.\n * Represents a git reference (tag or branch).\n */\nexport interface GitHubRef {\n /** The object this ref points to */\n object: {\n /** SHA of the commit or tag object */\n sha: string\n /** Type of object ('commit' or 'tag') */\n type: string\n /** API URL to fetch the full object details */\n url: string\n }\n /** Full ref path (e.g., 'refs/tags/v1.0.0' or 'refs/heads/main') */\n ref: string\n /** API URL for this ref */\n url: string\n}\n\n/**\n * GitHub annotated tag object returned by the API.\n * Represents a git tag with metadata.\n */\nexport interface GitHubTag {\n /** Tag annotation message */\n message: string\n /** The commit this tag points to */\n object: {\n /** SHA of the commit */\n sha: string\n /** Type of object (usually 'commit') */\n type: string\n /** API URL to fetch the commit details */\n url: string\n }\n /** SHA of this tag object itself */\n sha: string\n /** Tag name (e.g., 'v1.0.0') */\n tag: string\n /**\n * Information about who created the tag.\n * Undefined for lightweight tags.\n */\n tagger?: {\n /** Tag creation date in ISO 8601 format */\n date: string\n /** Tagger's email address */\n email: string\n /** Tagger's name */\n name: string\n }\n /** API URL for this tag object */\n url: string\n}\n\n/**\n * GitHub commit object returned by the API.\n * Represents a git commit with metadata.\n */\nexport interface GitHubCommit {\n /** Full commit SHA */\n sha: string\n /** API URL for this commit */\n url: string\n /** Commit details */\n commit: {\n /** Commit message */\n message: string\n /** Author information */\n author: {\n /** Commit author date in ISO 8601 format */\n date: string\n /** Author's email address */\n email: string\n /** Author's name */\n name: string\n }\n }\n}\n\n/**\n * Options for resolving git refs to commit SHAs.\n */\nexport interface ResolveRefOptions {\n /**\n * GitHub authentication token.\n * If not provided, will attempt to use token from environment variables.\n */\n token?: string | undefined\n}\n\n/**\n * Resolve a git ref (tag, branch, or commit SHA) to its full commit SHA.\n * Handles tags (annotated and lightweight), branches, and commit SHAs.\n * Results are cached in-memory and on disk (with TTL) to minimize API calls.\n *\n * Resolution strategy:\n * 1. Try as a tag (refs/tags/{ref})\n * 2. If tag is annotated, dereference to get the commit SHA\n * 3. If not a tag, try as a branch (refs/heads/{ref})\n * 4. If not a branch, try as a commit SHA directly\n *\n * Caching behavior:\n * - In-memory cache (Map) for immediate lookups\n * - Persistent disk cache (cacache) for durability across runs\n * - Default TTL: 5 minutes\n * - Disable caching with `DISABLE_GITHUB_CACHE` env var\n *\n * @param owner - Repository owner (user or organization name)\n * @param repo - Repository name\n * @param ref - Git reference to resolve (tag name, branch name, or commit SHA)\n * @param options - Resolution options including authentication token\n * @returns The full commit SHA (40-character hex string)\n *\n * @throws {Error} When ref cannot be resolved after trying all strategies\n * @throws {GitHubRateLimitError} When API rate limit is exceeded\n *\n * @example\n * ```ts\n * // Resolve a tag to commit SHA\n * const sha = await resolveRefToSha('owner', 'repo', 'v1.0.0')\n * console.log(sha) // 'a1b2c3d4e5f6...'\n * ```\n *\n * @example\n * ```ts\n * // Resolve a branch to latest commit SHA\n * const sha = await resolveRefToSha('owner', 'repo', 'main')\n * console.log(sha) // Latest commit on main branch\n * ```\n *\n * @example\n * ```ts\n * // Resolve with custom token\n * const sha = await resolveRefToSha(\n * 'owner',\n * 'repo',\n * 'develop',\n * { token: 'ghp_customtoken' }\n * )\n * ```\n *\n * @example\n * ```ts\n * // Commit SHA passes through unchanged (but validates it exists)\n * const sha = await resolveRefToSha('owner', 'repo', 'a1b2c3d4')\n * console.log(sha) // Full 40-char SHA\n * ```\n */\nexport async function resolveRefToSha(\n owner: string,\n repo: string,\n ref: string,\n options?: ResolveRefOptions | undefined,\n): Promise<string> {\n const opts = {\n __proto__: null,\n ...options,\n } as ResolveRefOptions\n\n const cacheKey = `${owner}/${repo}@${ref}`\n\n // Optionally disable cache.\n if (process.env['DISABLE_GITHUB_CACHE']) {\n return await fetchRefSha(owner, repo, ref, opts)\n }\n\n // Use TTL cache for persistent storage and in-memory memoization.\n const cache = getGithubCache()\n return await cache.getOrFetch(cacheKey, async () => {\n return await fetchRefSha(owner, repo, ref, opts)\n })\n}\n\n/**\n * Fetch the SHA for a git ref from GitHub API.\n * Internal helper that implements the multi-strategy ref resolution logic.\n * Tries tags, branches, and direct commit lookups in sequence.\n *\n * @param owner - Repository owner\n * @param repo - Repository name\n * @param ref - Git reference to resolve\n * @param options - Resolution options with authentication token\n * @returns The full commit SHA\n *\n * @throws {Error} When ref cannot be resolved after all strategies fail\n */\nasync function fetchRefSha(\n owner: string,\n repo: string,\n ref: string,\n options: ResolveRefOptions,\n): Promise<string> {\n const fetchOptions: GitHubFetchOptions = {\n token: options.token,\n }\n\n try {\n // Try as a tag first.\n const tagUrl = `${GITHUB_API_BASE_URL}/repos/${owner}/${repo}/git/refs/tags/${ref}`\n const tagData = await fetchGitHub<GitHubRef>(tagUrl, fetchOptions)\n\n // Tag might point to a tag object or directly to a commit.\n if (tagData.object.type === 'tag') {\n // Dereference the tag object to get the commit.\n const tagObject = await fetchGitHub<GitHubTag>(\n tagData.object.url,\n fetchOptions,\n )\n return tagObject.object.sha\n }\n return tagData.object.sha\n } catch {\n // Not a tag, try as a branch.\n try {\n const branchUrl = `${GITHUB_API_BASE_URL}/repos/${owner}/${repo}/git/refs/heads/${ref}`\n const branchData = await fetchGitHub<GitHubRef>(branchUrl, fetchOptions)\n return branchData.object.sha\n } catch {\n // Try without refs/ prefix (for commit SHAs or other refs).\n try {\n const commitUrl = `${GITHUB_API_BASE_URL}/repos/${owner}/${repo}/commits/${ref}`\n const commitData = await fetchGitHub<GitHubCommit>(\n commitUrl,\n fetchOptions,\n )\n return commitData.sha\n } catch (e) {\n throw new Error(\n `failed to resolve ref \"${ref}\" for ${owner}/${repo}: ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n }\n }\n}\n\n/**\n * Clear the ref resolution cache (in-memory only).\n * Clears the in-memory memoization cache without affecting the persistent disk cache.\n * Useful for testing or when you need fresh data from the API.\n *\n * Note: This only clears the in-memory cache. The persistent cacache storage\n * remains intact and will be used to rebuild the in-memory cache on next access.\n *\n * @returns Promise that resolves when cache is cleared\n *\n * @example\n * ```ts\n * // Clear cache to force fresh API calls\n * await clearRefCache()\n * const sha = await resolveRefToSha('owner', 'repo', 'main')\n * // This will hit the persistent cache or API, not in-memory cache\n * ```\n */\nexport async function clearRefCache(): Promise<void> {\n if (_githubCache) {\n await _githubCache.clear({ memoOnly: true })\n }\n}\n\n/**\n * Get GitHub authentication token from git config.\n * Reads the `github.token` configuration value from git config.\n * This is a fallback method when environment variables don't contain a token.\n *\n * @param options - Spawn options for git command execution\n * @returns GitHub token from git config, or `undefined` if not configured\n *\n * @example\n * ```ts\n * const token = await getGitHubTokenFromGitConfig()\n * if (token) {\n * console.log('Found token in git config')\n * }\n * ```\n *\n * @example\n * ```ts\n * // With custom working directory\n * const token = await getGitHubTokenFromGitConfig({\n * cwd: '/path/to/repo'\n * })\n * ```\n */\nexport async function getGitHubTokenFromGitConfig(\n options?: SpawnOptions | undefined,\n): Promise<string | undefined> {\n try {\n const result = await spawn('git', ['config', 'github.token'], {\n ...options,\n stdio: 'pipe',\n })\n if (result.code === 0 && result.stdout) {\n return result.stdout.toString().trim()\n }\n } catch {\n // Ignore errors - git config may not have token.\n }\n return undefined\n}\n\n/**\n * Get GitHub authentication token from all available sources.\n * Checks environment variables first, then falls back to git config.\n * This is the recommended way to get a GitHub token with maximum compatibility.\n *\n * Priority order:\n * 1. Environment variables (GITHUB_TOKEN, GH_TOKEN, SOCKET_CLI_GITHUB_TOKEN)\n * 2. Git config (github.token)\n *\n * @returns GitHub token from first available source, or `undefined` if none found\n *\n * @example\n * ```ts\n * const token = await getGitHubTokenWithFallback()\n * if (!token) {\n * throw new Error('GitHub token required')\n * }\n * ```\n */\nexport async function getGitHubTokenWithFallback(): Promise<\n string | undefined\n> {\n return getGitHubToken() || (await getGitHubTokenFromGitConfig())\n}\n\n/**\n * GitHub Security Advisory (GHSA) details.\n * Represents a complete security advisory from GitHub's database.\n */\nexport interface GhsaDetails {\n /** GHSA identifier (e.g., 'GHSA-xxxx-yyyy-zzzz') */\n ghsaId: string\n /** Short summary of the vulnerability */\n summary: string\n /** Detailed description of the vulnerability */\n details: string\n /** Severity level ('low', 'moderate', 'high', 'critical') */\n severity: string\n /** Alternative identifiers (CVE IDs, etc.) */\n aliases: string[]\n /** ISO 8601 timestamp when advisory was published */\n publishedAt: string\n /** ISO 8601 timestamp when advisory was last updated */\n updatedAt: string\n /**\n * ISO 8601 timestamp when advisory was withdrawn.\n * `null` if advisory is still active.\n */\n withdrawnAt: string | null\n /** External reference URLs for more information */\n references: Array<{ url: string }>\n /** Affected packages and version ranges */\n vulnerabilities: Array<{\n /** Package information */\n package: {\n /** Ecosystem (e.g., 'npm', 'pip', 'maven') */\n ecosystem: string\n /** Package name */\n name: string\n }\n /** Version range expression for vulnerable versions */\n vulnerableVersionRange: string\n /**\n * First patched version that fixes the vulnerability.\n * `null` if no patched version exists yet.\n */\n firstPatchedVersion: { identifier: string } | null\n }>\n /**\n * CVSS (Common Vulnerability Scoring System) information.\n * `null` if CVSS score is not available.\n */\n cvss: {\n /** CVSS score (0.0-10.0) */\n score: number\n /** CVSS vector string describing the vulnerability characteristics */\n vectorString: string\n } | null\n /** CWE (Common Weakness Enumeration) categories */\n cwes: Array<{\n /** CWE identifier (e.g., 'CWE-79') */\n cweId: string\n /** Human-readable CWE name */\n name: string\n /** Description of the weakness category */\n description: string\n }>\n}\n\n/**\n * Generate GitHub Security Advisory URL from GHSA ID.\n * Constructs the public advisory URL for a given GHSA identifier.\n *\n * @param ghsaId - GHSA identifier (e.g., 'GHSA-xxxx-yyyy-zzzz')\n * @returns Full URL to the advisory page\n *\n * @example\n * ```ts\n * const url = getGhsaUrl('GHSA-1234-5678-90ab')\n * console.log(url) // 'https://github.com/advisories/GHSA-1234-5678-90ab'\n * ```\n */\nexport function getGhsaUrl(ghsaId: string): string {\n return `https://github.com/advisories/${ghsaId}`\n}\n\n/**\n * Fetch GitHub Security Advisory details from the API.\n * Retrieves complete advisory information including severity, affected packages,\n * CVSS scores, and CWE classifications.\n *\n * @param ghsaId - GHSA identifier to fetch (e.g., 'GHSA-xxxx-yyyy-zzzz')\n * @param options - Fetch options including authentication token\n * @returns Complete advisory details with normalized field names\n *\n * @throws {Error} If advisory cannot be found or API request fails\n * @throws {GitHubRateLimitError} When API rate limit is exceeded\n *\n * @example\n * ```ts\n * const advisory = await fetchGhsaDetails('GHSA-1234-5678-90ab')\n * console.log(`Severity: ${advisory.severity}`)\n * console.log(`Affects: ${advisory.vulnerabilities.length} packages`)\n * if (advisory.cvss) {\n * console.log(`CVSS Score: ${advisory.cvss.score}`)\n * }\n * ```\n *\n * @example\n * ```ts\n * // Check if vulnerability is patched\n * const advisory = await fetchGhsaDetails('GHSA-xxxx-yyyy-zzzz')\n * for (const vuln of advisory.vulnerabilities) {\n * if (vuln.firstPatchedVersion) {\n * console.log(\n * `Patched in ${vuln.package.name}@${vuln.firstPatchedVersion.identifier}`\n * )\n * }\n * }\n * ```\n */\nexport async function fetchGhsaDetails(\n ghsaId: string,\n options?: GitHubFetchOptions | undefined,\n): Promise<GhsaDetails> {\n const url = `https://api.github.com/advisories/${ghsaId}`\n const data = await fetchGitHub<{\n aliases?: string[]\n cvss: unknown\n cwes?: Array<{ cweId: string; name: string; description: string }>\n details: string\n ghsa_id: string\n published_at: string\n references?: Array<{ url: string }>\n severity: string\n summary: string\n updated_at: string\n vulnerabilities?: Array<{\n package: { ecosystem: string; name: string }\n vulnerableVersionRange: string\n firstPatchedVersion: { identifier: string } | null\n }>\n withdrawn_at: string\n }>(url, options)\n\n return {\n ghsaId: data.ghsa_id,\n summary: data.summary,\n details: data.details,\n severity: data.severity,\n aliases: data.aliases || [],\n publishedAt: data.published_at,\n updatedAt: data.updated_at,\n withdrawnAt: data.withdrawn_at,\n references: data.references || [],\n vulnerabilities: data.vulnerabilities || [],\n cvss: data.cvss as { score: number; vectorString: string } | null,\n cwes: data.cwes || [],\n }\n}\n\n/**\n * Fetch GitHub Security Advisory details with caching.\n * Retrieves advisory information with two-tier caching (in-memory + persistent).\n * Cached results are stored with the default TTL (5 minutes).\n *\n * Caching behavior:\n * - Checks in-memory cache first for immediate response\n * - Falls back to persistent disk cache if not in memory\n * - Fetches from API only if not cached\n * - Stores result in both cache tiers\n * - Respects `DISABLE_GITHUB_CACHE` env var\n *\n * @param ghsaId - GHSA identifier to fetch\n * @param options - Fetch options including authentication token\n * @returns Complete advisory details\n *\n * @throws {Error} If advisory cannot be found or API request fails\n * @throws {GitHubRateLimitError} When API rate limit is exceeded\n *\n * @example\n * ```ts\n * // First call hits API\n * const advisory = await cacheFetchGhsa('GHSA-1234-5678-90ab')\n *\n * // Second call within 5 minutes returns cached data\n * const cached = await cacheFetchGhsa('GHSA-1234-5678-90ab')\n * ```\n *\n * @example\n * ```ts\n * // Disable caching for fresh data\n * process.env.DISABLE_GITHUB_CACHE = '1'\n * const advisory = await cacheFetchGhsa('GHSA-xxxx-yyyy-zzzz')\n * ```\n */\nexport async function cacheFetchGhsa(\n ghsaId: string,\n options?: GitHubFetchOptions | undefined,\n): Promise<GhsaDetails> {\n const cache = getGithubCache()\n const key = `ghsa:${ghsaId}`\n\n // Check cache first.\n if (!process.env['DISABLE_GITHUB_CACHE']) {\n const cached = await cache.get(key)\n if (cached) {\n return JSON.parse(cached as string) as GhsaDetails\n }\n }\n\n // Fetch and cache.\n const data = await fetchGhsaDetails(ghsaId, options)\n await cache.set(key, JSON.stringify(data))\n return data\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["github_exports", "__export", "cacheFetchGhsa", "clearRefCache", "fetchGhsaDetails", "fetchGitHub", "getGhsaUrl", "getGitHubToken", "getGitHubTokenFromGitConfig", "getGitHubTokenWithFallback", "resolveRefToSha", "__toCommonJS", "import_cache_with_ttl", "import_github", "import_socket_cli", "import_http_request", "import_spawn", "GITHUB_API_BASE_URL", "DEFAULT_CACHE_TTL_MS", "_githubCache", "getGithubCache", "url", "options", "opts", "token", "headers", "response", "rateLimit", "resetTime", "resetTimeStr", "resetDate", "error", "owner", "repo", "ref", "cacheKey", "fetchRefSha", "fetchOptions", "tagUrl", "tagData", "branchUrl", "commitUrl", "e", "result", "ghsaId", "data", "cache", "key", "cached"]
7
7
  }
package/dist/globs.js CHANGED
@@ -1,3 +1,3 @@
1
1
  /* Socket Lib - Built with esbuild */
2
- var l=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var _=Object.prototype.hasOwnProperty;var O=(e,o)=>{for(var n in o)l(e,n,{get:o[n],enumerable:!0})},y=(e,o,n,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let t of h(o))!_.call(e,t)&&t!==n&&l(e,t,{get:()=>o[t],enumerable:!(r=d(o,t))||r.enumerable});return e};var S=e=>y(l({},"__esModule",{value:!0}),e);var L={};O(L,{defaultIgnore:()=>f,getGlobMatcher:()=>w,globStreamLicenses:()=>v});module.exports=S(L);var u=require("./objects");const f=(0,u.objectFreeze)(["**/.git","**/.npmrc","**/node_modules","**/.DS_Store","**/.gitignore","**/.hg","**/.lock-wscript","**/.npmignore","**/.svn","**/.wafpickle-*","**/.*.swp","**/._*/**","**/archived-packages/**","**/build/config.gypi","**/CVS","**/npm-debug.log","**/*.orig","**/.env","**/.eslintcache","**/.nvm","**/.tap","**/.vscode","**/*.tsbuildinfo","**/Thumbs.db","**/bower_components"]);let c;function G(){return c===void 0&&(c=require("./external/picomatch")),c}let b;function E(){if(b===void 0){const e=require("./external/fast-glob");b=e.default||e}return b}function v(e,o){const{ignore:n,ignoreOriginals:r,recursive:t,...a}={__proto__:null,...o},s=[...Array.isArray(n)?n:f,"**/*.{cjs,cts,js,json,mjs,mts,ts}"];return r&&s.push(require("./constants/paths").LICENSE_ORIGINAL_GLOB_RECURSIVE),E().globStream([t?require("./constants/paths").LICENSE_GLOB_RECURSIVE:require("./constants/paths").LICENSE_GLOB],{__proto__:null,absolute:!0,caseSensitiveMatch:!1,cwd:e,...a,...s?{ignore:s}:{}})}const g=new Map;function w(e,o){const n=Array.isArray(e)?e:[e],r=JSON.stringify({patterns:n,options:o});let t=g.get(r);if(t)return t;const a=n.filter(i=>!i.startsWith("!")),s=n.filter(i=>i.startsWith("!")).map(i=>i.slice(1)),p=G(),m={dot:!0,nocase:!0,...o,...s.length>0?{ignore:s}:{}};return t=p(a.length>0?a:n,m),g.set(r,t),t}0&&(module.exports={defaultIgnore,getGlobMatcher,globStreamLicenses});
2
+ var l=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var _=Object.prototype.hasOwnProperty;var O=(e,o)=>{for(var n in o)l(e,n,{get:o[n],enumerable:!0})},y=(e,o,n,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let t of h(o))!_.call(e,t)&&t!==n&&l(e,t,{get:()=>o[t],enumerable:!(r=d(o,t))||r.enumerable});return e};var S=e=>y(l({},"__esModule",{value:!0}),e);var L={};O(L,{defaultIgnore:()=>f,getGlobMatcher:()=>w,globStreamLicenses:()=>v});module.exports=S(L);var u=require("./objects");const f=(0,u.objectFreeze)(["**/.git","**/.npmrc","**/node_modules","**/.DS_Store","**/.gitignore","**/.hg","**/.lock-wscript","**/.npmignore","**/.svn","**/.wafpickle-*","**/.*.swp","**/._*/**","**/archived-packages/**","**/build/config.gypi","**/CVS","**/npm-debug.log","**/*.orig","**/.env","**/.eslintcache","**/.nvm","**/.tap","**/.vscode","**/*.tsbuildinfo","**/Thumbs.db","**/bower_components"]);let c;function G(){return c===void 0&&(c=require("./external/picomatch")),c}let b;function E(){if(b===void 0){const e=require("./external/fast-glob");b=e.default||e}return b}function v(e,o){const{ignore:n,ignoreOriginals:r,recursive:t,...a}={__proto__:null,...o},s=[...Array.isArray(n)?n:f,"**/*.{cjs,cts,js,json,mjs,mts,ts}"];return r&&s.push(require("#constants/paths").LICENSE_ORIGINAL_GLOB_RECURSIVE),E().globStream([t?require("#constants/paths").LICENSE_GLOB_RECURSIVE:require("#constants/paths").LICENSE_GLOB],{__proto__:null,absolute:!0,caseSensitiveMatch:!1,cwd:e,...a,...s?{ignore:s}:{}})}const g=new Map;function w(e,o){const n=Array.isArray(e)?e:[e],r=JSON.stringify({patterns:n,options:o});let t=g.get(r);if(t)return t;const a=n.filter(i=>!i.startsWith("!")),s=n.filter(i=>i.startsWith("!")).map(i=>i.slice(1)),p=G(),m={dot:!0,nocase:!0,...o,...s.length>0?{ignore:s}:{}};return t=p(a.length>0?a:n,m),g.set(r,t),t}0&&(module.exports={defaultIgnore,getGlobMatcher,globStreamLicenses});
3
3
  //# sourceMappingURL=globs.js.map
package/dist/globs.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/globs.ts"],
4
- "sourcesContent": ["/**\n * @fileoverview Glob pattern matching utilities with default ignore patterns.\n * Provides file filtering and glob matcher functions for npm-like behavior.\n */\n\n// IMPORTANT: Do not use destructuring here - use direct assignment instead.\nimport { objectFreeze as ObjectFreeze } from './objects'\n\n// Type definitions\ntype Pattern = string\n\ninterface FastGlobOptions {\n absolute?: boolean\n baseNameMatch?: boolean\n braceExpansion?: boolean\n caseSensitiveMatch?: boolean\n concurrency?: number\n cwd?: string\n deep?: number\n dot?: boolean\n extglob?: boolean\n followSymbolicLinks?: boolean\n fs?: unknown\n globstar?: boolean\n ignore?: string[]\n ignoreFiles?: string[]\n markDirectories?: boolean\n objectMode?: boolean\n onlyDirectories?: boolean\n onlyFiles?: boolean\n stats?: boolean\n suppressErrors?: boolean\n throwErrorOnBrokenSymbolicLink?: boolean\n unique?: boolean\n}\n\nexport interface GlobOptions extends FastGlobOptions {\n ignoreOriginals?: boolean\n recursive?: boolean\n}\n\nexport type { Pattern, FastGlobOptions }\n\nexport const defaultIgnore = ObjectFreeze([\n // Most of these ignored files can be included specifically if included in the\n // files globs. Exceptions to this are:\n // https://docs.npmjs.com/cli/v10/configuring-npm/package-json#files\n // These can NOT be included.\n // https://github.com/npm/npm-packlist/blob/v10.0.0/lib/index.js#L280\n '**/.git',\n '**/.npmrc',\n // '**/bun.lockb?',\n '**/node_modules',\n // '**/package-lock.json',\n // '**/pnpm-lock.ya?ml',\n // '**/yarn.lock',\n // Include npm-packlist defaults:\n // https://github.com/npm/npm-packlist/blob/v10.0.0/lib/index.js#L15-L38\n '**/.DS_Store',\n '**/.gitignore',\n '**/.hg',\n '**/.lock-wscript',\n '**/.npmignore',\n '**/.svn',\n '**/.wafpickle-*',\n '**/.*.swp',\n '**/._*/**',\n '**/archived-packages/**',\n '**/build/config.gypi',\n '**/CVS',\n '**/npm-debug.log',\n '**/*.orig',\n // Inline generic socket-registry .gitignore entries.\n '**/.env',\n '**/.eslintcache',\n '**/.nvm',\n '**/.tap',\n '**/.vscode',\n '**/*.tsbuildinfo',\n '**/Thumbs.db',\n // Inline additional ignores.\n '**/bower_components',\n])\n\nlet _picomatch: typeof import('picomatch') | undefined\n/**\n * Lazily load the picomatch module.\n * @private\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getPicomatch() {\n if (_picomatch === undefined) {\n // The 'picomatch' package is browser safe.\n _picomatch = /*@__PURE__*/ require('./external/picomatch')\n }\n return _picomatch as typeof import('picomatch')\n}\n\nlet _fastGlob: typeof import('fast-glob') | undefined\n/**\n * Lazily load the fast-glob module.\n * @private\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getFastGlob() {\n if (_fastGlob === undefined) {\n const globExport = /*@__PURE__*/ require('./external/fast-glob')\n _fastGlob = globExport.default || globExport\n }\n return _fastGlob as typeof import('fast-glob')\n}\n\n/**\n * Create a stream of license file paths matching glob patterns.\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function globStreamLicenses(\n dirname: string,\n options?: GlobOptions,\n): NodeJS.ReadableStream {\n const {\n ignore: ignoreOpt,\n ignoreOriginals,\n recursive,\n ...globOptions\n } = { __proto__: null, ...options } as GlobOptions\n const ignore = [\n ...(Array.isArray(ignoreOpt) ? ignoreOpt : defaultIgnore),\n '**/*.{cjs,cts,js,json,mjs,mts,ts}',\n ]\n if (ignoreOriginals) {\n ignore.push(\n /*@__INLINE__*/ require('../constants/paths')\n .LICENSE_ORIGINAL_GLOB_RECURSIVE,\n )\n }\n const fastGlob = getFastGlob()\n return fastGlob.globStream(\n [\n recursive\n ? /*@__INLINE__*/ require('../constants/paths').LICENSE_GLOB_RECURSIVE\n : /*@__INLINE__*/ require('../constants/paths').LICENSE_GLOB,\n ],\n {\n __proto__: null,\n absolute: true,\n caseSensitiveMatch: false,\n cwd: dirname,\n ...globOptions,\n ...(ignore ? { ignore } : {}),\n } as import('fast-glob').Options,\n )\n}\n\nconst matcherCache = new Map()\n/**\n * Get a cached glob matcher function.\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function getGlobMatcher(\n glob: Pattern | Pattern[],\n options?: { dot?: boolean; nocase?: boolean; ignore?: string[] },\n): (path: string) => boolean {\n const patterns = Array.isArray(glob) ? glob : [glob]\n const key = JSON.stringify({ patterns, options })\n let matcher = matcherCache.get(key)\n if (matcher) {\n return matcher\n }\n\n // Separate positive and negative patterns.\n const positivePatterns = patterns.filter(p => !p.startsWith('!'))\n const negativePatterns = patterns\n .filter(p => p.startsWith('!'))\n .map(p => p.slice(1))\n\n const picomatch = getPicomatch()\n\n // Use ignore option for negation patterns.\n const matchOptions = {\n dot: true,\n nocase: true,\n ...options,\n ...(negativePatterns.length > 0 ? { ignore: negativePatterns } : {}),\n }\n\n matcher = picomatch(\n positivePatterns.length > 0 ? positivePatterns : patterns,\n matchOptions,\n )\n\n matcherCache.set(key, matcher)\n return matcher\n}\n"],
5
- "mappings": ";4ZAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,mBAAAE,EAAA,mBAAAC,EAAA,uBAAAC,IAAA,eAAAC,EAAAL,GAMA,IAAAM,EAA6C,qBAqCtC,MAAMJ,KAAgB,EAAAK,cAAa,CAMxC,UACA,YAEA,kBAMA,eACA,gBACA,SACA,mBACA,gBACA,UACA,kBACA,YACA,YACA,0BACA,uBACA,SACA,mBACA,YAEA,UACA,kBACA,UACA,UACA,aACA,mBACA,eAEA,qBACF,CAAC,EAED,IAAIC,EAMJ,SAASC,GAAe,CACtB,OAAID,IAAe,SAEjBA,EAA2B,QAAQ,sBAAsB,GAEpDA,CACT,CAEA,IAAIE,EAMJ,SAASC,GAAc,CACrB,GAAID,IAAc,OAAW,CAC3B,MAAME,EAA2B,QAAQ,sBAAsB,EAC/DF,EAAYE,EAAW,SAAWA,CACpC,CACA,OAAOF,CACT,CAMO,SAASN,EACdS,EACAC,EACuB,CACvB,KAAM,CACJ,OAAQC,EACR,gBAAAC,EACA,UAAAC,EACA,GAAGC,CACL,EAAI,CAAE,UAAW,KAAM,GAAGJ,CAAQ,EAC5BK,EAAS,CACb,GAAI,MAAM,QAAQJ,CAAS,EAAIA,EAAYb,EAC3C,mCACF,EACA,OAAIc,GACFG,EAAO,KACW,QAAQ,oBAAoB,EACzC,+BACL,EAEeR,EAAY,EACb,WACd,CACEM,EACoB,QAAQ,oBAAoB,EAAE,uBAC9B,QAAQ,oBAAoB,EAAE,YACpD,EACA,CACE,UAAW,KACX,SAAU,GACV,mBAAoB,GACpB,IAAKJ,EACL,GAAGK,EACH,GAAIC,EAAS,CAAE,OAAAA,CAAO,EAAI,CAAC,CAC7B,CACF,CACF,CAEA,MAAMC,EAAe,IAAI,IAKlB,SAASjB,EACdkB,EACAP,EAC2B,CAC3B,MAAMQ,EAAW,MAAM,QAAQD,CAAI,EAAIA,EAAO,CAACA,CAAI,EAC7CE,EAAM,KAAK,UAAU,CAAE,SAAAD,EAAU,QAAAR,CAAQ,CAAC,EAChD,IAAIU,EAAUJ,EAAa,IAAIG,CAAG,EAClC,GAAIC,EACF,OAAOA,EAIT,MAAMC,EAAmBH,EAAS,OAAOI,GAAK,CAACA,EAAE,WAAW,GAAG,CAAC,EAC1DC,EAAmBL,EACtB,OAAOI,GAAKA,EAAE,WAAW,GAAG,CAAC,EAC7B,IAAIA,GAAKA,EAAE,MAAM,CAAC,CAAC,EAEhBE,EAAYnB,EAAa,EAGzBoB,EAAe,CACnB,IAAK,GACL,OAAQ,GACR,GAAGf,EACH,GAAIa,EAAiB,OAAS,EAAI,CAAE,OAAQA,CAAiB,EAAI,CAAC,CACpE,EAEA,OAAAH,EAAUI,EACRH,EAAiB,OAAS,EAAIA,EAAmBH,EACjDO,CACF,EAEAT,EAAa,IAAIG,EAAKC,CAAO,EACtBA,CACT",
4
+ "sourcesContent": ["/**\n * @fileoverview Glob pattern matching utilities with default ignore patterns.\n * Provides file filtering and glob matcher functions for npm-like behavior.\n */\n\n// IMPORTANT: Do not use destructuring here - use direct assignment instead.\nimport { objectFreeze as ObjectFreeze } from './objects'\n\n// Type definitions\ntype Pattern = string\n\ninterface FastGlobOptions {\n absolute?: boolean\n baseNameMatch?: boolean\n braceExpansion?: boolean\n caseSensitiveMatch?: boolean\n concurrency?: number\n cwd?: string\n deep?: number\n dot?: boolean\n extglob?: boolean\n followSymbolicLinks?: boolean\n fs?: unknown\n globstar?: boolean\n ignore?: string[]\n ignoreFiles?: string[]\n markDirectories?: boolean\n objectMode?: boolean\n onlyDirectories?: boolean\n onlyFiles?: boolean\n stats?: boolean\n suppressErrors?: boolean\n throwErrorOnBrokenSymbolicLink?: boolean\n unique?: boolean\n}\n\nexport interface GlobOptions extends FastGlobOptions {\n ignoreOriginals?: boolean\n recursive?: boolean\n}\n\nexport type { Pattern, FastGlobOptions }\n\nexport const defaultIgnore = ObjectFreeze([\n // Most of these ignored files can be included specifically if included in the\n // files globs. Exceptions to this are:\n // https://docs.npmjs.com/cli/v10/configuring-npm/package-json#files\n // These can NOT be included.\n // https://github.com/npm/npm-packlist/blob/v10.0.0/lib/index.js#L280\n '**/.git',\n '**/.npmrc',\n // '**/bun.lockb?',\n '**/node_modules',\n // '**/package-lock.json',\n // '**/pnpm-lock.ya?ml',\n // '**/yarn.lock',\n // Include npm-packlist defaults:\n // https://github.com/npm/npm-packlist/blob/v10.0.0/lib/index.js#L15-L38\n '**/.DS_Store',\n '**/.gitignore',\n '**/.hg',\n '**/.lock-wscript',\n '**/.npmignore',\n '**/.svn',\n '**/.wafpickle-*',\n '**/.*.swp',\n '**/._*/**',\n '**/archived-packages/**',\n '**/build/config.gypi',\n '**/CVS',\n '**/npm-debug.log',\n '**/*.orig',\n // Inline generic socket-registry .gitignore entries.\n '**/.env',\n '**/.eslintcache',\n '**/.nvm',\n '**/.tap',\n '**/.vscode',\n '**/*.tsbuildinfo',\n '**/Thumbs.db',\n // Inline additional ignores.\n '**/bower_components',\n])\n\nlet _picomatch: typeof import('picomatch') | undefined\n/**\n * Lazily load the picomatch module.\n * @private\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getPicomatch() {\n if (_picomatch === undefined) {\n // The 'picomatch' package is browser safe.\n _picomatch = /*@__PURE__*/ require('./external/picomatch')\n }\n return _picomatch as typeof import('picomatch')\n}\n\nlet _fastGlob: typeof import('fast-glob') | undefined\n/**\n * Lazily load the fast-glob module.\n * @private\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getFastGlob() {\n if (_fastGlob === undefined) {\n const globExport = /*@__PURE__*/ require('./external/fast-glob')\n _fastGlob = globExport.default || globExport\n }\n return _fastGlob as typeof import('fast-glob')\n}\n\n/**\n * Create a stream of license file paths matching glob patterns.\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function globStreamLicenses(\n dirname: string,\n options?: GlobOptions,\n): NodeJS.ReadableStream {\n const {\n ignore: ignoreOpt,\n ignoreOriginals,\n recursive,\n ...globOptions\n } = { __proto__: null, ...options } as GlobOptions\n const ignore = [\n ...(Array.isArray(ignoreOpt) ? ignoreOpt : defaultIgnore),\n '**/*.{cjs,cts,js,json,mjs,mts,ts}',\n ]\n if (ignoreOriginals) {\n ignore.push(\n /*@__INLINE__*/ require('#constants/paths')\n .LICENSE_ORIGINAL_GLOB_RECURSIVE,\n )\n }\n const fastGlob = getFastGlob()\n return fastGlob.globStream(\n [\n recursive\n ? /*@__INLINE__*/ require('#constants/paths').LICENSE_GLOB_RECURSIVE\n : /*@__INLINE__*/ require('#constants/paths').LICENSE_GLOB,\n ],\n {\n __proto__: null,\n absolute: true,\n caseSensitiveMatch: false,\n cwd: dirname,\n ...globOptions,\n ...(ignore ? { ignore } : {}),\n } as import('fast-glob').Options,\n )\n}\n\nconst matcherCache = new Map()\n/**\n * Get a cached glob matcher function.\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function getGlobMatcher(\n glob: Pattern | Pattern[],\n options?: { dot?: boolean; nocase?: boolean; ignore?: string[] },\n): (path: string) => boolean {\n const patterns = Array.isArray(glob) ? glob : [glob]\n const key = JSON.stringify({ patterns, options })\n let matcher = matcherCache.get(key)\n if (matcher) {\n return matcher\n }\n\n // Separate positive and negative patterns.\n const positivePatterns = patterns.filter(p => !p.startsWith('!'))\n const negativePatterns = patterns\n .filter(p => p.startsWith('!'))\n .map(p => p.slice(1))\n\n const picomatch = getPicomatch()\n\n // Use ignore option for negation patterns.\n const matchOptions = {\n dot: true,\n nocase: true,\n ...options,\n ...(negativePatterns.length > 0 ? { ignore: negativePatterns } : {}),\n }\n\n matcher = picomatch(\n positivePatterns.length > 0 ? positivePatterns : patterns,\n matchOptions,\n )\n\n matcherCache.set(key, matcher)\n return matcher\n}\n"],
5
+ "mappings": ";4ZAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,mBAAAE,EAAA,mBAAAC,EAAA,uBAAAC,IAAA,eAAAC,EAAAL,GAMA,IAAAM,EAA6C,qBAqCtC,MAAMJ,KAAgB,EAAAK,cAAa,CAMxC,UACA,YAEA,kBAMA,eACA,gBACA,SACA,mBACA,gBACA,UACA,kBACA,YACA,YACA,0BACA,uBACA,SACA,mBACA,YAEA,UACA,kBACA,UACA,UACA,aACA,mBACA,eAEA,qBACF,CAAC,EAED,IAAIC,EAMJ,SAASC,GAAe,CACtB,OAAID,IAAe,SAEjBA,EAA2B,QAAQ,sBAAsB,GAEpDA,CACT,CAEA,IAAIE,EAMJ,SAASC,GAAc,CACrB,GAAID,IAAc,OAAW,CAC3B,MAAME,EAA2B,QAAQ,sBAAsB,EAC/DF,EAAYE,EAAW,SAAWA,CACpC,CACA,OAAOF,CACT,CAMO,SAASN,EACdS,EACAC,EACuB,CACvB,KAAM,CACJ,OAAQC,EACR,gBAAAC,EACA,UAAAC,EACA,GAAGC,CACL,EAAI,CAAE,UAAW,KAAM,GAAGJ,CAAQ,EAC5BK,EAAS,CACb,GAAI,MAAM,QAAQJ,CAAS,EAAIA,EAAYb,EAC3C,mCACF,EACA,OAAIc,GACFG,EAAO,KACW,QAAQ,kBAAkB,EACvC,+BACL,EAEeR,EAAY,EACb,WACd,CACEM,EACoB,QAAQ,kBAAkB,EAAE,uBAC5B,QAAQ,kBAAkB,EAAE,YAClD,EACA,CACE,UAAW,KACX,SAAU,GACV,mBAAoB,GACpB,IAAKJ,EACL,GAAGK,EACH,GAAIC,EAAS,CAAE,OAAAA,CAAO,EAAI,CAAC,CAC7B,CACF,CACF,CAEA,MAAMC,EAAe,IAAI,IAKlB,SAASjB,EACdkB,EACAP,EAC2B,CAC3B,MAAMQ,EAAW,MAAM,QAAQD,CAAI,EAAIA,EAAO,CAACA,CAAI,EAC7CE,EAAM,KAAK,UAAU,CAAE,SAAAD,EAAU,QAAAR,CAAQ,CAAC,EAChD,IAAIU,EAAUJ,EAAa,IAAIG,CAAG,EAClC,GAAIC,EACF,OAAOA,EAIT,MAAMC,EAAmBH,EAAS,OAAOI,GAAK,CAACA,EAAE,WAAW,GAAG,CAAC,EAC1DC,EAAmBL,EACtB,OAAOI,GAAKA,EAAE,WAAW,GAAG,CAAC,EAC7B,IAAIA,GAAKA,EAAE,MAAM,CAAC,CAAC,EAEhBE,EAAYnB,EAAa,EAGzBoB,EAAe,CACnB,IAAK,GACL,OAAQ,GACR,GAAGf,EACH,GAAIa,EAAiB,OAAS,EAAI,CAAE,OAAQA,CAAiB,EAAI,CAAC,CACpE,EAEA,OAAAH,EAAUI,EACRH,EAAiB,OAAS,EAAIA,EAAmBH,EACjDO,CACF,EAEAT,EAAa,IAAIG,EAAKC,CAAO,EACtBA,CACT",
6
6
  "names": ["globs_exports", "__export", "defaultIgnore", "getGlobMatcher", "globStreamLicenses", "__toCommonJS", "import_objects", "ObjectFreeze", "_picomatch", "getPicomatch", "_fastGlob", "getFastGlob", "globExport", "dirname", "options", "ignoreOpt", "ignoreOriginals", "recursive", "globOptions", "ignore", "matcherCache", "glob", "patterns", "key", "matcher", "positivePatterns", "p", "negativePatterns", "picomatch", "matchOptions"]
7
7
  }
package/dist/ipc.d.ts CHANGED
@@ -191,7 +191,7 @@ export declare function readIpcStub(stubPath: string): Promise<unknown>;
191
191
  * periodically or on application startup.
192
192
  *
193
193
  * ## Cleanup Rules:
194
- * - Files older than 5 minutes are removed
194
+ * - Files older than 5 minutes are removed (checked via both filesystem mtime and JSON timestamp)
195
195
  * - Only stub files (stub-*.json) are processed
196
196
  * - Errors are silently ignored (best-effort cleanup)
197
197
  *
package/dist/ipc.js CHANGED
@@ -1,3 +1,3 @@
1
1
  /* Socket Lib - Built with esbuild */
2
- var M=Object.create;var d=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var T=Object.getPrototypeOf,j=Object.prototype.hasOwnProperty;var P=(t,n)=>{for(var e in n)d(t,e,{get:n[e],enumerable:!0})},I=(t,n,e,o)=>{if(n&&typeof n=="object"||typeof n=="function")for(let s of S(n))!j.call(t,s)&&s!==e&&d(t,s,{get:()=>n[s],enumerable:!(o=v(n,s))||o.enumerable});return t};var f=(t,n,e)=>(e=t!=null?M(T(t)):{},I(n||!t||!t.__esModule?d(e,"default",{value:t,enumerable:!0}):e,t)),D=t=>I(d({},"__esModule",{value:!0}),t);var W={};P(W,{IpcHandshakeSchema:()=>B,cleanupIpcStubs:()=>O,createIpcChannelId:()=>N,createIpcMessage:()=>A,getIpcStubPath:()=>y,hasIpcChannel:()=>H,onIpc:()=>k,parseIpcMessage:()=>x,readIpcStub:()=>J,sendIpc:()=>C,waitForIpc:()=>F,writeIpcStub:()=>E});module.exports=D(W);var l=f(require("node:crypto")),r=require("node:fs"),g=f(require("node:os")),p=f(require("node:path")),i=require("./zod");const w=i.z.object({id:i.z.string().min(1),timestamp:i.z.number().positive(),type:i.z.string().min(1),data:i.z.unknown()}),B=w.extend({type:i.z.literal("handshake"),data:i.z.object({version:i.z.string(),pid:i.z.number().int().positive(),apiToken:i.z.string().optional(),appName:i.z.string()})}),b=i.z.object({pid:i.z.number().int().positive(),timestamp:i.z.number().positive(),data:i.z.unknown()});function N(t="socket"){return`${t}-${process.pid}-${l.default.randomBytes(8).toString("hex")}`}function y(t){const n=g.default.tmpdir(),e=p.default.join(n,".socket-ipc",t);return p.default.join(e,`stub-${process.pid}.json`)}async function $(t){const n=p.default.dirname(t);await r.promises.mkdir(n,{recursive:!0})}async function E(t,n){const e=y(t);await $(e);const o={data:n,pid:process.pid,timestamp:Date.now()},s=b.parse(o);return await r.promises.writeFile(e,JSON.stringify(s,null,2),"utf8"),e}async function J(t){try{const n=await r.promises.readFile(t,"utf8"),e=JSON.parse(n),o=b.parse(e),s=Date.now()-o.timestamp,a=300*1e3;return s>a?(await r.promises.unlink(t).catch(()=>{}),null):o.data}catch{return null}}async function O(t){const n=g.default.tmpdir(),e=p.default.join(n,".socket-ipc",t);try{const o=await r.promises.readdir(e),s=Date.now(),a=300*1e3;await Promise.all(o.map(async c=>{if(c.startsWith("stub-")&&c.endsWith(".json")){const u=p.default.join(e,c);try{const h=await r.promises.stat(u);s-h.mtimeMs>a&&await r.promises.unlink(u)}catch{}}}))}catch{}}function C(t,n){if(t&&typeof t=="object"&&"send"in t&&typeof t.send=="function")try{const e=w.parse(n);return t.send(e)}catch{return!1}return!1}function k(t){const n=e=>{const o=x(e);o&&t(o)};return process.on("message",n),()=>{process.off("message",n)}}function F(t,n={}){const{timeout:e=3e4}=n;return new Promise((o,s)=>{let a=null,c=null;const u=()=>{a&&a(),s(new Error(`IPC timeout waiting for message type: ${t}`))};a=k(m=>{m.type===t&&(c&&clearTimeout(c),a&&a(),o(m.data))}),e>0&&(c=setTimeout(u,e))})}function A(t,n){return{id:l.default.randomBytes(16).toString("hex"),timestamp:Date.now(),type:t,data:n}}function H(t){return!!(t&&typeof t=="object"&&"send"in t&&typeof t.send=="function"&&"channel"in t&&t.channel!==void 0)}function x(t){try{return w.parse(t)}catch{return null}}0&&(module.exports={IpcHandshakeSchema,cleanupIpcStubs,createIpcChannelId,createIpcMessage,getIpcStubPath,hasIpcChannel,onIpc,parseIpcMessage,readIpcStub,sendIpc,waitForIpc,writeIpcStub});
2
+ var P=Object.create;var m=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var O=Object.getPrototypeOf,A=Object.prototype.hasOwnProperty;var J=(t,e)=>{for(var n in e)m(t,n,{get:e[n],enumerable:!0})},y=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of B(e))!A.call(t,s)&&s!==n&&m(t,s,{get:()=>e[s],enumerable:!(o=N(e,s))||o.enumerable});return t};var k=(t,e,n)=>(n=t!=null?P(O(t)):{},y(e||!t||!t.__esModule?m(n,"default",{value:t,enumerable:!0}):n,t)),$=t=>y(m({},"__esModule",{value:!0}),t);var L={};J(L,{IpcHandshakeSchema:()=>E,cleanupIpcStubs:()=>z,createIpcChannelId:()=>F,createIpcMessage:()=>G,getIpcStubPath:()=>x,hasIpcChannel:()=>K,onIpc:()=>S,parseIpcMessage:()=>v,readIpcStub:()=>W,sendIpc:()=>_,waitForIpc:()=>q,writeIpcStub:()=>H});module.exports=$(L);var l=k(require("node:crypto")),c=require("node:fs"),p=k(require("node:path")),g=require("./fs"),h=require("./paths"),i=require("./zod");const w=i.z.object({id:i.z.string().min(1),timestamp:i.z.number().positive(),type:i.z.string().min(1),data:i.z.unknown()}),E=w.extend({type:i.z.literal("handshake"),data:i.z.object({version:i.z.string(),pid:i.z.number().int().positive(),apiToken:i.z.string().optional(),appName:i.z.string()})}),I=i.z.object({pid:i.z.number().int().positive(),timestamp:i.z.number().positive(),data:i.z.unknown()});function F(t="socket"){return`${t}-${process.pid}-${l.default.randomBytes(8).toString("hex")}`}function x(t){const e=(0,h.getOsTmpDir)(),n=p.default.join(e,".socket-ipc",t);return p.default.join(n,`stub-${process.pid}.json`)}async function C(t){const e=p.default.dirname(t);await c.promises.mkdir(e,{recursive:!0})}async function H(t,e){const n=x(t);await C(n);const o={data:e,pid:process.pid,timestamp:Date.now()},s=I.parse(o);return await c.promises.writeFile(n,JSON.stringify(s,null,2),"utf8"),n}async function W(t){try{const e=await c.promises.readFile(t,"utf8"),n=JSON.parse(e),o=I.parse(n),s=Date.now()-o.timestamp,a=300*1e3;if(s>a){try{(0,g.safeDeleteSync)(t,{force:!0})}catch{}return null}return o.data}catch{return null}}async function z(t){const e=(0,h.getOsTmpDir)(),n=p.default.join(e,".socket-ipc",t);try{const o=await c.promises.readdir(n),s=Date.now(),a=300*1e3;await Promise.all(o.map(async r=>{if(r.startsWith("stub-")&&r.endsWith(".json")){const u=p.default.join(n,r);try{const b=await c.promises.stat(u);let f=s-b.mtimeMs>a;try{const M=await c.promises.readFile(u,"utf8"),T=JSON.parse(M),D=I.parse(T),j=s-D.timestamp;f=f||j>a}catch{}f&&(0,g.safeDeleteSync)(u,{force:!0})}catch{}}}))}catch{}}function _(t,e){if(t&&typeof t=="object"&&"send"in t&&typeof t.send=="function")try{const n=w.parse(e);return t.send(n)}catch{return!1}return!1}function S(t){const e=n=>{const o=v(n);o&&t(o)};return process.on("message",e),()=>{process.off("message",e)}}function q(t,e={}){const{timeout:n=3e4}=e;return new Promise((o,s)=>{let a=null,r=null;const u=()=>{a&&a(),s(new Error(`IPC timeout waiting for message type: ${t}`))};a=S(d=>{d.type===t&&(r&&clearTimeout(r),a&&a(),o(d.data))}),n>0&&(r=setTimeout(u,n))})}function G(t,e){return{id:l.default.randomBytes(16).toString("hex"),timestamp:Date.now(),type:t,data:e}}function K(t){return!!(t&&typeof t=="object"&&"send"in t&&typeof t.send=="function"&&"channel"in t&&t.channel!==void 0)}function v(t){try{return w.parse(t)}catch{return null}}0&&(module.exports={IpcHandshakeSchema,cleanupIpcStubs,createIpcChannelId,createIpcMessage,getIpcStubPath,hasIpcChannel,onIpc,parseIpcMessage,readIpcStub,sendIpc,waitForIpc,writeIpcStub});
3
3
  //# sourceMappingURL=ipc.js.map