@warlock.js/core 5.31.0 → 5.32.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 (1018) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/esm/application/app.d.mts +3 -3
  3. package/esm/application/app.d.mts.map +1 -1
  4. package/esm/application/application-config-types.d.mts +1 -2
  5. package/esm/application/application-config-types.d.mts.map +1 -1
  6. package/esm/application/application.d.mts +5 -7
  7. package/esm/application/application.d.mts.map +1 -1
  8. package/esm/application/application.mjs +3 -1
  9. package/esm/application/application.mjs.map +1 -1
  10. package/esm/application/boot-signal.d.mts +14 -12
  11. package/esm/application/boot-signal.d.mts.map +1 -1
  12. package/esm/application/index.d.mts +2 -1
  13. package/esm/application/index.mjs +1 -1
  14. package/esm/application/public-url.d.mts +1 -2
  15. package/esm/application/public-url.d.mts.map +1 -1
  16. package/esm/application/roles.d.mts +10 -11
  17. package/esm/application/roles.d.mts.map +1 -1
  18. package/esm/benchmark/benchmark-snapshots.d.mts +1 -3
  19. package/esm/benchmark/benchmark-snapshots.d.mts.map +1 -1
  20. package/esm/benchmark/benchmark.d.mts +1 -3
  21. package/esm/benchmark/benchmark.d.mts.map +1 -1
  22. package/esm/benchmark/channels/console.channel.d.mts +1 -3
  23. package/esm/benchmark/channels/console.channel.d.mts.map +1 -1
  24. package/esm/benchmark/channels/noop.channel.d.mts +1 -3
  25. package/esm/benchmark/channels/noop.channel.d.mts.map +1 -1
  26. package/esm/benchmark/index.mjs +1 -1
  27. package/esm/benchmark/profiler.d.mts +1 -3
  28. package/esm/benchmark/profiler.d.mts.map +1 -1
  29. package/esm/benchmark/profiler.mjs +2 -1
  30. package/esm/benchmark/profiler.mjs.map +1 -1
  31. package/esm/benchmark/types.d.mts +22 -17
  32. package/esm/benchmark/types.d.mts.map +1 -1
  33. package/esm/bootstrap/setup.d.mts +1 -2
  34. package/esm/bootstrap/setup.d.mts.map +1 -1
  35. package/esm/bootstrap.d.mts +1 -2
  36. package/esm/bootstrap.d.mts.map +1 -1
  37. package/esm/cache/database-cache-driver.d.mts +3 -5
  38. package/esm/cache/database-cache-driver.d.mts.map +1 -1
  39. package/esm/cache/database-cache-driver.mjs +1 -1
  40. package/esm/cache/index.d.mts +2 -1
  41. package/esm/cache/index.mjs +1 -1
  42. package/esm/cli/cli-commands.manager.mjs +6 -3
  43. package/esm/cli/cli-commands.manager.mjs.map +1 -1
  44. package/esm/cli/commands/agents-md/agents-md-command.action.mjs +3 -2
  45. package/esm/cli/commands/agents-md/agents-md-command.action.mjs.map +1 -1
  46. package/esm/cli/commands/board/board-command.action.mjs +1 -1
  47. package/esm/cli/commands/check/check-command.action.mjs +1 -1
  48. package/esm/cli/commands/check/child-typecheck.mjs +1 -1
  49. package/esm/cli/commands/check/child-typecheck.mjs.map +1 -1
  50. package/esm/cli/commands/check/format-problems.mjs +1 -1
  51. package/esm/cli/commands/dev-server.command.mjs +3 -2
  52. package/esm/cli/commands/dev-server.command.mjs.map +1 -1
  53. package/esm/cli/commands/doctor/check.types.d.mts +29 -16
  54. package/esm/cli/commands/doctor/check.types.d.mts.map +1 -1
  55. package/esm/cli/commands/doctor/checks/locales-ts-deprecated.check.mjs +22 -27
  56. package/esm/cli/commands/doctor/checks/locales-ts-deprecated.check.mjs.map +1 -1
  57. package/esm/cli/commands/doctor/doctor-command.action.mjs +2 -1
  58. package/esm/cli/commands/doctor/doctor-command.action.mjs.map +1 -1
  59. package/esm/cli/commands/explain/explain-command.action.mjs +1 -1
  60. package/esm/cli/commands/generate/generators/controller.generator.mjs +5 -2
  61. package/esm/cli/commands/generate/generators/controller.generator.mjs.map +1 -1
  62. package/esm/cli/commands/generate/generators/endpoint.generator.mjs +5 -3
  63. package/esm/cli/commands/generate/generators/endpoint.generator.mjs.map +1 -1
  64. package/esm/cli/commands/generate/generators/model.generator.mjs +3 -2
  65. package/esm/cli/commands/generate/generators/model.generator.mjs.map +1 -1
  66. package/esm/cli/commands/generate/generators/repository.generator.mjs +3 -1
  67. package/esm/cli/commands/generate/generators/repository.generator.mjs.map +1 -1
  68. package/esm/cli/commands/generate/generators/resource.generator.mjs +3 -1
  69. package/esm/cli/commands/generate/generators/resource.generator.mjs.map +1 -1
  70. package/esm/cli/commands/generate/generators/service.generator.mjs +3 -1
  71. package/esm/cli/commands/generate/generators/service.generator.mjs.map +1 -1
  72. package/esm/cli/commands/generate/templates/endpoint-stubs.mjs +2 -2
  73. package/esm/cli/commands/generate/templates/endpoint-stubs.mjs.map +1 -1
  74. package/esm/cli/commands/generate/utils/endpoint-schema.mjs +1 -2
  75. package/esm/cli/commands/generate/utils/endpoint-schema.mjs.map +1 -1
  76. package/esm/cli/commands/generate/utils/name-parser.mjs +1 -1
  77. package/esm/cli/commands/generate/utils/path-resolver.mjs +1 -1
  78. package/esm/cli/commands/inspect/inspect-command.action.mjs +3 -2
  79. package/esm/cli/commands/inspect/inspect-command.action.mjs.map +1 -1
  80. package/esm/cli/commands/issue/collect-environment.mjs +187 -0
  81. package/esm/cli/commands/issue/collect-environment.mjs.map +1 -0
  82. package/esm/cli/commands/issue/issue-command.action.mjs +70 -0
  83. package/esm/cli/commands/issue/issue-command.action.mjs.map +1 -0
  84. package/esm/cli/commands/issue.command.mjs +31 -0
  85. package/esm/cli/commands/issue.command.mjs.map +1 -0
  86. package/esm/cli/commands/mcp/mcp-command.action.mjs +15 -14
  87. package/esm/cli/commands/mcp/mcp-command.action.mjs.map +1 -1
  88. package/esm/cli/commands/openapi-generator.action.mjs +1 -1
  89. package/esm/cli/commands/postman-generator.action.mjs +1 -1
  90. package/esm/cli/commands/routes/format-routes-table.mjs +1 -1
  91. package/esm/cli/commands/routes/route-row.mjs +1 -1
  92. package/esm/cli/commands/routes/routes-diff.action.mjs +2 -2
  93. package/esm/cli/commands/routes/routes-diff.action.mjs.map +1 -1
  94. package/esm/cli/commands/test.command.mjs +1 -1
  95. package/esm/cli/commands/trace/trace-command.action.mjs +1 -1
  96. package/esm/cli/commands-loader.mjs +1 -1
  97. package/esm/cli/framework-cli-commands.mjs +2 -0
  98. package/esm/cli/framework-cli-commands.mjs.map +1 -1
  99. package/esm/cli/parse-cli-args.mjs +2 -2
  100. package/esm/cli/parse-cli-args.mjs.map +1 -1
  101. package/esm/cli/start.d.mts +1 -1
  102. package/esm/cli/string-similarity.mjs +1 -1
  103. package/esm/commands/cli-command.d.mts +2 -4
  104. package/esm/commands/cli-command.d.mts.map +1 -1
  105. package/esm/commands/index.d.mts +2 -1
  106. package/esm/commands/index.mjs +1 -1
  107. package/esm/commands/types.d.mts +8 -8
  108. package/esm/commands/types.d.mts.map +1 -1
  109. package/esm/config/config-getter.d.mts +2 -3
  110. package/esm/config/config-getter.d.mts.map +1 -1
  111. package/esm/config/config-getter.mjs +5 -5
  112. package/esm/config/config-getter.mjs.map +1 -1
  113. package/esm/config/config-handlers.d.mts +1 -3
  114. package/esm/config/config-handlers.d.mts.map +1 -1
  115. package/esm/config/config-loader.d.mts +1 -2
  116. package/esm/config/config-loader.d.mts.map +1 -1
  117. package/esm/config/config-loader.mjs +3 -3
  118. package/esm/config/config-loader.mjs.map +1 -1
  119. package/esm/config/config-manager.mjs +1 -1
  120. package/esm/config/config-schema.d.mts +19 -16
  121. package/esm/config/config-schema.d.mts.map +1 -1
  122. package/esm/config/config-setter.d.mts +2 -4
  123. package/esm/config/config-setter.d.mts.map +1 -1
  124. package/esm/config/config-setter.mjs +2 -2
  125. package/esm/config/config-setter.mjs.map +1 -1
  126. package/esm/config/config-special-handlers.d.mts +2 -4
  127. package/esm/config/config-special-handlers.d.mts.map +1 -1
  128. package/esm/config/index.d.mts +2 -1
  129. package/esm/config/index.mjs +1 -1
  130. package/esm/config/types.d.mts +4 -5
  131. package/esm/config/types.d.mts.map +1 -1
  132. package/esm/connectors/access-connector.d.mts +1 -3
  133. package/esm/connectors/access-connector.d.mts.map +1 -1
  134. package/esm/connectors/access-connector.mjs +2 -2
  135. package/esm/connectors/access-connector.mjs.map +1 -1
  136. package/esm/connectors/ai-connector.d.mts +1 -3
  137. package/esm/connectors/ai-connector.d.mts.map +1 -1
  138. package/esm/connectors/ai-connector.mjs +2 -2
  139. package/esm/connectors/ai-connector.mjs.map +1 -1
  140. package/esm/connectors/assert-no-reserved-connector-names.d.mts +1 -3
  141. package/esm/connectors/assert-no-reserved-connector-names.d.mts.map +1 -1
  142. package/esm/connectors/assert-unique-connector-names.d.mts +1 -3
  143. package/esm/connectors/assert-unique-connector-names.d.mts.map +1 -1
  144. package/esm/connectors/assert-unique-connector-names.mjs +2 -1
  145. package/esm/connectors/assert-unique-connector-names.mjs.map +1 -1
  146. package/esm/connectors/base-connector.d.mts +1 -3
  147. package/esm/connectors/base-connector.d.mts.map +1 -1
  148. package/esm/connectors/cache-connector.d.mts +1 -3
  149. package/esm/connectors/cache-connector.d.mts.map +1 -1
  150. package/esm/connectors/cache-connector.mjs +3 -3
  151. package/esm/connectors/cache-connector.mjs.map +1 -1
  152. package/esm/connectors/connectors-manager.d.mts +2 -4
  153. package/esm/connectors/connectors-manager.d.mts.map +1 -1
  154. package/esm/connectors/connectors-manager.mjs +2 -2
  155. package/esm/connectors/connectors-manager.mjs.map +1 -1
  156. package/esm/connectors/database-connector.d.mts +1 -3
  157. package/esm/connectors/database-connector.d.mts.map +1 -1
  158. package/esm/connectors/database-connector.mjs +2 -2
  159. package/esm/connectors/database-connector.mjs.map +1 -1
  160. package/esm/connectors/describe-server-address.mjs +4 -4
  161. package/esm/connectors/describe-server-address.mjs.map +1 -1
  162. package/esm/connectors/herald-connector.d.mts +1 -3
  163. package/esm/connectors/herald-connector.d.mts.map +1 -1
  164. package/esm/connectors/herald-connector.mjs +2 -2
  165. package/esm/connectors/herald-connector.mjs.map +1 -1
  166. package/esm/connectors/http-connector.d.mts +1 -3
  167. package/esm/connectors/http-connector.d.mts.map +1 -1
  168. package/esm/connectors/http-connector.mjs +8 -7
  169. package/esm/connectors/http-connector.mjs.map +1 -1
  170. package/esm/connectors/index.d.mts +2 -1
  171. package/esm/connectors/index.mjs +1 -1
  172. package/esm/connectors/logger-connector.d.mts +1 -3
  173. package/esm/connectors/logger-connector.d.mts.map +1 -1
  174. package/esm/connectors/logger-connector.mjs +2 -2
  175. package/esm/connectors/logger-connector.mjs.map +1 -1
  176. package/esm/connectors/mail-connector.d.mts +1 -3
  177. package/esm/connectors/mail-connector.d.mts.map +1 -1
  178. package/esm/connectors/mail-connector.mjs +2 -2
  179. package/esm/connectors/mail-connector.mjs.map +1 -1
  180. package/esm/connectors/notifications-connector.d.mts +1 -3
  181. package/esm/connectors/notifications-connector.d.mts.map +1 -1
  182. package/esm/connectors/notifications-connector.mjs +2 -2
  183. package/esm/connectors/notifications-connector.mjs.map +1 -1
  184. package/esm/connectors/register-configured-connectors.d.mts +2 -4
  185. package/esm/connectors/register-configured-connectors.d.mts.map +1 -1
  186. package/esm/connectors/socket-connector.d.mts +1 -3
  187. package/esm/connectors/socket-connector.d.mts.map +1 -1
  188. package/esm/connectors/socket-connector.mjs +12 -10
  189. package/esm/connectors/socket-connector.mjs.map +1 -1
  190. package/esm/connectors/storage.connector.d.mts +1 -3
  191. package/esm/connectors/storage.connector.d.mts.map +1 -1
  192. package/esm/connectors/storage.connector.mjs +2 -2
  193. package/esm/connectors/storage.connector.mjs.map +1 -1
  194. package/esm/connectors/types.d.mts +17 -14
  195. package/esm/connectors/types.d.mts.map +1 -1
  196. package/esm/container/container-instance-registry.mjs.map +1 -1
  197. package/esm/container/development-app-modules.d.mts +7 -5
  198. package/esm/container/development-app-modules.d.mts.map +1 -1
  199. package/esm/container/development-model-modules.d.mts +6 -5
  200. package/esm/container/development-model-modules.d.mts.map +1 -1
  201. package/esm/container/index.d.mts +4 -4
  202. package/esm/container/index.d.mts.map +1 -1
  203. package/esm/database/index.d.mts +3 -1
  204. package/esm/database/index.mjs +1 -1
  205. package/esm/database/migrate-action.mjs +1 -1
  206. package/esm/database/models/database-log/database-log.d.mts +2 -3
  207. package/esm/database/models/database-log/database-log.d.mts.map +1 -1
  208. package/esm/database/models/database-log/index.d.mts +2 -1
  209. package/esm/database/models/database-log/index.mjs +1 -1
  210. package/esm/database/seed-command-action.mjs +1 -1
  211. package/esm/database/seeds/seeder.d.mts +2 -4
  212. package/esm/database/seeds/seeder.d.mts.map +1 -1
  213. package/esm/database/seeds/seeder.errors.d.mts +2 -3
  214. package/esm/database/seeds/seeder.errors.d.mts.map +1 -1
  215. package/esm/database/seeds/seeders.manager.mjs +2 -1
  216. package/esm/database/seeds/seeders.manager.mjs.map +1 -1
  217. package/esm/database/seeds/types.d.mts +7 -8
  218. package/esm/database/seeds/types.d.mts.map +1 -1
  219. package/esm/database/utils.d.mts +4 -5
  220. package/esm/database/utils.d.mts.map +1 -1
  221. package/esm/dev-server/app-module-registry.mjs +1 -1
  222. package/esm/dev-server/create-worker.mjs +5 -3
  223. package/esm/dev-server/create-worker.mjs.map +1 -1
  224. package/esm/dev-server/dependency-graph.d.mts +1 -3
  225. package/esm/dev-server/dependency-graph.d.mts.map +1 -1
  226. package/esm/dev-server/dependency-graph.mjs +1 -1
  227. package/esm/dev-server/dependency-graph.mjs.map +1 -1
  228. package/esm/dev-server/extract-translation-keys.mjs +16 -17
  229. package/esm/dev-server/extract-translation-keys.mjs.map +1 -1
  230. package/esm/dev-server/file-manager.d.mts +3 -7
  231. package/esm/dev-server/file-manager.d.mts.map +1 -1
  232. package/esm/dev-server/file-operations.d.mts +1 -3
  233. package/esm/dev-server/file-operations.d.mts.map +1 -1
  234. package/esm/dev-server/files-watcher.mjs +12 -11
  235. package/esm/dev-server/files-watcher.mjs.map +1 -1
  236. package/esm/dev-server/health-checker/checkers/typescript-health-checker.mjs +36 -115
  237. package/esm/dev-server/health-checker/checkers/typescript-health-checker.mjs.map +1 -1
  238. package/esm/dev-server/health-checker/file-health-checker.contract.d.mts +5 -5
  239. package/esm/dev-server/health-checker/file-health-checker.contract.d.mts.map +1 -1
  240. package/esm/dev-server/health-checker/file-health-result.d.mts +2 -2
  241. package/esm/dev-server/health-checker/file-health-result.d.mts.map +1 -1
  242. package/esm/dev-server/health-checker/files-healthcare.manager.mjs +1 -0
  243. package/esm/dev-server/health-checker/files-healthcare.manager.mjs.map +1 -1
  244. package/esm/dev-server/health-checker/oxlint-runner.mjs +6 -5
  245. package/esm/dev-server/health-checker/oxlint-runner.mjs.map +1 -1
  246. package/esm/dev-server/health-checker/workers/eslint-health.worker.d.mts +1 -1
  247. package/esm/dev-server/health-checker/workers/oxlint-health.worker.d.mts +1 -1
  248. package/esm/dev-server/health-checker/workers/ts-health.worker.d.mts +1 -1
  249. package/esm/dev-server/health-checker/workers/ts-health.worker.mjs +40 -174
  250. package/esm/dev-server/health-checker/workers/ts-health.worker.mjs.map +1 -1
  251. package/esm/dev-server/loader/hook-thread.d.mts +4 -8
  252. package/esm/dev-server/loader/hook-thread.d.mts.map +1 -1
  253. package/esm/dev-server/loader/load-hook.d.mts +10 -6
  254. package/esm/dev-server/loader/load-hook.d.mts.map +1 -1
  255. package/esm/dev-server/loader/load-hook.mjs +4 -3
  256. package/esm/dev-server/loader/load-hook.mjs.map +1 -1
  257. package/esm/dev-server/loader/own-resolver.mjs +1 -1
  258. package/esm/dev-server/loader/register-loader.mjs +3 -2
  259. package/esm/dev-server/loader/register-loader.mjs.map +1 -1
  260. package/esm/dev-server/loader/resolve-hook.d.mts +2 -2
  261. package/esm/dev-server/loader/resolve-hook.d.mts.map +1 -1
  262. package/esm/dev-server/loader/resolve-hook.mjs +2 -1
  263. package/esm/dev-server/loader/resolve-hook.mjs.map +1 -1
  264. package/esm/dev-server/loader/transpile-cache.mjs +2 -1
  265. package/esm/dev-server/loader/transpile-cache.mjs.map +1 -1
  266. package/esm/dev-server/manifest-manager.d.mts +1 -3
  267. package/esm/dev-server/manifest-manager.d.mts.map +1 -1
  268. package/esm/dev-server/model-module-registry.mjs +3 -3
  269. package/esm/dev-server/model-module-registry.mjs.map +1 -1
  270. package/esm/dev-server/model-resource-typings.mjs +40 -47
  271. package/esm/dev-server/model-resource-typings.mjs.map +1 -1
  272. package/esm/dev-server/module-loader.mjs +2 -2
  273. package/esm/dev-server/module-loader.mjs.map +1 -1
  274. package/esm/dev-server/package-json-manager.mjs +1 -1
  275. package/esm/dev-server/parse-imports.mjs +6 -38
  276. package/esm/dev-server/parse-imports.mjs.map +1 -1
  277. package/esm/dev-server/read-config-ast.mjs +3 -33
  278. package/esm/dev-server/read-config-ast.mjs.map +1 -1
  279. package/esm/dev-server/ready-block.mjs +1 -1
  280. package/esm/dev-server/shortcuts.mjs +1 -1
  281. package/esm/dev-server/special-files-collector.d.mts +2 -4
  282. package/esm/dev-server/special-files-collector.d.mts.map +1 -1
  283. package/esm/dev-server/supervisor.mjs +1 -1
  284. package/esm/dev-server/tsconfig-manager.mjs +3 -3
  285. package/esm/dev-server/tsconfig-manager.mjs.map +1 -1
  286. package/esm/dev-server/type-generator.mjs +28 -35
  287. package/esm/dev-server/type-generator.mjs.map +1 -1
  288. package/esm/dev-server/types.d.mts +3 -4
  289. package/esm/dev-server/types.d.mts.map +1 -1
  290. package/esm/dev-server/update-check-cache.mjs +2 -2
  291. package/esm/dev-server/update-check-cache.mjs.map +1 -1
  292. package/esm/encryption/encrypt.d.mts +2 -3
  293. package/esm/encryption/encrypt.d.mts.map +1 -1
  294. package/esm/encryption/hash.d.mts +1 -2
  295. package/esm/encryption/hash.d.mts.map +1 -1
  296. package/esm/encryption/index.mjs +1 -1
  297. package/esm/encryption/password.d.mts +2 -3
  298. package/esm/encryption/password.d.mts.map +1 -1
  299. package/esm/encryption/types.d.mts +2 -3
  300. package/esm/encryption/types.d.mts.map +1 -1
  301. package/esm/errors/error-codes.d.mts +29 -22
  302. package/esm/errors/error-codes.d.mts.map +1 -1
  303. package/esm/errors/warlock-error.d.mts +1 -3
  304. package/esm/errors/warlock-error.d.mts.map +1 -1
  305. package/esm/generations/add-command.action.mjs +3 -2
  306. package/esm/generations/add-command.action.mjs.map +1 -1
  307. package/esm/generations/features/bull-board.feature.mjs +2 -1
  308. package/esm/generations/features/bull-board.feature.mjs.map +1 -1
  309. package/esm/generations/features/notifications.feature.mjs +2 -1
  310. package/esm/generations/features/notifications.feature.mjs.map +1 -1
  311. package/esm/generations/features/shared/merge-web-sitemap-config.mjs +16 -23
  312. package/esm/generations/features/shared/merge-web-sitemap-config.mjs.map +1 -1
  313. package/esm/generations/features/shared/patch-tsconfig-include.mjs +1 -1
  314. package/esm/generations/features/shared/relocate-conflicting-home-route.mjs +1 -1
  315. package/esm/generations/features/sitemap.feature.mjs +2 -1
  316. package/esm/generations/features/sitemap.feature.mjs.map +1 -1
  317. package/esm/generations/generation-fs.mjs +1 -1
  318. package/esm/generations/generation-run.mjs +1 -1
  319. package/esm/generations/stubs.mjs +1 -1
  320. package/esm/generations/stubs.mjs.map +1 -1
  321. package/esm/http/boot-port-preflight.d.mts +4 -5
  322. package/esm/http/boot-port-preflight.d.mts.map +1 -1
  323. package/esm/http/boot-port-preflight.mjs +2 -2
  324. package/esm/http/boot-port-preflight.mjs.map +1 -1
  325. package/esm/http/bounded-stream-queue.d.mts +4 -4
  326. package/esm/http/bounded-stream-queue.d.mts.map +1 -1
  327. package/esm/http/bounded-stream-queue.mjs +1 -1
  328. package/esm/http/bounded-stream-queue.mjs.map +1 -1
  329. package/esm/http/build-cors-options.mjs +2 -2
  330. package/esm/http/build-cors-options.mjs.map +1 -1
  331. package/esm/http/build-rate-limit-options.d.mts +2 -3
  332. package/esm/http/build-rate-limit-options.d.mts.map +1 -1
  333. package/esm/http/build-rate-limit-options.mjs +1 -1
  334. package/esm/http/build-rate-limit-options.mjs.map +1 -1
  335. package/esm/http/conditional-request.d.mts +14 -13
  336. package/esm/http/conditional-request.d.mts.map +1 -1
  337. package/esm/http/config.d.mts +2 -4
  338. package/esm/http/config.d.mts.map +1 -1
  339. package/esm/http/config.mjs +2 -2
  340. package/esm/http/config.mjs.map +1 -1
  341. package/esm/http/context/request-context.d.mts +6 -7
  342. package/esm/http/context/request-context.d.mts.map +1 -1
  343. package/esm/http/context/request-memo.d.mts +1 -2
  344. package/esm/http/context/request-memo.d.mts.map +1 -1
  345. package/esm/http/createHttpApplication.d.mts +2 -3
  346. package/esm/http/createHttpApplication.d.mts.map +1 -1
  347. package/esm/http/createHttpApplication.mjs +2 -2
  348. package/esm/http/createHttpApplication.mjs.map +1 -1
  349. package/esm/http/csp.d.mts +10 -12
  350. package/esm/http/csp.d.mts.map +1 -1
  351. package/esm/http/csp.mjs +2 -2
  352. package/esm/http/csp.mjs.map +1 -1
  353. package/esm/http/csrf-default-guard.d.mts +2 -4
  354. package/esm/http/csrf-default-guard.d.mts.map +1 -1
  355. package/esm/http/csrf-default-guard.mjs +1 -1
  356. package/esm/http/csrf-default-guard.mjs.map +1 -1
  357. package/esm/http/csrf-origin-policy.d.mts +7 -9
  358. package/esm/http/csrf-origin-policy.d.mts.map +1 -1
  359. package/esm/http/csrf-origin-policy.mjs +2 -2
  360. package/esm/http/csrf-origin-policy.mjs.map +1 -1
  361. package/esm/http/database/RequestLog.d.mts +2 -3
  362. package/esm/http/database/RequestLog.d.mts.map +1 -1
  363. package/esm/http/error-codes.d.mts +1 -2
  364. package/esm/http/error-codes.d.mts.map +1 -1
  365. package/esm/http/error-mapper.d.mts +2 -4
  366. package/esm/http/error-mapper.d.mts.map +1 -1
  367. package/esm/http/error-mapper.mjs +2 -2
  368. package/esm/http/error-mapper.mjs.map +1 -1
  369. package/esm/http/errors/errors.d.mts +28 -29
  370. package/esm/http/errors/errors.d.mts.map +1 -1
  371. package/esm/http/escape-header-value.d.mts +1 -2
  372. package/esm/http/escape-header-value.d.mts.map +1 -1
  373. package/esm/http/events.d.mts +2 -4
  374. package/esm/http/events.d.mts.map +1 -1
  375. package/esm/http/health.d.mts +4 -4
  376. package/esm/http/health.d.mts.map +1 -1
  377. package/esm/http/index.d.mts +4 -1
  378. package/esm/http/index.mjs +1 -1
  379. package/esm/http/middleware/cache-response-middleware.d.mts +2 -4
  380. package/esm/http/middleware/cache-response-middleware.d.mts.map +1 -1
  381. package/esm/http/middleware/concurrency-limit.middleware.d.mts +3 -3
  382. package/esm/http/middleware/concurrency-limit.middleware.d.mts.map +1 -1
  383. package/esm/http/middleware/idempotency.middleware.d.mts +3 -3
  384. package/esm/http/middleware/idempotency.middleware.d.mts.map +1 -1
  385. package/esm/http/middleware/idempotency.middleware.mjs +6 -6
  386. package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
  387. package/esm/http/middleware/index.d.mts +3 -1
  388. package/esm/http/middleware/index.mjs +1 -1
  389. package/esm/http/middleware/inject-request-context.d.mts +2 -4
  390. package/esm/http/middleware/inject-request-context.d.mts.map +1 -1
  391. package/esm/http/middleware/inject-request-context.mjs +3 -3
  392. package/esm/http/middleware/inject-request-context.mjs.map +1 -1
  393. package/esm/http/middleware/ip-filter.middleware.d.mts +3 -3
  394. package/esm/http/middleware/ip-filter.middleware.d.mts.map +1 -1
  395. package/esm/http/middleware/maintenance.middleware.d.mts +3 -3
  396. package/esm/http/middleware/maintenance.middleware.d.mts.map +1 -1
  397. package/esm/http/middleware/maintenance.middleware.mjs +4 -4
  398. package/esm/http/middleware/maintenance.middleware.mjs.map +1 -1
  399. package/esm/http/middleware/max-body-size.middleware.d.mts +2 -2
  400. package/esm/http/middleware/max-body-size.middleware.d.mts.map +1 -1
  401. package/esm/http/middleware/middleware-list.d.mts +1 -3
  402. package/esm/http/middleware/middleware-list.d.mts.map +1 -1
  403. package/esm/http/middleware/rate-limit.middleware.d.mts +3 -3
  404. package/esm/http/middleware/rate-limit.middleware.d.mts.map +1 -1
  405. package/esm/http/middleware/rate-limit.middleware.mjs +2 -2
  406. package/esm/http/middleware/rate-limit.middleware.mjs.map +1 -1
  407. package/esm/http/middleware/utils/cidr-match.d.mts +2 -3
  408. package/esm/http/middleware/utils/cidr-match.d.mts.map +1 -1
  409. package/esm/http/middleware/utils/idempotency-key.d.mts +3 -5
  410. package/esm/http/middleware/utils/idempotency-key.d.mts.map +1 -1
  411. package/esm/http/middleware/utils/index.d.mts +2 -1
  412. package/esm/http/middleware/utils/parse-size.d.mts +1 -2
  413. package/esm/http/middleware/utils/parse-size.d.mts.map +1 -1
  414. package/esm/http/middleware/utils/parse-size.mjs +2 -2
  415. package/esm/http/middleware/utils/parse-size.mjs.map +1 -1
  416. package/esm/http/plugins.d.mts +2 -4
  417. package/esm/http/plugins.d.mts.map +1 -1
  418. package/esm/http/plugins.mjs +10 -10
  419. package/esm/http/plugins.mjs.map +1 -1
  420. package/esm/http/port-preflight.d.mts +3 -4
  421. package/esm/http/port-preflight.d.mts.map +1 -1
  422. package/esm/http/rate-limit-cache-store.mjs +4 -3
  423. package/esm/http/rate-limit-cache-store.mjs.map +1 -1
  424. package/esm/http/ready-report.d.mts +15 -10
  425. package/esm/http/ready-report.d.mts.map +1 -1
  426. package/esm/http/request-controller.d.mts +1 -3
  427. package/esm/http/request-controller.d.mts.map +1 -1
  428. package/esm/http/request-log-snapshot.d.mts +20 -16
  429. package/esm/http/request-log-snapshot.d.mts.map +1 -1
  430. package/esm/http/request-log-snapshot.mjs +3 -3
  431. package/esm/http/request-log-snapshot.mjs.map +1 -1
  432. package/esm/http/request.d.mts +8 -7
  433. package/esm/http/request.d.mts.map +1 -1
  434. package/esm/http/request.mjs +8 -7
  435. package/esm/http/request.mjs.map +1 -1
  436. package/esm/http/response.d.mts +12 -11
  437. package/esm/http/response.d.mts.map +1 -1
  438. package/esm/http/response.mjs +7 -7
  439. package/esm/http/response.mjs.map +1 -1
  440. package/esm/http/safe-redirect.d.mts +3 -4
  441. package/esm/http/safe-redirect.d.mts.map +1 -1
  442. package/esm/http/serialized.d.mts +12 -13
  443. package/esm/http/serialized.d.mts.map +1 -1
  444. package/esm/http/server-rebuilt.d.mts +3 -5
  445. package/esm/http/server-rebuilt.d.mts.map +1 -1
  446. package/esm/http/server.d.mts +9 -9
  447. package/esm/http/server.d.mts.map +1 -1
  448. package/esm/http/server.mjs +4 -4
  449. package/esm/http/server.mjs.map +1 -1
  450. package/esm/http/stream-react-response.d.mts +7 -7
  451. package/esm/http/stream-react-response.d.mts.map +1 -1
  452. package/esm/http/tracing/index.mjs +1 -1
  453. package/esm/http/tracing/trace-id.d.mts +2 -3
  454. package/esm/http/tracing/trace-id.d.mts.map +1 -1
  455. package/esm/http/tracing/tracing-dispatcher.d.mts +10 -11
  456. package/esm/http/tracing/tracing-dispatcher.d.mts.map +1 -1
  457. package/esm/http/tracing/tracing-dispatcher.mjs +2 -2
  458. package/esm/http/tracing/tracing-dispatcher.mjs.map +1 -1
  459. package/esm/http/tracing/tracing.type.d.mts +11 -9
  460. package/esm/http/tracing/tracing.type.d.mts.map +1 -1
  461. package/esm/http/types.d.mts +49 -43
  462. package/esm/http/types.d.mts.map +1 -1
  463. package/esm/http/uploaded-file.d.mts +6 -5
  464. package/esm/http/uploaded-file.d.mts.map +1 -1
  465. package/esm/http/uploads/generate-image-variants.d.mts +6 -6
  466. package/esm/http/uploads/generate-image-variants.d.mts.map +1 -1
  467. package/esm/http/uploads/generate-image-variants.mjs +1 -1
  468. package/esm/http/uploads/generate-image-variants.mjs.map +1 -1
  469. package/esm/http/uploads/image-variant-cache-entries.mjs +1 -1
  470. package/esm/http/uploads/image-variant-cache.mjs +8 -8
  471. package/esm/http/uploads/image-variant-cache.mjs.map +1 -1
  472. package/esm/http/uploads/image-variant-types.d.mts +7 -9
  473. package/esm/http/uploads/image-variant-types.d.mts.map +1 -1
  474. package/esm/http/uploads/image-variants-config-error.d.mts +1 -2
  475. package/esm/http/uploads/image-variants-config-error.d.mts.map +1 -1
  476. package/esm/http/uploads/index.d.mts +2 -1
  477. package/esm/http/uploads/index.mjs +1 -1
  478. package/esm/http/uploads/parse-uploaded-file-query.mjs +1 -1
  479. package/esm/http/uploads/parse-uploaded-file-query.mjs.map +1 -1
  480. package/esm/http/uploads/purge-image-variants.d.mts +2 -4
  481. package/esm/http/uploads/purge-image-variants.d.mts.map +1 -1
  482. package/esm/http/uploads/resolve-image-variant.d.mts +3 -5
  483. package/esm/http/uploads/resolve-image-variant.d.mts.map +1 -1
  484. package/esm/http/uploads/resolve-image-variants-config.mjs +4 -4
  485. package/esm/http/uploads/resolve-image-variants-config.mjs.map +1 -1
  486. package/esm/http/uploads/resolve-original-content-type.mjs +1 -1
  487. package/esm/http/uploads/resolve-original-content-type.mjs.map +1 -1
  488. package/esm/http/uploads/trim-image-variant-cache.mjs +3 -3
  489. package/esm/http/uploads/trim-image-variant-cache.mjs.map +1 -1
  490. package/esm/http/uploads/uploaded-file.controller.d.mts +6 -5
  491. package/esm/http/uploads/uploaded-file.controller.d.mts.map +1 -1
  492. package/esm/http/uploads/uploaded-file.controller.mjs +2 -1
  493. package/esm/http/uploads/uploaded-file.controller.mjs.map +1 -1
  494. package/esm/http/uploads/variant-cache-key.mjs +1 -1
  495. package/esm/http/uploads-config.d.mts +2 -4
  496. package/esm/http/uploads-config.d.mts.map +1 -1
  497. package/esm/http/uploads-types.d.mts +19 -17
  498. package/esm/http/uploads-types.d.mts.map +1 -1
  499. package/esm/http/xmlable.d.mts +1 -2
  500. package/esm/http/xmlable.d.mts.map +1 -1
  501. package/esm/image/image.d.mts +6 -7
  502. package/esm/image/image.d.mts.map +1 -1
  503. package/esm/image/image.mjs.map +1 -1
  504. package/esm/image/index.d.mts +2 -1
  505. package/esm/image/index.mjs +1 -1
  506. package/esm/index.d.mts +21 -0
  507. package/esm/loader/app-module-importer.d.mts +1 -2
  508. package/esm/loader/app-module-importer.d.mts.map +1 -1
  509. package/esm/localization/index.mjs +1 -1
  510. package/esm/localization/parse-locale-dictionary.d.mts +4 -5
  511. package/esm/localization/parse-locale-dictionary.d.mts.map +1 -1
  512. package/esm/localization/parse-locale-dictionary.mjs +1 -1
  513. package/esm/localization/parse-locale-dictionary.mjs.map +1 -1
  514. package/esm/localization/register-locale-dictionary.d.mts +3 -4
  515. package/esm/localization/register-locale-dictionary.d.mts.map +1 -1
  516. package/esm/localization/register-locale-dictionary.mjs +2 -2
  517. package/esm/localization/register-locale-dictionary.mjs.map +1 -1
  518. package/esm/logger/fatal-visibility.d.mts +1 -2
  519. package/esm/logger/fatal-visibility.d.mts.map +1 -1
  520. package/esm/logger/index.d.mts +2 -1
  521. package/esm/logger/index.mjs +1 -1
  522. package/esm/logger/logger.d.mts +1 -3
  523. package/esm/logger/logger.d.mts.map +1 -1
  524. package/esm/logger/types.d.mts +2 -3
  525. package/esm/logger/types.d.mts.map +1 -1
  526. package/esm/mail/config.d.mts +12 -14
  527. package/esm/mail/config.d.mts.map +1 -1
  528. package/esm/mail/events.d.mts +4 -6
  529. package/esm/mail/events.d.mts.map +1 -1
  530. package/esm/mail/index.d.mts +2 -1
  531. package/esm/mail/index.mjs +1 -1
  532. package/esm/mail/mail.d.mts +1 -3
  533. package/esm/mail/mail.d.mts.map +1 -1
  534. package/esm/mail/mailer-pool.d.mts +5 -7
  535. package/esm/mail/mailer-pool.d.mts.map +1 -1
  536. package/esm/mail/react-mail.d.mts +1 -3
  537. package/esm/mail/react-mail.d.mts.map +1 -1
  538. package/esm/mail/send-mail.d.mts +1 -3
  539. package/esm/mail/send-mail.d.mts.map +1 -1
  540. package/esm/mail/send-mail.mjs +2 -1
  541. package/esm/mail/send-mail.mjs.map +1 -1
  542. package/esm/mail/test-mailbox.d.mts +11 -13
  543. package/esm/mail/test-mailbox.d.mts.map +1 -1
  544. package/esm/mail/types.d.mts +17 -18
  545. package/esm/mail/types.d.mts.map +1 -1
  546. package/esm/manifest/manifest-manager.mjs +1 -1
  547. package/esm/openapi/build-openapi-document.d.mts +2 -4
  548. package/esm/openapi/build-openapi-document.d.mts.map +1 -1
  549. package/esm/openapi/cast-schema.mjs +1 -1
  550. package/esm/openapi/development-openapi-provider.d.mts +5 -6
  551. package/esm/openapi/development-openapi-provider.d.mts.map +1 -1
  552. package/esm/openapi/index.d.mts +3 -1
  553. package/esm/openapi/index.mjs +1 -1
  554. package/esm/openapi/openapi-child-output.mjs +2 -2
  555. package/esm/openapi/openapi-child-output.mjs.map +1 -1
  556. package/esm/openapi/postman/build-request-url.mjs +1 -1
  557. package/esm/openapi/postman/example-from-schema.d.mts +1 -3
  558. package/esm/openapi/postman/example-from-schema.d.mts.map +1 -1
  559. package/esm/openapi/postman/index.d.mts +2 -1
  560. package/esm/openapi/postman/openapi-to-postman-collection.d.mts +3 -5
  561. package/esm/openapi/postman/openapi-to-postman-collection.d.mts.map +1 -1
  562. package/esm/openapi/postman/postman-types.d.mts +19 -18
  563. package/esm/openapi/postman/postman-types.d.mts.map +1 -1
  564. package/esm/openapi/postman/schema-refs.d.mts +1 -3
  565. package/esm/openapi/postman/schema-refs.d.mts.map +1 -1
  566. package/esm/openapi/postman/uuid-v5.mjs +1 -1
  567. package/esm/openapi/schema-registry.d.mts +1 -1
  568. package/esm/openapi/security.mjs +1 -1
  569. package/esm/openapi/types.d.mts +23 -21
  570. package/esm/openapi/types.d.mts.map +1 -1
  571. package/esm/production/assert-generated-imports.mjs +1 -1
  572. package/esm/production/build-contributions.mjs +1 -1
  573. package/esm/production/bundle-framework-dependencies.mjs +1 -1
  574. package/esm/production/dist-build-manifest.mjs +1 -1
  575. package/esm/production/esbuild-plugins.mjs.map +1 -1
  576. package/esm/production/esbuild-preflight.mjs +1 -1
  577. package/esm/production/production-builder.mjs +2 -1
  578. package/esm/production/production-builder.mjs.map +1 -1
  579. package/esm/production/production-supervisor.mjs +1 -1
  580. package/esm/production/registration-child-runner.mjs +4 -3
  581. package/esm/production/registration-child-runner.mjs.map +1 -1
  582. package/esm/production/resolve-build-config.d.mts +4 -4
  583. package/esm/production/resolve-build-config.d.mts.map +1 -1
  584. package/esm/production/resolve-build-config.mjs +1 -1
  585. package/esm/production/route-registration-child.d.mts +1 -1
  586. package/esm/production/route-registration-child.mjs +8 -7
  587. package/esm/production/route-registration-child.mjs.map +1 -1
  588. package/esm/production/tsconfig-path-aliases.mjs +1 -1
  589. package/esm/react/index.d.mts +1 -3
  590. package/esm/react/index.d.mts.map +1 -1
  591. package/esm/react/index.mjs.map +1 -1
  592. package/esm/repositories/adapters/cascade/cascade-adapter.d.mts +3 -4
  593. package/esm/repositories/adapters/cascade/cascade-adapter.d.mts.map +1 -1
  594. package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts +2 -3
  595. package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts.map +1 -1
  596. package/esm/repositories/adapters/cascade/filter-applicator.mjs +10 -9
  597. package/esm/repositories/adapters/cascade/filter-applicator.mjs.map +1 -1
  598. package/esm/repositories/adapters/cascade/index.d.mts +2 -1
  599. package/esm/repositories/adapters/cascade/index.mjs +1 -1
  600. package/esm/repositories/contracts/index.d.mts +2 -1
  601. package/esm/repositories/contracts/query-builder.contract.d.mts +4 -6
  602. package/esm/repositories/contracts/query-builder.contract.d.mts.map +1 -1
  603. package/esm/repositories/contracts/repository-adapter.contract.d.mts +1 -3
  604. package/esm/repositories/contracts/repository-adapter.contract.d.mts.map +1 -1
  605. package/esm/repositories/contracts/types.d.mts +23 -25
  606. package/esm/repositories/contracts/types.d.mts.map +1 -1
  607. package/esm/repositories/index.d.mts +4 -1
  608. package/esm/repositories/index.mjs +1 -1
  609. package/esm/repositories/repository.manager.d.mts +2 -3
  610. package/esm/repositories/repository.manager.d.mts.map +1 -1
  611. package/esm/repositories/repository.manager.mjs +2 -2
  612. package/esm/repositories/repository.manager.mjs.map +1 -1
  613. package/esm/resource/define-resource.d.mts +3 -5
  614. package/esm/resource/define-resource.d.mts.map +1 -1
  615. package/esm/resource/index.d.mts +2 -1
  616. package/esm/resource/index.mjs +1 -1
  617. package/esm/resource/nullable-resource.d.mts +5 -7
  618. package/esm/resource/nullable-resource.d.mts.map +1 -1
  619. package/esm/resource/register-resource.d.mts +1 -3
  620. package/esm/resource/register-resource.d.mts.map +1 -1
  621. package/esm/resource/resource-field-builder.d.mts +1 -3
  622. package/esm/resource/resource-field-builder.d.mts.map +1 -1
  623. package/esm/resource/resource.d.mts +3 -5
  624. package/esm/resource/resource.d.mts.map +1 -1
  625. package/esm/resource/resource.mjs +4 -2
  626. package/esm/resource/resource.mjs.map +1 -1
  627. package/esm/resource/types.d.mts +21 -21
  628. package/esm/resource/types.d.mts.map +1 -1
  629. package/esm/restful/index.d.mts +2 -1
  630. package/esm/restful/index.mjs +1 -1
  631. package/esm/restful/restful.d.mts +12 -32
  632. package/esm/restful/restful.d.mts.map +1 -1
  633. package/esm/router/index.d.mts +2 -1
  634. package/esm/router/index.mjs +1 -1
  635. package/esm/router/named-api-routes-with-responses.mjs +2 -1
  636. package/esm/router/named-api-routes-with-responses.mjs.map +1 -1
  637. package/esm/router/normalize-request-path.d.mts +1 -2
  638. package/esm/router/normalize-request-path.d.mts.map +1 -1
  639. package/esm/router/normalize-route-path.d.mts +1 -2
  640. package/esm/router/normalize-route-path.d.mts.map +1 -1
  641. package/esm/router/positional-handler-diagnostics.d.mts +15 -13
  642. package/esm/router/positional-handler-diagnostics.d.mts.map +1 -1
  643. package/esm/router/resolve-route-rate-limit.mjs +3 -3
  644. package/esm/router/resolve-route-rate-limit.mjs.map +1 -1
  645. package/esm/router/route-builder.d.mts +1 -3
  646. package/esm/router/route-builder.d.mts.map +1 -1
  647. package/esm/router/route-guard-names.mjs +1 -1
  648. package/esm/router/route-guard-names.mjs.map +1 -1
  649. package/esm/router/route-name-method-suffix.d.mts +2 -3
  650. package/esm/router/route-name-method-suffix.d.mts.map +1 -1
  651. package/esm/router/route-name-taken-error.d.mts +1 -3
  652. package/esm/router/route-name-taken-error.d.mts.map +1 -1
  653. package/esm/router/route-registry.d.mts +1 -3
  654. package/esm/router/route-registry.d.mts.map +1 -1
  655. package/esm/router/router.d.mts +2 -4
  656. package/esm/router/router.d.mts.map +1 -1
  657. package/esm/router/router.mjs +8 -6
  658. package/esm/router/router.mjs.map +1 -1
  659. package/esm/router/types.d.mts +25 -26
  660. package/esm/router/types.d.mts.map +1 -1
  661. package/esm/router/unguarded-route-diagnostics.d.mts +6 -8
  662. package/esm/router/unguarded-route-diagnostics.d.mts.map +1 -1
  663. package/esm/socket/index.d.mts +2 -1
  664. package/esm/socket/index.mjs +1 -1
  665. package/esm/socket/types.d.mts +2 -4
  666. package/esm/socket/types.d.mts.map +1 -1
  667. package/esm/socket/utils.d.mts +1 -3
  668. package/esm/socket/utils.d.mts.map +1 -1
  669. package/esm/storage/config.d.mts +4 -6
  670. package/esm/storage/config.d.mts.map +1 -1
  671. package/esm/storage/context/storage-driver-context.d.mts +3 -4
  672. package/esm/storage/context/storage-driver-context.d.mts.map +1 -1
  673. package/esm/storage/drivers/cloud-driver.d.mts +2 -4
  674. package/esm/storage/drivers/cloud-driver.d.mts.map +1 -1
  675. package/esm/storage/drivers/cloud-driver.mjs.map +1 -1
  676. package/esm/storage/drivers/do-spaces-driver.d.mts +1 -3
  677. package/esm/storage/drivers/do-spaces-driver.d.mts.map +1 -1
  678. package/esm/storage/drivers/local-driver.d.mts +2 -3
  679. package/esm/storage/drivers/local-driver.d.mts.map +1 -1
  680. package/esm/storage/drivers/local-driver.mjs +8 -3
  681. package/esm/storage/drivers/local-driver.mjs.map +1 -1
  682. package/esm/storage/drivers/r2-driver.d.mts +1 -3
  683. package/esm/storage/drivers/r2-driver.d.mts.map +1 -1
  684. package/esm/storage/drivers/s3-driver.d.mts +1 -3
  685. package/esm/storage/drivers/s3-driver.d.mts.map +1 -1
  686. package/esm/storage/index.d.mts +2 -1
  687. package/esm/storage/index.mjs +1 -1
  688. package/esm/storage/local-disk-roots.mjs +2 -2
  689. package/esm/storage/local-disk-roots.mjs.map +1 -1
  690. package/esm/storage/scoped-storage.d.mts +2 -3
  691. package/esm/storage/scoped-storage.d.mts.map +1 -1
  692. package/esm/storage/storage-file.d.mts +1 -3
  693. package/esm/storage/storage-file.d.mts.map +1 -1
  694. package/esm/storage/storage.d.mts +3 -4
  695. package/esm/storage/storage.d.mts.map +1 -1
  696. package/esm/storage/types.d.mts +36 -36
  697. package/esm/storage/types.d.mts.map +1 -1
  698. package/esm/storage/utils/classify-ip-address.d.mts +1 -2
  699. package/esm/storage/utils/classify-ip-address.d.mts.map +1 -1
  700. package/esm/storage/utils/contain-path.d.mts +1 -2
  701. package/esm/storage/utils/contain-path.d.mts.map +1 -1
  702. package/esm/storage/utils/mime.d.mts +2 -3
  703. package/esm/storage/utils/mime.d.mts.map +1 -1
  704. package/esm/storage/utils/safe-fetch.d.mts +6 -6
  705. package/esm/storage/utils/safe-fetch.d.mts.map +1 -1
  706. package/esm/storage/utils/safe-fetch.mjs +3 -3
  707. package/esm/storage/utils/safe-fetch.mjs.map +1 -1
  708. package/esm/storage/utils/storage-capability-error.d.mts +1 -3
  709. package/esm/storage/utils/storage-capability-error.d.mts.map +1 -1
  710. package/esm/storage/utils/storage-error.d.mts +2 -3
  711. package/esm/storage/utils/storage-error.d.mts.map +1 -1
  712. package/esm/storage/utils/storage-not-initialized-error.d.mts +1 -2
  713. package/esm/storage/utils/storage-not-initialized-error.d.mts.map +1 -1
  714. package/esm/tests/authenticated-test-client.d.mts +5 -6
  715. package/esm/tests/authenticated-test-client.d.mts.map +1 -1
  716. package/esm/tests/factories.d.mts +38 -23
  717. package/esm/tests/factories.d.mts.map +1 -1
  718. package/esm/tests/fakes/cache-fake.d.mts +14 -9
  719. package/esm/tests/fakes/cache-fake.d.mts.map +1 -1
  720. package/esm/tests/fakes/clock-fake.d.mts +13 -8
  721. package/esm/tests/fakes/clock-fake.d.mts.map +1 -1
  722. package/esm/tests/fakes/fake-assertion-error.d.mts +2 -3
  723. package/esm/tests/fakes/fake-assertion-error.d.mts.map +1 -1
  724. package/esm/tests/fakes/ids-fake.d.mts +5 -4
  725. package/esm/tests/fakes/ids-fake.d.mts.map +1 -1
  726. package/esm/tests/fakes/index.d.mts +2 -1
  727. package/esm/tests/fakes/index.mjs +1 -1
  728. package/esm/tests/fakes/mail-fake.d.mts +21 -13
  729. package/esm/tests/fakes/mail-fake.d.mts.map +1 -1
  730. package/esm/tests/fakes/queue-fake.d.mts +21 -13
  731. package/esm/tests/fakes/queue-fake.d.mts.map +1 -1
  732. package/esm/tests/fakes/storage-fake.d.mts +12 -8
  733. package/esm/tests/fakes/storage-fake.d.mts.map +1 -1
  734. package/esm/tests/fakes/storage-fake.mjs +1 -1
  735. package/esm/tests/fakes/test-fakes.d.mts +8 -9
  736. package/esm/tests/fakes/test-fakes.d.mts.map +1 -1
  737. package/esm/tests/fakes/test-fakes.mjs +1 -1
  738. package/esm/tests/fakes/test-fakes.mjs.map +1 -1
  739. package/esm/tests/index.d.mts +1 -0
  740. package/esm/tests/snapshot-response.d.mts +4 -5
  741. package/esm/tests/snapshot-response.d.mts.map +1 -1
  742. package/esm/tests/start-http-development-server.d.mts +4 -6
  743. package/esm/tests/start-http-development-server.d.mts.map +1 -1
  744. package/esm/tests/start-http-development-server.mjs +5 -5
  745. package/esm/tests/start-http-development-server.mjs.map +1 -1
  746. package/esm/tests/test-connectors-selection.d.mts +2 -2
  747. package/esm/tests/test-connectors-selection.d.mts.map +1 -1
  748. package/esm/tests/test-connectors-selection.mjs +1 -1
  749. package/esm/tests/test-helpers.d.mts +11 -12
  750. package/esm/tests/test-helpers.d.mts.map +1 -1
  751. package/esm/tests/test-http-server.d.mts +14 -10
  752. package/esm/tests/test-http-server.d.mts.map +1 -1
  753. package/esm/tests/test-lifecycle-state.mjs +1 -1
  754. package/esm/tests/vitest-setup.d.mts +6 -7
  755. package/esm/tests/vitest-setup.d.mts.map +1 -1
  756. package/esm/tooling/agents-md/agents-md-markers.d.mts +4 -5
  757. package/esm/tooling/agents-md/agents-md-markers.d.mts.map +1 -1
  758. package/esm/tooling/agents-md/agents-md-markers.mjs +2 -1
  759. package/esm/tooling/agents-md/agents-md-markers.mjs.map +1 -1
  760. package/esm/tooling/agents-md/agents-md-refresher.d.mts +19 -12
  761. package/esm/tooling/agents-md/agents-md-refresher.d.mts.map +1 -1
  762. package/esm/tooling/agents-md/installed-skills.d.mts +13 -9
  763. package/esm/tooling/agents-md/installed-skills.d.mts.map +1 -1
  764. package/esm/tooling/agents-md/render-agents-md.d.mts +8 -7
  765. package/esm/tooling/agents-md/render-agents-md.d.mts.map +1 -1
  766. package/esm/tooling/agents-md/render-agents-md.mjs +2 -2
  767. package/esm/tooling/agents-md/render-agents-md.mjs.map +1 -1
  768. package/esm/tooling/agents-md/write-agents-md.d.mts +17 -12
  769. package/esm/tooling/agents-md/write-agents-md.d.mts.map +1 -1
  770. package/esm/tooling/board/board-message.d.mts +4 -6
  771. package/esm/tooling/board/board-message.d.mts.map +1 -1
  772. package/esm/tooling/board/board.d.mts +50 -38
  773. package/esm/tooling/board/board.d.mts.map +1 -1
  774. package/esm/tooling/board/board.mjs +4 -3
  775. package/esm/tooling/board/board.mjs.map +1 -1
  776. package/esm/tooling/board/board.types.d.mts +32 -23
  777. package/esm/tooling/board/board.types.d.mts.map +1 -1
  778. package/esm/tooling/check/changed-files.d.mts +4 -6
  779. package/esm/tooling/check/changed-files.d.mts.map +1 -1
  780. package/esm/tooling/check/changed-files.mjs +2 -2
  781. package/esm/tooling/check/changed-files.mjs.map +1 -1
  782. package/esm/tooling/check/check-report.types.d.mts +22 -17
  783. package/esm/tooling/check/check-report.types.d.mts.map +1 -1
  784. package/esm/tooling/check/code-style-conventions.mjs +25 -25
  785. package/esm/tooling/check/code-style-conventions.mjs.map +1 -1
  786. package/esm/tooling/check/conventions-step.d.mts +4 -6
  787. package/esm/tooling/check/conventions-step.d.mts.map +1 -1
  788. package/esm/tooling/check/conventions-step.mjs +7 -18
  789. package/esm/tooling/check/conventions-step.mjs.map +1 -1
  790. package/esm/tooling/check/environment-step.d.mts +2 -4
  791. package/esm/tooling/check/environment-step.d.mts.map +1 -1
  792. package/esm/tooling/check/environment-step.mjs +1 -1
  793. package/esm/tooling/check/index.mjs +1 -1
  794. package/esm/tooling/check/lint-step.d.mts +4 -5
  795. package/esm/tooling/check/lint-step.d.mts.map +1 -1
  796. package/esm/tooling/check/lint-step.mjs +2 -1
  797. package/esm/tooling/check/lint-step.mjs.map +1 -1
  798. package/esm/tooling/check/request-input.mjs +15 -15
  799. package/esm/tooling/check/request-input.mjs.map +1 -1
  800. package/esm/tooling/check/run-check.d.mts +22 -14
  801. package/esm/tooling/check/run-check.d.mts.map +1 -1
  802. package/esm/tooling/check/run-tests.d.mts +22 -15
  803. package/esm/tooling/check/run-tests.d.mts.map +1 -1
  804. package/esm/tooling/check/security-conventions.mjs +133 -131
  805. package/esm/tooling/check/security-conventions.mjs.map +1 -1
  806. package/esm/tooling/check/source-ast.mjs +92 -132
  807. package/esm/tooling/check/source-ast.mjs.map +1 -1
  808. package/esm/tooling/check/tests-step.d.mts +7 -8
  809. package/esm/tooling/check/tests-step.d.mts.map +1 -1
  810. package/esm/tooling/check/tests-step.mjs +3 -3
  811. package/esm/tooling/check/tests-step.mjs.map +1 -1
  812. package/esm/tooling/dev-state/dev-server-state.d.mts +17 -13
  813. package/esm/tooling/dev-state/dev-server-state.d.mts.map +1 -1
  814. package/esm/tooling/devtools/devtools-client.d.mts +29 -20
  815. package/esm/tooling/devtools/devtools-client.d.mts.map +1 -1
  816. package/esm/tooling/generate/generation.d.mts +34 -22
  817. package/esm/tooling/generate/generation.d.mts.map +1 -1
  818. package/esm/tooling/generate/generation.mjs +9 -5
  819. package/esm/tooling/generate/generation.mjs.map +1 -1
  820. package/esm/tooling/generate/generator-spec.d.mts +9 -9
  821. package/esm/tooling/generate/generator-spec.d.mts.map +1 -1
  822. package/esm/tooling/generate/index.mjs +1 -1
  823. package/esm/tooling/generate/project-files.mjs +3 -3
  824. package/esm/tooling/generate/project-files.mjs.map +1 -1
  825. package/esm/tooling/generate/run-cli.d.mts +14 -11
  826. package/esm/tooling/generate/run-cli.d.mts.map +1 -1
  827. package/esm/tooling/generate/run-cli.mjs +2 -2
  828. package/esm/tooling/generate/run-cli.mjs.map +1 -1
  829. package/esm/tooling/generate/unified-diff.d.mts +10 -7
  830. package/esm/tooling/generate/unified-diff.d.mts.map +1 -1
  831. package/esm/tooling/index.d.mts +1 -0
  832. package/esm/tooling/inspect/boot-for-inspect.d.mts +7 -7
  833. package/esm/tooling/inspect/boot-for-inspect.d.mts.map +1 -1
  834. package/esm/tooling/inspect/collect-config.mjs +3 -3
  835. package/esm/tooling/inspect/collect-config.mjs.map +1 -1
  836. package/esm/tooling/inspect/collect-models.d.mts +4 -3
  837. package/esm/tooling/inspect/collect-models.d.mts.map +1 -1
  838. package/esm/tooling/inspect/collect-models.mjs +1 -1
  839. package/esm/tooling/inspect/collect-packages.d.mts +1 -2
  840. package/esm/tooling/inspect/collect-packages.d.mts.map +1 -1
  841. package/esm/tooling/inspect/collect-pages.mjs +10 -10
  842. package/esm/tooling/inspect/collect-pages.mjs.map +1 -1
  843. package/esm/tooling/inspect/collect-routes.mjs +1 -1
  844. package/esm/tooling/inspect/event-recorder.d.mts +7 -7
  845. package/esm/tooling/inspect/event-recorder.d.mts.map +1 -1
  846. package/esm/tooling/inspect/index.d.mts +2 -1
  847. package/esm/tooling/inspect/index.mjs +1 -1
  848. package/esm/tooling/inspect/inspect-app.d.mts +25 -16
  849. package/esm/tooling/inspect/inspect-app.d.mts.map +1 -1
  850. package/esm/tooling/inspect/inspect-report.schema.d.mts +1 -2
  851. package/esm/tooling/inspect/inspect-report.schema.d.mts.map +1 -1
  852. package/esm/tooling/inspect/inspect-report.types.d.mts +86 -54
  853. package/esm/tooling/inspect/inspect-report.types.d.mts.map +1 -1
  854. package/esm/tooling/mcp/create-mcp-context.d.mts +11 -8
  855. package/esm/tooling/mcp/create-mcp-context.d.mts.map +1 -1
  856. package/esm/tooling/mcp/db-schema.d.mts +10 -9
  857. package/esm/tooling/mcp/db-schema.d.mts.map +1 -1
  858. package/esm/tooling/mcp/docs-search.d.mts +20 -15
  859. package/esm/tooling/mcp/docs-search.d.mts.map +1 -1
  860. package/esm/tooling/mcp/index.mjs +1 -1
  861. package/esm/tooling/mcp/load-ai-tools.d.mts +7 -8
  862. package/esm/tooling/mcp/load-ai-tools.d.mts.map +1 -1
  863. package/esm/tooling/mcp/load-ai-tools.mjs +2 -1
  864. package/esm/tooling/mcp/load-ai-tools.mjs.map +1 -1
  865. package/esm/tooling/mcp/mcp-tools.d.mts +29 -19
  866. package/esm/tooling/mcp/mcp-tools.d.mts.map +1 -1
  867. package/esm/tooling/mcp/mcp-tools.mjs +3 -2
  868. package/esm/tooling/mcp/mcp-tools.mjs.map +1 -1
  869. package/esm/tooling/mcp/start-mcp-server.d.mts +24 -17
  870. package/esm/tooling/mcp/start-mcp-server.d.mts.map +1 -1
  871. package/esm/tooling/mcp/start-mcp-server.mjs +1 -1
  872. package/esm/tooling/mcp/start-mcp-server.mjs.map +1 -1
  873. package/esm/tooling/mcp/tool-input.d.mts +7 -7
  874. package/esm/tooling/mcp/tool-input.d.mts.map +1 -1
  875. package/esm/tooling/problem.d.mts +27 -17
  876. package/esm/tooling/problem.d.mts.map +1 -1
  877. package/esm/tooling/syntax/ast.mjs +230 -0
  878. package/esm/tooling/syntax/ast.mjs.map +1 -0
  879. package/esm/tooling/syntax/imports.mjs +34 -0
  880. package/esm/tooling/syntax/imports.mjs.map +1 -0
  881. package/esm/tooling/trace/trace-report.types.d.mts +36 -22
  882. package/esm/tooling/trace/trace-report.types.d.mts.map +1 -1
  883. package/esm/tooling/trace/trace-request.d.mts +27 -20
  884. package/esm/tooling/trace/trace-request.d.mts.map +1 -1
  885. package/esm/tooling/trace/trace-request.mjs +2 -2
  886. package/esm/tooling/trace/trace-request.mjs.map +1 -1
  887. package/esm/tooling/typecheck/index.mjs +1 -1
  888. package/esm/tooling/typecheck/run-typecheck.d.mts +15 -48
  889. package/esm/tooling/typecheck/run-typecheck.d.mts.map +1 -1
  890. package/esm/tooling/typecheck/run-typecheck.mjs +42 -105
  891. package/esm/tooling/typecheck/run-typecheck.mjs.map +1 -1
  892. package/esm/tooling/typescript/compiler.d.mts +31 -0
  893. package/esm/tooling/typescript/compiler.d.mts.map +1 -0
  894. package/esm/tooling/typescript/compiler.mjs +120 -0
  895. package/esm/tooling/typescript/compiler.mjs.map +1 -0
  896. package/esm/updater/update-warlock-packages.mjs +3 -2
  897. package/esm/updater/update-warlock-packages.mjs.map +1 -1
  898. package/esm/upgrade/codemods/index.mjs +1 -1
  899. package/esm/upgrade/codemods/logger-sync-calls.mjs +1 -1
  900. package/esm/upgrade/codemods/logger-sync-calls.mjs.map +1 -1
  901. package/esm/upgrade/codemods/request-log-snapshot.mjs +1 -1
  902. package/esm/upgrade/codemods/request-log-snapshot.mjs.map +1 -1
  903. package/esm/upgrade/diff.mjs +1 -1
  904. package/esm/upgrade/diff.mjs.map +1 -1
  905. package/esm/upgrade/load-ts-morph.mjs +3 -2
  906. package/esm/upgrade/load-ts-morph.mjs.map +1 -1
  907. package/esm/upgrade/run-upgrade.mjs +1 -1
  908. package/esm/use-cases/index.d.mts +2 -1
  909. package/esm/use-cases/index.mjs +1 -1
  910. package/esm/use-cases/types.d.mts +116 -63
  911. package/esm/use-cases/types.d.mts.map +1 -1
  912. package/esm/use-cases/use-case-broadcast.d.mts +1 -3
  913. package/esm/use-cases/use-case-broadcast.d.mts.map +1 -1
  914. package/esm/use-cases/use-case-events.d.mts +3 -5
  915. package/esm/use-cases/use-case-events.d.mts.map +1 -1
  916. package/esm/use-cases/use-case-pipeline.d.mts +6 -6
  917. package/esm/use-cases/use-case-pipeline.d.mts.map +1 -1
  918. package/esm/use-cases/use-case.d.mts +2 -4
  919. package/esm/use-cases/use-case.d.mts.map +1 -1
  920. package/esm/use-cases/use-case.errors.d.mts +1 -3
  921. package/esm/use-cases/use-case.errors.d.mts.map +1 -1
  922. package/esm/use-cases/use-cases-registry.d.mts +8 -10
  923. package/esm/use-cases/use-cases-registry.d.mts.map +1 -1
  924. package/esm/utils/app-log.d.mts +1 -2
  925. package/esm/utils/app-log.d.mts.map +1 -1
  926. package/esm/utils/clock.d.mts +8 -6
  927. package/esm/utils/clock.d.mts.map +1 -1
  928. package/esm/utils/database-log.d.mts +3 -4
  929. package/esm/utils/database-log.d.mts.map +1 -1
  930. package/esm/utils/environment.d.mts +4 -5
  931. package/esm/utils/environment.d.mts.map +1 -1
  932. package/esm/utils/framework-vesion.mjs.map +1 -1
  933. package/esm/utils/get-localized.d.mts +2 -3
  934. package/esm/utils/get-localized.d.mts.map +1 -1
  935. package/esm/utils/ids.d.mts +9 -6
  936. package/esm/utils/ids.d.mts.map +1 -1
  937. package/esm/utils/index.d.mts +2 -1
  938. package/esm/utils/index.mjs +1 -1
  939. package/esm/utils/normalized-path.d.mts +1 -2
  940. package/esm/utils/normalized-path.d.mts.map +1 -1
  941. package/esm/utils/npm-registry.d.mts +1 -2
  942. package/esm/utils/npm-registry.d.mts.map +1 -1
  943. package/esm/utils/paths.d.mts +13 -14
  944. package/esm/utils/paths.d.mts.map +1 -1
  945. package/esm/utils/paths.mjs +2 -2
  946. package/esm/utils/paths.mjs.map +1 -1
  947. package/esm/utils/promise-all-object.d.mts +1 -2
  948. package/esm/utils/promise-all-object.d.mts.map +1 -1
  949. package/esm/utils/queue.d.mts +1 -2
  950. package/esm/utils/queue.d.mts.map +1 -1
  951. package/esm/utils/runtime.d.mts +11 -10
  952. package/esm/utils/runtime.d.mts.map +1 -1
  953. package/esm/utils/sleep.d.mts +1 -2
  954. package/esm/utils/sleep.d.mts.map +1 -1
  955. package/esm/utils/sluggable.d.mts +1 -3
  956. package/esm/utils/sluggable.d.mts.map +1 -1
  957. package/esm/utils/to-json.d.mts +1 -2
  958. package/esm/utils/to-json.d.mts.map +1 -1
  959. package/esm/utils/types.d.mts +1 -2
  960. package/esm/utils/types.d.mts.map +1 -1
  961. package/esm/utils/urls.d.mts +5 -6
  962. package/esm/utils/urls.d.mts.map +1 -1
  963. package/esm/utils/version-compare.d.mts +1 -2
  964. package/esm/utils/version-compare.d.mts.map +1 -1
  965. package/esm/validation/database/exists-except-current-id.d.mts +2 -3
  966. package/esm/validation/database/exists-except-current-id.d.mts.map +1 -1
  967. package/esm/validation/database/exists-except-current-user.d.mts +2 -3
  968. package/esm/validation/database/exists-except-current-user.d.mts.map +1 -1
  969. package/esm/validation/database/index.d.mts +2 -1
  970. package/esm/validation/database/index.mjs +1 -1
  971. package/esm/validation/database/types.d.mts +14 -10
  972. package/esm/validation/database/types.d.mts.map +1 -1
  973. package/esm/validation/database/unique-except-current-id.d.mts +2 -3
  974. package/esm/validation/database/unique-except-current-id.d.mts.map +1 -1
  975. package/esm/validation/database/unique-except-current-user.d.mts +2 -3
  976. package/esm/validation/database/unique-except-current-user.d.mts.map +1 -1
  977. package/esm/validation/file/file.d.mts +4 -6
  978. package/esm/validation/file/file.d.mts.map +1 -1
  979. package/esm/validation/file/index.d.mts +2 -1
  980. package/esm/validation/file/index.mjs +1 -1
  981. package/esm/validation/index.d.mts +5 -1
  982. package/esm/validation/index.mjs +1 -1
  983. package/esm/validation/plugins/index.mjs +1 -1
  984. package/esm/validation/types.d.mts +6 -4
  985. package/esm/validation/types.d.mts.map +1 -1
  986. package/esm/validation/validateAll.mjs +2 -2
  987. package/esm/validation/validateAll.mjs.map +1 -1
  988. package/esm/validation/validation-failure-status.mjs +2 -2
  989. package/esm/validation/validation-failure-status.mjs.map +1 -1
  990. package/esm/validation/validators/file-validator.d.mts +2 -4
  991. package/esm/validation/validators/file-validator.d.mts.map +1 -1
  992. package/esm/validation/validators/index.d.mts +2 -1
  993. package/esm/validation/validators/index.mjs +1 -1
  994. package/esm/vite/lower-stage3-decorators.d.mts +2 -3
  995. package/esm/vite/lower-stage3-decorators.d.mts.map +1 -1
  996. package/esm/warlock-config/define-config.d.mts +1 -3
  997. package/esm/warlock-config/define-config.d.mts.map +1 -1
  998. package/esm/warlock-config/define-config.mjs +3 -2
  999. package/esm/warlock-config/define-config.mjs.map +1 -1
  1000. package/esm/warlock-config/index.d.mts +2 -1
  1001. package/esm/warlock-config/index.mjs +1 -1
  1002. package/esm/warlock-config/types.d.mts +6 -5
  1003. package/esm/warlock-config/types.d.mts.map +1 -1
  1004. package/esm/warlock-config/warlock-config.manager.d.mts +5 -7
  1005. package/esm/warlock-config/warlock-config.manager.d.mts.map +1 -1
  1006. package/esm/warlock-config/warlock-config.manager.mjs +2 -1
  1007. package/esm/warlock-config/warlock-config.manager.mjs.map +1 -1
  1008. package/esm/warlock-config/warn-deprecated-config.mjs +1 -1
  1009. package/llms-full.txt +55 -5
  1010. package/package.json +17 -15
  1011. package/skills/create-module/SKILL.md +7 -0
  1012. package/skills/index.md +2 -0
  1013. package/skills/report-framework-issue.md +154 -0
  1014. package/skills/run-app/SKILL.md +6 -5
  1015. package/skills/upgrade-from-5-29/SKILL.md +41 -0
  1016. package/skills/warlock-check/SKILL.md +1 -0
  1017. package/esm/tooling/check/index.d.mts +0 -8
  1018. package/esm/tooling/typecheck/index.d.mts +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"security-conventions.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/check/security-conventions.ts"],"sourcesContent":["import { DEFAULT_REDACT_KEY_SET, normalizeRedactKey } from \"@warlock.js/logger\";\nimport ts from \"typescript\";\nimport { isAuthGuardName, isMutatingHttpMethod } from \"../../router/route-guard-names\";\nimport {\n containsRequestInput,\n REQUEST_BODY_MEMBERS,\n REQUEST_NAMES,\n requestMemberAccess,\n} from \"./request-input\";\nimport {\n ancestors,\n calleeName,\n isFunctionLike,\n isMemberAccess,\n keyName,\n literalString,\n memberName,\n referencesOf,\n resolveInitializer,\n rootIdentifier,\n type SourceFinding,\n unwrap,\n walk,\n} from \"./source-ast\";\n\n// ── WL9005: request.all() into a query, a service or inApp() ────────────────\n\n/** Request methods that return every input the client sent, validated or not. */\nconst UNFILTERED_METHODS: ReadonlySet<string> = new Set([\n \"all\",\n \"allExceptParams\",\n \"heavy\",\n \"heavyExceptParams\",\n]);\n\n/**\n * Responses and loggers are not the data sinks `WL9005` guards: echoing input\n * back is not mass assignment, and logging it is `WL9008`'s concern.\n */\nconst IGNORED_RECEIVERS: ReadonlySet<string> = new Set([\n \"response\",\n \"reply\",\n \"res\",\n \"console\",\n \"log\",\n \"logger\",\n]);\n\nfunction displayCallee(callee: ts.Node): string {\n const target = unwrap(callee);\n\n if (ts.isIdentifier(target)) return `${target.text}()`;\n\n if (isMemberAccess(target)) {\n const name = memberName(target);\n const object = unwrap(target.expression);\n const owner = ts.isIdentifier(object) ? `${object.text}.` : \"\";\n\n return name ? `${owner}${name}()` : \"a call\";\n }\n\n return \"a call\";\n}\n\nfunction isIgnoredReceiver(callee: ts.Node): boolean {\n const target = unwrap(callee);\n\n if (!isMemberAccess(target)) return false;\n\n const object = unwrap(target.expression);\n\n return ts.isIdentifier(object) && IGNORED_RECEIVERS.has(object.text);\n}\n\n/** When `node` flows into a call's arguments, the callee's display name. */\nfunction callReceiving(node: ts.Node): string | undefined {\n let current = node;\n\n for (;;) {\n const parent = current.parent;\n\n if (!parent) return undefined;\n\n if (ts.isCallExpression(parent) || ts.isNewExpression(parent)) {\n if (!(parent.arguments ?? []).some((argument) => argument === current)) return undefined;\n if (isIgnoredReceiver(parent.expression)) return undefined;\n\n return displayCallee(parent.expression);\n }\n\n if (\n ts.isSpreadElement(parent) ||\n ts.isSpreadAssignment(parent) ||\n ts.isObjectLiteralExpression(parent) ||\n ts.isArrayLiteralExpression(parent) ||\n (ts.isPropertyAssignment(parent) && parent.initializer === current) ||\n ts.isShorthandPropertyAssignment(parent) ||\n ts.isAsExpression(parent) ||\n ts.isNonNullExpression(parent) ||\n ts.isSatisfiesExpression(parent) ||\n ts.isTypeAssertionExpression(parent) ||\n ts.isParenthesizedExpression(parent) ||\n ts.isAwaitExpression(parent)\n ) {\n current = parent;\n continue;\n }\n\n return undefined;\n }\n}\n\n/**\n * The call that ends up receiving this value: directly as an argument, spread\n * into an object/array argument, or through a local constant later passed to\n * a call.\n */\nfunction receivingCall(node: ts.Node): string | undefined {\n const direct = callReceiving(node);\n\n if (direct) return direct;\n\n // `const data = request.all(); await Model.create(data);`\n const parent = node.parent;\n\n if (\n parent &&\n ts.isVariableDeclaration(parent) &&\n parent.initializer === node &&\n ts.isIdentifier(parent.name)\n ) {\n for (const reference of referencesOf(parent)) {\n const name = callReceiving(reference);\n if (name) return name;\n }\n }\n\n return undefined;\n}\n\nfunction checkRequestAll(node: ts.Node, findings: SourceFinding[]): void {\n if (!ts.isCallExpression(node)) return;\n\n const callee = unwrap(node.expression);\n\n if (!isMemberAccess(callee)) return;\n\n const object = unwrap(callee.expression);\n\n if (!ts.isIdentifier(object) || !REQUEST_NAMES.has(object.text)) return;\n\n const method = memberName(callee);\n\n if (!method || !UNFILTERED_METHODS.has(method)) return;\n\n const target = receivingCall(node);\n\n if (!target) return;\n\n findings.push({\n code: \"WL9005\",\n node,\n message: `\\`${object.text}.${method}()\\` passes every client-sent field to \\`${target}\\`. Use \\`${object.text}.validated()\\` so only the fields the validation schema accepted reach it.`,\n });\n}\n\n// ── WL9006: a mutating route with no auth guard and no public: true ─────────\n\nconst ROUTER_NAMES: ReadonlySet<string> = new Set([\"router\"]);\n\n/** Wrappers whose callback routes are guarded, e.g. `guarded(() => …)`. */\nconst GUARD_FUNCTIONS: ReadonlySet<string> = new Set([\"guarded\"]);\n\n/** `router.post(…)` and friends. */\nconst MUTATING_ROUTER_METHODS: ReadonlySet<string> = new Set([\"post\", \"put\", \"patch\", \"delete\"]);\n\n/** Route builder methods (`router.route(path).create(…)`) that register a mutating route. */\nconst MUTATING_BUILDER_METHODS: ReadonlySet<string> = new Set([\n \"post\",\n \"postOne\",\n \"put\",\n \"updateOne\",\n \"patch\",\n \"patchOne\",\n \"delete\",\n \"deleteOne\",\n \"create\",\n \"update\",\n \"destroy\",\n]);\n\nconst READ_ONLY_RESOURCE_METHODS: ReadonlySet<string> = new Set([\"list\", \"get\", \"show\"]);\n\nfunction isRouter(node: ts.Node): boolean {\n const target = unwrap(node);\n\n return ts.isIdentifier(target) && ROUTER_NAMES.has(target.text);\n}\n\nfunction isGuardName(name: string | undefined): boolean {\n return name !== undefined && isAuthGuardName(name);\n}\n\n/** Whether a constant is initialised with `markAuthGuard(fn)` (not `markAuthGuard(fn, false)`). */\nfunction isMarkedGuard(identifier: ts.Identifier): boolean {\n const initializer = resolveInitializer(identifier);\n const value = initializer ? unwrap(initializer) : undefined;\n\n return (\n value !== undefined &&\n ts.isCallExpression(value) &&\n calleeName(value) === \"markAuthGuard\" &&\n value.arguments[1]?.kind !== ts.SyntaxKind.FalseKeyword\n );\n}\n\nfunction middlewareHasGuard(node: ts.Node): boolean {\n const value = unwrap(node);\n\n // A variable or a call: the check cannot see into it, so it trusts it.\n if (!ts.isArrayLiteralExpression(value)) return true;\n\n return value.elements.some((element) => {\n if (ts.isSpreadElement(element)) return true;\n\n const item = unwrap(element);\n\n if (ts.isIdentifier(item)) return isGuardName(item.text) || isMarkedGuard(item);\n if (ts.isCallExpression(item)) return isGuardName(calleeName(item));\n if (isMemberAccess(item)) return isGuardName(memberName(item));\n\n return false;\n });\n}\n\n/** `public: true`, a guard in `middleware`, or an options value the check cannot see into. */\nfunction optionsGuard(node: ts.Node | undefined): \"guarded\" | \"unguarded\" | \"none\" {\n if (!node) return \"none\";\n\n const value = unwrap(node);\n\n if (!ts.isObjectLiteralExpression(value)) return \"guarded\";\n\n let verdict: \"guarded\" | \"unguarded\" = \"unguarded\";\n\n for (const property of value.properties) {\n if (ts.isSpreadAssignment(property)) {\n verdict = \"guarded\";\n continue;\n }\n\n let key: string | undefined;\n let propertyValue: ts.Node | undefined;\n\n if (ts.isPropertyAssignment(property)) {\n key = keyName(property.name);\n propertyValue = unwrap(property.initializer);\n } else if (ts.isShorthandPropertyAssignment(property)) {\n key = property.name.text;\n propertyValue = property.name;\n }\n\n if (!propertyValue) continue;\n if (key === \"public\" && propertyValue.kind === ts.SyntaxKind.TrueKeyword) return \"guarded\";\n if (key === \"middleware\" && middlewareHasGuard(propertyValue)) return \"guarded\";\n }\n\n return verdict;\n}\n\n/** Whether an enclosing function is a guarded (or public) group callback. */\nfunction insideGuardedGroup(node: ts.Node): boolean {\n for (const ancestor of ancestors(node)) {\n if (!ts.isArrowFunction(ancestor) && !ts.isFunctionExpression(ancestor)) continue;\n\n const parent = ancestor.parent;\n\n if (!parent || !ts.isCallExpression(parent)) continue;\n if (!parent.arguments.some((argument) => argument === ancestor)) continue;\n\n const name = calleeName(parent);\n\n if (name !== undefined && GUARD_FUNCTIONS.has(name)) return true;\n\n const callee = unwrap(parent.expression);\n\n if (\n isMemberAccess(callee) &&\n memberName(callee) === \"group\" &&\n isRouter(callee.expression) &&\n optionsGuard(parent.arguments[0]) === \"guarded\"\n ) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction pathText(node: ts.Node | undefined): string {\n return literalString(node) ?? \"(dynamic path)\";\n}\n\n/**\n * Walk a builder chain back to `router.route(path, options)`, collecting every\n * options object passed along the way (`route()`, `nest()`).\n */\nfunction builderChain(node: ts.Node): { path: string; optionNodes: ts.Node[] } | undefined {\n const optionNodes: ts.Node[] = [];\n let current = unwrap(node);\n\n while (ts.isCallExpression(current)) {\n const callee = unwrap(current.expression);\n\n if (!isMemberAccess(callee)) return undefined;\n\n const name = memberName(callee);\n\n if (name === \"route\" && isRouter(callee.expression)) {\n const options = current.arguments[1];\n if (options) optionNodes.push(options);\n\n return { path: pathText(current.arguments[0]), optionNodes };\n }\n\n if (name === \"nest\") {\n const options = current.arguments[1];\n if (options) optionNodes.push(options);\n }\n\n current = unwrap(callee.expression);\n }\n\n return undefined;\n}\n\nfunction resourceIsReadOnly(node: ts.Node | undefined): boolean {\n if (!node) return false;\n\n const value = unwrap(node);\n\n if (!ts.isObjectLiteralExpression(value)) return false;\n\n for (const property of value.properties) {\n if (!ts.isPropertyAssignment(property) || keyName(property.name) !== \"only\") continue;\n\n const only = unwrap(property.initializer);\n\n if (!ts.isArrayLiteralExpression(only)) return false;\n\n return only.elements.every((element) => {\n const method = literalString(element);\n return method !== undefined && READ_ONLY_RESOURCE_METHODS.has(method);\n });\n }\n\n return false;\n}\n\nfunction unguardedRoute(node: ts.Node, route: string): SourceFinding {\n return {\n code: \"WL9006\",\n node,\n message: `Mutating route \\`${route}\\` has no auth middleware. Add an auth guard (\\`middleware: [authMiddleware()]\\`, or register it inside a guarded group) or mark it intentionally open with \\`public: true\\`.`,\n };\n}\n\nfunction checkRouteGuard(node: ts.Node, findings: SourceFinding[]): void {\n if (!ts.isCallExpression(node)) return;\n\n const callee = unwrap(node.expression);\n\n if (!isMemberAccess(callee)) return;\n\n const method = memberName(callee);\n\n if (!method) return;\n\n const guarded = (options: ts.Node | undefined) =>\n optionsGuard(options) === \"guarded\" || insideGuardedGroup(node);\n\n if (isRouter(callee.expression)) {\n // router.post(path, handler, options)\n if (MUTATING_ROUTER_METHODS.has(method)) {\n if (!guarded(node.arguments[2])) {\n findings.push(\n unguardedRoute(node, `${method.toUpperCase()} ${pathText(node.arguments[0])}`),\n );\n }\n\n return;\n }\n\n // router.add(\"POST\", path, handler, options)\n if (method === \"add\") {\n const httpMethod = literalString(node.arguments[0])?.toUpperCase();\n\n if (!httpMethod || !isMutatingHttpMethod(httpMethod)) return;\n\n if (!guarded(node.arguments[3])) {\n findings.push(unguardedRoute(node, `${httpMethod} ${pathText(node.arguments[1])}`));\n }\n\n return;\n }\n\n // router.restfulResource(path, resource, options)\n if (method === \"restfulResource\") {\n if (resourceIsReadOnly(node.arguments[2])) return;\n\n if (!guarded(node.arguments[2])) {\n findings.push(unguardedRoute(node, `resource ${pathText(node.arguments[0])}`));\n }\n }\n\n return;\n }\n\n // router.route(path, options).create(handler, options)\n if (!MUTATING_BUILDER_METHODS.has(method)) return;\n\n const chain = builderChain(callee.expression);\n\n if (!chain) return;\n if (optionsGuard(node.arguments[1]) === \"guarded\") return;\n if (chain.optionNodes.some((options) => optionsGuard(options) === \"guarded\")) return;\n if (insideGuardedGroup(node)) return;\n\n findings.push(unguardedRoute(node, `${method} ${chain.path}`));\n}\n\n// ── WL9007: a redirect or link target from request input ────────────────────\n\n/** Calls that turn their first argument into a redirect or a navigation. */\nconst REDIRECT_CALLS: ReadonlySet<string> = new Set([\n \"redirect\",\n \"permanentRedirect\",\n \"navigateTo\",\n]);\n\n/** Components whose `to`/`href` prop navigates. */\nconst LINK_COMPONENTS: ReadonlySet<string> = new Set([\"Link\", \"NavLink\"]);\n\n/** Helpers that return an allowed target (or a fallback) for any input. */\nconst REDIRECT_SANITIZERS: ReadonlySet<string> = new Set([\"safeRedirect\", \"safeRedirectTarget\"]);\n\n/** Predicates that, used in an enclosing `if` or `? :`, prove the target was checked. */\nconst REDIRECT_VALIDATORS: ReadonlySet<string> = new Set([\"isSafeRedirect\", \"isSafeRedirectUrl\"]);\n\n/** Client-side input: query-string hooks. */\nconst CLIENT_INPUT_CALLS: ReadonlySet<string> = new Set([\n \"useQueryString\",\n \"useSearchParams\",\n \"useParams\",\n]);\n\n/** Identifiers whose members are client-controlled (a loader's `query`, URLSearchParams). */\nconst CLIENT_INPUT_NAMES: ReadonlySet<string> = new Set([\"query\", \"searchParams\"]);\n\nfunction isClientSource(node: ts.Node): boolean {\n if (ts.isCallExpression(node)) {\n const name = calleeName(node);\n if (name !== undefined && CLIENT_INPUT_CALLS.has(name)) return true;\n }\n\n if (isMemberAccess(node)) {\n const root = rootIdentifier(node);\n\n if (root && CLIENT_INPUT_NAMES.has(root.text)) return true;\n\n // location.search / window.location.hash\n const name = memberName(node);\n\n if (name === \"search\" || name === \"hash\") {\n const object = unwrap(node.expression);\n\n if (ts.isIdentifier(object) && object.text === \"location\") return true;\n if (isMemberAccess(object) && memberName(object) === \"location\") return true;\n }\n }\n\n return false;\n}\n\nfunction isRedirectTainted(node: ts.Node): boolean {\n return containsRequestInput(node, { sanitizers: REDIRECT_SANITIZERS, isSource: isClientSource });\n}\n\n/** An enclosing `if (isSafeRedirect(x))` or `isSafeRedirect(x) ? … : …` validated the target. */\nfunction checkedByValidator(node: ts.Node): boolean {\n for (const ancestor of ancestors(node)) {\n let test: ts.Node | undefined;\n\n if (ts.isIfStatement(ancestor)) test = ancestor.expression;\n else if (ts.isConditionalExpression(ancestor)) test = ancestor.condition;\n else continue;\n\n let validated = false;\n\n walk(test, (child) => {\n if (ts.isCallExpression(child)) {\n const name = calleeName(child);\n if (name !== undefined && REDIRECT_VALIDATORS.has(name)) validated = true;\n }\n\n return undefined;\n });\n\n if (validated) return true;\n }\n\n return false;\n}\n\nfunction unsafeRedirect(node: ts.Node, what: string, helper: string, from: string): SourceFinding {\n return {\n code: \"WL9007\",\n node,\n message: `This ${what} target comes from request input. Pass it through \\`${helper}()\\` from \\`${from}\\` so only same-origin paths and allow-listed origins are followed (open redirects and \\`javascript:\\` URLs otherwise).`,\n };\n}\n\nfunction checkRedirect(node: ts.Node, findings: SourceFinding[]): void {\n if (ts.isCallExpression(node)) {\n const name = calleeName(node);\n\n if (name === undefined || !REDIRECT_CALLS.has(name)) return;\n\n // `router.redirect(from, to)` registers a static redirect, not a request-time one.\n const callee = unwrap(node.expression);\n\n if (isMemberAccess(callee)) {\n const owner = unwrap(callee.expression);\n if (ts.isIdentifier(owner) && owner.text === \"router\") return;\n }\n\n const target = node.arguments[0];\n\n if (!target || ts.isSpreadElement(target)) return;\n if (!isRedirectTainted(target) || checkedByValidator(node)) return;\n\n findings.push(\n name === \"navigateTo\"\n ? unsafeRedirect(target, \"navigation\", \"safeRedirectTarget\", \"@warlock.js/web\")\n : unsafeRedirect(target, \"redirect\", \"safeRedirect\", \"@warlock.js/core\"),\n );\n\n return;\n }\n\n if (!ts.isJsxAttribute(node) || !ts.isIdentifier(node.name)) return;\n if (node.name.text !== \"to\" && node.name.text !== \"href\") return;\n\n const element = node.parent.parent;\n\n if (!ts.isJsxOpeningElement(element) && !ts.isJsxSelfClosingElement(element)) return;\n if (!ts.isIdentifier(element.tagName) || !LINK_COMPONENTS.has(element.tagName.text)) return;\n\n const initializer = node.initializer;\n\n if (!initializer || !ts.isJsxExpression(initializer) || !initializer.expression) return;\n\n const expression = initializer.expression;\n\n if (!isRedirectTainted(expression) || checkedByValidator(expression)) return;\n\n findings.push(unsafeRedirect(expression, \"link\", \"safeRedirectTarget\", \"@warlock.js/web\"));\n}\n\n// ── WL9008: raw emails, credentials and request bodies in logs ──────────────\n\nconst LOGGER_NAMES: ReadonlySet<string> = new Set([\"log\", \"logger\", \"console\"]);\n\nconst LOG_METHODS: ReadonlySet<string> = new Set([\n \"info\",\n \"warn\",\n \"error\",\n \"debug\",\n \"success\",\n \"fatal\",\n \"log\",\n \"assert\",\n \"trace\",\n]);\n\n/** Helpers that make a value safe to log; their arguments are not inspected. */\nconst REDACTORS: ReadonlySet<string> = new Set([\n \"maskEmail\",\n \"maskEmailsInText\",\n \"redact\",\n \"redactHeaders\",\n \"redactError\",\n \"redactUrlCredentials\",\n \"redactQueryCredentials\",\n \"escapeLogValue\",\n \"toLogSnapshot\",\n]);\n\n/** Name endings that mark a value as a credential. */\nconst SECRET_SUFFIXES = [\n \"token\",\n \"password\",\n \"passwd\",\n \"secret\",\n \"apikey\",\n \"authorization\",\n \"cookie\",\n \"cookies\",\n \"otp\",\n \"jwt\",\n \"privatekey\",\n];\n\n/**\n * Whether the logger censors this key by default (`DEFAULT_REDACT_KEYS` from\n * `@warlock.js/logger`). A secret logged under one of them never reaches a\n * channel. Emails are not on that list: they are not censored by default.\n */\nfunction isCensoredKey(key: string): boolean {\n return DEFAULT_REDACT_KEY_SET.has(normalizeRedactKey(key));\n}\n\n/** `email` for addresses, `secret` for credentials, otherwise `undefined`. */\nfunction sensitiveCategory(name: string): \"email\" | \"secret\" | undefined {\n const normalized = normalizeRedactKey(name);\n\n if (normalized.endsWith(\"email\") || normalized.endsWith(\"emailaddress\")) return \"email\";\n if (DEFAULT_REDACT_KEY_SET.has(normalized)) return \"secret\";\n if (SECRET_SUFFIXES.some((suffix) => normalized.endsWith(suffix))) return \"secret\";\n\n return undefined;\n}\n\nfunction describeCategory(category: \"email\" | \"secret\", name: string | undefined): string {\n if (category === \"email\") return \"a raw email address\";\n\n return name ? `the credential \\`${name}\\`` : \"a credential\";\n}\n\nfunction describeMember(member: string): string {\n if (member === \"headers\" || member === \"cookies\") return member;\n\n return `body (\\`${member}\\`)`;\n}\n\n/** `request.all()` / `request.body` itself, not `request.body.title`. */\nfunction isWholeAccess(node: ts.Node, member: string): boolean {\n if (ts.isCallExpression(node)) {\n const callee = unwrap(node.expression);\n return isMemberAccess(callee) && memberName(callee) === member;\n }\n\n return isMemberAccess(node) && memberName(node) === member;\n}\n\ntype LogFinding = { node: ts.Node; what: string };\n\nfunction inspectLogged(node: ts.Node, censoredKey: boolean, found: LogFinding[]): void {\n const value = unwrap(node);\n\n if (isFunctionLike(value)) return;\n\n if (ts.isCallExpression(value)) {\n const name = calleeName(value);\n if (name !== undefined && REDACTORS.has(name)) return;\n }\n\n // request.all() / request.body / request.headers / request.input(\"email\")\n if (ts.isCallExpression(value) || isMemberAccess(value)) {\n const member = requestMemberAccess(value);\n\n if (member !== undefined && isWholeAccess(value, member)) {\n if (REQUEST_BODY_MEMBERS.has(member)) {\n found.push({ node: value, what: `the request ${describeMember(member)}` });\n return;\n }\n\n if (member === \"email\") {\n found.push({ node: value, what: \"a raw email address\" });\n return;\n }\n }\n\n if (ts.isCallExpression(value) && member !== undefined) {\n const key = literalString(value.arguments[0]);\n const category = key ? sensitiveCategory(key) : undefined;\n\n if (category && !(censoredKey && category === \"secret\")) {\n found.push({ node: value, what: describeCategory(category, key) });\n return;\n }\n }\n }\n\n if (ts.isIdentifier(value) || isMemberAccess(value)) {\n const name = ts.isIdentifier(value) ? value.text : memberName(value);\n const category = name ? sensitiveCategory(name) : undefined;\n\n if (category && !(censoredKey && category === \"secret\")) {\n found.push({ node: value, what: describeCategory(category, name) });\n return;\n }\n\n // `request.body.title` reads one field; only the whole body is reported.\n if (isMemberAccess(value) && requestMemberAccess(value) === undefined) {\n inspectLogged(value.expression, false, found);\n\n if (ts.isElementAccessExpression(value))\n inspectLogged(value.argumentExpression, false, found);\n }\n\n return;\n }\n\n if (ts.isObjectLiteralExpression(value)) {\n for (const property of value.properties) {\n if (ts.isSpreadAssignment(property)) {\n inspectLogged(property.expression, false, found);\n } else if (ts.isPropertyAssignment(property)) {\n const key = keyName(property.name);\n inspectLogged(property.initializer, key !== undefined && isCensoredKey(key), found);\n } else if (ts.isShorthandPropertyAssignment(property)) {\n inspectLogged(property.name, isCensoredKey(property.name.text), found);\n }\n }\n\n return;\n }\n\n if (ts.isTemplateExpression(value)) {\n for (const span of value.templateSpans) inspectLogged(span.expression, false, found);\n return;\n }\n\n if (ts.isBinaryExpression(value)) {\n inspectLogged(value.left, false, found);\n inspectLogged(value.right, false, found);\n return;\n }\n\n if (ts.isConditionalExpression(value)) {\n inspectLogged(value.whenTrue, censoredKey, found);\n inspectLogged(value.whenFalse, censoredKey, found);\n return;\n }\n\n if (ts.isArrayLiteralExpression(value)) {\n for (const element of value.elements) {\n if (ts.isOmittedExpression(element)) continue;\n inspectLogged(ts.isSpreadElement(element) ? element.expression : element, false, found);\n }\n\n return;\n }\n\n if (ts.isCallExpression(value)) {\n // JSON.stringify(request.all()), String(user.email), user.email.trim()\n const callee = unwrap(value.expression);\n\n if (isMemberAccess(callee)) inspectLogged(callee.expression, false, found);\n\n for (const argument of value.arguments) {\n inspectLogged(ts.isSpreadElement(argument) ? argument.expression : argument, false, found);\n }\n\n return;\n }\n\n if (ts.isAwaitExpression(value)) inspectLogged(value.expression, censoredKey, found);\n}\n\nfunction checkSensitiveLog(node: ts.Node, findings: SourceFinding[]): void {\n if (!ts.isCallExpression(node)) return;\n\n const callee = unwrap(node.expression);\n\n if (!isMemberAccess(callee)) return;\n\n const method = memberName(callee);\n\n if (!method || !LOG_METHODS.has(method)) return;\n\n const owner = unwrap(callee.expression);\n\n if (!ts.isIdentifier(owner)) return;\n\n // log.info(…), console.log(…), and request.log(…)\n const isLogger =\n LOGGER_NAMES.has(owner.text) || (REQUEST_NAMES.has(owner.text) && method === \"log\");\n\n if (!isLogger) return;\n\n const found: LogFinding[] = [];\n\n for (const argument of node.arguments) {\n inspectLogged(ts.isSpreadElement(argument) ? argument.expression : argument, false, found);\n }\n\n for (const finding of found) {\n findings.push({\n code: \"WL9008\",\n node: finding.node,\n message: `Do not log ${finding.what} as-is. Pass it through a redaction helper (\\`maskEmail()\\`, \\`redact()\\`, \\`request.toLogSnapshot()\\`), or log it under a key the logger censors.`,\n });\n }\n}\n\n// ── WL9009: unbounded regex quantifiers on request input ────────────────────\n\n/** `regex.test(input)` / `regex.exec(input)`. */\nconst REGEX_METHODS: ReadonlySet<string> = new Set([\"test\", \"exec\"]);\n\n/** `input.match(regex)` and friends: the regex is the first argument. */\nconst STRING_METHODS: ReadonlySet<string> = new Set([\n \"match\",\n \"matchAll\",\n \"replace\",\n \"replaceAll\",\n \"search\",\n \"split\",\n]);\n\n/**\n * The first unbounded quantifier in a regex source (`*`, `+`, `{n,}`), skipping\n * escapes and character classes, or `undefined` when every repetition is\n * bounded.\n */\nexport function findUnboundedQuantifier(source: string): string | undefined {\n let inClass = false;\n\n for (let index = 0; index < source.length; index++) {\n const char = source[index];\n\n if (char === \"\\\\\") {\n index++;\n continue;\n }\n\n if (inClass) {\n if (char === \"]\") inClass = false;\n continue;\n }\n\n if (char === \"[\") {\n inClass = true;\n continue;\n }\n\n if (char === \"*\" || char === \"+\") {\n return `${char}${source[index + 1] === \"?\" ? \"?\" : \"\"}`;\n }\n\n if (char === \"{\") {\n const match = /^\\{(\\d+),\\}/.exec(source.slice(index));\n if (match) return match[0];\n }\n }\n\n return undefined;\n}\n\n/** The pattern of a regex literal, `new RegExp(\"…\")`, or a constant holding either. */\nfunction regexSource(node: ts.Node | undefined, depth = 0): string | undefined {\n if (!node || depth > 8) return undefined;\n\n const value = unwrap(node);\n\n if (ts.isRegularExpressionLiteral(value)) {\n return value.text.slice(1, value.text.lastIndexOf(\"/\"));\n }\n\n if (\n (ts.isNewExpression(value) || ts.isCallExpression(value)) &&\n ts.isIdentifier(value.expression) &&\n value.expression.text === \"RegExp\"\n ) {\n return literalString(value.arguments?.[0]);\n }\n\n if (ts.isIdentifier(value)) {\n const initializer = resolveInitializer(value);\n return initializer ? regexSource(initializer, depth + 1) : undefined;\n }\n\n return undefined;\n}\n\nfunction checkUnboundedRegex(node: ts.Node, findings: SourceFinding[]): void {\n if (!ts.isCallExpression(node)) return;\n\n const callee = unwrap(node.expression);\n\n if (!isMemberAccess(callee)) return;\n\n const method = memberName(callee);\n\n if (!method) return;\n\n const first = node.arguments[0];\n const firstArgument = first && !ts.isSpreadElement(first) ? first : undefined;\n let regex: ts.Node | undefined;\n let input: ts.Node | undefined;\n\n if (REGEX_METHODS.has(method)) {\n regex = callee.expression;\n input = firstArgument;\n } else if (STRING_METHODS.has(method)) {\n regex = firstArgument;\n input = callee.expression;\n } else {\n return;\n }\n\n if (!input) return;\n\n const source = regexSource(regex);\n\n if (source === undefined) return;\n\n const quantifier = findUnboundedQuantifier(source);\n\n if (!quantifier || !containsRequestInput(input)) return;\n\n findings.push({\n code: \"WL9009\",\n node,\n message: `This regex has an unbounded quantifier (\\`${quantifier}\\`) and runs on request input, so a crafted input can make it backtrack for a long time (ReDoS). Bound the repetition, e.g. \\`{1,256}\\`, or cap the input length before matching.`,\n });\n}\n\n/**\n * The security conventions in one parsed file:\n *\n * - `WL9005` `request.all()` (or `heavy()`, `allExceptParams()`) passed to a\n * query, a service or `inApp()`;\n * - `WL9006` a POST/PUT/PATCH/DELETE route with no auth middleware and no\n * `public: true`;\n * - `WL9007` a `redirect()` / `navigateTo()` / `<Link to|href>` target taken\n * from request input without `safeRedirect()` / `safeRedirectTarget()` or an\n * `isSafeRedirect()` check;\n * - `WL9008` a raw email, credential or request body passed to a logger;\n * - `WL9009` a regex with an unbounded quantifier run on request input.\n */\nexport function securityFindings(sourceFile: ts.SourceFile): SourceFinding[] {\n const findings: SourceFinding[] = [];\n\n walk(\n sourceFile,\n (node) => {\n checkRequestAll(node, findings);\n checkRouteGuard(node, findings);\n checkRedirect(node, findings);\n checkSensitiveLog(node, findings);\n checkUnboundedRegex(node, findings);\n\n return undefined;\n },\n true,\n );\n\n return findings;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"security-conventions.mjs","names":["ast.isIdentifier","ast.valueText","ast.expressionOf","ast.parentOf","ast.isCallExpression","ast.isNewExpression","ast.isSpreadElement","ast.isSpreadAssignment","ast.isObjectLiteralExpression","ast.isArrayLiteralExpression","ast.isPropertyAssignment","ast.isShorthandPropertyAssignment","ast.isAsExpression","ast.isNonNullExpression","ast.isSatisfiesExpression","ast.isTypeAssertionExpression","ast.isParenthesizedExpression","ast.isAwaitExpression","ast.isVariableDeclaration","ast.isArrowFunction","ast.isFunctionExpression","ast.isIfStatement","ast.isConditionalExpression","ast.isJsxAttribute","ast.nameNode","ast.isJsxOpeningElement","ast.isJsxSelfClosingElement","ast.isJsxExpression","ast.isElementAccessExpression","ast.isTemplateExpression","ast.isBinaryExpression","ast.isOmittedExpression","ast.isRegularExpressionLiteral"],"sources":["../../../../../../../../../packages/core/src/tooling/check/security-conventions.ts"],"sourcesContent":["import { DEFAULT_REDACT_KEY_SET, normalizeRedactKey } from \"@warlock.js/logger\";\nimport * as ast from \"../syntax/ast\";\nimport { isAuthGuardName, isMutatingHttpMethod } from \"../../router/route-guard-names\";\nimport {\n containsRequestInput,\n REQUEST_BODY_MEMBERS,\n REQUEST_NAMES,\n requestMemberAccess,\n} from \"./request-input\";\nimport {\n ancestors,\n calleeName,\n isFunctionLike,\n isMemberAccess,\n keyName,\n literalString,\n memberName,\n referencesOf,\n resolveInitializer,\n rootIdentifier,\n type SourceFinding,\n unwrap,\n walk,\n} from \"./source-ast\";\n\n// ── WL9005: request.all() into a query, a service or inApp() ────────────────\n\n/** Request methods that return every input the client sent, validated or not. */\nconst UNFILTERED_METHODS: ReadonlySet<string> = new Set([\n \"all\",\n \"allExceptParams\",\n \"heavy\",\n \"heavyExceptParams\",\n]);\n\n/**\n * Responses and loggers are not the data sinks `WL9005` guards: echoing input\n * back is not mass assignment, and logging it is `WL9008`'s concern.\n */\nconst IGNORED_RECEIVERS: ReadonlySet<string> = new Set([\n \"response\",\n \"reply\",\n \"res\",\n \"console\",\n \"log\",\n \"logger\",\n]);\n\nfunction displayCallee(callee: ast.Node): string {\n const target = unwrap(callee);\n\n if (ast.isIdentifier(target)) return `${ast.valueText(target)}()`;\n\n if (isMemberAccess(target)) {\n const name = memberName(target);\n const object = unwrap(ast.expressionOf(target));\n const owner = ast.isIdentifier(object) ? `${ast.valueText(object)}.` : \"\";\n\n return name ? `${owner}${name}()` : \"a call\";\n }\n\n return \"a call\";\n}\n\nfunction isIgnoredReceiver(callee: ast.Node): boolean {\n const target = unwrap(callee);\n\n if (!isMemberAccess(target)) return false;\n\n const object = unwrap(ast.expressionOf(target));\n\n return ast.isIdentifier(object) && IGNORED_RECEIVERS.has(ast.valueText(object));\n}\n\n/** When `node` flows into a call's arguments, the callee's display name. */\nfunction callReceiving(node: ast.Node): string | undefined {\n let current = node;\n\n for (;;) {\n const parent = ast.parentOf(current);\n\n if (!parent) return undefined;\n\n if (ast.isCallExpression(parent) || ast.isNewExpression(parent)) {\n if (!(parent.arguments ?? []).some((argument) => argument === current)) return undefined;\n if (isIgnoredReceiver(ast.expressionOf(parent))) return undefined;\n\n return displayCallee(ast.expressionOf(parent));\n }\n\n if (\n ast.isSpreadElement(parent) ||\n ast.isSpreadAssignment(parent) ||\n ast.isObjectLiteralExpression(parent) ||\n ast.isArrayLiteralExpression(parent) ||\n (ast.isPropertyAssignment(parent) && parent.value === current) ||\n ast.isShorthandPropertyAssignment(parent) ||\n ast.isAsExpression(parent) ||\n ast.isNonNullExpression(parent) ||\n ast.isSatisfiesExpression(parent) ||\n ast.isTypeAssertionExpression(parent) ||\n ast.isParenthesizedExpression(parent) ||\n ast.isAwaitExpression(parent)\n ) {\n current = parent;\n continue;\n }\n\n return undefined;\n }\n}\n\n/**\n * The call that ends up receiving this value: directly as an argument, spread\n * into an object/array argument, or through a local constant later passed to\n * a call.\n */\nfunction receivingCall(node: ast.Node): string | undefined {\n const direct = callReceiving(node);\n\n if (direct) return direct;\n\n // `const data = request.all(); await Model.create(data);`\n const parent = ast.parentOf(node);\n\n if (\n parent &&\n ast.isVariableDeclaration(parent) &&\n parent.init === node &&\n ast.isIdentifier(parent.id)\n ) {\n for (const reference of referencesOf(parent)) {\n const name = callReceiving(reference);\n if (name) return name;\n }\n }\n\n return undefined;\n}\n\nfunction checkRequestAll(node: ast.Node, findings: SourceFinding[]): void {\n if (!ast.isCallExpression(node)) return;\n\n const callee = unwrap(ast.expressionOf(node));\n\n if (!isMemberAccess(callee)) return;\n\n const object = unwrap(ast.expressionOf(callee));\n\n if (!ast.isIdentifier(object) || !REQUEST_NAMES.has(ast.valueText(object))) return;\n\n const method = memberName(callee);\n\n if (!method || !UNFILTERED_METHODS.has(method)) return;\n\n const target = receivingCall(node);\n\n if (!target) return;\n\n findings.push({\n code: \"WL9005\",\n node,\n message: `\\`${ast.valueText(object)}.${method}()\\` passes every client-sent field to \\`${target}\\`. Use \\`${ast.valueText(object)}.validated()\\` so only the fields the validation schema accepted reach it.`,\n });\n}\n\n// ── WL9006: a mutating route with no auth guard and no public: true ─────────\n\nconst ROUTER_NAMES: ReadonlySet<string> = new Set([\"router\"]);\n\n/** Wrappers whose callback routes are guarded, e.g. `guarded(() => …)`. */\nconst GUARD_FUNCTIONS: ReadonlySet<string> = new Set([\"guarded\"]);\n\n/** `router.post(…)` and friends. */\nconst MUTATING_ROUTER_METHODS: ReadonlySet<string> = new Set([\"post\", \"put\", \"patch\", \"delete\"]);\n\n/** Route builder methods (`router.route(path).create(…)`) that register a mutating route. */\nconst MUTATING_BUILDER_METHODS: ReadonlySet<string> = new Set([\n \"post\",\n \"postOne\",\n \"put\",\n \"updateOne\",\n \"patch\",\n \"patchOne\",\n \"delete\",\n \"deleteOne\",\n \"create\",\n \"update\",\n \"destroy\",\n]);\n\nconst READ_ONLY_RESOURCE_METHODS: ReadonlySet<string> = new Set([\"list\", \"get\", \"show\"]);\n\nfunction isRouter(node: ast.Node): boolean {\n const target = unwrap(node);\n\n return ast.isIdentifier(target) && ROUTER_NAMES.has(ast.valueText(target));\n}\n\nfunction isGuardName(name: string | undefined): boolean {\n return name !== undefined && isAuthGuardName(name);\n}\n\n/** Whether a constant is initialised with `markAuthGuard(fn)` (not `markAuthGuard(fn, false)`). */\nfunction isMarkedGuard(identifier: ast.Identifier): boolean {\n const initializer = resolveInitializer(identifier);\n const value = initializer ? unwrap(initializer) : undefined;\n\n return (\n value !== undefined &&\n ast.isCallExpression(value) &&\n calleeName(value) === \"markAuthGuard\" &&\n !(value.arguments[1]?.type === \"Literal\" && value.arguments[1].value === false)\n );\n}\n\nfunction middlewareHasGuard(node: ast.Node): boolean {\n const value = unwrap(node);\n\n // A variable or a call: the check cannot see into it, so it trusts it.\n if (!ast.isArrayLiteralExpression(value)) return true;\n\n return value.elements.some((element) => {\n if (!element) return false;\n if (ast.isSpreadElement(element)) return true;\n\n const item = unwrap(element);\n\n if (ast.isIdentifier(item)) return isGuardName(ast.valueText(item)) || isMarkedGuard(item);\n if (ast.isCallExpression(item)) return isGuardName(calleeName(item));\n if (isMemberAccess(item)) return isGuardName(memberName(item));\n\n return false;\n });\n}\n\n/** `public: true`, a guard in `middleware`, or an options value the check cannot see into. */\nfunction optionsGuard(node: ast.Node | undefined): \"guarded\" | \"unguarded\" | \"none\" {\n if (!node) return \"none\";\n\n const value = unwrap(node);\n\n if (!ast.isObjectLiteralExpression(value)) return \"guarded\";\n\n let verdict: \"guarded\" | \"unguarded\" = \"unguarded\";\n\n for (const property of value.properties) {\n if (ast.isSpreadAssignment(property)) {\n verdict = \"guarded\";\n continue;\n }\n\n let key: string | undefined;\n let propertyValue: ast.Node | undefined;\n\n if (ast.isPropertyAssignment(property)) {\n key = keyName(property.key);\n propertyValue = unwrap(property.value);\n } else if (ast.isShorthandPropertyAssignment(property)) {\n key = ast.valueText(property.key);\n propertyValue = property.key;\n }\n\n if (!propertyValue) continue;\n if (key === \"public\" && propertyValue.type === \"Literal\" && propertyValue.value === true)\n return \"guarded\";\n if (key === \"middleware\" && middlewareHasGuard(propertyValue)) return \"guarded\";\n }\n\n return verdict;\n}\n\n/** Whether an enclosing function is a guarded (or public) group callback. */\nfunction insideGuardedGroup(node: ast.Node): boolean {\n for (const ancestor of ancestors(node)) {\n if (!ast.isArrowFunction(ancestor) && !ast.isFunctionExpression(ancestor)) continue;\n\n const parent = ast.parentOf(ancestor);\n\n if (!parent || !ast.isCallExpression(parent)) continue;\n if (!parent.arguments.some((argument) => argument === ancestor)) continue;\n\n const name = calleeName(parent);\n\n if (name !== undefined && GUARD_FUNCTIONS.has(name)) return true;\n\n const callee = unwrap(ast.expressionOf(parent));\n\n if (\n isMemberAccess(callee) &&\n memberName(callee) === \"group\" &&\n isRouter(ast.expressionOf(callee)) &&\n optionsGuard(parent.arguments[0]) === \"guarded\"\n ) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction pathText(node: ast.Node | undefined): string {\n return literalString(node) ?? \"(dynamic path)\";\n}\n\n/**\n * Walk a builder chain back to `router.route(path, options)`, collecting every\n * options object passed along the way (`route()`, `nest()`).\n */\nfunction builderChain(node: ast.Node): { path: string; optionNodes: ast.Node[] } | undefined {\n const optionNodes: ast.Node[] = [];\n let current = unwrap(node);\n\n while (ast.isCallExpression(current)) {\n const callee = unwrap(ast.expressionOf(current));\n\n if (!isMemberAccess(callee)) return undefined;\n\n const name = memberName(callee);\n\n if (name === \"route\" && isRouter(ast.expressionOf(callee))) {\n const options = current.arguments[1];\n if (options) optionNodes.push(options);\n\n return { path: pathText(current.arguments[0]), optionNodes };\n }\n\n if (name === \"nest\") {\n const options = current.arguments[1];\n if (options) optionNodes.push(options);\n }\n\n current = unwrap(ast.expressionOf(callee));\n }\n\n return undefined;\n}\n\nfunction resourceIsReadOnly(node: ast.Node | undefined): boolean {\n if (!node) return false;\n\n const value = unwrap(node);\n\n if (!ast.isObjectLiteralExpression(value)) return false;\n\n for (const property of value.properties) {\n if (!ast.isPropertyAssignment(property) || keyName(property.key) !== \"only\") continue;\n\n const only = unwrap(property.value);\n\n if (!ast.isArrayLiteralExpression(only)) return false;\n\n return only.elements.every((element) => {\n if (!element) return false;\n const method = literalString(element);\n return method !== undefined && READ_ONLY_RESOURCE_METHODS.has(method);\n });\n }\n\n return false;\n}\n\nfunction unguardedRoute(node: ast.Node, route: string): SourceFinding {\n return {\n code: \"WL9006\",\n node,\n message: `Mutating route \\`${route}\\` has no auth middleware. Add an auth guard (\\`middleware: [authMiddleware()]\\`, or register it inside a guarded group) or mark it intentionally open with \\`public: true\\`.`,\n };\n}\n\nfunction checkRouteGuard(node: ast.Node, findings: SourceFinding[]): void {\n if (!ast.isCallExpression(node)) return;\n\n const callee = unwrap(ast.expressionOf(node));\n\n if (!isMemberAccess(callee)) return;\n\n const method = memberName(callee);\n\n if (!method) return;\n\n const guarded = (options: ast.Node | undefined) =>\n optionsGuard(options) === \"guarded\" || insideGuardedGroup(node);\n\n if (isRouter(ast.expressionOf(callee))) {\n // router.post(path, handler, options)\n if (MUTATING_ROUTER_METHODS.has(method)) {\n if (!guarded(node.arguments[2])) {\n findings.push(\n unguardedRoute(node, `${method.toUpperCase()} ${pathText(node.arguments[0])}`),\n );\n }\n\n return;\n }\n\n // router.add(\"POST\", path, handler, options)\n if (method === \"add\") {\n const httpMethod = literalString(node.arguments[0])?.toUpperCase();\n\n if (!httpMethod || !isMutatingHttpMethod(httpMethod)) return;\n\n if (!guarded(node.arguments[3])) {\n findings.push(unguardedRoute(node, `${httpMethod} ${pathText(node.arguments[1])}`));\n }\n\n return;\n }\n\n // router.restfulResource(path, resource, options)\n if (method === \"restfulResource\") {\n if (resourceIsReadOnly(node.arguments[2])) return;\n\n if (!guarded(node.arguments[2])) {\n findings.push(unguardedRoute(node, `resource ${pathText(node.arguments[0])}`));\n }\n }\n\n return;\n }\n\n // router.route(path, options).create(handler, options)\n if (!MUTATING_BUILDER_METHODS.has(method)) return;\n\n const chain = builderChain(ast.expressionOf(callee));\n\n if (!chain) return;\n if (optionsGuard(node.arguments[1]) === \"guarded\") return;\n if (chain.optionNodes.some((options) => optionsGuard(options) === \"guarded\")) return;\n if (insideGuardedGroup(node)) return;\n\n findings.push(unguardedRoute(node, `${method} ${chain.path}`));\n}\n\n// ── WL9007: a redirect or link target from request input ────────────────────\n\n/** Calls that turn their first argument into a redirect or a navigation. */\nconst REDIRECT_CALLS: ReadonlySet<string> = new Set([\n \"redirect\",\n \"permanentRedirect\",\n \"navigateTo\",\n]);\n\n/** Components whose `to`/`href` prop navigates. */\nconst LINK_COMPONENTS: ReadonlySet<string> = new Set([\"Link\", \"NavLink\"]);\n\n/** Helpers that return an allowed target (or a fallback) for any input. */\nconst REDIRECT_SANITIZERS: ReadonlySet<string> = new Set([\"safeRedirect\", \"safeRedirectTarget\"]);\n\n/** Predicates that, used in an enclosing `if` or `? :`, prove the target was checked. */\nconst REDIRECT_VALIDATORS: ReadonlySet<string> = new Set([\"isSafeRedirect\", \"isSafeRedirectUrl\"]);\n\n/** Client-side input: query-string hooks. */\nconst CLIENT_INPUT_CALLS: ReadonlySet<string> = new Set([\n \"useQueryString\",\n \"useSearchParams\",\n \"useParams\",\n]);\n\n/** Identifiers whose members are client-controlled (a loader's `query`, URLSearchParams). */\nconst CLIENT_INPUT_NAMES: ReadonlySet<string> = new Set([\"query\", \"searchParams\"]);\n\nfunction isClientSource(node: ast.Node): boolean {\n if (ast.isCallExpression(node)) {\n const name = calleeName(node);\n if (name !== undefined && CLIENT_INPUT_CALLS.has(name)) return true;\n }\n\n if (isMemberAccess(node)) {\n const root = rootIdentifier(node);\n\n if (root && CLIENT_INPUT_NAMES.has(ast.valueText(root))) return true;\n\n // location.search / window.location.hash\n const name = memberName(node);\n\n if (name === \"search\" || name === \"hash\") {\n const object = unwrap(ast.expressionOf(node));\n\n if (ast.isIdentifier(object) && ast.valueText(object) === \"location\") return true;\n if (isMemberAccess(object) && memberName(object) === \"location\") return true;\n }\n }\n\n return false;\n}\n\nfunction isRedirectTainted(node: ast.Node): boolean {\n return containsRequestInput(node, { sanitizers: REDIRECT_SANITIZERS, isSource: isClientSource });\n}\n\n/** An enclosing `if (isSafeRedirect(x))` or `isSafeRedirect(x) ? … : …` validated the target. */\nfunction checkedByValidator(node: ast.Node): boolean {\n for (const ancestor of ancestors(node)) {\n let test: ast.Node | undefined;\n\n if (ast.isIfStatement(ancestor)) test = ast.expressionOf(ancestor);\n else if (ast.isConditionalExpression(ancestor)) test = ancestor.test;\n else continue;\n\n let validated = false;\n\n walk(test, (child) => {\n if (ast.isCallExpression(child)) {\n const name = calleeName(child);\n if (name !== undefined && REDIRECT_VALIDATORS.has(name)) validated = true;\n }\n\n return undefined;\n });\n\n if (validated) return true;\n }\n\n return false;\n}\n\nfunction unsafeRedirect(node: ast.Node, what: string, helper: string, from: string): SourceFinding {\n return {\n code: \"WL9007\",\n node,\n message: `This ${what} target comes from request input. Pass it through \\`${helper}()\\` from \\`${from}\\` so only same-origin paths and allow-listed origins are followed (open redirects and \\`javascript:\\` URLs otherwise).`,\n };\n}\n\nfunction checkRedirect(node: ast.Node, findings: SourceFinding[]): void {\n if (ast.isCallExpression(node)) {\n const name = calleeName(node);\n\n if (name === undefined || !REDIRECT_CALLS.has(name)) return;\n\n // `router.redirect(from, to)` registers a static redirect, not a request-time one.\n const callee = unwrap(ast.expressionOf(node));\n\n if (isMemberAccess(callee)) {\n const owner = unwrap(ast.expressionOf(callee));\n if (ast.isIdentifier(owner) && ast.valueText(owner) === \"router\") return;\n }\n\n const target = node.arguments[0];\n\n if (!target || ast.isSpreadElement(target)) return;\n if (!isRedirectTainted(target) || checkedByValidator(node)) return;\n\n findings.push(\n name === \"navigateTo\"\n ? unsafeRedirect(target, \"navigation\", \"safeRedirectTarget\", \"@warlock.js/web\")\n : unsafeRedirect(target, \"redirect\", \"safeRedirect\", \"@warlock.js/core\"),\n );\n\n return;\n }\n\n if (!ast.isJsxAttribute(node) || ast.nameNode(node).type !== \"JSXIdentifier\") return;\n if (ast.valueText(ast.nameNode(node)) !== \"to\" && ast.valueText(ast.nameNode(node)) !== \"href\")\n return;\n\n const element = ast.parentOf(node);\n\n if (!element || (!ast.isJsxOpeningElement(element) && !ast.isJsxSelfClosingElement(element)))\n return;\n if (element.name.type !== \"JSXIdentifier\" || !LINK_COMPONENTS.has(element.name.name)) return;\n\n const initializer = node.value;\n\n if (!initializer || !ast.isJsxExpression(initializer) || !initializer.expression) return;\n\n const expression = initializer.expression;\n\n if (!isRedirectTainted(expression) || checkedByValidator(expression)) return;\n\n findings.push(unsafeRedirect(expression, \"link\", \"safeRedirectTarget\", \"@warlock.js/web\"));\n}\n\n// ── WL9008: raw emails, credentials and request bodies in logs ──────────────\n\nconst LOGGER_NAMES: ReadonlySet<string> = new Set([\"log\", \"logger\", \"console\"]);\n\nconst LOG_METHODS: ReadonlySet<string> = new Set([\n \"info\",\n \"warn\",\n \"error\",\n \"debug\",\n \"success\",\n \"fatal\",\n \"log\",\n \"assert\",\n \"trace\",\n]);\n\n/** Helpers that make a value safe to log; their arguments are not inspected. */\nconst REDACTORS: ReadonlySet<string> = new Set([\n \"maskEmail\",\n \"maskEmailsInText\",\n \"redact\",\n \"redactHeaders\",\n \"redactError\",\n \"redactUrlCredentials\",\n \"redactQueryCredentials\",\n \"escapeLogValue\",\n \"toLogSnapshot\",\n]);\n\n/** Name endings that mark a value as a credential. */\nconst SECRET_SUFFIXES = [\n \"token\",\n \"password\",\n \"passwd\",\n \"secret\",\n \"apikey\",\n \"authorization\",\n \"cookie\",\n \"cookies\",\n \"otp\",\n \"jwt\",\n \"privatekey\",\n];\n\n/**\n * Whether the logger censors this key by default (`DEFAULT_REDACT_KEYS` from\n * `@warlock.js/logger`). A secret logged under one of them never reaches a\n * channel. Emails are not on that list: they are not censored by default.\n */\nfunction isCensoredKey(key: string): boolean {\n return DEFAULT_REDACT_KEY_SET.has(normalizeRedactKey(key));\n}\n\n/** `email` for addresses, `secret` for credentials, otherwise `undefined`. */\nfunction sensitiveCategory(name: string): \"email\" | \"secret\" | undefined {\n const normalized = normalizeRedactKey(name);\n\n if (normalized.endsWith(\"email\") || normalized.endsWith(\"emailaddress\")) return \"email\";\n if (DEFAULT_REDACT_KEY_SET.has(normalized)) return \"secret\";\n if (SECRET_SUFFIXES.some((suffix) => normalized.endsWith(suffix))) return \"secret\";\n\n return undefined;\n}\n\nfunction describeCategory(category: \"email\" | \"secret\", name: string | undefined): string {\n if (category === \"email\") return \"a raw email address\";\n\n return name ? `the credential \\`${name}\\`` : \"a credential\";\n}\n\nfunction describeMember(member: string): string {\n if (member === \"headers\" || member === \"cookies\") return member;\n\n return `body (\\`${member}\\`)`;\n}\n\n/** `request.all()` / `request.body` itself, not `request.body.title`. */\nfunction isWholeAccess(node: ast.Node, member: string): boolean {\n if (ast.isCallExpression(node)) {\n const callee = unwrap(ast.expressionOf(node));\n return isMemberAccess(callee) && memberName(callee) === member;\n }\n\n return isMemberAccess(node) && memberName(node) === member;\n}\n\ntype LogFinding = { node: ast.Node; what: string };\n\nfunction inspectLogged(node: ast.Node, censoredKey: boolean, found: LogFinding[]): void {\n const value = unwrap(node);\n\n if (isFunctionLike(value)) return;\n\n if (ast.isCallExpression(value)) {\n const name = calleeName(value);\n if (name !== undefined && REDACTORS.has(name)) return;\n }\n\n // request.all() / request.body / request.headers / request.input(\"email\")\n if (ast.isCallExpression(value) || isMemberAccess(value)) {\n const member = requestMemberAccess(value);\n\n if (member !== undefined && isWholeAccess(value, member)) {\n if (REQUEST_BODY_MEMBERS.has(member)) {\n found.push({ node: value, what: `the request ${describeMember(member)}` });\n return;\n }\n\n if (member === \"email\") {\n found.push({ node: value, what: \"a raw email address\" });\n return;\n }\n }\n\n if (ast.isCallExpression(value) && member !== undefined) {\n const key = literalString(value.arguments[0]);\n const category = key ? sensitiveCategory(key) : undefined;\n\n if (category && !(censoredKey && category === \"secret\")) {\n found.push({ node: value, what: describeCategory(category, key) });\n return;\n }\n }\n }\n\n if (ast.isIdentifier(value) || isMemberAccess(value)) {\n const name = ast.isIdentifier(value) ? ast.valueText(value) : memberName(value);\n const category = name ? sensitiveCategory(name) : undefined;\n\n if (category && !(censoredKey && category === \"secret\")) {\n found.push({ node: value, what: describeCategory(category, name) });\n return;\n }\n\n // `request.body.title` reads one field; only the whole body is reported.\n if (isMemberAccess(value) && requestMemberAccess(value) === undefined) {\n inspectLogged(ast.expressionOf(value), false, found);\n\n if (ast.isElementAccessExpression(value)) inspectLogged(value.property, false, found);\n }\n\n return;\n }\n\n if (ast.isObjectLiteralExpression(value)) {\n for (const property of value.properties) {\n if (ast.isSpreadAssignment(property)) {\n inspectLogged(ast.expressionOf(property), false, found);\n } else if (ast.isPropertyAssignment(property)) {\n const key = keyName(property.key);\n inspectLogged(property.value, key !== undefined && isCensoredKey(key), found);\n } else if (ast.isShorthandPropertyAssignment(property)) {\n inspectLogged(property.key, isCensoredKey(ast.valueText(property.key)), found);\n }\n }\n\n return;\n }\n\n if (ast.isTemplateExpression(value)) {\n for (const expression of value.expressions) inspectLogged(expression, false, found);\n return;\n }\n\n if (ast.isBinaryExpression(value)) {\n inspectLogged(value.left, false, found);\n inspectLogged(value.right, false, found);\n return;\n }\n\n if (ast.isConditionalExpression(value)) {\n inspectLogged(value.consequent, censoredKey, found);\n inspectLogged(value.alternate, censoredKey, found);\n return;\n }\n\n if (ast.isArrayLiteralExpression(value)) {\n for (const element of value.elements) {\n if (ast.isOmittedExpression(element)) continue;\n inspectLogged(\n ast.isSpreadElement(element) ? ast.expressionOf(element) : element,\n false,\n found,\n );\n }\n\n return;\n }\n\n if (ast.isCallExpression(value)) {\n // JSON.stringify(request.all()), String(user.email), user.email.trim()\n const callee = unwrap(ast.expressionOf(value));\n\n if (isMemberAccess(callee)) inspectLogged(ast.expressionOf(callee), false, found);\n\n for (const argument of value.arguments) {\n inspectLogged(\n ast.isSpreadElement(argument) ? ast.expressionOf(argument) : argument,\n false,\n found,\n );\n }\n\n return;\n }\n\n if (ast.isAwaitExpression(value)) inspectLogged(ast.expressionOf(value), censoredKey, found);\n}\n\nfunction checkSensitiveLog(node: ast.Node, findings: SourceFinding[]): void {\n if (!ast.isCallExpression(node)) return;\n\n const callee = unwrap(ast.expressionOf(node));\n\n if (!isMemberAccess(callee)) return;\n\n const method = memberName(callee);\n\n if (!method || !LOG_METHODS.has(method)) return;\n\n const owner = unwrap(ast.expressionOf(callee));\n\n if (!ast.isIdentifier(owner)) return;\n\n // log.info(…), console.log(…), and request.log(…)\n const isLogger =\n LOGGER_NAMES.has(ast.valueText(owner)) ||\n (REQUEST_NAMES.has(ast.valueText(owner)) && method === \"log\");\n\n if (!isLogger) return;\n\n const found: LogFinding[] = [];\n\n for (const argument of node.arguments) {\n inspectLogged(\n ast.isSpreadElement(argument) ? ast.expressionOf(argument) : argument,\n false,\n found,\n );\n }\n\n for (const finding of found) {\n findings.push({\n code: \"WL9008\",\n node: finding.node,\n message: `Do not log ${finding.what} as-is. Pass it through a redaction helper (\\`maskEmail()\\`, \\`redact()\\`, \\`request.toLogSnapshot()\\`), or log it under a key the logger censors.`,\n });\n }\n}\n\n// ── WL9009: unbounded regex quantifiers on request input ────────────────────\n\n/** `regex.test(input)` / `regex.exec(input)`. */\nconst REGEX_METHODS: ReadonlySet<string> = new Set([\"test\", \"exec\"]);\n\n/** `input.match(regex)` and friends: the regex is the first argument. */\nconst STRING_METHODS: ReadonlySet<string> = new Set([\n \"match\",\n \"matchAll\",\n \"replace\",\n \"replaceAll\",\n \"search\",\n \"split\",\n]);\n\n/**\n * The first unbounded quantifier in a regex source (`*`, `+`, `{n,}`), skipping\n * escapes and character classes, or `undefined` when every repetition is\n * bounded.\n */\nexport function findUnboundedQuantifier(source: string): string | undefined {\n let inClass = false;\n\n for (let index = 0; index < source.length; index++) {\n const char = source[index];\n\n if (char === \"\\\\\") {\n index++;\n continue;\n }\n\n if (inClass) {\n if (char === \"]\") inClass = false;\n continue;\n }\n\n if (char === \"[\") {\n inClass = true;\n continue;\n }\n\n if (char === \"*\" || char === \"+\") {\n return `${char}${source[index + 1] === \"?\" ? \"?\" : \"\"}`;\n }\n\n if (char === \"{\") {\n const match = /^\\{(\\d+),\\}/.exec(source.slice(index));\n if (match) return match[0];\n }\n }\n\n return undefined;\n}\n\n/** The pattern of a regex literal, `new RegExp(\"…\")`, or a constant holding either. */\nfunction regexSource(node: ast.Node | undefined, depth = 0): string | undefined {\n if (!node || depth > 8) return undefined;\n\n const value = unwrap(node);\n\n if (ast.isRegularExpressionLiteral(value)) {\n return ast.valueText(value).slice(1, ast.valueText(value).lastIndexOf(\"/\"));\n }\n\n if (\n (ast.isNewExpression(value) || ast.isCallExpression(value)) &&\n ast.isIdentifier(ast.expressionOf(value)) &&\n ast.valueText(ast.expressionOf(value)) === \"RegExp\"\n ) {\n return literalString(value.arguments?.[0]);\n }\n\n if (ast.isIdentifier(value)) {\n const initializer = resolveInitializer(value);\n return initializer ? regexSource(initializer, depth + 1) : undefined;\n }\n\n return undefined;\n}\n\nfunction checkUnboundedRegex(node: ast.Node, findings: SourceFinding[]): void {\n if (!ast.isCallExpression(node)) return;\n\n const callee = unwrap(ast.expressionOf(node));\n\n if (!isMemberAccess(callee)) return;\n\n const method = memberName(callee);\n\n if (!method) return;\n\n const first = node.arguments[0];\n const firstArgument = first && !ast.isSpreadElement(first) ? first : undefined;\n let regex: ast.Node | undefined;\n let input: ast.Node | undefined;\n\n if (REGEX_METHODS.has(method)) {\n regex = ast.expressionOf(callee);\n input = firstArgument;\n } else if (STRING_METHODS.has(method)) {\n regex = firstArgument;\n input = ast.expressionOf(callee);\n } else {\n return;\n }\n\n if (!input) return;\n\n const source = regexSource(regex);\n\n if (source === undefined) return;\n\n const quantifier = findUnboundedQuantifier(source);\n\n if (!quantifier || !containsRequestInput(input)) return;\n\n findings.push({\n code: \"WL9009\",\n node,\n message: `This regex has an unbounded quantifier (\\`${quantifier}\\`) and runs on request input, so a crafted input can make it backtrack for a long time (ReDoS). Bound the repetition, e.g. \\`{1,256}\\`, or cap the input length before matching.`,\n });\n}\n\n/**\n * The security conventions in one parsed file:\n *\n * - `WL9005` `request.all()` (or `heavy()`, `allExceptParams()`) passed to a\n * query, a service or `inApp()`;\n * - `WL9006` a POST/PUT/PATCH/DELETE route with no auth middleware and no\n * `public: true`;\n * - `WL9007` a `redirect()` / `navigateTo()` / `<Link to|href>` target taken\n * from request input without `safeRedirect()` / `safeRedirectTarget()` or an\n * `isSafeRedirect()` check;\n * - `WL9008` a raw email, credential or request body passed to a logger;\n * - `WL9009` a regex with an unbounded quantifier run on request input.\n */\nexport function securityFindings(sourceFile: ast.SourceFile): SourceFinding[] {\n const findings: SourceFinding[] = [];\n\n walk(\n sourceFile,\n (node) => {\n checkRequestAll(node, findings);\n checkRouteGuard(node, findings);\n checkRedirect(node, findings);\n checkSensitiveLog(node, findings);\n checkUnboundedRegex(node, findings);\n\n return undefined;\n },\n true,\n );\n\n return findings;\n}\n"],"mappings":"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"}
@@ -1,195 +1,155 @@
1
- import ts from "typescript";
1
+ import { declarationName, expressionOf, forEachChild, isNoSubstitutionTemplateLiteral, isStringLiteral, keyName as keyName$1, parentOf, positionOf as positionOf$1, sourceOf } from "../syntax/ast.mjs";
2
2
 
3
3
  //#region ../../packages/core/src/tooling/check/source-ast.ts
4
- /** Whether a node is `a.b` or `a[b]`. */
5
- function isMemberAccess(node) {
6
- return ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node);
7
- }
8
- /** Strip parentheses and type-only wrappers (`x as T`, `x!`, `<T>x`, `x satisfies T`). */
4
+ const isMemberAccess = (node) => node.type === "MemberExpression";
5
+ const keyName = keyName$1;
6
+ const positionOf = positionOf$1;
9
7
  function unwrap(node) {
10
8
  let current = node;
11
- while (ts.isParenthesizedExpression(current) || ts.isAsExpression(current) || ts.isNonNullExpression(current) || ts.isTypeAssertionExpression(current) || ts.isSatisfiesExpression(current)) current = current.expression;
9
+ while ([
10
+ "ParenthesizedExpression",
11
+ "TSAsExpression",
12
+ "TSNonNullExpression",
13
+ "TSTypeAssertion",
14
+ "TSSatisfiesExpression",
15
+ "ChainExpression"
16
+ ].includes(current.type)) current = expressionOf(current);
12
17
  return current;
13
18
  }
14
- /** The text of a string literal or a template without substitutions. */
15
19
  function literalString(node) {
16
20
  if (!node) return void 0;
17
21
  const value = unwrap(node);
18
- return ts.isStringLiteral(value) || ts.isNoSubstitutionTemplateLiteral(value) ? value.text : void 0;
22
+ if (isStringLiteral(value)) return value.value;
23
+ if (isNoSubstitutionTemplateLiteral(value)) return value.quasis[0]?.value.cooked ?? void 0;
19
24
  }
20
- /** The static name of a member (`a.b` → `b`, `a["b"]` → `b`). */
21
25
  function memberName(node) {
22
- if (ts.isPropertyAccessExpression(node)) return node.name.text;
23
- return literalString(node.argumentExpression);
24
- }
25
- /** The static name of an object-literal or type-member key (`{ a: 1 }`, `{ "a": 1 }`). */
26
- function keyName(name) {
27
- if (!name) return void 0;
28
- if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isPrivateIdentifier(name)) return name.text;
29
- }
30
- /**
31
- * The name a call is made through: `foo()` → `foo`, `a.b.foo()` → `foo`.
32
- * Used to recognise helpers by name wherever they are imported from.
33
- */
26
+ return node.computed ? literalString(node.property) : keyName$1(node.property);
27
+ }
34
28
  function calleeName(call) {
35
- const callee = unwrap(call.expression);
36
- if (ts.isIdentifier(callee)) return callee.text;
37
- if (isMemberAccess(callee)) return memberName(callee);
29
+ const callee = unwrap(call.callee);
30
+ return callee.type === "Identifier" ? callee.name : isMemberAccess(callee) ? memberName(callee) : void 0;
38
31
  }
39
- /** The root identifier of a member chain: `a.b.c()` → `a`. */
40
32
  function rootIdentifier(node) {
41
33
  let current = unwrap(node);
42
34
  for (;;) {
43
- if (ts.isIdentifier(current)) return current;
44
- if (isMemberAccess(current) || ts.isCallExpression(current)) {
45
- current = unwrap(current.expression);
46
- continue;
47
- }
48
- return;
35
+ if (current.type === "Identifier") return current;
36
+ if (isMemberAccess(current) || current.type === "CallExpression") current = unwrap(expressionOf(current));
37
+ else return void 0;
49
38
  }
50
39
  }
51
- /** Whether a node is a function body owner (declaration, expression, arrow, method, accessor). */
52
40
  function isFunctionLike(node) {
53
- return ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isArrowFunction(node) || ts.isMethodDeclaration(node) || ts.isGetAccessorDeclaration(node) || ts.isSetAccessorDeclaration(node) || ts.isConstructorDeclaration(node);
41
+ return node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
54
42
  }
55
- /**
56
- * Walk a node depth-first, skipping type annotations. The visitor returns
57
- * `false` to skip a node's children. Nested functions are not entered unless
58
- * `enterFunctions`.
59
- */
60
43
  function walk(node, visit, enterFunctions = false) {
61
- if (visit(node) === false) return;
62
- if (!enterFunctions && isFunctionLike(node)) return;
63
- ts.forEachChild(node, (child) => {
64
- if (!ts.isTypeNode(child)) walk(child, visit, enterFunctions);
44
+ if (visit(node) === false || !enterFunctions && isFunctionLike(node)) return;
45
+ forEachChild(node, (child) => {
46
+ if (!child.type.startsWith("TS") || "expression" in child && typeof child.expression === "object") walk(child, visit, enterFunctions);
65
47
  });
66
48
  }
67
- /** Every ancestor of a node, nearest first. */
68
49
  function ancestors(node) {
69
50
  const list = [];
70
- let current = node.parent;
51
+ let current = parentOf(node);
71
52
  while (current) {
72
53
  list.push(current);
73
- current = current.parent;
54
+ current = parentOf(current);
74
55
  }
75
56
  return list;
76
57
  }
77
- /**
78
- * Whether an identifier is a value reference: not the `b` of `a.b`, an object
79
- * key, or the name a declaration introduces.
80
- */
81
58
  function isValueReference(identifier) {
82
- const parent = identifier.parent;
59
+ const parent = parentOf(identifier);
83
60
  if (!parent) return true;
84
- if (ts.isPropertyAccessExpression(parent)) return parent.expression === identifier;
85
- if (ts.isShorthandPropertyAssignment(parent)) return true;
86
- if (ts.isPropertyAssignment(parent) || ts.isMethodDeclaration(parent) || ts.isPropertyDeclaration(parent) || ts.isGetAccessorDeclaration(parent) || ts.isSetAccessorDeclaration(parent) || ts.isPropertySignature(parent) || ts.isVariableDeclaration(parent) || ts.isParameter(parent) || ts.isFunctionDeclaration(parent) || ts.isFunctionExpression(parent) || ts.isClassDeclaration(parent) || ts.isClassExpression(parent) || ts.isEnumMember(parent)) return parent.name !== identifier;
87
- if (ts.isBindingElement(parent)) return parent.name !== identifier && parent.propertyName !== identifier;
88
- return !(ts.isJsxAttribute(parent) || ts.isImportSpecifier(parent) || ts.isExportSpecifier(parent) || ts.isImportClause(parent) || ts.isNamespaceImport(parent) || ts.isLabeledStatement(parent) || ts.isBreakOrContinueStatement(parent));
89
- }
90
- function declarationListDeclares(list, name) {
91
- for (const declaration of list.declarations) if (ts.isIdentifier(declaration.name)) {
92
- if (declaration.name.text === name) return declaration;
93
- } else if (bindingDeclares(declaration.name, name)) return "other";
61
+ if (parent.type === "MemberExpression") return parent.object === identifier || parent.computed;
62
+ if (parent.type === "Property") return parent.value === identifier || parent.computed;
63
+ if (parent.type === "VariableDeclarator") return parent.id !== identifier;
64
+ if ((isFunctionLike(parent) || parent.type === "ClassDeclaration" || parent.type === "ClassExpression") && parent.id === identifier) return false;
65
+ return ![
66
+ "ImportSpecifier",
67
+ "ImportDefaultSpecifier",
68
+ "ImportNamespaceSpecifier",
69
+ "ExportSpecifier",
70
+ "JSXAttribute",
71
+ "LabeledStatement",
72
+ "BreakStatement",
73
+ "ContinueStatement",
74
+ "TSPropertySignature",
75
+ "PropertyDefinition",
76
+ "MethodDefinition",
77
+ "RestElement",
78
+ "ArrayPattern",
79
+ "ObjectPattern"
80
+ ].includes(parent.type);
94
81
  }
95
82
  function bindingDeclares(binding, name) {
96
- if (ts.isIdentifier(binding)) return binding.text === name;
97
- return binding.elements.some((element) => !ts.isOmittedExpression(element) && bindingDeclares(element.name, name));
83
+ if (binding.type === "Identifier") return binding.name === name;
84
+ if (binding.type === "RestElement") return bindingDeclares(binding.argument, name);
85
+ if (binding.type === "AssignmentPattern") return bindingDeclares(binding.left, name);
86
+ if (binding.type === "ObjectPattern") return binding.properties.some((property) => bindingDeclares(property.type === "RestElement" ? property.argument : property.value, name));
87
+ if (binding.type === "ArrayPattern") return binding.elements.some((element) => element !== null && bindingDeclares(element, name));
88
+ return false;
89
+ }
90
+ function declarationsDeclare(list, name) {
91
+ for (const declaration of list.declarations) if (bindingDeclares(declaration.id, name)) return declaration.id.type === "Identifier" ? declaration : "other";
98
92
  }
99
93
  function statementsDeclare(statements, name) {
100
- for (const statement of statements) if (ts.isVariableStatement(statement)) {
101
- const found = declarationListDeclares(statement.declarationList, name);
102
- if (found) return found;
103
- } else if ((ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement) || ts.isEnumDeclaration(statement)) && statement.name?.text === name) return "other";
104
- else if (ts.isImportDeclaration(statement) && importDeclares(statement, name)) return "other";
105
- }
106
- function importDeclares(statement, name) {
107
- const clause = statement.importClause;
108
- if (!clause) return false;
109
- if (clause.name?.text === name) return true;
110
- const bindings = clause.namedBindings;
111
- if (!bindings) return false;
112
- if (ts.isNamespaceImport(bindings)) return bindings.name.text === name;
113
- return bindings.elements.some((element) => element.name.text === name);
114
- }
115
- /** The declaration a scope node introduces for `name`, if it introduces one. */
116
- function scopeDeclares(scope, name) {
117
- if (ts.isSourceFile(scope) || ts.isBlock(scope) || ts.isModuleBlock(scope)) return statementsDeclare(scope.statements, name);
118
- if (ts.isCaseBlock(scope)) {
119
- for (const clause of scope.clauses) {
120
- const found = statementsDeclare(clause.statements, name);
94
+ for (let statement of statements) {
95
+ if (statement.type === "ExportNamedDeclaration" && statement.declaration) statement = statement.declaration;
96
+ if (statement.type === "VariableDeclaration") {
97
+ const found = declarationsDeclare(statement, name);
121
98
  if (found) return found;
122
- }
123
- return;
99
+ } else if (declarationName(statement) === name) return "other";
100
+ else if (statement.type === "ImportDeclaration" && statement.specifiers.some((specifier) => specifier.local.name === name)) return "other";
101
+ }
102
+ }
103
+ function scopeDeclares(scope, name) {
104
+ if (scope.type === "Program" || scope.type === "BlockStatement" || scope.type === "TSModuleBlock") return statementsDeclare(scope.body, name);
105
+ if (scope.type === "SwitchStatement") for (const clause of scope.cases) {
106
+ const found = statementsDeclare(clause.consequent, name);
107
+ if (found) return found;
124
108
  }
125
109
  if (isFunctionLike(scope)) {
126
- if (scope.parameters.some((parameter) => bindingDeclares(parameter.name, name))) return "other";
127
- return ts.isFunctionExpression(scope) && scope.name?.text === name ? "other" : void 0;
110
+ if (scope.params.some((parameter) => bindingDeclares(parameter, name))) return "other";
111
+ if (scope.type === "FunctionExpression" && scope.id?.name === name) return "other";
112
+ }
113
+ if (scope.type === "ForStatement" || scope.type === "ForInStatement" || scope.type === "ForOfStatement") {
114
+ const initializer = scope.type === "ForStatement" ? scope.init : scope.left;
115
+ if (initializer?.type === "VariableDeclaration" && declarationsDeclare(initializer, name)) return "other";
128
116
  }
129
- if ((ts.isForStatement(scope) || ts.isForInStatement(scope) || ts.isForOfStatement(scope)) && scope.initializer && ts.isVariableDeclarationList(scope.initializer)) return declarationListDeclares(scope.initializer, name) ? "other" : void 0;
130
- if (ts.isCatchClause(scope) && scope.variableDeclaration) return bindingDeclares(scope.variableDeclaration.name, name) ? "other" : void 0;
117
+ if (scope.type === "CatchClause" && scope.param && bindingDeclares(scope.param, name)) return "other";
131
118
  }
132
- /** The nearest declaration of an identifier's name, searching outward from it. */
133
119
  function findDeclaration(identifier) {
134
120
  for (const scope of ancestors(identifier)) {
135
- const found = scopeDeclares(scope, identifier.text);
121
+ const found = scopeDeclares(scope, identifier.name);
136
122
  if (found) return found;
137
123
  }
138
124
  }
139
- const ASSIGNMENT_OPERATORS = new Set([
140
- ts.SyntaxKind.EqualsToken,
141
- ts.SyntaxKind.PlusEqualsToken,
142
- ts.SyntaxKind.MinusEqualsToken,
143
- ts.SyntaxKind.AsteriskEqualsToken,
144
- ts.SyntaxKind.SlashEqualsToken,
145
- ts.SyntaxKind.BarBarEqualsToken,
146
- ts.SyntaxKind.AmpersandAmpersandEqualsToken,
147
- ts.SyntaxKind.QuestionQuestionEqualsToken
148
- ]);
149
- /** Whether a `let`/`var` is assigned again anywhere it is visible. */
150
125
  function isReassigned(declaration) {
151
- const name = declaration.name;
152
- if (!ts.isIdentifier(name)) return true;
126
+ const name = declaration.id;
127
+ if (name.type !== "Identifier") return true;
153
128
  let reassigned = false;
154
- walk(declaration.getSourceFile(), (node) => {
129
+ walk(sourceOf(declaration), (node) => {
155
130
  if (reassigned) return false;
156
- let target;
157
- if (ts.isBinaryExpression(node) && ASSIGNMENT_OPERATORS.has(node.operatorToken.kind)) target = unwrap(node.left);
158
- else if ((ts.isPrefixUnaryExpression(node) || ts.isPostfixUnaryExpression(node)) && (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator === ts.SyntaxKind.MinusMinusToken)) target = unwrap(node.operand);
159
- if (target && ts.isIdentifier(target) && target.text === name.text && findDeclaration(target) === declaration) reassigned = true;
131
+ const target = node.type === "AssignmentExpression" ? unwrap(node.left) : node.type === "UpdateExpression" ? unwrap(node.argument) : void 0;
132
+ if (target?.type === "Identifier" && target.name === name.name && findDeclaration(target) === declaration) reassigned = true;
160
133
  }, true);
161
134
  return reassigned;
162
135
  }
163
- /**
164
- * The expression an identifier was initialised with, when it names a
165
- * `const` (or a `let`/`var` never assigned again) declared once.
166
- */
167
136
  function resolveInitializer(identifier) {
168
137
  const declaration = findDeclaration(identifier);
169
- if (!declaration || declaration === "other" || !declaration.initializer) return void 0;
170
- const list = declaration.parent;
171
- if (!(ts.isVariableDeclarationList(list) && (list.flags & ts.NodeFlags.Const) !== 0) && isReassigned(declaration)) return void 0;
172
- return declaration.initializer;
138
+ if (!declaration || declaration === "other" || !declaration.init) return void 0;
139
+ const list = parentOf(declaration);
140
+ if (!(list?.type === "VariableDeclaration" && list.kind === "const") && isReassigned(declaration)) return void 0;
141
+ return declaration.init;
173
142
  }
174
- /** Every value reference to a variable declaration in its file (not the declaration itself). */
175
143
  function referencesOf(declaration) {
176
- const name = declaration.name;
177
- if (!ts.isIdentifier(name)) return [];
144
+ const name = declaration.id;
145
+ if (name.type !== "Identifier") return [];
178
146
  const found = [];
179
- walk(declaration.getSourceFile(), (node) => {
180
- if (ts.isIdentifier(node) && node !== name && node.text === name.text && isValueReference(node) && findDeclaration(node) === declaration) found.push(node);
147
+ walk(sourceOf(declaration), (node) => {
148
+ if (node.type === "Identifier" && node !== name && node.name === name.name && isValueReference(node) && findDeclaration(node) === declaration) found.push(node);
181
149
  }, true);
182
150
  return found;
183
151
  }
184
- /** 1-based line and column of a node's first character. */
185
- function positionOf(sourceFile, node) {
186
- const position = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
187
- return {
188
- line: position.line + 1,
189
- column: position.character + 1
190
- };
191
- }
192
152
 
193
153
  //#endregion
194
- export { ancestors, calleeName, isFunctionLike, isMemberAccess, isValueReference, keyName, literalString, memberName, positionOf, referencesOf, resolveInitializer, rootIdentifier, unwrap, walk };
154
+ export { ancestors, calleeName, findDeclaration, isFunctionLike, isMemberAccess, isValueReference, keyName, literalString, memberName, positionOf, referencesOf, resolveInitializer, rootIdentifier, unwrap, walk };
195
155
  //# sourceMappingURL=source-ast.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"source-ast.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/check/source-ast.ts"],"sourcesContent":["import ts from \"typescript\";\nimport type { WarlockErrorCode } from \"../../errors/error-codes\";\n\n/**\n * Syntax helpers for the source convention checks (`WL9005`–`WL9012`).\n *\n * The checks read one file at a time with `ts.createSourceFile` — no program,\n * no type checker — so they stay as fast as a parse and run the same whatever\n * linter the app uses. Identifiers are resolved to their declarations by\n * walking the enclosing scopes of the syntax tree.\n */\n\n/** One problem a source check found, before it is placed and turned into a problem. */\nexport type SourceFinding = {\n code: WarlockErrorCode;\n /** The node the problem is reported at. */\n node: ts.Node;\n message: string;\n /** Default `error`. */\n severity?: \"error\" | \"warning\";\n};\n\n/** `a.b` or `a[\"b\"]`. */\nexport type MemberAccess = ts.PropertyAccessExpression | ts.ElementAccessExpression;\n\n/** Whether a node is `a.b` or `a[b]`. */\nexport function isMemberAccess(node: ts.Node): node is MemberAccess {\n return ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node);\n}\n\n/** Strip parentheses and type-only wrappers (`x as T`, `x!`, `<T>x`, `x satisfies T`). */\nexport function unwrap(node: ts.Node): ts.Node {\n let current = node;\n\n while (\n ts.isParenthesizedExpression(current) ||\n ts.isAsExpression(current) ||\n ts.isNonNullExpression(current) ||\n ts.isTypeAssertionExpression(current) ||\n ts.isSatisfiesExpression(current)\n ) {\n current = current.expression;\n }\n\n return current;\n}\n\n/** The text of a string literal or a template without substitutions. */\nexport function literalString(node: ts.Node | undefined): string | undefined {\n if (!node) return undefined;\n\n const value = unwrap(node);\n\n return ts.isStringLiteral(value) || ts.isNoSubstitutionTemplateLiteral(value)\n ? value.text\n : undefined;\n}\n\n/** The static name of a member (`a.b` → `b`, `a[\"b\"]` → `b`). */\nexport function memberName(node: MemberAccess): string | undefined {\n if (ts.isPropertyAccessExpression(node)) return node.name.text;\n\n return literalString(node.argumentExpression);\n}\n\n/** The static name of an object-literal or type-member key (`{ a: 1 }`, `{ \"a\": 1 }`). */\nexport function keyName(name: ts.PropertyName | undefined): string | undefined {\n if (!name) return undefined;\n if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isPrivateIdentifier(name)) {\n return name.text;\n }\n\n return undefined;\n}\n\n/**\n * The name a call is made through: `foo()` → `foo`, `a.b.foo()` → `foo`.\n * Used to recognise helpers by name wherever they are imported from.\n */\nexport function calleeName(call: ts.CallExpression | ts.NewExpression): string | undefined {\n const callee = unwrap(call.expression);\n\n if (ts.isIdentifier(callee)) return callee.text;\n if (isMemberAccess(callee)) return memberName(callee);\n\n return undefined;\n}\n\n/** The root identifier of a member chain: `a.b.c()` → `a`. */\nexport function rootIdentifier(node: ts.Node): ts.Identifier | undefined {\n let current = unwrap(node);\n\n for (;;) {\n if (ts.isIdentifier(current)) return current;\n\n if (isMemberAccess(current) || ts.isCallExpression(current)) {\n current = unwrap(current.expression);\n continue;\n }\n\n return undefined;\n }\n}\n\n/** Whether a node is a function body owner (declaration, expression, arrow, method, accessor). */\nexport function isFunctionLike(node: ts.Node): node is ts.FunctionLikeDeclaration {\n return (\n ts.isFunctionDeclaration(node) ||\n ts.isFunctionExpression(node) ||\n ts.isArrowFunction(node) ||\n ts.isMethodDeclaration(node) ||\n ts.isGetAccessorDeclaration(node) ||\n ts.isSetAccessorDeclaration(node) ||\n ts.isConstructorDeclaration(node)\n );\n}\n\n/**\n * Walk a node depth-first, skipping type annotations. The visitor returns\n * `false` to skip a node's children. Nested functions are not entered unless\n * `enterFunctions`.\n */\nexport function walk(\n node: ts.Node,\n visit: (node: ts.Node) => boolean | void,\n enterFunctions = false,\n): void {\n if (visit(node) === false) return;\n if (!enterFunctions && isFunctionLike(node)) return;\n\n ts.forEachChild(node, (child) => {\n if (!ts.isTypeNode(child)) walk(child, visit, enterFunctions);\n\n return undefined;\n });\n}\n\n/** Every ancestor of a node, nearest first. */\nexport function ancestors(node: ts.Node): ts.Node[] {\n const list: ts.Node[] = [];\n let current = node.parent;\n\n while (current) {\n list.push(current);\n current = current.parent;\n }\n\n return list;\n}\n\n/**\n * Whether an identifier is a value reference: not the `b` of `a.b`, an object\n * key, or the name a declaration introduces.\n */\nexport function isValueReference(identifier: ts.Identifier): boolean {\n const parent = identifier.parent;\n\n if (!parent) return true;\n if (ts.isPropertyAccessExpression(parent)) return parent.expression === identifier;\n if (ts.isShorthandPropertyAssignment(parent)) return true;\n\n if (\n ts.isPropertyAssignment(parent) ||\n ts.isMethodDeclaration(parent) ||\n ts.isPropertyDeclaration(parent) ||\n ts.isGetAccessorDeclaration(parent) ||\n ts.isSetAccessorDeclaration(parent) ||\n ts.isPropertySignature(parent) ||\n ts.isVariableDeclaration(parent) ||\n ts.isParameter(parent) ||\n ts.isFunctionDeclaration(parent) ||\n ts.isFunctionExpression(parent) ||\n ts.isClassDeclaration(parent) ||\n ts.isClassExpression(parent) ||\n ts.isEnumMember(parent)\n ) {\n return parent.name !== identifier;\n }\n\n if (ts.isBindingElement(parent)) {\n return parent.name !== identifier && parent.propertyName !== identifier;\n }\n\n return !(\n ts.isJsxAttribute(parent) ||\n ts.isImportSpecifier(parent) ||\n ts.isExportSpecifier(parent) ||\n ts.isImportClause(parent) ||\n ts.isNamespaceImport(parent) ||\n ts.isLabeledStatement(parent) ||\n ts.isBreakOrContinueStatement(parent)\n );\n}\n\n/** What declares a name: a single `const`/`let`/`var` declarator, or something else. */\ntype Declaration = ts.VariableDeclaration | \"other\";\n\nfunction declarationListDeclares(\n list: ts.VariableDeclarationList,\n name: string,\n): Declaration | undefined {\n for (const declaration of list.declarations) {\n if (ts.isIdentifier(declaration.name)) {\n if (declaration.name.text === name) return declaration;\n } else if (bindingDeclares(declaration.name, name)) {\n return \"other\";\n }\n }\n\n return undefined;\n}\n\nfunction bindingDeclares(binding: ts.BindingName, name: string): boolean {\n if (ts.isIdentifier(binding)) return binding.text === name;\n\n return binding.elements.some(\n (element) => !ts.isOmittedExpression(element) && bindingDeclares(element.name, name),\n );\n}\n\nfunction statementsDeclare(\n statements: readonly ts.Statement[],\n name: string,\n): Declaration | undefined {\n for (const statement of statements) {\n if (ts.isVariableStatement(statement)) {\n const found = declarationListDeclares(statement.declarationList, name);\n if (found) return found;\n } else if (\n (ts.isFunctionDeclaration(statement) ||\n ts.isClassDeclaration(statement) ||\n ts.isEnumDeclaration(statement)) &&\n statement.name?.text === name\n ) {\n return \"other\";\n } else if (ts.isImportDeclaration(statement) && importDeclares(statement, name)) {\n return \"other\";\n }\n }\n\n return undefined;\n}\n\nfunction importDeclares(statement: ts.ImportDeclaration, name: string): boolean {\n const clause = statement.importClause;\n\n if (!clause) return false;\n if (clause.name?.text === name) return true;\n\n const bindings = clause.namedBindings;\n\n if (!bindings) return false;\n if (ts.isNamespaceImport(bindings)) return bindings.name.text === name;\n\n return bindings.elements.some((element) => element.name.text === name);\n}\n\n/** The declaration a scope node introduces for `name`, if it introduces one. */\nfunction scopeDeclares(scope: ts.Node, name: string): Declaration | undefined {\n if (ts.isSourceFile(scope) || ts.isBlock(scope) || ts.isModuleBlock(scope)) {\n return statementsDeclare(scope.statements, name);\n }\n\n if (ts.isCaseBlock(scope)) {\n for (const clause of scope.clauses) {\n const found = statementsDeclare(clause.statements, name);\n if (found) return found;\n }\n\n return undefined;\n }\n\n if (isFunctionLike(scope)) {\n if (scope.parameters.some((parameter) => bindingDeclares(parameter.name, name))) {\n return \"other\";\n }\n\n return ts.isFunctionExpression(scope) && scope.name?.text === name ? \"other\" : undefined;\n }\n\n if (\n (ts.isForStatement(scope) || ts.isForInStatement(scope) || ts.isForOfStatement(scope)) &&\n scope.initializer &&\n ts.isVariableDeclarationList(scope.initializer)\n ) {\n return declarationListDeclares(scope.initializer, name) ? \"other\" : undefined;\n }\n\n if (ts.isCatchClause(scope) && scope.variableDeclaration) {\n return bindingDeclares(scope.variableDeclaration.name, name) ? \"other\" : undefined;\n }\n\n return undefined;\n}\n\n/** The nearest declaration of an identifier's name, searching outward from it. */\nexport function findDeclaration(identifier: ts.Identifier): Declaration | undefined {\n for (const scope of ancestors(identifier)) {\n const found = scopeDeclares(scope, identifier.text);\n if (found) return found;\n }\n\n return undefined;\n}\n\nconst ASSIGNMENT_OPERATORS: ReadonlySet<ts.SyntaxKind> = new Set([\n ts.SyntaxKind.EqualsToken,\n ts.SyntaxKind.PlusEqualsToken,\n ts.SyntaxKind.MinusEqualsToken,\n ts.SyntaxKind.AsteriskEqualsToken,\n ts.SyntaxKind.SlashEqualsToken,\n ts.SyntaxKind.BarBarEqualsToken,\n ts.SyntaxKind.AmpersandAmpersandEqualsToken,\n ts.SyntaxKind.QuestionQuestionEqualsToken,\n]);\n\n/** Whether a `let`/`var` is assigned again anywhere it is visible. */\nfunction isReassigned(declaration: ts.VariableDeclaration): boolean {\n const name = declaration.name;\n\n if (!ts.isIdentifier(name)) return true;\n\n let reassigned = false;\n\n walk(\n declaration.getSourceFile(),\n (node) => {\n if (reassigned) return false;\n\n let target: ts.Node | undefined;\n\n if (ts.isBinaryExpression(node) && ASSIGNMENT_OPERATORS.has(node.operatorToken.kind)) {\n target = unwrap(node.left);\n } else if (\n (ts.isPrefixUnaryExpression(node) || ts.isPostfixUnaryExpression(node)) &&\n (node.operator === ts.SyntaxKind.PlusPlusToken ||\n node.operator === ts.SyntaxKind.MinusMinusToken)\n ) {\n target = unwrap(node.operand);\n }\n\n if (\n target &&\n ts.isIdentifier(target) &&\n target.text === name.text &&\n findDeclaration(target) === declaration\n ) {\n reassigned = true;\n }\n\n return undefined;\n },\n true,\n );\n\n return reassigned;\n}\n\n/**\n * The expression an identifier was initialised with, when it names a\n * `const` (or a `let`/`var` never assigned again) declared once.\n */\nexport function resolveInitializer(identifier: ts.Identifier): ts.Expression | undefined {\n const declaration = findDeclaration(identifier);\n\n if (!declaration || declaration === \"other\" || !declaration.initializer) return undefined;\n\n const list = declaration.parent;\n const isConst = ts.isVariableDeclarationList(list) && (list.flags & ts.NodeFlags.Const) !== 0;\n\n if (!isConst && isReassigned(declaration)) return undefined;\n\n return declaration.initializer;\n}\n\n/** Every value reference to a variable declaration in its file (not the declaration itself). */\nexport function referencesOf(declaration: ts.VariableDeclaration): ts.Identifier[] {\n const name = declaration.name;\n\n if (!ts.isIdentifier(name)) return [];\n\n const found: ts.Identifier[] = [];\n\n walk(\n declaration.getSourceFile(),\n (node) => {\n if (\n ts.isIdentifier(node) &&\n node !== name &&\n node.text === name.text &&\n isValueReference(node) &&\n findDeclaration(node) === declaration\n ) {\n found.push(node);\n }\n\n return undefined;\n },\n true,\n );\n\n return found;\n}\n\n/** 1-based line and column of a node's first character. */\nexport function positionOf(\n sourceFile: ts.SourceFile,\n node: ts.Node,\n): { line: number; column: number } {\n const position = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));\n\n return { line: position.line + 1, column: position.character + 1 };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"source-ast.mjs","names":["ast.keyName","ast.positionOf","ast.expressionOf","ast.isStringLiteral","ast.isNoSubstitutionTemplateLiteral","ast.parentOf","ast.declarationName","ast.sourceOf"],"sources":["../../../../../../../../../packages/core/src/tooling/check/source-ast.ts"],"sourcesContent":["import * as ast from \"../syntax/ast\";\nimport type { WarlockErrorCode } from \"../../errors/error-codes\";\n\nexport type SourceFinding = {\n code: WarlockErrorCode;\n node: ast.Node;\n message: string;\n severity?: \"error\" | \"warning\";\n};\nexport type MemberAccess = ast.MemberExpression;\nexport const isMemberAccess = (node: ast.Node): node is MemberAccess =>\n node.type === \"MemberExpression\";\nexport const keyName = ast.keyName;\nexport const positionOf = ast.positionOf;\n\nexport function unwrap(node: ast.Node): ast.Node {\n let current = node;\n while (\n [\n \"ParenthesizedExpression\",\n \"TSAsExpression\",\n \"TSNonNullExpression\",\n \"TSTypeAssertion\",\n \"TSSatisfiesExpression\",\n \"ChainExpression\",\n ].includes(current.type)\n )\n current = ast.expressionOf(current);\n return current;\n}\nexport function literalString(node: ast.Node | null | undefined): string | undefined {\n if (!node) return undefined;\n const value = unwrap(node);\n if (ast.isStringLiteral(value)) return value.value;\n if (ast.isNoSubstitutionTemplateLiteral(value)) return value.quasis[0]?.value.cooked ?? undefined;\n return undefined;\n}\nexport function memberName(node: MemberAccess): string | undefined {\n return node.computed ? literalString(node.property) : ast.keyName(node.property);\n}\nexport function calleeName(call: ast.CallExpression | ast.NewExpression): string | undefined {\n const callee = unwrap(call.callee);\n return callee.type === \"Identifier\"\n ? callee.name\n : isMemberAccess(callee)\n ? memberName(callee)\n : undefined;\n}\nexport function rootIdentifier(node: ast.Node): ast.Identifier | undefined {\n let current = unwrap(node);\n for (;;) {\n if (current.type === \"Identifier\") return current;\n if (isMemberAccess(current) || current.type === \"CallExpression\")\n current = unwrap(ast.expressionOf(current));\n else return undefined;\n }\n}\nexport function isFunctionLike(\n node: ast.Node,\n): node is ast.FunctionDeclaration | ast.FunctionExpression | ast.ArrowFunctionExpression {\n return (\n node.type === \"FunctionDeclaration\" ||\n node.type === \"FunctionExpression\" ||\n node.type === \"ArrowFunctionExpression\"\n );\n}\nexport function walk(\n node: ast.Node,\n visit: (node: ast.Node) => boolean | void,\n enterFunctions = false,\n): void {\n if (visit(node) === false || (!enterFunctions && isFunctionLike(node))) return;\n ast.forEachChild(node, (child) => {\n if (\n !child.type.startsWith(\"TS\") ||\n (\"expression\" in child && typeof child.expression === \"object\")\n )\n walk(child, visit, enterFunctions);\n });\n}\nexport function ancestors(node: ast.Node): ast.Node[] {\n const list: ast.Node[] = [];\n let current = ast.parentOf(node);\n while (current) {\n list.push(current);\n current = ast.parentOf(current);\n }\n return list;\n}\nexport function isValueReference(identifier: ast.Identifier): boolean {\n const parent = ast.parentOf(identifier);\n if (!parent) return true;\n if (parent.type === \"MemberExpression\") return parent.object === identifier || parent.computed;\n if (parent.type === \"Property\") return parent.value === identifier || parent.computed;\n if (parent.type === \"VariableDeclarator\") return parent.id !== identifier;\n if (\n (isFunctionLike(parent) ||\n parent.type === \"ClassDeclaration\" ||\n parent.type === \"ClassExpression\") &&\n parent.id === identifier\n )\n return false;\n return ![\n \"ImportSpecifier\",\n \"ImportDefaultSpecifier\",\n \"ImportNamespaceSpecifier\",\n \"ExportSpecifier\",\n \"JSXAttribute\",\n \"LabeledStatement\",\n \"BreakStatement\",\n \"ContinueStatement\",\n \"TSPropertySignature\",\n \"PropertyDefinition\",\n \"MethodDefinition\",\n \"RestElement\",\n \"ArrayPattern\",\n \"ObjectPattern\",\n ].includes(parent.type);\n}\n\ntype Declaration = ast.VariableDeclarator | \"other\";\nfunction bindingDeclares(binding: ast.Node, name: string): boolean {\n if (binding.type === \"Identifier\") return binding.name === name;\n if (binding.type === \"RestElement\") return bindingDeclares(binding.argument, name);\n if (binding.type === \"AssignmentPattern\") return bindingDeclares(binding.left, name);\n if (binding.type === \"ObjectPattern\")\n return binding.properties.some((property) =>\n bindingDeclares(property.type === \"RestElement\" ? property.argument : property.value, name),\n );\n if (binding.type === \"ArrayPattern\")\n return binding.elements.some((element) => element !== null && bindingDeclares(element, name));\n return false;\n}\nfunction declarationsDeclare(list: ast.VariableDeclaration, name: string): Declaration | undefined {\n for (const declaration of list.declarations) {\n if (bindingDeclares(declaration.id, name))\n return declaration.id.type === \"Identifier\" ? declaration : \"other\";\n }\n return undefined;\n}\nfunction statementsDeclare(\n statements: readonly ast.Statement[],\n name: string,\n): Declaration | undefined {\n for (let statement of statements) {\n if (statement.type === \"ExportNamedDeclaration\" && statement.declaration)\n statement = statement.declaration;\n if (statement.type === \"VariableDeclaration\") {\n const found = declarationsDeclare(statement, name);\n if (found) return found;\n } else if (ast.declarationName(statement) === name) return \"other\";\n else if (\n statement.type === \"ImportDeclaration\" &&\n statement.specifiers.some((specifier) => specifier.local.name === name)\n )\n return \"other\";\n }\n return undefined;\n}\nfunction scopeDeclares(scope: ast.Node, name: string): Declaration | undefined {\n if (scope.type === \"Program\" || scope.type === \"BlockStatement\" || scope.type === \"TSModuleBlock\")\n return statementsDeclare(scope.body, name);\n if (scope.type === \"SwitchStatement\") {\n for (const clause of scope.cases) {\n const found = statementsDeclare(clause.consequent, name);\n if (found) return found;\n }\n }\n if (isFunctionLike(scope)) {\n if (scope.params.some((parameter) => bindingDeclares(parameter, name))) return \"other\";\n if (scope.type === \"FunctionExpression\" && scope.id?.name === name) return \"other\";\n }\n if (\n scope.type === \"ForStatement\" ||\n scope.type === \"ForInStatement\" ||\n scope.type === \"ForOfStatement\"\n ) {\n const initializer = scope.type === \"ForStatement\" ? scope.init : scope.left;\n if (initializer?.type === \"VariableDeclaration\" && declarationsDeclare(initializer, name))\n return \"other\";\n }\n if (scope.type === \"CatchClause\" && scope.param && bindingDeclares(scope.param, name))\n return \"other\";\n return undefined;\n}\nexport function findDeclaration(identifier: ast.Identifier): Declaration | undefined {\n for (const scope of ancestors(identifier)) {\n const found = scopeDeclares(scope, identifier.name);\n if (found) return found;\n }\n return undefined;\n}\nfunction isReassigned(declaration: ast.VariableDeclarator): boolean {\n const name = declaration.id;\n if (name.type !== \"Identifier\") return true;\n let reassigned = false;\n walk(\n ast.sourceOf(declaration),\n (node) => {\n if (reassigned) return false;\n const target =\n node.type === \"AssignmentExpression\"\n ? unwrap(node.left)\n : node.type === \"UpdateExpression\"\n ? unwrap(node.argument)\n : undefined;\n if (\n target?.type === \"Identifier\" &&\n target.name === name.name &&\n findDeclaration(target) === declaration\n )\n reassigned = true;\n return undefined;\n },\n true,\n );\n return reassigned;\n}\nexport function resolveInitializer(identifier: ast.Identifier): ast.Expression | undefined {\n const declaration = findDeclaration(identifier);\n if (!declaration || declaration === \"other\" || !declaration.init) return undefined;\n const list = ast.parentOf(declaration);\n if (!(list?.type === \"VariableDeclaration\" && list.kind === \"const\") && isReassigned(declaration))\n return undefined;\n return declaration.init;\n}\nexport function referencesOf(declaration: ast.VariableDeclarator): ast.Identifier[] {\n const name = declaration.id;\n if (name.type !== \"Identifier\") return [];\n const found: ast.Identifier[] = [];\n walk(\n ast.sourceOf(declaration),\n (node) => {\n if (\n node.type === \"Identifier\" &&\n node !== name &&\n node.name === name.name &&\n isValueReference(node) &&\n findDeclaration(node) === declaration\n )\n found.push(node);\n return undefined;\n },\n true,\n );\n return found;\n}\n"],"mappings":"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"}